diff options
Diffstat (limited to 'arch/ia64/kernel/mca_asm.S')
-rw-r--r-- | arch/ia64/kernel/mca_asm.S | 928 |
1 files changed, 928 insertions, 0 deletions
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S new file mode 100644 index 000000000000..cf3f8014f9ad --- /dev/null +++ b/arch/ia64/kernel/mca_asm.S | |||
@@ -0,0 +1,928 @@ | |||
1 | // | ||
2 | // assembly portion of the IA64 MCA handling | ||
3 | // | ||
4 | // Mods by cfleck to integrate into kernel build | ||
5 | // 00/03/15 davidm Added various stop bits to get a clean compile | ||
6 | // | ||
7 | // 00/03/29 cfleck Added code to save INIT handoff state in pt_regs format, switch to temp | ||
8 | // kstack, switch modes, jump to C INIT handler | ||
9 | // | ||
10 | // 02/01/04 J.Hall <jenna.s.hall@intel.com> | ||
11 | // Before entering virtual mode code: | ||
12 | // 1. Check for TLB CPU error | ||
13 | // 2. Restore current thread pointer to kr6 | ||
14 | // 3. Move stack ptr 16 bytes to conform to C calling convention | ||
15 | // | ||
16 | // 04/11/12 Russ Anderson <rja@sgi.com> | ||
17 | // Added per cpu MCA/INIT stack save areas. | ||
18 | // | ||
19 | #include <linux/config.h> | ||
20 | #include <linux/threads.h> | ||
21 | |||
22 | #include <asm/asmmacro.h> | ||
23 | #include <asm/pgtable.h> | ||
24 | #include <asm/processor.h> | ||
25 | #include <asm/mca_asm.h> | ||
26 | #include <asm/mca.h> | ||
27 | |||
28 | /* | ||
29 | * When we get a machine check, the kernel stack pointer is no longer | ||
30 | * valid, so we need to set a new stack pointer. | ||
31 | */ | ||
32 | #define MINSTATE_PHYS /* Make sure stack access is physical for MINSTATE */ | ||
33 | |||
34 | /* | ||
35 | * Needed for return context to SAL | ||
36 | */ | ||
37 | #define IA64_MCA_SAME_CONTEXT 0 | ||
38 | #define IA64_MCA_COLD_BOOT -2 | ||
39 | |||
40 | #include "minstate.h" | ||
41 | |||
42 | /* | ||
43 | * SAL_TO_OS_MCA_HANDOFF_STATE (SAL 3.0 spec) | ||
44 | * 1. GR1 = OS GP | ||
45 | * 2. GR8 = PAL_PROC physical address | ||
46 | * 3. GR9 = SAL_PROC physical address | ||
47 | * 4. GR10 = SAL GP (physical) | ||
48 | * 5. GR11 = Rendez state | ||
49 | * 6. GR12 = Return address to location within SAL_CHECK | ||
50 | */ | ||
51 | #define SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(_tmp) \ | ||
52 | LOAD_PHYSICAL(p0, _tmp, ia64_sal_to_os_handoff_state);; \ | ||
53 | st8 [_tmp]=r1,0x08;; \ | ||
54 | st8 [_tmp]=r8,0x08;; \ | ||
55 | st8 [_tmp]=r9,0x08;; \ | ||
56 | st8 [_tmp]=r10,0x08;; \ | ||
57 | st8 [_tmp]=r11,0x08;; \ | ||
58 | st8 [_tmp]=r12,0x08;; \ | ||
59 | st8 [_tmp]=r17,0x08;; \ | ||
60 | st8 [_tmp]=r18,0x08 | ||
61 | |||
62 | /* | ||
63 | * OS_MCA_TO_SAL_HANDOFF_STATE (SAL 3.0 spec) | ||
64 | * (p6) is executed if we never entered virtual mode (TLB error) | ||
65 | * (p7) is executed if we entered virtual mode as expected (normal case) | ||
66 | * 1. GR8 = OS_MCA return status | ||
67 | * 2. GR9 = SAL GP (physical) | ||
68 | * 3. GR10 = 0/1 returning same/new context | ||
69 | * 4. GR22 = New min state save area pointer | ||
70 | * returns ptr to SAL rtn save loc in _tmp | ||
71 | */ | ||
72 | #define OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(_tmp) \ | ||
73 | movl _tmp=ia64_os_to_sal_handoff_state;; \ | ||
74 | DATA_VA_TO_PA(_tmp);; \ | ||
75 | ld8 r8=[_tmp],0x08;; \ | ||
76 | ld8 r9=[_tmp],0x08;; \ | ||
77 | ld8 r10=[_tmp],0x08;; \ | ||
78 | ld8 r22=[_tmp],0x08;; | ||
79 | // now _tmp is pointing to SAL rtn save location | ||
80 | |||
81 | /* | ||
82 | * COLD_BOOT_HANDOFF_STATE() sets ia64_mca_os_to_sal_state | ||
83 | * imots_os_status=IA64_MCA_COLD_BOOT | ||
84 | * imots_sal_gp=SAL GP | ||
85 | * imots_context=IA64_MCA_SAME_CONTEXT | ||
86 | * imots_new_min_state=Min state save area pointer | ||
87 | * imots_sal_check_ra=Return address to location within SAL_CHECK | ||
88 | * | ||
89 | */ | ||
90 | #define COLD_BOOT_HANDOFF_STATE(sal_to_os_handoff,os_to_sal_handoff,tmp)\ | ||
91 | movl tmp=IA64_MCA_COLD_BOOT; \ | ||
92 | movl sal_to_os_handoff=__pa(ia64_sal_to_os_handoff_state); \ | ||
93 | movl os_to_sal_handoff=__pa(ia64_os_to_sal_handoff_state);; \ | ||
94 | st8 [os_to_sal_handoff]=tmp,8;; \ | ||
95 | ld8 tmp=[sal_to_os_handoff],48;; \ | ||
96 | st8 [os_to_sal_handoff]=tmp,8;; \ | ||
97 | movl tmp=IA64_MCA_SAME_CONTEXT;; \ | ||
98 | st8 [os_to_sal_handoff]=tmp,8;; \ | ||
99 | ld8 tmp=[sal_to_os_handoff],-8;; \ | ||
100 | st8 [os_to_sal_handoff]=tmp,8;; \ | ||
101 | ld8 tmp=[sal_to_os_handoff];; \ | ||
102 | st8 [os_to_sal_handoff]=tmp;; | ||
103 | |||
104 | #define GET_IA64_MCA_DATA(reg) \ | ||
105 | GET_THIS_PADDR(reg, ia64_mca_data) \ | ||
106 | ;; \ | ||
107 | ld8 reg=[reg] | ||
108 | |||
109 | .global ia64_os_mca_dispatch | ||
110 | .global ia64_os_mca_dispatch_end | ||
111 | .global ia64_sal_to_os_handoff_state | ||
112 | .global ia64_os_to_sal_handoff_state | ||
113 | |||
114 | .text | ||
115 | .align 16 | ||
116 | |||
117 | ia64_os_mca_dispatch: | ||
118 | |||
119 | // Serialize all MCA processing | ||
120 | mov r3=1;; | ||
121 | LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);; | ||
122 | ia64_os_mca_spin: | ||
123 | xchg8 r4=[r2],r3;; | ||
124 | cmp.ne p6,p0=r4,r0 | ||
125 | (p6) br ia64_os_mca_spin | ||
126 | |||
127 | // Save the SAL to OS MCA handoff state as defined | ||
128 | // by SAL SPEC 3.0 | ||
129 | // NOTE : The order in which the state gets saved | ||
130 | // is dependent on the way the C-structure | ||
131 | // for ia64_mca_sal_to_os_state_t has been | ||
132 | // defined in include/asm/mca.h | ||
133 | SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2) | ||
134 | ;; | ||
135 | |||
136 | // LOG PROCESSOR STATE INFO FROM HERE ON.. | ||
137 | begin_os_mca_dump: | ||
138 | br ia64_os_mca_proc_state_dump;; | ||
139 | |||
140 | ia64_os_mca_done_dump: | ||
141 | |||
142 | LOAD_PHYSICAL(p0,r16,ia64_sal_to_os_handoff_state+56) | ||
143 | ;; | ||
144 | ld8 r18=[r16] // Get processor state parameter on existing PALE_CHECK. | ||
145 | ;; | ||
146 | tbit.nz p6,p7=r18,60 | ||
147 | (p7) br.spnt done_tlb_purge_and_reload | ||
148 | |||
149 | // The following code purges TC and TR entries. Then reload all TC entries. | ||
150 | // Purge percpu data TC entries. | ||
151 | begin_tlb_purge_and_reload: | ||
152 | |||
153 | #define O(member) IA64_CPUINFO_##member##_OFFSET | ||
154 | |||
155 | GET_THIS_PADDR(r2, cpu_info) // load phys addr of cpu_info into r2 | ||
156 | ;; | ||
157 | addl r17=O(PTCE_STRIDE),r2 | ||
158 | addl r2=O(PTCE_BASE),r2 | ||
159 | ;; | ||
160 | ld8 r18=[r2],(O(PTCE_COUNT)-O(PTCE_BASE));; // r18=ptce_base | ||
161 | ld4 r19=[r2],4 // r19=ptce_count[0] | ||
162 | ld4 r21=[r17],4 // r21=ptce_stride[0] | ||
163 | ;; | ||
164 | ld4 r20=[r2] // r20=ptce_count[1] | ||
165 | ld4 r22=[r17] // r22=ptce_stride[1] | ||
166 | mov r24=0 | ||
167 | ;; | ||
168 | adds r20=-1,r20 | ||
169 | ;; | ||
170 | #undef O | ||
171 | |||
172 | 2: | ||
173 | cmp.ltu p6,p7=r24,r19 | ||
174 | (p7) br.cond.dpnt.few 4f | ||
175 | mov ar.lc=r20 | ||
176 | 3: | ||
177 | ptc.e r18 | ||
178 | ;; | ||
179 | add r18=r22,r18 | ||
180 | br.cloop.sptk.few 3b | ||
181 | ;; | ||
182 | add r18=r21,r18 | ||
183 | add r24=1,r24 | ||
184 | ;; | ||
185 | br.sptk.few 2b | ||
186 | 4: | ||
187 | srlz.i // srlz.i implies srlz.d | ||
188 | ;; | ||
189 | |||
190 | // Now purge addresses formerly mapped by TR registers | ||
191 | // 1. Purge ITR&DTR for kernel. | ||
192 | movl r16=KERNEL_START | ||
193 | mov r18=KERNEL_TR_PAGE_SHIFT<<2 | ||
194 | ;; | ||
195 | ptr.i r16, r18 | ||
196 | ptr.d r16, r18 | ||
197 | ;; | ||
198 | srlz.i | ||
199 | ;; | ||
200 | srlz.d | ||
201 | ;; | ||
202 | // 2. Purge DTR for PERCPU data. | ||
203 | movl r16=PERCPU_ADDR | ||
204 | mov r18=PERCPU_PAGE_SHIFT<<2 | ||
205 | ;; | ||
206 | ptr.d r16,r18 | ||
207 | ;; | ||
208 | srlz.d | ||
209 | ;; | ||
210 | // 3. Purge ITR for PAL code. | ||
211 | GET_THIS_PADDR(r2, ia64_mca_pal_base) | ||
212 | ;; | ||
213 | ld8 r16=[r2] | ||
214 | mov r18=IA64_GRANULE_SHIFT<<2 | ||
215 | ;; | ||
216 | ptr.i r16,r18 | ||
217 | ;; | ||
218 | srlz.i | ||
219 | ;; | ||
220 | // 4. Purge DTR for stack. | ||
221 | mov r16=IA64_KR(CURRENT_STACK) | ||
222 | ;; | ||
223 | shl r16=r16,IA64_GRANULE_SHIFT | ||
224 | movl r19=PAGE_OFFSET | ||
225 | ;; | ||
226 | add r16=r19,r16 | ||
227 | mov r18=IA64_GRANULE_SHIFT<<2 | ||
228 | ;; | ||
229 | ptr.d r16,r18 | ||
230 | ;; | ||
231 | srlz.i | ||
232 | ;; | ||
233 | // Finally reload the TR registers. | ||
234 | // 1. Reload DTR/ITR registers for kernel. | ||
235 | mov r18=KERNEL_TR_PAGE_SHIFT<<2 | ||
236 | movl r17=KERNEL_START | ||
237 | ;; | ||
238 | mov cr.itir=r18 | ||
239 | mov cr.ifa=r17 | ||
240 | mov r16=IA64_TR_KERNEL | ||
241 | mov r19=ip | ||
242 | movl r18=PAGE_KERNEL | ||
243 | ;; | ||
244 | dep r17=0,r19,0, KERNEL_TR_PAGE_SHIFT | ||
245 | ;; | ||
246 | or r18=r17,r18 | ||
247 | ;; | ||
248 | itr.i itr[r16]=r18 | ||
249 | ;; | ||
250 | itr.d dtr[r16]=r18 | ||
251 | ;; | ||
252 | srlz.i | ||
253 | srlz.d | ||
254 | ;; | ||
255 | // 2. Reload DTR register for PERCPU data. | ||
256 | GET_THIS_PADDR(r2, ia64_mca_per_cpu_pte) | ||
257 | ;; | ||
258 | movl r16=PERCPU_ADDR // vaddr | ||
259 | movl r18=PERCPU_PAGE_SHIFT<<2 | ||
260 | ;; | ||
261 | mov cr.itir=r18 | ||
262 | mov cr.ifa=r16 | ||
263 | ;; | ||
264 | ld8 r18=[r2] // load per-CPU PTE | ||
265 | mov r16=IA64_TR_PERCPU_DATA; | ||
266 | ;; | ||
267 | itr.d dtr[r16]=r18 | ||
268 | ;; | ||
269 | srlz.d | ||
270 | ;; | ||
271 | // 3. Reload ITR for PAL code. | ||
272 | GET_THIS_PADDR(r2, ia64_mca_pal_pte) | ||
273 | ;; | ||
274 | ld8 r18=[r2] // load PAL PTE | ||
275 | ;; | ||
276 | GET_THIS_PADDR(r2, ia64_mca_pal_base) | ||
277 | ;; | ||
278 | ld8 r16=[r2] // load PAL vaddr | ||
279 | mov r19=IA64_GRANULE_SHIFT<<2 | ||
280 | ;; | ||
281 | mov cr.itir=r19 | ||
282 | mov cr.ifa=r16 | ||
283 | mov r20=IA64_TR_PALCODE | ||
284 | ;; | ||
285 | itr.i itr[r20]=r18 | ||
286 | ;; | ||
287 | srlz.i | ||
288 | ;; | ||
289 | // 4. Reload DTR for stack. | ||
290 | mov r16=IA64_KR(CURRENT_STACK) | ||
291 | ;; | ||
292 | shl r16=r16,IA64_GRANULE_SHIFT | ||
293 | movl r19=PAGE_OFFSET | ||
294 | ;; | ||
295 | add r18=r19,r16 | ||
296 | movl r20=PAGE_KERNEL | ||
297 | ;; | ||
298 | add r16=r20,r16 | ||
299 | mov r19=IA64_GRANULE_SHIFT<<2 | ||
300 | ;; | ||
301 | mov cr.itir=r19 | ||
302 | mov cr.ifa=r18 | ||
303 | mov r20=IA64_TR_CURRENT_STACK | ||
304 | ;; | ||
305 | itr.d dtr[r20]=r16 | ||
306 | ;; | ||
307 | srlz.d | ||
308 | ;; | ||
309 | br.sptk.many done_tlb_purge_and_reload | ||
310 | err: | ||
311 | COLD_BOOT_HANDOFF_STATE(r20,r21,r22) | ||
312 | br.sptk.many ia64_os_mca_done_restore | ||
313 | |||
314 | done_tlb_purge_and_reload: | ||
315 | |||
316 | // Setup new stack frame for OS_MCA handling | ||
317 | GET_IA64_MCA_DATA(r2) | ||
318 | ;; | ||
319 | add r3 = IA64_MCA_CPU_STACKFRAME_OFFSET, r2 | ||
320 | add r2 = IA64_MCA_CPU_RBSTORE_OFFSET, r2 | ||
321 | ;; | ||
322 | rse_switch_context(r6,r3,r2);; // RSC management in this new context | ||
323 | |||
324 | GET_IA64_MCA_DATA(r2) | ||
325 | ;; | ||
326 | add r2 = IA64_MCA_CPU_STACK_OFFSET+IA64_MCA_STACK_SIZE-16, r2 | ||
327 | ;; | ||
328 | mov r12=r2 // establish new stack-pointer | ||
329 | |||
330 | // Enter virtual mode from physical mode | ||
331 | VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4) | ||
332 | ia64_os_mca_virtual_begin: | ||
333 | |||
334 | // Call virtual mode handler | ||
335 | movl r2=ia64_mca_ucmc_handler;; | ||
336 | mov b6=r2;; | ||
337 | br.call.sptk.many b0=b6;; | ||
338 | .ret0: | ||
339 | // Revert back to physical mode before going back to SAL | ||
340 | PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4) | ||
341 | ia64_os_mca_virtual_end: | ||
342 | |||
343 | // restore the original stack frame here | ||
344 | GET_IA64_MCA_DATA(r2) | ||
345 | ;; | ||
346 | add r2 = IA64_MCA_CPU_STACKFRAME_OFFSET, r2 | ||
347 | ;; | ||
348 | movl r4=IA64_PSR_MC | ||
349 | ;; | ||
350 | rse_return_context(r4,r3,r2) // switch from interrupt context for RSE | ||
351 | |||
352 | // let us restore all the registers from our PSI structure | ||
353 | mov r8=gp | ||
354 | ;; | ||
355 | begin_os_mca_restore: | ||
356 | br ia64_os_mca_proc_state_restore;; | ||
357 | |||
358 | ia64_os_mca_done_restore: | ||
359 | OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(r2);; | ||
360 | // branch back to SALE_CHECK | ||
361 | ld8 r3=[r2];; | ||
362 | mov b0=r3;; // SAL_CHECK return address | ||
363 | |||
364 | // release lock | ||
365 | movl r3=ia64_mca_serialize;; | ||
366 | DATA_VA_TO_PA(r3);; | ||
367 | st8.rel [r3]=r0 | ||
368 | |||
369 | br b0 | ||
370 | ;; | ||
371 | ia64_os_mca_dispatch_end: | ||
372 | //EndMain////////////////////////////////////////////////////////////////////// | ||
373 | |||
374 | |||
375 | //++ | ||
376 | // Name: | ||
377 | // ia64_os_mca_proc_state_dump() | ||
378 | // | ||
379 | // Stub Description: | ||
380 | // | ||
381 | // This stub dumps the processor state during MCHK to a data area | ||
382 | // | ||
383 | //-- | ||
384 | |||
385 | ia64_os_mca_proc_state_dump: | ||
386 | // Save bank 1 GRs 16-31 which will be used by c-language code when we switch | ||
387 | // to virtual addressing mode. | ||
388 | GET_IA64_MCA_DATA(r2) | ||
389 | ;; | ||
390 | add r2 = IA64_MCA_CPU_PROC_STATE_DUMP_OFFSET, r2 | ||
391 | ;; | ||
392 | // save ar.NaT | ||
393 | mov r5=ar.unat // ar.unat | ||
394 | |||
395 | // save banked GRs 16-31 along with NaT bits | ||
396 | bsw.1;; | ||
397 | st8.spill [r2]=r16,8;; | ||
398 | st8.spill [r2]=r17,8;; | ||
399 | st8.spill [r2]=r18,8;; | ||
400 | st8.spill [r2]=r19,8;; | ||
401 | st8.spill [r2]=r20,8;; | ||
402 | st8.spill [r2]=r21,8;; | ||
403 | st8.spill [r2]=r22,8;; | ||
404 | st8.spill [r2]=r23,8;; | ||
405 | st8.spill [r2]=r24,8;; | ||
406 | st8.spill [r2]=r25,8;; | ||
407 | st8.spill [r2]=r26,8;; | ||
408 | st8.spill [r2]=r27,8;; | ||
409 | st8.spill [r2]=r28,8;; | ||
410 | st8.spill [r2]=r29,8;; | ||
411 | st8.spill [r2]=r30,8;; | ||
412 | st8.spill [r2]=r31,8;; | ||
413 | |||
414 | mov r4=ar.unat;; | ||
415 | st8 [r2]=r4,8 // save User NaT bits for r16-r31 | ||
416 | mov ar.unat=r5 // restore original unat | ||
417 | bsw.0;; | ||
418 | |||
419 | //save BRs | ||
420 | add r4=8,r2 // duplicate r2 in r4 | ||
421 | add r6=2*8,r2 // duplicate r2 in r4 | ||
422 | |||
423 | mov r3=b0 | ||
424 | mov r5=b1 | ||
425 | mov r7=b2;; | ||
426 | st8 [r2]=r3,3*8 | ||
427 | st8 [r4]=r5,3*8 | ||
428 | st8 [r6]=r7,3*8;; | ||
429 | |||
430 | mov r3=b3 | ||
431 | mov r5=b4 | ||
432 | mov r7=b5;; | ||
433 | st8 [r2]=r3,3*8 | ||
434 | st8 [r4]=r5,3*8 | ||
435 | st8 [r6]=r7,3*8;; | ||
436 | |||
437 | mov r3=b6 | ||
438 | mov r5=b7;; | ||
439 | st8 [r2]=r3,2*8 | ||
440 | st8 [r4]=r5,2*8;; | ||
441 | |||
442 | cSaveCRs: | ||
443 | // save CRs | ||
444 | add r4=8,r2 // duplicate r2 in r4 | ||
445 | add r6=2*8,r2 // duplicate r2 in r4 | ||
446 | |||
447 | mov r3=cr.dcr | ||
448 | mov r5=cr.itm | ||
449 | mov r7=cr.iva;; | ||
450 | |||
451 | st8 [r2]=r3,8*8 | ||
452 | st8 [r4]=r5,3*8 | ||
453 | st8 [r6]=r7,3*8;; // 48 byte rements | ||
454 | |||
455 | mov r3=cr.pta;; | ||
456 | st8 [r2]=r3,8*8;; // 64 byte rements | ||
457 | |||
458 | // if PSR.ic=0, reading interruption registers causes an illegal operation fault | ||
459 | mov r3=psr;; | ||
460 | tbit.nz.unc p6,p0=r3,PSR_IC;; // PSI Valid Log bit pos. test | ||
461 | (p6) st8 [r2]=r0,9*8+160 // increment by 232 byte inc. | ||
462 | begin_skip_intr_regs: | ||
463 | (p6) br SkipIntrRegs;; | ||
464 | |||
465 | add r4=8,r2 // duplicate r2 in r4 | ||
466 | add r6=2*8,r2 // duplicate r2 in r6 | ||
467 | |||
468 | mov r3=cr.ipsr | ||
469 | mov r5=cr.isr | ||
470 | mov r7=r0;; | ||
471 | st8 [r2]=r3,3*8 | ||
472 | st8 [r4]=r5,3*8 | ||
473 | st8 [r6]=r7,3*8;; | ||
474 | |||
475 | mov r3=cr.iip | ||
476 | mov r5=cr.ifa | ||
477 | mov r7=cr.itir;; | ||
478 | st8 [r2]=r3,3*8 | ||
479 | st8 [r4]=r5,3*8 | ||
480 | st8 [r6]=r7,3*8;; | ||
481 | |||
482 | mov r3=cr.iipa | ||
483 | mov r5=cr.ifs | ||
484 | mov r7=cr.iim;; | ||
485 | st8 [r2]=r3,3*8 | ||
486 | st8 [r4]=r5,3*8 | ||
487 | st8 [r6]=r7,3*8;; | ||
488 | |||
489 | mov r3=cr25;; // cr.iha | ||
490 | st8 [r2]=r3,160;; // 160 byte rement | ||
491 | |||
492 | SkipIntrRegs: | ||
493 | st8 [r2]=r0,152;; // another 152 byte . | ||
494 | |||
495 | add r4=8,r2 // duplicate r2 in r4 | ||
496 | add r6=2*8,r2 // duplicate r2 in r6 | ||
497 | |||
498 | mov r3=cr.lid | ||
499 | // mov r5=cr.ivr // cr.ivr, don't read it | ||
500 | mov r7=cr.tpr;; | ||
501 | st8 [r2]=r3,3*8 | ||
502 | st8 [r4]=r5,3*8 | ||
503 | st8 [r6]=r7,3*8;; | ||
504 | |||
505 | mov r3=r0 // cr.eoi => cr67 | ||
506 | mov r5=r0 // cr.irr0 => cr68 | ||
507 | mov r7=r0;; // cr.irr1 => cr69 | ||
508 | st8 [r2]=r3,3*8 | ||
509 | st8 [r4]=r5,3*8 | ||
510 | st8 [r6]=r7,3*8;; | ||
511 | |||
512 | mov r3=r0 // cr.irr2 => cr70 | ||
513 | mov r5=r0 // cr.irr3 => cr71 | ||
514 | mov r7=cr.itv;; | ||
515 | st8 [r2]=r3,3*8 | ||
516 | st8 [r4]=r5,3*8 | ||
517 | st8 [r6]=r7,3*8;; | ||
518 | |||
519 | mov r3=cr.pmv | ||
520 | mov r5=cr.cmcv;; | ||
521 | st8 [r2]=r3,7*8 | ||
522 | st8 [r4]=r5,7*8;; | ||
523 | |||
524 | mov r3=r0 // cr.lrr0 => cr80 | ||
525 | mov r5=r0;; // cr.lrr1 => cr81 | ||
526 | st8 [r2]=r3,23*8 | ||
527 | st8 [r4]=r5,23*8;; | ||
528 | |||
529 | adds r2=25*8,r2;; | ||
530 | |||
531 | cSaveARs: | ||
532 | // save ARs | ||
533 | add r4=8,r2 // duplicate r2 in r4 | ||
534 | add r6=2*8,r2 // duplicate r2 in r6 | ||
535 | |||
536 | mov r3=ar.k0 | ||
537 | mov r5=ar.k1 | ||
538 | mov r7=ar.k2;; | ||
539 | st8 [r2]=r3,3*8 | ||
540 | st8 [r4]=r5,3*8 | ||
541 | st8 [r6]=r7,3*8;; | ||
542 | |||
543 | mov r3=ar.k3 | ||
544 | mov r5=ar.k4 | ||
545 | mov r7=ar.k5;; | ||
546 | st8 [r2]=r3,3*8 | ||
547 | st8 [r4]=r5,3*8 | ||
548 | st8 [r6]=r7,3*8;; | ||
549 | |||
550 | mov r3=ar.k6 | ||
551 | mov r5=ar.k7 | ||
552 | mov r7=r0;; // ar.kr8 | ||
553 | st8 [r2]=r3,10*8 | ||
554 | st8 [r4]=r5,10*8 | ||
555 | st8 [r6]=r7,10*8;; // rement by 72 bytes | ||
556 | |||
557 | mov r3=ar.rsc | ||
558 | mov ar.rsc=r0 // put RSE in enforced lazy mode | ||
559 | mov r5=ar.bsp | ||
560 | ;; | ||
561 | mov r7=ar.bspstore;; | ||
562 | st8 [r2]=r3,3*8 | ||
563 | st8 [r4]=r5,3*8 | ||
564 | st8 [r6]=r7,3*8;; | ||
565 | |||
566 | mov r3=ar.rnat;; | ||
567 | st8 [r2]=r3,8*13 // increment by 13x8 bytes | ||
568 | |||
569 | mov r3=ar.ccv;; | ||
570 | st8 [r2]=r3,8*4 | ||
571 | |||
572 | mov r3=ar.unat;; | ||
573 | st8 [r2]=r3,8*4 | ||
574 | |||
575 | mov r3=ar.fpsr;; | ||
576 | st8 [r2]=r3,8*4 | ||
577 | |||
578 | mov r3=ar.itc;; | ||
579 | st8 [r2]=r3,160 // 160 | ||
580 | |||
581 | mov r3=ar.pfs;; | ||
582 | st8 [r2]=r3,8 | ||
583 | |||
584 | mov r3=ar.lc;; | ||
585 | st8 [r2]=r3,8 | ||
586 | |||
587 | mov r3=ar.ec;; | ||
588 | st8 [r2]=r3 | ||
589 | add r2=8*62,r2 //padding | ||
590 | |||
591 | // save RRs | ||
592 | mov ar.lc=0x08-1 | ||
593 | movl r4=0x00;; | ||
594 | |||
595 | cStRR: | ||
596 | dep.z r5=r4,61,3;; | ||
597 | mov r3=rr[r5];; | ||
598 | st8 [r2]=r3,8 | ||
599 | add r4=1,r4 | ||
600 | br.cloop.sptk.few cStRR | ||
601 | ;; | ||
602 | end_os_mca_dump: | ||
603 | br ia64_os_mca_done_dump;; | ||
604 | |||
605 | //EndStub////////////////////////////////////////////////////////////////////// | ||
606 | |||
607 | |||
608 | //++ | ||
609 | // Name: | ||
610 | // ia64_os_mca_proc_state_restore() | ||
611 | // | ||
612 | // Stub Description: | ||
613 | // | ||
614 | // This is a stub to restore the saved processor state during MCHK | ||
615 | // | ||
616 | //-- | ||
617 | |||
618 | ia64_os_mca_proc_state_restore: | ||
619 | |||
620 | // Restore bank1 GR16-31 | ||
621 | GET_IA64_MCA_DATA(r2) | ||
622 | ;; | ||
623 | add r2 = IA64_MCA_CPU_PROC_STATE_DUMP_OFFSET, r2 | ||
624 | |||
625 | restore_GRs: // restore bank-1 GRs 16-31 | ||
626 | bsw.1;; | ||
627 | add r3=16*8,r2;; // to get to NaT of GR 16-31 | ||
628 | ld8 r3=[r3];; | ||
629 | mov ar.unat=r3;; // first restore NaT | ||
630 | |||
631 | ld8.fill r16=[r2],8;; | ||
632 | ld8.fill r17=[r2],8;; | ||
633 | ld8.fill r18=[r2],8;; | ||
634 | ld8.fill r19=[r2],8;; | ||
635 | ld8.fill r20=[r2],8;; | ||
636 | ld8.fill r21=[r2],8;; | ||
637 | ld8.fill r22=[r2],8;; | ||
638 | ld8.fill r23=[r2],8;; | ||
639 | ld8.fill r24=[r2],8;; | ||
640 | ld8.fill r25=[r2],8;; | ||
641 | ld8.fill r26=[r2],8;; | ||
642 | ld8.fill r27=[r2],8;; | ||
643 | ld8.fill r28=[r2],8;; | ||
644 | ld8.fill r29=[r2],8;; | ||
645 | ld8.fill r30=[r2],8;; | ||
646 | ld8.fill r31=[r2],8;; | ||
647 | |||
648 | ld8 r3=[r2],8;; // increment to skip NaT | ||
649 | bsw.0;; | ||
650 | |||
651 | restore_BRs: | ||
652 | add r4=8,r2 // duplicate r2 in r4 | ||
653 | add r6=2*8,r2;; // duplicate r2 in r4 | ||
654 | |||
655 | ld8 r3=[r2],3*8 | ||
656 | ld8 r5=[r4],3*8 | ||
657 | ld8 r7=[r6],3*8;; | ||
658 | mov b0=r3 | ||
659 | mov b1=r5 | ||
660 | mov b2=r7;; | ||
661 | |||
662 | ld8 r3=[r2],3*8 | ||
663 | ld8 r5=[r4],3*8 | ||
664 | ld8 r7=[r6],3*8;; | ||
665 | mov b3=r3 | ||
666 | mov b4=r5 | ||
667 | mov b5=r7;; | ||
668 | |||
669 | ld8 r3=[r2],2*8 | ||
670 | ld8 r5=[r4],2*8;; | ||
671 | mov b6=r3 | ||
672 | mov b7=r5;; | ||
673 | |||
674 | restore_CRs: | ||
675 | add r4=8,r2 // duplicate r2 in r4 | ||
676 | add r6=2*8,r2;; // duplicate r2 in r4 | ||
677 | |||
678 | ld8 r3=[r2],8*8 | ||
679 | ld8 r5=[r4],3*8 | ||
680 | ld8 r7=[r6],3*8;; // 48 byte increments | ||
681 | mov cr.dcr=r3 | ||
682 | mov cr.itm=r5 | ||
683 | mov cr.iva=r7;; | ||
684 | |||
685 | ld8 r3=[r2],8*8;; // 64 byte increments | ||
686 | // mov cr.pta=r3 | ||
687 | |||
688 | |||
689 | // if PSR.ic=1, reading interruption registers causes an illegal operation fault | ||
690 | mov r3=psr;; | ||
691 | tbit.nz.unc p6,p0=r3,PSR_IC;; // PSI Valid Log bit pos. test | ||
692 | (p6) st8 [r2]=r0,9*8+160 // increment by 232 byte inc. | ||
693 | |||
694 | begin_rskip_intr_regs: | ||
695 | (p6) br rSkipIntrRegs;; | ||
696 | |||
697 | add r4=8,r2 // duplicate r2 in r4 | ||
698 | add r6=2*8,r2;; // duplicate r2 in r4 | ||
699 | |||
700 | ld8 r3=[r2],3*8 | ||
701 | ld8 r5=[r4],3*8 | ||
702 | ld8 r7=[r6],3*8;; | ||
703 | mov cr.ipsr=r3 | ||
704 | // mov cr.isr=r5 // cr.isr is read only | ||
705 | |||
706 | ld8 r3=[r2],3*8 | ||
707 | ld8 r5=[r4],3*8 | ||
708 | ld8 r7=[r6],3*8;; | ||
709 | mov cr.iip=r3 | ||
710 | mov cr.ifa=r5 | ||
711 | mov cr.itir=r7;; | ||
712 | |||
713 | ld8 r3=[r2],3*8 | ||
714 | ld8 r5=[r4],3*8 | ||
715 | ld8 r7=[r6],3*8;; | ||
716 | mov cr.iipa=r3 | ||
717 | mov cr.ifs=r5 | ||
718 | mov cr.iim=r7 | ||
719 | |||
720 | ld8 r3=[r2],160;; // 160 byte increment | ||
721 | mov cr.iha=r3 | ||
722 | |||
723 | rSkipIntrRegs: | ||
724 | ld8 r3=[r2],152;; // another 152 byte inc. | ||
725 | |||
726 | add r4=8,r2 // duplicate r2 in r4 | ||
727 | add r6=2*8,r2;; // duplicate r2 in r6 | ||
728 | |||
729 | ld8 r3=[r2],8*3 | ||
730 | ld8 r5=[r4],8*3 | ||
731 | ld8 r7=[r6],8*3;; | ||
732 | mov cr.lid=r3 | ||
733 | // mov cr.ivr=r5 // cr.ivr is read only | ||
734 | mov cr.tpr=r7;; | ||
735 | |||
736 | ld8 r3=[r2],8*3 | ||
737 | ld8 r5=[r4],8*3 | ||
738 | ld8 r7=[r6],8*3;; | ||
739 | // mov cr.eoi=r3 | ||
740 | // mov cr.irr0=r5 // cr.irr0 is read only | ||
741 | // mov cr.irr1=r7;; // cr.irr1 is read only | ||
742 | |||
743 | ld8 r3=[r2],8*3 | ||
744 | ld8 r5=[r4],8*3 | ||
745 | ld8 r7=[r6],8*3;; | ||
746 | // mov cr.irr2=r3 // cr.irr2 is read only | ||
747 | // mov cr.irr3=r5 // cr.irr3 is read only | ||
748 | mov cr.itv=r7;; | ||
749 | |||
750 | ld8 r3=[r2],8*7 | ||
751 | ld8 r5=[r4],8*7;; | ||
752 | mov cr.pmv=r3 | ||
753 | mov cr.cmcv=r5;; | ||
754 | |||
755 | ld8 r3=[r2],8*23 | ||
756 | ld8 r5=[r4],8*23;; | ||
757 | adds r2=8*23,r2 | ||
758 | adds r4=8*23,r4;; | ||
759 | // mov cr.lrr0=r3 | ||
760 | // mov cr.lrr1=r5 | ||
761 | |||
762 | adds r2=8*2,r2;; | ||
763 | |||
764 | restore_ARs: | ||
765 | add r4=8,r2 // duplicate r2 in r4 | ||
766 | add r6=2*8,r2;; // duplicate r2 in r4 | ||
767 | |||
768 | ld8 r3=[r2],3*8 | ||
769 | ld8 r5=[r4],3*8 | ||
770 | ld8 r7=[r6],3*8;; | ||
771 | mov ar.k0=r3 | ||
772 | mov ar.k1=r5 | ||
773 | mov ar.k2=r7;; | ||
774 | |||
775 | ld8 r3=[r2],3*8 | ||
776 | ld8 r5=[r4],3*8 | ||
777 | ld8 r7=[r6],3*8;; | ||
778 | mov ar.k3=r3 | ||
779 | mov ar.k4=r5 | ||
780 | mov ar.k5=r7;; | ||
781 | |||
782 | ld8 r3=[r2],10*8 | ||
783 | ld8 r5=[r4],10*8 | ||
784 | ld8 r7=[r6],10*8;; | ||
785 | mov ar.k6=r3 | ||
786 | mov ar.k7=r5 | ||
787 | ;; | ||
788 | |||
789 | ld8 r3=[r2],3*8 | ||
790 | ld8 r5=[r4],3*8 | ||
791 | ld8 r7=[r6],3*8;; | ||
792 | // mov ar.rsc=r3 | ||
793 | // mov ar.bsp=r5 // ar.bsp is read only | ||
794 | mov ar.rsc=r0 // make sure that RSE is in enforced lazy mode | ||
795 | ;; | ||
796 | mov ar.bspstore=r7;; | ||
797 | |||
798 | ld8 r9=[r2],8*13;; | ||
799 | mov ar.rnat=r9 | ||
800 | |||
801 | mov ar.rsc=r3 | ||
802 | ld8 r3=[r2],8*4;; | ||
803 | mov ar.ccv=r3 | ||
804 | |||
805 | ld8 r3=[r2],8*4;; | ||
806 | mov ar.unat=r3 | ||
807 | |||
808 | ld8 r3=[r2],8*4;; | ||
809 | mov ar.fpsr=r3 | ||
810 | |||
811 | ld8 r3=[r2],160;; // 160 | ||
812 | // mov ar.itc=r3 | ||
813 | |||
814 | ld8 r3=[r2],8;; | ||
815 | mov ar.pfs=r3 | ||
816 | |||
817 | ld8 r3=[r2],8;; | ||
818 | mov ar.lc=r3 | ||
819 | |||
820 | ld8 r3=[r2];; | ||
821 | mov ar.ec=r3 | ||
822 | add r2=8*62,r2;; // padding | ||
823 | |||
824 | restore_RRs: | ||
825 | mov r5=ar.lc | ||
826 | mov ar.lc=0x08-1 | ||
827 | movl r4=0x00;; | ||
828 | cStRRr: | ||
829 | dep.z r7=r4,61,3 | ||
830 | ld8 r3=[r2],8;; | ||
831 | mov rr[r7]=r3 // what are its access previledges? | ||
832 | add r4=1,r4 | ||
833 | br.cloop.sptk.few cStRRr | ||
834 | ;; | ||
835 | mov ar.lc=r5 | ||
836 | ;; | ||
837 | end_os_mca_restore: | ||
838 | br ia64_os_mca_done_restore;; | ||
839 | |||
840 | //EndStub////////////////////////////////////////////////////////////////////// | ||
841 | |||
842 | |||
843 | // ok, the issue here is that we need to save state information so | ||
844 | // it can be useable by the kernel debugger and show regs routines. | ||
845 | // In order to do this, our best bet is save the current state (plus | ||
846 | // the state information obtain from the MIN_STATE_AREA) into a pt_regs | ||
847 | // format. This way we can pass it on in a useable format. | ||
848 | // | ||
849 | |||
850 | // | ||
851 | // SAL to OS entry point for INIT on the monarch processor | ||
852 | // This has been defined for registration purposes with SAL | ||
853 | // as a part of ia64_mca_init. | ||
854 | // | ||
855 | // When we get here, the following registers have been | ||
856 | // set by the SAL for our use | ||
857 | // | ||
858 | // 1. GR1 = OS INIT GP | ||
859 | // 2. GR8 = PAL_PROC physical address | ||
860 | // 3. GR9 = SAL_PROC physical address | ||
861 | // 4. GR10 = SAL GP (physical) | ||
862 | // 5. GR11 = Init Reason | ||
863 | // 0 = Received INIT for event other than crash dump switch | ||
864 | // 1 = Received wakeup at the end of an OS_MCA corrected machine check | ||
865 | // 2 = Received INIT dude to CrashDump switch assertion | ||
866 | // | ||
867 | // 6. GR12 = Return address to location within SAL_INIT procedure | ||
868 | |||
869 | |||
870 | GLOBAL_ENTRY(ia64_monarch_init_handler) | ||
871 | .prologue | ||
872 | // stash the information the SAL passed to os | ||
873 | SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2) | ||
874 | ;; | ||
875 | SAVE_MIN_WITH_COVER | ||
876 | ;; | ||
877 | mov r8=cr.ifa | ||
878 | mov r9=cr.isr | ||
879 | adds r3=8,r2 // set up second base pointer | ||
880 | ;; | ||
881 | SAVE_REST | ||
882 | |||
883 | // ok, enough should be saved at this point to be dangerous, and supply | ||
884 | // information for a dump | ||
885 | // We need to switch to Virtual mode before hitting the C functions. | ||
886 | |||
887 | movl r2=IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN | ||
888 | mov r3=psr // get the current psr, minimum enabled at this point | ||
889 | ;; | ||
890 | or r2=r2,r3 | ||
891 | ;; | ||
892 | movl r3=IVirtual_Switch | ||
893 | ;; | ||
894 | mov cr.iip=r3 // short return to set the appropriate bits | ||
895 | mov cr.ipsr=r2 // need to do an rfi to set appropriate bits | ||
896 | ;; | ||
897 | rfi | ||
898 | ;; | ||
899 | IVirtual_Switch: | ||
900 | // | ||
901 | // We should now be running virtual | ||
902 | // | ||
903 | // Let's call the C handler to get the rest of the state info | ||
904 | // | ||
905 | alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!) | ||
906 | ;; | ||
907 | adds out0=16,sp // out0 = pointer to pt_regs | ||
908 | ;; | ||
909 | DO_SAVE_SWITCH_STACK | ||
910 | .body | ||
911 | adds out1=16,sp // out0 = pointer to switch_stack | ||
912 | |||
913 | br.call.sptk.many rp=ia64_init_handler | ||
914 | .ret1: | ||
915 | |||
916 | return_from_init: | ||
917 | br.sptk return_from_init | ||
918 | END(ia64_monarch_init_handler) | ||
919 | |||
920 | // | ||
921 | // SAL to OS entry point for INIT on the slave processor | ||
922 | // This has been defined for registration purposes with SAL | ||
923 | // as a part of ia64_mca_init. | ||
924 | // | ||
925 | |||
926 | GLOBAL_ENTRY(ia64_slave_init_handler) | ||
927 | 1: br.sptk 1b | ||
928 | END(ia64_slave_init_handler) | ||