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