From aa940437832f8c2a943ec967a9794f2ece14498e Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 8 Nov 2024 12:24:27 +0100 Subject: [PATCH] suit: Added the possibility to halt cores in some cases This commit adds the possibility to stop cores (and restart them) - however only in the case if it is the only local core started. Signed-off-by: Artur Hadasz --- .../suit/platform/sdfw/include/suit_cpu_run.h | 14 ++++ .../sdfw/src/runners/suit_run_nrf54h20.c | 74 ++++++++++++++++++- .../sdfw/src/runners/suit_run_posix.c | 14 ++++ .../suit/platform/sdfw/src/suit_plat_invoke.c | 6 +- 4 files changed, 104 insertions(+), 4 deletions(-) diff --git a/subsys/suit/platform/sdfw/include/suit_cpu_run.h b/subsys/suit/platform/sdfw/include/suit_cpu_run.h index d68017f4fba9..633ee518b78f 100644 --- a/subsys/suit/platform/sdfw/include/suit_cpu_run.h +++ b/subsys/suit/platform/sdfw/include/suit_cpu_run.h @@ -14,6 +14,20 @@ extern "C" { #endif +/** + * @brief Halt specified CPU. + * + * @note Implementation depends on SoC on which it's built. + * + * @param[in] cpu_id ID of CPU to be halted + * + * @retval SUIT_PLAT_SUCCESS in case of successful halt + * @retval SUIT_PLAT_ERR_CRASH if CPU halt failed + * @retval SUIT_PLAT_ERR_UNSUPPORTED if handling CPU halt is not supported + * @retval SUIT_PLAT_ERR_INVAL if CPU ID is unknown + */ +suit_plat_err_t suit_plat_cpu_halt(uint8_t cpu_id); + /** * @brief Run specified CPU. * diff --git a/subsys/suit/platform/sdfw/src/runners/suit_run_nrf54h20.c b/subsys/suit/platform/sdfw/src/runners/suit_run_nrf54h20.c index b547a7edac90..a566172f2ab1 100644 --- a/subsys/suit/platform/sdfw/src/runners/suit_run_nrf54h20.c +++ b/subsys/suit/platform/sdfw/src/runners/suit_run_nrf54h20.c @@ -18,6 +18,67 @@ LOG_MODULE_REGISTER(suit_plat_run, CONFIG_SUIT_LOG_LEVEL); +#define HALTABLE_CPUS (BIT(NRF_PROCESSOR_APPLICATION) | BIT(NRF_PROCESSOR_RADIOCORE)) + +/** Bitmask indicating, which CPU IDs were invoked. + * + * @note Since it is not possible to invoke the same CPU twice or halt a CPU that + * was not invoked, this value is used to detect those unsupported operations. + */ +static uint32_t running_cpus; + +suit_plat_err_t suit_plat_cpu_halt(uint8_t cpu_id) +{ + int ret = 0; + + switch (cpu_id) { + case NRF_PROCESSOR_APPLICATION: /* AppCore */ + case NRF_PROCESSOR_RADIOCORE: /* RadioCore */ +#ifdef CONFIG_SDFW_RESET_HANDLING_ENABLED + if ((running_cpus & BIT(cpu_id)) == 0) { + LOG_INF("Cortex core %d is not running - skip CPU halt", cpu_id); + } else if ((running_cpus & HALTABLE_CPUS) == BIT(cpu_id)) { + LOG_INF("Halting CPU %d", cpu_id); + ret = reset_mgr_reset_domains_sync(); + } else { + LOG_ERR("Failed to halt CPU %d", cpu_id); + LOG_ERR("Halting single CPU while other CPUs are running is not supported"); + return SUIT_PLAT_ERR_UNSUPPORTED; + } +#else /* CONFIG_SDFW_RESET_HANDLING_ENABLED */ + LOG_WRN("Cortex core handling not supported - skip CPU %d halt", cpu_id); +#endif /* CONFIG_SDFW_RESET_HANDLING_ENABLED */ + break; + + case NRF_PROCESSOR_SYSCTRL: /* SysCtrl */ + if ((running_cpus & BIT(cpu_id)) == 0) { + LOG_INF("Cortex core %d is not running - skip CPU halt", cpu_id); + break; + } else { + LOG_ERR("Halting SysCtrl is not supported"); + return SUIT_PLAT_ERR_UNSUPPORTED; + } + + case NRF_PROCESSOR_PPR: /* PPR(VPR) */ + case NRF_PROCESSOR_FLPR: /* FLPR(VPR) */ + LOG_ERR("Application VPR %d halt is not supported in SUIT", cpu_id); + return SUIT_PLAT_ERR_UNSUPPORTED; + + default: + LOG_ERR("Unsupported CPU ID: %d", cpu_id); + return SUIT_PLAT_ERR_INVAL; + } + + if (ret != 0) { + LOG_ERR("Failed to halt CPU %d (err: %d)", cpu_id, ret); + return SUIT_PLAT_ERR_CRASH; + } + + running_cpus &= ~BIT(cpu_id); + + return SUIT_PLAT_SUCCESS; +} + suit_plat_err_t suit_plat_cpu_run(uint8_t cpu_id, uintptr_t run_address) { int ret = 0; @@ -26,9 +87,14 @@ suit_plat_err_t suit_plat_cpu_run(uint8_t cpu_id, uintptr_t run_address) case NRF_PROCESSOR_APPLICATION: /* AppCore */ case NRF_PROCESSOR_RADIOCORE: /* RadioCore */ #ifdef CONFIG_SDFW_RESET_HANDLING_ENABLED - LOG_INF("Starting Cortex core %d from address 0x%lx", cpu_id, run_address); - /* Single run address implies no NSVTOR, so keep at reset value of 0x0. */ - ret = reset_mgr_init_and_boot_processor(cpu_id, run_address, 0); + if ((running_cpus & BIT(cpu_id)) == 0) { + LOG_INF("Starting Cortex core %d from address 0x%lx", cpu_id, run_address); + /* Single run address implies no NSVTOR, so keep at reset value of 0x0. */ + ret = reset_mgr_init_and_boot_processor(cpu_id, run_address, 0); + } else { + LOG_ERR("Cortex core %d is running - fail CPU start", cpu_id); + return SUIT_PLAT_ERR_INCORRECT_STATE; + } #else /* CONFIG_SDFW_RESET_HANDLING_ENABLED */ LOG_WRN("Cortex core handling not supported - skip CPU %d start", cpu_id); #endif /* CONFIG_SDFW_RESET_HANDLING_ENABLED */ @@ -59,5 +125,7 @@ suit_plat_err_t suit_plat_cpu_run(uint8_t cpu_id, uintptr_t run_address) return SUIT_PLAT_ERR_CRASH; } + running_cpus |= BIT(cpu_id); + return SUIT_PLAT_SUCCESS; } diff --git a/subsys/suit/platform/sdfw/src/runners/suit_run_posix.c b/subsys/suit/platform/sdfw/src/runners/suit_run_posix.c index 5992a6f62f90..919e7db7388f 100644 --- a/subsys/suit/platform/sdfw/src/runners/suit_run_posix.c +++ b/subsys/suit/platform/sdfw/src/runners/suit_run_posix.c @@ -17,6 +17,20 @@ LOG_MODULE_REGISTER(suit_plat_run, CONFIG_SUIT_LOG_LEVEL); +suit_plat_err_t suit_plat_cpu_halt(uint8_t cpu_id) +{ + switch (cpu_id) { + case NRF_PROCESSORPOSIX_1: + case NRF_PROCESSORPOSIX_2: + LOG_INF("Mock AppCore/RadioCore halt"); + return SUIT_PLAT_SUCCESS; + + default: + LOG_ERR("Unsupported CPU ID (%d)", cpu_id); + return SUIT_PLAT_ERR_INVAL; + } +} + suit_plat_err_t suit_plat_cpu_run(uint8_t cpu_id, uintptr_t run_address) { switch (cpu_id) { diff --git a/subsys/suit/platform/sdfw/src/suit_plat_invoke.c b/subsys/suit/platform/sdfw/src/suit_plat_invoke.c index 5c1b2c5f125f..e0c956ca85a6 100644 --- a/subsys/suit/platform/sdfw/src/suit_plat_invoke.c +++ b/subsys/suit/platform/sdfw/src/suit_plat_invoke.c @@ -99,7 +99,11 @@ int suit_plat_invoke(suit_component_t image_handle, struct zcbor_string *invoke_ switch (component_type) { case SUIT_COMPONENT_TYPE_MEM: /* memory-mapped */ - ret = suit_plat_cpu_run(cpu_id, run_address); + ret = suit_plat_cpu_halt(cpu_id); + + if (ret == 0) { + ret = suit_plat_cpu_run(cpu_id, run_address); + } break; default: LOG_ERR("Unsupported component type");