1
2
3
4
5
6
7
8
9
10 #include <linux/linkage.h>
11 #include <asm/asm-offsets.h>
12 #include <asm/page.h>
13 #include <asm/sigp.h>
14 #include <asm/ptrace.h>
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 #define bufsz purgatory_end-stack
35
36 .macro MEMCPY dst,src,len
37 lgr %r0,\dst
38 lgr %r1,\len
39 lgr %r2,\src
40 lgr %r3,\len
41
42 20: mvcle %r0,%r2,0
43 jo 20b
44 .endm
45
46 .macro MEMSWAP dst,src,buf,len
47 10: cghi \len,bufsz
48 jh 11f
49 lgr %r4,\len
50 j 12f
51 11: lghi %r4,bufsz
52
53 12: MEMCPY \buf,\dst,%r4
54 MEMCPY \dst,\src,%r4
55 MEMCPY \src,\buf,%r4
56
57 agr \dst,%r4
58 agr \src,%r4
59 sgr \len,%r4
60
61 cghi \len,0
62 jh 10b
63 .endm
64
65 .macro START_NEXT_KERNEL base
66 lg %r4,kernel_entry-\base(%r13)
67 lg %r5,load_psw_mask-\base(%r13)
68 ogr %r4,%r5
69 stg %r4,0(%r0)
70
71 xgr %r0,%r0
72 diag %r0,%r0,0x308
73 .endm
74
75 .text
76 .align PAGE_SIZE
77 ENTRY(purgatory_start)
78
79
80
81 lhi %r1,1
82 sigp %r1,%r0,SIGP_SET_ARCHITECTURE
83 sam64
84
85 larl %r5,gprregs
86 stmg %r6,%r15,0(%r5)
87
88 basr %r13,0
89 .base_crash:
90
91
92 larl %r15,purgatory_end-STACK_FRAME_OVERHEAD
93
94
95
96
97
98
99
100
101
102
103 lghi %r10,0
104 lg %r11,kernel_type-.base_crash(%r13)
105 cghi %r11,1
106 jne .do_checksum_verification
107 cghi %r2,0
108 jne .do_checksum_verification
109 lghi %r10,1
110
111 .do_checksum_verification:
112 brasl %r14,verify_sha256_digest
113
114 cghi %r10,1
115 je .return_old_kernel
116 cghi %r2,0
117 jne .disabled_wait
118
119
120
121
122 cghi %r11,1
123 je .start_crash_kernel
124
125
126 START_NEXT_KERNEL .base_crash
127
128 .return_old_kernel:
129 lmg %r6,%r15,gprregs-.base_crash(%r13)
130 br %r14
131
132 .disabled_wait:
133 lpswe disabled_wait_psw-.base_crash(%r13)
134
135 .start_crash_kernel:
136
137 lgr %r8,%r13
138 aghi %r8,-(.base_crash-purgatory_start)
139
140
141 lg %r9,crash_size-.base_crash(%r13)
142 aghi %r9,-(purgatory_end-purgatory_start)
143
144
145 lg %r10,crash_start-.base_crash(%r13)
146 agr %r10,%r9
147
148
149
150
151 lghi %r11,bufsz
152 larl %r12,stack
153
154 MEMCPY %r12,%r9,%r11
155 MEMCPY %r9,%r8,%r11
156
157
158 lgr %r7,%r9
159 aghi %r7,.jump_to_dst-purgatory_start
160 br %r7
161
162 .jump_to_dst:
163 basr %r13,0
164 .base_dst:
165
166
167 MEMCPY %r12,%r10,%r11
168
169
170 larl %r7,stack
171 aghi %r10,stack-purgatory_start
172 MEMCPY %r10,%r7,%r11
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 lgr %r12,%r7
189 lgr %r11,%r9
190 lghi %r10,0
191 lg %r9,crash_start-.base_dst(%r13)
192 lghi %r8,16
193 larl %r7,purgatory_sha_regions
194
195 j .loop_first
196
197
198 .loop_next:
199 aghi %r8,-1
200 cghi %r8,0
201 je .loop_out
202
203 aghi %r7,__KEXEC_SHA_REGION_SIZE
204
205 .loop_first:
206 lg %r5,__KEXEC_SHA_REGION_START(%r7)
207 cghi %r5,0
208 je .loop_next
209
210
211
212 sgr %r5,%r9
213 MEMCPY %r9,%r10,%r5
214
215 agr %r9,%r5
216 agr %r10,%r5
217 sgr %r11,%r5
218
219
220 lg %r6,__KEXEC_SHA_REGION_LEN(%r7)
221 MEMSWAP %r9,%r10,%r12,%r6
222 sg %r11,__KEXEC_SHA_REGION_LEN(%r7)
223 j .loop_next
224
225 .loop_out:
226
227 MEMCPY %r9,%r10,%r11
228
229
230 START_NEXT_KERNEL .base_dst
231
232
233 load_psw_mask:
234 .long 0x00080000,0x80000000
235
236 .align 8
237 disabled_wait_psw:
238 .quad 0x0002000180000000
239 .quad 0x0000000000000000 + .do_checksum_verification
240
241 gprregs:
242 .rept 10
243 .quad 0
244 .endr
245
246
247
248
249
250
251
252 .macro GLOBAL_VARIABLE name,size
253 \name:
254 .global \name
255 .size \name,\size
256 .type \name,object
257 .skip \size,0
258 .endm
259
260 GLOBAL_VARIABLE purgatory_sha256_digest,32
261 GLOBAL_VARIABLE purgatory_sha_regions,16*__KEXEC_SHA_REGION_SIZE
262 GLOBAL_VARIABLE kernel_entry,8
263 GLOBAL_VARIABLE kernel_type,8
264 GLOBAL_VARIABLE crash_start,8
265 GLOBAL_VARIABLE crash_size,8
266
267 .align PAGE_SIZE
268 stack:
269
270 .skip stack-purgatory_start
271 .align PAGE_SIZE
272 purgatory_end: