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