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