Skip to content

Commit c64bd82

Browse files
[nrf noup] 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. Signed-off-by: Adam Kondraciuk <[email protected]>
1 parent b10af16 commit c64bd82

File tree

3 files changed

+85
-31
lines changed

3 files changed

+85
-31
lines changed

arch/arm/core/cortex_m/pm_s2ram.S

Lines changed: 74 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,53 @@ GTEXT(pm_s2ram_mark_set)
2020
GTEXT(pm_s2ram_mark_check_and_clear)
2121
GDATA(_cpu_context)
2222

23+
#if !(CONFIG_PM_S2RAM_CUSTOM_MARKING)
24+
#define MAGIC (0xDABBAD00)
25+
GDATA(marker)
26+
27+
SECTION_FUNC(TEXT, pm_s2ram_mark_set)
28+
/*
29+
* Set the marker to MAGIC value
30+
*/
31+
ldr r0, =marker
32+
ldr r2, =MAGIC
33+
str r2, [r0]
34+
35+
/*
36+
* Restore the PC and continue
37+
*/
38+
mov r15, r1
39+
40+
SECTION_FUNC(TEXT, pm_s2ram_mark_check_and_clear)
41+
/* Set return value to 0 */
42+
mov r0, #0
43+
44+
/*
45+
* Check the marker
46+
*/
47+
ldr r2, =marker
48+
ldr r5, [r2]
49+
ldr r3, =MAGIC
50+
cmp r5, r3
51+
bne exit
52+
53+
/*
54+
* Reset the marker
55+
*/
56+
str r0, [r2]
57+
58+
/*
59+
* Set return value to 1
60+
*/
61+
mov r0, #1
62+
63+
exit:
64+
/*
65+
* Restore the PC and continue
66+
*/
67+
mov r15, r1
68+
#endif
69+
2370
SECTION_FUNC(TEXT, arch_pm_s2ram_suspend)
2471
/*
2572
* Save the CPU context
@@ -67,10 +114,16 @@ SECTION_FUNC(TEXT, arch_pm_s2ram_suspend)
67114
mrs r2, control
68115
str r2, [r1, #___cpu_context_t_control_OFFSET]
69116

117+
/*
118+
* Save the return address from `pm_s2ram_mark_set`
119+
*/
120+
mov r1, r15
121+
add r1, #6
122+
70123
/*
71124
* Mark entering suspend to RAM.
72125
*/
73-
bl pm_s2ram_mark_set
126+
b pm_s2ram_mark_set
74127

75128
/*
76129
* Call the system_off function passed as parameter. This should never
@@ -83,10 +136,16 @@ SECTION_FUNC(TEXT, arch_pm_s2ram_suspend)
83136
* not successful (in r0 the return value).
84137
*/
85138

139+
/*
140+
* Save the return address from `pm_s2ram_mark_check_and_clear`
141+
*/
142+
mov r1, r15
143+
add r1, #6
144+
86145
/*
87146
* Reset the marking of suspend to RAM, return is ignored.
88147
*/
89-
bl pm_s2ram_mark_check_and_clear
148+
b pm_s2ram_mark_check_and_clear
90149

91150
/* Move system_off back to r0 as return value */
92151
mov r0, r4
@@ -97,18 +156,21 @@ SECTION_FUNC(TEXT, arch_pm_s2ram_suspend)
97156

98157
GTEXT(arch_pm_s2ram_resume)
99158
SECTION_FUNC(TEXT, arch_pm_s2ram_resume)
159+
160+
161+
/*
162+
* Save the return address from `pm_s2ram_mark_check_and_clear`
163+
*/
164+
mov r1, r15
165+
add r1, #6
166+
100167
/*
101168
* Check if reset occurred after suspending to RAM.
102-
* Store LR to ensure we can continue boot when we are not suspended
103-
* to RAM. In addition to LR, R0 is pushed too, to ensure "SP mod 8 = 0",
104-
* as stated by ARM rule 6.2.1.2 for AAPCS32.
105-
*/
106-
push {r0, lr}
107-
bl pm_s2ram_mark_check_and_clear
108-
cmp r0, #0x1
109-
pop {r0, lr}
110-
beq resume
111-
bx lr
169+
*/
170+
b pm_s2ram_mark_check_and_clear
171+
cmp r0, #0x1
172+
beq resume
173+
bx lr
112174

113175
resume:
114176
/*

arch/arm/core/cortex_m/pm_s2ram.c

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99

1010
#include <zephyr/arch/common/pm_s2ram.h>
1111

12-
#define MAGIC (0xDABBAD00)
13-
1412
/**
1513
* CPU context for S2RAM
1614
*/
@@ -20,22 +18,6 @@ __noinit _cpu_context_t _cpu_context;
2018
/**
2119
* S2RAM Marker
2220
*/
23-
static __noinit uint32_t marker;
24-
25-
void pm_s2ram_mark_set(void)
26-
{
27-
marker = MAGIC;
28-
}
29-
30-
bool pm_s2ram_mark_check_and_clear(void)
31-
{
32-
if (marker == MAGIC) {
33-
marker = 0;
34-
35-
return true;
36-
}
37-
38-
return false;
39-
}
21+
__noinit uint32_t marker;
4022

4123
#endif /* CONFIG_PM_S2RAM_CUSTOM_MARKING */

include/zephyr/arch/common/pm_s2ram.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ int arch_pm_s2ram_suspend(pm_s2ram_system_off_fn_t system_off);
6565
*
6666
* Default implementation is setting a magic word in RAM. CONFIG_PM_S2RAM_CUSTOM_MARKING
6767
* allows custom implementation.
68+
* The following requirements must be fulfilled:
69+
* - the function cannot use stack (most likely asm function)
70+
* - the content of the R1, R4 and LR registers must remain unchanged
71+
* - the last instruction restores the PC stored in R1 register
72+
*
6873
*/
6974
void pm_s2ram_mark_set(void);
7075

@@ -76,6 +81,11 @@ void pm_s2ram_mark_set(void);
7681
*
7782
* Default implementation is checking a magic word in RAM. CONFIG_PM_S2RAM_CUSTOM_MARKING
7883
* allows custom implementation.
84+
* The following requirements must be fulfilled:
85+
* - the function cannot use stack (most likely asm function)
86+
* - the content of the R1, R4 and LR registers must remain unchanged
87+
* - the function's return value is passed by R0
88+
* - the last instruction restores the PC stored in R1 register
7989
*
8090
* @retval true if marking is found which indicates resuming after suspend-to-RAM.
8191
* @retval false if marking is not found which indicates standard boot.

0 commit comments

Comments
 (0)