📄 ivt.s
字号:
;; srlz.i // guarantee that interruption collectin is on ;;(p15) ssm psr.i // restore psr.i movl r14=ia64_leave_kernel ;; SAVE_REST mov rp=r14 ;; adds out2=16,r12 // out2 = pointer to pt_regs br.call.sptk.many b6=ia64_do_page_fault // ignore return addressEND(page_fault) .align 1024/////////////////////////////////////////////////////////////////////////////////////////// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)ENTRY(nested_dtlb_miss) /* * In the absence of kernel bugs, we get here when the virtually mapped linear * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction * Access-bit, or Data Access-bit faults). If the DTLB entry for the virtual page * table is missing, a nested TLB miss fault is triggered and control is * transferred to this point. When this happens, we lookup the pte for the * faulting address by walking the page table in physical mode and return to the * continuation point passed in register r30 (or call page_fault if the address is * not mapped). * * Input: r16: faulting address * r29: saved b0 * r30: continuation address * r31: saved pr * * Output: r17: physical address of L3 PTE of faulting address * r29: saved b0 * r30: continuation address * r31: saved pr * * Clobbered: b0, r18, r19, r21, psr.dt (cleared) */ rsm psr.dt // switch to using physical data addressing mov r19=IA64_KR(PT_BASE) // get the page table base address shl r21=r16,3 // shift bit 60 into sign bit ;; shr.u r17=r16,61 // get the region number into r17 ;; cmp.eq p6,p7=5,r17 // is faulting address in region 5? shr.u r18=r16,PGDIR_SHIFT // get bits 33-63 of faulting address ;;(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place srlz.d(p6) movl r19=__pa(swapper_pg_dir) // region 5 is rooted at swapper_pg_dir(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3 ;;(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8) cmp.eq p7,p6=0,r21 // unused address bits all zeroes? shr.u r18=r16,PMD_SHIFT // shift L2 index into position ;; ld8 r17=[r17] // fetch the L1 entry (may be 0) ;;(p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL? dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry ;;(p7) ld8 r17=[r17] // fetch the L2 entry (may be 0) shr.u r19=r16,PAGE_SHIFT // shift L3 index into position ;;(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL? dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table entry(p6) br.cond.spnt page_fault mov b0=r30 br.sptk.many b0 // return to continuation pointEND(nested_dtlb_miss) .align 1024/////////////////////////////////////////////////////////////////////////////////////////// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)ENTRY(ikey_miss) DBG_FAULT(6) FAULT(6)END(ikey_miss) .align 1024/////////////////////////////////////////////////////////////////////////////////////////// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)ENTRY(dkey_miss) DBG_FAULT(7) FAULT(7)END(dkey_miss) .align 1024/////////////////////////////////////////////////////////////////////////////////////////// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)ENTRY(dirty_bit) DBG_FAULT(8) /* * What we do here is to simply turn on the dirty bit in the PTE. We need to * update both the page-table and the TLB entry. To efficiently access the PTE, * we address it through the virtual page table. Most likely, the TLB entry for * the relevant virtual page table page is still present in the TLB so we can * normally do this without additional TLB misses. In case the necessary virtual * page table TLB entry isn't present, we take a nested TLB miss hit where we look * up the physical address of the L3 PTE and then continue at label 1 below. */ 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 r29=b0 // save b0 in case of nested fault 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)/* System call entry/exit only saves/restores part of pt_regs, i.e. no scratch registers * are saved/restored except r15 which contains syscall number and needs to be saved in the * entry. This optimization is based on the assumption that applications only call glibc * system call interface which doesn't use scratch registers after break into kernel. * Registers saved/restored during system call entry/exit are listed as follows: * * Registers to be saved & restored: * CR registers: cr_ipsr, cr_iip, cr_ifs * AR registers: ar_unat, ar_pfs, ar_rsc, ar_rnat, ar_bspstore, ar_fpsr * others: pr, b0, loadrs, r1, r12, r13, r15 * Registers to be restored only: * r8~r11: output value from the system call. * * During system call exit, scratch registers (including r15) are modified/cleared to * prevent leaking bits from kernel to user level. */ 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 mov r21=ar.fpsr; mov r29=cr.ipsr; mov r20=r1; mov r25=ar.unat; mov r27=ar.rsc; mov r26=ar.pfs; mov r28=cr.iip; mov r1=IA64_KR(CURRENT); /* r1 = current (physical) */ ;; invala; extr.u r16=r29,32,2; /* extract psr.cpl */ ;; cmp.eq pKern,pUser=r0,r16; /* are we in kernel mode already? (psr.cpl==0) */ /* switch from user to kernel RBS: */ ;; mov r30=r0 MINSTATE_START_SAVE_MIN_VIRT br.call.sptk.many b7=ia64_syscall_setup ;; 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=PT(CR_IPSR)+16,sp // get pointer to cr_ipsr adds r17=PT(CR_IIP)+16,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) .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) /* * 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...
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -