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 00000000000..cf3f8014f9a --- /dev/null +++ b/arch/ia64/kernel/mca_asm.S @@ -0,0 +1,928 @@ +// +// assembly portion of the IA64 MCA handling +// +// Mods by cfleck to integrate into kernel build +// 00/03/15 davidm Added various stop bits to get a clean compile +// +// 00/03/29 cfleck Added code to save INIT handoff state in pt_regs format, switch to temp +// kstack, switch modes, jump to C INIT handler +// +// 02/01/04 J.Hall <jenna.s.hall@intel.com> +// Before entering virtual mode code: +// 1. Check for TLB CPU error +// 2. Restore current thread pointer to kr6 +// 3. Move stack ptr 16 bytes to conform to C calling convention +// +// 04/11/12 Russ Anderson <rja@sgi.com> +// Added per cpu MCA/INIT stack save areas. +// +#include <linux/config.h> +#include <linux/threads.h> + +#include <asm/asmmacro.h> +#include <asm/pgtable.h> +#include <asm/processor.h> +#include <asm/mca_asm.h> +#include <asm/mca.h> + +/* + * When we get a machine check, the kernel stack pointer is no longer + * valid, so we need to set a new stack pointer. + */ +#define MINSTATE_PHYS /* Make sure stack access is physical for MINSTATE */ + +/* + * Needed for return context to SAL + */ +#define IA64_MCA_SAME_CONTEXT 0 +#define IA64_MCA_COLD_BOOT -2 + +#include "minstate.h" + +/* + * SAL_TO_OS_MCA_HANDOFF_STATE (SAL 3.0 spec) + * 1. GR1 = OS GP + * 2. GR8 = PAL_PROC physical address + * 3. GR9 = SAL_PROC physical address + * 4. GR10 = SAL GP (physical) + * 5. GR11 = Rendez state + * 6. GR12 = Return address to location within SAL_CHECK + */ +#define SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(_tmp) \ + LOAD_PHYSICAL(p0, _tmp, ia64_sal_to_os_handoff_state);; \ + st8 [_tmp]=r1,0x08;; \ + st8 [_tmp]=r8,0x08;; \ + st8 [_tmp]=r9,0x08;; \ + st8 [_tmp]=r10,0x08;; \ + st8 [_tmp]=r11,0x08;; \ + st8 [_tmp]=r12,0x08;; \ + st8 [_tmp]=r17,0x08;; \ + st8 [_tmp]=r18,0x08 + +/* + * OS_MCA_TO_SAL_HANDOFF_STATE (SAL 3.0 spec) + * (p6) is executed if we never entered virtual mode (TLB error) + * (p7) is executed if we entered virtual mode as expected (normal case) + * 1. GR8 = OS_MCA return status + * 2. GR9 = SAL GP (physical) + * 3. GR10 = 0/1 returning same/new context + * 4. GR22 = New min state save area pointer + * returns ptr to SAL rtn save loc in _tmp + */ +#define OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(_tmp) \ + movl _tmp=ia64_os_to_sal_handoff_state;; \ + DATA_VA_TO_PA(_tmp);; \ + ld8 r8=[_tmp],0x08;; \ + ld8 r9=[_tmp],0x08;; \ + ld8 r10=[_tmp],0x08;; \ + ld8 r22=[_tmp],0x08;; + // now _tmp is pointing to SAL rtn save location + +/* + * COLD_BOOT_HANDOFF_STATE() sets ia64_mca_os_to_sal_state + * imots_os_status=IA64_MCA_COLD_BOOT + * imots_sal_gp=SAL GP + * imots_context=IA64_MCA_SAME_CONTEXT + * imots_new_min_state=Min state save area pointer + * imots_sal_check_ra=Return address to location within SAL_CHECK + * + */ +#define COLD_BOOT_HANDOFF_STATE(sal_to_os_handoff,os_to_sal_handoff,tmp)\ + movl tmp=IA64_MCA_COLD_BOOT; \ + movl sal_to_os_handoff=__pa(ia64_sal_to_os_handoff_state); \ + movl os_to_sal_handoff=__pa(ia64_os_to_sal_handoff_state);; \ + st8 [os_to_sal_handoff]=tmp,8;; \ + ld8 tmp=[sal_to_os_handoff],48;; \ + st8 [os_to_sal_handoff]=tmp,8;; \ + movl tmp=IA64_MCA_SAME_CONTEXT;; \ + st8 [os_to_sal_handoff]=tmp,8;; \ + ld8 tmp=[sal_to_os_handoff],-8;; \ + st8 [os_to_sal_handoff]=tmp,8;; \ + ld8 tmp=[sal_to_os_handoff];; \ + st8 [os_to_sal_handoff]=tmp;; + +#define GET_IA64_MCA_DATA(reg) \ + GET_THIS_PADDR(reg, ia64_mca_data) \ + ;; \ + ld8 reg=[reg] + + .global ia64_os_mca_dispatch + .global ia64_os_mca_dispatch_end + .global ia64_sal_to_os_handoff_state + .global ia64_os_to_sal_handoff_state + + .text + .align 16 + +ia64_os_mca_dispatch: + + // Serialize all MCA processing + mov r3=1;; + LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);; +ia64_os_mca_spin: + xchg8 r4=[r2],r3;; + cmp.ne p6,p0=r4,r0 +(p6) br ia64_os_mca_spin + + // Save the SAL to OS MCA handoff state as defined + // by SAL SPEC 3.0 + // NOTE : The order in which the state gets saved + // is dependent on the way the C-structure + // for ia64_mca_sal_to_os_state_t has been + // defined in include/asm/mca.h + SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2) + ;; + + // LOG PROCESSOR STATE INFO FROM HERE ON.. +begin_os_mca_dump: + br ia64_os_mca_proc_state_dump;; + +ia64_os_mca_done_dump: + + LOAD_PHYSICAL(p0,r16,ia64_sal_to_os_handoff_state+56) + ;; + ld8 r18=[r16] // Get processor state parameter on existing PALE_CHECK. + ;; + tbit.nz p6,p7=r18,60 +(p7) br.spnt done_tlb_purge_and_reload + + // The following code purges TC and TR entries. Then reload all TC entries. + // Purge percpu data TC entries. +begin_tlb_purge_and_reload: + +#define O(member) IA64_CPUINFO_##member##_OFFSET + + GET_THIS_PADDR(r2, cpu_info) // load phys addr of cpu_info into r2 + ;; + addl r17=O(PTCE_STRIDE),r2 + addl r2=O(PTCE_BASE),r2 + ;; + ld8 r18=[r2],(O(PTCE_COUNT)-O(PTCE_BASE));; // r18=ptce_base + ld4 r19=[r2],4 // r19=ptce_count[0] + ld4 r21=[r17],4 // r21=ptce_stride[0] + ;; + ld4 r20=[r2] // r20=ptce_count[1] + ld4 r22=[r17] // r22=ptce_stride[1] + mov r24=0 + ;; + adds r20=-1,r20 + ;; +#undef O + +2: + cmp.ltu p6,p7=r24,r19 +(p7) br.cond.dpnt.few 4f + mov ar.lc=r20 +3: + ptc.e r18 + ;; + add r18=r22,r18 + br.cloop.sptk.few 3b + ;; + add r18=r21,r18 + add r24=1,r24 + ;; + br.sptk.few 2b +4: + srlz.i // srlz.i implies srlz.d + ;; + + // Now purge addresses formerly mapped by TR registers + // 1. Purge ITR&DTR for kernel. + movl r16=KERNEL_START + mov r18=KERNEL_TR_PAGE_SHIFT<<2 + ;; + ptr.i r16, r18 + ptr.d r16, r18 + ;; + srlz.i + ;; + srlz.d + ;; + // 2. Purge DTR for PERCPU data. + movl r16=PERCPU_ADDR + mov r18=PERCPU_PAGE_SHIFT<<2 + ;; + ptr.d r16,r18 + ;; + srlz.d + ;; + // 3. Purge ITR for PAL code. + GET_THIS_PADDR(r2, ia64_mca_pal_base) + ;; + ld8 r16=[r2] + mov r18=IA64_GRANULE_SHIFT<<2 + ;; + ptr.i r16,r18 + ;; + srlz.i + ;; + // 4. Purge DTR for stack. + mov r16=IA64_KR(CURRENT_STACK) + ;; + shl r16=r16,IA64_GRANULE_SHIFT + movl r19=PAGE_OFFSET + ;; + add r16=r19,r16 + mov r18=IA64_GRANULE_SHIFT<<2 + ;; + ptr.d r16,r18 + ;; + srlz.i + ;; + // Finally reload the TR registers. + // 1. Reload DTR/ITR registers for kernel. + mov r18=KERNEL_TR_PAGE_SHIFT<<2 + movl r17=KERNEL_START + ;; + mov cr.itir=r18 + mov cr.ifa=r17 + mov r16=IA64_TR_KERNEL + mov r19=ip + movl r18=PAGE_KERNEL + ;; + dep r17=0,r19,0, KERNEL_TR_PAGE_SHIFT + ;; + or r18=r17,r18 + ;; + itr.i itr[r16]=r18 + ;; + itr.d dtr[r16]=r18 + ;; + srlz.i + srlz.d + ;; + // 2. Reload DTR register for PERCPU data. + GET_THIS_PADDR(r2, ia64_mca_per_cpu_pte) + ;; + movl r16=PERCPU_ADDR // vaddr + movl r18=PERCPU_PAGE_SHIFT<<2 + ;; + mov cr.itir=r18 + mov cr.ifa=r16 + ;; + ld8 r18=[r2] // load per-CPU PTE + mov r16=IA64_TR_PERCPU_DATA; + ;; + itr.d dtr[r16]=r18 + ;; + srlz.d + ;; + // 3. Reload ITR for PAL code. + GET_THIS_PADDR(r2, ia64_mca_pal_pte) + ;; + ld8 r18=[r2] // load PAL PTE + ;; + GET_THIS_PADDR(r2, ia64_mca_pal_base) + ;; + ld8 r16=[r2] // load PAL vaddr + mov r19=IA64_GRANULE_SHIFT<<2 + ;; + mov cr.itir=r19 + mov cr.ifa=r16 + mov r20=IA64_TR_PALCODE + ;; + itr.i itr[r20]=r18 + ;; + srlz.i + ;; + // 4. Reload DTR for stack. + mov r16=IA64_KR(CURRENT_STACK) + ;; + shl r16=r16,IA64_GRANULE_SHIFT + movl r19=PAGE_OFFSET + ;; + add r18=r19,r16 + movl r20=PAGE_KERNEL + ;; + add r16=r20,r16 + mov r19=IA64_GRANULE_SHIFT<<2 + ;; + mov cr.itir=r19 + mov cr.ifa=r18 + mov r20=IA64_TR_CURRENT_STACK + ;; + itr.d dtr[r20]=r16 + ;; + srlz.d + ;; + br.sptk.many done_tlb_purge_and_reload +err: + COLD_BOOT_HANDOFF_STATE(r20,r21,r22) + br.sptk.many ia64_os_mca_done_restore + +done_tlb_purge_and_reload: + + // Setup new stack frame for OS_MCA handling + GET_IA64_MCA_DATA(r2) + ;; + add r3 = IA64_MCA_CPU_STACKFRAME_OFFSET, r2 + add r2 = IA64_MCA_CPU_RBSTORE_OFFSET, r2 + ;; + rse_switch_context(r6,r3,r2);; // RSC management in this new context + + GET_IA64_MCA_DATA(r2) + ;; + add r2 = IA64_MCA_CPU_STACK_OFFSET+IA64_MCA_STACK_SIZE-16, r2 + ;; + mov r12=r2 // establish new stack-pointer + + // Enter virtual mode from physical mode + VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4) +ia64_os_mca_virtual_begin: + + // Call virtual mode handler + movl r2=ia64_mca_ucmc_handler;; + mov b6=r2;; + br.call.sptk.many b0=b6;; +.ret0: + // Revert back to physical mode before going back to SAL + PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4) +ia64_os_mca_virtual_end: + + // restore the original stack frame here + GET_IA64_MCA_DATA(r2) + ;; + add r2 = IA64_MCA_CPU_STACKFRAME_OFFSET, r2 + ;; + movl r4=IA64_PSR_MC + ;; + rse_return_context(r4,r3,r2) // switch from interrupt context for RSE + + // let us restore all the registers from our PSI structure + mov r8=gp + ;; +begin_os_mca_restore: + br ia64_os_mca_proc_state_restore;; + +ia64_os_mca_done_restore: + OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(r2);; + // branch back to SALE_CHECK + ld8 r3=[r2];; + mov b0=r3;; // SAL_CHECK return address + + // release lock + movl r3=ia64_mca_serialize;; + DATA_VA_TO_PA(r3);; + st8.rel [r3]=r0 + + br b0 + ;; +ia64_os_mca_dispatch_end: +//EndMain////////////////////////////////////////////////////////////////////// + + +//++ +// Name: +// ia64_os_mca_proc_state_dump() +// +// Stub Description: +// +// This stub dumps the processor state during MCHK to a data area +// +//-- + +ia64_os_mca_proc_state_dump: +// Save bank 1 GRs 16-31 which will be used by c-language code when we switch +// to virtual addressing mode. + GET_IA64_MCA_DATA(r2) + ;; + add r2 = IA64_MCA_CPU_PROC_STATE_DUMP_OFFSET, r2 + ;; +// save ar.NaT + mov r5=ar.unat // ar.unat + +// save banked GRs 16-31 along with NaT bits + bsw.1;; + st8.spill [r2]=r16,8;; + st8.spill [r2]=r17,8;; + st8.spill [r2]=r18,8;; + st8.spill [r2]=r19,8;; + st8.spill [r2]=r20,8;; + st8.spill [r2]=r21,8;; + st8.spill [r2]=r22,8;; + st8.spill [r2]=r23,8;; + st8.spill [r2]=r24,8;; + st8.spill [r2]=r25,8;; + st8.spill [r2]=r26,8;; + st8.spill [r2]=r27,8;; + st8.spill [r2]=r28,8;; + st8.spill [r2]=r29,8;; + st8.spill [r2]=r30,8;; + st8.spill [r2]=r31,8;; + + mov r4=ar.unat;; + st8 [r2]=r4,8 // save User NaT bits for r16-r31 + mov ar.unat=r5 // restore original unat + bsw.0;; + +//save BRs + add r4=8,r2 // duplicate r2 in r4 + add r6=2*8,r2 // duplicate r2 in r4 + + mov r3=b0 + mov r5=b1 + mov r7=b2;; + st8 [r2]=r3,3*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; + + mov r3=b3 + mov r5=b4 + mov r7=b5;; + st8 [r2]=r3,3*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; + + mov r3=b6 + mov r5=b7;; + st8 [r2]=r3,2*8 + st8 [r4]=r5,2*8;; + +cSaveCRs: +// save CRs + add r4=8,r2 // duplicate r2 in r4 + add r6=2*8,r2 // duplicate r2 in r4 + + mov r3=cr.dcr + mov r5=cr.itm + mov r7=cr.iva;; + + st8 [r2]=r3,8*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; // 48 byte rements + + mov r3=cr.pta;; + st8 [r2]=r3,8*8;; // 64 byte rements + +// if PSR.ic=0, reading interruption registers causes an illegal operation fault + mov r3=psr;; + tbit.nz.unc p6,p0=r3,PSR_IC;; // PSI Valid Log bit pos. test +(p6) st8 [r2]=r0,9*8+160 // increment by 232 byte inc. +begin_skip_intr_regs: +(p6) br SkipIntrRegs;; + + add r4=8,r2 // duplicate r2 in r4 + add r6=2*8,r2 // duplicate r2 in r6 + + mov r3=cr.ipsr + mov r5=cr.isr + mov r7=r0;; + st8 [r2]=r3,3*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; + + mov r3=cr.iip + mov r5=cr.ifa + mov r7=cr.itir;; + st8 [r2]=r3,3*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; + + mov r3=cr.iipa + mov r5=cr.ifs + mov r7=cr.iim;; + st8 [r2]=r3,3*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; + + mov r3=cr25;; // cr.iha + st8 [r2]=r3,160;; // 160 byte rement + +SkipIntrRegs: + st8 [r2]=r0,152;; // another 152 byte . + + add r4=8,r2 // duplicate r2 in r4 + add r6=2*8,r2 // duplicate r2 in r6 + + mov r3=cr.lid +// mov r5=cr.ivr // cr.ivr, don't read it + mov r7=cr.tpr;; + st8 [r2]=r3,3*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; + + mov r3=r0 // cr.eoi => cr67 + mov r5=r0 // cr.irr0 => cr68 + mov r7=r0;; // cr.irr1 => cr69 + st8 [r2]=r3,3*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; + + mov r3=r0 // cr.irr2 => cr70 + mov r5=r0 // cr.irr3 => cr71 + mov r7=cr.itv;; + st8 [r2]=r3,3*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; + + mov r3=cr.pmv + mov r5=cr.cmcv;; + st8 [r2]=r3,7*8 + st8 [r4]=r5,7*8;; + + mov r3=r0 // cr.lrr0 => cr80 + mov r5=r0;; // cr.lrr1 => cr81 + st8 [r2]=r3,23*8 + st8 [r4]=r5,23*8;; + + adds r2=25*8,r2;; + +cSaveARs: +// save ARs + add r4=8,r2 // duplicate r2 in r4 + add r6=2*8,r2 // duplicate r2 in r6 + + mov r3=ar.k0 + mov r5=ar.k1 + mov r7=ar.k2;; + st8 [r2]=r3,3*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; + + mov r3=ar.k3 + mov r5=ar.k4 + mov r7=ar.k5;; + st8 [r2]=r3,3*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; + + mov r3=ar.k6 + mov r5=ar.k7 + mov r7=r0;; // ar.kr8 + st8 [r2]=r3,10*8 + st8 [r4]=r5,10*8 + st8 [r6]=r7,10*8;; // rement by 72 bytes + + mov r3=ar.rsc + mov ar.rsc=r0 // put RSE in enforced lazy mode + mov r5=ar.bsp + ;; + mov r7=ar.bspstore;; + st8 [r2]=r3,3*8 + st8 [r4]=r5,3*8 + st8 [r6]=r7,3*8;; + + mov r3=ar.rnat;; + st8 [r2]=r3,8*13 // increment by 13x8 bytes + + mov r3=ar.ccv;; + st8 [r2]=r3,8*4 + + mov r3=ar.unat;; + st8 [r2]=r3,8*4 + + mov r3=ar.fpsr;; + st8 [r2]=r3,8*4 + + mov r3=ar.itc;; + st8 [r2]=r3,160 // 160 + + mov r3=ar.pfs;; + st8 [r2]=r3,8 + + mov r3=ar.lc;; + st8 [r2]=r3,8 + + mov r3=ar.ec;; + st8 [r2]=r3 + add r2=8*62,r2 //padding + +// save RRs + mov ar.lc=0x08-1 + movl r4=0x00;; + +cStRR: + dep.z r5=r4,61,3;; + mov r3=rr[r5];; + st8 [r2]=r3,8 + add r4=1,r4 + br.cloop.sptk.few cStRR + ;; +end_os_mca_dump: + br ia64_os_mca_done_dump;; + +//EndStub////////////////////////////////////////////////////////////////////// + + +//++ +// Name: +// ia64_os_mca_proc_state_restore() +// +// Stub Description: +// +// This is a stub to restore the saved processor state during MCHK +// +//-- + +ia64_os_mca_proc_state_restore: + +// Restore bank1 GR16-31 + GET_IA64_MCA_DATA(r2) + ;; + add r2 = IA64_MCA_CPU_PROC_STATE_DUMP_OFFSET, r2 + +restore_GRs: // restore bank-1 GRs 16-31 + bsw.1;; + add r3=16*8,r2;; // to get to NaT of GR 16-31 + ld8 r3=[r3];; + mov ar.unat=r3;; // first restore NaT + + ld8.fill r16=[r2],8;; + ld8.fill r17=[r2],8;; + ld8.fill r18=[r2],8;; + ld8.fill r19=[r2],8;; + ld8.fill r20=[r2],8;; + ld8.fill r21=[r2],8;; + ld8.fill r22=[r2],8;; + ld8.fill r23=[r2],8;; + ld8.fill r24=[r2],8;; + ld8.fill r25=[r2],8;; + ld8.fill r26=[r2],8;; + ld8.fill r27=[r2],8;; + ld8.fill r28=[r2],8;; + ld8.fill r29=[r2],8;; + ld8.fill r30=[r2],8;; + ld8.fill r31=[r2],8;; + + ld8 r3=[r2],8;; // increment to skip NaT + bsw.0;; + +restore_BRs: + add r4=8,r2 // duplicate r2 in r4 + add r6=2*8,r2;; // duplicate r2 in r4 + + ld8 r3=[r2],3*8 + ld8 r5=[r4],3*8 + ld8 r7=[r6],3*8;; + mov b0=r3 + mov b1=r5 + mov b2=r7;; + + ld8 r3=[r2],3*8 + ld8 r5=[r4],3*8 + ld8 r7=[r6],3*8;; + mov b3=r3 + mov b4=r5 + mov b5=r7;; + + ld8 r3=[r2],2*8 + ld8 r5=[r4],2*8;; + mov b6=r3 + mov b7=r5;; + +restore_CRs: + add r4=8,r2 // duplicate r2 in r4 + add r6=2*8,r2;; // duplicate r2 in r4 + + ld8 r3=[r2],8*8 + ld8 r5=[r4],3*8 + ld8 r7=[r6],3*8;; // 48 byte increments + mov cr.dcr=r3 + mov cr.itm=r5 + mov cr.iva=r7;; + + ld8 r3=[r2],8*8;; // 64 byte increments +// mov cr.pta=r3 + + +// if PSR.ic=1, reading interruption registers causes an illegal operation fault + mov r3=psr;; + tbit.nz.unc p6,p0=r3,PSR_IC;; // PSI Valid Log bit pos. test +(p6) st8 [r2]=r0,9*8+160 // increment by 232 byte inc. + +begin_rskip_intr_regs: +(p6) br rSkipIntrRegs;; + + add r4=8,r2 // duplicate r2 in r4 + add r6=2*8,r2;; // duplicate r2 in r4 + + ld8 r3=[r2],3*8 + ld8 r5=[r4],3*8 + ld8 r7=[r6],3*8;; + mov cr.ipsr=r3 +// mov cr.isr=r5 // cr.isr is read only + + ld8 r3=[r2],3*8 + ld8 r5=[r4],3*8 + ld8 r7=[r6],3*8;; + mov cr.iip=r3 + mov cr.ifa=r5 + mov cr.itir=r7;; + + ld8 r3=[r2],3*8 + ld8 r5=[r4],3*8 + ld8 r7=[r6],3*8;; + mov cr.iipa=r3 + mov cr.ifs=r5 + mov cr.iim=r7 + + ld8 r3=[r2],160;; // 160 byte increment + mov cr.iha=r3 + +rSkipIntrRegs: + ld8 r3=[r2],152;; // another 152 byte inc. + + add r4=8,r2 // duplicate r2 in r4 + add r6=2*8,r2;; // duplicate r2 in r6 + + ld8 r3=[r2],8*3 + ld8 r5=[r4],8*3 + ld8 r7=[r6],8*3;; + mov cr.lid=r3 +// mov cr.ivr=r5 // cr.ivr is read only + mov cr.tpr=r7;; + + ld8 r3=[r2],8*3 + ld8 r5=[r4],8*3 + ld8 r7=[r6],8*3;; +// mov cr.eoi=r3 +// mov cr.irr0=r5 // cr.irr0 is read only +// mov cr.irr1=r7;; // cr.irr1 is read only + + ld8 r3=[r2],8*3 + ld8 r5=[r4],8*3 + ld8 r7=[r6],8*3;; +// mov cr.irr2=r3 // cr.irr2 is read only +// mov cr.irr3=r5 // cr.irr3 is read only + mov cr.itv=r7;; + + ld8 r3=[r2],8*7 + ld8 r5=[r4],8*7;; + mov cr.pmv=r3 + mov cr.cmcv=r5;; + + ld8 r3=[r2],8*23 + ld8 r5=[r4],8*23;; + adds r2=8*23,r2 + adds r4=8*23,r4;; +// mov cr.lrr0=r3 +// mov cr.lrr1=r5 + + adds r2=8*2,r2;; + +restore_ARs: + add r4=8,r2 // duplicate r2 in r4 + add r6=2*8,r2;; // duplicate r2 in r4 + + ld8 r3=[r2],3*8 + ld8 r5=[r4],3*8 + ld8 r7=[r6],3*8;; + mov ar.k0=r3 + mov ar.k1=r5 + mov ar.k2=r7;; + + ld8 r3=[r2],3*8 + ld8 r5=[r4],3*8 + ld8 r7=[r6],3*8;; + mov ar.k3=r3 + mov ar.k4=r5 + mov ar.k5=r7;; + + ld8 r3=[r2],10*8 + ld8 r5=[r4],10*8 + ld8 r7=[r6],10*8;; + mov ar.k6=r3 + mov ar.k7=r5 + ;; + + ld8 r3=[r2],3*8 + ld8 r5=[r4],3*8 + ld8 r7=[r6],3*8;; +// mov ar.rsc=r3 +// mov ar.bsp=r5 // ar.bsp is read only + mov ar.rsc=r0 // make sure that RSE is in enforced lazy mode + ;; + mov ar.bspstore=r7;; + + ld8 r9=[r2],8*13;; + mov ar.rnat=r9 + + mov ar.rsc=r3 + ld8 r3=[r2],8*4;; + mov ar.ccv=r3 + + ld8 r3=[r2],8*4;; + mov ar.unat=r3 + + ld8 r3=[r2],8*4;; + mov ar.fpsr=r3 + + ld8 r3=[r2],160;; // 160 +// mov ar.itc=r3 + + ld8 r3=[r2],8;; + mov ar.pfs=r3 + + ld8 r3=[r2],8;; + mov ar.lc=r3 + + ld8 r3=[r2];; + mov ar.ec=r3 + add r2=8*62,r2;; // padding + +restore_RRs: + mov r5=ar.lc + mov ar.lc=0x08-1 + movl r4=0x00;; +cStRRr: + dep.z r7=r4,61,3 + ld8 r3=[r2],8;; + mov rr[r7]=r3 // what are its access previledges? + add r4=1,r4 + br.cloop.sptk.few cStRRr + ;; + mov ar.lc=r5 + ;; +end_os_mca_restore: + br ia64_os_mca_done_restore;; + +//EndStub////////////////////////////////////////////////////////////////////// + + +// ok, the issue here is that we need to save state information so +// it can be useable by the kernel debugger and show regs routines. +// In order to do this, our best bet is save the current state (plus +// the state information obtain from the MIN_STATE_AREA) into a pt_regs +// format. This way we can pass it on in a useable format. +// + +// +// SAL to OS entry point for INIT on the monarch processor +// This has been defined for registration purposes with SAL +// as a part of ia64_mca_init. +// +// When we get here, the following registers have been +// set by the SAL for our use +// +// 1. GR1 = OS INIT GP +// 2. GR8 = PAL_PROC physical address +// 3. GR9 = SAL_PROC physical address +// 4. GR10 = SAL GP (physical) +// 5. GR11 = Init Reason +// 0 = Received INIT for event other than crash dump switch +// 1 = Received wakeup at the end of an OS_MCA corrected machine check +// 2 = Received INIT dude to CrashDump switch assertion +// +// 6. GR12 = Return address to location within SAL_INIT procedure + + +GLOBAL_ENTRY(ia64_monarch_init_handler) + .prologue + // stash the information the SAL passed to os + SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2) + ;; + SAVE_MIN_WITH_COVER + ;; + mov r8=cr.ifa + mov r9=cr.isr + adds r3=8,r2 // set up second base pointer + ;; + SAVE_REST + +// ok, enough should be saved at this point to be dangerous, and supply +// information for a dump +// We need to switch to Virtual mode before hitting the C functions. + + movl r2=IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN + mov r3=psr // get the current psr, minimum enabled at this point + ;; + or r2=r2,r3 + ;; + movl r3=IVirtual_Switch + ;; + mov cr.iip=r3 // short return to set the appropriate bits + mov cr.ipsr=r2 // need to do an rfi to set appropriate bits + ;; + rfi + ;; +IVirtual_Switch: + // + // We should now be running virtual + // + // Let's call the C handler to get the rest of the state info + // + alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!) + ;; + adds out0=16,sp // out0 = pointer to pt_regs + ;; + DO_SAVE_SWITCH_STACK + .body + adds out1=16,sp // out0 = pointer to switch_stack + + br.call.sptk.many rp=ia64_init_handler +.ret1: + +return_from_init: + br.sptk return_from_init +END(ia64_monarch_init_handler) + +// +// SAL to OS entry point for INIT on the slave processor +// This has been defined for registration purposes with SAL +// as a part of ia64_mca_init. +// + +GLOBAL_ENTRY(ia64_slave_init_handler) +1: br.sptk 1b +END(ia64_slave_init_handler) |