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