/arch/ia64/kernel/ivt.S
Assembly | 1689 lines | 1561 code | 45 blank | 83 comment | 34 complexity | 4b871dde0387bf86e5bbac9492f5de0c MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
Large files files are truncated, but you can click here to view the full file
- /*
- * arch/ia64/kernel/ivt.S
- *
- * Copyright (C) 1998-2001, 2003, 2005 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.
- *
- * Copyright (C) 2005 Hewlett-Packard Co
- * Dan Magenheimer <dan.magenheimer@hp.com>
- * Xen paravirtualization
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- * VA Linux Systems Japan K.K.
- * pv_ops.
- * Yaozu (Eddie) Dong <eddie.dong@intel.com>
- */
- /*
- * 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 <asm/asmmacro.h>
- #include <asm/break.h>
- #include <asm/kregs.h>
- #include <asm/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 <asm/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
- #include "minstate.h"
- #define FAULT(n) \
- mov r31=pr; \
- mov r19=n;; /* prepare to save predicates */ \
- br.sptk.many dispatch_to_fault_handler
- .section .text..ivt,"ax"
- .align 32768 // align on 32KB boundary
- .global ia64_ivt
- ia64_ivt:
- /////////////////////////////////////////////////////////////////////////////////////////
- // 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
- ENTRY(vhpt_miss)
- DBG_FAULT(0)
- /*
- * The VHPT vector is invoked when the TLB entry for the virtual page table
- * is missing. This happens only as a result of a previous
- * (the "original") TLB miss, which may either be caused by an instruction
- * fetch or a data access (or non-access).
- *
- * What we do here is normal TLB miss handing for the _original_ miss,
- * followed by inserting the TLB entry for the virtual page table page
- * that the VHPT walker was attempting to access. The latter gets
- * inserted as long as page table entry above pte level have valid
- * mappings for the faulting address. The TLB entry for the original
- * miss gets inserted only if the pte entry indicates that the page is
- * present.
- *
- * do_page_fault gets invoked in the following cases:
- * - the faulting virtual address uses unimplemented address bits
- * - the faulting virtual address has no valid page table mapping
- */
- MOV_FROM_IFA(r16) // get address that caused the TLB miss
- #ifdef CONFIG_HUGETLB_PAGE
- movl r18=PAGE_SHIFT
- MOV_FROM_ITIR(r25)
- #endif
- ;;
- RSM_PSR_DT // use physical addressing for data
- mov r31=pr // save the predicate registers
- mov r19=IA64_KR(PT_BASE) // get 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
- ;;
- shr.u r22=r21,3
- #ifdef CONFIG_HUGETLB_PAGE
- extr.u r26=r25,2,6
- ;;
- cmp.ne p8,p0=r18,r26
- sub r27=r26,r18
- ;;
- (p8) dep r25=r18,r25,2,6
- (p8) shr r22=r22,r27
- #endif
- ;;
- cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5?
- shr.u r18=r22,PGDIR_SHIFT // get bottom portion of pgd index bit
- ;;
- (p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
- srlz.d
- LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
- .pred.rel "mutex", p6, p7
- (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=pgd_offset for region 5
- (p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
- cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
- #ifdef CONFIG_PGTABLE_4
- shr.u r28=r22,PUD_SHIFT // shift pud index into position
- #else
- shr.u r18=r22,PMD_SHIFT // shift pmd index into position
- #endif
- ;;
- ld8 r17=[r17] // get *pgd (may be 0)
- ;;
- (p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
- #ifdef CONFIG_PGTABLE_4
- dep r28=r28,r17,3,(PAGE_SHIFT-3) // r28=pud_offset(pgd,addr)
- ;;
- shr.u r18=r22,PMD_SHIFT // shift pmd index into position
- (p7) ld8 r29=[r28] // get *pud (may be 0)
- ;;
- (p7) cmp.eq.or.andcm p6,p7=r29,r0 // was pud_present(*pud) == NULL?
- dep r17=r18,r29,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
- #else
- dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pgd,addr)
- #endif
- ;;
- (p7) ld8 r20=[r17] // get *pmd (may be 0)
- shr.u r19=r22,PAGE_SHIFT // shift pte index into position
- ;;
- (p7) cmp.eq.or.andcm p6,p7=r20,r0 // was pmd_present(*pmd) == NULL?
- dep r21=r19,r20,3,(PAGE_SHIFT-3) // r21=pte_offset(pmd,addr)
- ;;
- (p7) ld8 r18=[r21] // read *pte
- MOV_FROM_ISR(r19) // cr.isr bit 32 tells us if this is an insn miss
- ;;
- (p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared?
- MOV_FROM_IHA(r22) // get the VHPT address that caused the TLB miss
- ;; // avoid RAW on p7
- (p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB miss?
- dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page address
- ;;
- ITC_I_AND_D(p10, p11, r18, r24) // insert the instruction TLB entry and
- // insert the data TLB entry
- (p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault)
- MOV_TO_IFA(r22, r24)
- #ifdef CONFIG_HUGETLB_PAGE
- MOV_TO_ITIR(p8, r25, r24) // change to default page-size for VHPT
- #endif
- /*
- * Now compute and insert the TLB entry for the virtual page table. We never
- * execute in a page table page so there is no need to set the exception deferral
- * bit.
- */
- adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23
- ;;
- ITC_D(p7, r24, r25)
- ;;
- #ifdef CONFIG_SMP
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
- /*
- * Re-check pagetable entry. If they changed, we may have received a ptc.g
- * between reading the pagetable and the "itc". If so, flush the entry we
- * inserted and retry. At this point, we have:
- *
- * r28 = equivalent of pud_offset(pgd, ifa)
- * r17 = equivalent of pmd_offset(pud, ifa)
- * r21 = equivalent of pte_offset(pmd, ifa)
- *
- * r29 = *pud
- * r20 = *pmd
- * r18 = *pte
- */
- ld8 r25=[r21] // read *pte again
- ld8 r26=[r17] // read *pmd again
- #ifdef CONFIG_PGTABLE_4
- ld8 r19=[r28] // read *pud again
- #endif
- cmp.ne p6,p7=r0,r0
- ;;
- cmp.ne.or.andcm p6,p7=r26,r20 // did *pmd change
- #ifdef CONFIG_PGTABLE_4
- cmp.ne.or.andcm p6,p7=r19,r29 // did *pud change
- #endif
- mov r27=PAGE_SHIFT<<2
- ;;
- (p6) ptc.l r22,r27 // purge PTE page translation
- (p7) cmp.ne.or.andcm p6,p7=r25,r18 // did *pte change
- ;;
- (p6) ptc.l r16,r27 // purge translation
- #endif
- mov pr=r31,-1 // restore predicate registers
- RFI
- END(vhpt_miss)
- .org ia64_ivt+0x400