From 4364ba77ef242e0090b9a4da34f38e81fd34880e Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Sat, 4 Oct 2025 14:50:48 +0200 Subject: [PATCH 1/3] [nrf fromlist] soc: nordic: nrf54h: s2ram: Use ARM MPU save/restore funcs This reduced the amount of duplicate code and unifies the code with other platforms. MPU retention was originally added in ee9d23945f18868196db0353e2879a955af2667d. Upstream PR #: 97073 Signed-off-by: Rubin Gerritsen --- soc/nordic/nrf54h/pm_s2ram.c | 78 +++++------------------------------- 1 file changed, 10 insertions(+), 68 deletions(-) diff --git a/soc/nordic/nrf54h/pm_s2ram.c b/soc/nordic/nrf54h/pm_s2ram.c index 6916e488472..452ce473841 100644 --- a/soc/nordic/nrf54h/pm_s2ram.c +++ b/soc/nordic/nrf54h/pm_s2ram.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -22,16 +23,6 @@ #define SCnSCB_CPPWR_SU10_Pos 20U /*!< CPPWR: SU10 Position */ #define SCnSCB_CPPWR_SU10_Msk (1UL << SCnSCB_CPPWR_SU10_Pos) /*!< CPPWR: SU10 Mask */ -/* Currently dynamic regions are only used in case of userspace or stack guard and - * stack guard is not used by default on Cortex-M33 because there is a dedicated - * mechanism for stack overflow detection. Unless those condition change we don't - * need to store MPU content, it can just be reinitialized on resuming. - */ -#define MPU_USE_DYNAMIC_REGIONS IS_ENABLED(CONFIG_USERSPACE) || IS_ENABLED(CONFIG_MPU_STACK_GUARD) - -/* TODO: The num-mpu-regions property should be used. Needs to be added to dts bindings. */ -#define MPU_MAX_NUM_REGIONS 16 - typedef struct { /* NVIC components stored into RAM. */ uint32_t ISER[NVIC_MEMBER_SIZE(ISER)]; @@ -39,15 +30,6 @@ typedef struct { uint8_t IPR[NVIC_MEMBER_SIZE(IPR)]; } _nvic_context_t; -typedef struct { - uint32_t RNR; - uint32_t RBAR[MPU_MAX_NUM_REGIONS]; - uint32_t RLAR[MPU_MAX_NUM_REGIONS]; - uint32_t MAIR0; - uint32_t MAIR1; - uint32_t CTRL; -} _mpu_context_t; - typedef struct { uint32_t ICSR; uint32_t VTOR; @@ -76,7 +58,9 @@ typedef struct { struct backup { _nvic_context_t nvic_context; - _mpu_context_t mpu_context; +#if defined(CONFIG_ARM_MPU) + struct z_mpu_context_retained mpu_context; +#endif _scb_context_t scb_context; #if defined(CONFIG_FPU) && !defined(CONFIG_FPU_SHARING) _fpu_context_t fpu_context; @@ -85,52 +69,6 @@ struct backup { static __noinit struct backup backup_data; -extern void z_arm_configure_static_mpu_regions(void); -extern int z_arm_mpu_init(void); - -/* MPU registers cannot be simply copied because content of RBARx RLARx registers - * depends on region which is selected by RNR register. - */ -static void mpu_save(_mpu_context_t *backup) -{ - if (!MPU_USE_DYNAMIC_REGIONS) { - return; - } - - backup->RNR = MPU->RNR; - - for (uint8_t i = 0; i < MPU_MAX_NUM_REGIONS; i++) { - MPU->RNR = i; - backup->RBAR[i] = MPU->RBAR; - backup->RLAR[i] = MPU->RLAR; - } - backup->MAIR0 = MPU->MAIR0; - backup->MAIR1 = MPU->MAIR1; - backup->CTRL = MPU->CTRL; -} - -static void mpu_restore(_mpu_context_t *backup) -{ - if (!MPU_USE_DYNAMIC_REGIONS) { - z_arm_mpu_init(); - z_arm_configure_static_mpu_regions(); - return; - } - - uint32_t rnr = backup->RNR; - - for (uint8_t i = 0; i < MPU_MAX_NUM_REGIONS; i++) { - MPU->RNR = i; - MPU->RBAR = backup->RBAR[i]; - MPU->RLAR = backup->RLAR[i]; - } - - MPU->MAIR0 = backup->MAIR0; - MPU->MAIR1 = backup->MAIR1; - MPU->RNR = rnr; - MPU->CTRL = backup->CTRL; -} - static void nvic_save(_nvic_context_t *backup) { memcpy(backup->ISER, (uint32_t *)NVIC->ISER, sizeof(NVIC->ISER)); @@ -245,7 +183,9 @@ int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) fpu_power_down(); #endif nvic_save(&backup_data.nvic_context); - mpu_save(&backup_data.mpu_context); +#if defined(CONFIG_ARM_MPU) + z_arm_save_mpu_context(&backup_data.mpu_context); +#endif ret = arch_pm_s2ram_suspend(system_off); /* Cache and FPU are powered down so power up is needed even if s2ram failed. */ nrf_power_up_cache(); @@ -260,7 +200,9 @@ int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) return ret; } - mpu_restore(&backup_data.mpu_context); +#if defined(CONFIG_ARM_MPU) + z_arm_restore_mpu_context(&backup_data.mpu_context); +#endif nvic_restore(&backup_data.nvic_context); scb_restore(&backup_data.scb_context); From ee1acf101b9923c3f63425eee80f4ed02219e337 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Sat, 4 Oct 2025 14:57:26 +0200 Subject: [PATCH 2/3] [nrf fromlist] soc: nordic: nrf54h: s2ram: Use ARM SCB save/restore funcs This reduced the amount of duplicate code and unifies the code with other platforms. With this change fewer registers are stored and restored. See also comment in scb.h for scb_context stating that only essential registers are stored and restored. No longer stored: - ICSR - SCR - CFSR - HFSR - DFSR - MMFAR - BFAR - AFSR No longer used: - SHPR[3..12]. This backup register was declared in the wrong way. In core_cm33.h and core_cm4.h this is declared as an array of 12 uint8_t's. That is 3 uint32_t's. Orignal SCB retention was added in 2055f7d5956aecf55c4babca22eadb23d59bc534. Upstream PR #: 97073 Signed-off-by: Rubin Gerritsen --- soc/nordic/nrf54h/pm_s2ram.c | 60 +++--------------------------------- 1 file changed, 4 insertions(+), 56 deletions(-) diff --git a/soc/nordic/nrf54h/pm_s2ram.c b/soc/nordic/nrf54h/pm_s2ram.c index 452ce473841..d1e1fbdfaca 100644 --- a/soc/nordic/nrf54h/pm_s2ram.c +++ b/soc/nordic/nrf54h/pm_s2ram.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -30,23 +31,6 @@ typedef struct { uint8_t IPR[NVIC_MEMBER_SIZE(IPR)]; } _nvic_context_t; -typedef struct { - uint32_t ICSR; - uint32_t VTOR; - uint32_t AIRCR; - uint32_t SCR; - uint32_t CCR; - uint32_t SHPR[12U]; - uint32_t SHCSR; - uint32_t CFSR; - uint32_t HFSR; - uint32_t DFSR; - uint32_t MMFAR; - uint32_t BFAR; - uint32_t AFSR; - uint32_t CPACR; -} _scb_context_t; - #if defined(CONFIG_FPU) && !defined(CONFIG_FPU_SHARING) typedef struct { uint32_t FPCCR; @@ -61,7 +45,7 @@ struct backup { #if defined(CONFIG_ARM_MPU) struct z_mpu_context_retained mpu_context; #endif - _scb_context_t scb_context; + struct scb_context scb_context; #if defined(CONFIG_FPU) && !defined(CONFIG_FPU_SHARING) _fpu_context_t fpu_context; #endif @@ -83,42 +67,6 @@ static void nvic_restore(_nvic_context_t *backup) memcpy((uint32_t *)NVIC->IPR, backup->IPR, sizeof(NVIC->IPR)); } -static void scb_save(_scb_context_t *backup) -{ - backup->ICSR = SCB->ICSR; - backup->VTOR = SCB->VTOR; - backup->AIRCR = SCB->AIRCR; - backup->SCR = SCB->SCR; - backup->CCR = SCB->CCR; - memcpy(backup->SHPR, (uint32_t *)SCB->SHPR, sizeof(SCB->SHPR)); - backup->SHCSR = SCB->SHCSR; - backup->CFSR = SCB->CFSR; - backup->HFSR = SCB->HFSR; - backup->DFSR = SCB->DFSR; - backup->MMFAR = SCB->MMFAR; - backup->BFAR = SCB->BFAR; - backup->AFSR = SCB->AFSR; - backup->CPACR = SCB->CPACR; -} - -static void scb_restore(_scb_context_t *backup) -{ - SCB->ICSR = backup->ICSR; - SCB->VTOR = backup->VTOR; - SCB->AIRCR = backup->AIRCR; - SCB->SCR = backup->SCR; - SCB->CCR = backup->CCR; - memcpy((uint32_t *)SCB->SHPR, backup->SHPR, sizeof(SCB->SHPR)); - SCB->SHCSR = backup->SHCSR; - SCB->CFSR = backup->CFSR; - SCB->HFSR = backup->HFSR; - SCB->DFSR = backup->DFSR; - SCB->MMFAR = backup->MMFAR; - SCB->BFAR = backup->BFAR; - SCB->AFSR = backup->AFSR; - SCB->CPACR = backup->CPACR; -} - #if defined(CONFIG_FPU) static void fpu_power_down(void) { @@ -175,7 +123,7 @@ int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) int ret; SET_MCUBOOT_RESUME_MAGIC(); - scb_save(&backup_data.scb_context); + z_arm_save_scb_context(&backup_data.scb_context); #if defined(CONFIG_FPU) #if !defined(CONFIG_FPU_SHARING) fpu_save(&backup_data.fpu_context); @@ -204,7 +152,7 @@ int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) z_arm_restore_mpu_context(&backup_data.mpu_context); #endif nvic_restore(&backup_data.nvic_context); - scb_restore(&backup_data.scb_context); + z_arm_restore_scb_context(&backup_data.scb_context); return ret; } From 4ceb55a77da895db2f27944662794240ad581ff2 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Sat, 4 Oct 2025 15:08:25 +0200 Subject: [PATCH 3/3] [nrf fromlist] soc: nordic: nrf54h: s2ram: Use ARM FPU save/restore funcs This reduced the amount of duplicate code and unifies the code with other platforms. With this change the caller and callee status registers are stored separately. Also, a different set of status registers are stored: - FPSCR instead of FPDSCR. FPDSCR contains the default values to be assigned to FPSCR when a new floating-point context is created. It therefore seems more correct to store the FPSCR. - FPCCR and FPCAR are no longer stored. FPU retention was originally added in: 8a5365c26c69c53c9800ae70498a0cde875d2726. Upstream PR #: 97073 Signed-off-by: Rubin Gerritsen --- soc/nordic/nrf54h/pm_s2ram.c | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/soc/nordic/nrf54h/pm_s2ram.c b/soc/nordic/nrf54h/pm_s2ram.c index d1e1fbdfaca..08be128ac43 100644 --- a/soc/nordic/nrf54h/pm_s2ram.c +++ b/soc/nordic/nrf54h/pm_s2ram.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -31,15 +32,6 @@ typedef struct { uint8_t IPR[NVIC_MEMBER_SIZE(IPR)]; } _nvic_context_t; -#if defined(CONFIG_FPU) && !defined(CONFIG_FPU_SHARING) -typedef struct { - uint32_t FPCCR; - uint32_t FPCAR; - uint32_t FPDSCR; - uint32_t S[32]; -} _fpu_context_t; -#endif - struct backup { _nvic_context_t nvic_context; #if defined(CONFIG_ARM_MPU) @@ -47,7 +39,7 @@ struct backup { #endif struct scb_context scb_context; #if defined(CONFIG_FPU) && !defined(CONFIG_FPU_SHARING) - _fpu_context_t fpu_context; + struct fpu_ctx_full fpu_context; #endif }; @@ -83,26 +75,6 @@ static void fpu_power_up(void) __DSB(); __ISB(); } - -#if !defined(CONFIG_FPU_SHARING) -static void fpu_save(_fpu_context_t *backup) -{ - backup->FPCCR = FPU->FPCCR; - backup->FPCAR = FPU->FPCAR; - backup->FPDSCR = FPU->FPDSCR; - - __asm__ volatile("vstmia %0, {s0-s31}\n" : : "r"(backup->S) : "memory"); -} - -static void fpu_restore(_fpu_context_t *backup) -{ - FPU->FPCCR = backup->FPCCR; - FPU->FPCAR = backup->FPCAR; - FPU->FPDSCR = backup->FPDSCR; - - __asm__ volatile("vldmia %0, {s0-s31}\n" : : "r"(backup->S) : "memory"); -} -#endif /* !defined(CONFIG_FPU_SHARING) */ #endif /* defined(CONFIG_FPU) */ #if DT_NODE_EXISTS(DT_NODELABEL(mcuboot_s2ram)) &&\ @@ -126,7 +98,7 @@ int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) z_arm_save_scb_context(&backup_data.scb_context); #if defined(CONFIG_FPU) #if !defined(CONFIG_FPU_SHARING) - fpu_save(&backup_data.fpu_context); + z_arm_save_fp_context(&backup_data.fpu_context); #endif fpu_power_down(); #endif @@ -141,7 +113,7 @@ int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) fpu_power_up(); #if !defined(CONFIG_FPU_SHARING) /* Also the FPU content might be lost. */ - fpu_restore(&backup_data.fpu_context); + z_arm_restore_fp_context(&backup_data.fpu_context); #endif #endif if (ret < 0) {