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