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