📄 ivt.s
字号:
mov r31=pr // save pr#ifdef CONFIG_SMP mov r28=ar.ccv // save ar.ccv ;;1: ld8 r18=[r17] ;; // avoid RAW on r18 mov ar.ccv=r18 // set compare value for cmpxchg or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits ;; cmpxchg8.acq r26=[r17],r25,ar.ccv mov r24=PAGE_SHIFT<<2 ;; cmp.eq p6,p7=r26,r18 ;;(p6) itc.d r25 // install updated PTE ;; ld8 r18=[r17] // read PTE again ;; cmp.eq p6,p7=r18,r25 // is it same as the newly installed ;;(p7) ptc.l r16,r24 mov b0=r29 // restore b0 mov ar.ccv=r28#else ;;1: ld8 r18=[r17] ;; // avoid RAW on r18 or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits mov b0=r29 // restore b0 ;; st8 [r17]=r18 // store back updated PTE itc.d r18 // install updated PTE#endif mov pr=r31,-1 // restore pr rfiEND(idirty_bit) .align 1024/////////////////////////////////////////////////////////////////////////////////////////// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)ENTRY(iaccess_bit) DBG_FAULT(9) // Like Entry 8, except for instruction access mov r16=cr.ifa // get the address that caused the fault movl r30=1f // load continuation point in case of nested fault mov r31=pr // save predicates#ifdef CONFIG_ITANIUM /* * Erratum 10 (IFA may contain incorrect address) has "NoFix" status. */ mov r17=cr.ipsr ;; mov r18=cr.iip tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set? ;;(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa#endif /* CONFIG_ITANIUM */ ;; thash r17=r16 // compute virtual address of L3 PTE mov r29=b0 // save b0 in case of nested fault)#ifdef CONFIG_SMP mov r28=ar.ccv // save ar.ccv ;;1: ld8 r18=[r17] ;; mov ar.ccv=r18 // set compare value for cmpxchg or r25=_PAGE_A,r18 // set the accessed bit ;; cmpxchg8.acq r26=[r17],r25,ar.ccv mov r24=PAGE_SHIFT<<2 ;; cmp.eq p6,p7=r26,r18 ;;(p6) itc.i r25 // install updated PTE ;; ld8 r18=[r17] // read PTE again ;; cmp.eq p6,p7=r18,r25 // is it same as the newly installed ;;(p7) ptc.l r16,r24 mov b0=r29 // restore b0 mov ar.ccv=r28#else /* !CONFIG_SMP */ ;;1: ld8 r18=[r17] ;; or r18=_PAGE_A,r18 // set the accessed bit mov b0=r29 // restore b0 ;; st8 [r17]=r18 // store back updated PTE itc.i r18 // install updated PTE#endif /* !CONFIG_SMP */ mov pr=r31,-1 rfiEND(iaccess_bit) .align 1024/////////////////////////////////////////////////////////////////////////////////////////// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)ENTRY(daccess_bit) DBG_FAULT(10) // Like Entry 8, except for data access mov r16=cr.ifa // get the address that caused the fault movl r30=1f // load continuation point in case of nested fault ;; thash r17=r16 // compute virtual address of L3 PTE mov r31=pr mov r29=b0 // save b0 in case of nested fault)#ifdef CONFIG_SMP mov r28=ar.ccv // save ar.ccv ;;1: ld8 r18=[r17] ;; // avoid RAW on r18 mov ar.ccv=r18 // set compare value for cmpxchg or r25=_PAGE_A,r18 // set the dirty bit ;; cmpxchg8.acq r26=[r17],r25,ar.ccv mov r24=PAGE_SHIFT<<2 ;; cmp.eq p6,p7=r26,r18 ;;(p6) itc.d r25 // install updated PTE ;; ld8 r18=[r17] // read PTE again ;; cmp.eq p6,p7=r18,r25 // is it same as the newly installed ;;(p7) ptc.l r16,r24 mov ar.ccv=r28#else ;;1: ld8 r18=[r17] ;; // avoid RAW on r18 or r18=_PAGE_A,r18 // set the accessed bit ;; st8 [r17]=r18 // store back updated PTE itc.d r18 // install updated PTE#endif mov b0=r29 // restore b0 mov pr=r31,-1 rfiEND(daccess_bit) .align 1024/////////////////////////////////////////////////////////////////////////////////////////// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)ENTRY(break_fault) DBG_FAULT(11) mov r16=cr.iim mov r17=__IA64_BREAK_SYSCALL mov r31=pr // prepare to save predicates ;; cmp.eq p0,p7=r16,r17 // is this a system call? (p7 <- false, if so)(p7) br.cond.spnt non_syscall SAVE_MIN // uses r31; defines r2: ssm psr.ic | PSR_DEFAULT_BITS ;; srlz.i // guarantee that interruption collection is on cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 ;;(p15) ssm psr.i // restore psr.i adds r8=(IA64_PT_REGS_R8_OFFSET-IA64_PT_REGS_R16_OFFSET),r2 ;; stf8 [r8]=f1 // ensure pt_regs.r8 != 0 (see handle_syscall_error) adds r3=8,r2 // set up second base pointer for SAVE_REST ;; SAVE_REST br.call.sptk.many rp=demine_args // clear NaT bits in (potential) syscall args mov r3=255 adds r15=-1024,r15 // r15 contains the syscall number---subtract 1024 adds r2=IA64_TASK_PTRACE_OFFSET,r13 // r2 = ¤t->ptrace ;; cmp.geu p6,p7=r3,r15 // (syscall > 0 && syscall <= 1024+255) ? movl r16=sys_call_table ;;(p6) shladd r16=r15,3,r16 movl r15=ia64_ret_from_syscall(p7) adds r16=(__NR_ni_syscall-1024)*8,r16 // force __NR_ni_syscall ;; ld8 r16=[r16] // load address of syscall entry point mov rp=r15 // set the real return addr ;; ld8 r2=[r2] // r2 = current->ptrace mov b6=r16 // arrange things so we skip over break instruction when returning: adds r16=16,sp // get pointer to cr_ipsr adds r17=24,sp // get pointer to cr_iip ;; ld8 r18=[r16] // fetch cr_ipsr tbit.z p8,p0=r2,PT_TRACESYS_BIT // (current->ptrace & PF_TRACESYS) == 0? ;; ld8 r19=[r17] // fetch cr_iip extr.u r20=r18,41,2 // extract ei field ;; cmp.eq p6,p7=2,r20 // isr.ei==2? adds r19=16,r19 // compute address of next bundle ;;(p6) mov r20=0 // clear ei to 0(p7) adds r20=1,r20 // increment ei to next slot ;;(p6) st8 [r17]=r19 // store new cr.iip if cr.isr.ei wrapped around dep r18=r20,r18,41,2 // insert new ei into cr.isr ;; st8 [r16]=r18 // store new value for cr.isr(p8) br.call.sptk.many b6=b6 // ignore this return addr br.cond.sptk ia64_trace_syscall // NOT REACHEDEND(break_fault)ENTRY(demine_args) alloc r2=ar.pfs,8,0,0,0 tnat.nz p8,p0=in0 tnat.nz p9,p0=in1 ;;(p8) mov in0=-1 tnat.nz p10,p0=in2 tnat.nz p11,p0=in3(p9) mov in1=-1 tnat.nz p12,p0=in4 tnat.nz p13,p0=in5 ;;(p10) mov in2=-1 tnat.nz p14,p0=in6 tnat.nz p15,p0=in7(p11) mov in3=-1 tnat.nz p8,p0=r15 // demining r15 is not a must, but it is safer(p12) mov in4=-1(p13) mov in5=-1 ;;(p14) mov in6=-1(p15) mov in7=-1(p8) mov r15=-1 br.ret.sptk.many rpEND(demine_args) .align 1024/////////////////////////////////////////////////////////////////////////////////////////// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)ENTRY(interrupt) DBG_FAULT(12) mov r31=pr // prepare to save predicates ;; SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3 ssm psr.ic | PSR_DEFAULT_BITS ;; adds r3=8,r2 // set up second base pointer for SAVE_REST srlz.i // ensure everybody knows psr.ic is back on ;; SAVE_REST ;; alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group mov out0=cr.ivr // pass cr.ivr as first arg add out1=16,sp // pass pointer to pt_regs as second arg ;; srlz.d // make sure we see the effect of cr.ivr movl r14=ia64_leave_kernel ;; mov rp=r14 br.call.sptk.many b6=ia64_handle_irqEND(interrupt) .align 1024/////////////////////////////////////////////////////////////////////////////////////////// 0x3400 Entry 13 (size 64 bundles) Reserved DBG_FAULT(13) FAULT(13) .align 1024/////////////////////////////////////////////////////////////////////////////////////////// 0x3800 Entry 14 (size 64 bundles) Reserved DBG_FAULT(14) FAULT(14) .align 1024/////////////////////////////////////////////////////////////////////////////////////////// 0x3c00 Entry 15 (size 64 bundles) Reserved DBG_FAULT(15) FAULT(15) /* * Squatting in this space ... * * This special case dispatcher for illegal operation faults allows preserved * registers to be modified through a callback function (asm only) that is handed * back from the fault handler in r8. Up to three arguments can be passed to the * callback function by returning an aggregate with the callback as its first * element, followed by the arguments. */ENTRY(dispatch_illegal_op_fault) SAVE_MIN_WITH_COVER ssm psr.ic | PSR_DEFAULT_BITS ;; srlz.i // guarantee that interruption collection is on ;;(p15) ssm psr.i // restore psr.i adds r3=8,r2 // set up second base pointer for SAVE_REST ;; alloc r14=ar.pfs,0,0,1,0 // must be first in insn group mov out0=ar.ec ;; SAVE_REST ;; br.call.sptk.many rp=ia64_illegal_op_fault.ret0: ;; alloc r14=ar.pfs,0,0,3,0 // must be first in insn group mov out0=r9 mov out1=r10 mov out2=r11 movl r15=ia64_leave_kernel ;; mov rp=r15 mov b6=r8 ;; cmp.ne p6,p0=0,r8(p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel br.sptk.many ia64_leave_kernelEND(dispatch_illegal_op_fault) .align 1024/////////////////////////////////////////////////////////////////////////////////////////// 0x4000 Entry 16 (size 64 bundles) Reserved DBG_FAULT(16) FAULT(16)#ifdef CONFIG_IA32_SUPPORT /* * There is no particular reason for this code to be here, other than that * there happens to be space here that would go unused otherwise. If this * fault ever gets "unreserved", simply moved the following code to a more * suitable spot... */ // IA32 interrupt entry pointENTRY(dispatch_to_ia32_handler) SAVE_MIN ;; mov r14=cr.isr ssm psr.ic | PSR_DEFAULT_BITS ;; srlz.i // guarantee that interruption collection is on ;;(p15) ssm psr.i adds r3=8,r2 // Base pointer for SAVE_REST ;; SAVE_REST ;; mov r15=0x80 shr r14=r14,16 // Get interrupt number ;; cmp.ne p6,p0=r14,r15(p6) br.call.dpnt.many b6=non_ia32_syscall adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW conventions adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp ;; cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP) ;; alloc r15=ar.pfs,0,0,6,0 // must first in an insn group ;; ld4 r8=[r14],8 // r8 == eax (syscall number) mov r15=230 // number of entries in ia32 system call table ;; cmp.ltu.unc p6,p7=r8,r15 ld4 out1=[r14],8 // r9 == ecx ;; ld4 out2=[r14],8 // r10 == edx ;; ld4 out0=[r14] // r11 == ebx adds r14=(IA64_PT_REGS_R8_OFFSET-(8*3)) + 16,sp ;; ld4 out5=[r14],8 // r13 == ebp ;; ld4 out3=[r14],8 // r14 == esi adds r2=IA64_TASK_PTRACE_OFFSET,r13 // r2 = ¤t->ptrace ;; ld4 out4=[r14] // r15 == edi movl r16=ia32_syscall_table ;;(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number ld8 r2=[r2] // r2 = current->ptrace ;; ld8 r16=[r16] tbit.z p8,p0=r2,PT_TRACESYS_BIT // (current->ptrace & PT_TRACESYS) == 0? ;; mov b6=r16 movl r15=ia32_ret_from_syscall ;; mov rp=r15(p8) br.call.sptk.many b6=b6 br.cond.sptk ia32_trace_syscallnon_ia32_syscall: alloc r15=ar.pfs,0,0,2,0 mov out0=r14 // interrupt # add out1=16,sp // pointer to pt_regs ;; // avoid WAW on CFM br.call.sptk.many rp=ia32_bad_interrupt.ret1: movl r15=ia64_leave_kernel ;; mov rp=r15 br.ret.sptk.many rpEND(dispatch_to_ia32_handler)#endif /* CONFIG_IA32_SUPPORT */ .align 1024/////////////////////////////////////////////////////////////////////////////////////////// 0x4400 Entry 17 (size 64 bundles) Reserved DBG_FAULT(17) FAULT(17)ENTRY(non_syscall) SAVE_MIN_WITH_COVER // There is no particular reason for this code to be here, other than that // there happens to be space here that would go unused otherwise. If this // fault ever gets "unreserved", simply moved the following code to a more // suitable spot... alloc r14=ar.pfs,0,0,2,0 mov out0=cr.iim add out1=16,sp adds r3=8,r2 // set up second base pointer for SAVE_REST ssm psr.ic | PSR_DEFAULT_BITS ;; srlz.i // guarantee that interruption collection is on ;;(p15) ssm psr.i // restore psr.i movl r15=ia64_leave_kernel ;; SAVE_REST mov rp=r15 ;; br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addrEND(non_syscall) .align 1024/////////////////////////////////////////////////////////////////////////////////////////// 0x4800 Entry 18 (size 64 bundles) Reserved DBG_FAULT(18) FAULT(18) /* * There is no particular reason for this code to be here, other than that * there happens to be space here that would go unused otherwise. If this * fault ever gets "unreserved", simply moved the following code to a more * suitable spot... */ENTRY(dispatch_unaligned_handler) SAVE_MIN_WITH_COVER ;; alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!) mov out0=cr.ifa adds out1=16,sp ssm psr.ic | PSR_DEFAULT_BITS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -