xref: /freebsd-12.1/sys/amd64/amd64/exception.S (revision 8e45ca01)
1/*-
2 * Copyright (c) 1989, 1990 William F. Jolitz.
3 * Copyright (c) 1990 The Regents of the University of California.
4 * Copyright (c) 2007-2018 The FreeBSD Foundation
5 * All rights reserved.
6 *
7 * Portions of this software were developed by A. Joseph Koshy under
8 * sponsorship from the FreeBSD Foundation and Google, Inc.
9 *
10 * Portions of this software were developed by
11 * Konstantin Belousov <[email protected]> under sponsorship from
12 * the FreeBSD Foundation.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 *    notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 *    notice, this list of conditions and the following disclaimer in the
21 *    documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * $FreeBSD$
39 */
40
41#include "opt_atpic.h"
42#include "opt_hwpmc_hooks.h"
43
44#include "assym.inc"
45
46#include <machine/psl.h>
47#include <machine/asmacros.h>
48#include <machine/trap.h>
49#include <machine/specialreg.h>
50
51#ifdef KDTRACE_HOOKS
52	.bss
53	.globl	dtrace_invop_jump_addr
54	.align	8
55	.type	dtrace_invop_jump_addr,@object
56	.size	dtrace_invop_jump_addr,8
57dtrace_invop_jump_addr:
58	.zero	8
59	.globl	dtrace_invop_calltrap_addr
60	.align	8
61	.type	dtrace_invop_calltrap_addr,@object
62	.size	dtrace_invop_calltrap_addr,8
63dtrace_invop_calltrap_addr:
64	.zero	8
65#endif
66	.text
67#ifdef HWPMC_HOOKS
68	ENTRY(start_exceptions)
69#endif
70
71/*****************************************************************************/
72/* Trap handling                                                             */
73/*****************************************************************************/
74/*
75 * Trap and fault vector routines.
76 *
77 * All traps are 'interrupt gates', SDT_SYSIGT.  An interrupt gate pushes
78 * state on the stack but also disables interrupts.  This is important for
79 * us for the use of the swapgs instruction.  We cannot be interrupted
80 * until the GS.base value is correct.  For most traps, we automatically
81 * then enable interrupts if the interrupted context had them enabled.
82 * This is equivalent to the i386 port's use of SDT_SYS386TGT.
83 *
84 * The cpu will push a certain amount of state onto the kernel stack for
85 * the current process.  See amd64/include/frame.h.
86 * This includes the current RFLAGS (status register, which includes
87 * the interrupt disable state prior to the trap), the code segment register,
88 * and the return instruction pointer are pushed by the cpu.  The cpu
89 * will also push an 'error' code for certain traps.  We push a dummy
90 * error code for those traps where the cpu doesn't in order to maintain
91 * a consistent frame.  We also push a contrived 'trap number'.
92 *
93 * The CPU does not push the general registers, so we must do that, and we
94 * must restore them prior to calling 'iret'.  The CPU adjusts %cs and %ss
95 * but does not mess with %ds, %es, %gs or %fs.  We swap the %gs base for
96 * for the kernel mode operation shortly, without changes to the selector
97 * loaded.  Since superuser long mode works with any selectors loaded into
98 * segment registers other then %cs, which makes them mostly unused in long
99 * mode, and kernel does not reference %fs, leave them alone.  The segment
100 * registers are reloaded on return to the usermode.
101 */
102
103MCOUNT_LABEL(user)
104MCOUNT_LABEL(btrap)
105
106/* Traps that we leave interrupts disabled for. */
107	.macro	TRAP_NOEN	l, trapno
108	PTI_ENTRY	\l,\l\()_pti_k,\l\()_pti_u
109\l\()_pti_k:
110	subq	$TF_RIP,%rsp
111	movl	$\trapno,TF_TRAPNO(%rsp)
112	movq	$0,TF_ADDR(%rsp)
113	movq	$0,TF_ERR(%rsp)
114	jmp	alltraps_noen_k
115\l\()_pti_u:
116	subq	$TF_RIP,%rsp
117	movl	$\trapno,TF_TRAPNO(%rsp)
118	movq	$0,TF_ADDR(%rsp)
119	movq	$0,TF_ERR(%rsp)
120	jmp	alltraps_noen_u
121
122	.globl	X\l
123	.type	X\l,@function
124X\l:
125	subq	$TF_RIP,%rsp
126	movl	$\trapno,TF_TRAPNO(%rsp)
127	movq	$0,TF_ADDR(%rsp)
128	movq	$0,TF_ERR(%rsp)
129	testb	$SEL_RPL_MASK,TF_CS(%rsp)
130	jz	alltraps_noen_k
131	swapgs
132	lfence
133	jmp	alltraps_noen_u
134	.endm
135
136	TRAP_NOEN	bpt, T_BPTFLT
137#ifdef KDTRACE_HOOKS
138	TRAP_NOEN	dtrace_ret, T_DTRACE_RET
139#endif
140
141/* Regular traps; The cpu does not supply tf_err for these. */
142	.macro	TRAP	l, trapno
143	PTI_ENTRY	\l,\l\()_pti_k,\l\()_pti_u
144\l\()_pti_k:
145	subq	$TF_RIP,%rsp
146	movl	$\trapno,TF_TRAPNO(%rsp)
147	movq	$0,TF_ADDR(%rsp)
148	movq	$0,TF_ERR(%rsp)
149	jmp	alltraps_k
150\l\()_pti_u:
151	subq	$TF_RIP,%rsp
152	movl	$\trapno,TF_TRAPNO(%rsp)
153	movq	$0,TF_ADDR(%rsp)
154	movq	$0,TF_ERR(%rsp)
155	jmp	alltraps_u
156
157	.globl	X\l
158	.type	X\l,@function
159X\l:
160	subq	$TF_RIP,%rsp
161	movl	$\trapno,TF_TRAPNO(%rsp)
162	movq	$0,TF_ADDR(%rsp)
163	movq	$0,TF_ERR(%rsp)
164	testb	$SEL_RPL_MASK,TF_CS(%rsp)
165	jz	alltraps_k
166	swapgs
167	lfence
168	jmp	alltraps_u
169	.endm
170
171	TRAP	div, T_DIVIDE
172	TRAP	ofl, T_OFLOW
173	TRAP	bnd, T_BOUND
174	TRAP	ill, T_PRIVINFLT
175	TRAP	dna, T_DNA
176	TRAP	fpusegm, T_FPOPFLT
177	TRAP	rsvd, T_RESERVED
178	TRAP	fpu, T_ARITHTRAP
179	TRAP	xmm, T_XMMFLT
180
181/* This group of traps have tf_err already pushed by the cpu. */
182	.macro	TRAP_ERR	l, trapno
183	PTI_ENTRY	\l,\l\()_pti_k,\l\()_pti_u,has_err=1
184\l\()_pti_k:
185	subq	$TF_ERR,%rsp
186	movl	$\trapno,TF_TRAPNO(%rsp)
187	movq	$0,TF_ADDR(%rsp)
188	jmp	alltraps_k
189\l\()_pti_u:
190	subq	$TF_ERR,%rsp
191	movl	$\trapno,TF_TRAPNO(%rsp)
192	movq	$0,TF_ADDR(%rsp)
193	jmp	alltraps_u
194	.globl	X\l
195	.type	X\l,@function
196X\l:
197	subq	$TF_ERR,%rsp
198	movl	$\trapno,TF_TRAPNO(%rsp)
199	movq	$0,TF_ADDR(%rsp)
200	testb	$SEL_RPL_MASK,TF_CS(%rsp)
201	jz	alltraps_k
202	swapgs
203	lfence
204	jmp	alltraps_u
205	.endm
206
207	TRAP_ERR	tss, T_TSSFLT
208	TRAP_ERR	align, T_ALIGNFLT
209
210	/*
211	 * alltraps_u/k entry points.
212	 * SWAPGS must be already performed by prologue,
213	 * if this is the first time in the kernel from userland.
214	 * Reenable interrupts if they were enabled before the trap.
215	 * This approximates SDT_SYS386TGT on the i386 port.
216	 */
217	SUPERALIGN_TEXT
218	.globl	alltraps_u
219	.type	alltraps_u,@function
220alltraps_u:
221	movq	%rdi,TF_RDI(%rsp)
222	movq	%rdx,TF_RDX(%rsp)
223	movq	%rax,TF_RAX(%rsp)
224	movq	%rcx,TF_RCX(%rsp)
225	movq	PCPU(CURPCB),%rdi
226	andl	$~PCB_FULL_IRET,PCB_FLAGS(%rdi)
227	call	handle_ibrs_entry
228	jmp	alltraps_save_segs
229	SUPERALIGN_TEXT
230	.globl	alltraps_k
231	.type	alltraps_k,@function
232alltraps_k:
233	lfence
234	movq	%rdi,TF_RDI(%rsp)
235	movq	%rdx,TF_RDX(%rsp)
236	movq	%rax,TF_RAX(%rsp)
237	movq	%rcx,TF_RCX(%rsp)
238alltraps_save_segs:
239	SAVE_SEGS
240	testl	$PSL_I,TF_RFLAGS(%rsp)
241	jz	alltraps_pushregs_no_rax
242	sti
243alltraps_pushregs_no_rax:
244	movq	%rsi,TF_RSI(%rsp)
245	movq	%r8,TF_R8(%rsp)
246	movq	%r9,TF_R9(%rsp)
247	movq	%rbx,TF_RBX(%rsp)
248	movq	%rbp,TF_RBP(%rsp)
249	movq	%r10,TF_R10(%rsp)
250	movq	%r11,TF_R11(%rsp)
251	movq	%r12,TF_R12(%rsp)
252	movq	%r13,TF_R13(%rsp)
253	movq	%r14,TF_R14(%rsp)
254	movq	%r15,TF_R15(%rsp)
255	movl	$TF_HASSEGS,TF_FLAGS(%rsp)
256	pushfq
257	andq	$~(PSL_D | PSL_AC),(%rsp)
258	popfq
259	FAKE_MCOUNT(TF_RIP(%rsp))
260#ifdef KDTRACE_HOOKS
261	/*
262	 * DTrace Function Boundary Trace (fbt) probes are triggered
263	 * by int3 (0xcc) which causes the #BP (T_BPTFLT) breakpoint
264	 * interrupt. For all other trap types, just handle them in
265	 * the usual way.
266	 */
267	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
268	jnz	calltrap		/* ignore userland traps */
269	cmpl	$T_BPTFLT,TF_TRAPNO(%rsp)
270	jne	calltrap
271
272	/* Check if there is no DTrace hook registered. */
273	cmpq	$0,dtrace_invop_jump_addr
274	je	calltrap
275
276	/*
277	 * Set our jump address for the jump back in the event that
278	 * the breakpoint wasn't caused by DTrace at all.
279	 */
280	movq	$calltrap,dtrace_invop_calltrap_addr(%rip)
281
282	/* Jump to the code hooked in by DTrace. */
283	jmpq	*dtrace_invop_jump_addr
284#endif
285	.globl	calltrap
286	.type	calltrap,@function
287calltrap:
288	movq	%rsp,%rdi
289	call	trap_check
290	MEXITCOUNT
291	jmp	doreti			/* Handle any pending ASTs */
292
293	/*
294	 * alltraps_noen_u/k entry points.
295	 * Again, SWAPGS must be already performed by prologue, if needed.
296	 * Unlike alltraps above, we want to leave the interrupts disabled.
297	 * This corresponds to SDT_SYS386IGT on the i386 port.
298	 */
299	SUPERALIGN_TEXT
300	.globl	alltraps_noen_u
301	.type	alltraps_noen_u,@function
302alltraps_noen_u:
303	movq	%rdi,TF_RDI(%rsp)
304	movq	PCPU(CURPCB),%rdi
305	andl	$~PCB_FULL_IRET,PCB_FLAGS(%rdi)
306	jmp	alltraps_noen_save_segs
307	SUPERALIGN_TEXT
308	.globl	alltraps_noen_k
309	.type	alltraps_noen_k,@function
310alltraps_noen_k:
311	lfence
312	movq	%rdi,TF_RDI(%rsp)
313alltraps_noen_save_segs:
314	SAVE_SEGS
315	movq	%rdx,TF_RDX(%rsp)
316	movq	%rax,TF_RAX(%rsp)
317	movq	%rcx,TF_RCX(%rsp)
318	testb	$SEL_RPL_MASK,TF_CS(%rsp)
319	jz	alltraps_pushregs_no_rax
320	call	handle_ibrs_entry
321	jmp	alltraps_pushregs_no_rax
322
323IDTVEC(dblfault)
324	subq	$TF_ERR,%rsp
325	movl	$T_DOUBLEFLT,TF_TRAPNO(%rsp)
326	movq	$0,TF_ADDR(%rsp)
327	movq	$0,TF_ERR(%rsp)
328	movq	%rdi,TF_RDI(%rsp)
329	movq	%rsi,TF_RSI(%rsp)
330	movq	%rdx,TF_RDX(%rsp)
331	movq	%rcx,TF_RCX(%rsp)
332	movq	%r8,TF_R8(%rsp)
333	movq	%r9,TF_R9(%rsp)
334	movq	%rax,TF_RAX(%rsp)
335	movq	%rbx,TF_RBX(%rsp)
336	movq	%rbp,TF_RBP(%rsp)
337	movq	%r10,TF_R10(%rsp)
338	movq	%r11,TF_R11(%rsp)
339	movq	%r12,TF_R12(%rsp)
340	movq	%r13,TF_R13(%rsp)
341	movq	%r14,TF_R14(%rsp)
342	movq	%r15,TF_R15(%rsp)
343	SAVE_SEGS
344	movl	$TF_HASSEGS,TF_FLAGS(%rsp)
345	pushfq
346	andq	$~(PSL_D | PSL_AC),(%rsp)
347	popfq
348	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
349	jz	1f			/* already running with kernel GS.base */
350	swapgs
3511:	lfence
352	movq	PCPU(KCR3),%rax
353	cmpq	$~0,%rax
354	je	2f
355	movq	%rax,%cr3
3562:	movq	%rsp,%rdi
357	call	dblfault_handler
3583:	hlt
359	jmp	3b
360
361	ALIGN_TEXT
362IDTVEC(page_pti)
363	testb	$SEL_RPL_MASK,PTI_CS-PTI_ERR(%rsp)
364	jz	page_k
365	swapgs
366	lfence
367	pushq	%rax
368	movq	%cr3,%rax
369	movq	%rax,PCPU(SAVED_UCR3)
370	cmpq	$~0,PCPU(UCR3)
371	jne	1f
372	popq	%rax
373	jmp	page_u
3741:	pushq	%rdx
375	PTI_UUENTRY has_err=1
376	jmp	page_u
377	ALIGN_TEXT
378IDTVEC(page)
379	testb	$SEL_RPL_MASK,TF_CS-TF_ERR(%rsp) /* Did we come from kernel? */
380	jnz	page_u_swapgs		/* already running with kernel GS.base */
381page_k:
382	lfence
383	subq	$TF_ERR,%rsp
384	movq	%rdi,TF_RDI(%rsp)	/* free up GP registers */
385	movq	%rax,TF_RAX(%rsp)
386	movq	%rdx,TF_RDX(%rsp)
387	movq	%rcx,TF_RCX(%rsp)
388	jmp	page_cr2
389	ALIGN_TEXT
390page_u_swapgs:
391	swapgs
392	lfence
393page_u:
394	subq	$TF_ERR,%rsp
395	movq	%rdi,TF_RDI(%rsp)
396	movq	%rax,TF_RAX(%rsp)
397	movq	%rdx,TF_RDX(%rsp)
398	movq	%rcx,TF_RCX(%rsp)
399	movq	PCPU(CURPCB),%rdi
400	andl	$~PCB_FULL_IRET,PCB_FLAGS(%rdi)
401	movq	PCPU(SAVED_UCR3),%rax
402	movq	%rax,PCB_SAVED_UCR3(%rdi)
403	call	handle_ibrs_entry
404page_cr2:
405	movq	%cr2,%rdi		/* preserve %cr2 before ..  */
406	movq	%rdi,TF_ADDR(%rsp)	/* enabling interrupts. */
407	SAVE_SEGS
408	movl	$T_PAGEFLT,TF_TRAPNO(%rsp)
409	testl	$PSL_I,TF_RFLAGS(%rsp)
410	jz	alltraps_pushregs_no_rax
411	sti
412	jmp	alltraps_pushregs_no_rax
413
414	/*
415	 * We have to special-case this one.  If we get a trap in doreti() at
416	 * the iretq stage, we'll reenter with the wrong gs state.  We'll have
417	 * to do a special the swapgs in this case even coming from the kernel.
418	 * XXX linux has a trap handler for their equivalent of load_gs().
419	 *
420	 * On the stack, we have the hardware interrupt frame to return
421	 * to usermode (faulted) and another frame with error code, for
422	 * fault.  For PTI, copy both frames to the main thread stack.
423	 * Handle the potential 16-byte alignment adjustment incurred
424	 * during the second fault by copying both frames independently
425	 * while unwinding the stack in between.
426	 */
427	.macro PROTF_ENTRY name,trapno
428\name\()_pti_doreti:
429	swapgs
430	lfence
431	cmpq	$~0,PCPU(UCR3)
432	je	1f
433	pushq	%rax
434	pushq	%rdx
435	movq	PCPU(KCR3),%rax
436	movq	%rax,%cr3
437	movq	PCPU(RSP0),%rax
438	subq	$2*PTI_SIZE-3*8,%rax /* no err, %rax, %rdx in faulted frame */
439	MOVE_STACKS	(PTI_SIZE / 8)
440	addq	$PTI_SIZE,%rax
441	movq	PTI_RSP(%rsp),%rsp
442	MOVE_STACKS	(PTI_SIZE / 8 - 3)
443	subq	$PTI_SIZE,%rax
444	movq	%rax,%rsp
445	popq	%rdx
446	popq	%rax
4471:	swapgs
448	jmp	X\name
449IDTVEC(\name\()_pti)
450	cmpq	$doreti_iret,PTI_RIP-2*8(%rsp)
451	je	\name\()_pti_doreti
452	testb	$SEL_RPL_MASK,PTI_CS-2*8(%rsp) /* %rax, %rdx not yet pushed */
453	jz	X\name		/* lfence is not needed until %gs: use */
454	PTI_UENTRY has_err=1
455	swapgs	/* fence provided by PTI_UENTRY */
456IDTVEC(\name)
457	subq	$TF_ERR,%rsp
458	movl	$\trapno,TF_TRAPNO(%rsp)
459	jmp	prot_addrf
460	.endm
461
462	PROTF_ENTRY	missing, T_SEGNPFLT
463	PROTF_ENTRY	stk, T_STKFLT
464	PROTF_ENTRY	prot, T_PROTFLT
465
466prot_addrf:
467	movq	$0,TF_ADDR(%rsp)
468	movq	%rdi,TF_RDI(%rsp)	/* free up a GP register */
469	movq	%rax,TF_RAX(%rsp)
470	movq	%rdx,TF_RDX(%rsp)
471	movq	%rcx,TF_RCX(%rsp)
472	movw	%fs,TF_FS(%rsp)
473	movw	%gs,TF_GS(%rsp)
474	leaq	doreti_iret(%rip),%rdi
475	cmpq	%rdi,TF_RIP(%rsp)
476	je	5f			/* kernel but with user gsbase!! */
477	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
478	jz	6f			/* already running with kernel GS.base */
479	testb	$CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip)
480	jz	2f
481	cmpw	$KUF32SEL,TF_FS(%rsp)
482	jne	1f
483	rdfsbase %rax
4841:	cmpw	$KUG32SEL,TF_GS(%rsp)
485	jne	2f
486	rdgsbase %rdx
4872:	swapgs
488	lfence
489	movq	PCPU(CURPCB),%rdi
490	testb	$CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip)
491	jz	4f
492	cmpw	$KUF32SEL,TF_FS(%rsp)
493	jne	3f
494	movq	%rax,PCB_FSBASE(%rdi)
4953:	cmpw	$KUG32SEL,TF_GS(%rsp)
496	jne	4f
497	movq	%rdx,PCB_GSBASE(%rdi)
4984:	call	handle_ibrs_entry
499	orl	$PCB_FULL_IRET,PCB_FLAGS(%rdi)	/* always full iret from GPF */
500	movw	%es,TF_ES(%rsp)
501	movw	%ds,TF_DS(%rsp)
502	testl	$PSL_I,TF_RFLAGS(%rsp)
503	jz	alltraps_pushregs_no_rax
504	sti
505	jmp	alltraps_pushregs_no_rax
506
5075:	swapgs
5086:	lfence
509	movq	PCPU(CURPCB),%rdi
510	jmp	4b
511
512/*
513 * Fast syscall entry point.  We enter here with just our new %cs/%ss set,
514 * and the new privilige level.  We are still running on the old user stack
515 * pointer.  We have to juggle a few things around to find our stack etc.
516 * swapgs gives us access to our PCPU space only.
517 *
518 * We do not support invoking this from a custom segment registers,
519 * esp. %cs, %ss, %fs, %gs, e.g. using entries from an LDT.
520 */
521	SUPERALIGN_TEXT
522IDTVEC(fast_syscall_pti)
523	swapgs
524	lfence
525	movq	%rax,PCPU(SCRATCH_RAX)
526	cmpq	$~0,PCPU(UCR3)
527	je	fast_syscall_common
528	movq	PCPU(KCR3),%rax
529	movq	%rax,%cr3
530	jmp	fast_syscall_common
531	SUPERALIGN_TEXT
532IDTVEC(fast_syscall)
533	swapgs
534	lfence
535	movq	%rax,PCPU(SCRATCH_RAX)
536fast_syscall_common:
537	movq	%rsp,PCPU(SCRATCH_RSP)
538	movq	PCPU(RSP0),%rsp
539	/* Now emulate a trapframe. Make the 8 byte alignment odd for call. */
540	subq	$TF_SIZE,%rsp
541	/* defer TF_RSP till we have a spare register */
542	movq	%r11,TF_RFLAGS(%rsp)
543	movq	%rcx,TF_RIP(%rsp)	/* %rcx original value is in %r10 */
544	movq	PCPU(SCRATCH_RSP),%r11	/* %r11 already saved */
545	movq	%r11,TF_RSP(%rsp)	/* user stack pointer */
546	movq	PCPU(SCRATCH_RAX),%rax
547	/*
548	 * Save a few arg registers early to free them for use in
549	 * handle_ibrs_entry().  %r10 is especially tricky.  It is not an
550	 * arg register, but it holds the arg register %rcx.  Profiling
551	 * preserves %rcx, but may clobber %r10.  Profiling may also
552	 * clobber %r11, but %r11 (original %eflags) has been saved.
553	 */
554	movq	%rax,TF_RAX(%rsp)	/* syscall number */
555	movq	%rdx,TF_RDX(%rsp)	/* arg 3 */
556	movq	%r10,TF_RCX(%rsp)	/* arg 4 */
557	SAVE_SEGS
558	call	handle_ibrs_entry
559	movq	PCPU(CURPCB),%r11
560	andl	$~PCB_FULL_IRET,PCB_FLAGS(%r11)
561	sti
562	movq	$KUDSEL,TF_SS(%rsp)
563	movq	$KUCSEL,TF_CS(%rsp)
564	movq	$2,TF_ERR(%rsp)
565	movq	%rdi,TF_RDI(%rsp)	/* arg 1 */
566	movq	%rsi,TF_RSI(%rsp)	/* arg 2 */
567	movq	%r8,TF_R8(%rsp)		/* arg 5 */
568	movq	%r9,TF_R9(%rsp)		/* arg 6 */
569	movq	%rbx,TF_RBX(%rsp)	/* C preserved */
570	movq	%rbp,TF_RBP(%rsp)	/* C preserved */
571	movq	%r12,TF_R12(%rsp)	/* C preserved */
572	movq	%r13,TF_R13(%rsp)	/* C preserved */
573	movq	%r14,TF_R14(%rsp)	/* C preserved */
574	movq	%r15,TF_R15(%rsp)	/* C preserved */
575	movl	$TF_HASSEGS,TF_FLAGS(%rsp)
576	FAKE_MCOUNT(TF_RIP(%rsp))
577	movq	PCPU(CURTHREAD),%rdi
578	movq	%rsp,TD_FRAME(%rdi)
579	movl	TF_RFLAGS(%rsp),%esi
580	andl	$PSL_T,%esi
581	call	amd64_syscall
5821:	movq	PCPU(CURPCB),%rax
583	/* Disable interrupts before testing PCB_FULL_IRET. */
584	cli
585	testl	$PCB_FULL_IRET,PCB_FLAGS(%rax)
586	jnz	4f
587	/* Check for and handle AST's on return to userland. */
588	movq	PCPU(CURTHREAD),%rax
589	testl	$TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
590	jne	3f
591	call	handle_ibrs_exit
592	callq	*mds_handler
593	/* Restore preserved registers. */
594	MEXITCOUNT
595	movq	TF_RDI(%rsp),%rdi	/* bonus; preserve arg 1 */
596	movq	TF_RSI(%rsp),%rsi	/* bonus: preserve arg 2 */
597	movq	TF_RDX(%rsp),%rdx	/* return value 2 */
598	movq	TF_RAX(%rsp),%rax	/* return value 1 */
599	movq	TF_RFLAGS(%rsp),%r11	/* original %rflags */
600	movq	TF_RIP(%rsp),%rcx	/* original %rip */
601	movq	TF_RSP(%rsp),%rsp	/* user stack pointer */
602	xorl	%r8d,%r8d		/* zero the rest of GPRs */
603	xorl	%r10d,%r10d
604	cmpq	$~0,PCPU(UCR3)
605	je	2f
606	movq	PCPU(UCR3),%r9
607	movq	%r9,%cr3
6082:	xorl	%r9d,%r9d
609	swapgs
610	sysretq
611
6123:	/* AST scheduled. */
613	sti
614	movq	%rsp,%rdi
615	call	ast
616	jmp	1b
617
6184:	/* Requested full context restore, use doreti for that. */
619	MEXITCOUNT
620	jmp	doreti
621
622/*
623 * Here for CYA insurance, in case a "syscall" instruction gets
624 * issued from 32 bit compatibility mode. MSR_CSTAR has to point
625 * to *something* if EFER_SCE is enabled.
626 */
627IDTVEC(fast_syscall32)
628	sysret
629
630/*
631 * DB# handler is very similar to NM#, because 'mov/pop %ss' delay
632 * generation of exception until the next instruction is executed,
633 * which might be a kernel entry.  So we must execute the handler
634 * on IST stack and be ready for non-kernel GSBASE.
635 */
636IDTVEC(dbg)
637	subq	$TF_RIP,%rsp
638	movl	$(T_TRCTRAP),TF_TRAPNO(%rsp)
639	movq	$0,TF_ADDR(%rsp)
640	movq	$0,TF_ERR(%rsp)
641	movq	%rdi,TF_RDI(%rsp)
642	movq	%rsi,TF_RSI(%rsp)
643	movq	%rdx,TF_RDX(%rsp)
644	movq	%rcx,TF_RCX(%rsp)
645	movq	%r8,TF_R8(%rsp)
646	movq	%r9,TF_R9(%rsp)
647	movq	%rax,TF_RAX(%rsp)
648	movq	%rbx,TF_RBX(%rsp)
649	movq	%rbp,TF_RBP(%rsp)
650	movq	%r10,TF_R10(%rsp)
651	movq	%r11,TF_R11(%rsp)
652	movq	%r12,TF_R12(%rsp)
653	movq	%r13,TF_R13(%rsp)
654	movq	%r14,TF_R14(%rsp)
655	movq	%r15,TF_R15(%rsp)
656	SAVE_SEGS
657	movl	$TF_HASSEGS,TF_FLAGS(%rsp)
658	pushfq
659	andq	$~(PSL_D | PSL_AC),(%rsp)
660	popfq
661	testb	$SEL_RPL_MASK,TF_CS(%rsp)
662	jnz	dbg_fromuserspace
663	lfence
664	/*
665	 * We've interrupted the kernel.  Preserve GS.base in %r12,
666	 * %cr3 in %r13, and possibly lower half of MSR_IA32_SPEC_CTL in %r14d.
667	 */
668	movl	$MSR_GSBASE,%ecx
669	rdmsr
670	movq	%rax,%r12
671	shlq	$32,%rdx
672	orq	%rdx,%r12
673	/* Retrieve and load the canonical value for GS.base. */
674	movq	TF_SIZE(%rsp),%rdx
675	movl	%edx,%eax
676	shrq	$32,%rdx
677	wrmsr
678	movq	%cr3,%r13
679	movq	PCPU(KCR3),%rax
680	cmpq	$~0,%rax
681	je	1f
682	movq	%rax,%cr3
6831:	testl	$CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
684	je	2f
685	movl	$MSR_IA32_SPEC_CTRL,%ecx
686	rdmsr
687	movl	%eax,%r14d
688	call	handle_ibrs_entry
6892:	FAKE_MCOUNT(TF_RIP(%rsp))
690	movq	%rsp,%rdi
691	call	trap
692	MEXITCOUNT
693	testl	$CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
694	je	3f
695	movl	%r14d,%eax
696	xorl	%edx,%edx
697	movl	$MSR_IA32_SPEC_CTRL,%ecx
698	wrmsr
699	/*
700	 * Put back the preserved MSR_GSBASE value.
701	 */
7023:	movl	$MSR_GSBASE,%ecx
703	movq	%r12,%rdx
704	movl	%edx,%eax
705	shrq	$32,%rdx
706	wrmsr
707	movq	%r13,%cr3
708	RESTORE_REGS
709	addq	$TF_RIP,%rsp
710	jmp	doreti_iret
711dbg_fromuserspace:
712	/*
713	 * Switch to kernel GSBASE and kernel page table, and copy frame
714	 * from the IST stack to the normal kernel stack, since trap()
715	 * re-enables interrupts, and since we might trap on DB# while
716	 * in trap().
717	 */
718	swapgs
719	lfence
720	movq	PCPU(KCR3),%rax
721	cmpq	$~0,%rax
722	je	1f
723	movq	%rax,%cr3
7241:	movq	PCPU(RSP0),%rax
725	movl	$TF_SIZE,%ecx
726	subq	%rcx,%rax
727	movq	%rax,%rdi
728	movq	%rsp,%rsi
729	rep;movsb
730	movq	%rax,%rsp
731	call	handle_ibrs_entry
732	movq	PCPU(CURPCB),%rdi
733	orl	$PCB_FULL_IRET,PCB_FLAGS(%rdi)
734	testb	$CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip)
735	jz	3f
736	cmpw	$KUF32SEL,TF_FS(%rsp)
737	jne	2f
738	rdfsbase %rax
739	movq	%rax,PCB_FSBASE(%rdi)
7402:	cmpw	$KUG32SEL,TF_GS(%rsp)
741	jne	3f
742	movl	$MSR_KGSBASE,%ecx
743	rdmsr
744	shlq	$32,%rdx
745	orq	%rdx,%rax
746	movq	%rax,PCB_GSBASE(%rdi)
7473:	jmp	calltrap
748
749/*
750 * NMI handling is special.
751 *
752 * First, NMIs do not respect the state of the processor's RFLAGS.IF
753 * bit.  The NMI handler may be entered at any time, including when
754 * the processor is in a critical section with RFLAGS.IF == 0.
755 * The processor's GS.base value could be invalid on entry to the
756 * handler.
757 *
758 * Second, the processor treats NMIs specially, blocking further NMIs
759 * until an 'iretq' instruction is executed.  We thus need to execute
760 * the NMI handler with interrupts disabled, to prevent a nested interrupt
761 * from executing an 'iretq' instruction and inadvertently taking the
762 * processor out of NMI mode.
763 *
764 * Third, the NMI handler runs on its own stack (tss_ist2). The canonical
765 * GS.base value for the processor is stored just above the bottom of its
766 * NMI stack.  For NMIs taken from kernel mode, the current value in
767 * the processor's GS.base is saved at entry to C-preserved register %r12,
768 * the canonical value for GS.base is then loaded into the processor, and
769 * the saved value is restored at exit time.  For NMIs taken from user mode,
770 * the cheaper 'SWAPGS' instructions are used for swapping GS.base.
771 */
772
773IDTVEC(nmi)
774	subq	$TF_RIP,%rsp
775	movl	$(T_NMI),TF_TRAPNO(%rsp)
776	movq	$0,TF_ADDR(%rsp)
777	movq	$0,TF_ERR(%rsp)
778	movq	%rdi,TF_RDI(%rsp)
779	movq	%rsi,TF_RSI(%rsp)
780	movq	%rdx,TF_RDX(%rsp)
781	movq	%rcx,TF_RCX(%rsp)
782	movq	%r8,TF_R8(%rsp)
783	movq	%r9,TF_R9(%rsp)
784	movq	%rax,TF_RAX(%rsp)
785	movq	%rbx,TF_RBX(%rsp)
786	movq	%rbp,TF_RBP(%rsp)
787	movq	%r10,TF_R10(%rsp)
788	movq	%r11,TF_R11(%rsp)
789	movq	%r12,TF_R12(%rsp)
790	movq	%r13,TF_R13(%rsp)
791	movq	%r14,TF_R14(%rsp)
792	movq	%r15,TF_R15(%rsp)
793	SAVE_SEGS
794	movl	$TF_HASSEGS,TF_FLAGS(%rsp)
795	pushfq
796	andq	$~(PSL_D | PSL_AC),(%rsp)
797	popfq
798	xorl	%ebx,%ebx
799	testb	$SEL_RPL_MASK,TF_CS(%rsp)
800	jnz	nmi_fromuserspace
801	/*
802	 * We've interrupted the kernel.  Preserve GS.base in %r12,
803	 * %cr3 in %r13, and possibly lower half of MSR_IA32_SPEC_CTL in %r14d.
804	 */
805	lfence
806	movl	$MSR_GSBASE,%ecx
807	rdmsr
808	movq	%rax,%r12
809	shlq	$32,%rdx
810	orq	%rdx,%r12
811	/* Retrieve and load the canonical value for GS.base. */
812	movq	TF_SIZE(%rsp),%rdx
813	movl	%edx,%eax
814	shrq	$32,%rdx
815	wrmsr
816	movq	%cr3,%r13
817	movq	PCPU(KCR3),%rax
818	cmpq	$~0,%rax
819	je	1f
820	movq	%rax,%cr3
8211:	testl	$CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
822	je	nmi_calltrap
823	movl	$MSR_IA32_SPEC_CTRL,%ecx
824	rdmsr
825	movl	%eax,%r14d
826	call	handle_ibrs_entry
827	jmp	nmi_calltrap
828nmi_fromuserspace:
829	incl	%ebx
830	swapgs
831	lfence
832	movq	%cr3,%r13
833	movq	PCPU(KCR3),%rax
834	cmpq	$~0,%rax
835	je	1f
836	movq	%rax,%cr3
8371:	call	handle_ibrs_entry
838	movq	PCPU(CURPCB),%rdi
839	testq	%rdi,%rdi
840	jz	3f
841	orl	$PCB_FULL_IRET,PCB_FLAGS(%rdi)
842	testb	$CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip)
843	jz	3f
844	cmpw	$KUF32SEL,TF_FS(%rsp)
845	jne	2f
846	rdfsbase %rax
847	movq	%rax,PCB_FSBASE(%rdi)
8482:	cmpw	$KUG32SEL,TF_GS(%rsp)
849	jne	3f
850	movl	$MSR_KGSBASE,%ecx
851	rdmsr
852	shlq	$32,%rdx
853	orq	%rdx,%rax
854	movq	%rax,PCB_GSBASE(%rdi)
8553:
856/* Note: this label is also used by ddb and gdb: */
857nmi_calltrap:
858	FAKE_MCOUNT(TF_RIP(%rsp))
859	movq	%rsp,%rdi
860	call	trap
861	MEXITCOUNT
862#ifdef HWPMC_HOOKS
863	/*
864	 * Capture a userspace callchain if needed.
865	 *
866	 * - Check if the current trap was from user mode.
867	 * - Check if the current thread is valid.
868	 * - Check if the thread requires a user call chain to be
869	 *   captured.
870	 *
871	 * We are still in NMI mode at this point.
872	 */
873	testl	%ebx,%ebx
874	jz	nocallchain	/* not from userspace */
875	movq	PCPU(CURTHREAD),%rax
876	orq	%rax,%rax	/* curthread present? */
877	jz	nocallchain
878	/*
879	 * Move execution to the regular kernel stack, because we
880	 * committed to return through doreti.
881	 */
882	movq	%rsp,%rsi	/* source stack pointer */
883	movq	$TF_SIZE,%rcx
884	movq	PCPU(RSP0),%rdx
885	subq	%rcx,%rdx
886	movq	%rdx,%rdi	/* destination stack pointer */
887	shrq	$3,%rcx		/* trap frame size in long words */
888	pushfq
889	andq	$~(PSL_D | PSL_AC),(%rsp)
890	popfq
891	rep
892	movsq			/* copy trapframe */
893	movq	%rdx,%rsp	/* we are on the regular kstack */
894
895	testl	$TDP_CALLCHAIN,TD_PFLAGS(%rax) /* flagged for capture? */
896	jz	nocallchain
897	/*
898	 * A user callchain is to be captured, so:
899	 * - Take the processor out of "NMI" mode by faking an "iret",
900	 *   to allow for nested NMI interrupts.
901	 * - Enable interrupts, so that copyin() can work.
902	 */
903	movl	%ss,%eax
904	pushq	%rax		/* tf_ss */
905	pushq	%rdx		/* tf_rsp (on kernel stack) */
906	pushfq			/* tf_rflags */
907	movl	%cs,%eax
908	pushq	%rax		/* tf_cs */
909	pushq	$outofnmi	/* tf_rip */
910	iretq
911outofnmi:
912	/*
913	 * At this point the processor has exited NMI mode and is running
914	 * with interrupts turned off on the normal kernel stack.
915	 *
916	 * If a pending NMI gets recognized at or after this point, it
917	 * will cause a kernel callchain to be traced.
918	 *
919	 * We turn interrupts back on, and call the user callchain capture hook.
920	 */
921	movq	pmc_hook,%rax
922	orq	%rax,%rax
923	jz	nocallchain
924	movq	PCPU(CURTHREAD),%rdi		/* thread */
925	movq	$PMC_FN_USER_CALLCHAIN,%rsi	/* command */
926	movq	%rsp,%rdx			/* frame */
927	sti
928	call	*%rax
929	cli
930nocallchain:
931#endif
932	testl	%ebx,%ebx	/* %ebx == 0 => return to userland */
933	jnz	doreti_exit
934	/*
935	 * Restore speculation control MSR, if preserved.
936	 */
937	testl	$CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
938	je	1f
939	movl	%r14d,%eax
940	xorl	%edx,%edx
941	movl	$MSR_IA32_SPEC_CTRL,%ecx
942	wrmsr
943	/*
944	 * Put back the preserved MSR_GSBASE value.
945	 */
9461:	movl	$MSR_GSBASE,%ecx
947	movq	%r12,%rdx
948	movl	%edx,%eax
949	shrq	$32,%rdx
950	wrmsr
951	cmpb	$0, nmi_flush_l1d_sw(%rip)
952	je	2f
953	call	flush_l1d_sw		/* bhyve L1TF assist */
9542:	movq	%r13,%cr3
955	RESTORE_REGS
956	addq	$TF_RIP,%rsp
957	jmp	doreti_iret
958
959/*
960 * MC# handling is similar to NMI.
961 *
962 * As with NMIs, machine check exceptions do not respect RFLAGS.IF and
963 * can occur at any time with a GS.base value that does not correspond
964 * to the privilege level in CS.
965 *
966 * Machine checks are not unblocked by iretq, but it is best to run
967 * the handler with interrupts disabled since the exception may have
968 * interrupted a critical section.
969 *
970 * The MC# handler runs on its own stack (tss_ist3).  The canonical
971 * GS.base value for the processor is stored just above the bottom of
972 * its MC# stack.  For exceptions taken from kernel mode, the current
973 * value in the processor's GS.base is saved at entry to C-preserved
974 * register %r12, the canonical value for GS.base is then loaded into
975 * the processor, and the saved value is restored at exit time.  For
976 * exceptions taken from user mode, the cheaper 'SWAPGS' instructions
977 * are used for swapping GS.base.
978 */
979
980IDTVEC(mchk)
981	subq	$TF_RIP,%rsp
982	movl	$(T_MCHK),TF_TRAPNO(%rsp)
983	movq	$0,TF_ADDR(%rsp)
984	movq	$0,TF_ERR(%rsp)
985	movq	%rdi,TF_RDI(%rsp)
986	movq	%rsi,TF_RSI(%rsp)
987	movq	%rdx,TF_RDX(%rsp)
988	movq	%rcx,TF_RCX(%rsp)
989	movq	%r8,TF_R8(%rsp)
990	movq	%r9,TF_R9(%rsp)
991	movq	%rax,TF_RAX(%rsp)
992	movq	%rbx,TF_RBX(%rsp)
993	movq	%rbp,TF_RBP(%rsp)
994	movq	%r10,TF_R10(%rsp)
995	movq	%r11,TF_R11(%rsp)
996	movq	%r12,TF_R12(%rsp)
997	movq	%r13,TF_R13(%rsp)
998	movq	%r14,TF_R14(%rsp)
999	movq	%r15,TF_R15(%rsp)
1000	SAVE_SEGS
1001	movl	$TF_HASSEGS,TF_FLAGS(%rsp)
1002	pushfq
1003	andq	$~(PSL_D | PSL_AC),(%rsp)
1004	popfq
1005	xorl	%ebx,%ebx
1006	testb	$SEL_RPL_MASK,TF_CS(%rsp)
1007	jnz	mchk_fromuserspace
1008	/*
1009	 * We've interrupted the kernel.  Preserve GS.base in %r12,
1010	 * %cr3 in %r13, and possibly lower half of MSR_IA32_SPEC_CTL in %r14d.
1011	 */
1012	movl	$MSR_GSBASE,%ecx
1013	rdmsr
1014	movq	%rax,%r12
1015	shlq	$32,%rdx
1016	orq	%rdx,%r12
1017	/* Retrieve and load the canonical value for GS.base. */
1018	movq	TF_SIZE(%rsp),%rdx
1019	movl	%edx,%eax
1020	shrq	$32,%rdx
1021	wrmsr
1022	movq	%cr3,%r13
1023	movq	PCPU(KCR3),%rax
1024	cmpq	$~0,%rax
1025	je	1f
1026	movq	%rax,%cr3
10271:	testl	$CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
1028	je	mchk_calltrap
1029	movl	$MSR_IA32_SPEC_CTRL,%ecx
1030	rdmsr
1031	movl	%eax,%r14d
1032	call	handle_ibrs_entry
1033	jmp	mchk_calltrap
1034mchk_fromuserspace:
1035	incl	%ebx
1036	swapgs
1037	movq	%cr3,%r13
1038	movq	PCPU(KCR3),%rax
1039	cmpq	$~0,%rax
1040	je	1f
1041	movq	%rax,%cr3
10421:	call	handle_ibrs_entry
1043/* Note: this label is also used by ddb and gdb: */
1044mchk_calltrap:
1045	FAKE_MCOUNT(TF_RIP(%rsp))
1046	movq	%rsp,%rdi
1047	call	mca_intr
1048	MEXITCOUNT
1049	testl	%ebx,%ebx	/* %ebx == 0 => return to userland */
1050	jnz	doreti_exit
1051	/*
1052	 * Restore speculation control MSR, if preserved.
1053	 */
1054	testl	$CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
1055	je	1f
1056	movl	%r14d,%eax
1057	xorl	%edx,%edx
1058	movl	$MSR_IA32_SPEC_CTRL,%ecx
1059	wrmsr
1060	/*
1061	 * Put back the preserved MSR_GSBASE value.
1062	 */
10631:	movl	$MSR_GSBASE,%ecx
1064	movq	%r12,%rdx
1065	movl	%edx,%eax
1066	shrq	$32,%rdx
1067	wrmsr
1068	movq	%r13,%cr3
1069	RESTORE_REGS
1070	addq	$TF_RIP,%rsp
1071	jmp	doreti_iret
1072
1073ENTRY(fork_trampoline)
1074	movq	%r12,%rdi		/* function */
1075	movq	%rbx,%rsi		/* arg1 */
1076	movq	%rsp,%rdx		/* trapframe pointer */
1077	call	fork_exit
1078	MEXITCOUNT
1079	jmp	doreti			/* Handle any ASTs */
1080
1081/*
1082 * To efficiently implement classification of trap and interrupt handlers
1083 * for profiling, there must be only trap handlers between the labels btrap
1084 * and bintr, and only interrupt handlers between the labels bintr and
1085 * eintr.  This is implemented (partly) by including files that contain
1086 * some of the handlers.  Before including the files, set up a normal asm
1087 * environment so that the included files doen't need to know that they are
1088 * included.
1089 */
1090
1091#ifdef COMPAT_FREEBSD32
1092	.data
1093	.p2align 4
1094	.text
1095	SUPERALIGN_TEXT
1096
1097#include <amd64/ia32/ia32_exception.S>
1098#endif
1099
1100	.data
1101	.p2align 4
1102	.text
1103	SUPERALIGN_TEXT
1104MCOUNT_LABEL(bintr)
1105
1106#include <amd64/amd64/apic_vector.S>
1107
1108#ifdef DEV_ATPIC
1109	.data
1110	.p2align 4
1111	.text
1112	SUPERALIGN_TEXT
1113
1114#include <amd64/amd64/atpic_vector.S>
1115#endif
1116
1117	.text
1118MCOUNT_LABEL(eintr)
1119
1120/*
1121 * void doreti(struct trapframe)
1122 *
1123 * Handle return from interrupts, traps and syscalls.
1124 */
1125	.text
1126	SUPERALIGN_TEXT
1127	.type	doreti,@function
1128	.globl	doreti
1129doreti:
1130	FAKE_MCOUNT($bintr)		/* init "from" bintr -> doreti */
1131	/*
1132	 * Check if ASTs can be handled now.
1133	 */
1134	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* are we returning to user mode? */
1135	jz	doreti_exit		/* can't handle ASTs now if not */
1136
1137doreti_ast:
1138	/*
1139	 * Check for ASTs atomically with returning.  Disabling CPU
1140	 * interrupts provides sufficient locking even in the SMP case,
1141	 * since we will be informed of any new ASTs by an IPI.
1142	 */
1143	cli
1144	movq	PCPU(CURTHREAD),%rax
1145	testl	$TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
1146	je	doreti_exit
1147	sti
1148	movq	%rsp,%rdi	/* pass a pointer to the trapframe */
1149	call	ast
1150	jmp	doreti_ast
1151
1152	/*
1153	 * doreti_exit:	pop registers, iret.
1154	 *
1155	 *	The segment register pop is a special case, since it may
1156	 *	fault if (for example) a sigreturn specifies bad segment
1157	 *	registers.  The fault is handled in trap.c.
1158	 */
1159doreti_exit:
1160	MEXITCOUNT
1161	movq	PCPU(CURPCB),%r8
1162
1163	/*
1164	 * Do not reload segment registers for kernel.
1165	 * Since we do not reload segments registers with sane
1166	 * values on kernel entry, descriptors referenced by
1167	 * segments registers might be not valid.  This is fatal
1168	 * for user mode, but is not a problem for the kernel.
1169	 */
1170	testb	$SEL_RPL_MASK,TF_CS(%rsp)
1171	jz	ld_regs
1172	testl	$PCB_FULL_IRET,PCB_FLAGS(%r8)
1173	jz	ld_regs
1174	andl	$~PCB_FULL_IRET,PCB_FLAGS(%r8)
1175	testl	$TF_HASSEGS,TF_FLAGS(%rsp)
1176	je	set_segs
1177
1178do_segs:
1179	/* Restore %fs and fsbase */
1180	movw	TF_FS(%rsp),%ax
1181	.globl	ld_fs
1182ld_fs:
1183	movw	%ax,%fs
1184	cmpw	$KUF32SEL,%ax
1185	jne	1f
1186	movl	$MSR_FSBASE,%ecx
1187	movl	PCB_FSBASE(%r8),%eax
1188	movl	PCB_FSBASE+4(%r8),%edx
1189	.globl	ld_fsbase
1190ld_fsbase:
1191	wrmsr
11921:
1193	/* Restore %gs and gsbase */
1194	movw	TF_GS(%rsp),%si
1195	pushfq
1196	cli
1197	movl	$MSR_GSBASE,%ecx
1198	/* Save current kernel %gs base into %r12d:%r13d */
1199	rdmsr
1200	movl	%eax,%r12d
1201	movl	%edx,%r13d
1202	.globl	ld_gs
1203ld_gs:
1204	movw	%si,%gs
1205	/* Save user %gs base into %r14d:%r15d */
1206	rdmsr
1207	movl	%eax,%r14d
1208	movl	%edx,%r15d
1209	/* Restore kernel %gs base */
1210	movl	%r12d,%eax
1211	movl	%r13d,%edx
1212	wrmsr
1213	popfq
1214	/*
1215	 * Restore user %gs base, either from PCB if used for TLS, or
1216	 * from the previously saved msr read.
1217	 */
1218	movl	$MSR_KGSBASE,%ecx
1219	cmpw	$KUG32SEL,%si
1220	jne	1f
1221	movl	PCB_GSBASE(%r8),%eax
1222	movl	PCB_GSBASE+4(%r8),%edx
1223	jmp	ld_gsbase
12241:
1225	movl	%r14d,%eax
1226	movl	%r15d,%edx
1227	.globl	ld_gsbase
1228ld_gsbase:
1229	wrmsr	/* May trap if non-canonical, but only for TLS. */
1230	.globl	ld_es
1231ld_es:
1232	movw	TF_ES(%rsp),%es
1233	.globl	ld_ds
1234ld_ds:
1235	movw	TF_DS(%rsp),%ds
1236ld_regs:
1237	RESTORE_REGS
1238	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
1239	jz	2f			/* keep running with kernel GS.base */
1240	cli
1241	call	handle_ibrs_exit_rs
1242	callq	*mds_handler
1243	cmpq	$~0,PCPU(UCR3)
1244	je	1f
1245	pushq	%rdx
1246	movq	PCPU(PTI_RSP0),%rdx
1247	subq	$PTI_SIZE,%rdx
1248	movq	%rax,PTI_RAX(%rdx)
1249	popq	%rax
1250	movq	%rax,PTI_RDX(%rdx)
1251	movq	TF_RIP(%rsp),%rax
1252	movq	%rax,PTI_RIP(%rdx)
1253	movq	TF_CS(%rsp),%rax
1254	movq	%rax,PTI_CS(%rdx)
1255	movq	TF_RFLAGS(%rsp),%rax
1256	movq	%rax,PTI_RFLAGS(%rdx)
1257	movq	TF_RSP(%rsp),%rax
1258	movq	%rax,PTI_RSP(%rdx)
1259	movq	TF_SS(%rsp),%rax
1260	movq	%rax,PTI_SS(%rdx)
1261	movq	PCPU(UCR3),%rax
1262	swapgs
1263	movq	%rdx,%rsp
1264	movq	%rax,%cr3
1265	popq	%rdx
1266	popq	%rax
1267	addq	$8,%rsp
1268	jmp	doreti_iret
12691:	swapgs
12702:	addq	$TF_RIP,%rsp
1271	.globl	doreti_iret
1272doreti_iret:
1273	iretq
1274
1275set_segs:
1276	movw	$KUDSEL,%ax
1277	movw	%ax,TF_DS(%rsp)
1278	movw	%ax,TF_ES(%rsp)
1279	movw	$KUF32SEL,TF_FS(%rsp)
1280	movw	$KUG32SEL,TF_GS(%rsp)
1281	jmp	do_segs
1282
1283	/*
1284	 * doreti_iret_fault.  Alternative return code for
1285	 * the case where we get a fault in the doreti_exit code
1286	 * above.  trap() (amd64/amd64/trap.c) catches this specific
1287	 * case, sends the process a signal and continues in the
1288	 * corresponding place in the code below.
1289	 */
1290	ALIGN_TEXT
1291	.globl	doreti_iret_fault
1292doreti_iret_fault:
1293	subq	$TF_RIP,%rsp		/* space including tf_err, tf_trapno */
1294	movq	%rax,TF_RAX(%rsp)
1295	movq	%rdx,TF_RDX(%rsp)
1296	movq	%rcx,TF_RCX(%rsp)
1297	call	handle_ibrs_entry
1298	testb	$SEL_RPL_MASK,TF_CS(%rsp)
1299	jz	1f
1300	sti
13011:
1302	SAVE_SEGS
1303	movl	$TF_HASSEGS,TF_FLAGS(%rsp)
1304	movq	%rdi,TF_RDI(%rsp)
1305	movq	%rsi,TF_RSI(%rsp)
1306	movq	%r8,TF_R8(%rsp)
1307	movq	%r9,TF_R9(%rsp)
1308	movq	%rbx,TF_RBX(%rsp)
1309	movq	%rbp,TF_RBP(%rsp)
1310	movq	%r10,TF_R10(%rsp)
1311	movq	%r11,TF_R11(%rsp)
1312	movq	%r12,TF_R12(%rsp)
1313	movq	%r13,TF_R13(%rsp)
1314	movq	%r14,TF_R14(%rsp)
1315	movq	%r15,TF_R15(%rsp)
1316	movl	$T_PROTFLT,TF_TRAPNO(%rsp)
1317	movq	$0,TF_ERR(%rsp)	/* XXX should be the error code */
1318	movq	$0,TF_ADDR(%rsp)
1319	FAKE_MCOUNT(TF_RIP(%rsp))
1320	jmp	calltrap
1321
1322	ALIGN_TEXT
1323	.globl	ds_load_fault
1324ds_load_fault:
1325	movl	$T_PROTFLT,TF_TRAPNO(%rsp)
1326	testb	$SEL_RPL_MASK,TF_CS(%rsp)
1327	jz	1f
1328	sti
13291:
1330	movq	%rsp,%rdi
1331	call	trap
1332	movw	$KUDSEL,TF_DS(%rsp)
1333	jmp	doreti
1334
1335	ALIGN_TEXT
1336	.globl	es_load_fault
1337es_load_fault:
1338	movl	$T_PROTFLT,TF_TRAPNO(%rsp)
1339	testl	$PSL_I,TF_RFLAGS(%rsp)
1340	jz	1f
1341	sti
13421:
1343	movq	%rsp,%rdi
1344	call	trap
1345	movw	$KUDSEL,TF_ES(%rsp)
1346	jmp	doreti
1347
1348	ALIGN_TEXT
1349	.globl	fs_load_fault
1350fs_load_fault:
1351	testl	$PSL_I,TF_RFLAGS(%rsp)
1352	jz	1f
1353	sti
13541:
1355	movl	$T_PROTFLT,TF_TRAPNO(%rsp)
1356	movq	%rsp,%rdi
1357	call	trap
1358	movw	$KUF32SEL,TF_FS(%rsp)
1359	jmp	doreti
1360
1361	ALIGN_TEXT
1362	.globl	gs_load_fault
1363gs_load_fault:
1364	popfq
1365	movl	$T_PROTFLT,TF_TRAPNO(%rsp)
1366	testl	$PSL_I,TF_RFLAGS(%rsp)
1367	jz	1f
1368	sti
13691:
1370	movq	%rsp,%rdi
1371	call	trap
1372	movw	$KUG32SEL,TF_GS(%rsp)
1373	jmp	doreti
1374
1375	ALIGN_TEXT
1376	.globl	fsbase_load_fault
1377fsbase_load_fault:
1378	movl	$T_PROTFLT,TF_TRAPNO(%rsp)
1379	testl	$PSL_I,TF_RFLAGS(%rsp)
1380	jz	1f
1381	sti
13821:
1383	movq	%rsp,%rdi
1384	call	trap
1385	movq	PCPU(CURTHREAD),%r8
1386	movq	TD_PCB(%r8),%r8
1387	movq	$0,PCB_FSBASE(%r8)
1388	jmp	doreti
1389
1390	ALIGN_TEXT
1391	.globl	gsbase_load_fault
1392gsbase_load_fault:
1393	movl	$T_PROTFLT,TF_TRAPNO(%rsp)
1394	testl	$PSL_I,TF_RFLAGS(%rsp)
1395	jz	1f
1396	sti
13971:
1398	movq	%rsp,%rdi
1399	call	trap
1400	movq	PCPU(CURTHREAD),%r8
1401	movq	TD_PCB(%r8),%r8
1402	movq	$0,PCB_GSBASE(%r8)
1403	jmp	doreti
1404
1405#ifdef HWPMC_HOOKS
1406	ENTRY(end_exceptions)
1407#endif
1408