📄 mca_asm.s
字号:
add regs=MCA_SWITCH_STACK_OFFSET-MCA_PT_REGS_OFFSET, regs ;; add temp1=SW(F2), regs add temp2=SW(F3), regs ;; stf.spill [temp1]=f2,32 stf.spill [temp2]=f3,32 ;; stf.spill [temp1]=f4,32 stf.spill [temp2]=f5,32 ;; stf.spill [temp1]=f12,32 stf.spill [temp2]=f13,32 ;; stf.spill [temp1]=f14,32 stf.spill [temp2]=f15,32 ;; stf.spill [temp1]=f16,32 stf.spill [temp2]=f17,32 ;; stf.spill [temp1]=f18,32 stf.spill [temp2]=f19,32 ;; stf.spill [temp1]=f20,32 stf.spill [temp2]=f21,32 ;; stf.spill [temp1]=f22,32 stf.spill [temp2]=f23,32 ;; stf.spill [temp1]=f24,32 stf.spill [temp2]=f25,32 ;; stf.spill [temp1]=f26,32 stf.spill [temp2]=f27,32 ;; stf.spill [temp1]=f28,32 stf.spill [temp2]=f29,32 ;; stf.spill [temp1]=f30,SW(B2)-SW(F30) stf.spill [temp2]=f31,SW(B3)-SW(F31) mov temp3=b2 mov temp4=b3 ;; st8 [temp1]=temp3,16 // save b2 st8 [temp2]=temp4,16 // save b3 mov temp3=b4 mov temp4=b5 ;; st8 [temp1]=temp3,SW(AR_LC)-SW(B4) // save b4 st8 [temp2]=temp4 // save b5 mov temp3=ar.lc ;; st8 [temp1]=temp3 // save ar.lc // FIXME: Some proms are incorrectly accessing the minstate area as // cached data. The C code uses region 6, uncached virtual. Ensure // that there is no cache data lying around for the first 1K of the // minstate area. // Remove this code in September 2006, that gives platforms a year to // fix their proms and get their customers updated. add r1=32*1,r17 add r2=32*2,r17 add r3=32*3,r17 add r4=32*4,r17 add r5=32*5,r17 add r6=32*6,r17 add r7=32*7,r17 ;; fc r17 fc r1 fc r2 fc r3 fc r4 fc r5 fc r6 fc r7 add r17=32*8,r17 add r1=32*8,r1 add r2=32*8,r2 add r3=32*8,r3 add r4=32*8,r4 add r5=32*8,r5 add r6=32*8,r6 add r7=32*8,r7 ;; fc r17 fc r1 fc r2 fc r3 fc r4 fc r5 fc r6 fc r7 add r17=32*8,r17 add r1=32*8,r1 add r2=32*8,r2 add r3=32*8,r3 add r4=32*8,r4 add r5=32*8,r5 add r6=32*8,r6 add r7=32*8,r7 ;; fc r17 fc r1 fc r2 fc r3 fc r4 fc r5 fc r6 fc r7 add r17=32*8,r17 add r1=32*8,r1 add r2=32*8,r2 add r3=32*8,r3 add r4=32*8,r4 add r5=32*8,r5 add r6=32*8,r6 add r7=32*8,r7 ;; fc r17 fc r1 fc r2 fc r3 fc r4 fc r5 fc r6 fc r7 br.sptk b0//EndStub////////////////////////////////////////////////////////////////////////++// Name:// ia64_state_restore()//// Stub Description://// Restore the SAL/OS state. This is sensitive to the layout of struct// ia64_sal_os_state in mca.h.//// r2 contains the return address, r3 contains either// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.//// In addition to the SAL to OS state, this routine restores all the// registers that appear in struct pt_regs and struct switch_stack,// excluding those in the PAL minstate area.////--ia64_state_restore: // Restore the switch_stack data that is not in minstate nor pt_regs. add regs=MCA_SWITCH_STACK_OFFSET, r3 mov b0=r2 // save return address ;; GET_IA64_MCA_DATA(temp2) ;; add regs=temp2, regs ;; add temp1=SW(F2), regs add temp2=SW(F3), regs ;; ldf.fill f2=[temp1],32 ldf.fill f3=[temp2],32 ;; ldf.fill f4=[temp1],32 ldf.fill f5=[temp2],32 ;; ldf.fill f12=[temp1],32 ldf.fill f13=[temp2],32 ;; ldf.fill f14=[temp1],32 ldf.fill f15=[temp2],32 ;; ldf.fill f16=[temp1],32 ldf.fill f17=[temp2],32 ;; ldf.fill f18=[temp1],32 ldf.fill f19=[temp2],32 ;; ldf.fill f20=[temp1],32 ldf.fill f21=[temp2],32 ;; ldf.fill f22=[temp1],32 ldf.fill f23=[temp2],32 ;; ldf.fill f24=[temp1],32 ldf.fill f25=[temp2],32 ;; ldf.fill f26=[temp1],32 ldf.fill f27=[temp2],32 ;; ldf.fill f28=[temp1],32 ldf.fill f29=[temp2],32 ;; ldf.fill f30=[temp1],SW(B2)-SW(F30) ldf.fill f31=[temp2],SW(B3)-SW(F31) ;; ld8 temp3=[temp1],16 // restore b2 ld8 temp4=[temp2],16 // restore b3 ;; mov b2=temp3 mov b3=temp4 ld8 temp3=[temp1],SW(AR_LC)-SW(B4) // restore b4 ld8 temp4=[temp2] // restore b5 ;; mov b4=temp3 mov b5=temp4 ld8 temp3=[temp1] // restore ar.lc ;; mov ar.lc=temp3 // Restore the pt_regs data that is not in minstate. The previous code // left regs at switch_stack. add regs=MCA_PT_REGS_OFFSET-MCA_SWITCH_STACK_OFFSET, regs ;; add temp1=PT(B6), regs add temp2=PT(B7), regs ;; ld8 temp3=[temp1],PT(AR_CSD)-PT(B6) // restore b6 ld8 temp4=[temp2],PT(AR_SSD)-PT(B7) // restore b7 ;; mov b6=temp3 mov b7=temp4 ld8 temp3=[temp1],PT(AR_UNAT)-PT(AR_CSD) // restore ar.csd ld8 temp4=[temp2],PT(AR_PFS)-PT(AR_SSD) // restore ar.ssd ;; mov ar.csd=temp3 mov ar.ssd=temp4 ld8 temp3=[temp1] // restore ar.unat add temp1=PT(AR_CCV)-PT(AR_UNAT), temp1 ld8 temp4=[temp2],PT(AR_FPSR)-PT(AR_PFS) // restore ar.pfs ;; mov ar.unat=temp3 mov ar.pfs=temp4 // ar.rnat, ar.bspstore, loadrs are restore in ia64_old_stack. ld8 temp3=[temp1],PT(F6)-PT(AR_CCV) // restore ar.ccv ld8 temp4=[temp2],PT(F7)-PT(AR_FPSR) // restore ar.fpsr ;; mov ar.ccv=temp3 mov ar.fpsr=temp4 ldf.fill f6=[temp1],PT(F8)-PT(F6) ldf.fill f7=[temp2],PT(F9)-PT(F7) ;; ldf.fill f8=[temp1],PT(F10)-PT(F8) ldf.fill f9=[temp2],PT(F11)-PT(F9) ;; ldf.fill f10=[temp1] ldf.fill f11=[temp2] // Restore the SAL to OS state. The previous code left regs at pt_regs. add regs=MCA_SOS_OFFSET-MCA_PT_REGS_OFFSET, regs ;; add temp1=SOS(SAL_RA), regs add temp2=SOS(SAL_GP), regs ;; ld8 r12=[temp1],16 // sal_ra ld8 r9=[temp2],16 // sal_gp ;; ld8 r22=[temp1],16 // pal_min_state, virtual ld8 r13=[temp2],16 // prev_IA64_KR_CURRENT ;; ld8 r16=[temp1],16 // prev_IA64_KR_CURRENT_STACK ld8 r20=[temp2],16 // prev_task ;; ld8 temp3=[temp1],16 // cr.isr ld8 temp4=[temp2],16 // cr.ifa ;; mov cr.isr=temp3 mov cr.ifa=temp4 ld8 temp3=[temp1],16 // cr.itir ld8 temp4=[temp2],16 // cr.iipa ;; mov cr.itir=temp3 mov cr.iipa=temp4 ld8 temp3=[temp1] // cr.iim ld8 temp4=[temp2] // cr.iha add temp1=SOS(OS_STATUS), regs add temp2=SOS(CONTEXT), regs ;; mov cr.iim=temp3 mov cr.iha=temp4 dep r22=0,r22,62,1 // pal_min_state, physical, uncached mov IA64_KR(CURRENT)=r13 ld8 r8=[temp1] // os_status ld8 r10=[temp2] // context /* Wire IA64_TR_CURRENT_STACK to the stack that we are resuming to. To * avoid any dependencies on the algorithm in ia64_switch_to(), just * purge any existing CURRENT_STACK mapping and insert the new one. * * r16 contains prev_IA64_KR_CURRENT_STACK, r13 contains * prev_IA64_KR_CURRENT, these values may have been changed by the C * code. Do not use r8, r9, r10, r22, they contain values ready for * the return to SAL. */ mov r15=IA64_KR(CURRENT_STACK) // physical granule mapped by IA64_TR_CURRENT_STACK ;; shl r15=r15,IA64_GRANULE_SHIFT ;; dep r15=-1,r15,61,3 // virtual granule mov r18=IA64_GRANULE_SHIFT<<2 // for cr.itir.ps ;; ptr.d r15,r18 ;; srlz.d extr.u r19=r13,61,3 // r13 = prev_IA64_KR_CURRENT shl r20=r16,IA64_GRANULE_SHIFT // r16 = prev_IA64_KR_CURRENT_STACK movl r21=PAGE_KERNEL // page properties ;; mov IA64_KR(CURRENT_STACK)=r16 cmp.ne p6,p0=RGN_KERNEL,r19 // new stack is in the kernel region? or r21=r20,r21 // construct PA | page properties(p6) br.spnt 1f // the dreaded cpu 0 idle task in region 5:( ;; mov cr.itir=r18 mov cr.ifa=r13 mov r20=IA64_TR_CURRENT_STACK ;; itr.d dtr[r20]=r21 ;; srlz.d1: br.sptk b0//EndStub////////////////////////////////////////////////////////////////////////++// Name:// ia64_new_stack()//// Stub Description://// Switch to the MCA/INIT stack.//// r2 contains the return address, r3 contains either// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.//// On entry RBS is still on the original stack, this routine switches RBS// to use the MCA/INIT stack.//// On entry, sos->pal_min_state is physical, on exit it is virtual.////--ia64_new_stack: add regs=MCA_PT_REGS_OFFSET, r3 add temp2=MCA_SOS_OFFSET+SOS(PAL_MIN_STATE), r3 mov b0=r2 // save return address GET_IA64_MCA_DATA(temp1) invala ;; add temp2=temp2, temp1 // struct ia64_sal_os_state.pal_min_state on MCA or INIT stack add regs=regs, temp1 // struct pt_regs on MCA or INIT stack ;; // Address of minstate area provided by PAL is physical, uncacheable. // Convert to Linux virtual address in region 6 for C code. ld8 ms=[temp2] // pal_min_state, physical ;; dep temp1=-1,ms,62,2 // set region 6 mov temp3=IA64_RBS_OFFSET-MCA_PT_REGS_OFFSET ;; st8 [temp2]=temp1 // pal_min_state, virtual add temp4=temp3, regs // start of bspstore on new stack ;; mov ar.bspstore=temp4 // switch RBS to MCA/INIT stack ;; flushrs // must be first in group br.sptk b0//EndStub////////////////////////////////////////////////////////////////////////++// Name:// ia64_old_stack()//// Stub Description://// Switch to the old stack.//// r2 contains the return address, r3 contains either// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.//// On entry, pal_min_state is virtual, on exit it is physical.//// On entry RBS is on the MCA/INIT stack, this routine switches RBS// back to the previous stack.//// The psr is set to all zeroes. SAL return requires either all zeroes or// just psr.mc set. Leaving psr.mc off allows INIT to be issued if this// code does not perform correctly.//// The dirty registers at the time of the event were flushed to the// MCA/INIT stack in ia64_pt_regs_save(). Restore the dirty registers// before reverting to the previous bspstore.//--ia64_old_stack: add regs=MCA_PT_REGS_OFFSET, r3 mov b0=r2 // save return address GET_IA64_MCA_DATA(temp2) LOAD_PHYSICAL(p0,temp1,1f) ;; mov cr.ipsr=r0 mov cr.ifs=r0 mov cr.iip=temp1 ;; invala rfi1: add regs=regs, temp2 // struct pt_regs on MCA or INIT stack ;; add temp1=PT(LOADRS), regs ;; ld8 temp2=[temp1],PT(AR_BSPSTORE)-PT(LOADRS) // restore loadrs ;; ld8 temp3=[temp1],PT(AR_RNAT)-PT(AR_BSPSTORE) // restore ar.bspstore mov ar.rsc=temp2 ;; loadrs ld8 temp4=[temp1] // restore ar.rnat ;; mov ar.bspstore=temp3 // back to old stack ;; mov ar.rnat=temp4 ;; br.sptk b0//EndStub////////////////////////////////////////////////////////////////////////++// Name:// ia64_set_kernel_registers()//// Stub Description://// Set the registers that are required by the C code in order to run on an// MCA/INIT stack.//// r2 contains the return address, r3 contains either// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.////--ia64_set_kernel_registers: add temp3=MCA_SP_OFFSET, r3 mov b0=r2 // save return address GET_IA64_MCA_DATA(temp1) ;; add r12=temp1, temp3 // kernel stack pointer on MCA/INIT stack add r13=temp1, r3 // set current to start of MCA/INIT stack add r20=temp1, r3 // physical start of MCA/INIT stack ;; DATA_PA_TO_VA(r12,temp2) DATA_PA_TO_VA(r13,temp3) ;; mov IA64_KR(CURRENT)=r13 /* Wire IA64_TR_CURRENT_STACK to the MCA/INIT handler stack. To avoid * any dependencies on the algorithm in ia64_switch_to(), just purge * any existing CURRENT_STACK mapping and insert the new one. */ mov r16=IA64_KR(CURRENT_STACK) // physical granule mapped by IA64_TR_CURRENT_STACK ;; shl r16=r16,IA64_GRANULE_SHIFT ;; dep r16=-1,r16,61,3 // virtual granule mov r18=IA64_GRANULE_SHIFT<<2 // for cr.itir.ps ;; ptr.d r16,r18 ;; srlz.d shr.u r16=r20,IA64_GRANULE_SHIFT // r20 = physical start of MCA/INIT stack movl r21=PAGE_KERNEL // page properties ;; mov IA64_KR(CURRENT_STACK)=r16 or r21=r20,r21 // construct PA | page properties ;; mov cr.itir=r18 mov cr.ifa=r13 mov r20=IA64_TR_CURRENT_STACK movl r17=FPSR_DEFAULT ;; mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value ;; itr.d dtr[r20]=r21 ;; srlz.d br.sptk b0//EndStub//////////////////////////////////////////////////////////////////////#undef ms#undef regs#undef temp1#undef temp2#undef temp3#undef temp4// Support function for mca.c, it is here to avoid using inline asm. Given the// address of an rnat slot, if that address is below the current ar.bspstore// then return the contents of that slot, otherwise return the contents of// ar.rnat.GLOBAL_ENTRY(ia64_get_rnat) alloc r14=ar.pfs,1,0,0,0 mov ar.rsc=0 ;; mov r14=ar.bspstore ;; cmp.lt p6,p7=in0,r14 ;;(p6) ld8 r8=[in0](p7) mov r8=ar.rnat mov ar.rsc=3 br.ret.sptk.many rpEND(ia64_get_rnat)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -