📄 ivt.s
字号:
#include <asm/debugger.h>#include <asm/vhpt.h>#include <public/arch-ia64.h>#include <asm/config.h>/* * arch/ia64/kernel/ivt.S * * Copyright (C) 1998-2001, 2003 Hewlett-Packard Co * Stephane Eranian <eranian@hpl.hp.com> * David Mosberger <davidm@hpl.hp.com> * Copyright (C) 2000, 2002-2003 Intel Co * Asit Mallick <asit.k.mallick@intel.com> * Suresh Siddha <suresh.b.siddha@intel.com> * Kenneth Chen <kenneth.w.chen@intel.com> * Fenghua Yu <fenghua.yu@intel.com> * * 00/08/23 Asit Mallick <asit.k.mallick@intel.com> TLB handling for SMP * 00/12/20 David Mosberger-Tang <davidm@hpl.hp.com> DTLB/ITLB handler now * uses virtual PT. *//* * This file defines the interruption vector table used by the CPU. * It does not include one entry per possible cause of interruption. * * The first 20 entries of the table contain 64 bundles each while the * remaining 48 entries contain only 16 bundles each. * * The 64 bundles are used to allow inlining the whole handler for critical * interruptions like TLB misses. * * For each entry, the comment is as follows: * * // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51) * entry offset ----/ / / / / * entry number ---------/ / / / * size of the entry -------------/ / / * vector name -------------------------------------/ / * interruptions triggering this vector ----------------------/ * * The table is 32KB in size and must be aligned on 32KB boundary. * (The CPU ignores the 15 lower bits of the address) * * Table is based upon EAS2.6 (Oct 1999) */#include <linux/config.h>#include <asm/asmmacro.h>#include <asm/break.h>#include <asm/ia32.h>#include <asm/kregs.h>#include <asm/offsets.h>#include <asm/pgtable.h>#include <asm/processor.h>#include <asm/ptrace.h>#include <asm/system.h>#include <asm/thread_info.h>#include <asm/unistd.h>#include <xen/errno.h>#if 1# define PSR_DEFAULT_BITS psr.ac#else# define PSR_DEFAULT_BITS 0#endif#if 0 /* * This lets you track the last eight faults that occurred on the CPU. * Make sure ar.k2 isn't needed for something else before enabling this... */# define DBG_FAULT(i) \ mov r16=ar.k2;; \ shl r16=r16,8;; \ add r16=(i),r16;; \ mov ar.k2=r16#else# define DBG_FAULT(i)#endif#define MINSTATE_VIRT /* needed by minstate.h */#include "minstate.h"#define FAULT(n) \ mov r19=n; /* prepare to save predicates */ \ mov r31=pr; \ br.sptk.many dispatch_to_fault_handler#define FAULT_OR_REFLECT(n) \ mov r20=cr.ipsr; \ mov r19=n; /* prepare to save predicates */ \ mov r31=pr;; \ extr.u r20=r20,IA64_PSR_CPL0_BIT,2;; \ cmp.ne p6,p0=r0,r20; /* cpl != 0?*/ \(p6) br.dptk.many dispatch_reflection; \ br.sptk.few dispatch_to_fault_handler .section .text.ivt,"ax" .align 32768 // align on 32KB boundary .global ia64_ivtia64_ivt://////////////////////////////////////////////////////////////////////////// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)ENTRY(vhpt_miss) DBG_FAULT(0) FAULT(0)END(vhpt_miss) .org ia64_ivt+0x400//////////////////////////////////////////////////////////////////////////// 0x0400 Entry 1 (size 64 bundles) ITLB (21)ENTRY(itlb_miss) DBG_FAULT(1) mov r16 = cr.ifa mov r31 = pr ;; extr.u r17=r16,59,5 ;; /* If address belongs to VMM, go to alt tlb handler */ cmp.eq p6,p0=0x1e,r17(p6) br.cond.spnt late_alt_itlb_miss br.cond.sptk fast_tlb_miss_reflect ;;END(itlb_miss) .org ia64_ivt+0x0800//////////////////////////////////////////////////////////////////////////// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)ENTRY(dtlb_miss) DBG_FAULT(2) mov r16=cr.ifa // get virtual address mov r31=pr ;; extr.u r17=r16,59,5 ;; /* If address belongs to VMM, go to alt tlb handler */ cmp.eq p6,p0=0x1e,r17(p6) br.cond.spnt late_alt_dtlb_miss br.cond.sptk fast_tlb_miss_reflect ;;END(dtlb_miss) .org ia64_ivt+0x0c00//////////////////////////////////////////////////////////////////////////// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)ENTRY(alt_itlb_miss) DBG_FAULT(3) mov r16=cr.ifa // get address that caused the TLB miss mov r31=pr ;;late_alt_itlb_miss: mov r21=cr.ipsr movl r17=PAGE_KERNEL movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff) ;; mov r20=cr.itir extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl and r19=r19,r16 // clear ed, reserved bits, and PTE ctrl bits extr.u r18=r16,XEN_VIRT_UC_BIT,1 // extract UC bit ;; cmp.ne p8,p0=r0,r23 // psr.cpl != 0? or r19=r17,r19 // insert PTE control bits into r19 dep r20=0,r20,IA64_ITIR_KEY,IA64_ITIR_KEY_LEN // clear the key ;; dep r19=r18,r19,4,1 // set bit 4 (uncached) if access to UC area. mov cr.itir=r20 // set itir with cleared key(p8) br.cond.spnt page_fault ;; itc.i r19 // insert the TLB entry mov pr=r31,-1 rfiEND(alt_itlb_miss) .org ia64_ivt+0x1000//////////////////////////////////////////////////////////////////////////// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)ENTRY(alt_dtlb_miss) DBG_FAULT(4) mov r16=cr.ifa // get address that caused the TLB miss mov r31=pr ;;late_alt_dtlb_miss: mov r20=cr.isr movl r17=PAGE_KERNEL mov r21=cr.ipsr movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff) ;; extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl and r22=IA64_ISR_CODE_MASK,r20 // get the isr.code field tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on? extr.u r18=r16,XEN_VIRT_UC_BIT,1 // extract UC bit and r19=r19,r16 // clear ed, reserved bits, and // PTE control bits tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on? ;; cmp.ne p8,p0=r0,r23(p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field(p8) br.cond.spnt page_fault ;; mov r20=cr.itir#ifdef CONFIG_VIRTUAL_FRAME_TABLE shr r22=r16,56 // Test for the address of virtual frame_table ;; cmp.eq p8,p0=((VIRT_FRAME_TABLE_ADDR>>56)&0xff)-0x100,r22(p8) br.cond.sptk frametable_miss ;;#endif // If it is not a Xen address, handle it via page_fault. extr.u r22=r16,59,5 ;; dep r20=0,r20,IA64_ITIR_KEY,IA64_ITIR_KEY_LEN // clear the key cmp.ne p8,p0=0x1e,r22(p8) br.cond.sptk page_fault ;; dep r21=-1,r21,IA64_PSR_ED_BIT,1 or r19=r19,r17 // insert PTE control bits into r19 mov cr.itir=r20 // set itir with cleared key ;; dep r19=r18,r19,4,1 // set bit 4 (uncached) if access to UC area(p6) mov cr.ipsr=r21 ;;(p7) itc.d r19 // insert the TLB entry mov pr=r31,-1 rfiEND(alt_dtlb_miss)#ifdef CONFIG_VIRTUAL_FRAME_TABLE GLOBAL_ENTRY(frametable_miss) rsm psr.dt // switch to using physical data addressing movl r24=(frametable_pg_dir-PAGE_OFFSET) // r24=__pa(frametable_pg_dir) ;; srlz.d extr.u r17=r16,PGDIR_SHIFT,(PAGE_SHIFT-3) ;; shladd r24=r17,3,r24 // r24=&pgd[pgd_offset(addr)] ;; ld8 r24=[r24] // r24=pgd[pgd_offset(addr)] extr.u r18=r16,PMD_SHIFT,(PAGE_SHIFT-3) // r18=pmd_offset ;; cmp.eq p6,p7=0,r24 // pgd present? shladd r24=r18,3,r24 // r24=&pmd[pmd_offset(addr)] ;;(p7) ld8 r24=[r24] // r24=pmd[pmd_offset(addr)] extr.u r19=r16,PAGE_SHIFT,(PAGE_SHIFT-3)// r19=pte_offset(p6) br.spnt.few frametable_fault ;; cmp.eq p6,p7=0,r24 // pmd present? shladd r24=r19,3,r24 // r24=&pte[pte_offset(addr)] ;;(p7) ld8 r24=[r24] // r24=pte[pte_offset(addr)] mov r25=(PAGE_SHIFT<<IA64_ITIR_PS)(p6) br.spnt.few frametable_fault ;; mov cr.itir=r25 ssm psr.dt // switch to using virtual data addressing tbit.z p6,p7=r24,_PAGE_P_BIT // pte present? ;;(p7) itc.d r24 // install updated PTE(p6) br.spnt.few frametable_fault // page present bit cleared? ;; mov pr=r31,-1 // restore predicate registers rfiEND(frametable_miss)ENTRY(frametable_fault) ssm psr.dt // switch to using virtual data addressing mov r18=cr.iip movl r19=ia64_frametable_probe ;; cmp.eq p6,p7=r18,r19 // is faulting addrress ia64_frametable_probe? mov r8=0 // assumes that 'probe.r' uses r8 dep r21=-1,r21,IA64_PSR_RI_BIT+1,1 // return to next instruction in // bundle 2 ;;(p6) mov cr.ipsr=r21 mov r19=4 // FAULT(4)(p7) br.spnt.few dispatch_to_fault_handler ;; mov pr=r31,-1 rfiEND(frametable_fault)GLOBAL_ENTRY(ia64_frametable_probe) { probe.r r8=r32,0 // destination register must be r8 nop.f 0x0 br.ret.sptk.many b0 // this instruction must be in bundle 2 }END(ia64_frametable_probe)#endif /* CONFIG_VIRTUAL_FRAME_TABLE */ .org ia64_ivt+0x1400/////////////////////////////////////////////////////////////////////////////////////////// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)ENTRY(nested_dtlb_miss) DBG_FAULT(5) mov b0=r30 br.sptk.many b0 // return to the continuation point ;;END(nested_dtlb_miss)GLOBAL_ENTRY(dispatch_reflection) /* * Input: * psr.ic: off * r19: intr type (offset into ivt, see ia64_int.h) * r31: contains saved predicates (pr) */ SAVE_MIN_WITH_COVER_R19 alloc r14=ar.pfs,0,0,5,0 mov out4=r15 mov out0=cr.ifa adds out1=16,sp mov out2=cr.isr mov out3=cr.iim 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 ;; SAVE_REST movl r14=ia64_leave_kernel ;; mov rp=r14// br.sptk.many ia64_prepare_handle_reflection // TODO: why commented out? br.call.sptk.many b6=ia64_handle_reflectionEND(dispatch_reflection) .org ia64_ivt+0x1800//////////////////////////////////////////////////////////////////////////// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)ENTRY(ikey_miss) DBG_FAULT(6) FAULT_OR_REFLECT(6)END(ikey_miss) //---------------------------------------------------------------- // call do_page_fault (predicates are in r31, psr.dt may be off, // r16 is faulting address)GLOBAL_ENTRY(page_fault) ssm psr.dt ;; srlz.i ;; SAVE_MIN_WITH_COVER alloc r15=ar.pfs,0,0,4,0 mov out0=cr.ifa mov out1=cr.isr mov out3=cr.itir adds r3=8,r2 // set up second base pointer ;; ssm psr.ic | PSR_DEFAULT_BITS ;; srlz.i // guarantee that interruption // collection 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) .org ia64_ivt+0x1c00//////////////////////////////////////////////////////////////////////////// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)ENTRY(dkey_miss) DBG_FAULT(7) FAULT_OR_REFLECT(7)END(dkey_miss) .org ia64_ivt+0x2000//////////////////////////////////////////////////////////////////////////// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)ENTRY(dirty_bit) DBG_FAULT(8) mov r20=cr.ipsr mov r31=pr ;; extr.u r20=r20,IA64_PSR_CPL0_BIT,2 ;; mov r19=8 // prepare to save predicates cmp.eq p6,p0=r0,r20 // cpl == 0?(p6) br.sptk.few dispatch_to_fault_handler // If shadow mode is not enabled, reflect the fault. movl r22=THIS_CPU(cpu_kr)+IA64_KR_CURRENT_OFFSET ;; ld8 r22=[r22] ;; add r22=IA64_VCPU_DOMAIN_OFFSET,r22 ;; ld8 r22=[r22] // read domain ;; add r22=IA64_DOMAIN_SHADOW_BITMAP_OFFSET,r22 ;; ld8 r22=[r22] ;; cmp.eq p6,p0=r0,r22 // !shadow_bitmap ?(p6) br.dptk.many dispatch_reflection SAVE_MIN_WITH_COVER alloc r14=ar.pfs,0,0,4,0 mov out0=cr.ifa mov out1=cr.itir mov out2=cr.isr adds out3=16,sp 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 ;; SAVE_REST movl r14=ia64_leave_kernel ;; mov rp=r14 br.call.sptk.many b6=ia64_shadow_faultEND(dirty_bit) .org ia64_ivt+0x2400//////////////////////////////////////////////////////////////////////////// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)ENTRY(iaccess_bit) DBG_FAULT(9) mov r16=cr.isr mov r17=cr.ifa mov r31=pr mov r19=9 mov r20=0x2400 br.sptk.many fast_access_reflect;;END(iaccess_bit) .org ia64_ivt+0x2800//////////////////////////////////////////////////////////////////////////// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)ENTRY(daccess_bit) DBG_FAULT(10) mov r16=cr.isr mov r17=cr.ifa mov r31=pr mov r19=10 mov r20=0x2800 br.sptk.many fast_access_reflect ;;END(daccess_bit) .org ia64_ivt+0x2c00//////////////////////////////////////////////////////////////////////////// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)ENTRY(break_fault) .body /* * The streamlined system call entry/exit paths only save/restore * the initial part of pt_regs. This implies that the callers of * system-calls must adhere to the normal procedure calling * conventions. * * 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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -