Commit | Line | Data |
---|---|---|
543b9fd3 JB |
1 | /* |
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> | |
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 | |
5a31057f WD |
49 | #define SL_SPRG1 0x100 |
50 | #define SL_TCR 0x108 | |
51 | #define SL_SIZE SL_TCR+8 | |
543b9fd3 JB |
52 | |
53 | /* these macros rely on the save area being | |
54 | * pointed to by r11 */ | |
5a31057f WD |
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 | |
543b9fd3 JB |
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 | |
76 | swsusp_save_area: | |
77 | .space SL_SIZE | |
78 | ||
79 | .section ".toc","aw" | |
80 | swsusp_save_area_ptr: | |
81 | .tc swsusp_save_area[TC],swsusp_save_area | |
82 | restore_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) | |
543b9fd3 | 115 | SAVE_SPECIAL(XER) |
5a31057f | 116 | #ifdef CONFIG_PPC_BOOK3S_64 |
711b5138 | 117 | BEGIN_FW_FTR_SECTION |
5a31057f | 118 | SAVE_SPECIAL(SDR1) |
711b5138 | 119 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR) |
5a31057f WD |
120 | #else |
121 | SAVE_SPR(TCR) | |
122 | ||
123 | /* Save SPRG1, SPRG1 be used save paca */ | |
124 | SAVE_SPR(SPRG1) | |
125 | #endif | |
543b9fd3 JB |
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 */ | |
144 | BEGIN_FTR_SECTION | |
145 | DSSALL | |
146 | END_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 | |
2e2b4043 | 154 | li r15,PAGE_SIZE>>3 |
543b9fd3 JB |
155 | copyloop: |
156 | ld r13,pbe_address(r12) | |
157 | ld r14,pbe_orig_address(r12) | |
158 | ||
159 | mtctr r15 | |
160 | li r10,0 | |
161 | copy_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 | |
170 | nothing_to_copy: | |
171 | ||
5a31057f | 172 | #ifdef CONFIG_PPC_BOOK3S_64 |
543b9fd3 JB |
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 | |
181 | 1: | |
182 | dcbf r0,r3 | |
183 | addi r3,r3,0x20 | |
184 | bdnz 1b | |
185 | ||
186 | sync | |
187 | ||
188 | tlbia | |
5a31057f | 189 | #endif |
543b9fd3 JB |
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) | |
5a31057f WD |
231 | |
232 | #ifdef CONFIG_PPC_BOOK3S_64 | |
543b9fd3 JB |
233 | /* can't use RESTORE_SPECIAL(MSR) */ |
234 | ld r0, SL_MSR(r11) | |
235 | mtmsrd r0, 0 | |
711b5138 | 236 | BEGIN_FW_FTR_SECTION |
543b9fd3 | 237 | RESTORE_SPECIAL(SDR1) |
711b5138 | 238 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR) |
5a31057f WD |
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 | |
543b9fd3 JB |
258 | RESTORE_SPECIAL(XER) |
259 | ||
260 | sync | |
261 | ||
262 | addi r1,r1,-128 | |
5a31057f | 263 | #ifdef CONFIG_PPC_BOOK3S_64 |
543b9fd3 | 264 | bl slb_flush_and_rebolt |
5a31057f | 265 | #endif |
543b9fd3 JB |
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 |