Loading...
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * PowerPC 64-bit swsusp implementation
4 *
5 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
6 */
7
8#include <linux/threads.h>
9#include <asm/processor.h>
10#include <asm/page.h>
11#include <asm/cputable.h>
12#include <asm/thread_info.h>
13#include <asm/ppc_asm.h>
14#include <asm/asm-offsets.h>
15#include <asm/feature-fixups.h>
16
17/*
18 * Structure for storing CPU registers on the save area.
19 */
20#define SL_r1 0x00 /* stack pointer */
21#define SL_PC 0x08
22#define SL_MSR 0x10
23#define SL_SDR1 0x18
24#define SL_XER 0x20
25#define SL_TB 0x40
26#define SL_r2 0x48
27#define SL_CR 0x50
28#define SL_LR 0x58
29#define SL_r12 0x60
30#define SL_r13 0x68
31#define SL_r14 0x70
32#define SL_r15 0x78
33#define SL_r16 0x80
34#define SL_r17 0x88
35#define SL_r18 0x90
36#define SL_r19 0x98
37#define SL_r20 0xa0
38#define SL_r21 0xa8
39#define SL_r22 0xb0
40#define SL_r23 0xb8
41#define SL_r24 0xc0
42#define SL_r25 0xc8
43#define SL_r26 0xd0
44#define SL_r27 0xd8
45#define SL_r28 0xe0
46#define SL_r29 0xe8
47#define SL_r30 0xf0
48#define SL_r31 0xf8
49#define SL_SPRG1 0x100
50#define SL_TCR 0x108
51#define SL_SIZE SL_TCR+8
52
53/* these macros rely on the save area being
54 * pointed to by r11 */
55
56#define SAVE_SPR(register) \
57 mfspr r0, SPRN_##register ;\
58 std r0, SL_##register(r11)
59#define RESTORE_SPR(register) \
60 ld r0, SL_##register(r11) ;\
61 mtspr SPRN_##register, r0
62#define SAVE_SPECIAL(special) \
63 mf##special r0 ;\
64 std r0, SL_##special(r11)
65#define RESTORE_SPECIAL(special) \
66 ld r0, SL_##special(r11) ;\
67 mt##special r0
68#define SAVE_REGISTER(reg) \
69 std reg, SL_##reg(r11)
70#define RESTORE_REGISTER(reg) \
71 ld reg, SL_##reg(r11)
72
73/* space for storing cpu state */
74 .section .data
75 .align 5
76swsusp_save_area:
77 .space SL_SIZE
78
79 .section .text
80 .align 5
81_GLOBAL(swsusp_arch_suspend)
82 LOAD_REG_ADDR(r11, swsusp_save_area)
83 SAVE_SPECIAL(LR)
84 SAVE_REGISTER(r1)
85 SAVE_SPECIAL(CR)
86 SAVE_SPECIAL(TB)
87 SAVE_REGISTER(r2)
88 SAVE_REGISTER(r12)
89 SAVE_REGISTER(r13)
90 SAVE_REGISTER(r14)
91 SAVE_REGISTER(r15)
92 SAVE_REGISTER(r16)
93 SAVE_REGISTER(r17)
94 SAVE_REGISTER(r18)
95 SAVE_REGISTER(r19)
96 SAVE_REGISTER(r20)
97 SAVE_REGISTER(r21)
98 SAVE_REGISTER(r22)
99 SAVE_REGISTER(r23)
100 SAVE_REGISTER(r24)
101 SAVE_REGISTER(r25)
102 SAVE_REGISTER(r26)
103 SAVE_REGISTER(r27)
104 SAVE_REGISTER(r28)
105 SAVE_REGISTER(r29)
106 SAVE_REGISTER(r30)
107 SAVE_REGISTER(r31)
108 SAVE_SPECIAL(MSR)
109 SAVE_SPECIAL(XER)
110#ifdef CONFIG_PPC_BOOK3S_64
111BEGIN_FW_FTR_SECTION
112 SAVE_SPECIAL(SDR1)
113END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR)
114#else
115 SAVE_SPR(TCR)
116
117 /* Save SPRG1, SPRG1 be used save paca */
118 SAVE_SPR(SPRG1)
119#endif
120
121 /* we push the stack up 128 bytes but don't store the
122 * stack pointer on the stack like a real stackframe */
123 addi r1,r1,-128
124
125 bl swsusp_save
126
127 /* restore LR */
128 LOAD_REG_ADDR(r11, swsusp_save_area)
129 RESTORE_SPECIAL(LR)
130 addi r1,r1,128
131
132 blr
133
134/* Resume code */
135_GLOBAL(swsusp_arch_resume)
136 /* Stop pending alitvec streams and memory accesses */
137BEGIN_FTR_SECTION
138 PPC_DSSALL
139END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
140 sync
141
142 LOAD_REG_ADDR(r11, restore_pblist)
143 ld r12,0(r12)
144
145 cmpdi r12,0
146 beq- nothing_to_copy
147 li r15,PAGE_SIZE>>3
148copyloop:
149 ld r13,pbe_address(r12)
150 ld r14,pbe_orig_address(r12)
151
152 mtctr r15
153 li r10,0
154copy_page_loop:
155 ldx r0,r10,r13
156 stdx r0,r10,r14
157 addi r10,r10,8
158 bdnz copy_page_loop
159
160 ld r12,pbe_next(r12)
161 cmpdi r12,0
162 bne+ copyloop
163nothing_to_copy:
164
165#ifdef CONFIG_PPC_BOOK3S_64
166 /* flush caches */
167 lis r3, 0x10
168 mtctr r3
169 li r3, 0
170 ori r3, r3, CONFIG_KERNEL_START>>48
171 li r0, 48
172 sld r3, r3, r0
173 li r0, 0
1741:
175 dcbf 0,r3
176 addi r3,r3,0x20
177 bdnz 1b
178
179 sync
180
181 tlbia
182#endif
183
184 LOAD_REG_ADDR(r11, swsusp_save_area)
185
186 RESTORE_SPECIAL(CR)
187
188 /* restore timebase */
189 /* load saved tb */
190 ld r1, SL_TB(r11)
191 /* get upper 32 bits of it */
192 srdi r2, r1, 32
193 /* clear tb lower to avoid wrap */
194 li r0, 0
195 mttbl r0
196 /* set tb upper */
197 mttbu r2
198 /* set tb lower */
199 mttbl r1
200
201 /* restore registers */
202 RESTORE_REGISTER(r1)
203 RESTORE_REGISTER(r2)
204 RESTORE_REGISTER(r12)
205 RESTORE_REGISTER(r13)
206 RESTORE_REGISTER(r14)
207 RESTORE_REGISTER(r15)
208 RESTORE_REGISTER(r16)
209 RESTORE_REGISTER(r17)
210 RESTORE_REGISTER(r18)
211 RESTORE_REGISTER(r19)
212 RESTORE_REGISTER(r20)
213 RESTORE_REGISTER(r21)
214 RESTORE_REGISTER(r22)
215 RESTORE_REGISTER(r23)
216 RESTORE_REGISTER(r24)
217 RESTORE_REGISTER(r25)
218 RESTORE_REGISTER(r26)
219 RESTORE_REGISTER(r27)
220 RESTORE_REGISTER(r28)
221 RESTORE_REGISTER(r29)
222 RESTORE_REGISTER(r30)
223 RESTORE_REGISTER(r31)
224
225#ifdef CONFIG_PPC_BOOK3S_64
226 /* can't use RESTORE_SPECIAL(MSR) */
227 ld r0, SL_MSR(r11)
228 mtmsrd r0, 0
229BEGIN_FW_FTR_SECTION
230 RESTORE_SPECIAL(SDR1)
231END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR)
232#else
233 /* Restore SPRG1, be used to save paca */
234 ld r0, SL_SPRG1(r11)
235 mtsprg 1, r0
236
237 RESTORE_SPECIAL(MSR)
238
239 /* Restore TCR and clear any pending bits in TSR. */
240 RESTORE_SPR(TCR)
241 lis r0, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h
242 mtspr SPRN_TSR, r0
243
244 /* Kick decrementer */
245 li r0, 1
246 mtdec r0
247
248 /* Invalidate all tlbs */
249 bl _tlbil_all
250#endif
251 RESTORE_SPECIAL(XER)
252
253 sync
254
255 addi r1,r1,-128
256#ifdef CONFIG_PPC_BOOK3S_64
257 bl slb_flush_and_restore_bolted
258#endif
259 bl do_after_copyback
260 addi r1,r1,128
261
262 LOAD_REG_ADDR(r11, swsusp_save_area)
263 RESTORE_SPECIAL(LR)
264
265 li r3, 0
266 blr
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * PowerPC 64-bit swsusp implementation
4 *
5 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
6 */
7
8#include <linux/threads.h>
9#include <asm/processor.h>
10#include <asm/page.h>
11#include <asm/cputable.h>
12#include <asm/thread_info.h>
13#include <asm/ppc_asm.h>
14#include <asm/asm-offsets.h>
15#include <asm/feature-fixups.h>
16
17/*
18 * Structure for storing CPU registers on the save area.
19 */
20#define SL_r1 0x00 /* stack pointer */
21#define SL_PC 0x08
22#define SL_MSR 0x10
23#define SL_SDR1 0x18
24#define SL_XER 0x20
25#define SL_TB 0x40
26#define SL_r2 0x48
27#define SL_CR 0x50
28#define SL_LR 0x58
29#define SL_r12 0x60
30#define SL_r13 0x68
31#define SL_r14 0x70
32#define SL_r15 0x78
33#define SL_r16 0x80
34#define SL_r17 0x88
35#define SL_r18 0x90
36#define SL_r19 0x98
37#define SL_r20 0xa0
38#define SL_r21 0xa8
39#define SL_r22 0xb0
40#define SL_r23 0xb8
41#define SL_r24 0xc0
42#define SL_r25 0xc8
43#define SL_r26 0xd0
44#define SL_r27 0xd8
45#define SL_r28 0xe0
46#define SL_r29 0xe8
47#define SL_r30 0xf0
48#define SL_r31 0xf8
49#define SL_SPRG1 0x100
50#define SL_TCR 0x108
51#define SL_SIZE SL_TCR+8
52
53/* these macros rely on the save area being
54 * pointed to by r11 */
55
56#define SAVE_SPR(register) \
57 mfspr r0, SPRN_##register ;\
58 std r0, SL_##register(r11)
59#define RESTORE_SPR(register) \
60 ld r0, SL_##register(r11) ;\
61 mtspr SPRN_##register, r0
62#define SAVE_SPECIAL(special) \
63 mf##special r0 ;\
64 std r0, SL_##special(r11)
65#define RESTORE_SPECIAL(special) \
66 ld r0, SL_##special(r11) ;\
67 mt##special r0
68#define SAVE_REGISTER(reg) \
69 std reg, SL_##reg(r11)
70#define RESTORE_REGISTER(reg) \
71 ld reg, SL_##reg(r11)
72
73/* space for storing cpu state */
74 .section .data
75 .align 5
76swsusp_save_area:
77 .space SL_SIZE
78
79 .section ".toc","aw"
80swsusp_save_area_ptr:
81 .tc swsusp_save_area[TC],swsusp_save_area
82restore_pblist_ptr:
83 .tc restore_pblist[TC],restore_pblist
84
85 .section .text
86 .align 5
87_GLOBAL(swsusp_arch_suspend)
88 ld r11,swsusp_save_area_ptr@toc(r2)
89 SAVE_SPECIAL(LR)
90 SAVE_REGISTER(r1)
91 SAVE_SPECIAL(CR)
92 SAVE_SPECIAL(TB)
93 SAVE_REGISTER(r2)
94 SAVE_REGISTER(r12)
95 SAVE_REGISTER(r13)
96 SAVE_REGISTER(r14)
97 SAVE_REGISTER(r15)
98 SAVE_REGISTER(r16)
99 SAVE_REGISTER(r17)
100 SAVE_REGISTER(r18)
101 SAVE_REGISTER(r19)
102 SAVE_REGISTER(r20)
103 SAVE_REGISTER(r21)
104 SAVE_REGISTER(r22)
105 SAVE_REGISTER(r23)
106 SAVE_REGISTER(r24)
107 SAVE_REGISTER(r25)
108 SAVE_REGISTER(r26)
109 SAVE_REGISTER(r27)
110 SAVE_REGISTER(r28)
111 SAVE_REGISTER(r29)
112 SAVE_REGISTER(r30)
113 SAVE_REGISTER(r31)
114 SAVE_SPECIAL(MSR)
115 SAVE_SPECIAL(XER)
116#ifdef CONFIG_PPC_BOOK3S_64
117BEGIN_FW_FTR_SECTION
118 SAVE_SPECIAL(SDR1)
119END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR)
120#else
121 SAVE_SPR(TCR)
122
123 /* Save SPRG1, SPRG1 be used save paca */
124 SAVE_SPR(SPRG1)
125#endif
126
127 /* we push the stack up 128 bytes but don't store the
128 * stack pointer on the stack like a real stackframe */
129 addi r1,r1,-128
130
131 bl _iommu_save
132 bl swsusp_save
133
134 /* restore LR */
135 ld r11,swsusp_save_area_ptr@toc(r2)
136 RESTORE_SPECIAL(LR)
137 addi r1,r1,128
138
139 blr
140
141/* Resume code */
142_GLOBAL(swsusp_arch_resume)
143 /* Stop pending alitvec streams and memory accesses */
144BEGIN_FTR_SECTION
145 DSSALL
146END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
147 sync
148
149 ld r12,restore_pblist_ptr@toc(r2)
150 ld r12,0(r12)
151
152 cmpdi r12,0
153 beq- nothing_to_copy
154 li r15,PAGE_SIZE>>3
155copyloop:
156 ld r13,pbe_address(r12)
157 ld r14,pbe_orig_address(r12)
158
159 mtctr r15
160 li r10,0
161copy_page_loop:
162 ldx r0,r10,r13
163 stdx r0,r10,r14
164 addi r10,r10,8
165 bdnz copy_page_loop
166
167 ld r12,pbe_next(r12)
168 cmpdi r12,0
169 bne+ copyloop
170nothing_to_copy:
171
172#ifdef CONFIG_PPC_BOOK3S_64
173 /* flush caches */
174 lis r3, 0x10
175 mtctr r3
176 li r3, 0
177 ori r3, r3, CONFIG_KERNEL_START>>48
178 li r0, 48
179 sld r3, r3, r0
180 li r0, 0
1811:
182 dcbf 0,r3
183 addi r3,r3,0x20
184 bdnz 1b
185
186 sync
187
188 tlbia
189#endif
190
191 ld r11,swsusp_save_area_ptr@toc(r2)
192
193 RESTORE_SPECIAL(CR)
194
195 /* restore timebase */
196 /* load saved tb */
197 ld r1, SL_TB(r11)
198 /* get upper 32 bits of it */
199 srdi r2, r1, 32
200 /* clear tb lower to avoid wrap */
201 li r0, 0
202 mttbl r0
203 /* set tb upper */
204 mttbu r2
205 /* set tb lower */
206 mttbl r1
207
208 /* restore registers */
209 RESTORE_REGISTER(r1)
210 RESTORE_REGISTER(r2)
211 RESTORE_REGISTER(r12)
212 RESTORE_REGISTER(r13)
213 RESTORE_REGISTER(r14)
214 RESTORE_REGISTER(r15)
215 RESTORE_REGISTER(r16)
216 RESTORE_REGISTER(r17)
217 RESTORE_REGISTER(r18)
218 RESTORE_REGISTER(r19)
219 RESTORE_REGISTER(r20)
220 RESTORE_REGISTER(r21)
221 RESTORE_REGISTER(r22)
222 RESTORE_REGISTER(r23)
223 RESTORE_REGISTER(r24)
224 RESTORE_REGISTER(r25)
225 RESTORE_REGISTER(r26)
226 RESTORE_REGISTER(r27)
227 RESTORE_REGISTER(r28)
228 RESTORE_REGISTER(r29)
229 RESTORE_REGISTER(r30)
230 RESTORE_REGISTER(r31)
231
232#ifdef CONFIG_PPC_BOOK3S_64
233 /* can't use RESTORE_SPECIAL(MSR) */
234 ld r0, SL_MSR(r11)
235 mtmsrd r0, 0
236BEGIN_FW_FTR_SECTION
237 RESTORE_SPECIAL(SDR1)
238END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR)
239#else
240 /* Restore SPRG1, be used to save paca */
241 ld r0, SL_SPRG1(r11)
242 mtsprg 1, r0
243
244 RESTORE_SPECIAL(MSR)
245
246 /* Restore TCR and clear any pending bits in TSR. */
247 RESTORE_SPR(TCR)
248 lis r0, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h
249 mtspr SPRN_TSR, r0
250
251 /* Kick decrementer */
252 li r0, 1
253 mtdec r0
254
255 /* Invalidate all tlbs */
256 bl _tlbil_all
257#endif
258 RESTORE_SPECIAL(XER)
259
260 sync
261
262 addi r1,r1,-128
263#ifdef CONFIG_PPC_BOOK3S_64
264 bl slb_flush_and_restore_bolted
265#endif
266 bl do_after_copyback
267 addi r1,r1,128
268
269 ld r11,swsusp_save_area_ptr@toc(r2)
270 RESTORE_SPECIAL(LR)
271
272 li r3, 0
273 blr