]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/amd64/amd64/exception.S
MFV r359401: OpenBSM: import ee79d73e8df5: auditreduce: add a zone filter
[FreeBSD/FreeBSD.git] / sys / amd64 / amd64 / exception.S
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 <kib@FreeBSD.org> 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
57 dtrace_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
63 dtrace_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
103 MCOUNT_LABEL(user)
104 MCOUNT_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
124 X\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
159 X\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
196 X\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
220 alltraps_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
232 alltraps_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)
238 alltraps_save_segs:
239         SAVE_SEGS
240         testl   $PSL_I,TF_RFLAGS(%rsp)
241         jz      alltraps_pushregs_no_rax
242         sti
243 alltraps_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
287 calltrap:
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
302 alltraps_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
310 alltraps_noen_k:
311         lfence
312         movq    %rdi,TF_RDI(%rsp)
313 alltraps_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
323 IDTVEC(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         movq    TF_SIZE(%rsp),%rdx
349         movl    %edx,%eax
350         shrq    $32,%rdx
351         movl    $MSR_GSBASE,%ecx
352         wrmsr
353         movq    %cr3,%rax
354         movq    %rax,PCPU(SAVED_UCR3)
355         movq    PCPU(KCR3),%rax
356         cmpq    $~0,%rax
357         je      2f
358         movq    %rax,%cr3
359 2:      movq    %rsp,%rdi
360         call    dblfault_handler
361 3:      hlt
362         jmp     3b
363
364         ALIGN_TEXT
365 IDTVEC(page_pti)
366         testb   $SEL_RPL_MASK,PTI_CS-PTI_ERR(%rsp)
367         jz      page_k
368         swapgs
369         lfence
370         pushq   %rax
371         movq    %cr3,%rax
372         movq    %rax,PCPU(SAVED_UCR3)
373         cmpq    $~0,PCPU(UCR3)
374         jne     1f
375         popq    %rax
376         jmp     page_u
377 1:      pushq   %rdx
378         PTI_UUENTRY has_err=1
379         jmp     page_u
380         ALIGN_TEXT
381 IDTVEC(page)
382         testb   $SEL_RPL_MASK,TF_CS-TF_ERR(%rsp) /* Did we come from kernel? */
383         jnz     page_u_swapgs           /* already running with kernel GS.base */
384 page_k:
385         lfence
386         subq    $TF_ERR,%rsp
387         movq    %rdi,TF_RDI(%rsp)       /* free up GP registers */
388         movq    %rax,TF_RAX(%rsp)
389         movq    %rdx,TF_RDX(%rsp)
390         movq    %rcx,TF_RCX(%rsp)
391         jmp     page_cr2
392         ALIGN_TEXT
393 page_u_swapgs:
394         swapgs
395         lfence
396 page_u:
397         subq    $TF_ERR,%rsp
398         movq    %rdi,TF_RDI(%rsp)
399         movq    %rax,TF_RAX(%rsp)
400         movq    %rdx,TF_RDX(%rsp)
401         movq    %rcx,TF_RCX(%rsp)
402         movq    PCPU(CURPCB),%rdi
403         andl    $~PCB_FULL_IRET,PCB_FLAGS(%rdi)
404         movq    PCPU(SAVED_UCR3),%rax
405         movq    %rax,PCB_SAVED_UCR3(%rdi)
406         call    handle_ibrs_entry
407 page_cr2:
408         movq    %cr2,%rdi               /* preserve %cr2 before ..  */
409         movq    %rdi,TF_ADDR(%rsp)      /* enabling interrupts. */
410         SAVE_SEGS
411         movl    $T_PAGEFLT,TF_TRAPNO(%rsp)
412         testl   $PSL_I,TF_RFLAGS(%rsp)
413         jz      alltraps_pushregs_no_rax
414         sti
415         jmp     alltraps_pushregs_no_rax
416
417         /*
418          * We have to special-case this one.  If we get a trap in doreti() at
419          * the iretq stage, we'll reenter with the wrong gs state.  We'll have
420          * to do a special the swapgs in this case even coming from the kernel.
421          * XXX linux has a trap handler for their equivalent of load_gs().
422          *
423          * On the stack, we have the hardware interrupt frame to return
424          * to usermode (faulted) and another frame with error code, for
425          * fault.  For PTI, copy both frames to the main thread stack.
426          * Handle the potential 16-byte alignment adjustment incurred
427          * during the second fault by copying both frames independently
428          * while unwinding the stack in between.
429          */
430         .macro PROTF_ENTRY name,trapno
431 \name\()_pti_doreti:
432         swapgs
433         lfence
434         cmpq    $~0,PCPU(UCR3)
435         je      1f
436         pushq   %rax
437         pushq   %rdx
438         movq    PCPU(KCR3),%rax
439         movq    %rax,%cr3
440         movq    PCPU(RSP0),%rax
441         subq    $2*PTI_SIZE-3*8,%rax /* no err, %rax, %rdx in faulted frame */
442         MOVE_STACKS     (PTI_SIZE / 8)
443         addq    $PTI_SIZE,%rax
444         movq    PTI_RSP(%rsp),%rsp
445         MOVE_STACKS     (PTI_SIZE / 8 - 3)
446         subq    $PTI_SIZE,%rax
447         movq    %rax,%rsp
448         popq    %rdx
449         popq    %rax
450 1:      swapgs
451         jmp     X\name
452 IDTVEC(\name\()_pti)
453         cmpq    $doreti_iret,PTI_RIP-2*8(%rsp)
454         je      \name\()_pti_doreti
455         testb   $SEL_RPL_MASK,PTI_CS-2*8(%rsp) /* %rax, %rdx not yet pushed */
456         jz      X\name          /* lfence is not needed until %gs: use */
457         PTI_UENTRY has_err=1
458         swapgs  /* fence provided by PTI_UENTRY */
459 IDTVEC(\name)
460         subq    $TF_ERR,%rsp
461         movl    $\trapno,TF_TRAPNO(%rsp)
462         jmp     prot_addrf
463         .endm
464
465         PROTF_ENTRY     missing, T_SEGNPFLT
466         PROTF_ENTRY     stk, T_STKFLT
467         PROTF_ENTRY     prot, T_PROTFLT
468
469 prot_addrf:
470         movq    $0,TF_ADDR(%rsp)
471         movq    %rdi,TF_RDI(%rsp)       /* free up a GP register */
472         movq    %rax,TF_RAX(%rsp)
473         movq    %rdx,TF_RDX(%rsp)
474         movq    %rcx,TF_RCX(%rsp)
475         movw    %fs,TF_FS(%rsp)
476         movw    %gs,TF_GS(%rsp)
477         leaq    doreti_iret(%rip),%rdi
478         cmpq    %rdi,TF_RIP(%rsp)
479         je      5f                      /* kernel but with user gsbase!! */
480         testb   $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
481         jz      6f                      /* already running with kernel GS.base */
482         testb   $CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip)
483         jz      2f
484         cmpw    $KUF32SEL,TF_FS(%rsp)
485         jne     1f
486         rdfsbase %rax
487 1:      cmpw    $KUG32SEL,TF_GS(%rsp)
488         jne     2f
489         rdgsbase %rdx
490 2:      swapgs
491         lfence
492         movq    PCPU(CURPCB),%rdi
493         testb   $CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip)
494         jz      4f
495         cmpw    $KUF32SEL,TF_FS(%rsp)
496         jne     3f
497         movq    %rax,PCB_FSBASE(%rdi)
498 3:      cmpw    $KUG32SEL,TF_GS(%rsp)
499         jne     4f
500         movq    %rdx,PCB_GSBASE(%rdi)
501         orl     $PCB_FULL_IRET,PCB_FLAGS(%rdi)  /* full iret from user #gp */
502 4:      call    handle_ibrs_entry
503         movw    %es,TF_ES(%rsp)
504         movw    %ds,TF_DS(%rsp)
505         testl   $PSL_I,TF_RFLAGS(%rsp)
506         jz      alltraps_pushregs_no_rax
507         sti
508         jmp     alltraps_pushregs_no_rax
509
510 5:      swapgs
511 6:      lfence
512         movq    PCPU(CURPCB),%rdi
513         jmp     4b
514
515 /*
516  * Fast syscall entry point.  We enter here with just our new %cs/%ss set,
517  * and the new privilige level.  We are still running on the old user stack
518  * pointer.  We have to juggle a few things around to find our stack etc.
519  * swapgs gives us access to our PCPU space only.
520  *
521  * We do not support invoking this from a custom segment registers,
522  * esp. %cs, %ss, %fs, %gs, e.g. using entries from an LDT.
523  */
524         SUPERALIGN_TEXT
525 IDTVEC(fast_syscall_pti)
526         swapgs
527         lfence
528         movq    %rax,PCPU(SCRATCH_RAX)
529         cmpq    $~0,PCPU(UCR3)
530         je      fast_syscall_common
531         movq    PCPU(KCR3),%rax
532         movq    %rax,%cr3
533         jmp     fast_syscall_common
534         SUPERALIGN_TEXT
535 IDTVEC(fast_syscall)
536         swapgs
537         lfence
538         movq    %rax,PCPU(SCRATCH_RAX)
539 fast_syscall_common:
540         movq    %rsp,PCPU(SCRATCH_RSP)
541         movq    PCPU(RSP0),%rsp
542         /* Now emulate a trapframe. Make the 8 byte alignment odd for call. */
543         subq    $TF_SIZE,%rsp
544         /* defer TF_RSP till we have a spare register */
545         movq    %r11,TF_RFLAGS(%rsp)
546         movq    %rcx,TF_RIP(%rsp)       /* %rcx original value is in %r10 */
547         movq    PCPU(SCRATCH_RSP),%r11  /* %r11 already saved */
548         movq    %r11,TF_RSP(%rsp)       /* user stack pointer */
549         movq    PCPU(SCRATCH_RAX),%rax
550         /*
551          * Save a few arg registers early to free them for use in
552          * handle_ibrs_entry().  %r10 is especially tricky.  It is not an
553          * arg register, but it holds the arg register %rcx.  Profiling
554          * preserves %rcx, but may clobber %r10.  Profiling may also
555          * clobber %r11, but %r11 (original %eflags) has been saved.
556          */
557         movq    %rax,TF_RAX(%rsp)       /* syscall number */
558         movq    %rdx,TF_RDX(%rsp)       /* arg 3 */
559         movq    %r10,TF_RCX(%rsp)       /* arg 4 */
560         SAVE_SEGS
561         call    handle_ibrs_entry
562         movq    PCPU(CURPCB),%r11
563         andl    $~PCB_FULL_IRET,PCB_FLAGS(%r11)
564         sti
565         movq    $KUDSEL,TF_SS(%rsp)
566         movq    $KUCSEL,TF_CS(%rsp)
567         movq    $2,TF_ERR(%rsp)
568         movq    %rdi,TF_RDI(%rsp)       /* arg 1 */
569         movq    %rsi,TF_RSI(%rsp)       /* arg 2 */
570         movq    %r8,TF_R8(%rsp)         /* arg 5 */
571         movq    %r9,TF_R9(%rsp)         /* arg 6 */
572         movq    %rbx,TF_RBX(%rsp)       /* C preserved */
573         movq    %rbp,TF_RBP(%rsp)       /* C preserved */
574         movq    %r12,TF_R12(%rsp)       /* C preserved */
575         movq    %r13,TF_R13(%rsp)       /* C preserved */
576         movq    %r14,TF_R14(%rsp)       /* C preserved */
577         movq    %r15,TF_R15(%rsp)       /* C preserved */
578         movl    $TF_HASSEGS,TF_FLAGS(%rsp)
579         FAKE_MCOUNT(TF_RIP(%rsp))
580         movq    PCPU(CURTHREAD),%rdi
581         movq    %rsp,TD_FRAME(%rdi)
582         movl    TF_RFLAGS(%rsp),%esi
583         andl    $PSL_T,%esi
584         call    amd64_syscall
585 1:      movq    PCPU(CURPCB),%rax
586         /* Disable interrupts before testing PCB_FULL_IRET. */
587         cli
588         testl   $PCB_FULL_IRET,PCB_FLAGS(%rax)
589         jnz     4f
590         /* Check for and handle AST's on return to userland. */
591         movq    PCPU(CURTHREAD),%rax
592         testl   $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
593         jne     3f
594         call    handle_ibrs_exit
595         callq   *mds_handler
596         /* Restore preserved registers. */
597         MEXITCOUNT
598         movq    TF_RDI(%rsp),%rdi       /* bonus; preserve arg 1 */
599         movq    TF_RSI(%rsp),%rsi       /* bonus: preserve arg 2 */
600         movq    TF_RDX(%rsp),%rdx       /* return value 2 */
601         movq    TF_RAX(%rsp),%rax       /* return value 1 */
602         movq    TF_RFLAGS(%rsp),%r11    /* original %rflags */
603         movq    TF_RIP(%rsp),%rcx       /* original %rip */
604         movq    TF_RSP(%rsp),%rsp       /* user stack pointer */
605         xorl    %r8d,%r8d               /* zero the rest of GPRs */
606         xorl    %r10d,%r10d
607         cmpq    $~0,PCPU(UCR3)
608         je      2f
609         movq    PCPU(UCR3),%r9
610         movq    %r9,%cr3
611 2:      xorl    %r9d,%r9d
612         swapgs
613         sysretq
614
615 3:      /* AST scheduled. */
616         sti
617         movq    %rsp,%rdi
618         call    ast
619         jmp     1b
620
621 4:      /* Requested full context restore, use doreti for that. */
622         MEXITCOUNT
623         jmp     doreti
624
625 /*
626  * Here for CYA insurance, in case a "syscall" instruction gets
627  * issued from 32 bit compatibility mode. MSR_CSTAR has to point
628  * to *something* if EFER_SCE is enabled.
629  */
630 IDTVEC(fast_syscall32)
631         sysret
632
633 /*
634  * DB# handler is very similar to NM#, because 'mov/pop %ss' delay
635  * generation of exception until the next instruction is executed,
636  * which might be a kernel entry.  So we must execute the handler
637  * on IST stack and be ready for non-kernel GSBASE.
638  */
639 IDTVEC(dbg)
640         subq    $TF_RIP,%rsp
641         movl    $(T_TRCTRAP),TF_TRAPNO(%rsp)
642         movq    $0,TF_ADDR(%rsp)
643         movq    $0,TF_ERR(%rsp)
644         movq    %rdi,TF_RDI(%rsp)
645         movq    %rsi,TF_RSI(%rsp)
646         movq    %rdx,TF_RDX(%rsp)
647         movq    %rcx,TF_RCX(%rsp)
648         movq    %r8,TF_R8(%rsp)
649         movq    %r9,TF_R9(%rsp)
650         movq    %rax,TF_RAX(%rsp)
651         movq    %rbx,TF_RBX(%rsp)
652         movq    %rbp,TF_RBP(%rsp)
653         movq    %r10,TF_R10(%rsp)
654         movq    %r11,TF_R11(%rsp)
655         movq    %r12,TF_R12(%rsp)
656         movq    %r13,TF_R13(%rsp)
657         movq    %r14,TF_R14(%rsp)
658         movq    %r15,TF_R15(%rsp)
659         SAVE_SEGS
660         movl    $TF_HASSEGS,TF_FLAGS(%rsp)
661         pushfq
662         andq    $~(PSL_D | PSL_AC),(%rsp)
663         popfq
664         testb   $SEL_RPL_MASK,TF_CS(%rsp)
665         jnz     dbg_fromuserspace
666         lfence
667         /*
668          * We've interrupted the kernel.  Preserve GS.base in %r12,
669          * %cr3 in %r13, and possibly lower half of MSR_IA32_SPEC_CTL in %r14d.
670          */
671         movl    $MSR_GSBASE,%ecx
672         rdmsr
673         movq    %rax,%r12
674         shlq    $32,%rdx
675         orq     %rdx,%r12
676         /* Retrieve and load the canonical value for GS.base. */
677         movq    TF_SIZE(%rsp),%rdx
678         movl    %edx,%eax
679         shrq    $32,%rdx
680         wrmsr
681         movq    %cr3,%r13
682         movq    PCPU(KCR3),%rax
683         cmpq    $~0,%rax
684         je      1f
685         movq    %rax,%cr3
686 1:      testl   $CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
687         je      2f
688         movl    $MSR_IA32_SPEC_CTRL,%ecx
689         rdmsr
690         movl    %eax,%r14d
691         call    handle_ibrs_entry
692 2:      FAKE_MCOUNT(TF_RIP(%rsp))
693         movq    %rsp,%rdi
694         call    trap
695         MEXITCOUNT
696         testl   $CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
697         je      3f
698         movl    %r14d,%eax
699         xorl    %edx,%edx
700         movl    $MSR_IA32_SPEC_CTRL,%ecx
701         wrmsr
702         /*
703          * Put back the preserved MSR_GSBASE value.
704          */
705 3:      movl    $MSR_GSBASE,%ecx
706         movq    %r12,%rdx
707         movl    %edx,%eax
708         shrq    $32,%rdx
709         wrmsr
710         movq    %r13,%cr3
711         RESTORE_REGS
712         addq    $TF_RIP,%rsp
713         jmp     doreti_iret
714 dbg_fromuserspace:
715         /*
716          * Switch to kernel GSBASE and kernel page table, and copy frame
717          * from the IST stack to the normal kernel stack, since trap()
718          * re-enables interrupts, and since we might trap on DB# while
719          * in trap().
720          */
721         swapgs
722         lfence
723         movq    PCPU(KCR3),%rax
724         cmpq    $~0,%rax
725         je      1f
726         movq    %rax,%cr3
727 1:      movq    PCPU(RSP0),%rax
728         movl    $TF_SIZE,%ecx
729         subq    %rcx,%rax
730         movq    %rax,%rdi
731         movq    %rsp,%rsi
732         rep;movsb
733         movq    %rax,%rsp
734         call    handle_ibrs_entry
735         movq    PCPU(CURPCB),%rdi
736         orl     $PCB_FULL_IRET,PCB_FLAGS(%rdi)
737         testb   $CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip)
738         jz      3f
739         cmpw    $KUF32SEL,TF_FS(%rsp)
740         jne     2f
741         rdfsbase %rax
742         movq    %rax,PCB_FSBASE(%rdi)
743 2:      cmpw    $KUG32SEL,TF_GS(%rsp)
744         jne     3f
745         movl    $MSR_KGSBASE,%ecx
746         rdmsr
747         shlq    $32,%rdx
748         orq     %rdx,%rax
749         movq    %rax,PCB_GSBASE(%rdi)
750 3:      jmp     calltrap
751
752 /*
753  * NMI handling is special.
754  *
755  * First, NMIs do not respect the state of the processor's RFLAGS.IF
756  * bit.  The NMI handler may be entered at any time, including when
757  * the processor is in a critical section with RFLAGS.IF == 0.
758  * The processor's GS.base value could be invalid on entry to the
759  * handler.
760  *
761  * Second, the processor treats NMIs specially, blocking further NMIs
762  * until an 'iretq' instruction is executed.  We thus need to execute
763  * the NMI handler with interrupts disabled, to prevent a nested interrupt
764  * from executing an 'iretq' instruction and inadvertently taking the
765  * processor out of NMI mode.
766  *
767  * Third, the NMI handler runs on its own stack (tss_ist2). The canonical
768  * GS.base value for the processor is stored just above the bottom of its
769  * NMI stack.  For NMIs taken from kernel mode, the current value in
770  * the processor's GS.base is saved at entry to C-preserved register %r12,
771  * the canonical value for GS.base is then loaded into the processor, and
772  * the saved value is restored at exit time.  For NMIs taken from user mode,
773  * the cheaper 'SWAPGS' instructions are used for swapping GS.base.
774  */
775
776 IDTVEC(nmi)
777         subq    $TF_RIP,%rsp
778         movl    $(T_NMI),TF_TRAPNO(%rsp)
779         movq    $0,TF_ADDR(%rsp)
780         movq    $0,TF_ERR(%rsp)
781         movq    %rdi,TF_RDI(%rsp)
782         movq    %rsi,TF_RSI(%rsp)
783         movq    %rdx,TF_RDX(%rsp)
784         movq    %rcx,TF_RCX(%rsp)
785         movq    %r8,TF_R8(%rsp)
786         movq    %r9,TF_R9(%rsp)
787         movq    %rax,TF_RAX(%rsp)
788         movq    %rbx,TF_RBX(%rsp)
789         movq    %rbp,TF_RBP(%rsp)
790         movq    %r10,TF_R10(%rsp)
791         movq    %r11,TF_R11(%rsp)
792         movq    %r12,TF_R12(%rsp)
793         movq    %r13,TF_R13(%rsp)
794         movq    %r14,TF_R14(%rsp)
795         movq    %r15,TF_R15(%rsp)
796         SAVE_SEGS
797         movl    $TF_HASSEGS,TF_FLAGS(%rsp)
798         pushfq
799         andq    $~(PSL_D | PSL_AC),(%rsp)
800         popfq
801         xorl    %ebx,%ebx
802         testb   $SEL_RPL_MASK,TF_CS(%rsp)
803         jnz     nmi_fromuserspace
804         /*
805          * We've interrupted the kernel.  Preserve GS.base in %r12,
806          * %cr3 in %r13, and possibly lower half of MSR_IA32_SPEC_CTL in %r14d.
807          */
808         lfence
809         movl    $MSR_GSBASE,%ecx
810         rdmsr
811         movq    %rax,%r12
812         shlq    $32,%rdx
813         orq     %rdx,%r12
814         /* Retrieve and load the canonical value for GS.base. */
815         movq    TF_SIZE(%rsp),%rdx
816         movl    %edx,%eax
817         shrq    $32,%rdx
818         wrmsr
819         movq    %cr3,%r13
820         movq    PCPU(KCR3),%rax
821         cmpq    $~0,%rax
822         je      1f
823         movq    %rax,%cr3
824 1:      testl   $CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
825         je      nmi_calltrap
826         movl    $MSR_IA32_SPEC_CTRL,%ecx
827         rdmsr
828         movl    %eax,%r14d
829         call    handle_ibrs_entry
830         jmp     nmi_calltrap
831 nmi_fromuserspace:
832         incl    %ebx
833         swapgs
834         lfence
835         movq    %cr3,%r13
836         movq    PCPU(KCR3),%rax
837         cmpq    $~0,%rax
838         je      1f
839         movq    %rax,%cr3
840 1:      call    handle_ibrs_entry
841         movq    PCPU(CURPCB),%rdi
842         testq   %rdi,%rdi
843         jz      3f
844         orl     $PCB_FULL_IRET,PCB_FLAGS(%rdi)
845         testb   $CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip)
846         jz      3f
847         cmpw    $KUF32SEL,TF_FS(%rsp)
848         jne     2f
849         rdfsbase %rax
850         movq    %rax,PCB_FSBASE(%rdi)
851 2:      cmpw    $KUG32SEL,TF_GS(%rsp)
852         jne     3f
853         movl    $MSR_KGSBASE,%ecx
854         rdmsr
855         shlq    $32,%rdx
856         orq     %rdx,%rax
857         movq    %rax,PCB_GSBASE(%rdi)
858 3:
859 /* Note: this label is also used by ddb and gdb: */
860 nmi_calltrap:
861         FAKE_MCOUNT(TF_RIP(%rsp))
862         movq    %rsp,%rdi
863         call    trap
864         MEXITCOUNT
865 #ifdef HWPMC_HOOKS
866         /*
867          * Capture a userspace callchain if needed.
868          *
869          * - Check if the current trap was from user mode.
870          * - Check if the current thread is valid.
871          * - Check if the thread requires a user call chain to be
872          *   captured.
873          *
874          * We are still in NMI mode at this point.
875          */
876         testl   %ebx,%ebx
877         jz      nocallchain     /* not from userspace */
878         movq    PCPU(CURTHREAD),%rax
879         orq     %rax,%rax       /* curthread present? */
880         jz      nocallchain
881         /*
882          * Move execution to the regular kernel stack, because we
883          * committed to return through doreti.
884          */
885         movq    %rsp,%rsi       /* source stack pointer */
886         movq    $TF_SIZE,%rcx
887         movq    PCPU(RSP0),%rdx
888         subq    %rcx,%rdx
889         movq    %rdx,%rdi       /* destination stack pointer */
890         shrq    $3,%rcx         /* trap frame size in long words */
891         pushfq
892         andq    $~(PSL_D | PSL_AC),(%rsp)
893         popfq
894         rep
895         movsq                   /* copy trapframe */
896         movq    %rdx,%rsp       /* we are on the regular kstack */
897
898         testl   $TDP_CALLCHAIN,TD_PFLAGS(%rax) /* flagged for capture? */
899         jz      nocallchain
900         /*
901          * A user callchain is to be captured, so:
902          * - Take the processor out of "NMI" mode by faking an "iret",
903          *   to allow for nested NMI interrupts.
904          * - Enable interrupts, so that copyin() can work.
905          */
906         movl    %ss,%eax
907         pushq   %rax            /* tf_ss */
908         pushq   %rdx            /* tf_rsp (on kernel stack) */
909         pushfq                  /* tf_rflags */
910         movl    %cs,%eax
911         pushq   %rax            /* tf_cs */
912         pushq   $outofnmi       /* tf_rip */
913         iretq
914 outofnmi:
915         /*
916          * At this point the processor has exited NMI mode and is running
917          * with interrupts turned off on the normal kernel stack.
918          *
919          * If a pending NMI gets recognized at or after this point, it
920          * will cause a kernel callchain to be traced.
921          *
922          * We turn interrupts back on, and call the user callchain capture hook.
923          */
924         movq    pmc_hook,%rax
925         orq     %rax,%rax
926         jz      nocallchain
927         movq    PCPU(CURTHREAD),%rdi            /* thread */
928         movq    $PMC_FN_USER_CALLCHAIN,%rsi     /* command */
929         movq    %rsp,%rdx                       /* frame */
930         sti
931         call    *%rax
932         cli
933 nocallchain:
934 #endif
935         testl   %ebx,%ebx       /* %ebx == 0 => return to userland */
936         jnz     doreti_exit
937         /*
938          * Restore speculation control MSR, if preserved.
939          */
940         testl   $CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
941         je      1f
942         movl    %r14d,%eax
943         xorl    %edx,%edx
944         movl    $MSR_IA32_SPEC_CTRL,%ecx
945         wrmsr
946         /*
947          * Put back the preserved MSR_GSBASE value.
948          */
949 1:      movl    $MSR_GSBASE,%ecx
950         movq    %r12,%rdx
951         movl    %edx,%eax
952         shrq    $32,%rdx
953         wrmsr
954         cmpb    $0, nmi_flush_l1d_sw(%rip)
955         je      2f
956         call    flush_l1d_sw            /* bhyve L1TF assist */
957 2:      movq    %r13,%cr3
958         RESTORE_REGS
959         addq    $TF_RIP,%rsp
960         jmp     doreti_iret
961
962 /*
963  * MC# handling is similar to NMI.
964  *
965  * As with NMIs, machine check exceptions do not respect RFLAGS.IF and
966  * can occur at any time with a GS.base value that does not correspond
967  * to the privilege level in CS.
968  *
969  * Machine checks are not unblocked by iretq, but it is best to run
970  * the handler with interrupts disabled since the exception may have
971  * interrupted a critical section.
972  *
973  * The MC# handler runs on its own stack (tss_ist3).  The canonical
974  * GS.base value for the processor is stored just above the bottom of
975  * its MC# stack.  For exceptions taken from kernel mode, the current
976  * value in the processor's GS.base is saved at entry to C-preserved
977  * register %r12, the canonical value for GS.base is then loaded into
978  * the processor, and the saved value is restored at exit time.  For
979  * exceptions taken from user mode, the cheaper 'SWAPGS' instructions
980  * are used for swapping GS.base.
981  */
982
983 IDTVEC(mchk)
984         subq    $TF_RIP,%rsp
985         movl    $(T_MCHK),TF_TRAPNO(%rsp)
986         movq    $0,TF_ADDR(%rsp)
987         movq    $0,TF_ERR(%rsp)
988         movq    %rdi,TF_RDI(%rsp)
989         movq    %rsi,TF_RSI(%rsp)
990         movq    %rdx,TF_RDX(%rsp)
991         movq    %rcx,TF_RCX(%rsp)
992         movq    %r8,TF_R8(%rsp)
993         movq    %r9,TF_R9(%rsp)
994         movq    %rax,TF_RAX(%rsp)
995         movq    %rbx,TF_RBX(%rsp)
996         movq    %rbp,TF_RBP(%rsp)
997         movq    %r10,TF_R10(%rsp)
998         movq    %r11,TF_R11(%rsp)
999         movq    %r12,TF_R12(%rsp)
1000         movq    %r13,TF_R13(%rsp)
1001         movq    %r14,TF_R14(%rsp)
1002         movq    %r15,TF_R15(%rsp)
1003         SAVE_SEGS
1004         movl    $TF_HASSEGS,TF_FLAGS(%rsp)
1005         pushfq
1006         andq    $~(PSL_D | PSL_AC),(%rsp)
1007         popfq
1008         xorl    %ebx,%ebx
1009         testb   $SEL_RPL_MASK,TF_CS(%rsp)
1010         jnz     mchk_fromuserspace
1011         /*
1012          * We've interrupted the kernel.  Preserve GS.base in %r12,
1013          * %cr3 in %r13, and possibly lower half of MSR_IA32_SPEC_CTL in %r14d.
1014          */
1015         movl    $MSR_GSBASE,%ecx
1016         rdmsr
1017         movq    %rax,%r12
1018         shlq    $32,%rdx
1019         orq     %rdx,%r12
1020         /* Retrieve and load the canonical value for GS.base. */
1021         movq    TF_SIZE(%rsp),%rdx
1022         movl    %edx,%eax
1023         shrq    $32,%rdx
1024         wrmsr
1025         movq    %cr3,%r13
1026         movq    PCPU(KCR3),%rax
1027         cmpq    $~0,%rax
1028         je      1f
1029         movq    %rax,%cr3
1030 1:      testl   $CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
1031         je      mchk_calltrap
1032         movl    $MSR_IA32_SPEC_CTRL,%ecx
1033         rdmsr
1034         movl    %eax,%r14d
1035         call    handle_ibrs_entry
1036         jmp     mchk_calltrap
1037 mchk_fromuserspace:
1038         incl    %ebx
1039         swapgs
1040         movq    %cr3,%r13
1041         movq    PCPU(KCR3),%rax
1042         cmpq    $~0,%rax
1043         je      1f
1044         movq    %rax,%cr3
1045 1:      call    handle_ibrs_entry
1046 /* Note: this label is also used by ddb and gdb: */
1047 mchk_calltrap:
1048         FAKE_MCOUNT(TF_RIP(%rsp))
1049         movq    %rsp,%rdi
1050         call    mca_intr
1051         MEXITCOUNT
1052         testl   %ebx,%ebx       /* %ebx == 0 => return to userland */
1053         jnz     doreti_exit
1054         /*
1055          * Restore speculation control MSR, if preserved.
1056          */
1057         testl   $CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
1058         je      1f
1059         movl    %r14d,%eax
1060         xorl    %edx,%edx
1061         movl    $MSR_IA32_SPEC_CTRL,%ecx
1062         wrmsr
1063         /*
1064          * Put back the preserved MSR_GSBASE value.
1065          */
1066 1:      movl    $MSR_GSBASE,%ecx
1067         movq    %r12,%rdx
1068         movl    %edx,%eax
1069         shrq    $32,%rdx
1070         wrmsr
1071         movq    %r13,%cr3
1072         RESTORE_REGS
1073         addq    $TF_RIP,%rsp
1074         jmp     doreti_iret
1075
1076 ENTRY(fork_trampoline)
1077         movq    %r12,%rdi               /* function */
1078         movq    %rbx,%rsi               /* arg1 */
1079         movq    %rsp,%rdx               /* trapframe pointer */
1080         call    fork_exit
1081         MEXITCOUNT
1082         jmp     doreti                  /* Handle any ASTs */
1083
1084 /*
1085  * To efficiently implement classification of trap and interrupt handlers
1086  * for profiling, there must be only trap handlers between the labels btrap
1087  * and bintr, and only interrupt handlers between the labels bintr and
1088  * eintr.  This is implemented (partly) by including files that contain
1089  * some of the handlers.  Before including the files, set up a normal asm
1090  * environment so that the included files doen't need to know that they are
1091  * included.
1092  */
1093
1094 #ifdef COMPAT_FREEBSD32
1095         .data
1096         .p2align 4
1097         .text
1098         SUPERALIGN_TEXT
1099
1100 #include <amd64/ia32/ia32_exception.S>
1101 #endif
1102
1103         .data
1104         .p2align 4
1105         .text
1106         SUPERALIGN_TEXT
1107 MCOUNT_LABEL(bintr)
1108
1109 #include <amd64/amd64/apic_vector.S>
1110
1111 #ifdef DEV_ATPIC
1112         .data
1113         .p2align 4
1114         .text
1115         SUPERALIGN_TEXT
1116
1117 #include <amd64/amd64/atpic_vector.S>
1118 #endif
1119
1120         .text
1121 MCOUNT_LABEL(eintr)
1122
1123 /*
1124  * void doreti(struct trapframe)
1125  *
1126  * Handle return from interrupts, traps and syscalls.
1127  */
1128         .text
1129         SUPERALIGN_TEXT
1130         .type   doreti,@function
1131         .globl  doreti
1132 doreti:
1133         FAKE_MCOUNT($bintr)             /* init "from" bintr -> doreti */
1134         /*
1135          * Check if ASTs can be handled now.
1136          */
1137         testb   $SEL_RPL_MASK,TF_CS(%rsp) /* are we returning to user mode? */
1138         jz      doreti_exit             /* can't handle ASTs now if not */
1139
1140 doreti_ast:
1141         /*
1142          * Check for ASTs atomically with returning.  Disabling CPU
1143          * interrupts provides sufficient locking even in the SMP case,
1144          * since we will be informed of any new ASTs by an IPI.
1145          */
1146         cli
1147         movq    PCPU(CURTHREAD),%rax
1148         testl   $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
1149         je      doreti_exit
1150         sti
1151         movq    %rsp,%rdi       /* pass a pointer to the trapframe */
1152         call    ast
1153         jmp     doreti_ast
1154
1155         /*
1156          * doreti_exit: pop registers, iret.
1157          *
1158          *      The segment register pop is a special case, since it may
1159          *      fault if (for example) a sigreturn specifies bad segment
1160          *      registers.  The fault is handled in trap.c.
1161          */
1162 doreti_exit:
1163         MEXITCOUNT
1164         movq    PCPU(CURPCB),%r8
1165
1166         /*
1167          * Do not reload segment registers for kernel.
1168          * Since we do not reload segments registers with sane
1169          * values on kernel entry, descriptors referenced by
1170          * segments registers might be not valid.  This is fatal
1171          * for user mode, but is not a problem for the kernel.
1172          */
1173         testb   $SEL_RPL_MASK,TF_CS(%rsp)
1174         jz      ld_regs
1175         testl   $PCB_FULL_IRET,PCB_FLAGS(%r8)
1176         jz      ld_regs
1177         andl    $~PCB_FULL_IRET,PCB_FLAGS(%r8)
1178         testl   $TF_HASSEGS,TF_FLAGS(%rsp)
1179         je      set_segs
1180
1181 do_segs:
1182         /* Restore %fs and fsbase */
1183         movw    TF_FS(%rsp),%ax
1184         .globl  ld_fs
1185 ld_fs:
1186         movw    %ax,%fs
1187         cmpw    $KUF32SEL,%ax
1188         jne     1f
1189         movl    $MSR_FSBASE,%ecx
1190         movl    PCB_FSBASE(%r8),%eax
1191         movl    PCB_FSBASE+4(%r8),%edx
1192         .globl  ld_fsbase
1193 ld_fsbase:
1194         wrmsr
1195 1:
1196         /* Restore %gs and gsbase */
1197         movw    TF_GS(%rsp),%si
1198         pushfq
1199         cli
1200         movl    $MSR_GSBASE,%ecx
1201         /* Save current kernel %gs base into %r12d:%r13d */
1202         rdmsr
1203         movl    %eax,%r12d
1204         movl    %edx,%r13d
1205         .globl  ld_gs
1206 ld_gs:
1207         movw    %si,%gs
1208         /* Save user %gs base into %r14d:%r15d */
1209         rdmsr
1210         movl    %eax,%r14d
1211         movl    %edx,%r15d
1212         /* Restore kernel %gs base */
1213         movl    %r12d,%eax
1214         movl    %r13d,%edx
1215         wrmsr
1216         popfq
1217         /*
1218          * Restore user %gs base, either from PCB if used for TLS, or
1219          * from the previously saved msr read.
1220          */
1221         movl    $MSR_KGSBASE,%ecx
1222         cmpw    $KUG32SEL,%si
1223         jne     1f
1224         movl    PCB_GSBASE(%r8),%eax
1225         movl    PCB_GSBASE+4(%r8),%edx
1226         jmp     ld_gsbase
1227 1:
1228         movl    %r14d,%eax
1229         movl    %r15d,%edx
1230         .globl  ld_gsbase
1231 ld_gsbase:
1232         wrmsr   /* May trap if non-canonical, but only for TLS. */
1233         .globl  ld_es
1234 ld_es:
1235         movw    TF_ES(%rsp),%es
1236         .globl  ld_ds
1237 ld_ds:
1238         movw    TF_DS(%rsp),%ds
1239 ld_regs:
1240         RESTORE_REGS
1241         testb   $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
1242         jz      2f                      /* keep running with kernel GS.base */
1243         cli
1244         call    handle_ibrs_exit_rs
1245         callq   *mds_handler
1246         cmpq    $~0,PCPU(UCR3)
1247         je      1f
1248         pushq   %rdx
1249         movq    PCPU(PTI_RSP0),%rdx
1250         subq    $PTI_SIZE,%rdx
1251         movq    %rax,PTI_RAX(%rdx)
1252         popq    %rax
1253         movq    %rax,PTI_RDX(%rdx)
1254         movq    TF_RIP(%rsp),%rax
1255         movq    %rax,PTI_RIP(%rdx)
1256         movq    TF_CS(%rsp),%rax
1257         movq    %rax,PTI_CS(%rdx)
1258         movq    TF_RFLAGS(%rsp),%rax
1259         movq    %rax,PTI_RFLAGS(%rdx)
1260         movq    TF_RSP(%rsp),%rax
1261         movq    %rax,PTI_RSP(%rdx)
1262         movq    TF_SS(%rsp),%rax
1263         movq    %rax,PTI_SS(%rdx)
1264         movq    PCPU(UCR3),%rax
1265         swapgs
1266         movq    %rdx,%rsp
1267         movq    %rax,%cr3
1268         popq    %rdx
1269         popq    %rax
1270         addq    $8,%rsp
1271         jmp     doreti_iret
1272 1:      swapgs
1273 2:      addq    $TF_RIP,%rsp
1274         .globl  doreti_iret
1275 doreti_iret:
1276         iretq
1277
1278 set_segs:
1279         movw    $KUDSEL,%ax
1280         movw    %ax,TF_DS(%rsp)
1281         movw    %ax,TF_ES(%rsp)
1282         movw    $KUF32SEL,TF_FS(%rsp)
1283         movw    $KUG32SEL,TF_GS(%rsp)
1284         jmp     do_segs
1285
1286         /*
1287          * doreti_iret_fault.  Alternative return code for
1288          * the case where we get a fault in the doreti_exit code
1289          * above.  trap() (amd64/amd64/trap.c) catches this specific
1290          * case, sends the process a signal and continues in the
1291          * corresponding place in the code below.
1292          */
1293         ALIGN_TEXT
1294         .globl  doreti_iret_fault
1295 doreti_iret_fault:
1296         subq    $TF_RIP,%rsp            /* space including tf_err, tf_trapno */
1297         movq    %rax,TF_RAX(%rsp)
1298         movq    %rdx,TF_RDX(%rsp)
1299         movq    %rcx,TF_RCX(%rsp)
1300         call    handle_ibrs_entry
1301         testb   $SEL_RPL_MASK,TF_CS(%rsp)
1302         jz      1f
1303         sti
1304 1:
1305         SAVE_SEGS
1306         movl    $TF_HASSEGS,TF_FLAGS(%rsp)
1307         movq    %rdi,TF_RDI(%rsp)
1308         movq    %rsi,TF_RSI(%rsp)
1309         movq    %r8,TF_R8(%rsp)
1310         movq    %r9,TF_R9(%rsp)
1311         movq    %rbx,TF_RBX(%rsp)
1312         movq    %rbp,TF_RBP(%rsp)
1313         movq    %r10,TF_R10(%rsp)
1314         movq    %r11,TF_R11(%rsp)
1315         movq    %r12,TF_R12(%rsp)
1316         movq    %r13,TF_R13(%rsp)
1317         movq    %r14,TF_R14(%rsp)
1318         movq    %r15,TF_R15(%rsp)
1319         movl    $T_PROTFLT,TF_TRAPNO(%rsp)
1320         movq    $0,TF_ERR(%rsp) /* XXX should be the error code */
1321         movq    $0,TF_ADDR(%rsp)
1322         FAKE_MCOUNT(TF_RIP(%rsp))
1323         jmp     calltrap
1324
1325         ALIGN_TEXT
1326         .globl  ds_load_fault
1327 ds_load_fault:
1328         movl    $T_PROTFLT,TF_TRAPNO(%rsp)
1329         testb   $SEL_RPL_MASK,TF_CS(%rsp)
1330         jz      1f
1331         sti
1332 1:
1333         movq    %rsp,%rdi
1334         call    trap
1335         movw    $KUDSEL,TF_DS(%rsp)
1336         jmp     doreti
1337
1338         ALIGN_TEXT
1339         .globl  es_load_fault
1340 es_load_fault:
1341         movl    $T_PROTFLT,TF_TRAPNO(%rsp)
1342         testl   $PSL_I,TF_RFLAGS(%rsp)
1343         jz      1f
1344         sti
1345 1:
1346         movq    %rsp,%rdi
1347         call    trap
1348         movw    $KUDSEL,TF_ES(%rsp)
1349         jmp     doreti
1350
1351         ALIGN_TEXT
1352         .globl  fs_load_fault
1353 fs_load_fault:
1354         testl   $PSL_I,TF_RFLAGS(%rsp)
1355         jz      1f
1356         sti
1357 1:
1358         movl    $T_PROTFLT,TF_TRAPNO(%rsp)
1359         movq    %rsp,%rdi
1360         call    trap
1361         movw    $KUF32SEL,TF_FS(%rsp)
1362         jmp     doreti
1363
1364         ALIGN_TEXT
1365         .globl  gs_load_fault
1366 gs_load_fault:
1367         popfq
1368         movl    $T_PROTFLT,TF_TRAPNO(%rsp)
1369         testl   $PSL_I,TF_RFLAGS(%rsp)
1370         jz      1f
1371         sti
1372 1:
1373         movq    %rsp,%rdi
1374         call    trap
1375         movw    $KUG32SEL,TF_GS(%rsp)
1376         jmp     doreti
1377
1378         ALIGN_TEXT
1379         .globl  fsbase_load_fault
1380 fsbase_load_fault:
1381         movl    $T_PROTFLT,TF_TRAPNO(%rsp)
1382         testl   $PSL_I,TF_RFLAGS(%rsp)
1383         jz      1f
1384         sti
1385 1:
1386         movq    %rsp,%rdi
1387         call    trap
1388         movq    PCPU(CURTHREAD),%r8
1389         movq    TD_PCB(%r8),%r8
1390         movq    $0,PCB_FSBASE(%r8)
1391         jmp     doreti
1392
1393         ALIGN_TEXT
1394         .globl  gsbase_load_fault
1395 gsbase_load_fault:
1396         movl    $T_PROTFLT,TF_TRAPNO(%rsp)
1397         testl   $PSL_I,TF_RFLAGS(%rsp)
1398         jz      1f
1399         sti
1400 1:
1401         movq    %rsp,%rdi
1402         call    trap
1403         movq    PCPU(CURTHREAD),%r8
1404         movq    TD_PCB(%r8),%r8
1405         movq    $0,PCB_GSBASE(%r8)
1406         jmp     doreti
1407
1408 #ifdef HWPMC_HOOKS
1409         ENTRY(end_exceptions)
1410 #endif