aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@arm.com>2022-02-11 11:29:39 +0000
committerTom Rini <trini@konsulko.com>2022-03-02 13:59:29 -0500
commit5ff4857d3569710c0f1ce1848f1e7486e3a4cfbe (patch)
treeda9d57e285034143ed1e9cd4dfc30577792275ad /arch
parentf660fe0bd3a8cfa7fc6271bbf27b1530e7348b85 (diff)
downloadu-boot-5ff4857d3569710c0f1ce1848f1e7486e3a4cfbe.zip
u-boot-5ff4857d3569710c0f1ce1848f1e7486e3a4cfbe.tar.gz
u-boot-5ff4857d3569710c0f1ce1848f1e7486e3a4cfbe.tar.bz2
armv8: Fix and simplify branch_if_master/branch_if_slave
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>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S2
-rw-r--r--arch/arm/cpu/armv8/start.S6
-rw-r--r--arch/arm/include/asm/macro.h29
-rw-r--r--arch/arm/mach-rmobile/lowlevel_init_gen3.S2
-rw-r--r--arch/arm/mach-socfpga/lowlevel_init_soc64.S2
5 files changed, 14 insertions, 27 deletions
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
index 0929c58..2fb4e40 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
+++ b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
@@ -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)
/*
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S
index e1461f2..6a6a4f8 100644
--- a/arch/arm/cpu/armv8/start.S
+++ b/arch/arm/cpu/armv8/start.S
@@ -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.
diff --git a/arch/arm/include/asm/macro.h b/arch/arm/include/asm/macro.h
index acd5190..1a1edc9 100644
--- a/arch/arm/include/asm/macro.h
+++ b/arch/arm/include/asm/macro.h
@@ -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
diff --git a/arch/arm/mach-rmobile/lowlevel_init_gen3.S b/arch/arm/mach-rmobile/lowlevel_init_gen3.S
index 1df2c40..0d77800 100644
--- a/arch/arm/mach-rmobile/lowlevel_init_gen3.S
+++ b/arch/arm/mach-rmobile/lowlevel_init_gen3.S
@@ -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.
diff --git a/arch/arm/mach-socfpga/lowlevel_init_soc64.S b/arch/arm/mach-socfpga/lowlevel_init_soc64.S
index 612ea8a..875927c 100644
--- a/arch/arm/mach-socfpga/lowlevel_init_soc64.S
+++ b/arch/arm/mach-socfpga/lowlevel_init_soc64.S
@@ -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.