ARM: shmobile: Per-CPU SMP boot / sleep code
Magnus Damm
maintainercover ARM: shmobile: Per-CPU SMP boot / sleep code
ARM: shmobile: Per-CPU SMP boot / sleep code
[PATCH 01/02] ARM: shmobile: Introduce per-CPU SMP boot / sleep code [PATCH 02/02] ARM: shmobile: Per-CPU SMP boot / sleep code for SCU SoCs
This series adds per-CPU SMP boot / sleep code to mach-shmobile and ties it in with the Cortex-A9 SoCs using the shared SCU code. With this code in place mach-shmobile has a common per-CPU demuxer that CPUs to start from and a place where CPUs also go to sleep (perhaps forever).
---
Written against renesas.git renesas-devel-20130731 and [PATCH 00/07] ARM: shmobile: sh73a0, r8a7779 and emev2 SMP SCU rework
Requires "[PATCH] ARM: Fix memblock_reserve() to include stext" during run time to allow test of CPU Hotplug with v3.11-rc kernels.
arch/arm/mach-shmobile/headsmp.S | 50 ++++++++++++++++++++++++++ arch/arm/mach-shmobile/include/mach/common.h | 4 ++ arch/arm/mach-shmobile/platsmp-scu.c | 17 +++++--- arch/arm/mach-shmobile/platsmp.c | 18 +++++++++ 4 files changed, 83 insertions(+), 6 deletions(-)
Magnus Damm
maintainerPATCH 1/2 ARM: shmobile: Introduce per-CPU SMP boot / sleep code
From: Magnus Damm <[email protected]>
Add per-CPU SMP boot / sleep code that can be used by all SoCs included in mach-shmobile.
The boot code reads out the per-CPU MPIDR id value and matches it with the value stored for any CPU number, and if there is a match and the boot function is set as well then the boot function will be executed.
The sleep code simply uses WFI and then jumps back to the boot code to see if anyone has asked to wake up that CPU, if not it will sleep again.
---
arch/arm/mach-shmobile/headsmp.S | 50 ++++++++++++++++++++++++++ arch/arm/mach-shmobile/include/mach/common.h | 4 ++ arch/arm/mach-shmobile/platsmp.c | 18 +++++++++ 3 files changed, 72 insertions(+)
arch/arm/mach-shmobile/headsmp.S +50 -0
@@ -40,3 +40,53 @@ shmobile_boot_fn: .globl shmobile_boot_arg shmobile_boot_arg: 2: .space 4 + +/* + * Per-CPU SMP boot function/argument selection code based on MPIDR + */ + +ENTRY(shmobile_smp_boot) + @ r0 = MPIDR_HWID_BITMASK + mrc p15, 0, r1, c0, c0, 5 @ r1 = MPIDR + and r0, r1, r0 @ r0 = cpu_logical_map() value + mov r1, #0 @ r1 = CPU index + adr r5, 1f @ array of per-cpu mpidr values + adr r6, 2f @ array of per-cpu functions + adr r7, 3f @ array of per-cpu arguments + +shmobile_smp_boot_find_mpidr: + ldr r8, [r5, r1, lsl #2] + cmp r8, r0 + bne shmobile_smp_boot_next + + ldr r9, [r6, r1, lsl #2] + cmp r9, #0 + bne shmobile_smp_boot_found + +shmobile_smp_boot_next: + add r1, r1, #1 + cmp r1, #CONFIG_NR_CPUS + blo shmobile_smp_boot_find_mpidr + + b shmobile_smp_sleep + +shmobile_smp_boot_found: + ldr r0, [r7, r1, lsl #2] + mov pc, r9 +ENDPROC(shmobile_smp_boot) + +ENTRY(shmobile_smp_sleep) + wfi + b shmobile_smp_boot +ENDPROC(shmobile_smp_sleep) + + .globl shmobile_smp_mpidr +shmobile_smp_mpidr: +1: .space CONFIG_NR_CPUS * 4 + .globl shmobile_smp_fn +shmobile_smp_fn: +2: .space CONFIG_NR_CPUS * 4 + .globl shmobile_smp_arg +shmobile_smp_arg: +3: .space CONFIG_NR_CPUS * 4 +
arch/arm/mach-shmobile/include/mach/common.h +4 -0
@@ -10,6 +10,10 @@ extern void shmobile_setup_console(void)extern void shmobile_boot_vector (void );extern unsigned long shmobile_boot_fn;extern unsigned long shmobile_boot_arg; +extern void shmobile_smp_boot (void ); +extern void shmobile_smp_sleep (void ); +extern void shmobile_smp_hook (unsigned int cpu,unsigned long fn, +unsigned long arg);extern void shmobile_boot_scu (void );extern void shmobile_smp_scu_prepare_cpus (unsigned int max_cpus); extern int shmobile_smp_scu_boot_secondary(unsigned int cpu,
arch/arm/mach-shmobile/platsmp.c +18 -0
@@ -12,6 +12,9 @@*/ #include <linux/init.h> #include <linux/smp.h> +#include <asm/cacheflush.h> +#include <asm/smp_plat.h> +#include <mach/common.h> void __init shmobile_smp_init_cpus (unsigned int ncores) {
@@ -26,3 +29,18 @@ void __init shmobile_smp_init_cpus(unsigfor (i =0 ; i < ncores; i++)set_cpu_possible (i, true); } + +extern unsigned long shmobile_smp_fn[]; +extern unsigned long shmobile_smp_arg[]; +extern unsigned long shmobile_smp_mpidr[]; + +void shmobile_smp_hook (unsigned int cpu,unsigned long fn,unsigned long arg) +{ + shmobile_smp_fn[cpu] =0 ; +flush_cache_all (); + + shmobile_smp_mpidr[cpu] =cpu_logical_map (cpu); + shmobile_smp_fn[cpu] = fn; + shmobile_smp_arg[cpu] = arg; +flush_cache_all (); +}
PATCH 1/2 ARM: shmobile: Introduce per-CPU SMP boot / sleep code
Quoted 10 lines · Magnus Damm
From: Magnus Damm <[email protected]>
Add per-CPU SMP boot / sleep code that can be used by all SoCs included in mach-shmobile.
The boot code reads out the per-CPU MPIDR id value and matches it with the value stored for any CPU number, and if there is a match and the boot function is set as well then the boot function will be executed.
Quoted 5 lines
The sleep code simply uses WFI and then jumps back to the boot code to see if anyone has asked to wake up that CPU, if not it will sleep again.
Signed-off-by Magnus Damm <[email protected]>
Hi Magnus,
I have queued this up for v3.12 in the smp branch
with the following whitespace changes:
Quoted 17 lines
---
arch/arm/mach-shmobile/headsmp.S | 50 ++++++++++++++++++++++++++ arch/arm/mach-shmobile/include/mach/common.h | 4 ++ arch/arm/mach-shmobile/platsmp.c | 18 +++++++++ 3 files changed, 72 insertions(+)arch/arm/mach-shmobile/headsmp.S +4
-0@@ -40,3 +40,53 @@ shmobile_boot_fn: .globl shmobile_boot_arg shmobile_boot_arg: 2: .space 4 + +/* + * Per-CPU SMP boot function/argument selection code based on MPIDR + */
arch/arm/mach-shmobile/headsmp.S shmobile_boot_fn: · line 56
Quoted 10 lines
arch/arm/mach-shmobile/headsmp.S +10
-0+ +ENTRY(shmobile_smp_boot) + @ r0 = MPIDR_HWID_BITMASK + mrc p15, 0, r1, c0, c0, 5 @ r1 = MPIDR + and r0, r1, r0 @ r0 = cpu_logical_map() value + mov r1, #0 @ r1 = CPU index + adr r5, 1f @ array of per-cpu mpidr values + adr r6, 2f @ array of per-cpu functions + adr r7, 3f @ array of per-cpu arguments +
Removed trailing whitespace from line above.
arch/arm/mach-shmobile/headsmp.S shmobile_boot_fn: · line 65
Quoted 9 lines
arch/arm/mach-shmobile/headsmp.S +9
-0+shmobile_smp_boot_find_mpidr: + ldr r8, [r5, r1, lsl #2] + cmp r8, r0 + bne shmobile_smp_boot_next + + ldr r9, [r6, r1, lsl #2] + cmp r9, #0 + bne shmobile_smp_boot_found +
Removed trailing whitespace from line above.
arch/arm/mach-shmobile/headsmp.S shmobile_boot_fn: · line 72
Quoted 7 lines
arch/arm/mach-shmobile/headsmp.S +7
-0+shmobile_smp_boot_next: + add r1, r1, #1 + cmp r1, #CONFIG_NR_CPUS + blo shmobile_smp_boot_find_mpidr + + b shmobile_smp_sleep +
Removed trailing whitespace from line above.
Quoted 10 lines
arch/arm/mach-shmobile/headsmp.S +10
-0+shmobile_smp_boot_found: + ldr r0, [r7, r1, lsl #2] + mov pc, r9 +ENDPROC(shmobile_smp_boot) + +ENTRY(shmobile_smp_sleep) + wfi + b shmobile_smp_boot +ENDPROC(shmobile_smp_sleep) +
arch/arm/mach-shmobile/headsmp.S shmobile_boot_fn: · line 92
Quoted 10 lines
arch/arm/mach-shmobile/headsmp.S +10
-0+ .globl shmobile_smp_mpidr +shmobile_smp_mpidr: +1: .space CONFIG_NR_CPUS * 4 + .globl shmobile_smp_fn +shmobile_smp_fn: +2: .space CONFIG_NR_CPUS * 4 + .globl shmobile_smp_arg +shmobile_smp_arg: +3: .space CONFIG_NR_CPUS * 4 +
Remove trailing blank line from line above.
Quoted 45 lines
arch/arm/mach-shmobile/include/mach/common.h +4
-0@@ -10,6 +10,10 @@ extern void shmobile_setup_console(void)extern void shmobile_boot_vector (void );extern unsigned long shmobile_boot_fn;extern unsigned long shmobile_boot_arg; +extern void shmobile_smp_boot (void ); +extern void shmobile_smp_sleep (void ); +extern void shmobile_smp_hook (unsigned int cpu,unsigned long fn, +unsigned long arg);extern void shmobile_boot_scu (void );extern void shmobile_smp_scu_prepare_cpus (unsigned int max_cpus); extern int shmobile_smp_scu_boot_secondary(unsigned int cpu,arch/arm/mach-shmobile/platsmp.c +18
-0@@ -12,6 +12,9 @@*/ #include <linux/init.h> #include <linux/smp.h> +#include <asm/cacheflush.h> +#include <asm/smp_plat.h> +#include <mach/common.h> void __init shmobile_smp_init_cpus (unsigned int ncores) {@@ -26,3 +29,18 @@ void __init shmobile_smp_init_cpus(unsigfor (i =0 ; i < ncores; i++)set_cpu_possible (i, true); } + +extern unsigned long shmobile_smp_fn[]; +extern unsigned long shmobile_smp_arg[]; +extern unsigned long shmobile_smp_mpidr[]; + +void shmobile_smp_hook (unsigned int cpu,unsigned long fn,unsigned long arg) +{ + shmobile_smp_fn[cpu] =0 ; +flush_cache_all (); + + shmobile_smp_mpidr[cpu] =cpu_logical_map (cpu); + shmobile_smp_fn[cpu] = fn; + shmobile_smp_arg[cpu] = arg; +flush_cache_all (); +}
Magnus Damm
maintainerPATCH 2/2 ARM: shmobile: Per-CPU SMP boot / sleep code for SCU SoCs
In reply to Magnus DammFrom: Magnus Damm <[email protected]>
Hook in the per-CPU boot and sleep code in the shared mach-shmobile SCU code. CPUs may be kept in the asm routine until ->boot_secondary() when the per-CPU boot vector is installed. At the end of ->die() the asm sleep routine is invoked.
---
arch/arm/mach-shmobile/platsmp-scu.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
arch/arm/mach-shmobile/platsmp-scu.c +11 -6
@@ -18,8 +18,9 @@void __init shmobile_smp_scu_prepare_cpus (unsigned int max_cpus) { - shmobile_boot_fn =virt_to_phys (shmobile_boot_scu); - shmobile_boot_arg = (unsigned long )shmobile_scu_base; +/* install boot code shared by all CPUs */ + shmobile_boot_fn =virt_to_phys (shmobile_smp_boot); + shmobile_boot_arg =MPIDR_HWID_BITMASK ;/* enable SCU and cache coherency on booting CPU */ scu_enable (shmobile_scu_base);
@@ -28,22 +29,26 @@ void __init shmobile_smp_scu_prepare_cpuint shmobile_smp_scu_boot_secondary (unsigned int cpu,struct task_struct *idle) { -/* do nothing for now */ +/* For this particular CPU register SCU boot vector */ +shmobile_smp_hook (cpu,virt_to_phys (shmobile_boot_scu), + (unsigned long )shmobile_scu_base);return 0 ; }#ifdef CONFIG_HOTPLUG_CPU void shmobile_smp_scu_cpu_die (unsigned int cpu) { +/* For this particular CPU deregister boot vector */ +shmobile_smp_hook (cpu,0 ,0 ); +dsb ();flush_cache_all ();/* disable cache coherency */ scu_power_mode (shmobile_scu_base,SCU_PM_POWEROFF ); -/* Endless loop until reset */ -while (1 ) -cpu_do_idle (); +/* jump to shared mach-shmobile sleep / reset code */ +shmobile_smp_sleep (); }static int shmobile_smp_scu_psr_core_disabled (int cpu)
PATCH 2/2 ARM: shmobile: Per-CPU SMP boot / sleep code for SCU SoCs
Quoted 9 lines · Magnus Damm
From: Magnus Damm <[email protected]>
Hook in the per-CPU boot and sleep code in the shared mach-shmobile SCU code. CPUs may be kept in the asm routine until ->boot_secondary() when the per-CPU boot vector is installed. At the end of ->die() the asm sleep routine is invoked.
Signed-off-by Magnus Damm <[email protected]>
Thanks, I have queued this up for v3.12 in the smp branch.