]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
armv8: Fix and simplify branch_if_master/branch_if_slave
authorAndre Przywara <andre.przywara@arm.com>
Fri, 11 Feb 2022 11:29:39 +0000 (11:29 +0000)
committerTom Rini <trini@konsulko.com>
Wed, 2 Mar 2022 18:59:29 +0000 (13:59 -0500)
The branch_if_master macro jumps to a label if the CPU is the "master"
core, which we define as having all affinity levels set to 0. To check
for this condition, we need to mask off some bits from the MPIDR
register, then compare the remaining register value against zero.

The implementation of this was slighly broken (it preserved the upper
RES0 bits), overly complicated and hard to understand, especially since
it lacked comments. The same was true for the very similar
branch_if_slave macro.

Use a much shorter assembly sequence for those checks, use the same
masking for both macros (just negate the final branch), and put some
comments on them, to make it clear what the code does.
This allows to drop the second temporary register for branch_if_master,
so we adjust all call sites as well.

Also use the opportunity to remove a misleading comment: the macro
works fine on SoCs with multiple clusters. Judging by the commit
message, the original problem with the Juno SoC stems from the fact that
the master CPU *can* be configured to be from cluster 1, so the
assumption that the master CPU has all affinity values set to 0 does not
hold there. But this is already mentioned above in a comment, so remove
the extra comment.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
arch/arm/cpu/armv8/start.S
arch/arm/include/asm/macro.h
arch/arm/mach-rmobile/lowlevel_init_gen3.S
arch/arm/mach-socfpga/lowlevel_init_soc64.S
board/cortina/presidio-asic/lowlevel_init.S

index 0929c58d43f1d656c03c9ea9115eca3a3447b470..2fb4e404a245770d1854bf45d9892869e330e4f5 100644 (file)
@@ -200,7 +200,7 @@ ENTRY(lowlevel_init)
 #endif
 
 100:
-       branch_if_master x0, x1, 2f
+       branch_if_master x0, 2f
 
 #if defined(CONFIG_MP) && defined(CONFIG_ARMV8_MULTIENTRY)
        /*
index e1461f2319eac74fa3d32c98a933ca9a9cef1fbe..6a6a4f86502bb83522f2e1d8bed8c48b56d51dcb 100644 (file)
@@ -175,11 +175,11 @@ pie_fixup_done:
        bl      lowlevel_init
 
 #if defined(CONFIG_ARMV8_SPIN_TABLE) && !defined(CONFIG_SPL_BUILD)
-       branch_if_master x0, x1, master_cpu
+       branch_if_master x0, master_cpu
        b       spin_table_secondary_jump
        /* never return */
 #elif defined(CONFIG_ARMV8_MULTIENTRY)
-       branch_if_master x0, x1, master_cpu
+       branch_if_master x0, master_cpu
 
        /*
         * Slave CPUs
@@ -305,7 +305,7 @@ WEAK(lowlevel_init)
 #endif
 
 #ifdef CONFIG_ARMV8_MULTIENTRY
-       branch_if_master x0, x1, 2f
+       branch_if_master x0, 2f
 
        /*
         * Slave should wait for master clearing spin table.
index acd519020d7f45dd590be610107b8e5b4a30c928..1a1edc98703760073e0e05903ea608f4c8558133 100644 (file)
@@ -121,19 +121,10 @@ lr        .req    x30
  */
 .macro branch_if_slave, xreg, slave_label
 #ifdef CONFIG_ARMV8_MULTIENTRY
-       /* NOTE: MPIDR handling will be erroneous on multi-cluster machines */
        mrs     \xreg, mpidr_el1
-       tst     \xreg, #0xff            /* Test Affinity 0 */
-       b.ne    \slave_label
-       lsr     \xreg, \xreg, #8
-       tst     \xreg, #0xff            /* Test Affinity 1 */
-       b.ne    \slave_label
-       lsr     \xreg, \xreg, #8
-       tst     \xreg, #0xff            /* Test Affinity 2 */
-       b.ne    \slave_label
-       lsr     \xreg, \xreg, #16
-       tst     \xreg, #0xff            /* Test Affinity 3 */
-       b.ne    \slave_label
+       and     \xreg, \xreg,  0xffffffffff     /* clear bits [63:40] */
+       and     \xreg, \xreg, ~0x00ff000000     /* also clear bits [31:24] */
+       cbnz    \xreg, \slave_label
 #endif
 .endm
 
@@ -141,16 +132,12 @@ lr        .req    x30
  * Branch if current processor is a master,
  * choose processor with all zero affinity value as the master.
  */
-.macro branch_if_master, xreg1, xreg2, master_label
+.macro branch_if_master, xreg, master_label
 #ifdef CONFIG_ARMV8_MULTIENTRY
-       /* NOTE: MPIDR handling will be erroneous on multi-cluster machines */
-       mrs     \xreg1, mpidr_el1
-       lsr     \xreg2, \xreg1, #32
-       lsl     \xreg2, \xreg2, #32
-       lsl     \xreg1, \xreg1, #40
-       lsr     \xreg1, \xreg1, #40
-       orr     \xreg1, \xreg1, \xreg2
-       cbz     \xreg1, \master_label
+       mrs     \xreg, mpidr_el1
+       and     \xreg, \xreg,  0xffffffffff     /* clear bits [63:40] */
+       and     \xreg, \xreg, ~0x00ff000000     /* also clear bits [31:24] */
+       cbz     \xreg, \master_label
 #else
        b       \master_label
 #endif
index 1df2c4034531ae657c638ccb38104ac10db6f4e7..0d7780031ac5c91bb9e831979e4f9cfc3f2d38ec 100644 (file)
@@ -64,7 +64,7 @@ ENTRY(lowlevel_init)
 #endif
 #endif
 
-       branch_if_master x0, x1, 2f
+       branch_if_master x0, 2f
 
        /*
         * Slave should wait for master clearing spin table.
index 612ea8a0371fd5acde0171f96af10d2d66df0f4c..875927cc4d909a482c183392bc73ac3f849dcd76 100644 (file)
@@ -38,7 +38,7 @@ slave_wait_atf:
 #endif
 
 #ifdef CONFIG_ARMV8_MULTIENTRY
-       branch_if_master x0, x1, 2f
+       branch_if_master x0, 2f
 
        /*
         * Slave should wait for master clearing spin table.
index 4450a5df79fcff4d2fb23f6e6a56fad4ec86d27f..cbf8134346d5c4ba8013b02157fc8ce96f2d548e 100644 (file)
@@ -50,7 +50,7 @@ skip_smp_setup:
 #endif
 
 #ifdef CONFIG_ARMV8_MULTIENTRY
-       branch_if_master x0, x1, 2f
+       branch_if_master x0, 2f
 
        /*
         * Slave should wait for master clearing spin table.