From d90712ad2f6ae1c11226bf84241eac6dd2976431 Mon Sep 17 00:00:00 2001 From: Adam Kondraciuk Date: Thu, 17 Oct 2024 12:28:03 +0200 Subject: [PATCH] [nrf fromlist] arch: arm: cortex_m: pm_s2ram: Rework S2RAM mark functions The S2RAM procedure requires marker checking after reset. Such checking is performed on very early stage of the system initialization and must ensure that the stack is not used due to the TLS pointer which is not initialized yet. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/80039 Signed-off-by: Adam Kondraciuk --- arch/arm/core/cortex_m/pm_s2ram.S | 86 +++++++++++++++++++++++---- arch/arm/core/cortex_m/pm_s2ram.c | 20 +------ include/zephyr/arch/common/pm_s2ram.h | 10 ++++ 3 files changed, 85 insertions(+), 31 deletions(-) diff --git a/arch/arm/core/cortex_m/pm_s2ram.S b/arch/arm/core/cortex_m/pm_s2ram.S index f9c82b4069b..744f560ae7a 100644 --- a/arch/arm/core/cortex_m/pm_s2ram.S +++ b/arch/arm/core/cortex_m/pm_s2ram.S @@ -20,6 +20,53 @@ GTEXT(pm_s2ram_mark_set) GTEXT(pm_s2ram_mark_check_and_clear) GDATA(_cpu_context) +#if !(CONFIG_PM_S2RAM_CUSTOM_MARKING) +#define MAGIC (0xDABBAD00) +GDATA(marker) + +SECTION_FUNC(TEXT, pm_s2ram_mark_set) + /* + * Set the marker to MAGIC value + */ + ldr r0, =marker + ldr r2, =MAGIC + str r2, [r0] + + /* + * Restore the PC and continue + */ + mov r15, r1 + +SECTION_FUNC(TEXT, pm_s2ram_mark_check_and_clear) + /* Set return value to 0 */ + mov r0, #0 + + /* + * Check the marker + */ + ldr r2, =marker + ldr r5, [r2] + ldr r3, =MAGIC + cmp r5, r3 + bne exit + + /* + * Reset the marker + */ + str r0, [r2] + + /* + * Set return value to 1 + */ + mov r0, #1 + +exit: + /* + * Restore the PC and continue + */ + mov r15, r1 +#endif + SECTION_FUNC(TEXT, arch_pm_s2ram_suspend) /* * Save the CPU context @@ -67,10 +114,16 @@ SECTION_FUNC(TEXT, arch_pm_s2ram_suspend) mrs r2, control str r2, [r1, #___cpu_context_t_control_OFFSET] + /* + * Save the return address from `pm_s2ram_mark_set` + */ + mov r1, r15 + add r1, #6 + /* * Mark entering suspend to RAM. */ - bl pm_s2ram_mark_set + b pm_s2ram_mark_set /* * Call the system_off function passed as parameter. This should never @@ -83,10 +136,16 @@ SECTION_FUNC(TEXT, arch_pm_s2ram_suspend) * not successful (in r0 the return value). */ + /* + * Save the return address from `pm_s2ram_mark_check_and_clear` + */ + mov r1, r15 + add r1, #6 + /* * Reset the marking of suspend to RAM, return is ignored. */ - bl pm_s2ram_mark_check_and_clear + b pm_s2ram_mark_check_and_clear /* Move system_off back to r0 as return value */ mov r0, r4 @@ -97,18 +156,21 @@ SECTION_FUNC(TEXT, arch_pm_s2ram_suspend) GTEXT(arch_pm_s2ram_resume) SECTION_FUNC(TEXT, arch_pm_s2ram_resume) + + + /* + * Save the return address from `pm_s2ram_mark_check_and_clear` + */ + mov r1, r15 + add r1, #6 + /* * Check if reset occurred after suspending to RAM. - * Store LR to ensure we can continue boot when we are not suspended - * to RAM. In addition to LR, R0 is pushed too, to ensure "SP mod 8 = 0", - * as stated by ARM rule 6.2.1.2 for AAPCS32. - */ - push {r0, lr} - bl pm_s2ram_mark_check_and_clear - cmp r0, #0x1 - pop {r0, lr} - beq resume - bx lr + */ + b pm_s2ram_mark_check_and_clear + cmp r0, #0x1 + beq resume + bx lr resume: /* diff --git a/arch/arm/core/cortex_m/pm_s2ram.c b/arch/arm/core/cortex_m/pm_s2ram.c index 2657d48dc32..88788b0c81a 100644 --- a/arch/arm/core/cortex_m/pm_s2ram.c +++ b/arch/arm/core/cortex_m/pm_s2ram.c @@ -9,8 +9,6 @@ #include -#define MAGIC (0xDABBAD00) - /** * CPU context for S2RAM */ @@ -20,22 +18,6 @@ __noinit _cpu_context_t _cpu_context; /** * S2RAM Marker */ -static __noinit uint32_t marker; - -void pm_s2ram_mark_set(void) -{ - marker = MAGIC; -} - -bool pm_s2ram_mark_check_and_clear(void) -{ - if (marker == MAGIC) { - marker = 0; - - return true; - } - - return false; -} +__noinit uint32_t marker; #endif /* CONFIG_PM_S2RAM_CUSTOM_MARKING */ diff --git a/include/zephyr/arch/common/pm_s2ram.h b/include/zephyr/arch/common/pm_s2ram.h index 34c544c769b..956f07aa352 100644 --- a/include/zephyr/arch/common/pm_s2ram.h +++ b/include/zephyr/arch/common/pm_s2ram.h @@ -65,6 +65,11 @@ int arch_pm_s2ram_suspend(pm_s2ram_system_off_fn_t system_off); * * Default implementation is setting a magic word in RAM. CONFIG_PM_S2RAM_CUSTOM_MARKING * allows custom implementation. + * The following requirements must be fulfilled: + * - the function cannot use stack (most likely asm function) + * - the content of the R1, R4 and LR registers must remain unchanged + * - the last instruction restores the PC stored in R1 register + * */ void pm_s2ram_mark_set(void); @@ -76,6 +81,11 @@ void pm_s2ram_mark_set(void); * * Default implementation is checking a magic word in RAM. CONFIG_PM_S2RAM_CUSTOM_MARKING * allows custom implementation. + * The following requirements must be fulfilled: + * - the function cannot use stack (most likely asm function) + * - the content of the R1, R4 and LR registers must remain unchanged + * - the function's return value is passed by R0 + * - the last instruction restores the PC stored in R1 register * * @retval true if marking is found which indicates resuming after suspend-to-RAM. * @retval false if marking is not found which indicates standard boot.