exception.S revision 140553
1757Sdg/*-
299703Sjulian * Copyright (c) 1989, 1990 William F. Jolitz.
3757Sdg * Copyright (c) 1990 The Regents of the University of California.
4757Sdg * All rights reserved.
5757Sdg *
6757Sdg * Redistribution and use in source and binary forms, with or without
7757Sdg * modification, are permitted provided that the following conditions
8757Sdg * are met:
9757Sdg * 1. Redistributions of source code must retain the above copyright
10757Sdg *    notice, this list of conditions and the following disclaimer.
11757Sdg * 2. Redistributions in binary form must reproduce the above copyright
12757Sdg *    notice, this list of conditions and the following disclaimer in the
13757Sdg *    documentation and/or other materials provided with the distribution.
14757Sdg * 4. Neither the name of the University nor the names of its contributors
15757Sdg *    may be used to endorse or promote products derived from this software
16757Sdg *    without specific prior written permission.
17757Sdg *
18757Sdg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19757Sdg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20757Sdg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21757Sdg * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22757Sdg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23757Sdg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24757Sdg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25757Sdg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26757Sdg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27757Sdg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28757Sdg * SUCH DAMAGE.
29757Sdg *
3050477Speter * $FreeBSD: head/sys/amd64/amd64/exception.S 140553 2005-01-21 05:56:41Z peter $
31757Sdg */
32757Sdg
33129653Sbde#include "opt_atpic.h"
34133854Sobrien#include "opt_compat.h"
35129653Sbde
3628921Sfsmp#include <machine/asmacros.h>
3730786Sbde#include <machine/psl.h>
3830786Sbde#include <machine/trap.h>
39757Sdg
4030786Sbde#include "assym.s"
4130786Sbde
42757Sdg	.text
43757Sdg
44757Sdg/*****************************************************************************/
45757Sdg/* Trap handling                                                             */
46757Sdg/*****************************************************************************/
47757Sdg/*
4858717Sdillon * Trap and fault vector routines.
4958717Sdillon *
50114928Speter * All traps are 'interrupt gates', SDT_SYSIGT.  An interrupt gate pushes
51114928Speter * state on the stack but also disables interrupts.  This is important for
52114928Speter * us for the use of the swapgs instruction.  We cannot be interrupted
53114928Speter * until the GS.base value is correct.  For most traps, we automatically
54114928Speter * then enable interrupts if the interrupted context had them enabled.
55114928Speter * This is equivalent to the i386 port's use of SDT_SYS386TGT.
5658717Sdillon *
5758717Sdillon * The cpu will push a certain amount of state onto the kernel stack for
58114928Speter * the current process.  See amd64/include/frame.h.
59114928Speter * This includes the current RFLAGS (status register, which includes
6058717Sdillon * the interrupt disable state prior to the trap), the code segment register,
6158717Sdillon * and the return instruction pointer are pushed by the cpu.  The cpu
6258717Sdillon * will also push an 'error' code for certain traps.  We push a dummy
6358717Sdillon * error code for those traps where the cpu doesn't in order to maintain
6458717Sdillon * a consistent frame.  We also push a contrived 'trap number'.
6558717Sdillon *
6658717Sdillon * The cpu does not push the general registers, we must do that, and we
6758717Sdillon * must restore them prior to calling 'iret'.  The cpu adjusts the %cs and
6858717Sdillon * %ss segment registers, but does not mess with %ds, %es, or %fs.  Thus we
6958717Sdillon * must load them with appropriate values for supervisor mode operation.
701321Sdg */
711321Sdg
721321SdgMCOUNT_LABEL(user)
731321SdgMCOUNT_LABEL(btrap)
741321Sdg
75114952Speter/* Traps that we leave interrupts disabled for.. */
76114952Speter#define	TRAP_NOEN(a)	\
77114952Speter	subq $TF_RIP,%rsp; \
78114952Speter	movq $(a),TF_TRAPNO(%rsp) ; \
79114952Speter	movq $0,TF_ADDR(%rsp) ; \
80114952Speter	movq $0,TF_ERR(%rsp) ; \
81114952Speter	jmp alltraps_noen
82114952SpeterIDTVEC(dbg)
83114952Speter	TRAP_NOEN(T_TRCTRAP)
84114952SpeterIDTVEC(bpt)
85114952Speter	TRAP_NOEN(T_BPTFLT)
86114952Speter
87114952Speter/* Regular traps; The cpu does not supply tf_err for these. */
88114952Speter#define	TRAP(a)	 \
89114952Speter	subq $TF_RIP,%rsp; \
90114952Speter	movq $(a),TF_TRAPNO(%rsp) ; \
91114952Speter	movq $0,TF_ADDR(%rsp) ; \
92114952Speter	movq $0,TF_ERR(%rsp) ; \
93114952Speter	jmp alltraps
94757SdgIDTVEC(div)
95114952Speter	TRAP(T_DIVIDE)
96757SdgIDTVEC(nmi)
97114952Speter	TRAP(T_NMI)
98757SdgIDTVEC(ofl)
99114952Speter	TRAP(T_OFLOW)
100757SdgIDTVEC(bnd)
101114952Speter	TRAP(T_BOUND)
102757SdgIDTVEC(ill)
103114952Speter	TRAP(T_PRIVINFLT)
104757SdgIDTVEC(dna)
105114952Speter	TRAP(T_DNA)
106757SdgIDTVEC(fpusegm)
107114952Speter	TRAP(T_FPOPFLT)
108114952SpeterIDTVEC(mchk)
109114952Speter	TRAP(T_MCHK)
110114952SpeterIDTVEC(rsvd)
111114952Speter	TRAP(T_RESERVED)
112114952SpeterIDTVEC(fpu)
113114952Speter	TRAP(T_ARITHTRAP)
114114952SpeterIDTVEC(xmm)
115114952Speter	TRAP(T_XMMFLT)
116114952Speter
117114952Speter/* This group of traps have tf_err already pushed by the cpu */
118114952Speter#define	TRAP_ERR(a)	\
119114952Speter	subq $TF_ERR,%rsp; \
120114952Speter	movq $(a),TF_TRAPNO(%rsp) ; \
121114952Speter	movq $0,TF_ADDR(%rsp) ; \
122114952Speter	jmp alltraps_noen
123757SdgIDTVEC(tss)
124114952Speter	TRAP_ERR(T_TSSFLT)
125757SdgIDTVEC(missing)
126114952Speter	TRAP_ERR(T_SEGNPFLT)
127757SdgIDTVEC(stk)
128114952Speter	TRAP_ERR(T_STKFLT)
129757SdgIDTVEC(prot)
130114952Speter	TRAP_ERR(T_PROTFLT)
1315603SbdeIDTVEC(align)
132114952Speter	TRAP_ERR(T_ALIGNFLT)
133140553Speter
13458717Sdillon	/*
135114928Speter	 * alltraps entry point.  Use swapgs if this is the first time in the
136114928Speter	 * kernel from userland.  Reenable interrupts if they were enabled
137114928Speter	 * before the trap.  This approximates SDT_SYS386TGT on the i386 port.
13858717Sdillon	 */
13958717Sdillon
140757Sdg	SUPERALIGN_TEXT
14173011Sjake	.globl	alltraps
14273011Sjake	.type	alltraps,@function
14373011Sjakealltraps:
144114928Speter	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
145114928Speter	jz	alltraps_testi		/* already running with kernel GS.base */
146114928Speter	swapgs
147114928Speteralltraps_testi:
148114928Speter	testl	$PSL_I,TF_RFLAGS(%rsp)
149114928Speter	jz	alltraps_pushregs
150114928Speter	sti
151114928Speteralltraps_pushregs:
152114349Speter	movq	%rdi,TF_RDI(%rsp)
153114952Speteralltraps_pushregs_no_rdi:
154114349Speter	movq	%rsi,TF_RSI(%rsp)
155114349Speter	movq	%rdx,TF_RDX(%rsp)
156114349Speter	movq	%rcx,TF_RCX(%rsp)
157114349Speter	movq	%r8,TF_R8(%rsp)
158114349Speter	movq	%r9,TF_R9(%rsp)
159114349Speter	movq	%rax,TF_RAX(%rsp)
160114349Speter	movq	%rbx,TF_RBX(%rsp)
161114349Speter	movq	%rbp,TF_RBP(%rsp)
162114349Speter	movq	%r10,TF_R10(%rsp)
163114349Speter	movq	%r11,TF_R11(%rsp)
164114349Speter	movq	%r12,TF_R12(%rsp)
165114349Speter	movq	%r13,TF_R13(%rsp)
166114349Speter	movq	%r14,TF_R14(%rsp)
167114349Speter	movq	%r15,TF_R15(%rsp)
1685603Sbdealltraps_with_regs_pushed:
169129623Sbde	FAKE_MCOUNT(TF_RIP(%rsp))
170757Sdgcalltrap:
17173011Sjake	call	trap
172129623Sbde	MEXITCOUNT
173114349Speter	jmp	doreti			/* Handle any pending ASTs */
174757Sdg
175114928Speter	/*
176114928Speter	 * alltraps_noen entry point.  Unlike alltraps above, we want to
177114928Speter	 * leave the interrupts disabled.  This corresponds to
178114928Speter	 * SDT_SYS386IGT on the i386 port.
179114928Speter	 */
180114928Speter	SUPERALIGN_TEXT
181114928Speter	.globl	alltraps_noen
182114928Speter	.type	alltraps_noen,@function
183114928Speteralltraps_noen:
184114928Speter	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
185114928Speter	jz	alltraps_pushregs	/* already running with kernel GS.base */
186114928Speter	swapgs
187114928Speter	jmp	alltraps_pushregs
188114928Speter
189114928SpeterIDTVEC(dblfault)
190114952Speter	subq	$TF_ERR,%rsp
191114952Speter	movq	$T_DOUBLEFLT,TF_TRAPNO(%rsp)
192114928Speter	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
193114928Speter	jz	1f			/* already running with kernel GS.base */
194114928Speter	swapgs
195114928Speter1:	call	dblfault_handler
196114928Speter2:	hlt
197114928Speter	jmp	2b
198114928Speter
199114952SpeterIDTVEC(page)
200114952Speter	subq	$TF_ERR,%rsp
201114952Speter	movq	$T_PAGEFLT,TF_TRAPNO(%rsp)
202114952Speter	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
203114952Speter	jz	1f			/* already running with kernel GS.base */
204114952Speter	swapgs
205114952Speter1:	movq	%rdi,TF_RDI(%rsp)	/* free up a GP register */
206114952Speter	movq	%cr2,%rdi		/* preserve %cr2 before ..  */
207114952Speter	movq	%rdi,TF_ADDR(%rsp)	/* enabling interrupts. */
208114952Speter	testl	$PSL_I,TF_RFLAGS(%rsp)
209114952Speter	jz	alltraps_pushregs_no_rdi
210114952Speter	sti
211114952Speter	jmp	alltraps_pushregs_no_rdi
212114952Speter
213757Sdg/*
214114349Speter * Fast syscall entry point.  We enter here with just our new %cs/%ss set,
215114349Speter * and the new privilige level.  We are still running on the old user stack
216114349Speter * pointer.  We have to juggle a few things around to find our stack etc.
217114349Speter * swapgs gives us access to our PCPU space only.
2186380Ssos */
219114349SpeterIDTVEC(fast_syscall)
220114928Speter	swapgs
221114349Speter	movq	%rsp,PCPU(SCRATCH_RSP)
222122849Speter	movq	PCPU(RSP0),%rsp
223119924Speter	/* Now emulate a trapframe. Make the 8 byte alignment odd for call. */
224121103Speter	subq	$TF_SIZE,%rsp
225114349Speter	/* defer TF_RSP till we have a spare register */
226114349Speter	movq	%r11,TF_RFLAGS(%rsp)
227114928Speter	movq	%rcx,TF_RIP(%rsp)	/* %rcx original value is in %r10 */
228114928Speter	movq	PCPU(SCRATCH_RSP),%r11	/* %r11 already saved */
229114928Speter	movq	%r11,TF_RSP(%rsp)	/* user stack pointer */
230114928Speter	sti
231114928Speter	movq	$KUDSEL,TF_SS(%rsp)
232114349Speter	movq	$KUCSEL,TF_CS(%rsp)
233114349Speter	movq	$2,TF_ERR(%rsp)
234114349Speter	movq	%rdi,TF_RDI(%rsp)	/* arg 1 */
235114349Speter	movq	%rsi,TF_RSI(%rsp)	/* arg 2 */
236114349Speter	movq	%rdx,TF_RDX(%rsp)	/* arg 3 */
237114349Speter	movq	%r10,TF_RCX(%rsp)	/* arg 4 */
238114349Speter	movq	%r8,TF_R8(%rsp)		/* arg 5 */
239114349Speter	movq	%r9,TF_R9(%rsp)		/* arg 6 */
240114349Speter	movq	%rax,TF_RAX(%rsp)	/* syscall number */
241114349Speter	movq	%rbx,TF_RBX(%rsp)	/* C preserved */
242114349Speter	movq	%rbp,TF_RBP(%rsp)	/* C preserved */
243114349Speter	movq	%r12,TF_R12(%rsp)	/* C preserved */
244114349Speter	movq	%r13,TF_R13(%rsp)	/* C preserved */
245114349Speter	movq	%r14,TF_R14(%rsp)	/* C preserved */
246114349Speter	movq	%r15,TF_R15(%rsp)	/* C preserved */
247129623Sbde	FAKE_MCOUNT(TF_RIP(%rsp))
24873011Sjake	call	syscall
249114349Speter	movq	PCPU(CURPCB),%rax
250114349Speter	testq	$PCB_FULLCTX,PCB_FLAGS(%rax)
251114349Speter	jne	3f
252114349Speter1:	/* Check for and handle AST's on return to userland */
253114349Speter	cli
254114349Speter	movq	PCPU(CURTHREAD),%rax
255114349Speter	testl	$TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
256114349Speter	je	2f
257114349Speter	sti
258114349Speter	movq	%rsp, %rdi
259114349Speter	call	ast
260114349Speter	jmp	1b
261114349Speter2:	/* restore preserved registers */
262129623Sbde	MEXITCOUNT
263114349Speter	movq	TF_RDI(%rsp),%rdi	/* bonus; preserve arg 1 */
264114349Speter	movq	TF_RSI(%rsp),%rsi	/* bonus: preserve arg 2 */
265114349Speter	movq	TF_RDX(%rsp),%rdx	/* return value 2 */
266114349Speter	movq	TF_RAX(%rsp),%rax	/* return value 1 */
267114349Speter	movq	TF_RBX(%rsp),%rbx	/* C preserved */
268114349Speter	movq	TF_RBP(%rsp),%rbp	/* C preserved */
269114349Speter	movq	TF_R12(%rsp),%r12	/* C preserved */
270114349Speter	movq	TF_R13(%rsp),%r13	/* C preserved */
271114349Speter	movq	TF_R14(%rsp),%r14	/* C preserved */
272114349Speter	movq	TF_R15(%rsp),%r15	/* C preserved */
273114349Speter	movq	TF_RFLAGS(%rsp),%r11	/* original %rflags */
274114349Speter	movq	TF_RIP(%rsp),%rcx	/* original %rip */
275114349Speter	movq	TF_RSP(%rsp),%r9	/* user stack pointer */
276114349Speter	movq	%r9,%rsp		/* original %rsp */
277114928Speter	swapgs
278114349Speter	sysretq
279114349Speter3:	/* Requested full context restore, use doreti for that */
280114349Speter	andq	$~PCB_FULLCTX,PCB_FLAGS(%rax)
281129623Sbde	MEXITCOUNT
28273011Sjake	jmp	doreti
2836380Ssos
284114349Speter/*
285114349Speter * Here for CYA insurance, in case a "syscall" instruction gets
286114349Speter * issued from 32 bit compatability mode. MSR_CSTAR has to point
287114349Speter * to *something* if EFER_SCE is enabled.
288114349Speter */
289114349SpeterIDTVEC(fast_syscall32)
290114349Speter	sysret
291114349Speter
29224691SpeterENTRY(fork_trampoline)
293114349Speter	movq	%r12, %rdi		/* function */
294114349Speter	movq	%rbx, %rsi		/* arg1 */
295114349Speter	movq	%rsp, %rdx		/* trapframe pointer */
29673011Sjake	call	fork_exit
297129623Sbde	MEXITCOUNT
298114349Speter	jmp	doreti			/* Handle any ASTs */
29924691Speter
300129653Sbde/*
301129653Sbde * To efficiently implement classification of trap and interrupt handlers
302129653Sbde * for profiling, there must be only trap handlers between the labels btrap
303129653Sbde * and bintr, and only interrupt handlers between the labels bintr and
304129653Sbde * eintr.  This is implemented (partly) by including files that contain
305129653Sbde * some of the handlers.  Before including the files, set up a normal asm
306129653Sbde * environment so that the included files doen't need to know that they are
307129653Sbde * included.
308129653Sbde */
309129653Sbde
310133854Sobrien#ifdef COMPAT_IA32
31199703Sjulian	.data
312129656Sbde	.p2align 4
313129653Sbde	.text
314129653Sbde	SUPERALIGN_TEXT
31599703Sjulian
316129653Sbde#include <amd64/ia32/ia32_exception.S>
317129653Sbde#endif
318129653Sbde
319129653Sbde	.data
320129656Sbde	.p2align 4
321129653Sbde	.text
322129653Sbde	SUPERALIGN_TEXT
323129653SbdeMCOUNT_LABEL(bintr)
324129653Sbde
325129653Sbde#include <amd64/amd64/apic_vector.S>
326129653Sbde
327129653Sbde#ifdef DEV_ATPIC
328129653Sbde	.data
329129656Sbde	.p2align 4
330129653Sbde	.text
331129653Sbde	SUPERALIGN_TEXT
332129653Sbde
333129653Sbde#include <amd64/isa/atpic_vector.S>
334129653Sbde#endif
335129653Sbde
336129653Sbde	.text
337129653SbdeMCOUNT_LABEL(eintr)
338129653Sbde
3393156Sbde/*
34099703Sjulian * void doreti(struct trapframe)
34199703Sjulian *
34299703Sjulian * Handle return from interrupts, traps and syscalls.
3433156Sbde */
3443156Sbde	.text
3453156Sbde	SUPERALIGN_TEXT
34699703Sjulian	.type	doreti,@function
34799703Sjuliandoreti:
348129623Sbde	FAKE_MCOUNT($bintr)		/* init "from" bintr -> doreti */
34999703Sjulian	/*
350114349Speter	 * Check if ASTs can be handled now.
35199703Sjulian	 */
352114349Speter	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* are we returning to user mode? */
35399703Sjulian	jz	doreti_exit		/* can't handle ASTs now if not */
35499703Sjulian
35599703Sjuliandoreti_ast:
35699703Sjulian	/*
35799703Sjulian	 * Check for ASTs atomically with returning.  Disabling CPU
358120354Speter	 * interrupts provides sufficient locking eve in the SMP case,
35999703Sjulian	 * since we will be informed of any new ASTs by an IPI.
36099703Sjulian	 */
36199703Sjulian	cli
362114349Speter	movq	PCPU(CURTHREAD),%rax
363114349Speter	testl	$TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
36499703Sjulian	je	doreti_exit
36599703Sjulian	sti
366114349Speter	movq	%rsp, %rdi			/* pass a pointer to the trapframe */
36799703Sjulian	call	ast
36899703Sjulian	jmp	doreti_ast
36999703Sjulian
37099703Sjulian	/*
37199703Sjulian	 * doreti_exit:	pop registers, iret.
37299703Sjulian	 *
37399703Sjulian	 *	The segment register pop is a special case, since it may
37499703Sjulian	 *	fault if (for example) a sigreturn specifies bad segment
37599703Sjulian	 *	registers.  The fault is handled in trap.c.
37699703Sjulian	 */
37799703Sjuliandoreti_exit:
378129623Sbde	MEXITCOUNT
379114349Speter	movq	TF_RDI(%rsp),%rdi
380114349Speter	movq	TF_RSI(%rsp),%rsi
381114349Speter	movq	TF_RDX(%rsp),%rdx
382114349Speter	movq	TF_RCX(%rsp),%rcx
383114349Speter	movq	TF_R8(%rsp),%r8
384114349Speter	movq	TF_R9(%rsp),%r9
385114349Speter	movq	TF_RAX(%rsp),%rax
386114349Speter	movq	TF_RBX(%rsp),%rbx
387114349Speter	movq	TF_RBP(%rsp),%rbp
388114349Speter	movq	TF_R10(%rsp),%r10
389114349Speter	movq	TF_R11(%rsp),%r11
390114349Speter	movq	TF_R12(%rsp),%r12
391114349Speter	movq	TF_R13(%rsp),%r13
392114349Speter	movq	TF_R14(%rsp),%r14
393114349Speter	movq	TF_R15(%rsp),%r15
394114928Speter	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
395114928Speter	jz	1f			/* keep running with kernel GS.base */
396114928Speter	cli
397114928Speter	swapgs
398114928Speter1:	addq	$TF_RIP,%rsp		/* skip over tf_err, tf_trapno */
39999703Sjulian	.globl	doreti_iret
40099703Sjuliandoreti_iret:
401114349Speter	iretq
40299703Sjulian
403114928Speter	/*
40499703Sjulian	 * doreti_iret_fault and friends.  Alternative return code for
40599703Sjulian	 * the case where we get a fault in the doreti_exit code
40699703Sjulian	 * above.  trap() (i386/i386/trap.c) catches this specific
40799703Sjulian	 * case, sends the process a signal and continues in the
40899703Sjulian	 * corresponding place in the code below.
40999703Sjulian	 */
41099703Sjulian	ALIGN_TEXT
41199703Sjulian	.globl	doreti_iret_fault
41299703Sjuliandoreti_iret_fault:
413114349Speter	subq	$TF_RIP,%rsp		/* space including tf_err, tf_trapno */
414114928Speter	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
415114928Speter	jz	1f			/* already running with kernel GS.base */
416114928Speter	swapgs
417114928Speter1:	testl	$PSL_I,TF_RFLAGS(%rsp)
418114928Speter	jz	2f
419114928Speter	sti
420114928Speter2:	movq	%rdi,TF_RDI(%rsp)
421114349Speter	movq	%rsi,TF_RSI(%rsp)
422114349Speter	movq	%rdx,TF_RDX(%rsp)
423114349Speter	movq	%rcx,TF_RCX(%rsp)
424114349Speter	movq	%r8,TF_R8(%rsp)
425114349Speter	movq	%r9,TF_R9(%rsp)
426114349Speter	movq	%rax,TF_RAX(%rsp)
427114349Speter	movq	%rbx,TF_RBX(%rsp)
428114349Speter	movq	%rbp,TF_RBP(%rsp)
429114349Speter	movq	%r10,TF_R10(%rsp)
430114349Speter	movq	%r11,TF_R11(%rsp)
431114349Speter	movq	%r12,TF_R12(%rsp)
432114349Speter	movq	%r13,TF_R13(%rsp)
433114349Speter	movq	%r14,TF_R14(%rsp)
434114349Speter	movq	%r15,TF_R15(%rsp)
435114349Speter	movq	$T_PROTFLT,TF_TRAPNO(%rsp)
436114349Speter	movq	$0,TF_ERR(%rsp)	/* XXX should be the error code */
43799703Sjulian	jmp	alltraps_with_regs_pushed
438