xref: /openbmc/linux/arch/ia64/kernel/ivt.S (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds/*
31da177e4SLinus Torvalds * arch/ia64/kernel/ivt.S
41da177e4SLinus Torvalds *
5060561ffSDavid Mosberger-Tang * Copyright (C) 1998-2001, 2003, 2005 Hewlett-Packard Co
61da177e4SLinus Torvalds *	Stephane Eranian <eranian@hpl.hp.com>
71da177e4SLinus Torvalds *	David Mosberger <davidm@hpl.hp.com>
81da177e4SLinus Torvalds * Copyright (C) 2000, 2002-2003 Intel Co
91da177e4SLinus Torvalds *	Asit Mallick <asit.k.mallick@intel.com>
101da177e4SLinus Torvalds *      Suresh Siddha <suresh.b.siddha@intel.com>
111da177e4SLinus Torvalds *      Kenneth Chen <kenneth.w.chen@intel.com>
121da177e4SLinus Torvalds *      Fenghua Yu <fenghua.yu@intel.com>
131da177e4SLinus Torvalds *
141da177e4SLinus Torvalds * 00/08/23 Asit Mallick <asit.k.mallick@intel.com> TLB handling for SMP
151da177e4SLinus Torvalds * 00/12/20 David Mosberger-Tang <davidm@hpl.hp.com> DTLB/ITLB handler now uses virtual PT.
16498c5170SIsaku Yamahata *
17498c5170SIsaku Yamahata * Copyright (C) 2005 Hewlett-Packard Co
18498c5170SIsaku Yamahata *	Dan Magenheimer <dan.magenheimer@hp.com>
19498c5170SIsaku Yamahata *      Xen paravirtualization
20498c5170SIsaku Yamahata * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
21498c5170SIsaku Yamahata *                    VA Linux Systems Japan K.K.
22498c5170SIsaku Yamahata *                    pv_ops.
23498c5170SIsaku Yamahata *      Yaozu (Eddie) Dong <eddie.dong@intel.com>
241da177e4SLinus Torvalds */
251da177e4SLinus Torvalds/*
261da177e4SLinus Torvalds * This file defines the interruption vector table used by the CPU.
271da177e4SLinus Torvalds * It does not include one entry per possible cause of interruption.
281da177e4SLinus Torvalds *
291da177e4SLinus Torvalds * The first 20 entries of the table contain 64 bundles each while the
301da177e4SLinus Torvalds * remaining 48 entries contain only 16 bundles each.
311da177e4SLinus Torvalds *
321da177e4SLinus Torvalds * The 64 bundles are used to allow inlining the whole handler for critical
331da177e4SLinus Torvalds * interruptions like TLB misses.
341da177e4SLinus Torvalds *
351da177e4SLinus Torvalds *  For each entry, the comment is as follows:
361da177e4SLinus Torvalds *
371da177e4SLinus Torvalds *		// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
381da177e4SLinus Torvalds *  entry offset ----/     /         /                  /          /
391da177e4SLinus Torvalds *  entry number ---------/         /                  /          /
401da177e4SLinus Torvalds *  size of the entry -------------/                  /          /
411da177e4SLinus Torvalds *  vector name -------------------------------------/          /
421da177e4SLinus Torvalds *  interruptions triggering this vector ----------------------/
431da177e4SLinus Torvalds *
441da177e4SLinus Torvalds * The table is 32KB in size and must be aligned on 32KB boundary.
451da177e4SLinus Torvalds * (The CPU ignores the 15 lower bits of the address)
461da177e4SLinus Torvalds *
471da177e4SLinus Torvalds * Table is based upon EAS2.6 (Oct 1999)
481da177e4SLinus Torvalds */
491da177e4SLinus Torvalds
50*ab03e604SMasahiro Yamada#include <linux/export.h>
5165fddcfcSMike Rapoport#include <linux/pgtable.h>
521da177e4SLinus Torvalds#include <asm/asmmacro.h>
531da177e4SLinus Torvalds#include <asm/break.h>
541da177e4SLinus Torvalds#include <asm/kregs.h>
5539e01cb8SSam Ravnborg#include <asm/asm-offsets.h>
561da177e4SLinus Torvalds#include <asm/processor.h>
571da177e4SLinus Torvalds#include <asm/ptrace.h>
581da177e4SLinus Torvalds#include <asm/thread_info.h>
591da177e4SLinus Torvalds#include <asm/unistd.h>
601da177e4SLinus Torvalds#include <asm/errno.h>
611da177e4SLinus Torvalds
62c0b5a64dSTony Luck#if 0
631da177e4SLinus Torvalds# define PSR_DEFAULT_BITS	psr.ac
641da177e4SLinus Torvalds#else
651da177e4SLinus Torvalds# define PSR_DEFAULT_BITS	0
661da177e4SLinus Torvalds#endif
671da177e4SLinus Torvalds
681da177e4SLinus Torvalds#if 0
691da177e4SLinus Torvalds  /*
701da177e4SLinus Torvalds   * This lets you track the last eight faults that occurred on the CPU.  Make sure ar.k2 isn't
711da177e4SLinus Torvalds   * needed for something else before enabling this...
721da177e4SLinus Torvalds   */
731da177e4SLinus Torvalds# define DBG_FAULT(i)	mov r16=ar.k2;;	shl r16=r16,8;;	add r16=(i),r16;;mov ar.k2=r16
741da177e4SLinus Torvalds#else
751da177e4SLinus Torvalds# define DBG_FAULT(i)
761da177e4SLinus Torvalds#endif
771da177e4SLinus Torvalds
781da177e4SLinus Torvalds#include "minstate.h"
791da177e4SLinus Torvalds
801da177e4SLinus Torvalds#define FAULT(n)									\
811da177e4SLinus Torvalds	mov r31=pr;									\
821da177e4SLinus Torvalds	mov r19=n;;			/* prepare to save predicates */		\
831da177e4SLinus Torvalds	br.sptk.many dispatch_to_fault_handler
841da177e4SLinus Torvalds
852b55f367SDenys Vlasenko	.section .text..ivt,"ax"
861da177e4SLinus Torvalds
871da177e4SLinus Torvalds	.align 32768	// align on 32KB boundary
881da177e4SLinus Torvalds	.global ia64_ivt
897d59313fSMasahiro Yamada	EXPORT_SYMBOL(ia64_ivt)
901da177e4SLinus Torvaldsia64_ivt:
911da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
921da177e4SLinus Torvalds// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
931da177e4SLinus TorvaldsENTRY(vhpt_miss)
941da177e4SLinus Torvalds	DBG_FAULT(0)
951da177e4SLinus Torvalds	/*
961da177e4SLinus Torvalds	 * The VHPT vector is invoked when the TLB entry for the virtual page table
971da177e4SLinus Torvalds	 * is missing.  This happens only as a result of a previous
981da177e4SLinus Torvalds	 * (the "original") TLB miss, which may either be caused by an instruction
991da177e4SLinus Torvalds	 * fetch or a data access (or non-access).
1001da177e4SLinus Torvalds	 *
101e8aabc47SChen, Kenneth W	 * What we do here is normal TLB miss handing for the _original_ miss,
102e8aabc47SChen, Kenneth W	 * followed by inserting the TLB entry for the virtual page table page
103e8aabc47SChen, Kenneth W	 * that the VHPT walker was attempting to access.  The latter gets
104e8aabc47SChen, Kenneth W	 * inserted as long as page table entry above pte level have valid
105e8aabc47SChen, Kenneth W	 * mappings for the faulting address.  The TLB entry for the original
106e8aabc47SChen, Kenneth W	 * miss gets inserted only if the pte entry indicates that the page is
107e8aabc47SChen, Kenneth W	 * present.
1081da177e4SLinus Torvalds	 *
1091da177e4SLinus Torvalds	 * do_page_fault gets invoked in the following cases:
1101da177e4SLinus Torvalds	 *	- the faulting virtual address uses unimplemented address bits
111e8aabc47SChen, Kenneth W	 *	- the faulting virtual address has no valid page table mapping
1121da177e4SLinus Torvalds	 */
113498c5170SIsaku Yamahata	MOV_FROM_IFA(r16)			// get address that caused the TLB miss
1141da177e4SLinus Torvalds#ifdef CONFIG_HUGETLB_PAGE
1151da177e4SLinus Torvalds	movl r18=PAGE_SHIFT
116498c5170SIsaku Yamahata	MOV_FROM_ITIR(r25)
1171da177e4SLinus Torvalds#endif
1181da177e4SLinus Torvalds	;;
119498c5170SIsaku Yamahata	RSM_PSR_DT				// use physical addressing for data
1201da177e4SLinus Torvalds	mov r31=pr				// save the predicate registers
1211da177e4SLinus Torvalds	mov r19=IA64_KR(PT_BASE)		// get page table base address
1221da177e4SLinus Torvalds	shl r21=r16,3				// shift bit 60 into sign bit
1231da177e4SLinus Torvalds	shr.u r17=r16,61			// get the region number into r17
1241da177e4SLinus Torvalds	;;
125837cd0bdSRobin Holt	shr.u r22=r21,3
1261da177e4SLinus Torvalds#ifdef CONFIG_HUGETLB_PAGE
1271da177e4SLinus Torvalds	extr.u r26=r25,2,6
1281da177e4SLinus Torvalds	;;
1291da177e4SLinus Torvalds	cmp.ne p8,p0=r18,r26
1301da177e4SLinus Torvalds	sub r27=r26,r18
1311da177e4SLinus Torvalds	;;
1321da177e4SLinus Torvalds(p8)	dep r25=r18,r25,2,6
1331da177e4SLinus Torvalds(p8)	shr r22=r22,r27
1341da177e4SLinus Torvalds#endif
1351da177e4SLinus Torvalds	;;
1361da177e4SLinus Torvalds	cmp.eq p6,p7=5,r17			// is IFA pointing into to region 5?
137e8aabc47SChen, Kenneth W	shr.u r18=r22,PGDIR_SHIFT		// get bottom portion of pgd index bit
1381da177e4SLinus Torvalds	;;
1391da177e4SLinus Torvalds(p7)	dep r17=r17,r19,(PAGE_SHIFT-3),3	// put region number bits in place
1401da177e4SLinus Torvalds
1411da177e4SLinus Torvalds	srlz.d
1421da177e4SLinus Torvalds	LOAD_PHYSICAL(p6, r19, swapper_pg_dir)	// region 5 is rooted at swapper_pg_dir
1431da177e4SLinus Torvalds
1441da177e4SLinus Torvalds	.pred.rel "mutex", p6, p7
1451da177e4SLinus Torvalds(p6)	shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
1461da177e4SLinus Torvalds(p7)	shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
1471da177e4SLinus Torvalds	;;
148e8aabc47SChen, Kenneth W(p6)	dep r17=r18,r19,3,(PAGE_SHIFT-3)	// r17=pgd_offset for region 5
149e8aabc47SChen, Kenneth W(p7)	dep r17=r18,r17,3,(PAGE_SHIFT-6)	// r17=pgd_offset for region[0-4]
1501da177e4SLinus Torvalds	cmp.eq p7,p6=0,r21			// unused address bits all zeroes?
1514d66bcc7SKirill A. Shutemov#if CONFIG_PGTABLE_LEVELS == 4
152e8aabc47SChen, Kenneth W	shr.u r28=r22,PUD_SHIFT			// shift pud index into position
153837cd0bdSRobin Holt#else
154e8aabc47SChen, Kenneth W	shr.u r18=r22,PMD_SHIFT			// shift pmd index into position
155837cd0bdSRobin Holt#endif
1561da177e4SLinus Torvalds	;;
157e8aabc47SChen, Kenneth W	ld8 r17=[r17]				// get *pgd (may be 0)
1581da177e4SLinus Torvalds	;;
159e8aabc47SChen, Kenneth W(p7)	cmp.eq p6,p7=r17,r0			// was pgd_present(*pgd) == NULL?
1604d66bcc7SKirill A. Shutemov#if CONFIG_PGTABLE_LEVELS == 4
161e8aabc47SChen, Kenneth W	dep r28=r28,r17,3,(PAGE_SHIFT-3)	// r28=pud_offset(pgd,addr)
1621da177e4SLinus Torvalds	;;
163e8aabc47SChen, Kenneth W	shr.u r18=r22,PMD_SHIFT			// shift pmd index into position
164e8aabc47SChen, Kenneth W(p7)	ld8 r29=[r28]				// get *pud (may be 0)
1651da177e4SLinus Torvalds	;;
166e8aabc47SChen, Kenneth W(p7)	cmp.eq.or.andcm p6,p7=r29,r0		// was pud_present(*pud) == NULL?
167e8aabc47SChen, Kenneth W	dep r17=r18,r29,3,(PAGE_SHIFT-3)	// r17=pmd_offset(pud,addr)
168837cd0bdSRobin Holt#else
169e8aabc47SChen, Kenneth W	dep r17=r18,r17,3,(PAGE_SHIFT-3)	// r17=pmd_offset(pgd,addr)
170837cd0bdSRobin Holt#endif
1711da177e4SLinus Torvalds	;;
172e8aabc47SChen, Kenneth W(p7)	ld8 r20=[r17]				// get *pmd (may be 0)
173e8aabc47SChen, Kenneth W	shr.u r19=r22,PAGE_SHIFT		// shift pte index into position
174837cd0bdSRobin Holt	;;
175e8aabc47SChen, Kenneth W(p7)	cmp.eq.or.andcm p6,p7=r20,r0		// was pmd_present(*pmd) == NULL?
176e8aabc47SChen, Kenneth W	dep r21=r19,r20,3,(PAGE_SHIFT-3)	// r21=pte_offset(pmd,addr)
177837cd0bdSRobin Holt	;;
178e8aabc47SChen, Kenneth W(p7)	ld8 r18=[r21]				// read *pte
179498c5170SIsaku Yamahata	MOV_FROM_ISR(r19)			// cr.isr bit 32 tells us if this is an insn miss
1801da177e4SLinus Torvalds	;;
1811da177e4SLinus Torvalds(p7)	tbit.z p6,p7=r18,_PAGE_P_BIT		// page present bit cleared?
182498c5170SIsaku Yamahata	MOV_FROM_IHA(r22)			// get the VHPT address that caused the TLB miss
1831da177e4SLinus Torvalds	;;					// avoid RAW on p7
1841da177e4SLinus Torvalds(p7)	tbit.nz.unc p10,p11=r19,32		// is it an instruction TLB miss?
1851da177e4SLinus Torvalds	dep r23=0,r20,0,PAGE_SHIFT		// clear low bits to get page address
1861da177e4SLinus Torvalds	;;
187498c5170SIsaku Yamahata	ITC_I_AND_D(p10, p11, r18, r24)		// insert the instruction TLB entry and
188498c5170SIsaku Yamahata						// insert the data TLB entry
1891da177e4SLinus Torvalds(p6)	br.cond.spnt.many page_fault		// handle bad address/page not present (page fault)
190498c5170SIsaku Yamahata	MOV_TO_IFA(r22, r24)
1911da177e4SLinus Torvalds
1921da177e4SLinus Torvalds#ifdef CONFIG_HUGETLB_PAGE
193498c5170SIsaku Yamahata	MOV_TO_ITIR(p8, r25, r24)		// change to default page-size for VHPT
1941da177e4SLinus Torvalds#endif
1951da177e4SLinus Torvalds
1961da177e4SLinus Torvalds	/*
1971da177e4SLinus Torvalds	 * Now compute and insert the TLB entry for the virtual page table.  We never
1981da177e4SLinus Torvalds	 * execute in a page table page so there is no need to set the exception deferral
1991da177e4SLinus Torvalds	 * bit.
2001da177e4SLinus Torvalds	 */
2011da177e4SLinus Torvalds	adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23
2021da177e4SLinus Torvalds	;;
203498c5170SIsaku Yamahata	ITC_D(p7, r24, r25)
2041da177e4SLinus Torvalds	;;
2051da177e4SLinus Torvalds#ifdef CONFIG_SMP
2061da177e4SLinus Torvalds	/*
2071da177e4SLinus Torvalds	 * Tell the assemblers dependency-violation checker that the above "itc" instructions
2081da177e4SLinus Torvalds	 * cannot possibly affect the following loads:
2091da177e4SLinus Torvalds	 */
2101da177e4SLinus Torvalds	dv_serialize_data
2111da177e4SLinus Torvalds
2121da177e4SLinus Torvalds	/*
213e8aabc47SChen, Kenneth W	 * Re-check pagetable entry.  If they changed, we may have received a ptc.g
2141da177e4SLinus Torvalds	 * between reading the pagetable and the "itc".  If so, flush the entry we
215e8aabc47SChen, Kenneth W	 * inserted and retry.  At this point, we have:
216e8aabc47SChen, Kenneth W	 *
217e8aabc47SChen, Kenneth W	 * r28 = equivalent of pud_offset(pgd, ifa)
218e8aabc47SChen, Kenneth W	 * r17 = equivalent of pmd_offset(pud, ifa)
219e8aabc47SChen, Kenneth W	 * r21 = equivalent of pte_offset(pmd, ifa)
220e8aabc47SChen, Kenneth W	 *
221e8aabc47SChen, Kenneth W	 * r29 = *pud
222e8aabc47SChen, Kenneth W	 * r20 = *pmd
223e8aabc47SChen, Kenneth W	 * r18 = *pte
2241da177e4SLinus Torvalds	 */
225e8aabc47SChen, Kenneth W	ld8 r25=[r21]				// read *pte again
226e8aabc47SChen, Kenneth W	ld8 r26=[r17]				// read *pmd again
2274d66bcc7SKirill A. Shutemov#if CONFIG_PGTABLE_LEVELS == 4
228e8aabc47SChen, Kenneth W	ld8 r19=[r28]				// read *pud again
229837cd0bdSRobin Holt#endif
230837cd0bdSRobin Holt	cmp.ne p6,p7=r0,r0
2311da177e4SLinus Torvalds	;;
232e8aabc47SChen, Kenneth W	cmp.ne.or.andcm p6,p7=r26,r20		// did *pmd change
2334d66bcc7SKirill A. Shutemov#if CONFIG_PGTABLE_LEVELS == 4
234e8aabc47SChen, Kenneth W	cmp.ne.or.andcm p6,p7=r19,r29		// did *pud change
235837cd0bdSRobin Holt#endif
2361da177e4SLinus Torvalds	mov r27=PAGE_SHIFT<<2
2371da177e4SLinus Torvalds	;;
2381da177e4SLinus Torvalds(p6)	ptc.l r22,r27				// purge PTE page translation
239e8aabc47SChen, Kenneth W(p7)	cmp.ne.or.andcm p6,p7=r25,r18		// did *pte change
2401da177e4SLinus Torvalds	;;
2411da177e4SLinus Torvalds(p6)	ptc.l r16,r27				// purge translation
2421da177e4SLinus Torvalds#endif
2431da177e4SLinus Torvalds
2441da177e4SLinus Torvalds	mov pr=r31,-1				// restore predicate registers
245498c5170SIsaku Yamahata	RFI
2461da177e4SLinus TorvaldsEND(vhpt_miss)
2471da177e4SLinus Torvalds
2481da177e4SLinus Torvalds	.org ia64_ivt+0x400
2491da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
2501da177e4SLinus Torvalds// 0x0400 Entry 1 (size 64 bundles) ITLB (21)
2511da177e4SLinus TorvaldsENTRY(itlb_miss)
2521da177e4SLinus Torvalds	DBG_FAULT(1)
2531da177e4SLinus Torvalds	/*
254e8aabc47SChen, Kenneth W	 * The ITLB handler accesses the PTE via the virtually mapped linear
2551da177e4SLinus Torvalds	 * page table.  If a nested TLB miss occurs, we switch into physical
256e8aabc47SChen, Kenneth W	 * mode, walk the page table, and then re-execute the PTE read and
257e8aabc47SChen, Kenneth W	 * go on normally after that.
2581da177e4SLinus Torvalds	 */
259498c5170SIsaku Yamahata	MOV_FROM_IFA(r16)			// get virtual address
2601da177e4SLinus Torvalds	mov r29=b0				// save b0
2611da177e4SLinus Torvalds	mov r31=pr				// save predicates
2621da177e4SLinus Torvalds.itlb_fault:
263498c5170SIsaku Yamahata	MOV_FROM_IHA(r17)			// get virtual address of PTE
2641da177e4SLinus Torvalds	movl r30=1f				// load nested fault continuation point
2651da177e4SLinus Torvalds	;;
266e8aabc47SChen, Kenneth W1:	ld8 r18=[r17]				// read *pte
2671da177e4SLinus Torvalds	;;
2681da177e4SLinus Torvalds	mov b0=r29
2691da177e4SLinus Torvalds	tbit.z p6,p0=r18,_PAGE_P_BIT		// page present bit cleared?
2701da177e4SLinus Torvalds(p6)	br.cond.spnt page_fault
2711da177e4SLinus Torvalds	;;
272498c5170SIsaku Yamahata	ITC_I(p0, r18, r19)
2731da177e4SLinus Torvalds	;;
2741da177e4SLinus Torvalds#ifdef CONFIG_SMP
2751da177e4SLinus Torvalds	/*
2761da177e4SLinus Torvalds	 * Tell the assemblers dependency-violation checker that the above "itc" instructions
2771da177e4SLinus Torvalds	 * cannot possibly affect the following loads:
2781da177e4SLinus Torvalds	 */
2791da177e4SLinus Torvalds	dv_serialize_data
2801da177e4SLinus Torvalds
281e8aabc47SChen, Kenneth W	ld8 r19=[r17]				// read *pte again and see if same
2821da177e4SLinus Torvalds	mov r20=PAGE_SHIFT<<2			// setup page size for purge
2831da177e4SLinus Torvalds	;;
2841da177e4SLinus Torvalds	cmp.ne p7,p0=r18,r19
2851da177e4SLinus Torvalds	;;
2861da177e4SLinus Torvalds(p7)	ptc.l r16,r20
2871da177e4SLinus Torvalds#endif
2881da177e4SLinus Torvalds	mov pr=r31,-1
289498c5170SIsaku Yamahata	RFI
2901da177e4SLinus TorvaldsEND(itlb_miss)
2911da177e4SLinus Torvalds
2921da177e4SLinus Torvalds	.org ia64_ivt+0x0800
2931da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
2941da177e4SLinus Torvalds// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
2951da177e4SLinus TorvaldsENTRY(dtlb_miss)
2961da177e4SLinus Torvalds	DBG_FAULT(2)
2971da177e4SLinus Torvalds	/*
298e8aabc47SChen, Kenneth W	 * The DTLB handler accesses the PTE via the virtually mapped linear
2991da177e4SLinus Torvalds	 * page table.  If a nested TLB miss occurs, we switch into physical
300e8aabc47SChen, Kenneth W	 * mode, walk the page table, and then re-execute the PTE read and
301e8aabc47SChen, Kenneth W	 * go on normally after that.
3021da177e4SLinus Torvalds	 */
303498c5170SIsaku Yamahata	MOV_FROM_IFA(r16)			// get virtual address
3041da177e4SLinus Torvalds	mov r29=b0				// save b0
3051da177e4SLinus Torvalds	mov r31=pr				// save predicates
3061da177e4SLinus Torvaldsdtlb_fault:
307498c5170SIsaku Yamahata	MOV_FROM_IHA(r17)			// get virtual address of PTE
3081da177e4SLinus Torvalds	movl r30=1f				// load nested fault continuation point
3091da177e4SLinus Torvalds	;;
310e8aabc47SChen, Kenneth W1:	ld8 r18=[r17]				// read *pte
3111da177e4SLinus Torvalds	;;
3121da177e4SLinus Torvalds	mov b0=r29
3131da177e4SLinus Torvalds	tbit.z p6,p0=r18,_PAGE_P_BIT		// page present bit cleared?
3141da177e4SLinus Torvalds(p6)	br.cond.spnt page_fault
3151da177e4SLinus Torvalds	;;
316498c5170SIsaku Yamahata	ITC_D(p0, r18, r19)
3171da177e4SLinus Torvalds	;;
3181da177e4SLinus Torvalds#ifdef CONFIG_SMP
3191da177e4SLinus Torvalds	/*
3201da177e4SLinus Torvalds	 * Tell the assemblers dependency-violation checker that the above "itc" instructions
3211da177e4SLinus Torvalds	 * cannot possibly affect the following loads:
3221da177e4SLinus Torvalds	 */
3231da177e4SLinus Torvalds	dv_serialize_data
3241da177e4SLinus Torvalds
325e8aabc47SChen, Kenneth W	ld8 r19=[r17]				// read *pte again and see if same
3261da177e4SLinus Torvalds	mov r20=PAGE_SHIFT<<2			// setup page size for purge
3271da177e4SLinus Torvalds	;;
3281da177e4SLinus Torvalds	cmp.ne p7,p0=r18,r19
3291da177e4SLinus Torvalds	;;
3301da177e4SLinus Torvalds(p7)	ptc.l r16,r20
3311da177e4SLinus Torvalds#endif
3321da177e4SLinus Torvalds	mov pr=r31,-1
333498c5170SIsaku Yamahata	RFI
3341da177e4SLinus TorvaldsEND(dtlb_miss)
3351da177e4SLinus Torvalds
3361da177e4SLinus Torvalds	.org ia64_ivt+0x0c00
3371da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
3381da177e4SLinus Torvalds// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
3391da177e4SLinus TorvaldsENTRY(alt_itlb_miss)
3401da177e4SLinus Torvalds	DBG_FAULT(3)
341498c5170SIsaku Yamahata	MOV_FROM_IFA(r16)	// get address that caused the TLB miss
3421da177e4SLinus Torvalds	movl r17=PAGE_KERNEL
343498c5170SIsaku Yamahata	MOV_FROM_IPSR(p0, r21)
3441da177e4SLinus Torvalds	movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
3451da177e4SLinus Torvalds	mov r31=pr
3461da177e4SLinus Torvalds	;;
3471da177e4SLinus Torvalds#ifdef CONFIG_DISABLE_VHPT
3481da177e4SLinus Torvalds	shr.u r22=r16,61			// get the region number into r21
3491da177e4SLinus Torvalds	;;
3501da177e4SLinus Torvalds	cmp.gt p8,p0=6,r22			// user mode
3511da177e4SLinus Torvalds	;;
352498c5170SIsaku Yamahata	THASH(p8, r17, r16, r23)
3531da177e4SLinus Torvalds	;;
354498c5170SIsaku Yamahata	MOV_TO_IHA(p8, r17, r23)
3551da177e4SLinus Torvalds(p8)	mov r29=b0				// save b0
3561da177e4SLinus Torvalds(p8)	br.cond.dptk .itlb_fault
3571da177e4SLinus Torvalds#endif
3581da177e4SLinus Torvalds	extr.u r23=r21,IA64_PSR_CPL0_BIT,2	// extract psr.cpl
3591da177e4SLinus Torvalds	and r19=r19,r16		// clear ed, reserved bits, and PTE control bits
3601da177e4SLinus Torvalds	shr.u r18=r16,57	// move address bit 61 to bit 4
3611da177e4SLinus Torvalds	;;
3621da177e4SLinus Torvalds	andcm r18=0x10,r18	// bit 4=~address-bit(61)
3631da177e4SLinus Torvalds	cmp.ne p8,p0=r0,r23	// psr.cpl != 0?
3641da177e4SLinus Torvalds	or r19=r17,r19		// insert PTE control bits into r19
3651da177e4SLinus Torvalds	;;
3661da177e4SLinus Torvalds	or r19=r19,r18		// set bit 4 (uncached) if the access was to region 6
3671da177e4SLinus Torvalds(p8)	br.cond.spnt page_fault
3681da177e4SLinus Torvalds	;;
369498c5170SIsaku Yamahata	ITC_I(p0, r19, r18)	// insert the TLB entry
3701da177e4SLinus Torvalds	mov pr=r31,-1
371498c5170SIsaku Yamahata	RFI
3721da177e4SLinus TorvaldsEND(alt_itlb_miss)
3731da177e4SLinus Torvalds
3741da177e4SLinus Torvalds	.org ia64_ivt+0x1000
3751da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
3761da177e4SLinus Torvalds// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
3771da177e4SLinus TorvaldsENTRY(alt_dtlb_miss)
3781da177e4SLinus Torvalds	DBG_FAULT(4)
379498c5170SIsaku Yamahata	MOV_FROM_IFA(r16)	// get address that caused the TLB miss
3801da177e4SLinus Torvalds	movl r17=PAGE_KERNEL
381498c5170SIsaku Yamahata	MOV_FROM_ISR(r20)
3821da177e4SLinus Torvalds	movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
383498c5170SIsaku Yamahata	MOV_FROM_IPSR(p0, r21)
3841da177e4SLinus Torvalds	mov r31=pr
38500b65985SChen, Kenneth W	mov r24=PERCPU_ADDR
3861da177e4SLinus Torvalds	;;
3871da177e4SLinus Torvalds#ifdef CONFIG_DISABLE_VHPT
3881da177e4SLinus Torvalds	shr.u r22=r16,61			// get the region number into r21
3891da177e4SLinus Torvalds	;;
3901da177e4SLinus Torvalds	cmp.gt p8,p0=6,r22			// access to region 0-5
3911da177e4SLinus Torvalds	;;
392498c5170SIsaku Yamahata	THASH(p8, r17, r16, r25)
3931da177e4SLinus Torvalds	;;
394498c5170SIsaku Yamahata	MOV_TO_IHA(p8, r17, r25)
3951da177e4SLinus Torvalds(p8)	mov r29=b0				// save b0
3961da177e4SLinus Torvalds(p8)	br.cond.dptk dtlb_fault
3971da177e4SLinus Torvalds#endif
39800b65985SChen, Kenneth W	cmp.ge p10,p11=r16,r24			// access to per_cpu_data?
39900b65985SChen, Kenneth W	tbit.z p12,p0=r16,61			// access to region 6?
40000b65985SChen, Kenneth W	mov r25=PERCPU_PAGE_SHIFT << 2
40100b65985SChen, Kenneth W	mov r26=PERCPU_PAGE_SIZE
40200b65985SChen, Kenneth W	nop.m 0
40300b65985SChen, Kenneth W	nop.b 0
40400b65985SChen, Kenneth W	;;
40500b65985SChen, Kenneth W(p10)	mov r19=IA64_KR(PER_CPU_DATA)
40600b65985SChen, Kenneth W(p11)	and r19=r19,r16				// clear non-ppn fields
4071da177e4SLinus Torvalds	extr.u r23=r21,IA64_PSR_CPL0_BIT,2	// extract psr.cpl
4081da177e4SLinus Torvalds	and r22=IA64_ISR_CODE_MASK,r20		// get the isr.code field
4091da177e4SLinus Torvalds	tbit.nz p6,p7=r20,IA64_ISR_SP_BIT	// is speculation bit on?
4101da177e4SLinus Torvalds	tbit.nz p9,p0=r20,IA64_ISR_NA_BIT	// is non-access bit on?
4111da177e4SLinus Torvalds	;;
41200b65985SChen, Kenneth W(p10)	sub r19=r19,r26
413498c5170SIsaku Yamahata	MOV_TO_ITIR(p10, r25, r24)
4141da177e4SLinus Torvalds	cmp.ne p8,p0=r0,r23
4151da177e4SLinus Torvalds(p9)	cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22	// check isr.code field
41600b65985SChen, Kenneth W(p12)	dep r17=-1,r17,4,1			// set ma=UC for region 6 addr
4171da177e4SLinus Torvalds(p8)	br.cond.spnt page_fault
4181da177e4SLinus Torvalds
4191da177e4SLinus Torvalds	dep r21=-1,r21,IA64_PSR_ED_BIT,1
4201da177e4SLinus Torvalds	;;
42100b65985SChen, Kenneth W	or r19=r19,r17		// insert PTE control bits into r19
422498c5170SIsaku Yamahata	MOV_TO_IPSR(p6, r21, r24)
4231da177e4SLinus Torvalds	;;
424498c5170SIsaku Yamahata	ITC_D(p7, r19, r18)	// insert the TLB entry
4251da177e4SLinus Torvalds	mov pr=r31,-1
426498c5170SIsaku Yamahata	RFI
4271da177e4SLinus TorvaldsEND(alt_dtlb_miss)
4281da177e4SLinus Torvalds
4291da177e4SLinus Torvalds	.org ia64_ivt+0x1400
4301da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
4311da177e4SLinus Torvalds// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
4321da177e4SLinus TorvaldsENTRY(nested_dtlb_miss)
4331da177e4SLinus Torvalds	/*
4341da177e4SLinus Torvalds	 * In the absence of kernel bugs, we get here when the virtually mapped linear
4351da177e4SLinus Torvalds	 * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction
4361da177e4SLinus Torvalds	 * Access-bit, or Data Access-bit faults).  If the DTLB entry for the virtual page
4371da177e4SLinus Torvalds	 * table is missing, a nested TLB miss fault is triggered and control is
4381da177e4SLinus Torvalds	 * transferred to this point.  When this happens, we lookup the pte for the
4391da177e4SLinus Torvalds	 * faulting address by walking the page table in physical mode and return to the
4401da177e4SLinus Torvalds	 * continuation point passed in register r30 (or call page_fault if the address is
4411da177e4SLinus Torvalds	 * not mapped).
4421da177e4SLinus Torvalds	 *
4431da177e4SLinus Torvalds	 * Input:	r16:	faulting address
4441da177e4SLinus Torvalds	 *		r29:	saved b0
4451da177e4SLinus Torvalds	 *		r30:	continuation address
4461da177e4SLinus Torvalds	 *		r31:	saved pr
4471da177e4SLinus Torvalds	 *
448e8aabc47SChen, Kenneth W	 * Output:	r17:	physical address of PTE of faulting address
4491da177e4SLinus Torvalds	 *		r29:	saved b0
4501da177e4SLinus Torvalds	 *		r30:	continuation address
4511da177e4SLinus Torvalds	 *		r31:	saved pr
4521da177e4SLinus Torvalds	 *
4530393eed5SKen Chen	 * Clobbered:	b0, r18, r19, r21, r22, psr.dt (cleared)
4541da177e4SLinus Torvalds	 */
455498c5170SIsaku Yamahata	RSM_PSR_DT				// switch to using physical data addressing
4561da177e4SLinus Torvalds	mov r19=IA64_KR(PT_BASE)		// get the page table base address
4571da177e4SLinus Torvalds	shl r21=r16,3				// shift bit 60 into sign bit
458498c5170SIsaku Yamahata	MOV_FROM_ITIR(r18)
4591da177e4SLinus Torvalds	;;
4601da177e4SLinus Torvalds	shr.u r17=r16,61			// get the region number into r17
4610393eed5SKen Chen	extr.u r18=r18,2,6			// get the faulting page size
4621da177e4SLinus Torvalds	;;
4631da177e4SLinus Torvalds	cmp.eq p6,p7=5,r17			// is faulting address in region 5?
4640393eed5SKen Chen	add r22=-PAGE_SHIFT,r18			// adjustment for hugetlb address
4650393eed5SKen Chen	add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
4661da177e4SLinus Torvalds	;;
4670393eed5SKen Chen	shr.u r22=r16,r22
4680393eed5SKen Chen	shr.u r18=r16,r18
4691da177e4SLinus Torvalds(p7)	dep r17=r17,r19,(PAGE_SHIFT-3),3	// put region number bits in place
4701da177e4SLinus Torvalds
4711da177e4SLinus Torvalds	srlz.d
4721da177e4SLinus Torvalds	LOAD_PHYSICAL(p6, r19, swapper_pg_dir)	// region 5 is rooted at swapper_pg_dir
4731da177e4SLinus Torvalds
4741da177e4SLinus Torvalds	.pred.rel "mutex", p6, p7
4751da177e4SLinus Torvalds(p6)	shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
4761da177e4SLinus Torvalds(p7)	shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
4771da177e4SLinus Torvalds	;;
478e8aabc47SChen, Kenneth W(p6)	dep r17=r18,r19,3,(PAGE_SHIFT-3)	// r17=pgd_offset for region 5
479e8aabc47SChen, Kenneth W(p7)	dep r17=r18,r17,3,(PAGE_SHIFT-6)	// r17=pgd_offset for region[0-4]
4801da177e4SLinus Torvalds	cmp.eq p7,p6=0,r21			// unused address bits all zeroes?
4814d66bcc7SKirill A. Shutemov#if CONFIG_PGTABLE_LEVELS == 4
482e8aabc47SChen, Kenneth W	shr.u r18=r22,PUD_SHIFT			// shift pud index into position
483837cd0bdSRobin Holt#else
484e8aabc47SChen, Kenneth W	shr.u r18=r22,PMD_SHIFT			// shift pmd index into position
485837cd0bdSRobin Holt#endif
4861da177e4SLinus Torvalds	;;
487e8aabc47SChen, Kenneth W	ld8 r17=[r17]				// get *pgd (may be 0)
4881da177e4SLinus Torvalds	;;
489e8aabc47SChen, Kenneth W(p7)	cmp.eq p6,p7=r17,r0			// was pgd_present(*pgd) == NULL?
490e8aabc47SChen, Kenneth W	dep r17=r18,r17,3,(PAGE_SHIFT-3)	// r17=p[u|m]d_offset(pgd,addr)
4911da177e4SLinus Torvalds	;;
4924d66bcc7SKirill A. Shutemov#if CONFIG_PGTABLE_LEVELS == 4
493e8aabc47SChen, Kenneth W(p7)	ld8 r17=[r17]				// get *pud (may be 0)
494e8aabc47SChen, Kenneth W	shr.u r18=r22,PMD_SHIFT			// shift pmd index into position
4951da177e4SLinus Torvalds	;;
496e8aabc47SChen, Kenneth W(p7)	cmp.eq.or.andcm p6,p7=r17,r0		// was pud_present(*pud) == NULL?
497e8aabc47SChen, Kenneth W	dep r17=r18,r17,3,(PAGE_SHIFT-3)	// r17=pmd_offset(pud,addr)
498837cd0bdSRobin Holt	;;
499837cd0bdSRobin Holt#endif
500e8aabc47SChen, Kenneth W(p7)	ld8 r17=[r17]				// get *pmd (may be 0)
501e8aabc47SChen, Kenneth W	shr.u r19=r22,PAGE_SHIFT		// shift pte index into position
502837cd0bdSRobin Holt	;;
503e8aabc47SChen, Kenneth W(p7)	cmp.eq.or.andcm p6,p7=r17,r0		// was pmd_present(*pmd) == NULL?
504e8aabc47SChen, Kenneth W	dep r17=r19,r17,3,(PAGE_SHIFT-3)	// r17=pte_offset(pmd,addr);
5051da177e4SLinus Torvalds(p6)	br.cond.spnt page_fault
5061da177e4SLinus Torvalds	mov b0=r30
5071da177e4SLinus Torvalds	br.sptk.many b0				// return to continuation point
5081da177e4SLinus TorvaldsEND(nested_dtlb_miss)
5091da177e4SLinus Torvalds
5101da177e4SLinus Torvalds	.org ia64_ivt+0x1800
5111da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
5121da177e4SLinus Torvalds// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
5131da177e4SLinus TorvaldsENTRY(ikey_miss)
5141da177e4SLinus Torvalds	DBG_FAULT(6)
5151da177e4SLinus Torvalds	FAULT(6)
5161da177e4SLinus TorvaldsEND(ikey_miss)
5171da177e4SLinus Torvalds
5181da177e4SLinus Torvalds	.org ia64_ivt+0x1c00
5191da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
5201da177e4SLinus Torvalds// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
5211da177e4SLinus TorvaldsENTRY(dkey_miss)
5221da177e4SLinus Torvalds	DBG_FAULT(7)
5231da177e4SLinus Torvalds	FAULT(7)
5241da177e4SLinus TorvaldsEND(dkey_miss)
5251da177e4SLinus Torvalds
5261da177e4SLinus Torvalds	.org ia64_ivt+0x2000
5271da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
5281da177e4SLinus Torvalds// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
5291da177e4SLinus TorvaldsENTRY(dirty_bit)
5301da177e4SLinus Torvalds	DBG_FAULT(8)
5311da177e4SLinus Torvalds	/*
5321da177e4SLinus Torvalds	 * What we do here is to simply turn on the dirty bit in the PTE.  We need to
5331da177e4SLinus Torvalds	 * update both the page-table and the TLB entry.  To efficiently access the PTE,
5341da177e4SLinus Torvalds	 * we address it through the virtual page table.  Most likely, the TLB entry for
5351da177e4SLinus Torvalds	 * the relevant virtual page table page is still present in the TLB so we can
5361da177e4SLinus Torvalds	 * normally do this without additional TLB misses.  In case the necessary virtual
5371da177e4SLinus Torvalds	 * page table TLB entry isn't present, we take a nested TLB miss hit where we look
5381da177e4SLinus Torvalds	 * up the physical address of the L3 PTE and then continue at label 1 below.
5391da177e4SLinus Torvalds	 */
540498c5170SIsaku Yamahata	MOV_FROM_IFA(r16)			// get the address that caused the fault
5411da177e4SLinus Torvalds	movl r30=1f				// load continuation point in case of nested fault
5421da177e4SLinus Torvalds	;;
543498c5170SIsaku Yamahata	THASH(p0, r17, r16, r18)		// compute virtual address of L3 PTE
5441da177e4SLinus Torvalds	mov r29=b0				// save b0 in case of nested fault
5451da177e4SLinus Torvalds	mov r31=pr				// save pr
5461da177e4SLinus Torvalds#ifdef CONFIG_SMP
5471da177e4SLinus Torvalds	mov r28=ar.ccv				// save ar.ccv
5481da177e4SLinus Torvalds	;;
5491da177e4SLinus Torvalds1:	ld8 r18=[r17]
5501da177e4SLinus Torvalds	;;					// avoid RAW on r18
5511da177e4SLinus Torvalds	mov ar.ccv=r18				// set compare value for cmpxchg
5521da177e4SLinus Torvalds	or r25=_PAGE_D|_PAGE_A,r18		// set the dirty and accessed bits
553d8117ce5SChristoph Lameter	tbit.z p7,p6 = r18,_PAGE_P_BIT		// Check present bit
5541da177e4SLinus Torvalds	;;
555d8117ce5SChristoph Lameter(p6)	cmpxchg8.acq r26=[r17],r25,ar.ccv	// Only update if page is present
5561da177e4SLinus Torvalds	mov r24=PAGE_SHIFT<<2
5571da177e4SLinus Torvalds	;;
558d8117ce5SChristoph Lameter(p6)	cmp.eq p6,p7=r26,r18			// Only compare if page is present
5591da177e4SLinus Torvalds	;;
560498c5170SIsaku Yamahata	ITC_D(p6, r25, r18)			// install updated PTE
5611da177e4SLinus Torvalds	;;
5621da177e4SLinus Torvalds	/*
5631da177e4SLinus Torvalds	 * Tell the assemblers dependency-violation checker that the above "itc" instructions
5641da177e4SLinus Torvalds	 * cannot possibly affect the following loads:
5651da177e4SLinus Torvalds	 */
5661da177e4SLinus Torvalds	dv_serialize_data
5671da177e4SLinus Torvalds
5681da177e4SLinus Torvalds	ld8 r18=[r17]				// read PTE again
5691da177e4SLinus Torvalds	;;
5701da177e4SLinus Torvalds	cmp.eq p6,p7=r18,r25			// is it same as the newly installed
5711da177e4SLinus Torvalds	;;
5721da177e4SLinus Torvalds(p7)	ptc.l r16,r24
5731da177e4SLinus Torvalds	mov b0=r29				// restore b0
5741da177e4SLinus Torvalds	mov ar.ccv=r28
5751da177e4SLinus Torvalds#else
5761da177e4SLinus Torvalds	;;
5771da177e4SLinus Torvalds1:	ld8 r18=[r17]
5781da177e4SLinus Torvalds	;;					// avoid RAW on r18
5791da177e4SLinus Torvalds	or r18=_PAGE_D|_PAGE_A,r18		// set the dirty and accessed bits
5801da177e4SLinus Torvalds	mov b0=r29				// restore b0
5811da177e4SLinus Torvalds	;;
5821da177e4SLinus Torvalds	st8 [r17]=r18				// store back updated PTE
583749da791SIsaku Yamahata	ITC_D(p0, r18, r16)			// install updated PTE
5841da177e4SLinus Torvalds#endif
5851da177e4SLinus Torvalds	mov pr=r31,-1				// restore pr
586498c5170SIsaku Yamahata	RFI
5871da177e4SLinus TorvaldsEND(dirty_bit)
5881da177e4SLinus Torvalds
5891da177e4SLinus Torvalds	.org ia64_ivt+0x2400
5901da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
5911da177e4SLinus Torvalds// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
5921da177e4SLinus TorvaldsENTRY(iaccess_bit)
5931da177e4SLinus Torvalds	DBG_FAULT(9)
5941da177e4SLinus Torvalds	// Like Entry 8, except for instruction access
595498c5170SIsaku Yamahata	MOV_FROM_IFA(r16)			// get the address that caused the fault
5961da177e4SLinus Torvalds	movl r30=1f				// load continuation point in case of nested fault
5971da177e4SLinus Torvalds	mov r31=pr				// save predicates
5981da177e4SLinus Torvalds#ifdef CONFIG_ITANIUM
5991da177e4SLinus Torvalds	/*
6001da177e4SLinus Torvalds	 * Erratum 10 (IFA may contain incorrect address) has "NoFix" status.
6011da177e4SLinus Torvalds	 */
602498c5170SIsaku Yamahata	MOV_FROM_IPSR(p0, r17)
6031da177e4SLinus Torvalds	;;
604498c5170SIsaku Yamahata	MOV_FROM_IIP(r18)
6051da177e4SLinus Torvalds	tbit.z p6,p0=r17,IA64_PSR_IS_BIT	// IA64 instruction set?
6061da177e4SLinus Torvalds	;;
6071da177e4SLinus Torvalds(p6)	mov r16=r18				// if so, use cr.iip instead of cr.ifa
6081da177e4SLinus Torvalds#endif /* CONFIG_ITANIUM */
6091da177e4SLinus Torvalds	;;
610498c5170SIsaku Yamahata	THASH(p0, r17, r16, r18)		// compute virtual address of L3 PTE
6111da177e4SLinus Torvalds	mov r29=b0				// save b0 in case of nested fault)
6121da177e4SLinus Torvalds#ifdef CONFIG_SMP
6131da177e4SLinus Torvalds	mov r28=ar.ccv				// save ar.ccv
6141da177e4SLinus Torvalds	;;
6151da177e4SLinus Torvalds1:	ld8 r18=[r17]
6161da177e4SLinus Torvalds	;;
6171da177e4SLinus Torvalds	mov ar.ccv=r18				// set compare value for cmpxchg
6181da177e4SLinus Torvalds	or r25=_PAGE_A,r18			// set the accessed bit
619d8117ce5SChristoph Lameter	tbit.z p7,p6 = r18,_PAGE_P_BIT	 	// Check present bit
6201da177e4SLinus Torvalds	;;
621d8117ce5SChristoph Lameter(p6)	cmpxchg8.acq r26=[r17],r25,ar.ccv	// Only if page present
6221da177e4SLinus Torvalds	mov r24=PAGE_SHIFT<<2
6231da177e4SLinus Torvalds	;;
624d8117ce5SChristoph Lameter(p6)	cmp.eq p6,p7=r26,r18			// Only if page present
6251da177e4SLinus Torvalds	;;
626498c5170SIsaku Yamahata	ITC_I(p6, r25, r26)			// install updated PTE
6271da177e4SLinus Torvalds	;;
6281da177e4SLinus Torvalds	/*
6291da177e4SLinus Torvalds	 * Tell the assemblers dependency-violation checker that the above "itc" instructions
6301da177e4SLinus Torvalds	 * cannot possibly affect the following loads:
6311da177e4SLinus Torvalds	 */
6321da177e4SLinus Torvalds	dv_serialize_data
6331da177e4SLinus Torvalds
6341da177e4SLinus Torvalds	ld8 r18=[r17]				// read PTE again
6351da177e4SLinus Torvalds	;;
6361da177e4SLinus Torvalds	cmp.eq p6,p7=r18,r25			// is it same as the newly installed
6371da177e4SLinus Torvalds	;;
6381da177e4SLinus Torvalds(p7)	ptc.l r16,r24
6391da177e4SLinus Torvalds	mov b0=r29				// restore b0
6401da177e4SLinus Torvalds	mov ar.ccv=r28
6411da177e4SLinus Torvalds#else /* !CONFIG_SMP */
6421da177e4SLinus Torvalds	;;
6431da177e4SLinus Torvalds1:	ld8 r18=[r17]
6441da177e4SLinus Torvalds	;;
6451da177e4SLinus Torvalds	or r18=_PAGE_A,r18			// set the accessed bit
6461da177e4SLinus Torvalds	mov b0=r29				// restore b0
6471da177e4SLinus Torvalds	;;
6481da177e4SLinus Torvalds	st8 [r17]=r18				// store back updated PTE
649749da791SIsaku Yamahata	ITC_I(p0, r18, r16)			// install updated PTE
6501da177e4SLinus Torvalds#endif /* !CONFIG_SMP */
6511da177e4SLinus Torvalds	mov pr=r31,-1
652498c5170SIsaku Yamahata	RFI
6531da177e4SLinus TorvaldsEND(iaccess_bit)
6541da177e4SLinus Torvalds
6551da177e4SLinus Torvalds	.org ia64_ivt+0x2800
6561da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
6571da177e4SLinus Torvalds// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
6581da177e4SLinus TorvaldsENTRY(daccess_bit)
6591da177e4SLinus Torvalds	DBG_FAULT(10)
6601da177e4SLinus Torvalds	// Like Entry 8, except for data access
661498c5170SIsaku Yamahata	MOV_FROM_IFA(r16)			// get the address that caused the fault
6621da177e4SLinus Torvalds	movl r30=1f				// load continuation point in case of nested fault
6631da177e4SLinus Torvalds	;;
664498c5170SIsaku Yamahata	THASH(p0, r17, r16, r18)		// compute virtual address of L3 PTE
6651da177e4SLinus Torvalds	mov r31=pr
6661da177e4SLinus Torvalds	mov r29=b0				// save b0 in case of nested fault)
6671da177e4SLinus Torvalds#ifdef CONFIG_SMP
6681da177e4SLinus Torvalds	mov r28=ar.ccv				// save ar.ccv
6691da177e4SLinus Torvalds	;;
6701da177e4SLinus Torvalds1:	ld8 r18=[r17]
6711da177e4SLinus Torvalds	;;					// avoid RAW on r18
6721da177e4SLinus Torvalds	mov ar.ccv=r18				// set compare value for cmpxchg
6731da177e4SLinus Torvalds	or r25=_PAGE_A,r18			// set the dirty bit
674d8117ce5SChristoph Lameter	tbit.z p7,p6 = r18,_PAGE_P_BIT		// Check present bit
6751da177e4SLinus Torvalds	;;
676d8117ce5SChristoph Lameter(p6)	cmpxchg8.acq r26=[r17],r25,ar.ccv	// Only if page is present
6771da177e4SLinus Torvalds	mov r24=PAGE_SHIFT<<2
6781da177e4SLinus Torvalds	;;
679d8117ce5SChristoph Lameter(p6)	cmp.eq p6,p7=r26,r18			// Only if page is present
6801da177e4SLinus Torvalds	;;
681498c5170SIsaku Yamahata	ITC_D(p6, r25, r26)			// install updated PTE
6821da177e4SLinus Torvalds	/*
6831da177e4SLinus Torvalds	 * Tell the assemblers dependency-violation checker that the above "itc" instructions
6841da177e4SLinus Torvalds	 * cannot possibly affect the following loads:
6851da177e4SLinus Torvalds	 */
6861da177e4SLinus Torvalds	dv_serialize_data
6871da177e4SLinus Torvalds	;;
6881da177e4SLinus Torvalds	ld8 r18=[r17]				// read PTE again
6891da177e4SLinus Torvalds	;;
6901da177e4SLinus Torvalds	cmp.eq p6,p7=r18,r25			// is it same as the newly installed
6911da177e4SLinus Torvalds	;;
6921da177e4SLinus Torvalds(p7)	ptc.l r16,r24
6931da177e4SLinus Torvalds	mov ar.ccv=r28
6941da177e4SLinus Torvalds#else
6951da177e4SLinus Torvalds	;;
6961da177e4SLinus Torvalds1:	ld8 r18=[r17]
6971da177e4SLinus Torvalds	;;					// avoid RAW on r18
6981da177e4SLinus Torvalds	or r18=_PAGE_A,r18			// set the accessed bit
6991da177e4SLinus Torvalds	;;
7001da177e4SLinus Torvalds	st8 [r17]=r18				// store back updated PTE
701749da791SIsaku Yamahata	ITC_D(p0, r18, r16)			// install updated PTE
7021da177e4SLinus Torvalds#endif
7031da177e4SLinus Torvalds	mov b0=r29				// restore b0
7041da177e4SLinus Torvalds	mov pr=r31,-1
705498c5170SIsaku Yamahata	RFI
7061da177e4SLinus TorvaldsEND(daccess_bit)
7071da177e4SLinus Torvalds
7081da177e4SLinus Torvalds	.org ia64_ivt+0x2c00
7091da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
7101da177e4SLinus Torvalds// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
7111da177e4SLinus TorvaldsENTRY(break_fault)
7121da177e4SLinus Torvalds	/*
7131da177e4SLinus Torvalds	 * The streamlined system call entry/exit paths only save/restore the initial part
7141da177e4SLinus Torvalds	 * of pt_regs.  This implies that the callers of system-calls must adhere to the
7151da177e4SLinus Torvalds	 * normal procedure calling conventions.
7161da177e4SLinus Torvalds	 *
7171da177e4SLinus Torvalds	 *   Registers to be saved & restored:
7181da177e4SLinus Torvalds	 *	CR registers: cr.ipsr, cr.iip, cr.ifs
7191da177e4SLinus Torvalds	 *	AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr
7201da177e4SLinus Torvalds	 * 	others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15
7211da177e4SLinus Torvalds	 *   Registers to be restored only:
7221da177e4SLinus Torvalds	 * 	r8-r11: output value from the system call.
7231da177e4SLinus Torvalds	 *
7241da177e4SLinus Torvalds	 * During system call exit, scratch registers (including r15) are modified/cleared
7251da177e4SLinus Torvalds	 * to prevent leaking bits from kernel to user level.
7261da177e4SLinus Torvalds	 */
7271da177e4SLinus Torvalds	DBG_FAULT(11)
728f8fa5448SDavid Mosberger-Tang	mov.m r16=IA64_KR(CURRENT)		// M2 r16 <- current task (12 cyc)
729498c5170SIsaku Yamahata	MOV_FROM_IPSR(p0, r29)			// M2 (12 cyc)
730f8fa5448SDavid Mosberger-Tang	mov r31=pr				// I0 (2 cyc)
731f8fa5448SDavid Mosberger-Tang
732498c5170SIsaku Yamahata	MOV_FROM_IIM(r17)			// M2 (2 cyc)
733f8fa5448SDavid Mosberger-Tang	mov.m r27=ar.rsc			// M2 (12 cyc)
734f8fa5448SDavid Mosberger-Tang	mov r18=__IA64_BREAK_SYSCALL		// A
735f8fa5448SDavid Mosberger-Tang
736f8fa5448SDavid Mosberger-Tang	mov.m ar.rsc=0				// M2
737f8fa5448SDavid Mosberger-Tang	mov.m r21=ar.fpsr			// M2 (12 cyc)
738f8fa5448SDavid Mosberger-Tang	mov r19=b6				// I0 (2 cyc)
7391da177e4SLinus Torvalds	;;
740f8fa5448SDavid Mosberger-Tang	mov.m r23=ar.bspstore			// M2 (12 cyc)
741f8fa5448SDavid Mosberger-Tang	mov.m r24=ar.rnat			// M2 (5 cyc)
742f8fa5448SDavid Mosberger-Tang	mov.i r26=ar.pfs			// I0 (2 cyc)
743f8fa5448SDavid Mosberger-Tang
744f8fa5448SDavid Mosberger-Tang	invala					// M0|1
745f8fa5448SDavid Mosberger-Tang	nop.m 0					// M
746f8fa5448SDavid Mosberger-Tang	mov r20=r1				// A			save r1
747f8fa5448SDavid Mosberger-Tang
748f8fa5448SDavid Mosberger-Tang	nop.m 0
749f8fa5448SDavid Mosberger-Tang	movl r30=sys_call_table			// X
750f8fa5448SDavid Mosberger-Tang
751498c5170SIsaku Yamahata	MOV_FROM_IIP(r28)			// M2 (2 cyc)
752f8fa5448SDavid Mosberger-Tang	cmp.eq p0,p7=r18,r17			// I0 is this a system call?
753f8fa5448SDavid Mosberger-Tang(p7)	br.cond.spnt non_syscall		// B  no ->
754f8fa5448SDavid Mosberger-Tang	//
755f8fa5448SDavid Mosberger-Tang	// From this point on, we are definitely on the syscall-path
756f8fa5448SDavid Mosberger-Tang	// and we can use (non-banked) scratch registers.
757f8fa5448SDavid Mosberger-Tang	//
758f8fa5448SDavid Mosberger-Tang///////////////////////////////////////////////////////////////////////
759f8fa5448SDavid Mosberger-Tang	mov r1=r16				// A    move task-pointer to "addl"-addressable reg
760f8fa5448SDavid Mosberger-Tang	mov r2=r16				// A    setup r2 for ia64_syscall_setup
761f8fa5448SDavid Mosberger-Tang	add r9=TI_FLAGS+IA64_TASK_SIZE,r16	// A	r9 = &current_thread_info()->flags
762f8fa5448SDavid Mosberger-Tang
7631da177e4SLinus Torvalds	adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16
764f8fa5448SDavid Mosberger-Tang	adds r15=-1024,r15			// A    subtract 1024 from syscall number
7651da177e4SLinus Torvalds	mov r3=NR_syscalls - 1
7661da177e4SLinus Torvalds	;;
767f8fa5448SDavid Mosberger-Tang	ld1.bias r17=[r16]			// M0|1 r17 = current->thread.on_ustack flag
768f8fa5448SDavid Mosberger-Tang	ld4 r9=[r9]				// M0|1 r9 = current_thread_info()->flags
769f8fa5448SDavid Mosberger-Tang	extr.u r8=r29,41,2			// I0   extract ei field from cr.ipsr
7701da177e4SLinus Torvalds
771f8fa5448SDavid Mosberger-Tang	shladd r30=r15,3,r30			// A    r30 = sys_call_table + 8*(syscall-1024)
772f8fa5448SDavid Mosberger-Tang	addl r22=IA64_RBS_OFFSET,r1		// A    compute base of RBS
773f8fa5448SDavid Mosberger-Tang	cmp.leu p6,p7=r15,r3			// A    syscall number in range?
7741da177e4SLinus Torvalds	;;
7751da177e4SLinus Torvalds
776f8fa5448SDavid Mosberger-Tang	lfetch.fault.excl.nt1 [r22]		// M0|1 prefetch RBS
777f8fa5448SDavid Mosberger-Tang(p6)	ld8 r30=[r30]				// M0|1 load address of syscall entry point
778f8fa5448SDavid Mosberger-Tang	tnat.nz.or p7,p0=r15			// I0	is syscall nr a NaT?
779f8fa5448SDavid Mosberger-Tang
780f8fa5448SDavid Mosberger-Tang	mov.m ar.bspstore=r22			// M2   switch to kernel RBS
781f8fa5448SDavid Mosberger-Tang	cmp.eq p8,p9=2,r8			// A    isr.ei==2?
7821da177e4SLinus Torvalds	;;
783f8fa5448SDavid Mosberger-Tang
784f8fa5448SDavid Mosberger-Tang(p8)	mov r8=0				// A    clear ei to 0
785f8fa5448SDavid Mosberger-Tang(p7)	movl r30=sys_ni_syscall			// X
786f8fa5448SDavid Mosberger-Tang
787f8fa5448SDavid Mosberger-Tang(p8)	adds r28=16,r28				// A    switch cr.iip to next bundle
788f8fa5448SDavid Mosberger-Tang(p9)	adds r8=1,r8				// A    increment ei to next slot
789abf917cdSFrederic Weisbecker#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
790b64f34cdSHidetoshi Seto	;;
791b64f34cdSHidetoshi Seto	mov b6=r30				// I0   setup syscall handler branch reg early
792b64f34cdSHidetoshi Seto#else
793f8fa5448SDavid Mosberger-Tang	nop.i 0
7941da177e4SLinus Torvalds	;;
795b64f34cdSHidetoshi Seto#endif
796f8fa5448SDavid Mosberger-Tang
797f8fa5448SDavid Mosberger-Tang	mov.m r25=ar.unat			// M2 (5 cyc)
798f8fa5448SDavid Mosberger-Tang	dep r29=r8,r29,41,2			// I0   insert new ei into cr.ipsr
799f8fa5448SDavid Mosberger-Tang	adds r15=1024,r15			// A    restore original syscall number
800f8fa5448SDavid Mosberger-Tang	//
801f8fa5448SDavid Mosberger-Tang	// If any of the above loads miss in L1D, we'll stall here until
802f8fa5448SDavid Mosberger-Tang	// the data arrives.
803f8fa5448SDavid Mosberger-Tang	//
804f8fa5448SDavid Mosberger-Tang///////////////////////////////////////////////////////////////////////
805f8fa5448SDavid Mosberger-Tang	st1 [r16]=r0				// M2|3 clear current->thread.on_ustack flag
806abf917cdSFrederic Weisbecker#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
80794752a79SIsaku Yamahata	MOV_FROM_ITC(p0, p14, r30, r18)		// M    get cycle for accounting
808b64f34cdSHidetoshi Seto#else
809f8fa5448SDavid Mosberger-Tang	mov b6=r30				// I0   setup syscall handler branch reg early
810b64f34cdSHidetoshi Seto#endif
811f8fa5448SDavid Mosberger-Tang	cmp.eq pKStk,pUStk=r0,r17		// A    were we on kernel stacks already?
812f8fa5448SDavid Mosberger-Tang
813f8fa5448SDavid Mosberger-Tang	and r9=_TIF_SYSCALL_TRACEAUDIT,r9	// A    mask trace or audit
814f8fa5448SDavid Mosberger-Tang	mov r18=ar.bsp				// M2 (12 cyc)
815f8fa5448SDavid Mosberger-Tang(pKStk)	br.cond.spnt .break_fixup		// B	we're already in kernel-mode -- fix up RBS
8161da177e4SLinus Torvalds	;;
817f8fa5448SDavid Mosberger-Tang.back_from_break_fixup:
818f8fa5448SDavid Mosberger-Tang(pUStk)	addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1 // A    compute base of memory stack
819f8fa5448SDavid Mosberger-Tang	cmp.eq p14,p0=r9,r0			// A    are syscalls being traced/audited?
820f8fa5448SDavid Mosberger-Tang	br.call.sptk.many b7=ia64_syscall_setup	// B
821f8fa5448SDavid Mosberger-Tang1:
822abf917cdSFrederic Weisbecker#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
823b64f34cdSHidetoshi Seto	// mov.m r30=ar.itc is called in advance, and r13 is current
824b64f34cdSHidetoshi Seto	add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13	// A
825b64f34cdSHidetoshi Seto	add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13	// A
826b64f34cdSHidetoshi Seto(pKStk)	br.cond.spnt .skip_accounting		// B	unlikely skip
827b64f34cdSHidetoshi Seto	;;
828b64f34cdSHidetoshi Seto	ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP	// M  get last stamp
829b64f34cdSHidetoshi Seto	ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE	// M  time at leave
830b64f34cdSHidetoshi Seto	;;
831b64f34cdSHidetoshi Seto	ld8 r20=[r16],TI_AC_STAMP-TI_AC_STIME	// M  cumulated stime
832b64f34cdSHidetoshi Seto	ld8 r21=[r17]				// M  cumulated utime
833b64f34cdSHidetoshi Seto	sub r22=r19,r18				// A  stime before leave
834b64f34cdSHidetoshi Seto	;;
835b64f34cdSHidetoshi Seto	st8 [r16]=r30,TI_AC_STIME-TI_AC_STAMP	// M  update stamp
836b64f34cdSHidetoshi Seto	sub r18=r30,r19				// A  elapsed time in user
837b64f34cdSHidetoshi Seto	;;
838b64f34cdSHidetoshi Seto	add r20=r20,r22				// A  sum stime
839b64f34cdSHidetoshi Seto	add r21=r21,r18				// A  sum utime
840b64f34cdSHidetoshi Seto	;;
841b64f34cdSHidetoshi Seto	st8 [r16]=r20				// M  update stime
842b64f34cdSHidetoshi Seto	st8 [r17]=r21				// M  update utime
843b64f34cdSHidetoshi Seto	;;
844b64f34cdSHidetoshi Seto.skip_accounting:
845b64f34cdSHidetoshi Seto#endif
846f8fa5448SDavid Mosberger-Tang	mov ar.rsc=0x3				// M2   set eager mode, pl 0, LE, loadrs=0
847f8fa5448SDavid Mosberger-Tang	nop 0
848498c5170SIsaku Yamahata	BSW_1(r2, r14)				// B (6 cyc) regs are saved, switch to bank 1
8491da177e4SLinus Torvalds	;;
850f8fa5448SDavid Mosberger-Tang
851498c5170SIsaku Yamahata	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r16)	// M2	now it's safe to re-enable intr.-collection
852498c5170SIsaku Yamahata						// M0   ensure interruption collection is on
853f8fa5448SDavid Mosberger-Tang	movl r3=ia64_ret_from_syscall		// X
854f8fa5448SDavid Mosberger-Tang	;;
855f8fa5448SDavid Mosberger-Tang	mov rp=r3				// I0   set the real return addr
856f8fa5448SDavid Mosberger-Tang(p10)	br.cond.spnt.many ia64_ret_from_syscall	// B    return if bad call-frame or r15 is a NaT
857f8fa5448SDavid Mosberger-Tang
858498c5170SIsaku Yamahata	SSM_PSR_I(p15, p15, r16)		// M2   restore psr.i
859f8fa5448SDavid Mosberger-Tang(p14)	br.call.sptk.many b6=b6			// B    invoke syscall-handker (ignore return addr)
860f8fa5448SDavid Mosberger-Tang	br.cond.spnt.many ia64_trace_syscall	// B	do syscall-tracing thingamagic
8611da177e4SLinus Torvalds	// NOT REACHED
862f8fa5448SDavid Mosberger-Tang///////////////////////////////////////////////////////////////////////
863f8fa5448SDavid Mosberger-Tang	// On entry, we optimistically assumed that we're coming from user-space.
864f8fa5448SDavid Mosberger-Tang	// For the rare cases where a system-call is done from within the kernel,
865f8fa5448SDavid Mosberger-Tang	// we fix things up at this point:
866f8fa5448SDavid Mosberger-Tang.break_fixup:
867f8fa5448SDavid Mosberger-Tang	add r1=-IA64_PT_REGS_SIZE,sp		// A    allocate space for pt_regs structure
868f8fa5448SDavid Mosberger-Tang	mov ar.rnat=r24				// M2	restore kernel's AR.RNAT
869f8fa5448SDavid Mosberger-Tang	;;
870f8fa5448SDavid Mosberger-Tang	mov ar.bspstore=r23			// M2	restore kernel's AR.BSPSTORE
871f8fa5448SDavid Mosberger-Tang	br.cond.sptk .back_from_break_fixup
8721da177e4SLinus TorvaldsEND(break_fault)
8731da177e4SLinus Torvalds
8741da177e4SLinus Torvalds	.org ia64_ivt+0x3000
8751da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
8761da177e4SLinus Torvalds// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
8771da177e4SLinus TorvaldsENTRY(interrupt)
8784d58bbccSIsaku Yamahata	/* interrupt handler has become too big to fit this area. */
8794d58bbccSIsaku Yamahata	br.sptk.many __interrupt
8801da177e4SLinus TorvaldsEND(interrupt)
8811da177e4SLinus Torvalds
8821da177e4SLinus Torvalds	.org ia64_ivt+0x3400
8831da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
8841da177e4SLinus Torvalds// 0x3400 Entry 13 (size 64 bundles) Reserved
8851da177e4SLinus Torvalds	DBG_FAULT(13)
8861da177e4SLinus Torvalds	FAULT(13)
8871da177e4SLinus Torvalds
8881da177e4SLinus Torvalds	.org ia64_ivt+0x3800
8891da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
8901da177e4SLinus Torvalds// 0x3800 Entry 14 (size 64 bundles) Reserved
8911da177e4SLinus Torvalds	DBG_FAULT(14)
8921da177e4SLinus Torvalds	FAULT(14)
8931da177e4SLinus Torvalds
8941da177e4SLinus Torvalds	/*
8951da177e4SLinus Torvalds	 * There is no particular reason for this code to be here, other than that
8961da177e4SLinus Torvalds	 * there happens to be space here that would go unused otherwise.  If this
8971da177e4SLinus Torvalds	 * fault ever gets "unreserved", simply moved the following code to a more
8981da177e4SLinus Torvalds	 * suitable spot...
8991da177e4SLinus Torvalds	 *
9001da177e4SLinus Torvalds	 * ia64_syscall_setup() is a separate subroutine so that it can
9011da177e4SLinus Torvalds	 *	allocate stacked registers so it can safely demine any
9021da177e4SLinus Torvalds	 *	potential NaT values from the input registers.
9031da177e4SLinus Torvalds	 *
9041da177e4SLinus Torvalds	 * On entry:
9051da177e4SLinus Torvalds	 *	- executing on bank 0 or bank 1 register set (doesn't matter)
9061da177e4SLinus Torvalds	 *	-  r1: stack pointer
9071da177e4SLinus Torvalds	 *	-  r2: current task pointer
9081da177e4SLinus Torvalds	 *	-  r3: preserved
9091da177e4SLinus Torvalds	 *	- r11: original contents (saved ar.pfs to be saved)
9101da177e4SLinus Torvalds	 *	- r12: original contents (sp to be saved)
9111da177e4SLinus Torvalds	 *	- r13: original contents (tp to be saved)
9121da177e4SLinus Torvalds	 *	- r15: original contents (syscall # to be saved)
9131da177e4SLinus Torvalds	 *	- r18: saved bsp (after switching to kernel stack)
9141da177e4SLinus Torvalds	 *	- r19: saved b6
9151da177e4SLinus Torvalds	 *	- r20: saved r1 (gp)
9161da177e4SLinus Torvalds	 *	- r21: saved ar.fpsr
9171da177e4SLinus Torvalds	 *	- r22: kernel's register backing store base (krbs_base)
9181da177e4SLinus Torvalds	 *	- r23: saved ar.bspstore
9191da177e4SLinus Torvalds	 *	- r24: saved ar.rnat
9201da177e4SLinus Torvalds	 *	- r25: saved ar.unat
9211da177e4SLinus Torvalds	 *	- r26: saved ar.pfs
9221da177e4SLinus Torvalds	 *	- r27: saved ar.rsc
9231da177e4SLinus Torvalds	 *	- r28: saved cr.iip
9241da177e4SLinus Torvalds	 *	- r29: saved cr.ipsr
925b64f34cdSHidetoshi Seto	 *	- r30: ar.itc for accounting (don't touch)
9261da177e4SLinus Torvalds	 *	- r31: saved pr
9271da177e4SLinus Torvalds	 *	-  b0: original contents (to be saved)
9281da177e4SLinus Torvalds	 * On exit:
9291da177e4SLinus Torvalds	 *	-  p10: TRUE if syscall is invoked with more than 8 out
9301da177e4SLinus Torvalds	 *		registers or r15's Nat is true
9311da177e4SLinus Torvalds	 *	-  r1: kernel's gp
9321da177e4SLinus Torvalds	 *	-  r3: preserved (same as on entry)
9331da177e4SLinus Torvalds	 *	-  r8: -EINVAL if p10 is true
9341da177e4SLinus Torvalds	 *	- r12: points to kernel stack
9351da177e4SLinus Torvalds	 *	- r13: points to current task
936f8fa5448SDavid Mosberger-Tang	 *	- r14: preserved (same as on entry)
937f8fa5448SDavid Mosberger-Tang	 *	- p13: preserved
9381da177e4SLinus Torvalds	 *	- p15: TRUE if interrupts need to be re-enabled
9391da177e4SLinus Torvalds	 *	- ar.fpsr: set to kernel settings
940f8fa5448SDavid Mosberger-Tang	 *	-  b6: preserved (same as on entry)
9411da177e4SLinus Torvalds	 */
9421da177e4SLinus TorvaldsGLOBAL_ENTRY(ia64_syscall_setup)
9431da177e4SLinus Torvalds#if PT(B6) != 0
9441da177e4SLinus Torvalds# error This code assumes that b6 is the first field in pt_regs.
9451da177e4SLinus Torvalds#endif
9461da177e4SLinus Torvalds	st8 [r1]=r19				// save b6
9471da177e4SLinus Torvalds	add r16=PT(CR_IPSR),r1			// initialize first base pointer
9481da177e4SLinus Torvalds	add r17=PT(R11),r1			// initialize second base pointer
9491da177e4SLinus Torvalds	;;
9501da177e4SLinus Torvalds	alloc r19=ar.pfs,8,0,0,0		// ensure in0-in7 are writable
9511da177e4SLinus Torvalds	st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR)	// save cr.ipsr
9521da177e4SLinus Torvalds	tnat.nz p8,p0=in0
9531da177e4SLinus Torvalds
9541da177e4SLinus Torvalds	st8.spill [r17]=r11,PT(CR_IIP)-PT(R11)	// save r11
9551da177e4SLinus Torvalds	tnat.nz p9,p0=in1
9561da177e4SLinus Torvalds(pKStk)	mov r18=r0				// make sure r18 isn't NaT
9571da177e4SLinus Torvalds	;;
9581da177e4SLinus Torvalds
9591da177e4SLinus Torvalds	st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS)	// save ar.pfs
9601da177e4SLinus Torvalds	st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP)	// save cr.iip
9611da177e4SLinus Torvalds	mov r28=b0				// save b0 (2 cyc)
9621da177e4SLinus Torvalds	;;
9631da177e4SLinus Torvalds
9641da177e4SLinus Torvalds	st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT)	// save ar.unat
9651da177e4SLinus Torvalds	dep r19=0,r19,38,26			// clear all bits but 0..37 [I0]
9661da177e4SLinus Torvalds(p8)	mov in0=-1
9671da177e4SLinus Torvalds	;;
9681da177e4SLinus Torvalds
9691da177e4SLinus Torvalds	st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS)	// store ar.pfs.pfm in cr.ifs
9701da177e4SLinus Torvalds	extr.u r11=r19,7,7	// I0		// get sol of ar.pfs
9711da177e4SLinus Torvalds	and r8=0x7f,r19		// A		// get sof of ar.pfs
9721da177e4SLinus Torvalds
9731da177e4SLinus Torvalds	st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc
9741da177e4SLinus Torvalds	tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0
9751da177e4SLinus Torvalds(p9)	mov in1=-1
9761da177e4SLinus Torvalds	;;
9771da177e4SLinus Torvalds
9781da177e4SLinus Torvalds(pUStk) sub r18=r18,r22				// r18=RSE.ndirty*8
9791da177e4SLinus Torvalds	tnat.nz p10,p0=in2
9801da177e4SLinus Torvalds	add r11=8,r11
9811da177e4SLinus Torvalds	;;
9821da177e4SLinus Torvalds(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16		// skip over ar_rnat field
9831da177e4SLinus Torvalds(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17	// skip over ar_bspstore field
9841da177e4SLinus Torvalds	tnat.nz p11,p0=in3
9851da177e4SLinus Torvalds	;;
9861da177e4SLinus Torvalds(p10)	mov in2=-1
9871da177e4SLinus Torvalds	tnat.nz p12,p0=in4				// [I0]
9881da177e4SLinus Torvalds(p11)	mov in3=-1
9891da177e4SLinus Torvalds	;;
9901da177e4SLinus Torvalds(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT)	// save ar.rnat
9911da177e4SLinus Torvalds(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE)	// save ar.bspstore
9921da177e4SLinus Torvalds	shl r18=r18,16				// compute ar.rsc to be used for "loadrs"
9931da177e4SLinus Torvalds	;;
9941da177e4SLinus Torvalds	st8 [r16]=r31,PT(LOADRS)-PT(PR)		// save predicates
9951da177e4SLinus Torvalds	st8 [r17]=r28,PT(R1)-PT(B0)		// save b0
9961da177e4SLinus Torvalds	tnat.nz p13,p0=in5				// [I0]
9971da177e4SLinus Torvalds	;;
9981da177e4SLinus Torvalds	st8 [r16]=r18,PT(R12)-PT(LOADRS)	// save ar.rsc value for "loadrs"
9991da177e4SLinus Torvalds	st8.spill [r17]=r20,PT(R13)-PT(R1)	// save original r1
10001da177e4SLinus Torvalds(p12)	mov in4=-1
10011da177e4SLinus Torvalds	;;
10021da177e4SLinus Torvalds
10031da177e4SLinus Torvalds.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12)	// save r12
10041da177e4SLinus Torvalds.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13)		// save r13
10051da177e4SLinus Torvalds(p13)	mov in5=-1
10061da177e4SLinus Torvalds	;;
10071da177e4SLinus Torvalds	st8 [r16]=r21,PT(R8)-PT(AR_FPSR)	// save ar.fpsr
1008f8fa5448SDavid Mosberger-Tang	tnat.nz p13,p0=in6
10091da177e4SLinus Torvalds	cmp.lt p10,p9=r11,r8	// frame size can't be more than local+8
10101da177e4SLinus Torvalds	;;
1011060561ffSDavid Mosberger-Tang	mov r8=1
10121da177e4SLinus Torvalds(p9)	tnat.nz p10,p0=r15
10131da177e4SLinus Torvalds	adds r12=-16,r1		// switch to kernel memory stack (with 16 bytes of scratch)
10141da177e4SLinus Torvalds
10151da177e4SLinus Torvalds	st8.spill [r17]=r15			// save r15
10161da177e4SLinus Torvalds	tnat.nz p8,p0=in7
10171da177e4SLinus Torvalds	nop.i 0
10181da177e4SLinus Torvalds
10191da177e4SLinus Torvalds	mov r13=r2				// establish `current'
10201da177e4SLinus Torvalds	movl r1=__gp				// establish kernel global pointer
10211da177e4SLinus Torvalds	;;
1022060561ffSDavid Mosberger-Tang	st8 [r16]=r8		// ensure pt_regs.r8 != 0 (see handle_syscall_error)
1023f8fa5448SDavid Mosberger-Tang(p13)	mov in6=-1
10241da177e4SLinus Torvalds(p8)	mov in7=-1
10251da177e4SLinus Torvalds
10261da177e4SLinus Torvalds	cmp.eq pSys,pNonSys=r0,r0		// set pSys=1, pNonSys=0
10271da177e4SLinus Torvalds	movl r17=FPSR_DEFAULT
10281da177e4SLinus Torvalds	;;
10291da177e4SLinus Torvalds	mov.m ar.fpsr=r17			// set ar.fpsr to kernel default value
10301da177e4SLinus Torvalds(p10)	mov r8=-EINVAL
10311da177e4SLinus Torvalds	br.ret.sptk.many b7
10321da177e4SLinus TorvaldsEND(ia64_syscall_setup)
10331da177e4SLinus Torvalds
10341da177e4SLinus Torvalds	.org ia64_ivt+0x3c00
10351da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
10361da177e4SLinus Torvalds// 0x3c00 Entry 15 (size 64 bundles) Reserved
10371da177e4SLinus Torvalds	DBG_FAULT(15)
10381da177e4SLinus Torvalds	FAULT(15)
10391da177e4SLinus Torvalds
10401da177e4SLinus Torvalds	.org ia64_ivt+0x4000
10411da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
10421da177e4SLinus Torvalds// 0x4000 Entry 16 (size 64 bundles) Reserved
10431da177e4SLinus Torvalds	DBG_FAULT(16)
10441da177e4SLinus Torvalds	FAULT(16)
10451da177e4SLinus Torvalds
1046e55645ecSLuis R. Rodriguez#if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE)
1047b64f34cdSHidetoshi Seto	/*
1048b64f34cdSHidetoshi Seto	 * There is no particular reason for this code to be here, other than
1049b64f34cdSHidetoshi Seto	 * that there happens to be space here that would go unused otherwise.
1050b64f34cdSHidetoshi Seto	 * If this fault ever gets "unreserved", simply moved the following
1051b64f34cdSHidetoshi Seto	 * code to a more suitable spot...
1052b64f34cdSHidetoshi Seto	 *
1053b64f34cdSHidetoshi Seto	 * account_sys_enter is called from SAVE_MIN* macros if accounting is
1054b64f34cdSHidetoshi Seto	 * enabled and if the macro is entered from user mode.
1055b64f34cdSHidetoshi Seto	 */
1056498c5170SIsaku YamahataGLOBAL_ENTRY(account_sys_enter)
1057b64f34cdSHidetoshi Seto	// mov.m r20=ar.itc is called in advance, and r13 is current
1058b64f34cdSHidetoshi Seto	add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13
1059b64f34cdSHidetoshi Seto	add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13
1060b64f34cdSHidetoshi Seto	;;
1061b64f34cdSHidetoshi Seto	ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP	// time at last check in kernel
1062b64f34cdSHidetoshi Seto	ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE	// time at left from kernel
1063b64f34cdSHidetoshi Seto        ;;
1064b64f34cdSHidetoshi Seto	ld8 r23=[r16],TI_AC_STAMP-TI_AC_STIME	// cumulated stime
1065b64f34cdSHidetoshi Seto	ld8 r21=[r17]				// cumulated utime
1066b64f34cdSHidetoshi Seto	sub r22=r19,r18				// stime before leave kernel
1067b64f34cdSHidetoshi Seto	;;
1068b64f34cdSHidetoshi Seto	st8 [r16]=r20,TI_AC_STIME-TI_AC_STAMP	// update stamp
1069b64f34cdSHidetoshi Seto	sub r18=r20,r19				// elapsed time in user mode
1070b64f34cdSHidetoshi Seto	;;
1071b64f34cdSHidetoshi Seto	add r23=r23,r22				// sum stime
1072b64f34cdSHidetoshi Seto	add r21=r21,r18				// sum utime
1073b64f34cdSHidetoshi Seto	;;
1074b64f34cdSHidetoshi Seto	st8 [r16]=r23				// update stime
1075b64f34cdSHidetoshi Seto	st8 [r17]=r21				// update utime
1076b64f34cdSHidetoshi Seto	;;
1077b64f34cdSHidetoshi Seto	br.ret.sptk.many rp
1078b64f34cdSHidetoshi SetoEND(account_sys_enter)
1079b64f34cdSHidetoshi Seto#endif
1080b64f34cdSHidetoshi Seto
10811da177e4SLinus Torvalds	.org ia64_ivt+0x4400
10821da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
10831da177e4SLinus Torvalds// 0x4400 Entry 17 (size 64 bundles) Reserved
10841da177e4SLinus Torvalds	DBG_FAULT(17)
10851da177e4SLinus Torvalds	FAULT(17)
10861da177e4SLinus Torvalds
10871da177e4SLinus Torvalds	.org ia64_ivt+0x4800
10881da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
10891da177e4SLinus Torvalds// 0x4800 Entry 18 (size 64 bundles) Reserved
10901da177e4SLinus Torvalds	DBG_FAULT(18)
10911da177e4SLinus Torvalds	FAULT(18)
10921da177e4SLinus Torvalds
10931da177e4SLinus Torvalds	.org ia64_ivt+0x4c00
10941da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
10951da177e4SLinus Torvalds// 0x4c00 Entry 19 (size 64 bundles) Reserved
10961da177e4SLinus Torvalds	DBG_FAULT(19)
10971da177e4SLinus Torvalds	FAULT(19)
10981da177e4SLinus Torvalds
10991da177e4SLinus Torvalds//
11001da177e4SLinus Torvalds// --- End of long entries, Beginning of short entries
11011da177e4SLinus Torvalds//
11021da177e4SLinus Torvalds
11031da177e4SLinus Torvalds	.org ia64_ivt+0x5000
11041da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
11051da177e4SLinus Torvalds// 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49)
11061da177e4SLinus TorvaldsENTRY(page_not_present)
11071da177e4SLinus Torvalds	DBG_FAULT(20)
1108498c5170SIsaku Yamahata	MOV_FROM_IFA(r16)
1109498c5170SIsaku Yamahata	RSM_PSR_DT
11101da177e4SLinus Torvalds	/*
11111da177e4SLinus Torvalds	 * The Linux page fault handler doesn't expect non-present pages to be in
11121da177e4SLinus Torvalds	 * the TLB.  Flush the existing entry now, so we meet that expectation.
11131da177e4SLinus Torvalds	 */
11141da177e4SLinus Torvalds	mov r17=PAGE_SHIFT<<2
11151da177e4SLinus Torvalds	;;
11161da177e4SLinus Torvalds	ptc.l r16,r17
11171da177e4SLinus Torvalds	;;
11181da177e4SLinus Torvalds	mov r31=pr
11191da177e4SLinus Torvalds	srlz.d
11201da177e4SLinus Torvalds	br.sptk.many page_fault
11211da177e4SLinus TorvaldsEND(page_not_present)
11221da177e4SLinus Torvalds
11231da177e4SLinus Torvalds	.org ia64_ivt+0x5100
11241da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
11251da177e4SLinus Torvalds// 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52)
11261da177e4SLinus TorvaldsENTRY(key_permission)
11271da177e4SLinus Torvalds	DBG_FAULT(21)
1128498c5170SIsaku Yamahata	MOV_FROM_IFA(r16)
1129498c5170SIsaku Yamahata	RSM_PSR_DT
11301da177e4SLinus Torvalds	mov r31=pr
11311da177e4SLinus Torvalds	;;
11321da177e4SLinus Torvalds	srlz.d
11331da177e4SLinus Torvalds	br.sptk.many page_fault
11341da177e4SLinus TorvaldsEND(key_permission)
11351da177e4SLinus Torvalds
11361da177e4SLinus Torvalds	.org ia64_ivt+0x5200
11371da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
11381da177e4SLinus Torvalds// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
11391da177e4SLinus TorvaldsENTRY(iaccess_rights)
11401da177e4SLinus Torvalds	DBG_FAULT(22)
1141498c5170SIsaku Yamahata	MOV_FROM_IFA(r16)
1142498c5170SIsaku Yamahata	RSM_PSR_DT
11431da177e4SLinus Torvalds	mov r31=pr
11441da177e4SLinus Torvalds	;;
11451da177e4SLinus Torvalds	srlz.d
11461da177e4SLinus Torvalds	br.sptk.many page_fault
11471da177e4SLinus TorvaldsEND(iaccess_rights)
11481da177e4SLinus Torvalds
11491da177e4SLinus Torvalds	.org ia64_ivt+0x5300
11501da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
11511da177e4SLinus Torvalds// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
11521da177e4SLinus TorvaldsENTRY(daccess_rights)
11531da177e4SLinus Torvalds	DBG_FAULT(23)
1154498c5170SIsaku Yamahata	MOV_FROM_IFA(r16)
1155498c5170SIsaku Yamahata	RSM_PSR_DT
11561da177e4SLinus Torvalds	mov r31=pr
11571da177e4SLinus Torvalds	;;
11581da177e4SLinus Torvalds	srlz.d
11591da177e4SLinus Torvalds	br.sptk.many page_fault
11601da177e4SLinus TorvaldsEND(daccess_rights)
11611da177e4SLinus Torvalds
11621da177e4SLinus Torvalds	.org ia64_ivt+0x5400
11631da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
11641da177e4SLinus Torvalds// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
11651da177e4SLinus TorvaldsENTRY(general_exception)
11661da177e4SLinus Torvalds	DBG_FAULT(24)
1167498c5170SIsaku Yamahata	MOV_FROM_ISR(r16)
11681da177e4SLinus Torvalds	mov r31=pr
11691da177e4SLinus Torvalds	;;
11701da177e4SLinus Torvalds	cmp4.eq p6,p0=0,r16
11711da177e4SLinus Torvalds(p6)	br.sptk.many dispatch_illegal_op_fault
11721da177e4SLinus Torvalds	;;
11731da177e4SLinus Torvalds	mov r19=24		// fault number
11741da177e4SLinus Torvalds	br.sptk.many dispatch_to_fault_handler
11751da177e4SLinus TorvaldsEND(general_exception)
11761da177e4SLinus Torvalds
11771da177e4SLinus Torvalds	.org ia64_ivt+0x5500
11781da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
11791da177e4SLinus Torvalds// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
11801da177e4SLinus TorvaldsENTRY(disabled_fp_reg)
11811da177e4SLinus Torvalds	DBG_FAULT(25)
11821da177e4SLinus Torvalds	rsm psr.dfh		// ensure we can access fph
11831da177e4SLinus Torvalds	;;
11841da177e4SLinus Torvalds	srlz.d
11851da177e4SLinus Torvalds	mov r31=pr
11861da177e4SLinus Torvalds	mov r19=25
11871da177e4SLinus Torvalds	br.sptk.many dispatch_to_fault_handler
11881da177e4SLinus TorvaldsEND(disabled_fp_reg)
11891da177e4SLinus Torvalds
11901da177e4SLinus Torvalds	.org ia64_ivt+0x5600
11911da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
11921da177e4SLinus Torvalds// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
11931da177e4SLinus TorvaldsENTRY(nat_consumption)
11941da177e4SLinus Torvalds	DBG_FAULT(26)
1195458f9355SDavid Mosberger-Tang
1196498c5170SIsaku Yamahata	MOV_FROM_IPSR(p0, r16)
1197498c5170SIsaku Yamahata	MOV_FROM_ISR(r17)
1198458f9355SDavid Mosberger-Tang	mov r31=pr				// save PR
1199458f9355SDavid Mosberger-Tang	;;
1200458f9355SDavid Mosberger-Tang	and r18=0xf,r17				// r18 = cr.ipsr.code{3:0}
1201458f9355SDavid Mosberger-Tang	tbit.z p6,p0=r17,IA64_ISR_NA_BIT
1202458f9355SDavid Mosberger-Tang	;;
1203458f9355SDavid Mosberger-Tang	cmp.ne.or p6,p0=IA64_ISR_CODE_LFETCH,r18
1204458f9355SDavid Mosberger-Tang	dep r16=-1,r16,IA64_PSR_ED_BIT,1
1205458f9355SDavid Mosberger-Tang(p6)	br.cond.spnt 1f		// branch if (cr.ispr.na == 0 || cr.ipsr.code{3:0} != LFETCH)
1206458f9355SDavid Mosberger-Tang	;;
1207498c5170SIsaku Yamahata	MOV_TO_IPSR(p0, r16, r18)
1208458f9355SDavid Mosberger-Tang	mov pr=r31,-1
1209458f9355SDavid Mosberger-Tang	;;
1210498c5170SIsaku Yamahata	RFI
1211458f9355SDavid Mosberger-Tang
1212458f9355SDavid Mosberger-Tang1:	mov pr=r31,-1
1213458f9355SDavid Mosberger-Tang	;;
12141da177e4SLinus Torvalds	FAULT(26)
12151da177e4SLinus TorvaldsEND(nat_consumption)
12161da177e4SLinus Torvalds
12171da177e4SLinus Torvalds	.org ia64_ivt+0x5700
12181da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
12191da177e4SLinus Torvalds// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
12201da177e4SLinus TorvaldsENTRY(speculation_vector)
12211da177e4SLinus Torvalds	DBG_FAULT(27)
12221da177e4SLinus Torvalds	/*
12231da177e4SLinus Torvalds	 * A [f]chk.[as] instruction needs to take the branch to the recovery code but
12241da177e4SLinus Torvalds	 * this part of the architecture is not implemented in hardware on some CPUs, such
12251da177e4SLinus Torvalds	 * as Itanium.  Thus, in general we need to emulate the behavior.  IIM contains
12261da177e4SLinus Torvalds	 * the relative target (not yet sign extended).  So after sign extending it we
12271da177e4SLinus Torvalds	 * simply add it to IIP.  We also need to reset the EI field of the IPSR to zero,
12281da177e4SLinus Torvalds	 * i.e., the slot to restart into.
12291da177e4SLinus Torvalds	 *
12301da177e4SLinus Torvalds	 * cr.imm contains zero_ext(imm21)
12311da177e4SLinus Torvalds	 */
1232498c5170SIsaku Yamahata	MOV_FROM_IIM(r18)
12331da177e4SLinus Torvalds	;;
1234498c5170SIsaku Yamahata	MOV_FROM_IIP(r17)
12351da177e4SLinus Torvalds	shl r18=r18,43			// put sign bit in position (43=64-21)
12361da177e4SLinus Torvalds	;;
12371da177e4SLinus Torvalds
1238498c5170SIsaku Yamahata	MOV_FROM_IPSR(p0, r16)
12391da177e4SLinus Torvalds	shr r18=r18,39			// sign extend (39=43-4)
12401da177e4SLinus Torvalds	;;
12411da177e4SLinus Torvalds
12421da177e4SLinus Torvalds	add r17=r17,r18			// now add the offset
12431da177e4SLinus Torvalds	;;
12449b3cbf72SIsaku Yamahata	MOV_TO_IIP(r17, r19)
12451da177e4SLinus Torvalds	dep r16=0,r16,41,2		// clear EI
12461da177e4SLinus Torvalds	;;
12471da177e4SLinus Torvalds
12489b3cbf72SIsaku Yamahata	MOV_TO_IPSR(p0, r16, r19)
12491da177e4SLinus Torvalds	;;
12501da177e4SLinus Torvalds
1251498c5170SIsaku Yamahata	RFI
12521da177e4SLinus TorvaldsEND(speculation_vector)
12531da177e4SLinus Torvalds
12541da177e4SLinus Torvalds	.org ia64_ivt+0x5800
12551da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
12561da177e4SLinus Torvalds// 0x5800 Entry 28 (size 16 bundles) Reserved
12571da177e4SLinus Torvalds	DBG_FAULT(28)
12581da177e4SLinus Torvalds	FAULT(28)
12591da177e4SLinus Torvalds
12601da177e4SLinus Torvalds	.org ia64_ivt+0x5900
12611da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
12621da177e4SLinus Torvalds// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
12631da177e4SLinus TorvaldsENTRY(debug_vector)
12641da177e4SLinus Torvalds	DBG_FAULT(29)
12651da177e4SLinus Torvalds	FAULT(29)
12661da177e4SLinus TorvaldsEND(debug_vector)
12671da177e4SLinus Torvalds
12681da177e4SLinus Torvalds	.org ia64_ivt+0x5a00
12691da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
12701da177e4SLinus Torvalds// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
12711da177e4SLinus TorvaldsENTRY(unaligned_access)
12721da177e4SLinus Torvalds	DBG_FAULT(30)
12731da177e4SLinus Torvalds	mov r31=pr		// prepare to save predicates
12741da177e4SLinus Torvalds	;;
12751da177e4SLinus Torvalds	br.sptk.many dispatch_unaligned_handler
12761da177e4SLinus TorvaldsEND(unaligned_access)
12771da177e4SLinus Torvalds
12781da177e4SLinus Torvalds	.org ia64_ivt+0x5b00
12791da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
12801da177e4SLinus Torvalds// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
12811da177e4SLinus TorvaldsENTRY(unsupported_data_reference)
12821da177e4SLinus Torvalds	DBG_FAULT(31)
12831da177e4SLinus Torvalds	FAULT(31)
12841da177e4SLinus TorvaldsEND(unsupported_data_reference)
12851da177e4SLinus Torvalds
12861da177e4SLinus Torvalds	.org ia64_ivt+0x5c00
12871da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
12881da177e4SLinus Torvalds// 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64)
12891da177e4SLinus TorvaldsENTRY(floating_point_fault)
12901da177e4SLinus Torvalds	DBG_FAULT(32)
12911da177e4SLinus Torvalds	FAULT(32)
12921da177e4SLinus TorvaldsEND(floating_point_fault)
12931da177e4SLinus Torvalds
12941da177e4SLinus Torvalds	.org ia64_ivt+0x5d00
12951da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
12961da177e4SLinus Torvalds// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
12971da177e4SLinus TorvaldsENTRY(floating_point_trap)
12981da177e4SLinus Torvalds	DBG_FAULT(33)
12991da177e4SLinus Torvalds	FAULT(33)
13001da177e4SLinus TorvaldsEND(floating_point_trap)
13011da177e4SLinus Torvalds
13021da177e4SLinus Torvalds	.org ia64_ivt+0x5e00
13031da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
13041da177e4SLinus Torvalds// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66)
13051da177e4SLinus TorvaldsENTRY(lower_privilege_trap)
13061da177e4SLinus Torvalds	DBG_FAULT(34)
13071da177e4SLinus Torvalds	FAULT(34)
13081da177e4SLinus TorvaldsEND(lower_privilege_trap)
13091da177e4SLinus Torvalds
13101da177e4SLinus Torvalds	.org ia64_ivt+0x5f00
13111da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
13121da177e4SLinus Torvalds// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
13131da177e4SLinus TorvaldsENTRY(taken_branch_trap)
13141da177e4SLinus Torvalds	DBG_FAULT(35)
13151da177e4SLinus Torvalds	FAULT(35)
13161da177e4SLinus TorvaldsEND(taken_branch_trap)
13171da177e4SLinus Torvalds
13181da177e4SLinus Torvalds	.org ia64_ivt+0x6000
13191da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
13201da177e4SLinus Torvalds// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
13211da177e4SLinus TorvaldsENTRY(single_step_trap)
13221da177e4SLinus Torvalds	DBG_FAULT(36)
13231da177e4SLinus Torvalds	FAULT(36)
13241da177e4SLinus TorvaldsEND(single_step_trap)
13251da177e4SLinus Torvalds
13261da177e4SLinus Torvalds	.org ia64_ivt+0x6100
13271da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
13281da177e4SLinus Torvalds// 0x6100 Entry 37 (size 16 bundles) Reserved
13291da177e4SLinus Torvalds	DBG_FAULT(37)
13301da177e4SLinus Torvalds	FAULT(37)
13311da177e4SLinus Torvalds
13321da177e4SLinus Torvalds	.org ia64_ivt+0x6200
13331da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
13341da177e4SLinus Torvalds// 0x6200 Entry 38 (size 16 bundles) Reserved
13351da177e4SLinus Torvalds	DBG_FAULT(38)
13361da177e4SLinus Torvalds	FAULT(38)
13371da177e4SLinus Torvalds
13381da177e4SLinus Torvalds	.org ia64_ivt+0x6300
13391da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
13401da177e4SLinus Torvalds// 0x6300 Entry 39 (size 16 bundles) Reserved
13411da177e4SLinus Torvalds	DBG_FAULT(39)
13421da177e4SLinus Torvalds	FAULT(39)
13431da177e4SLinus Torvalds
13441da177e4SLinus Torvalds	.org ia64_ivt+0x6400
13451da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
13461da177e4SLinus Torvalds// 0x6400 Entry 40 (size 16 bundles) Reserved
13471da177e4SLinus Torvalds	DBG_FAULT(40)
13481da177e4SLinus Torvalds	FAULT(40)
13491da177e4SLinus Torvalds
13501da177e4SLinus Torvalds	.org ia64_ivt+0x6500
13511da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
13521da177e4SLinus Torvalds// 0x6500 Entry 41 (size 16 bundles) Reserved
13531da177e4SLinus Torvalds	DBG_FAULT(41)
13541da177e4SLinus Torvalds	FAULT(41)
13551da177e4SLinus Torvalds
13561da177e4SLinus Torvalds	.org ia64_ivt+0x6600
13571da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
13581da177e4SLinus Torvalds// 0x6600 Entry 42 (size 16 bundles) Reserved
13591da177e4SLinus Torvalds	DBG_FAULT(42)
13601da177e4SLinus Torvalds	FAULT(42)
13611da177e4SLinus Torvalds
13621da177e4SLinus Torvalds	.org ia64_ivt+0x6700
13631da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
13641da177e4SLinus Torvalds// 0x6700 Entry 43 (size 16 bundles) Reserved
13651da177e4SLinus Torvalds	DBG_FAULT(43)
13661da177e4SLinus Torvalds	FAULT(43)
13671da177e4SLinus Torvalds
13681da177e4SLinus Torvalds	.org ia64_ivt+0x6800
13691da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
13701da177e4SLinus Torvalds// 0x6800 Entry 44 (size 16 bundles) Reserved
13711da177e4SLinus Torvalds	DBG_FAULT(44)
13721da177e4SLinus Torvalds	FAULT(44)
13731da177e4SLinus Torvalds
13741da177e4SLinus Torvalds	.org ia64_ivt+0x6900
13751da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
13761da177e4SLinus Torvalds// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
13771da177e4SLinus TorvaldsENTRY(ia32_exception)
13781da177e4SLinus Torvalds	DBG_FAULT(45)
13791da177e4SLinus Torvalds	FAULT(45)
13801da177e4SLinus TorvaldsEND(ia32_exception)
13811da177e4SLinus Torvalds
13821da177e4SLinus Torvalds	.org ia64_ivt+0x6a00
13831da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
13841da177e4SLinus Torvalds// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept  (30,31,59,70,71)
13851da177e4SLinus TorvaldsENTRY(ia32_intercept)
13861da177e4SLinus Torvalds	DBG_FAULT(46)
13871da177e4SLinus Torvalds	FAULT(46)
13881da177e4SLinus TorvaldsEND(ia32_intercept)
13891da177e4SLinus Torvalds
13901da177e4SLinus Torvalds	.org ia64_ivt+0x6b00
13911da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
13921da177e4SLinus Torvalds// 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt  (74)
13931da177e4SLinus TorvaldsENTRY(ia32_interrupt)
13941da177e4SLinus Torvalds	DBG_FAULT(47)
13951da177e4SLinus Torvalds	FAULT(47)
13961da177e4SLinus TorvaldsEND(ia32_interrupt)
13971da177e4SLinus Torvalds
13981da177e4SLinus Torvalds	.org ia64_ivt+0x6c00
13991da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14001da177e4SLinus Torvalds// 0x6c00 Entry 48 (size 16 bundles) Reserved
14011da177e4SLinus Torvalds	DBG_FAULT(48)
14021da177e4SLinus Torvalds	FAULT(48)
14031da177e4SLinus Torvalds
14041da177e4SLinus Torvalds	.org ia64_ivt+0x6d00
14051da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14061da177e4SLinus Torvalds// 0x6d00 Entry 49 (size 16 bundles) Reserved
14071da177e4SLinus Torvalds	DBG_FAULT(49)
14081da177e4SLinus Torvalds	FAULT(49)
14091da177e4SLinus Torvalds
14101da177e4SLinus Torvalds	.org ia64_ivt+0x6e00
14111da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14121da177e4SLinus Torvalds// 0x6e00 Entry 50 (size 16 bundles) Reserved
14131da177e4SLinus Torvalds	DBG_FAULT(50)
14141da177e4SLinus Torvalds	FAULT(50)
14151da177e4SLinus Torvalds
14161da177e4SLinus Torvalds	.org ia64_ivt+0x6f00
14171da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14181da177e4SLinus Torvalds// 0x6f00 Entry 51 (size 16 bundles) Reserved
14191da177e4SLinus Torvalds	DBG_FAULT(51)
14201da177e4SLinus Torvalds	FAULT(51)
14211da177e4SLinus Torvalds
14221da177e4SLinus Torvalds	.org ia64_ivt+0x7000
14231da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14241da177e4SLinus Torvalds// 0x7000 Entry 52 (size 16 bundles) Reserved
14251da177e4SLinus Torvalds	DBG_FAULT(52)
14261da177e4SLinus Torvalds	FAULT(52)
14271da177e4SLinus Torvalds
14281da177e4SLinus Torvalds	.org ia64_ivt+0x7100
14291da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14301da177e4SLinus Torvalds// 0x7100 Entry 53 (size 16 bundles) Reserved
14311da177e4SLinus Torvalds	DBG_FAULT(53)
14321da177e4SLinus Torvalds	FAULT(53)
14331da177e4SLinus Torvalds
14341da177e4SLinus Torvalds	.org ia64_ivt+0x7200
14351da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14361da177e4SLinus Torvalds// 0x7200 Entry 54 (size 16 bundles) Reserved
14371da177e4SLinus Torvalds	DBG_FAULT(54)
14381da177e4SLinus Torvalds	FAULT(54)
14391da177e4SLinus Torvalds
14401da177e4SLinus Torvalds	.org ia64_ivt+0x7300
14411da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14421da177e4SLinus Torvalds// 0x7300 Entry 55 (size 16 bundles) Reserved
14431da177e4SLinus Torvalds	DBG_FAULT(55)
14441da177e4SLinus Torvalds	FAULT(55)
14451da177e4SLinus Torvalds
14461da177e4SLinus Torvalds	.org ia64_ivt+0x7400
14471da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14481da177e4SLinus Torvalds// 0x7400 Entry 56 (size 16 bundles) Reserved
14491da177e4SLinus Torvalds	DBG_FAULT(56)
14501da177e4SLinus Torvalds	FAULT(56)
14511da177e4SLinus Torvalds
14521da177e4SLinus Torvalds	.org ia64_ivt+0x7500
14531da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14541da177e4SLinus Torvalds// 0x7500 Entry 57 (size 16 bundles) Reserved
14551da177e4SLinus Torvalds	DBG_FAULT(57)
14561da177e4SLinus Torvalds	FAULT(57)
14571da177e4SLinus Torvalds
14581da177e4SLinus Torvalds	.org ia64_ivt+0x7600
14591da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14601da177e4SLinus Torvalds// 0x7600 Entry 58 (size 16 bundles) Reserved
14611da177e4SLinus Torvalds	DBG_FAULT(58)
14621da177e4SLinus Torvalds	FAULT(58)
14631da177e4SLinus Torvalds
14641da177e4SLinus Torvalds	.org ia64_ivt+0x7700
14651da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14661da177e4SLinus Torvalds// 0x7700 Entry 59 (size 16 bundles) Reserved
14671da177e4SLinus Torvalds	DBG_FAULT(59)
14681da177e4SLinus Torvalds	FAULT(59)
14691da177e4SLinus Torvalds
14701da177e4SLinus Torvalds	.org ia64_ivt+0x7800
14711da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14721da177e4SLinus Torvalds// 0x7800 Entry 60 (size 16 bundles) Reserved
14731da177e4SLinus Torvalds	DBG_FAULT(60)
14741da177e4SLinus Torvalds	FAULT(60)
14751da177e4SLinus Torvalds
14761da177e4SLinus Torvalds	.org ia64_ivt+0x7900
14771da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14781da177e4SLinus Torvalds// 0x7900 Entry 61 (size 16 bundles) Reserved
14791da177e4SLinus Torvalds	DBG_FAULT(61)
14801da177e4SLinus Torvalds	FAULT(61)
14811da177e4SLinus Torvalds
14821da177e4SLinus Torvalds	.org ia64_ivt+0x7a00
14831da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14841da177e4SLinus Torvalds// 0x7a00 Entry 62 (size 16 bundles) Reserved
14851da177e4SLinus Torvalds	DBG_FAULT(62)
14861da177e4SLinus Torvalds	FAULT(62)
14871da177e4SLinus Torvalds
14881da177e4SLinus Torvalds	.org ia64_ivt+0x7b00
14891da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14901da177e4SLinus Torvalds// 0x7b00 Entry 63 (size 16 bundles) Reserved
14911da177e4SLinus Torvalds	DBG_FAULT(63)
14921da177e4SLinus Torvalds	FAULT(63)
14931da177e4SLinus Torvalds
14941da177e4SLinus Torvalds	.org ia64_ivt+0x7c00
14951da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
14961da177e4SLinus Torvalds// 0x7c00 Entry 64 (size 16 bundles) Reserved
14971da177e4SLinus Torvalds	DBG_FAULT(64)
14981da177e4SLinus Torvalds	FAULT(64)
14991da177e4SLinus Torvalds
15001da177e4SLinus Torvalds	.org ia64_ivt+0x7d00
15011da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
15021da177e4SLinus Torvalds// 0x7d00 Entry 65 (size 16 bundles) Reserved
15031da177e4SLinus Torvalds	DBG_FAULT(65)
15041da177e4SLinus Torvalds	FAULT(65)
15051da177e4SLinus Torvalds
15061da177e4SLinus Torvalds	.org ia64_ivt+0x7e00
15071da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
15081da177e4SLinus Torvalds// 0x7e00 Entry 66 (size 16 bundles) Reserved
15091da177e4SLinus Torvalds	DBG_FAULT(66)
15101da177e4SLinus Torvalds	FAULT(66)
15111da177e4SLinus Torvalds
15121da177e4SLinus Torvalds	.org ia64_ivt+0x7f00
15131da177e4SLinus Torvalds/////////////////////////////////////////////////////////////////////////////////////////
15141da177e4SLinus Torvalds// 0x7f00 Entry 67 (size 16 bundles) Reserved
15151da177e4SLinus Torvalds	DBG_FAULT(67)
15161da177e4SLinus Torvalds	FAULT(67)
15171da177e4SLinus Torvalds
15184d58bbccSIsaku Yamahata	//-----------------------------------------------------------------------------------
15194d58bbccSIsaku Yamahata	// call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
15204d58bbccSIsaku YamahataENTRY(page_fault)
15214d58bbccSIsaku Yamahata	SSM_PSR_DT_AND_SRLZ_I
15224d58bbccSIsaku Yamahata	;;
15234d58bbccSIsaku Yamahata	SAVE_MIN_WITH_COVER
15244d58bbccSIsaku Yamahata	alloc r15=ar.pfs,0,0,3,0
15254d58bbccSIsaku Yamahata	MOV_FROM_IFA(out0)
15264d58bbccSIsaku Yamahata	MOV_FROM_ISR(out1)
15274d58bbccSIsaku Yamahata	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r14, r3)
15284d58bbccSIsaku Yamahata	adds r3=8,r2				// set up second base pointer
15294d58bbccSIsaku Yamahata	SSM_PSR_I(p15, p15, r14)		// restore psr.i
15304d58bbccSIsaku Yamahata	movl r14=ia64_leave_kernel
15314d58bbccSIsaku Yamahata	;;
15324d58bbccSIsaku Yamahata	SAVE_REST
15334d58bbccSIsaku Yamahata	mov rp=r14
15344d58bbccSIsaku Yamahata	;;
15354d58bbccSIsaku Yamahata	adds out2=16,r12			// out2 = pointer to pt_regs
15364d58bbccSIsaku Yamahata	br.call.sptk.many b6=ia64_do_page_fault	// ignore return address
15374d58bbccSIsaku YamahataEND(page_fault)
15384d58bbccSIsaku Yamahata
15394d58bbccSIsaku YamahataENTRY(non_syscall)
15404d58bbccSIsaku Yamahata	mov ar.rsc=r27			// restore ar.rsc before SAVE_MIN_WITH_COVER
15414d58bbccSIsaku Yamahata	;;
15424d58bbccSIsaku Yamahata	SAVE_MIN_WITH_COVER
15434d58bbccSIsaku Yamahata
15444d58bbccSIsaku Yamahata	// There is no particular reason for this code to be here, other than that
15454d58bbccSIsaku Yamahata	// there happens to be space here that would go unused otherwise.  If this
15464d58bbccSIsaku Yamahata	// fault ever gets "unreserved", simply moved the following code to a more
15474d58bbccSIsaku Yamahata	// suitable spot...
15484d58bbccSIsaku Yamahata
15494d58bbccSIsaku Yamahata	alloc r14=ar.pfs,0,0,2,0
15504d58bbccSIsaku Yamahata	MOV_FROM_IIM(out0)
15514d58bbccSIsaku Yamahata	add out1=16,sp
15524d58bbccSIsaku Yamahata	adds r3=8,r2			// set up second base pointer for SAVE_REST
15534d58bbccSIsaku Yamahata
15544d58bbccSIsaku Yamahata	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r15, r24)
15554d58bbccSIsaku Yamahata					// guarantee that interruption collection is on
15564d58bbccSIsaku Yamahata	SSM_PSR_I(p15, p15, r15)	// restore psr.i
15574d58bbccSIsaku Yamahata	movl r15=ia64_leave_kernel
15584d58bbccSIsaku Yamahata	;;
15594d58bbccSIsaku Yamahata	SAVE_REST
15604d58bbccSIsaku Yamahata	mov rp=r15
15614d58bbccSIsaku Yamahata	;;
15624d58bbccSIsaku Yamahata	br.call.sptk.many b6=ia64_bad_break	// avoid WAW on CFM and ignore return addr
15634d58bbccSIsaku YamahataEND(non_syscall)
15644d58bbccSIsaku Yamahata
15654d58bbccSIsaku YamahataENTRY(__interrupt)
15664d58bbccSIsaku Yamahata	DBG_FAULT(12)
15674d58bbccSIsaku Yamahata	mov r31=pr		// prepare to save predicates
15684d58bbccSIsaku Yamahata	;;
15694d58bbccSIsaku Yamahata	SAVE_MIN_WITH_COVER	// uses r31; defines r2 and r3
15704d58bbccSIsaku Yamahata	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r14)
15714d58bbccSIsaku Yamahata				// ensure everybody knows psr.ic is back on
15724d58bbccSIsaku Yamahata	adds r3=8,r2		// set up second base pointer for SAVE_REST
15734d58bbccSIsaku Yamahata	;;
15744d58bbccSIsaku Yamahata	SAVE_REST
15754d58bbccSIsaku Yamahata	;;
15764d58bbccSIsaku Yamahata	MCA_RECOVER_RANGE(interrupt)
15774d58bbccSIsaku Yamahata	alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
15784d58bbccSIsaku Yamahata	MOV_FROM_IVR(out0, r8)	// pass cr.ivr as first arg
15794d58bbccSIsaku Yamahata	add out1=16,sp		// pass pointer to pt_regs as second arg
15804d58bbccSIsaku Yamahata	;;
15814d58bbccSIsaku Yamahata	srlz.d			// make sure we see the effect of cr.ivr
15824d58bbccSIsaku Yamahata	movl r14=ia64_leave_kernel
15834d58bbccSIsaku Yamahata	;;
15844d58bbccSIsaku Yamahata	mov rp=r14
15854d58bbccSIsaku Yamahata	br.call.sptk.many b6=ia64_handle_irq
15864d58bbccSIsaku YamahataEND(__interrupt)
15874d58bbccSIsaku Yamahata
15884d58bbccSIsaku Yamahata	/*
15894d58bbccSIsaku Yamahata	 * There is no particular reason for this code to be here, other than that
15904d58bbccSIsaku Yamahata	 * there happens to be space here that would go unused otherwise.  If this
15914d58bbccSIsaku Yamahata	 * fault ever gets "unreserved", simply moved the following code to a more
15924d58bbccSIsaku Yamahata	 * suitable spot...
15934d58bbccSIsaku Yamahata	 */
15944d58bbccSIsaku Yamahata
15954d58bbccSIsaku YamahataENTRY(dispatch_unaligned_handler)
15964d58bbccSIsaku Yamahata	SAVE_MIN_WITH_COVER
15974d58bbccSIsaku Yamahata	;;
15984d58bbccSIsaku Yamahata	alloc r14=ar.pfs,0,0,2,0		// now it's safe (must be first in insn group!)
15994d58bbccSIsaku Yamahata	MOV_FROM_IFA(out0)
16004d58bbccSIsaku Yamahata	adds out1=16,sp
16014d58bbccSIsaku Yamahata
16024d58bbccSIsaku Yamahata	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24)
16034d58bbccSIsaku Yamahata						// guarantee that interruption collection is on
16044d58bbccSIsaku Yamahata	SSM_PSR_I(p15, p15, r3)			// restore psr.i
16054d58bbccSIsaku Yamahata	adds r3=8,r2				// set up second base pointer
16064d58bbccSIsaku Yamahata	;;
16074d58bbccSIsaku Yamahata	SAVE_REST
16084d58bbccSIsaku Yamahata	movl r14=ia64_leave_kernel
16094d58bbccSIsaku Yamahata	;;
16104d58bbccSIsaku Yamahata	mov rp=r14
16114d58bbccSIsaku Yamahata	br.sptk.many ia64_prepare_handle_unaligned
16124d58bbccSIsaku YamahataEND(dispatch_unaligned_handler)
16134d58bbccSIsaku Yamahata
16144d58bbccSIsaku Yamahata	/*
16154d58bbccSIsaku Yamahata	 * There is no particular reason for this code to be here, other than that
16164d58bbccSIsaku Yamahata	 * there happens to be space here that would go unused otherwise.  If this
16174d58bbccSIsaku Yamahata	 * fault ever gets "unreserved", simply moved the following code to a more
16184d58bbccSIsaku Yamahata	 * suitable spot...
16194d58bbccSIsaku Yamahata	 */
16204d58bbccSIsaku Yamahata
16214d58bbccSIsaku YamahataENTRY(dispatch_to_fault_handler)
16224d58bbccSIsaku Yamahata	/*
16234d58bbccSIsaku Yamahata	 * Input:
16244d58bbccSIsaku Yamahata	 *	psr.ic:	off
16254d58bbccSIsaku Yamahata	 *	r19:	fault vector number (e.g., 24 for General Exception)
16264d58bbccSIsaku Yamahata	 *	r31:	contains saved predicates (pr)
16274d58bbccSIsaku Yamahata	 */
16284d58bbccSIsaku Yamahata	SAVE_MIN_WITH_COVER_R19
16294d58bbccSIsaku Yamahata	alloc r14=ar.pfs,0,0,5,0
16304d58bbccSIsaku Yamahata	MOV_FROM_ISR(out1)
16314d58bbccSIsaku Yamahata	MOV_FROM_IFA(out2)
16324d58bbccSIsaku Yamahata	MOV_FROM_IIM(out3)
16334d58bbccSIsaku Yamahata	MOV_FROM_ITIR(out4)
16344d58bbccSIsaku Yamahata	;;
16354d58bbccSIsaku Yamahata	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, out0)
16364d58bbccSIsaku Yamahata						// guarantee that interruption collection is on
16374d58bbccSIsaku Yamahata	mov out0=r15
16384d58bbccSIsaku Yamahata	;;
16394d58bbccSIsaku Yamahata	SSM_PSR_I(p15, p15, r3)			// restore psr.i
16404d58bbccSIsaku Yamahata	adds r3=8,r2				// set up second base pointer for SAVE_REST
16414d58bbccSIsaku Yamahata	;;
16424d58bbccSIsaku Yamahata	SAVE_REST
16434d58bbccSIsaku Yamahata	movl r14=ia64_leave_kernel
16444d58bbccSIsaku Yamahata	;;
16454d58bbccSIsaku Yamahata	mov rp=r14
16464d58bbccSIsaku Yamahata	br.call.sptk.many b6=ia64_fault
16474d58bbccSIsaku YamahataEND(dispatch_to_fault_handler)
16484d58bbccSIsaku Yamahata
16494dcc29e1STony Luck	/*
16504dcc29e1STony Luck	 * Squatting in this space ...
16514dcc29e1STony Luck	 *
16524dcc29e1STony Luck	 * This special case dispatcher for illegal operation faults allows preserved
16534dcc29e1STony Luck	 * registers to be modified through a callback function (asm only) that is handed
16544dcc29e1STony Luck	 * back from the fault handler in r8. Up to three arguments can be passed to the
16554dcc29e1STony Luck	 * callback function by returning an aggregate with the callback as its first
16564dcc29e1STony Luck	 * element, followed by the arguments.
16574dcc29e1STony Luck	 */
16584dcc29e1STony LuckENTRY(dispatch_illegal_op_fault)
16594dcc29e1STony Luck	.prologue
16604dcc29e1STony Luck	.body
16614dcc29e1STony Luck	SAVE_MIN_WITH_COVER
1662498c5170SIsaku Yamahata	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24)
1663498c5170SIsaku Yamahata				// guarantee that interruption collection is on
16644dcc29e1STony Luck	;;
1665498c5170SIsaku Yamahata	SSM_PSR_I(p15, p15, r3)	// restore psr.i
16664dcc29e1STony Luck	adds r3=8,r2	// set up second base pointer for SAVE_REST
16674dcc29e1STony Luck	;;
16684dcc29e1STony Luck	alloc r14=ar.pfs,0,0,1,0	// must be first in insn group
16694dcc29e1STony Luck	mov out0=ar.ec
16704dcc29e1STony Luck	;;
16714dcc29e1STony Luck	SAVE_REST
16724dcc29e1STony Luck	PT_REGS_UNWIND_INFO(0)
16734dcc29e1STony Luck	;;
16744dcc29e1STony Luck	br.call.sptk.many rp=ia64_illegal_op_fault
16754dcc29e1STony Luck.ret0:	;;
16764dcc29e1STony Luck	alloc r14=ar.pfs,0,0,3,0	// must be first in insn group
16774dcc29e1STony Luck	mov out0=r9
16784dcc29e1STony Luck	mov out1=r10
16794dcc29e1STony Luck	mov out2=r11
16804dcc29e1STony Luck	movl r15=ia64_leave_kernel
16814dcc29e1STony Luck	;;
16824dcc29e1STony Luck	mov rp=r15
16834dcc29e1STony Luck	mov b6=r8
16844dcc29e1STony Luck	;;
16854dcc29e1STony Luck	cmp.ne p6,p0=0,r8
16864dcc29e1STony Luck(p6)	br.call.dpnt.many b6=b6		// call returns to ia64_leave_kernel
16874dcc29e1STony Luck	br.sptk.many ia64_leave_kernel
16884dcc29e1STony LuckEND(dispatch_illegal_op_fault)
1689