blob: 23749ed3cf08449c4bd88b9e28e17d19f3010c51 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * arch/ia64/kernel/ivt.S
3 *
David Mosberger-Tang060561f2005-04-27 21:17:03 -07004 * Copyright (C) 1998-2001, 2003, 2005 Hewlett-Packard Co
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Stephane Eranian <eranian@hpl.hp.com>
6 * David Mosberger <davidm@hpl.hp.com>
7 * Copyright (C) 2000, 2002-2003 Intel Co
8 * Asit Mallick <asit.k.mallick@intel.com>
9 * Suresh Siddha <suresh.b.siddha@intel.com>
10 * Kenneth Chen <kenneth.w.chen@intel.com>
11 * Fenghua Yu <fenghua.yu@intel.com>
12 *
13 * 00/08/23 Asit Mallick <asit.k.mallick@intel.com> TLB handling for SMP
14 * 00/12/20 David Mosberger-Tang <davidm@hpl.hp.com> DTLB/ITLB handler now uses virtual PT.
Isaku Yamahata498c5172008-05-19 22:13:38 +090015 *
16 * Copyright (C) 2005 Hewlett-Packard Co
17 * Dan Magenheimer <dan.magenheimer@hp.com>
18 * Xen paravirtualization
19 * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
20 * VA Linux Systems Japan K.K.
21 * pv_ops.
22 * Yaozu (Eddie) Dong <eddie.dong@intel.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070023 */
24/*
25 * This file defines the interruption vector table used by the CPU.
26 * It does not include one entry per possible cause of interruption.
27 *
28 * The first 20 entries of the table contain 64 bundles each while the
29 * remaining 48 entries contain only 16 bundles each.
30 *
31 * The 64 bundles are used to allow inlining the whole handler for critical
32 * interruptions like TLB misses.
33 *
34 * For each entry, the comment is as follows:
35 *
36 * // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
37 * entry offset ----/ / / / /
38 * entry number ---------/ / / /
39 * size of the entry -------------/ / /
40 * vector name -------------------------------------/ /
41 * interruptions triggering this vector ----------------------/
42 *
43 * The table is 32KB in size and must be aligned on 32KB boundary.
44 * (The CPU ignores the 15 lower bits of the address)
45 *
46 * Table is based upon EAS2.6 (Oct 1999)
47 */
48
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
50#include <asm/asmmacro.h>
51#include <asm/break.h>
52#include <asm/ia32.h>
53#include <asm/kregs.h>
Sam Ravnborg39e01cb2005-09-09 22:03:13 +020054#include <asm/asm-offsets.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055#include <asm/pgtable.h>
56#include <asm/processor.h>
57#include <asm/ptrace.h>
58#include <asm/system.h>
59#include <asm/thread_info.h>
60#include <asm/unistd.h>
61#include <asm/errno.h>
62
63#if 1
64# define PSR_DEFAULT_BITS psr.ac
65#else
66# define PSR_DEFAULT_BITS 0
67#endif
68
69#if 0
70 /*
71 * This lets you track the last eight faults that occurred on the CPU. Make sure ar.k2 isn't
72 * needed for something else before enabling this...
73 */
74# define DBG_FAULT(i) mov r16=ar.k2;; shl r16=r16,8;; add r16=(i),r16;;mov ar.k2=r16
75#else
76# define DBG_FAULT(i)
77#endif
78
Linus Torvalds1da177e2005-04-16 15:20:36 -070079#include "minstate.h"
80
81#define FAULT(n) \
82 mov r31=pr; \
83 mov r19=n;; /* prepare to save predicates */ \
84 br.sptk.many dispatch_to_fault_handler
85
86 .section .text.ivt,"ax"
87
88 .align 32768 // align on 32KB boundary
89 .global ia64_ivt
90ia64_ivt:
91/////////////////////////////////////////////////////////////////////////////////////////
92// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
93ENTRY(vhpt_miss)
94 DBG_FAULT(0)
95 /*
96 * The VHPT vector is invoked when the TLB entry for the virtual page table
97 * is missing. This happens only as a result of a previous
98 * (the "original") TLB miss, which may either be caused by an instruction
99 * fetch or a data access (or non-access).
100 *
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800101 * What we do here is normal TLB miss handing for the _original_ miss,
102 * followed by inserting the TLB entry for the virtual page table page
103 * that the VHPT walker was attempting to access. The latter gets
104 * inserted as long as page table entry above pte level have valid
105 * mappings for the faulting address. The TLB entry for the original
106 * miss gets inserted only if the pte entry indicates that the page is
107 * present.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 *
109 * do_page_fault gets invoked in the following cases:
110 * - the faulting virtual address uses unimplemented address bits
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800111 * - the faulting virtual address has no valid page table mapping
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 */
Isaku Yamahata498c5172008-05-19 22:13:38 +0900113 MOV_FROM_IFA(r16) // get address that caused the TLB miss
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114#ifdef CONFIG_HUGETLB_PAGE
115 movl r18=PAGE_SHIFT
Isaku Yamahata498c5172008-05-19 22:13:38 +0900116 MOV_FROM_ITIR(r25)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117#endif
118 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900119 RSM_PSR_DT // use physical addressing for data
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 mov r31=pr // save the predicate registers
121 mov r19=IA64_KR(PT_BASE) // get page table base address
122 shl r21=r16,3 // shift bit 60 into sign bit
123 shr.u r17=r16,61 // get the region number into r17
124 ;;
Robin Holt837cd0b2005-11-11 09:35:43 -0600125 shr.u r22=r21,3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126#ifdef CONFIG_HUGETLB_PAGE
127 extr.u r26=r25,2,6
128 ;;
129 cmp.ne p8,p0=r18,r26
130 sub r27=r26,r18
131 ;;
132(p8) dep r25=r18,r25,2,6
133(p8) shr r22=r22,r27
134#endif
135 ;;
136 cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5?
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800137 shr.u r18=r22,PGDIR_SHIFT // get bottom portion of pgd index bit
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 ;;
139(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
140
141 srlz.d
142 LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
143
144 .pred.rel "mutex", p6, p7
145(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
146(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
147 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800148(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
149(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
Robin Holt837cd0b2005-11-11 09:35:43 -0600151#ifdef CONFIG_PGTABLE_4
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800152 shr.u r28=r22,PUD_SHIFT // shift pud index into position
Robin Holt837cd0b2005-11-11 09:35:43 -0600153#else
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800154 shr.u r18=r22,PMD_SHIFT // shift pmd index into position
Robin Holt837cd0b2005-11-11 09:35:43 -0600155#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800157 ld8 r17=[r17] // get *pgd (may be 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800159(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
Robin Holt837cd0b2005-11-11 09:35:43 -0600160#ifdef CONFIG_PGTABLE_4
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800161 dep r28=r28,r17,3,(PAGE_SHIFT-3) // r28=pud_offset(pgd,addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800163 shr.u r18=r22,PMD_SHIFT // shift pmd index into position
164(p7) ld8 r29=[r28] // get *pud (may be 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800166(p7) cmp.eq.or.andcm p6,p7=r29,r0 // was pud_present(*pud) == NULL?
167 dep r17=r18,r29,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
Robin Holt837cd0b2005-11-11 09:35:43 -0600168#else
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800169 dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pgd,addr)
Robin Holt837cd0b2005-11-11 09:35:43 -0600170#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800172(p7) ld8 r20=[r17] // get *pmd (may be 0)
173 shr.u r19=r22,PAGE_SHIFT // shift pte index into position
Robin Holt837cd0b2005-11-11 09:35:43 -0600174 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800175(p7) cmp.eq.or.andcm p6,p7=r20,r0 // was pmd_present(*pmd) == NULL?
176 dep r21=r19,r20,3,(PAGE_SHIFT-3) // r21=pte_offset(pmd,addr)
Robin Holt837cd0b2005-11-11 09:35:43 -0600177 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800178(p7) ld8 r18=[r21] // read *pte
Isaku Yamahata498c5172008-05-19 22:13:38 +0900179 MOV_FROM_ISR(r19) // cr.isr bit 32 tells us if this is an insn miss
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 ;;
181(p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared?
Isaku Yamahata498c5172008-05-19 22:13:38 +0900182 MOV_FROM_IHA(r22) // get the VHPT address that caused the TLB miss
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 ;; // avoid RAW on p7
184(p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB miss?
185 dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page address
186 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900187 ITC_I_AND_D(p10, p11, r18, r24) // insert the instruction TLB entry and
188 // insert the data TLB entry
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189(p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault)
Isaku Yamahata498c5172008-05-19 22:13:38 +0900190 MOV_TO_IFA(r22, r24)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191
192#ifdef CONFIG_HUGETLB_PAGE
Isaku Yamahata498c5172008-05-19 22:13:38 +0900193 MOV_TO_ITIR(p8, r25, r24) // change to default page-size for VHPT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194#endif
195
196 /*
197 * Now compute and insert the TLB entry for the virtual page table. We never
198 * execute in a page table page so there is no need to set the exception deferral
199 * bit.
200 */
201 adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23
202 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900203 ITC_D(p7, r24, r25)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 ;;
205#ifdef CONFIG_SMP
206 /*
207 * Tell the assemblers dependency-violation checker that the above "itc" instructions
208 * cannot possibly affect the following loads:
209 */
210 dv_serialize_data
211
212 /*
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800213 * Re-check pagetable entry. If they changed, we may have received a ptc.g
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 * between reading the pagetable and the "itc". If so, flush the entry we
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800215 * inserted and retry. At this point, we have:
216 *
217 * r28 = equivalent of pud_offset(pgd, ifa)
218 * r17 = equivalent of pmd_offset(pud, ifa)
219 * r21 = equivalent of pte_offset(pmd, ifa)
220 *
221 * r29 = *pud
222 * r20 = *pmd
223 * r18 = *pte
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 */
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800225 ld8 r25=[r21] // read *pte again
226 ld8 r26=[r17] // read *pmd again
Robin Holt837cd0b2005-11-11 09:35:43 -0600227#ifdef CONFIG_PGTABLE_4
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800228 ld8 r19=[r28] // read *pud again
Robin Holt837cd0b2005-11-11 09:35:43 -0600229#endif
230 cmp.ne p6,p7=r0,r0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800232 cmp.ne.or.andcm p6,p7=r26,r20 // did *pmd change
Robin Holt837cd0b2005-11-11 09:35:43 -0600233#ifdef CONFIG_PGTABLE_4
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800234 cmp.ne.or.andcm p6,p7=r19,r29 // did *pud change
Robin Holt837cd0b2005-11-11 09:35:43 -0600235#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 mov r27=PAGE_SHIFT<<2
237 ;;
238(p6) ptc.l r22,r27 // purge PTE page translation
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800239(p7) cmp.ne.or.andcm p6,p7=r25,r18 // did *pte change
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 ;;
241(p6) ptc.l r16,r27 // purge translation
242#endif
243
244 mov pr=r31,-1 // restore predicate registers
Isaku Yamahata498c5172008-05-19 22:13:38 +0900245 RFI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246END(vhpt_miss)
247
248 .org ia64_ivt+0x400
249/////////////////////////////////////////////////////////////////////////////////////////
250// 0x0400 Entry 1 (size 64 bundles) ITLB (21)
251ENTRY(itlb_miss)
252 DBG_FAULT(1)
253 /*
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800254 * The ITLB handler accesses the PTE via the virtually mapped linear
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 * page table. If a nested TLB miss occurs, we switch into physical
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800256 * mode, walk the page table, and then re-execute the PTE read and
257 * go on normally after that.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 */
Isaku Yamahata498c5172008-05-19 22:13:38 +0900259 MOV_FROM_IFA(r16) // get virtual address
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 mov r29=b0 // save b0
261 mov r31=pr // save predicates
262.itlb_fault:
Isaku Yamahata498c5172008-05-19 22:13:38 +0900263 MOV_FROM_IHA(r17) // get virtual address of PTE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 movl r30=1f // load nested fault continuation point
265 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -08002661: ld8 r18=[r17] // read *pte
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 ;;
268 mov b0=r29
269 tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
270(p6) br.cond.spnt page_fault
271 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900272 ITC_I(p0, r18, r19)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 ;;
274#ifdef CONFIG_SMP
275 /*
276 * Tell the assemblers dependency-violation checker that the above "itc" instructions
277 * cannot possibly affect the following loads:
278 */
279 dv_serialize_data
280
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800281 ld8 r19=[r17] // read *pte again and see if same
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 mov r20=PAGE_SHIFT<<2 // setup page size for purge
283 ;;
284 cmp.ne p7,p0=r18,r19
285 ;;
286(p7) ptc.l r16,r20
287#endif
288 mov pr=r31,-1
Isaku Yamahata498c5172008-05-19 22:13:38 +0900289 RFI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290END(itlb_miss)
291
292 .org ia64_ivt+0x0800
293/////////////////////////////////////////////////////////////////////////////////////////
294// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
295ENTRY(dtlb_miss)
296 DBG_FAULT(2)
297 /*
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800298 * The DTLB handler accesses the PTE via the virtually mapped linear
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 * page table. If a nested TLB miss occurs, we switch into physical
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800300 * mode, walk the page table, and then re-execute the PTE read and
301 * go on normally after that.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 */
Isaku Yamahata498c5172008-05-19 22:13:38 +0900303 MOV_FROM_IFA(r16) // get virtual address
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 mov r29=b0 // save b0
305 mov r31=pr // save predicates
306dtlb_fault:
Isaku Yamahata498c5172008-05-19 22:13:38 +0900307 MOV_FROM_IHA(r17) // get virtual address of PTE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 movl r30=1f // load nested fault continuation point
309 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -08003101: ld8 r18=[r17] // read *pte
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 ;;
312 mov b0=r29
313 tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
314(p6) br.cond.spnt page_fault
315 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900316 ITC_D(p0, r18, r19)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 ;;
318#ifdef CONFIG_SMP
319 /*
320 * Tell the assemblers dependency-violation checker that the above "itc" instructions
321 * cannot possibly affect the following loads:
322 */
323 dv_serialize_data
324
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800325 ld8 r19=[r17] // read *pte again and see if same
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 mov r20=PAGE_SHIFT<<2 // setup page size for purge
327 ;;
328 cmp.ne p7,p0=r18,r19
329 ;;
330(p7) ptc.l r16,r20
331#endif
332 mov pr=r31,-1
Isaku Yamahata498c5172008-05-19 22:13:38 +0900333 RFI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334END(dtlb_miss)
335
336 .org ia64_ivt+0x0c00
337/////////////////////////////////////////////////////////////////////////////////////////
338// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
339ENTRY(alt_itlb_miss)
340 DBG_FAULT(3)
Isaku Yamahata498c5172008-05-19 22:13:38 +0900341 MOV_FROM_IFA(r16) // get address that caused the TLB miss
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 movl r17=PAGE_KERNEL
Isaku Yamahata498c5172008-05-19 22:13:38 +0900343 MOV_FROM_IPSR(p0, r21)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
345 mov r31=pr
346 ;;
347#ifdef CONFIG_DISABLE_VHPT
348 shr.u r22=r16,61 // get the region number into r21
349 ;;
350 cmp.gt p8,p0=6,r22 // user mode
351 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900352 THASH(p8, r17, r16, r23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900354 MOV_TO_IHA(p8, r17, r23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355(p8) mov r29=b0 // save b0
356(p8) br.cond.dptk .itlb_fault
357#endif
358 extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
359 and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
360 shr.u r18=r16,57 // move address bit 61 to bit 4
361 ;;
362 andcm r18=0x10,r18 // bit 4=~address-bit(61)
363 cmp.ne p8,p0=r0,r23 // psr.cpl != 0?
364 or r19=r17,r19 // insert PTE control bits into r19
365 ;;
366 or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
367(p8) br.cond.spnt page_fault
368 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900369 ITC_I(p0, r19, r18) // insert the TLB entry
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 mov pr=r31,-1
Isaku Yamahata498c5172008-05-19 22:13:38 +0900371 RFI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372END(alt_itlb_miss)
373
374 .org ia64_ivt+0x1000
375/////////////////////////////////////////////////////////////////////////////////////////
376// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
377ENTRY(alt_dtlb_miss)
378 DBG_FAULT(4)
Isaku Yamahata498c5172008-05-19 22:13:38 +0900379 MOV_FROM_IFA(r16) // get address that caused the TLB miss
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 movl r17=PAGE_KERNEL
Isaku Yamahata498c5172008-05-19 22:13:38 +0900381 MOV_FROM_ISR(r20)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
Isaku Yamahata498c5172008-05-19 22:13:38 +0900383 MOV_FROM_IPSR(p0, r21)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 mov r31=pr
Chen, Kenneth W00b65982006-10-13 10:08:13 -0700385 mov r24=PERCPU_ADDR
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 ;;
387#ifdef CONFIG_DISABLE_VHPT
388 shr.u r22=r16,61 // get the region number into r21
389 ;;
390 cmp.gt p8,p0=6,r22 // access to region 0-5
391 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900392 THASH(p8, r17, r16, r25)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900394 MOV_TO_IHA(p8, r17, r25)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395(p8) mov r29=b0 // save b0
396(p8) br.cond.dptk dtlb_fault
397#endif
Chen, Kenneth W00b65982006-10-13 10:08:13 -0700398 cmp.ge p10,p11=r16,r24 // access to per_cpu_data?
399 tbit.z p12,p0=r16,61 // access to region 6?
400 mov r25=PERCPU_PAGE_SHIFT << 2
401 mov r26=PERCPU_PAGE_SIZE
402 nop.m 0
403 nop.b 0
404 ;;
405(p10) mov r19=IA64_KR(PER_CPU_DATA)
406(p11) and r19=r19,r16 // clear non-ppn fields
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
408 and r22=IA64_ISR_CODE_MASK,r20 // get the isr.code field
409 tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on?
411 ;;
Chen, Kenneth W00b65982006-10-13 10:08:13 -0700412(p10) sub r19=r19,r26
Isaku Yamahata498c5172008-05-19 22:13:38 +0900413 MOV_TO_ITIR(p10, r25, r24)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 cmp.ne p8,p0=r0,r23
415(p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field
Chen, Kenneth W00b65982006-10-13 10:08:13 -0700416(p12) dep r17=-1,r17,4,1 // set ma=UC for region 6 addr
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417(p8) br.cond.spnt page_fault
418
419 dep r21=-1,r21,IA64_PSR_ED_BIT,1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 ;;
Chen, Kenneth W00b65982006-10-13 10:08:13 -0700421 or r19=r19,r17 // insert PTE control bits into r19
Isaku Yamahata498c5172008-05-19 22:13:38 +0900422 MOV_TO_IPSR(p6, r21, r24)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900424 ITC_D(p7, r19, r18) // insert the TLB entry
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 mov pr=r31,-1
Isaku Yamahata498c5172008-05-19 22:13:38 +0900426 RFI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427END(alt_dtlb_miss)
428
429 .org ia64_ivt+0x1400
430/////////////////////////////////////////////////////////////////////////////////////////
431// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
432ENTRY(nested_dtlb_miss)
433 /*
434 * In the absence of kernel bugs, we get here when the virtually mapped linear
435 * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction
436 * Access-bit, or Data Access-bit faults). If the DTLB entry for the virtual page
437 * table is missing, a nested TLB miss fault is triggered and control is
438 * transferred to this point. When this happens, we lookup the pte for the
439 * faulting address by walking the page table in physical mode and return to the
440 * continuation point passed in register r30 (or call page_fault if the address is
441 * not mapped).
442 *
443 * Input: r16: faulting address
444 * r29: saved b0
445 * r30: continuation address
446 * r31: saved pr
447 *
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800448 * Output: r17: physical address of PTE of faulting address
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 * r29: saved b0
450 * r30: continuation address
451 * r31: saved pr
452 *
Ken Chen0393eed2005-06-21 14:40:31 -0700453 * Clobbered: b0, r18, r19, r21, r22, psr.dt (cleared)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 */
Isaku Yamahata498c5172008-05-19 22:13:38 +0900455 RSM_PSR_DT // switch to using physical data addressing
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 mov r19=IA64_KR(PT_BASE) // get the page table base address
457 shl r21=r16,3 // shift bit 60 into sign bit
Isaku Yamahata498c5172008-05-19 22:13:38 +0900458 MOV_FROM_ITIR(r18)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 ;;
460 shr.u r17=r16,61 // get the region number into r17
Ken Chen0393eed2005-06-21 14:40:31 -0700461 extr.u r18=r18,2,6 // get the faulting page size
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 ;;
463 cmp.eq p6,p7=5,r17 // is faulting address in region 5?
Ken Chen0393eed2005-06-21 14:40:31 -0700464 add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address
465 add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 ;;
Ken Chen0393eed2005-06-21 14:40:31 -0700467 shr.u r22=r16,r22
468 shr.u r18=r16,r18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
470
471 srlz.d
472 LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
473
474 .pred.rel "mutex", p6, p7
475(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
476(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
477 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800478(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
479(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
Robin Holt837cd0b2005-11-11 09:35:43 -0600481#ifdef CONFIG_PGTABLE_4
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800482 shr.u r18=r22,PUD_SHIFT // shift pud index into position
Robin Holt837cd0b2005-11-11 09:35:43 -0600483#else
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800484 shr.u r18=r22,PMD_SHIFT // shift pmd index into position
Robin Holt837cd0b2005-11-11 09:35:43 -0600485#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800487 ld8 r17=[r17] // get *pgd (may be 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800489(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
490 dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=p[u|m]d_offset(pgd,addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 ;;
Robin Holt837cd0b2005-11-11 09:35:43 -0600492#ifdef CONFIG_PGTABLE_4
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800493(p7) ld8 r17=[r17] // get *pud (may be 0)
494 shr.u r18=r22,PMD_SHIFT // shift pmd index into position
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800496(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pud_present(*pud) == NULL?
497 dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
Robin Holt837cd0b2005-11-11 09:35:43 -0600498 ;;
499#endif
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800500(p7) ld8 r17=[r17] // get *pmd (may be 0)
501 shr.u r19=r22,PAGE_SHIFT // shift pte index into position
Robin Holt837cd0b2005-11-11 09:35:43 -0600502 ;;
Chen, Kenneth We8aabc42005-11-17 01:55:34 -0800503(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pmd_present(*pmd) == NULL?
504 dep r17=r19,r17,3,(PAGE_SHIFT-3) // r17=pte_offset(pmd,addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505(p6) br.cond.spnt page_fault
506 mov b0=r30
507 br.sptk.many b0 // return to continuation point
508END(nested_dtlb_miss)
509
510 .org ia64_ivt+0x1800
511/////////////////////////////////////////////////////////////////////////////////////////
512// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
513ENTRY(ikey_miss)
514 DBG_FAULT(6)
515 FAULT(6)
516END(ikey_miss)
517
518 //-----------------------------------------------------------------------------------
519 // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
520ENTRY(page_fault)
Isaku Yamahata498c5172008-05-19 22:13:38 +0900521 SSM_PSR_DT_AND_SRLZ_I
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 ;;
523 SAVE_MIN_WITH_COVER
524 alloc r15=ar.pfs,0,0,3,0
Isaku Yamahata498c5172008-05-19 22:13:38 +0900525 MOV_FROM_IFA(out0)
526 MOV_FROM_ISR(out1)
527 SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r14, r3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 adds r3=8,r2 // set up second base pointer
Isaku Yamahata498c5172008-05-19 22:13:38 +0900529 SSM_PSR_I(p15, p15, r14) // restore psr.i
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 movl r14=ia64_leave_kernel
531 ;;
532 SAVE_REST
533 mov rp=r14
534 ;;
535 adds out2=16,r12 // out2 = pointer to pt_regs
536 br.call.sptk.many b6=ia64_do_page_fault // ignore return address
537END(page_fault)
538
539 .org ia64_ivt+0x1c00
540/////////////////////////////////////////////////////////////////////////////////////////
541// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
542ENTRY(dkey_miss)
543 DBG_FAULT(7)
544 FAULT(7)
545END(dkey_miss)
546
547 .org ia64_ivt+0x2000
548/////////////////////////////////////////////////////////////////////////////////////////
549// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
550ENTRY(dirty_bit)
551 DBG_FAULT(8)
552 /*
553 * What we do here is to simply turn on the dirty bit in the PTE. We need to
554 * update both the page-table and the TLB entry. To efficiently access the PTE,
555 * we address it through the virtual page table. Most likely, the TLB entry for
556 * the relevant virtual page table page is still present in the TLB so we can
557 * normally do this without additional TLB misses. In case the necessary virtual
558 * page table TLB entry isn't present, we take a nested TLB miss hit where we look
559 * up the physical address of the L3 PTE and then continue at label 1 below.
560 */
Isaku Yamahata498c5172008-05-19 22:13:38 +0900561 MOV_FROM_IFA(r16) // get the address that caused the fault
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 movl r30=1f // load continuation point in case of nested fault
563 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900564 THASH(p0, r17, r16, r18) // compute virtual address of L3 PTE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 mov r29=b0 // save b0 in case of nested fault
566 mov r31=pr // save pr
567#ifdef CONFIG_SMP
568 mov r28=ar.ccv // save ar.ccv
569 ;;
5701: ld8 r18=[r17]
571 ;; // avoid RAW on r18
572 mov ar.ccv=r18 // set compare value for cmpxchg
573 or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
Christoph Lameterd8117ce2006-03-07 19:05:32 -0800574 tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 ;;
Christoph Lameterd8117ce2006-03-07 19:05:32 -0800576(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only update if page is present
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 mov r24=PAGE_SHIFT<<2
578 ;;
Christoph Lameterd8117ce2006-03-07 19:05:32 -0800579(p6) cmp.eq p6,p7=r26,r18 // Only compare if page is present
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900581 ITC_D(p6, r25, r18) // install updated PTE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 ;;
583 /*
584 * Tell the assemblers dependency-violation checker that the above "itc" instructions
585 * cannot possibly affect the following loads:
586 */
587 dv_serialize_data
588
589 ld8 r18=[r17] // read PTE again
590 ;;
591 cmp.eq p6,p7=r18,r25 // is it same as the newly installed
592 ;;
593(p7) ptc.l r16,r24
594 mov b0=r29 // restore b0
595 mov ar.ccv=r28
596#else
597 ;;
5981: ld8 r18=[r17]
599 ;; // avoid RAW on r18
600 or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
601 mov b0=r29 // restore b0
602 ;;
603 st8 [r17]=r18 // store back updated PTE
604 itc.d r18 // install updated PTE
605#endif
606 mov pr=r31,-1 // restore pr
Isaku Yamahata498c5172008-05-19 22:13:38 +0900607 RFI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608END(dirty_bit)
609
610 .org ia64_ivt+0x2400
611/////////////////////////////////////////////////////////////////////////////////////////
612// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
613ENTRY(iaccess_bit)
614 DBG_FAULT(9)
615 // Like Entry 8, except for instruction access
Isaku Yamahata498c5172008-05-19 22:13:38 +0900616 MOV_FROM_IFA(r16) // get the address that caused the fault
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 movl r30=1f // load continuation point in case of nested fault
618 mov r31=pr // save predicates
619#ifdef CONFIG_ITANIUM
620 /*
621 * Erratum 10 (IFA may contain incorrect address) has "NoFix" status.
622 */
Isaku Yamahata498c5172008-05-19 22:13:38 +0900623 MOV_FROM_IPSR(p0, r17)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900625 MOV_FROM_IIP(r18)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set?
627 ;;
628(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa
629#endif /* CONFIG_ITANIUM */
630 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900631 THASH(p0, r17, r16, r18) // compute virtual address of L3 PTE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 mov r29=b0 // save b0 in case of nested fault)
633#ifdef CONFIG_SMP
634 mov r28=ar.ccv // save ar.ccv
635 ;;
6361: ld8 r18=[r17]
637 ;;
638 mov ar.ccv=r18 // set compare value for cmpxchg
639 or r25=_PAGE_A,r18 // set the accessed bit
Christoph Lameterd8117ce2006-03-07 19:05:32 -0800640 tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 ;;
Christoph Lameterd8117ce2006-03-07 19:05:32 -0800642(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page present
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 mov r24=PAGE_SHIFT<<2
644 ;;
Christoph Lameterd8117ce2006-03-07 19:05:32 -0800645(p6) cmp.eq p6,p7=r26,r18 // Only if page present
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900647 ITC_I(p6, r25, r26) // install updated PTE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 ;;
649 /*
650 * Tell the assemblers dependency-violation checker that the above "itc" instructions
651 * cannot possibly affect the following loads:
652 */
653 dv_serialize_data
654
655 ld8 r18=[r17] // read PTE again
656 ;;
657 cmp.eq p6,p7=r18,r25 // is it same as the newly installed
658 ;;
659(p7) ptc.l r16,r24
660 mov b0=r29 // restore b0
661 mov ar.ccv=r28
662#else /* !CONFIG_SMP */
663 ;;
6641: ld8 r18=[r17]
665 ;;
666 or r18=_PAGE_A,r18 // set the accessed bit
667 mov b0=r29 // restore b0
668 ;;
669 st8 [r17]=r18 // store back updated PTE
670 itc.i r18 // install updated PTE
671#endif /* !CONFIG_SMP */
672 mov pr=r31,-1
Isaku Yamahata498c5172008-05-19 22:13:38 +0900673 RFI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674END(iaccess_bit)
675
676 .org ia64_ivt+0x2800
677/////////////////////////////////////////////////////////////////////////////////////////
678// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
679ENTRY(daccess_bit)
680 DBG_FAULT(10)
681 // Like Entry 8, except for data access
Isaku Yamahata498c5172008-05-19 22:13:38 +0900682 MOV_FROM_IFA(r16) // get the address that caused the fault
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 movl r30=1f // load continuation point in case of nested fault
684 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900685 THASH(p0, r17, r16, r18) // compute virtual address of L3 PTE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 mov r31=pr
687 mov r29=b0 // save b0 in case of nested fault)
688#ifdef CONFIG_SMP
689 mov r28=ar.ccv // save ar.ccv
690 ;;
6911: ld8 r18=[r17]
692 ;; // avoid RAW on r18
693 mov ar.ccv=r18 // set compare value for cmpxchg
694 or r25=_PAGE_A,r18 // set the dirty bit
Christoph Lameterd8117ce2006-03-07 19:05:32 -0800695 tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 ;;
Christoph Lameterd8117ce2006-03-07 19:05:32 -0800697(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page is present
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 mov r24=PAGE_SHIFT<<2
699 ;;
Christoph Lameterd8117ce2006-03-07 19:05:32 -0800700(p6) cmp.eq p6,p7=r26,r18 // Only if page is present
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +0900702 ITC_D(p6, r25, r26) // install updated PTE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 /*
704 * Tell the assemblers dependency-violation checker that the above "itc" instructions
705 * cannot possibly affect the following loads:
706 */
707 dv_serialize_data
708 ;;
709 ld8 r18=[r17] // read PTE again
710 ;;
711 cmp.eq p6,p7=r18,r25 // is it same as the newly installed
712 ;;
713(p7) ptc.l r16,r24
714 mov ar.ccv=r28
715#else
716 ;;
7171: ld8 r18=[r17]
718 ;; // avoid RAW on r18
719 or r18=_PAGE_A,r18 // set the accessed bit
720 ;;
721 st8 [r17]=r18 // store back updated PTE
722 itc.d r18 // install updated PTE
723#endif
724 mov b0=r29 // restore b0
725 mov pr=r31,-1
Isaku Yamahata498c5172008-05-19 22:13:38 +0900726 RFI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727END(daccess_bit)
728
729 .org ia64_ivt+0x2c00
730/////////////////////////////////////////////////////////////////////////////////////////
731// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
732ENTRY(break_fault)
733 /*
734 * The streamlined system call entry/exit paths only save/restore the initial part
735 * of pt_regs. This implies that the callers of system-calls must adhere to the
736 * normal procedure calling conventions.
737 *
738 * Registers to be saved & restored:
739 * CR registers: cr.ipsr, cr.iip, cr.ifs
740 * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr
741 * others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15
742 * Registers to be restored only:
743 * r8-r11: output value from the system call.
744 *
745 * During system call exit, scratch registers (including r15) are modified/cleared
746 * to prevent leaking bits from kernel to user level.
747 */
748 DBG_FAULT(11)
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700749 mov.m r16=IA64_KR(CURRENT) // M2 r16 <- current task (12 cyc)
Isaku Yamahata498c5172008-05-19 22:13:38 +0900750 MOV_FROM_IPSR(p0, r29) // M2 (12 cyc)
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700751 mov r31=pr // I0 (2 cyc)
752
Isaku Yamahata498c5172008-05-19 22:13:38 +0900753 MOV_FROM_IIM(r17) // M2 (2 cyc)
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700754 mov.m r27=ar.rsc // M2 (12 cyc)
755 mov r18=__IA64_BREAK_SYSCALL // A
756
757 mov.m ar.rsc=0 // M2
758 mov.m r21=ar.fpsr // M2 (12 cyc)
759 mov r19=b6 // I0 (2 cyc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 ;;
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700761 mov.m r23=ar.bspstore // M2 (12 cyc)
762 mov.m r24=ar.rnat // M2 (5 cyc)
763 mov.i r26=ar.pfs // I0 (2 cyc)
764
765 invala // M0|1
766 nop.m 0 // M
767 mov r20=r1 // A save r1
768
769 nop.m 0
770 movl r30=sys_call_table // X
771
Isaku Yamahata498c5172008-05-19 22:13:38 +0900772 MOV_FROM_IIP(r28) // M2 (2 cyc)
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700773 cmp.eq p0,p7=r18,r17 // I0 is this a system call?
774(p7) br.cond.spnt non_syscall // B no ->
775 //
776 // From this point on, we are definitely on the syscall-path
777 // and we can use (non-banked) scratch registers.
778 //
779///////////////////////////////////////////////////////////////////////
780 mov r1=r16 // A move task-pointer to "addl"-addressable reg
781 mov r2=r16 // A setup r2 for ia64_syscall_setup
782 add r9=TI_FLAGS+IA64_TASK_SIZE,r16 // A r9 = &current_thread_info()->flags
783
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700785 adds r15=-1024,r15 // A subtract 1024 from syscall number
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 mov r3=NR_syscalls - 1
787 ;;
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700788 ld1.bias r17=[r16] // M0|1 r17 = current->thread.on_ustack flag
789 ld4 r9=[r9] // M0|1 r9 = current_thread_info()->flags
790 extr.u r8=r29,41,2 // I0 extract ei field from cr.ipsr
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700792 shladd r30=r15,3,r30 // A r30 = sys_call_table + 8*(syscall-1024)
793 addl r22=IA64_RBS_OFFSET,r1 // A compute base of RBS
794 cmp.leu p6,p7=r15,r3 // A syscall number in range?
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 ;;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700797 lfetch.fault.excl.nt1 [r22] // M0|1 prefetch RBS
798(p6) ld8 r30=[r30] // M0|1 load address of syscall entry point
799 tnat.nz.or p7,p0=r15 // I0 is syscall nr a NaT?
800
801 mov.m ar.bspstore=r22 // M2 switch to kernel RBS
802 cmp.eq p8,p9=2,r8 // A isr.ei==2?
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 ;;
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700804
805(p8) mov r8=0 // A clear ei to 0
806(p7) movl r30=sys_ni_syscall // X
807
808(p8) adds r28=16,r28 // A switch cr.iip to next bundle
809(p9) adds r8=1,r8 // A increment ei to next slot
Hidetoshi Setob64f34c2008-01-29 14:27:30 +0900810#ifdef CONFIG_VIRT_CPU_ACCOUNTING
811 ;;
812 mov b6=r30 // I0 setup syscall handler branch reg early
813#else
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700814 nop.i 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 ;;
Hidetoshi Setob64f34c2008-01-29 14:27:30 +0900816#endif
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700817
818 mov.m r25=ar.unat // M2 (5 cyc)
819 dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr
820 adds r15=1024,r15 // A restore original syscall number
821 //
822 // If any of the above loads miss in L1D, we'll stall here until
823 // the data arrives.
824 //
825///////////////////////////////////////////////////////////////////////
826 st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag
Hidetoshi Setob64f34c2008-01-29 14:27:30 +0900827#ifdef CONFIG_VIRT_CPU_ACCOUNTING
828 mov.m r30=ar.itc // M get cycle for accounting
829#else
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700830 mov b6=r30 // I0 setup syscall handler branch reg early
Hidetoshi Setob64f34c2008-01-29 14:27:30 +0900831#endif
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700832 cmp.eq pKStk,pUStk=r0,r17 // A were we on kernel stacks already?
833
834 and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit
835 mov r18=ar.bsp // M2 (12 cyc)
836(pKStk) br.cond.spnt .break_fixup // B we're already in kernel-mode -- fix up RBS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 ;;
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700838.back_from_break_fixup:
839(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1 // A compute base of memory stack
840 cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited?
841 br.call.sptk.many b7=ia64_syscall_setup // B
8421:
Hidetoshi Setob64f34c2008-01-29 14:27:30 +0900843#ifdef CONFIG_VIRT_CPU_ACCOUNTING
844 // mov.m r30=ar.itc is called in advance, and r13 is current
845 add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13 // A
846 add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13 // A
847(pKStk) br.cond.spnt .skip_accounting // B unlikely skip
848 ;;
849 ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // M get last stamp
850 ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // M time at leave
851 ;;
852 ld8 r20=[r16],TI_AC_STAMP-TI_AC_STIME // M cumulated stime
853 ld8 r21=[r17] // M cumulated utime
854 sub r22=r19,r18 // A stime before leave
855 ;;
856 st8 [r16]=r30,TI_AC_STIME-TI_AC_STAMP // M update stamp
857 sub r18=r30,r19 // A elapsed time in user
858 ;;
859 add r20=r20,r22 // A sum stime
860 add r21=r21,r18 // A sum utime
861 ;;
862 st8 [r16]=r20 // M update stime
863 st8 [r17]=r21 // M update utime
864 ;;
865.skip_accounting:
866#endif
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700867 mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0
868 nop 0
Isaku Yamahata498c5172008-05-19 22:13:38 +0900869 BSW_1(r2, r14) // B (6 cyc) regs are saved, switch to bank 1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 ;;
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700871
Isaku Yamahata498c5172008-05-19 22:13:38 +0900872 SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r16) // M2 now it's safe to re-enable intr.-collection
873 // M0 ensure interruption collection is on
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700874 movl r3=ia64_ret_from_syscall // X
875 ;;
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700876 mov rp=r3 // I0 set the real return addr
877(p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT
878
Isaku Yamahata498c5172008-05-19 22:13:38 +0900879 SSM_PSR_I(p15, p15, r16) // M2 restore psr.i
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700880(p14) br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr)
881 br.cond.spnt.many ia64_trace_syscall // B do syscall-tracing thingamagic
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 // NOT REACHED
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700883///////////////////////////////////////////////////////////////////////
884 // On entry, we optimistically assumed that we're coming from user-space.
885 // For the rare cases where a system-call is done from within the kernel,
886 // we fix things up at this point:
887.break_fixup:
888 add r1=-IA64_PT_REGS_SIZE,sp // A allocate space for pt_regs structure
889 mov ar.rnat=r24 // M2 restore kernel's AR.RNAT
890 ;;
891 mov ar.bspstore=r23 // M2 restore kernel's AR.BSPSTORE
892 br.cond.sptk .back_from_break_fixup
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893END(break_fault)
894
895 .org ia64_ivt+0x3000
896/////////////////////////////////////////////////////////////////////////////////////////
897// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
898ENTRY(interrupt)
899 DBG_FAULT(12)
900 mov r31=pr // prepare to save predicates
901 ;;
902 SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3
Isaku Yamahata498c5172008-05-19 22:13:38 +0900903 SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r14)
904 // ensure everybody knows psr.ic is back on
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 adds r3=8,r2 // set up second base pointer for SAVE_REST
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 ;;
907 SAVE_REST
908 ;;
Russ Andersond2a28ad2006-03-24 09:49:52 -0800909 MCA_RECOVER_RANGE(interrupt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
Isaku Yamahata498c5172008-05-19 22:13:38 +0900911 MOV_FROM_IVR(out0, r8) // pass cr.ivr as first arg
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 add out1=16,sp // pass pointer to pt_regs as second arg
913 ;;
914 srlz.d // make sure we see the effect of cr.ivr
915 movl r14=ia64_leave_kernel
916 ;;
917 mov rp=r14
918 br.call.sptk.many b6=ia64_handle_irq
919END(interrupt)
920
921 .org ia64_ivt+0x3400
922/////////////////////////////////////////////////////////////////////////////////////////
923// 0x3400 Entry 13 (size 64 bundles) Reserved
924 DBG_FAULT(13)
925 FAULT(13)
926
927 .org ia64_ivt+0x3800
928/////////////////////////////////////////////////////////////////////////////////////////
929// 0x3800 Entry 14 (size 64 bundles) Reserved
930 DBG_FAULT(14)
931 FAULT(14)
932
933 /*
934 * There is no particular reason for this code to be here, other than that
935 * there happens to be space here that would go unused otherwise. If this
936 * fault ever gets "unreserved", simply moved the following code to a more
937 * suitable spot...
938 *
939 * ia64_syscall_setup() is a separate subroutine so that it can
940 * allocate stacked registers so it can safely demine any
941 * potential NaT values from the input registers.
942 *
943 * On entry:
944 * - executing on bank 0 or bank 1 register set (doesn't matter)
945 * - r1: stack pointer
946 * - r2: current task pointer
947 * - r3: preserved
948 * - r11: original contents (saved ar.pfs to be saved)
949 * - r12: original contents (sp to be saved)
950 * - r13: original contents (tp to be saved)
951 * - r15: original contents (syscall # to be saved)
952 * - r18: saved bsp (after switching to kernel stack)
953 * - r19: saved b6
954 * - r20: saved r1 (gp)
955 * - r21: saved ar.fpsr
956 * - r22: kernel's register backing store base (krbs_base)
957 * - r23: saved ar.bspstore
958 * - r24: saved ar.rnat
959 * - r25: saved ar.unat
960 * - r26: saved ar.pfs
961 * - r27: saved ar.rsc
962 * - r28: saved cr.iip
963 * - r29: saved cr.ipsr
Hidetoshi Setob64f34c2008-01-29 14:27:30 +0900964 * - r30: ar.itc for accounting (don't touch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 * - r31: saved pr
966 * - b0: original contents (to be saved)
967 * On exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 * - p10: TRUE if syscall is invoked with more than 8 out
969 * registers or r15's Nat is true
970 * - r1: kernel's gp
971 * - r3: preserved (same as on entry)
972 * - r8: -EINVAL if p10 is true
973 * - r12: points to kernel stack
974 * - r13: points to current task
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700975 * - r14: preserved (same as on entry)
976 * - p13: preserved
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 * - p15: TRUE if interrupts need to be re-enabled
978 * - ar.fpsr: set to kernel settings
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -0700979 * - b6: preserved (same as on entry)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 */
Isaku Yamahata498c5172008-05-19 22:13:38 +0900981#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982GLOBAL_ENTRY(ia64_syscall_setup)
983#if PT(B6) != 0
984# error This code assumes that b6 is the first field in pt_regs.
985#endif
986 st8 [r1]=r19 // save b6
987 add r16=PT(CR_IPSR),r1 // initialize first base pointer
988 add r17=PT(R11),r1 // initialize second base pointer
989 ;;
990 alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable
991 st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr
992 tnat.nz p8,p0=in0
993
994 st8.spill [r17]=r11,PT(CR_IIP)-PT(R11) // save r11
995 tnat.nz p9,p0=in1
996(pKStk) mov r18=r0 // make sure r18 isn't NaT
997 ;;
998
999 st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS) // save ar.pfs
1000 st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP) // save cr.iip
1001 mov r28=b0 // save b0 (2 cyc)
1002 ;;
1003
1004 st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT) // save ar.unat
1005 dep r19=0,r19,38,26 // clear all bits but 0..37 [I0]
1006(p8) mov in0=-1
1007 ;;
1008
1009 st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS) // store ar.pfs.pfm in cr.ifs
1010 extr.u r11=r19,7,7 // I0 // get sol of ar.pfs
1011 and r8=0x7f,r19 // A // get sof of ar.pfs
1012
1013 st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc
1014 tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0
1015(p9) mov in1=-1
1016 ;;
1017
1018(pUStk) sub r18=r18,r22 // r18=RSE.ndirty*8
1019 tnat.nz p10,p0=in2
1020 add r11=8,r11
1021 ;;
1022(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16 // skip over ar_rnat field
1023(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17 // skip over ar_bspstore field
1024 tnat.nz p11,p0=in3
1025 ;;
1026(p10) mov in2=-1
1027 tnat.nz p12,p0=in4 // [I0]
1028(p11) mov in3=-1
1029 ;;
1030(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat
1031(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore
1032 shl r18=r18,16 // compute ar.rsc to be used for "loadrs"
1033 ;;
1034 st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates
1035 st8 [r17]=r28,PT(R1)-PT(B0) // save b0
1036 tnat.nz p13,p0=in5 // [I0]
1037 ;;
1038 st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs"
1039 st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1
1040(p12) mov in4=-1
1041 ;;
1042
1043.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12) // save r12
1044.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13) // save r13
1045(p13) mov in5=-1
1046 ;;
1047 st8 [r16]=r21,PT(R8)-PT(AR_FPSR) // save ar.fpsr
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -07001048 tnat.nz p13,p0=in6
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 cmp.lt p10,p9=r11,r8 // frame size can't be more than local+8
1050 ;;
David Mosberger-Tang060561f2005-04-27 21:17:03 -07001051 mov r8=1
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052(p9) tnat.nz p10,p0=r15
1053 adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch)
1054
1055 st8.spill [r17]=r15 // save r15
1056 tnat.nz p8,p0=in7
1057 nop.i 0
1058
1059 mov r13=r2 // establish `current'
1060 movl r1=__gp // establish kernel global pointer
1061 ;;
David Mosberger-Tang060561f2005-04-27 21:17:03 -07001062 st8 [r16]=r8 // ensure pt_regs.r8 != 0 (see handle_syscall_error)
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -07001063(p13) mov in6=-1
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064(p8) mov in7=-1
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
1066 cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
1067 movl r17=FPSR_DEFAULT
1068 ;;
1069 mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value
1070(p10) mov r8=-EINVAL
1071 br.ret.sptk.many b7
1072END(ia64_syscall_setup)
Isaku Yamahata498c5172008-05-19 22:13:38 +09001073#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074
1075 .org ia64_ivt+0x3c00
1076/////////////////////////////////////////////////////////////////////////////////////////
1077// 0x3c00 Entry 15 (size 64 bundles) Reserved
1078 DBG_FAULT(15)
1079 FAULT(15)
1080
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 .org ia64_ivt+0x4000
1082/////////////////////////////////////////////////////////////////////////////////////////
1083// 0x4000 Entry 16 (size 64 bundles) Reserved
1084 DBG_FAULT(16)
1085 FAULT(16)
1086
Isaku Yamahata498c5172008-05-19 22:13:38 +09001087#if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(__IA64_ASM_PARAVIRTUALIZED_NATIVE)
Hidetoshi Setob64f34c2008-01-29 14:27:30 +09001088 /*
1089 * There is no particular reason for this code to be here, other than
1090 * that there happens to be space here that would go unused otherwise.
1091 * If this fault ever gets "unreserved", simply moved the following
1092 * code to a more suitable spot...
1093 *
1094 * account_sys_enter is called from SAVE_MIN* macros if accounting is
1095 * enabled and if the macro is entered from user mode.
1096 */
Isaku Yamahata498c5172008-05-19 22:13:38 +09001097GLOBAL_ENTRY(account_sys_enter)
Hidetoshi Setob64f34c2008-01-29 14:27:30 +09001098 // mov.m r20=ar.itc is called in advance, and r13 is current
1099 add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13
1100 add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13
1101 ;;
1102 ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // time at last check in kernel
1103 ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // time at left from kernel
1104 ;;
1105 ld8 r23=[r16],TI_AC_STAMP-TI_AC_STIME // cumulated stime
1106 ld8 r21=[r17] // cumulated utime
1107 sub r22=r19,r18 // stime before leave kernel
1108 ;;
1109 st8 [r16]=r20,TI_AC_STIME-TI_AC_STAMP // update stamp
1110 sub r18=r20,r19 // elapsed time in user mode
1111 ;;
1112 add r23=r23,r22 // sum stime
1113 add r21=r21,r18 // sum utime
1114 ;;
1115 st8 [r16]=r23 // update stime
1116 st8 [r17]=r21 // update utime
1117 ;;
1118 br.ret.sptk.many rp
1119END(account_sys_enter)
1120#endif
1121
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 .org ia64_ivt+0x4400
1123/////////////////////////////////////////////////////////////////////////////////////////
1124// 0x4400 Entry 17 (size 64 bundles) Reserved
1125 DBG_FAULT(17)
1126 FAULT(17)
1127
1128ENTRY(non_syscall)
David Mosberger-Tangf8fa5442005-04-27 21:19:04 -07001129 mov ar.rsc=r27 // restore ar.rsc before SAVE_MIN_WITH_COVER
1130 ;;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 SAVE_MIN_WITH_COVER
1132
1133 // There is no particular reason for this code to be here, other than that
1134 // there happens to be space here that would go unused otherwise. If this
1135 // fault ever gets "unreserved", simply moved the following code to a more
1136 // suitable spot...
1137
1138 alloc r14=ar.pfs,0,0,2,0
Isaku Yamahata498c5172008-05-19 22:13:38 +09001139 MOV_FROM_IIM(out0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 add out1=16,sp
1141 adds r3=8,r2 // set up second base pointer for SAVE_REST
1142
Isaku Yamahata498c5172008-05-19 22:13:38 +09001143 SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r15, r24)
1144 // guarantee that interruption collection is on
1145 SSM_PSR_I(p15, p15, r15) // restore psr.i
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 movl r15=ia64_leave_kernel
1147 ;;
1148 SAVE_REST
1149 mov rp=r15
1150 ;;
1151 br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr
1152END(non_syscall)
1153
1154 .org ia64_ivt+0x4800
1155/////////////////////////////////////////////////////////////////////////////////////////
1156// 0x4800 Entry 18 (size 64 bundles) Reserved
1157 DBG_FAULT(18)
1158 FAULT(18)
1159
1160 /*
1161 * There is no particular reason for this code to be here, other than that
1162 * there happens to be space here that would go unused otherwise. If this
1163 * fault ever gets "unreserved", simply moved the following code to a more
1164 * suitable spot...
1165 */
1166
1167ENTRY(dispatch_unaligned_handler)
1168 SAVE_MIN_WITH_COVER
1169 ;;
1170 alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!)
Isaku Yamahata498c5172008-05-19 22:13:38 +09001171 MOV_FROM_IFA(out0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 adds out1=16,sp
1173
Isaku Yamahata498c5172008-05-19 22:13:38 +09001174 SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24)
1175 // guarantee that interruption collection is on
1176 SSM_PSR_I(p15, p15, r3) // restore psr.i
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 adds r3=8,r2 // set up second base pointer
1178 ;;
1179 SAVE_REST
1180 movl r14=ia64_leave_kernel
1181 ;;
1182 mov rp=r14
1183 br.sptk.many ia64_prepare_handle_unaligned
1184END(dispatch_unaligned_handler)
1185
1186 .org ia64_ivt+0x4c00
1187/////////////////////////////////////////////////////////////////////////////////////////
1188// 0x4c00 Entry 19 (size 64 bundles) Reserved
1189 DBG_FAULT(19)
1190 FAULT(19)
1191
1192 /*
1193 * There is no particular reason for this code to be here, other than that
1194 * there happens to be space here that would go unused otherwise. If this
1195 * fault ever gets "unreserved", simply moved the following code to a more
1196 * suitable spot...
1197 */
1198
1199ENTRY(dispatch_to_fault_handler)
1200 /*
1201 * Input:
1202 * psr.ic: off
1203 * r19: fault vector number (e.g., 24 for General Exception)
1204 * r31: contains saved predicates (pr)
1205 */
1206 SAVE_MIN_WITH_COVER_R19
1207 alloc r14=ar.pfs,0,0,5,0
Isaku Yamahata498c5172008-05-19 22:13:38 +09001208 MOV_FROM_ISR(out1)
1209 MOV_FROM_IFA(out2)
1210 MOV_FROM_IIM(out3)
1211 MOV_FROM_ITIR(out4)
1212 ;;
1213 SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, out0)
1214 // guarantee that interruption collection is on
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 mov out0=r15
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +09001217 SSM_PSR_I(p15, p15, r3) // restore psr.i
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 adds r3=8,r2 // set up second base pointer for SAVE_REST
1219 ;;
1220 SAVE_REST
1221 movl r14=ia64_leave_kernel
1222 ;;
1223 mov rp=r14
1224 br.call.sptk.many b6=ia64_fault
1225END(dispatch_to_fault_handler)
1226
1227//
1228// --- End of long entries, Beginning of short entries
1229//
1230
1231 .org ia64_ivt+0x5000
1232/////////////////////////////////////////////////////////////////////////////////////////
1233// 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49)
1234ENTRY(page_not_present)
1235 DBG_FAULT(20)
Isaku Yamahata498c5172008-05-19 22:13:38 +09001236 MOV_FROM_IFA(r16)
1237 RSM_PSR_DT
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 /*
1239 * The Linux page fault handler doesn't expect non-present pages to be in
1240 * the TLB. Flush the existing entry now, so we meet that expectation.
1241 */
1242 mov r17=PAGE_SHIFT<<2
1243 ;;
1244 ptc.l r16,r17
1245 ;;
1246 mov r31=pr
1247 srlz.d
1248 br.sptk.many page_fault
1249END(page_not_present)
1250
1251 .org ia64_ivt+0x5100
1252/////////////////////////////////////////////////////////////////////////////////////////
1253// 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52)
1254ENTRY(key_permission)
1255 DBG_FAULT(21)
Isaku Yamahata498c5172008-05-19 22:13:38 +09001256 MOV_FROM_IFA(r16)
1257 RSM_PSR_DT
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 mov r31=pr
1259 ;;
1260 srlz.d
1261 br.sptk.many page_fault
1262END(key_permission)
1263
1264 .org ia64_ivt+0x5200
1265/////////////////////////////////////////////////////////////////////////////////////////
1266// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
1267ENTRY(iaccess_rights)
1268 DBG_FAULT(22)
Isaku Yamahata498c5172008-05-19 22:13:38 +09001269 MOV_FROM_IFA(r16)
1270 RSM_PSR_DT
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 mov r31=pr
1272 ;;
1273 srlz.d
1274 br.sptk.many page_fault
1275END(iaccess_rights)
1276
1277 .org ia64_ivt+0x5300
1278/////////////////////////////////////////////////////////////////////////////////////////
1279// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
1280ENTRY(daccess_rights)
1281 DBG_FAULT(23)
Isaku Yamahata498c5172008-05-19 22:13:38 +09001282 MOV_FROM_IFA(r16)
1283 RSM_PSR_DT
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 mov r31=pr
1285 ;;
1286 srlz.d
1287 br.sptk.many page_fault
1288END(daccess_rights)
1289
1290 .org ia64_ivt+0x5400
1291/////////////////////////////////////////////////////////////////////////////////////////
1292// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
1293ENTRY(general_exception)
1294 DBG_FAULT(24)
Isaku Yamahata498c5172008-05-19 22:13:38 +09001295 MOV_FROM_ISR(r16)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 mov r31=pr
1297 ;;
1298 cmp4.eq p6,p0=0,r16
1299(p6) br.sptk.many dispatch_illegal_op_fault
1300 ;;
1301 mov r19=24 // fault number
1302 br.sptk.many dispatch_to_fault_handler
1303END(general_exception)
1304
1305 .org ia64_ivt+0x5500
1306/////////////////////////////////////////////////////////////////////////////////////////
1307// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
1308ENTRY(disabled_fp_reg)
1309 DBG_FAULT(25)
1310 rsm psr.dfh // ensure we can access fph
1311 ;;
1312 srlz.d
1313 mov r31=pr
1314 mov r19=25
1315 br.sptk.many dispatch_to_fault_handler
1316END(disabled_fp_reg)
1317
1318 .org ia64_ivt+0x5600
1319/////////////////////////////////////////////////////////////////////////////////////////
1320// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
1321ENTRY(nat_consumption)
1322 DBG_FAULT(26)
David Mosberger-Tang458f9352005-05-04 13:25:00 -07001323
Isaku Yamahata498c5172008-05-19 22:13:38 +09001324 MOV_FROM_IPSR(p0, r16)
1325 MOV_FROM_ISR(r17)
David Mosberger-Tang458f9352005-05-04 13:25:00 -07001326 mov r31=pr // save PR
1327 ;;
1328 and r18=0xf,r17 // r18 = cr.ipsr.code{3:0}
1329 tbit.z p6,p0=r17,IA64_ISR_NA_BIT
1330 ;;
1331 cmp.ne.or p6,p0=IA64_ISR_CODE_LFETCH,r18
1332 dep r16=-1,r16,IA64_PSR_ED_BIT,1
1333(p6) br.cond.spnt 1f // branch if (cr.ispr.na == 0 || cr.ipsr.code{3:0} != LFETCH)
1334 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +09001335 MOV_TO_IPSR(p0, r16, r18)
David Mosberger-Tang458f9352005-05-04 13:25:00 -07001336 mov pr=r31,-1
1337 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +09001338 RFI
David Mosberger-Tang458f9352005-05-04 13:25:00 -07001339
13401: mov pr=r31,-1
1341 ;;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 FAULT(26)
1343END(nat_consumption)
1344
1345 .org ia64_ivt+0x5700
1346/////////////////////////////////////////////////////////////////////////////////////////
1347// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
1348ENTRY(speculation_vector)
1349 DBG_FAULT(27)
1350 /*
1351 * A [f]chk.[as] instruction needs to take the branch to the recovery code but
1352 * this part of the architecture is not implemented in hardware on some CPUs, such
1353 * as Itanium. Thus, in general we need to emulate the behavior. IIM contains
1354 * the relative target (not yet sign extended). So after sign extending it we
1355 * simply add it to IIP. We also need to reset the EI field of the IPSR to zero,
1356 * i.e., the slot to restart into.
1357 *
1358 * cr.imm contains zero_ext(imm21)
1359 */
Isaku Yamahata498c5172008-05-19 22:13:38 +09001360 MOV_FROM_IIM(r18)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +09001362 MOV_FROM_IIP(r17)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 shl r18=r18,43 // put sign bit in position (43=64-21)
1364 ;;
1365
Isaku Yamahata498c5172008-05-19 22:13:38 +09001366 MOV_FROM_IPSR(p0, r16)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 shr r18=r18,39 // sign extend (39=43-4)
1368 ;;
1369
1370 add r17=r17,r18 // now add the offset
1371 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +09001372 MOV_FROM_IIP(r17)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 dep r16=0,r16,41,2 // clear EI
1374 ;;
1375
Isaku Yamahata498c5172008-05-19 22:13:38 +09001376 MOV_FROM_IPSR(p0, r16)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 ;;
1378
Isaku Yamahata498c5172008-05-19 22:13:38 +09001379 RFI
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380END(speculation_vector)
1381
1382 .org ia64_ivt+0x5800
1383/////////////////////////////////////////////////////////////////////////////////////////
1384// 0x5800 Entry 28 (size 16 bundles) Reserved
1385 DBG_FAULT(28)
1386 FAULT(28)
1387
1388 .org ia64_ivt+0x5900
1389/////////////////////////////////////////////////////////////////////////////////////////
1390// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
1391ENTRY(debug_vector)
1392 DBG_FAULT(29)
1393 FAULT(29)
1394END(debug_vector)
1395
1396 .org ia64_ivt+0x5a00
1397/////////////////////////////////////////////////////////////////////////////////////////
1398// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
1399ENTRY(unaligned_access)
1400 DBG_FAULT(30)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 mov r31=pr // prepare to save predicates
1402 ;;
1403 br.sptk.many dispatch_unaligned_handler
1404END(unaligned_access)
1405
1406 .org ia64_ivt+0x5b00
1407/////////////////////////////////////////////////////////////////////////////////////////
1408// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
1409ENTRY(unsupported_data_reference)
1410 DBG_FAULT(31)
1411 FAULT(31)
1412END(unsupported_data_reference)
1413
1414 .org ia64_ivt+0x5c00
1415/////////////////////////////////////////////////////////////////////////////////////////
1416// 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64)
1417ENTRY(floating_point_fault)
1418 DBG_FAULT(32)
1419 FAULT(32)
1420END(floating_point_fault)
1421
1422 .org ia64_ivt+0x5d00
1423/////////////////////////////////////////////////////////////////////////////////////////
1424// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
1425ENTRY(floating_point_trap)
1426 DBG_FAULT(33)
1427 FAULT(33)
1428END(floating_point_trap)
1429
1430 .org ia64_ivt+0x5e00
1431/////////////////////////////////////////////////////////////////////////////////////////
1432// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66)
1433ENTRY(lower_privilege_trap)
1434 DBG_FAULT(34)
1435 FAULT(34)
1436END(lower_privilege_trap)
1437
1438 .org ia64_ivt+0x5f00
1439/////////////////////////////////////////////////////////////////////////////////////////
1440// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
1441ENTRY(taken_branch_trap)
1442 DBG_FAULT(35)
1443 FAULT(35)
1444END(taken_branch_trap)
1445
1446 .org ia64_ivt+0x6000
1447/////////////////////////////////////////////////////////////////////////////////////////
1448// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
1449ENTRY(single_step_trap)
1450 DBG_FAULT(36)
1451 FAULT(36)
1452END(single_step_trap)
1453
1454 .org ia64_ivt+0x6100
1455/////////////////////////////////////////////////////////////////////////////////////////
1456// 0x6100 Entry 37 (size 16 bundles) Reserved
1457 DBG_FAULT(37)
1458 FAULT(37)
1459
1460 .org ia64_ivt+0x6200
1461/////////////////////////////////////////////////////////////////////////////////////////
1462// 0x6200 Entry 38 (size 16 bundles) Reserved
1463 DBG_FAULT(38)
1464 FAULT(38)
1465
1466 .org ia64_ivt+0x6300
1467/////////////////////////////////////////////////////////////////////////////////////////
1468// 0x6300 Entry 39 (size 16 bundles) Reserved
1469 DBG_FAULT(39)
1470 FAULT(39)
1471
1472 .org ia64_ivt+0x6400
1473/////////////////////////////////////////////////////////////////////////////////////////
1474// 0x6400 Entry 40 (size 16 bundles) Reserved
1475 DBG_FAULT(40)
1476 FAULT(40)
1477
1478 .org ia64_ivt+0x6500
1479/////////////////////////////////////////////////////////////////////////////////////////
1480// 0x6500 Entry 41 (size 16 bundles) Reserved
1481 DBG_FAULT(41)
1482 FAULT(41)
1483
1484 .org ia64_ivt+0x6600
1485/////////////////////////////////////////////////////////////////////////////////////////
1486// 0x6600 Entry 42 (size 16 bundles) Reserved
1487 DBG_FAULT(42)
1488 FAULT(42)
1489
1490 .org ia64_ivt+0x6700
1491/////////////////////////////////////////////////////////////////////////////////////////
1492// 0x6700 Entry 43 (size 16 bundles) Reserved
1493 DBG_FAULT(43)
1494 FAULT(43)
1495
1496 .org ia64_ivt+0x6800
1497/////////////////////////////////////////////////////////////////////////////////////////
1498// 0x6800 Entry 44 (size 16 bundles) Reserved
1499 DBG_FAULT(44)
1500 FAULT(44)
1501
1502 .org ia64_ivt+0x6900
1503/////////////////////////////////////////////////////////////////////////////////////////
1504// 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)
1505ENTRY(ia32_exception)
1506 DBG_FAULT(45)
1507 FAULT(45)
1508END(ia32_exception)
1509
1510 .org ia64_ivt+0x6a00
1511/////////////////////////////////////////////////////////////////////////////////////////
1512// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71)
1513ENTRY(ia32_intercept)
1514 DBG_FAULT(46)
1515#ifdef CONFIG_IA32_SUPPORT
1516 mov r31=pr
Isaku Yamahata498c5172008-05-19 22:13:38 +09001517 MOV_FROM_ISR(r16)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 ;;
1519 extr.u r17=r16,16,8 // get ISR.code
1520 mov r18=ar.eflag
Isaku Yamahata498c5172008-05-19 22:13:38 +09001521 MOV_FROM_IIM(r19) // old eflag value
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 ;;
1523 cmp.ne p6,p0=2,r17
1524(p6) br.cond.spnt 1f // not a system flag fault
1525 xor r16=r18,r19
1526 ;;
1527 extr.u r17=r16,18,1 // get the eflags.ac bit
1528 ;;
1529 cmp.eq p6,p0=0,r17
1530(p6) br.cond.spnt 1f // eflags.ac bit didn't change
1531 ;;
1532 mov pr=r31,-1 // restore predicate registers
Isaku Yamahata498c5172008-05-19 22:13:38 +09001533 RFI
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534
15351:
1536#endif // CONFIG_IA32_SUPPORT
1537 FAULT(46)
1538END(ia32_intercept)
1539
1540 .org ia64_ivt+0x6b00
1541/////////////////////////////////////////////////////////////////////////////////////////
1542// 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74)
1543ENTRY(ia32_interrupt)
1544 DBG_FAULT(47)
1545#ifdef CONFIG_IA32_SUPPORT
1546 mov r31=pr
1547 br.sptk.many dispatch_to_ia32_handler
1548#else
1549 FAULT(47)
1550#endif
1551END(ia32_interrupt)
1552
1553 .org ia64_ivt+0x6c00
1554/////////////////////////////////////////////////////////////////////////////////////////
1555// 0x6c00 Entry 48 (size 16 bundles) Reserved
1556 DBG_FAULT(48)
1557 FAULT(48)
1558
1559 .org ia64_ivt+0x6d00
1560/////////////////////////////////////////////////////////////////////////////////////////
1561// 0x6d00 Entry 49 (size 16 bundles) Reserved
1562 DBG_FAULT(49)
1563 FAULT(49)
1564
1565 .org ia64_ivt+0x6e00
1566/////////////////////////////////////////////////////////////////////////////////////////
1567// 0x6e00 Entry 50 (size 16 bundles) Reserved
1568 DBG_FAULT(50)
1569 FAULT(50)
1570
1571 .org ia64_ivt+0x6f00
1572/////////////////////////////////////////////////////////////////////////////////////////
1573// 0x6f00 Entry 51 (size 16 bundles) Reserved
1574 DBG_FAULT(51)
1575 FAULT(51)
1576
1577 .org ia64_ivt+0x7000
1578/////////////////////////////////////////////////////////////////////////////////////////
1579// 0x7000 Entry 52 (size 16 bundles) Reserved
1580 DBG_FAULT(52)
1581 FAULT(52)
1582
1583 .org ia64_ivt+0x7100
1584/////////////////////////////////////////////////////////////////////////////////////////
1585// 0x7100 Entry 53 (size 16 bundles) Reserved
1586 DBG_FAULT(53)
1587 FAULT(53)
1588
1589 .org ia64_ivt+0x7200
1590/////////////////////////////////////////////////////////////////////////////////////////
1591// 0x7200 Entry 54 (size 16 bundles) Reserved
1592 DBG_FAULT(54)
1593 FAULT(54)
1594
1595 .org ia64_ivt+0x7300
1596/////////////////////////////////////////////////////////////////////////////////////////
1597// 0x7300 Entry 55 (size 16 bundles) Reserved
1598 DBG_FAULT(55)
1599 FAULT(55)
1600
1601 .org ia64_ivt+0x7400
1602/////////////////////////////////////////////////////////////////////////////////////////
1603// 0x7400 Entry 56 (size 16 bundles) Reserved
1604 DBG_FAULT(56)
1605 FAULT(56)
1606
1607 .org ia64_ivt+0x7500
1608/////////////////////////////////////////////////////////////////////////////////////////
1609// 0x7500 Entry 57 (size 16 bundles) Reserved
1610 DBG_FAULT(57)
1611 FAULT(57)
1612
1613 .org ia64_ivt+0x7600
1614/////////////////////////////////////////////////////////////////////////////////////////
1615// 0x7600 Entry 58 (size 16 bundles) Reserved
1616 DBG_FAULT(58)
1617 FAULT(58)
1618
1619 .org ia64_ivt+0x7700
1620/////////////////////////////////////////////////////////////////////////////////////////
1621// 0x7700 Entry 59 (size 16 bundles) Reserved
1622 DBG_FAULT(59)
1623 FAULT(59)
1624
1625 .org ia64_ivt+0x7800
1626/////////////////////////////////////////////////////////////////////////////////////////
1627// 0x7800 Entry 60 (size 16 bundles) Reserved
1628 DBG_FAULT(60)
1629 FAULT(60)
1630
1631 .org ia64_ivt+0x7900
1632/////////////////////////////////////////////////////////////////////////////////////////
1633// 0x7900 Entry 61 (size 16 bundles) Reserved
1634 DBG_FAULT(61)
1635 FAULT(61)
1636
1637 .org ia64_ivt+0x7a00
1638/////////////////////////////////////////////////////////////////////////////////////////
1639// 0x7a00 Entry 62 (size 16 bundles) Reserved
1640 DBG_FAULT(62)
1641 FAULT(62)
1642
1643 .org ia64_ivt+0x7b00
1644/////////////////////////////////////////////////////////////////////////////////////////
1645// 0x7b00 Entry 63 (size 16 bundles) Reserved
1646 DBG_FAULT(63)
1647 FAULT(63)
1648
1649 .org ia64_ivt+0x7c00
1650/////////////////////////////////////////////////////////////////////////////////////////
1651// 0x7c00 Entry 64 (size 16 bundles) Reserved
1652 DBG_FAULT(64)
1653 FAULT(64)
1654
1655 .org ia64_ivt+0x7d00
1656/////////////////////////////////////////////////////////////////////////////////////////
1657// 0x7d00 Entry 65 (size 16 bundles) Reserved
1658 DBG_FAULT(65)
1659 FAULT(65)
1660
1661 .org ia64_ivt+0x7e00
1662/////////////////////////////////////////////////////////////////////////////////////////
1663// 0x7e00 Entry 66 (size 16 bundles) Reserved
1664 DBG_FAULT(66)
1665 FAULT(66)
1666
1667 .org ia64_ivt+0x7f00
1668/////////////////////////////////////////////////////////////////////////////////////////
1669// 0x7f00 Entry 67 (size 16 bundles) Reserved
1670 DBG_FAULT(67)
1671 FAULT(67)
1672
Tony Luck4dcc29e2008-05-27 13:23:16 -07001673 /*
1674 * Squatting in this space ...
1675 *
1676 * This special case dispatcher for illegal operation faults allows preserved
1677 * registers to be modified through a callback function (asm only) that is handed
1678 * back from the fault handler in r8. Up to three arguments can be passed to the
1679 * callback function by returning an aggregate with the callback as its first
1680 * element, followed by the arguments.
1681 */
1682ENTRY(dispatch_illegal_op_fault)
1683 .prologue
1684 .body
1685 SAVE_MIN_WITH_COVER
Isaku Yamahata498c5172008-05-19 22:13:38 +09001686 SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24)
1687 // guarantee that interruption collection is on
Tony Luck4dcc29e2008-05-27 13:23:16 -07001688 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +09001689 SSM_PSR_I(p15, p15, r3) // restore psr.i
Tony Luck4dcc29e2008-05-27 13:23:16 -07001690 adds r3=8,r2 // set up second base pointer for SAVE_REST
1691 ;;
1692 alloc r14=ar.pfs,0,0,1,0 // must be first in insn group
1693 mov out0=ar.ec
1694 ;;
1695 SAVE_REST
1696 PT_REGS_UNWIND_INFO(0)
1697 ;;
1698 br.call.sptk.many rp=ia64_illegal_op_fault
1699.ret0: ;;
1700 alloc r14=ar.pfs,0,0,3,0 // must be first in insn group
1701 mov out0=r9
1702 mov out1=r10
1703 mov out2=r11
1704 movl r15=ia64_leave_kernel
1705 ;;
1706 mov rp=r15
1707 mov b6=r8
1708 ;;
1709 cmp.ne p6,p0=0,r8
1710(p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel
1711 br.sptk.many ia64_leave_kernel
1712END(dispatch_illegal_op_fault)
1713
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714#ifdef CONFIG_IA32_SUPPORT
1715
1716 /*
1717 * There is no particular reason for this code to be here, other than that
1718 * there happens to be space here that would go unused otherwise. If this
1719 * fault ever gets "unreserved", simply moved the following code to a more
1720 * suitable spot...
1721 */
1722
1723 // IA32 interrupt entry point
1724
1725ENTRY(dispatch_to_ia32_handler)
1726 SAVE_MIN
1727 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +09001728 MOV_FROM_ISR(r14)
1729 SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24)
1730 // guarantee that interruption collection is on
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 ;;
Isaku Yamahata498c5172008-05-19 22:13:38 +09001732 SSM_PSR_I(p15, p15, r3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 adds r3=8,r2 // Base pointer for SAVE_REST
1734 ;;
1735 SAVE_REST
1736 ;;
1737 mov r15=0x80
1738 shr r14=r14,16 // Get interrupt number
1739 ;;
1740 cmp.ne p6,p0=r14,r15
1741(p6) br.call.dpnt.many b6=non_ia32_syscall
1742
1743 adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW conventions
1744 adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp
1745 ;;
1746 cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
1747 ld8 r8=[r14] // get r8
1748 ;;
1749 st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP)
1750 ;;
1751 alloc r15=ar.pfs,0,0,6,0 // must first in an insn group
1752 ;;
1753 ld4 r8=[r14],8 // r8 == eax (syscall number)
1754 mov r15=IA32_NR_syscalls
1755 ;;
1756 cmp.ltu.unc p6,p7=r8,r15
1757 ld4 out1=[r14],8 // r9 == ecx
1758 ;;
1759 ld4 out2=[r14],8 // r10 == edx
1760 ;;
1761 ld4 out0=[r14] // r11 == ebx
1762 adds r14=(IA64_PT_REGS_R13_OFFSET) + 16,sp
1763 ;;
1764 ld4 out5=[r14],PT(R14)-PT(R13) // r13 == ebp
1765 ;;
1766 ld4 out3=[r14],PT(R15)-PT(R14) // r14 == esi
1767 adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
1768 ;;
1769 ld4 out4=[r14] // r15 == edi
1770 movl r16=ia32_syscall_table
1771 ;;
1772(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number
1773 ld4 r2=[r2] // r2 = current_thread_info()->flags
1774 ;;
1775 ld8 r16=[r16]
1776 and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit
1777 ;;
1778 mov b6=r16
1779 movl r15=ia32_ret_from_syscall
1780 cmp.eq p8,p0=r2,r0
1781 ;;
1782 mov rp=r15
1783(p8) br.call.sptk.many b6=b6
1784 br.cond.sptk ia32_trace_syscall
1785
1786non_ia32_syscall:
1787 alloc r15=ar.pfs,0,0,2,0
1788 mov out0=r14 // interrupt #
1789 add out1=16,sp // pointer to pt_regs
1790 ;; // avoid WAW on CFM
1791 br.call.sptk.many rp=ia32_bad_interrupt
1792.ret1: movl r15=ia64_leave_kernel
1793 ;;
1794 mov rp=r15
1795 br.ret.sptk.many rp
1796END(dispatch_to_ia32_handler)
1797
1798#endif /* CONFIG_IA32_SUPPORT */