📄 mca_asm.s
字号:
//// 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//#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) \ movl _tmp=ia64_sal_to_os_handoff_state;; \ DATA_VA_TO_PA(_tmp);; \ 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;; .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 .global ia64_mca_proc_state_dump .global ia64_mca_stack .global ia64_mca_stackframe .global ia64_mca_bspstore .global ia64_init_stack .text .align 16ia64_os_mca_dispatch: // Serialize all MCA processing movl r2=ia64_mca_serialize mov r3=1;; DATA_VA_TO_PA(r2);;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: movl r16=__pa(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: mov r16=cr.lid movl r17=__pa(ia64_mca_tlb_list) // Physical address of ia64_mca_tlb_list mov r19=0 mov r20=NR_CPUS ;;1: cmp.eq p6,p7=r19,r20(p6) br.spnt.few err ld8 r18=[r17],IA64_MCA_TLB_INFO_SIZE ;; add r19=1,r19 cmp.eq p6,p7=r18,r16(p7) br.sptk.few 1b ;; adds r17=-IA64_MCA_TLB_INFO_SIZE,r17 ;; mov r23=r17 // save current ia64_mca_percpu_info addr pointer. adds r17=16,r17 ;; ld8 r18=[r17],8 // r18=ptce_base ;; ld4 r19=[r17],4 // r19=ptce_count[0] ;; ld4 r20=[r17],4 // r20=ptce_count[1] ;; ld4 r21=[r17],4 // r21=ptce_stride[0] mov r24=0 ;; ld4 r22=[r17],4 // r22=ptce_stride[1] adds r20=-1,r20 ;;2: cmp.ltu p6,p7=r24,r19(p7) br.cond.dpnt.few 4f mov ar.lc=r203: ptc.e r18 ;; add r18=r22,r18 br.cloop.sptk.few 3b ;; add r18=r21,r18 add r24=1,r24 ;; br.sptk.few 2b4: 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=PAGE_SHIFT<<2 ;; ptr.d r16,r18 ;; srlz.d ;; // 3. Purge ITR for PAL code. adds r17=48,r23 ;; ld8 r16=[r17] 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 movl r18=((1 << KERNEL_TR_PAGE_SHIFT) | PAGE_KERNEL) ;; itr.i itr[r16]=r18 ;; itr.d dtr[r16]=r18 ;; srlz.i srlz.d ;; // 2. Reload DTR register for PERCPU data. adds r17=8,r23 movl r16=PERCPU_ADDR // vaddr movl r18=PAGE_SHIFT<<2 ;; mov cr.itir=r18 mov cr.ifa=r16 ;; ld8 r18=[r17] // pte mov r16=IA64_TR_PERCPU_DATA; ;; itr.d dtr[r16]=r18 ;; srlz.d ;; // 3. Reload ITR for PAL code. adds r17=40,r23 ;; ld8 r18=[r17],8 // pte ;; ld8 r16=[r17] // 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_reloaderr: COLD_BOOT_HANDOFF_STATE(r20,r21,r22) br.sptk.many ia64_os_mca_done_restoredone_tlb_purge_and_reload: // Setup new stack frame for OS_MCA handling movl r2=ia64_mca_bspstore;; // local bspstore area location in r2 DATA_VA_TO_PA(r2);; movl r3=ia64_mca_stackframe;; // save stack frame to memory in r3 DATA_VA_TO_PA(r3);; rse_switch_context(r6,r3,r2);; // RSC management in this new context movl r12=ia64_mca_stack mov r2=8*1024;; // stack size must be same as C array add r12=r2,r12;; // stack base @ bottom of array adds r12=-16,r12;; // allow 16 bytes of scratch // (C calling convention) DATA_VA_TO_PA(r12);; // 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 movl r2=ia64_mca_stackframe // restore stack frame from memory at r2 ;; DATA_VA_TO_PA(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. movl r2=ia64_mca_proc_state_dump;; // Os state dump area DATA_VA_TO_PA(r2) // convert to to physical address// 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -