[PATCH] armv8: layerscape: fix spin-table support

Michael Walle michael at walle.cc
Sat May 23 01:07:45 CEST 2020


Spin tables are broken with bootefi. This is because - in contrast to
the booti call chain - there is no call to smp_kick_all_cpus(). Due to
this missing call the secondary CPUs are never released from their "wait
for interrupt state", see secondary_boot_func() in lowlevel.S.

Originally, this "wait for interrupt" it there to make sure, the spin
table is cleared before the secondary cores read it for the first time.
But the boot flow for the layerscape architecture is different from
that. The CPUs are release from their BootROM _after_ U-Boot's
spin-table is cleared, see fsl_layerscape_wake_seconday_cores() in mp.c.
Thus, there is no need to wait for this interrupt and no need for
kicking all cores on cpu_release. An atomic 64bit write to the
spin-table and a "sev" is sufficient.

Signed-off-by: Michael Walle <michael at walle.cc>
---
 arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S | 7 -------
 arch/arm/cpu/armv8/fsl-layerscape/mp.c       | 9 +++++----
 2 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
index 711ab87556..2a8d592cc5 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
+++ b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
@@ -474,13 +474,6 @@ ENTRY(secondary_boot_func)
 	mov	x4, #1
 	str	x4, [x11, #8]	/* STATUS */
 	dsb	sy
-#if defined(CONFIG_GICV3)
-	gic_wait_for_interrupt_m x0
-#elif defined(CONFIG_GICV2)
-	bl	get_gic_offset
-	mov	x0, x1
-        gic_wait_for_interrupt_m x0, w1
-#endif
 
 slave_cpu:
 	wfe
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/mp.c b/arch/arm/cpu/armv8/fsl-layerscape/mp.c
index 1ea887b331..e078d1cd37 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/mp.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/mp.c
@@ -277,11 +277,12 @@ int cpu_release(u32 nr, int argc, char *const argv[])
 	flush_dcache_range((unsigned long)table,
 			   (unsigned long)table + SPIN_TABLE_ELEM_SIZE);
 	asm volatile("dsb st");
-	smp_kick_all_cpus();	/* only those with entry addr set will run */
+
 	/*
-	 * When the first release command runs, all cores are set to go. Those
-	 * without a valid entry address will be trapped by "wfe". "sev" kicks
-	 * them off to check the address again. When set, they continue to run.
+	 * The secondary CPUs polling the spin-table above for a non-zero
+	 * value. To save power "wfe" is called. Thus call "sev" here to
+	 * wake the CPUs and let them check the spin-table again (see
+	 * slave_cpu loop in lowlevel.S)
 	 */
 	asm volatile("sev");
 
-- 
2.20.1



More information about the U-Boot mailing list