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