Hi, I am proposing to have a generic api in psci lib which can be used to force power down all other cores from any initiating core analogous to 'smp_cpu_stop' in linux. It is immune to interrupt lock by EL1/EL2 software.
Platforms may use this api in case of secure side panic, secure watchdog interrupt handling or if required in certain types of warm resets. The usage is platform dependent.
This depends on a generic implementation of secure IPI (1) which uses EHF to handle IPI at platform defined priority. We probably require more types of secure IPIs.
Please review the series Ref: https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/5324
diff --git a/lib/psci/psci_system_off.c b/lib/psci/psci_system_off.c index 141d69e..011aaa6 100644 --- a/lib/psci/psci_system_off.c +++ b/lib/psci/psci_system_off.c @@ -10,10 +10,44 @@ #include <arch_helpers.h> #include <common/debug.h> #include <drivers/console.h> +#include <drivers/delay_timer.h> #include <plat/common/platform.h>
#include "psci_private.h"
+#ifndef PLAT_CORES_PWRDWN_WAIT_TIMEOUT_MS +#define PLAT_CORES_PWRDWN_WAIT_TIMEOUT_MS 1000 +#endif + +#if IMAGE_BL31 +void psci_stop_other_cores(void) +{ +#define PLAT_CORES_PWRDWN_WAIT_TIMEOUT_MS 1000 +#endif + +#if IMAGE_BL31 +void psci_stop_other_cores(void) +{ + int idx, this_cpu_idx, cnt; + + this_cpu_idx = plat_my_core_pos(); + + /* Raise G0 IPI cpustop to all cores but self */ + for (idx = 0; idx < psci_plat_core_count; idx++) { + if ((idx != this_cpu_idx) && + (psci_get_aff_info_state_by_idx(idx) == AFF_STATE_ON)) { + plat_ipi_send_cpu_stop(psci_cpu_pd_nodes[idx].mpidr); + } + } + + /* Wait for others cores to shutdown */ + for (cnt = 0; cnt < PLAT_CORES_PWRDWN_WAIT_TIMEOUT_MS; cnt++) { + if (psci_is_last_on_cpu()) + break; + mdelay(1); + } + + if (!psci_is_last_on_cpu()) { + WARN("Failed to stop all cores!\n"); + psci_print_power_domain_map(); + } +} +#endif +
(1) RFC: ipi: add ipi feature Ref: https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/5323/1
Thanks Sandeep