GNU Linux-libre 4.9.333-gnu1
[releases.git] / arch / powerpc / kernel / swsusp_32.S
1 #include <linux/threads.h>
2 #include <asm/processor.h>
3 #include <asm/page.h>
4 #include <asm/cputable.h>
5 #include <asm/thread_info.h>
6 #include <asm/ppc_asm.h>
7 #include <asm/asm-offsets.h>
8 #include <asm/mmu.h>
9
10 /*
11  * Structure for storing CPU registers on the save area.
12  */
13 #define SL_SP           0
14 #define SL_PC           4
15 #define SL_MSR          8
16 #define SL_SDR1         0xc
17 #define SL_SPRG0        0x10    /* 4 sprg's */
18 #define SL_DBAT0        0x20
19 #define SL_IBAT0        0x28
20 #define SL_DBAT1        0x30
21 #define SL_IBAT1        0x38
22 #define SL_DBAT2        0x40
23 #define SL_IBAT2        0x48
24 #define SL_DBAT3        0x50
25 #define SL_IBAT3        0x58
26 #define SL_DBAT4        0x60
27 #define SL_IBAT4        0x68
28 #define SL_DBAT5        0x70
29 #define SL_IBAT5        0x78
30 #define SL_DBAT6        0x80
31 #define SL_IBAT6        0x88
32 #define SL_DBAT7        0x90
33 #define SL_IBAT7        0x98
34 #define SL_TB           0xa0
35 #define SL_R2           0xa8
36 #define SL_CR           0xac
37 #define SL_LR           0xb0
38 #define SL_R12          0xb4    /* r12 to r31 */
39 #define SL_SIZE         (SL_R12 + 80)
40
41         .section .data
42         .align  5
43
44 _GLOBAL(swsusp_save_area)
45         .space  SL_SIZE
46
47
48         .section .text
49         .align  5
50
51 _GLOBAL(swsusp_arch_suspend)
52
53         lis     r11,swsusp_save_area@h
54         ori     r11,r11,swsusp_save_area@l
55
56         mflr    r0
57         stw     r0,SL_LR(r11)
58         mfcr    r0
59         stw     r0,SL_CR(r11)
60         stw     r1,SL_SP(r11)
61         stw     r2,SL_R2(r11)
62         stmw    r12,SL_R12(r11)
63
64         /* Save MSR & SDR1 */
65         mfmsr   r4
66         stw     r4,SL_MSR(r11)
67         mfsdr1  r4
68         stw     r4,SL_SDR1(r11)
69
70         /* Get a stable timebase and save it */
71 1:      mftbu   r4
72         stw     r4,SL_TB(r11)
73         mftb    r5
74         stw     r5,SL_TB+4(r11)
75         mftbu   r3
76         cmpw    r3,r4
77         bne     1b
78
79         /* Save SPRGs */
80         mfsprg  r4,0
81         stw     r4,SL_SPRG0(r11)
82         mfsprg  r4,1
83         stw     r4,SL_SPRG0+4(r11)
84         mfsprg  r4,2
85         stw     r4,SL_SPRG0+8(r11)
86         mfsprg  r4,3
87         stw     r4,SL_SPRG0+12(r11)
88
89         /* Save BATs */
90         mfdbatu r4,0
91         stw     r4,SL_DBAT0(r11)
92         mfdbatl r4,0
93         stw     r4,SL_DBAT0+4(r11)
94         mfdbatu r4,1
95         stw     r4,SL_DBAT1(r11)
96         mfdbatl r4,1
97         stw     r4,SL_DBAT1+4(r11)
98         mfdbatu r4,2
99         stw     r4,SL_DBAT2(r11)
100         mfdbatl r4,2
101         stw     r4,SL_DBAT2+4(r11)
102         mfdbatu r4,3
103         stw     r4,SL_DBAT3(r11)
104         mfdbatl r4,3
105         stw     r4,SL_DBAT3+4(r11)
106         mfibatu r4,0
107         stw     r4,SL_IBAT0(r11)
108         mfibatl r4,0
109         stw     r4,SL_IBAT0+4(r11)
110         mfibatu r4,1
111         stw     r4,SL_IBAT1(r11)
112         mfibatl r4,1
113         stw     r4,SL_IBAT1+4(r11)
114         mfibatu r4,2
115         stw     r4,SL_IBAT2(r11)
116         mfibatl r4,2
117         stw     r4,SL_IBAT2+4(r11)
118         mfibatu r4,3
119         stw     r4,SL_IBAT3(r11)
120         mfibatl r4,3
121         stw     r4,SL_IBAT3+4(r11)
122
123 BEGIN_MMU_FTR_SECTION
124         mfspr   r4,SPRN_DBAT4U
125         stw     r4,SL_DBAT4(r11)
126         mfspr   r4,SPRN_DBAT4L
127         stw     r4,SL_DBAT4+4(r11)
128         mfspr   r4,SPRN_DBAT5U
129         stw     r4,SL_DBAT5(r11)
130         mfspr   r4,SPRN_DBAT5L
131         stw     r4,SL_DBAT5+4(r11)
132         mfspr   r4,SPRN_DBAT6U
133         stw     r4,SL_DBAT6(r11)
134         mfspr   r4,SPRN_DBAT6L
135         stw     r4,SL_DBAT6+4(r11)
136         mfspr   r4,SPRN_DBAT7U
137         stw     r4,SL_DBAT7(r11)
138         mfspr   r4,SPRN_DBAT7L
139         stw     r4,SL_DBAT7+4(r11)
140         mfspr   r4,SPRN_IBAT4U
141         stw     r4,SL_IBAT4(r11)
142         mfspr   r4,SPRN_IBAT4L
143         stw     r4,SL_IBAT4+4(r11)
144         mfspr   r4,SPRN_IBAT5U
145         stw     r4,SL_IBAT5(r11)
146         mfspr   r4,SPRN_IBAT5L
147         stw     r4,SL_IBAT5+4(r11)
148         mfspr   r4,SPRN_IBAT6U
149         stw     r4,SL_IBAT6(r11)
150         mfspr   r4,SPRN_IBAT6L
151         stw     r4,SL_IBAT6+4(r11)
152         mfspr   r4,SPRN_IBAT7U
153         stw     r4,SL_IBAT7(r11)
154         mfspr   r4,SPRN_IBAT7L
155         stw     r4,SL_IBAT7+4(r11)
156 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
157
158 #if  0
159         /* Backup various CPU config stuffs */
160         bl      __save_cpu_setup
161 #endif
162         /* Call the low level suspend stuff (we should probably have made
163          * a stackframe...
164          */
165         bl      swsusp_save
166
167         /* Restore LR from the save area */
168         lis     r11,swsusp_save_area@h
169         ori     r11,r11,swsusp_save_area@l
170         lwz     r0,SL_LR(r11)
171         mtlr    r0
172
173         blr
174
175
176 /* Resume code */
177 _GLOBAL(swsusp_arch_resume)
178
179 #ifdef CONFIG_ALTIVEC
180         /* Stop pending alitvec streams and memory accesses */
181 BEGIN_FTR_SECTION
182         DSSALL
183 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
184 #endif
185         sync
186
187         /* Disable MSR:DR to make sure we don't take a TLB or
188          * hash miss during the copy, as our hash table will
189          * for a while be unusable. For .text, we assume we are
190          * covered by a BAT. This works only for non-G5 at this
191          * point. G5 will need a better approach, possibly using
192          * a small temporary hash table filled with large mappings,
193          * disabling the MMU completely isn't a good option for
194          * performance reasons.
195          * (Note that 750's may have the same performance issue as
196          * the G5 in this case, we should investigate using moving
197          * BATs for these CPUs)
198          */
199         mfmsr   r0
200         sync
201         rlwinm  r0,r0,0,28,26           /* clear MSR_DR */
202         mtmsr   r0
203         sync
204         isync
205
206         /* Load ptr the list of pages to copy in r3 */
207         lis     r11,(restore_pblist - KERNELBASE)@h
208         ori     r11,r11,restore_pblist@l
209         lwz     r10,0(r11)
210
211         /* Copy the pages. This is a very basic implementation, to
212          * be replaced by something more cache efficient */
213 1:
214         tophys(r3,r10)
215         li      r0,256
216         mtctr   r0
217         lwz     r11,pbe_address(r3)     /* source */
218         tophys(r5,r11)
219         lwz     r10,pbe_orig_address(r3)        /* destination */
220         tophys(r6,r10)
221 2:
222         lwz     r8,0(r5)
223         lwz     r9,4(r5)
224         lwz     r10,8(r5)
225         lwz     r11,12(r5)
226         addi    r5,r5,16
227         stw     r8,0(r6)
228         stw     r9,4(r6)
229         stw     r10,8(r6)
230         stw     r11,12(r6)
231         addi    r6,r6,16
232         bdnz    2b
233         lwz             r10,pbe_next(r3)
234         cmpwi   0,r10,0
235         bne     1b
236
237         /* Do a very simple cache flush/inval of the L1 to ensure
238          * coherency of the icache
239          */
240         lis     r3,0x0002
241         mtctr   r3
242         li      r3, 0
243 1:
244         lwz     r0,0(r3)
245         addi    r3,r3,0x0020
246         bdnz    1b
247         isync
248         sync
249
250         /* Now flush those cache lines */
251         lis     r3,0x0002
252         mtctr   r3
253         li      r3, 0
254 1:
255         dcbf    0,r3
256         addi    r3,r3,0x0020
257         bdnz    1b
258         sync
259
260         /* Ok, we are now running with the kernel data of the old
261          * kernel fully restored. We can get to the save area
262          * easily now. As for the rest of the code, it assumes the
263          * loader kernel and the booted one are exactly identical
264          */
265         lis     r11,swsusp_save_area@h
266         ori     r11,r11,swsusp_save_area@l
267         tophys(r11,r11)
268
269 #if 0
270         /* Restore various CPU config stuffs */
271         bl      __restore_cpu_setup
272 #endif
273         /* Restore the BATs, and SDR1.  Then we can turn on the MMU.
274          * This is a bit hairy as we are running out of those BATs,
275          * but first, our code is probably in the icache, and we are
276          * writing the same value to the BAT, so that should be fine,
277          * though a better solution will have to be found long-term
278          */
279         lwz     r4,SL_SDR1(r11)
280         mtsdr1  r4
281         lwz     r4,SL_SPRG0(r11)
282         mtsprg  0,r4
283         lwz     r4,SL_SPRG0+4(r11)
284         mtsprg  1,r4
285         lwz     r4,SL_SPRG0+8(r11)
286         mtsprg  2,r4
287         lwz     r4,SL_SPRG0+12(r11)
288         mtsprg  3,r4
289
290 #if 0
291         lwz     r4,SL_DBAT0(r11)
292         mtdbatu 0,r4
293         lwz     r4,SL_DBAT0+4(r11)
294         mtdbatl 0,r4
295         lwz     r4,SL_DBAT1(r11)
296         mtdbatu 1,r4
297         lwz     r4,SL_DBAT1+4(r11)
298         mtdbatl 1,r4
299         lwz     r4,SL_DBAT2(r11)
300         mtdbatu 2,r4
301         lwz     r4,SL_DBAT2+4(r11)
302         mtdbatl 2,r4
303         lwz     r4,SL_DBAT3(r11)
304         mtdbatu 3,r4
305         lwz     r4,SL_DBAT3+4(r11)
306         mtdbatl 3,r4
307         lwz     r4,SL_IBAT0(r11)
308         mtibatu 0,r4
309         lwz     r4,SL_IBAT0+4(r11)
310         mtibatl 0,r4
311         lwz     r4,SL_IBAT1(r11)
312         mtibatu 1,r4
313         lwz     r4,SL_IBAT1+4(r11)
314         mtibatl 1,r4
315         lwz     r4,SL_IBAT2(r11)
316         mtibatu 2,r4
317         lwz     r4,SL_IBAT2+4(r11)
318         mtibatl 2,r4
319         lwz     r4,SL_IBAT3(r11)
320         mtibatu 3,r4
321         lwz     r4,SL_IBAT3+4(r11)
322         mtibatl 3,r4
323 BEGIN_MMU_FTR_SECTION
324         lwz     r4,SL_DBAT4(r11)
325         mtspr   SPRN_DBAT4U,r4
326         lwz     r4,SL_DBAT4+4(r11)
327         mtspr   SPRN_DBAT4L,r4
328         lwz     r4,SL_DBAT5(r11)
329         mtspr   SPRN_DBAT5U,r4
330         lwz     r4,SL_DBAT5+4(r11)
331         mtspr   SPRN_DBAT5L,r4
332         lwz     r4,SL_DBAT6(r11)
333         mtspr   SPRN_DBAT6U,r4
334         lwz     r4,SL_DBAT6+4(r11)
335         mtspr   SPRN_DBAT6L,r4
336         lwz     r4,SL_DBAT7(r11)
337         mtspr   SPRN_DBAT7U,r4
338         lwz     r4,SL_DBAT7+4(r11)
339         mtspr   SPRN_DBAT7L,r4
340         lwz     r4,SL_IBAT4(r11)
341         mtspr   SPRN_IBAT4U,r4
342         lwz     r4,SL_IBAT4+4(r11)
343         mtspr   SPRN_IBAT4L,r4
344         lwz     r4,SL_IBAT5(r11)
345         mtspr   SPRN_IBAT5U,r4
346         lwz     r4,SL_IBAT5+4(r11)
347         mtspr   SPRN_IBAT5L,r4
348         lwz     r4,SL_IBAT6(r11)
349         mtspr   SPRN_IBAT6U,r4
350         lwz     r4,SL_IBAT6+4(r11)
351         mtspr   SPRN_IBAT6L,r4
352         lwz     r4,SL_IBAT7(r11)
353         mtspr   SPRN_IBAT7U,r4
354         lwz     r4,SL_IBAT7+4(r11)
355         mtspr   SPRN_IBAT7L,r4
356 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
357 #endif
358
359         /* Flush all TLBs */
360         lis     r4,0x1000
361 1:      addic.  r4,r4,-0x1000
362         tlbie   r4
363         bgt     1b
364         sync
365
366         /* restore the MSR and turn on the MMU */
367         lwz     r3,SL_MSR(r11)
368         bl      turn_on_mmu
369         tovirt(r11,r11)
370
371         /* Restore TB */
372         li      r3,0
373         mttbl   r3
374         lwz     r3,SL_TB(r11)
375         lwz     r4,SL_TB+4(r11)
376         mttbu   r3
377         mttbl   r4
378
379         /* Kick decrementer */
380         li      r0,1
381         mtdec   r0
382
383         /* Restore the callee-saved registers and return */
384         lwz     r0,SL_CR(r11)
385         mtcr    r0
386         lwz     r2,SL_R2(r11)
387         lmw     r12,SL_R12(r11)
388         lwz     r1,SL_SP(r11)
389         lwz     r0,SL_LR(r11)
390         mtlr    r0
391
392         // XXX Note: we don't really need to call swsusp_resume
393
394         li      r3,0
395         blr
396
397 /* FIXME:This construct is actually not useful since we don't shut
398  * down the instruction MMU, we could just flip back MSR-DR on.
399  */
400 turn_on_mmu:
401         mflr    r4
402         mtsrr0  r4
403         mtsrr1  r3
404         sync
405         isync
406         rfi
407