From: Mirela Simonovic Date: Fri, 1 Jun 2018 13:17:43 +0000 (+0200) Subject: xen/arm: Implement CPU_OFF PSCI call (physical interface) X-Git-Tag: archive/raspbian/4.14.0+80-gd101b417b7-1+rpi1^2~63^2~3704^2~20 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=cd80acdaddd791f9c8846d8a5c614db2a942c0c4;p=xen.git xen/arm: Implement CPU_OFF PSCI call (physical interface) During the system suspend to RAM non-boot CPUs will be hotplugged. This will be triggered via disable_nonboot_cpus() call. When hotplugged the CPU will end up in an infinite wfi loop in stop_cpu(). This patch adds PSCI CPU_OFF call to the EL3 with the aim to get powered down the calling CPU during the suspend. The CPU_OFF call will be made only if the PSCI version is higher than v0.1 (Note that the CPU_OFF function is mandatory since PSCI v0.2). If PSCI CPU_OFF call to the EL3 succeeds it will not return. Otherwise, when the PSCI CPU_OFF call returns we'll raise panic, because the calling CPU couldn't be enabled afterwards (stays in WFI loop forever). Note that if the PSCI version is higher than v0.1 the CPU_OFF will be called regardless of the system state. This is done because scenarios other than suspend may benefit from powering off the CPU. Signed-off-by: Mirela Simonovic Acked-by: Julien Grall --- diff --git a/xen/arch/arm/psci.c b/xen/arch/arm/psci.c index 94b616df9b..3cf5ecf0f3 100644 --- a/xen/arch/arm/psci.c +++ b/xen/arch/arm/psci.c @@ -46,6 +46,19 @@ int call_psci_cpu_on(int cpu) return call_smc(psci_cpu_on_nr, cpu_logical_map(cpu), __pa(init_secondary), 0); } +void call_psci_cpu_off(void) +{ + if ( psci_ver > PSCI_VERSION(0, 1) ) + { + int errno; + + /* If successfull the PSCI cpu_off call doesn't return */ + errno = call_smc(PSCI_0_2_FN32_CPU_OFF, 0, 0, 0); + panic("PSCI cpu off failed for CPU%d err=%d\n", smp_processor_id(), + errno); + } +} + void call_psci_system_off(void) { if ( psci_ver > PSCI_VERSION(0, 1) ) diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c index b2116f0d2d..8b1e274bf3 100644 --- a/xen/arch/arm/smpboot.c +++ b/xen/arch/arm/smpboot.c @@ -395,6 +395,8 @@ void stop_cpu(void) /* Make sure the write happens before we sleep forever */ dsb(sy); isb(); + call_psci_cpu_off(); + while ( 1 ) wfi(); } diff --git a/xen/include/asm-arm/psci.h b/xen/include/asm-arm/psci.h index 9ac820e94a..832f77afff 100644 --- a/xen/include/asm-arm/psci.h +++ b/xen/include/asm-arm/psci.h @@ -20,6 +20,7 @@ extern uint32_t psci_ver; int psci_init(void); int call_psci_cpu_on(int cpu); +void call_psci_cpu_off(void); void call_psci_system_off(void); void call_psci_system_reset(void);