#include "opt_atpic.h"
#include "opt_hwpmc_hooks.h"
#include "assym.inc"
#include <machine/psl.h>
#include <machine/asmacros.h>
#include <machine/trap.h>
#include <machine/specialreg.h>
#include <machine/pmap.h>
#ifdef KDTRACE_HOOKS
.bss
.globl dtrace_invop_jump_addr
.align 8
.type dtrace_invop_jump_addr,@object
.size dtrace_invop_jump_addr,8
dtrace_invop_jump_addr:
.zero 8
.globl dtrace_invop_calltrap_addr
.align 8
.type dtrace_invop_calltrap_addr,@object
.size dtrace_invop_calltrap_addr,8
dtrace_invop_calltrap_addr:
.zero 8
#endif
.text
#ifdef HWPMC_HOOKS
ENTRY(start_exceptions)
#endif
.macro TRAP_NOEN l, trapno
PTI_ENTRY \l,\l\()_pti_k,\l\()_pti_u
\l\()_pti_k:
subq $TF_RIP,%rsp
movl $\trapno,TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
movq $0,TF_ERR(%rsp)
jmp alltraps_noen_k
\l\()_pti_u:
subq $TF_RIP,%rsp
movl $\trapno,TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
movq $0,TF_ERR(%rsp)
jmp alltraps_noen_u
.globl X\l
.type X\l,@function
X\l:
subq $TF_RIP,%rsp
movl $\trapno,TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
movq $0,TF_ERR(%rsp)
testb $SEL_RPL_MASK,TF_CS(%rsp)
jz alltraps_noen_k
swapgs
lfence
jmp alltraps_noen_u
.endm
TRAP_NOEN bpt, T_BPTFLT
#ifdef KDTRACE_HOOKS
TRAP_NOEN dtrace_ret, T_DTRACE_RET
#endif
.macro TRAP l, trapno
PTI_ENTRY \l,\l\()_pti_k,\l\()_pti_u
\l\()_pti_k:
subq $TF_RIP,%rsp
movl $\trapno,TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
movq $0,TF_ERR(%rsp)
jmp alltraps_k
\l\()_pti_u:
subq $TF_RIP,%rsp
movl $\trapno,TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
movq $0,TF_ERR(%rsp)
jmp alltraps_u
.globl X\l
.type X\l,@function
X\l:
subq $TF_RIP,%rsp
movl $\trapno,TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
movq $0,TF_ERR(%rsp)
testb $SEL_RPL_MASK,TF_CS(%rsp)
jz alltraps_k
swapgs
lfence
jmp alltraps_u
.endm
TRAP div, T_DIVIDE
TRAP ofl, T_OFLOW
TRAP bnd, T_BOUND
TRAP ill, T_PRIVINFLT
TRAP dna, T_DNA
TRAP fpusegm, T_FPOPFLT
TRAP rsvd, T_RESERVED
TRAP fpu, T_ARITHTRAP
TRAP xmm, T_XMMFLT
.macro TRAP_ERR l, trapno
PTI_ENTRY \l,\l\()_pti_k,\l\()_pti_u,has_err=1
\l\()_pti_k:
subq $TF_ERR,%rsp
movl $\trapno,TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
jmp alltraps_k
\l\()_pti_u:
subq $TF_ERR,%rsp
movl $\trapno,TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
jmp alltraps_u
.globl X\l
.type X\l,@function
X\l:
subq $TF_ERR,%rsp
movl $\trapno,TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
testb $SEL_RPL_MASK,TF_CS(%rsp)
jz alltraps_k
swapgs
lfence
jmp alltraps_u
.endm
TRAP_ERR tss, T_TSSFLT
TRAP_ERR align, T_ALIGNFLT
SUPERALIGN_TEXT
.globl alltraps_u
.type alltraps_u,@function
alltraps_u:
movq %rdi,TF_RDI(%rsp)
movq %rdx,TF_RDX(%rsp)
movq %rax,TF_RAX(%rsp)
movq %rcx,TF_RCX(%rsp)
movq PCPU(CURPCB),%rdi
andl $~PCB_FULL_IRET,PCB_FLAGS(%rdi)
call handle_ibrs_entry
jmp alltraps_save_segs
SUPERALIGN_TEXT
.globl alltraps_k
.type alltraps_k,@function
alltraps_k:
lfence
movq %rdi,TF_RDI(%rsp)
movq %rdx,TF_RDX(%rsp)
movq %rax,TF_RAX(%rsp)
movq %rcx,TF_RCX(%rsp)
alltraps_save_segs:
SAVE_SEGS
testl $PSL_I,TF_RFLAGS(%rsp)
jz alltraps_pushregs_no_rax
sti
alltraps_pushregs_no_rax:
movq %rsi,TF_RSI(%rsp)
movq %r8,TF_R8(%rsp)
movq %r9,TF_R9(%rsp)
movq %rbx,TF_RBX(%rsp)
movq %rbp,TF_RBP(%rsp)
movq %r10,TF_R10(%rsp)
movq %r11,TF_R11(%rsp)
movq %r12,TF_R12(%rsp)
movq %r13,TF_R13(%rsp)
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
movl $TF_HASSEGS,TF_FLAGS(%rsp)
pushfq
andq $~(PSL_D | PSL_AC),(%rsp)
popfq
#ifdef KDTRACE_HOOKS
testb $SEL_RPL_MASK,TF_CS(%rsp)
jnz calltrap
cmpl $T_BPTFLT,TF_TRAPNO(%rsp)
jne calltrap
cmpq $0,dtrace_invop_jump_addr
je calltrap
movq $calltrap,dtrace_invop_calltrap_addr(%rip)
jmpq *dtrace_invop_jump_addr
#endif
.globl calltrap
.type calltrap,@function
calltrap:
KMSAN_ENTER
movq %rsp, %rdi
call trap_check
KMSAN_LEAVE
jmp doreti
SUPERALIGN_TEXT
.globl alltraps_noen_u
.type alltraps_noen_u,@function
alltraps_noen_u:
movq %rdi,TF_RDI(%rsp)
movq PCPU(CURPCB),%rdi
andl $~PCB_FULL_IRET,PCB_FLAGS(%rdi)
jmp alltraps_noen_save_segs
SUPERALIGN_TEXT
.globl alltraps_noen_k
.type alltraps_noen_k,@function
alltraps_noen_k:
lfence
movq %rdi,TF_RDI(%rsp)
alltraps_noen_save_segs:
SAVE_SEGS
movq %rdx,TF_RDX(%rsp)
movq %rax,TF_RAX(%rsp)
movq %rcx,TF_RCX(%rsp)
testb $SEL_RPL_MASK,TF_CS(%rsp)
jz alltraps_pushregs_no_rax
call handle_ibrs_entry
jmp alltraps_pushregs_no_rax
IDTVEC(dblfault)
subq $TF_ERR,%rsp
movl $T_DOUBLEFLT,TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
movq $0,TF_ERR(%rsp)
movq %rdi,TF_RDI(%rsp)
movq %rsi,TF_RSI(%rsp)
movq %rdx,TF_RDX(%rsp)
movq %rcx,TF_RCX(%rsp)
movq %r8,TF_R8(%rsp)
movq %r9,TF_R9(%rsp)
movq %rax,TF_RAX(%rsp)
movq %rbx,TF_RBX(%rsp)
movq %rbp,TF_RBP(%rsp)
movq %r10,TF_R10(%rsp)
movq %r11,TF_R11(%rsp)
movq %r12,TF_R12(%rsp)
movq %r13,TF_R13(%rsp)
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
SAVE_SEGS
movl $TF_HASSEGS,TF_FLAGS(%rsp)
pushfq
andq $~(PSL_D | PSL_AC),(%rsp)
popfq
movq TF_SIZE(%rsp),%rdx
movl %edx,%eax
shrq $32,%rdx
movl $MSR_GSBASE,%ecx
wrmsr
movq %cr3,%rax
movq %rax,PCPU(SAVED_UCR3)
movq PCPU(KCR3),%rax
cmpq $~0,%rax
je 2f
movq %rax,%cr3
2: KMSAN_ENTER
movq %rsp,%rdi
call dblfault_handler
KMSAN_LEAVE
3: hlt
jmp 3b
ALIGN_TEXT
IDTVEC(page_pti)
testb $SEL_RPL_MASK,PTI_CS-PTI_ERR(%rsp)
jz page_k
swapgs
lfence
pushq %rax
movq %cr3,%rax
movq %rax,PCPU(SAVED_UCR3)
cmpq $~0,PCPU(UCR3)
jne 1f
popq %rax
jmp page_u
1: pushq %rdx
PTI_UUENTRY has_err=1
jmp page_u
ALIGN_TEXT
IDTVEC(page)
testb $SEL_RPL_MASK,TF_CS-TF_ERR(%rsp)
jnz page_u_swapgs
page_k:
lfence
subq $TF_ERR,%rsp
movq %rdi,TF_RDI(%rsp)
movq %rax,TF_RAX(%rsp)
movq %rdx,TF_RDX(%rsp)
movq %rcx,TF_RCX(%rsp)
jmp page_cr2
ALIGN_TEXT
page_u_swapgs:
swapgs
lfence
page_u:
subq $TF_ERR,%rsp
movq %rdi,TF_RDI(%rsp)
movq %rax,TF_RAX(%rsp)
movq %rdx,TF_RDX(%rsp)
movq %rcx,TF_RCX(%rsp)
movq PCPU(CURPCB),%rdi
andl $~PCB_FULL_IRET,PCB_FLAGS(%rdi)
movq PCPU(SAVED_UCR3),%rax
movq %rax,PCB_SAVED_UCR3(%rdi)
call handle_ibrs_entry
page_cr2:
movq %cr2,%rdi
movq %rdi,TF_ADDR(%rsp)
SAVE_SEGS
movl $T_PAGEFLT,TF_TRAPNO(%rsp)
testl $PSL_I,TF_RFLAGS(%rsp)
jz alltraps_pushregs_no_rax
sti
jmp alltraps_pushregs_no_rax
.macro PROTF_ENTRY name,trapno
\name\()_pti_doreti:
swapgs
lfence
cmpq $~0,PCPU(UCR3)
je 1f
pushq %rax
pushq %rdx
movq PCPU(KCR3),%rax
movq %rax,%cr3
movq PCPU(RSP0),%rax
subq $2*PTI_SIZE-3*8,%rax
MOVE_STACKS (PTI_SIZE / 8)
addq $PTI_SIZE,%rax
movq PTI_RSP(%rsp),%rsp
MOVE_STACKS (PTI_SIZE / 8 - 3)
subq $PTI_SIZE,%rax
movq %rax,%rsp
popq %rdx
popq %rax
1: swapgs
jmp X\name
IDTVEC(\name\()_pti)
cmpq $doreti_iret,PTI_RIP-2*8(%rsp)
je \name\()_pti_doreti
testb $SEL_RPL_MASK,PTI_CS-2*8(%rsp)
jz X\name
PTI_UENTRY has_err=1
swapgs
IDTVEC(\name)
subq $TF_ERR,%rsp
movl $\trapno,TF_TRAPNO(%rsp)
jmp prot_addrf
.endm
PROTF_ENTRY missing, T_SEGNPFLT
PROTF_ENTRY stk, T_STKFLT
PROTF_ENTRY prot, T_PROTFLT
prot_addrf:
movq $0,TF_ADDR(%rsp)
movq %rdi,TF_RDI(%rsp)
movq %rax,TF_RAX(%rsp)
movq %rdx,TF_RDX(%rsp)
movq %rcx,TF_RCX(%rsp)
movw %fs,TF_FS(%rsp)
movw %gs,TF_GS(%rsp)
leaq doreti_iret(%rip),%rdi
cmpq %rdi,TF_RIP(%rsp)
je 5f
testb $SEL_RPL_MASK,TF_CS(%rsp)
jz 6f
testb $CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip)
jz 2f
rdfsbase %rax
rdgsbase %rdx
2: swapgs
lfence
movq PCPU(CURPCB),%rdi
testb $CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip)
jz 4f
movq %rax,PCB_FSBASE(%rdi)
movq %rdx,PCB_GSBASE(%rdi)
orl $PCB_FULL_IRET,PCB_FLAGS(%rdi)
4: call handle_ibrs_entry
movw %es,TF_ES(%rsp)
movw %ds,TF_DS(%rsp)
testl $PSL_I,TF_RFLAGS(%rsp)
jz alltraps_pushregs_no_rax
sti
jmp alltraps_pushregs_no_rax
5: swapgs
6: lfence
movq PCPU(CURPCB),%rdi
jmp 4b
SUPERALIGN_TEXT
IDTVEC(fast_syscall_pti)
swapgs
cmpq $~0,PCPU(UCR3)
je fast_syscall_common
movq %rax,PCPU(SCRATCH_RAX)
movq PCPU(KCR3),%rax
movq %rax,%cr3
movq PCPU(SCRATCH_RAX),%rax
jmp fast_syscall_common
SUPERALIGN_TEXT
IDTVEC(fast_syscall)
swapgs
fast_syscall_common:
movq %rsp,PCPU(SCRATCH_RSP)
movq PCPU(RSP0),%rsp
subq $TF_SIZE,%rsp
movq %r11,TF_RFLAGS(%rsp)
movq %rcx,TF_RIP(%rsp)
movq PCPU(SCRATCH_RSP),%r11
movq %r11,TF_RSP(%rsp)
movq %rax,TF_RAX(%rsp)
movq %rdx,TF_RDX(%rsp)
movq %r10,TF_RCX(%rsp)
SAVE_SEGS
call handle_ibrs_entry
movq PCPU(CURPCB),%r11
andl $~PCB_FULL_IRET,PCB_FLAGS(%r11)
sti
movq $KUDSEL,TF_SS(%rsp)
movq $KUCSEL,TF_CS(%rsp)
movq $2,TF_ERR(%rsp)
movq %rdi,TF_RDI(%rsp)
movq %rsi,TF_RSI(%rsp)
movq %r8,TF_R8(%rsp)
movq %r9,TF_R9(%rsp)
movq %rbx,TF_RBX(%rsp)
movq %rbp,TF_RBP(%rsp)
movq %r12,TF_R12(%rsp)
movq %r13,TF_R13(%rsp)
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
movl $TF_HASSEGS,TF_FLAGS(%rsp)
movq PCPU(CURTHREAD),%rdi
movq %rsp,TD_FRAME(%rdi)
movl TF_RFLAGS(%rsp),%esi
andl $PSL_T,%esi
call amd64_syscall
1: movq PCPU(CURPCB),%rax
cli
testl $PCB_FULL_IRET,PCB_FLAGS(%rax)
jnz 4f
movq PCPU(CURTHREAD),%rax
cmpl $0,TD_AST(%rax)
jne 3f
call handle_ibrs_exit
callq *mds_handler
movq TF_RDI(%rsp),%rdi
movq TF_RSI(%rsp),%rsi
movq TF_RDX(%rsp),%rdx
movq TF_RAX(%rsp),%rax
movq TF_RFLAGS(%rsp),%r11
movq TF_RIP(%rsp),%rcx
movq TF_RSP(%rsp),%rsp
xorl %r8d,%r8d
xorl %r10d,%r10d
cmpq $~0,PCPU(UCR3)
je 2f
movq PCPU(UCR3),%r9
andq PCPU(UCR3_LOAD_MASK),%r9
movq %r9,%cr3
2: xorl %r9d,%r9d
movq $PMAP_UCR3_NOMASK,PCPU(UCR3_LOAD_MASK)
swapgs
sysretq
3:
sti
movq %rsp,%rdi
call ast
jmp 1b
4:
jmp doreti
IDTVEC(fast_syscall32)
sysret
IDTVEC(dbg)
subq $TF_RIP,%rsp
movl $(T_TRCTRAP),TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
movq $0,TF_ERR(%rsp)
movq %rdi,TF_RDI(%rsp)
movq %rsi,TF_RSI(%rsp)
movq %rdx,TF_RDX(%rsp)
movq %rcx,TF_RCX(%rsp)
movq %r8,TF_R8(%rsp)
movq %r9,TF_R9(%rsp)
movq %rax,TF_RAX(%rsp)
movq %rbx,TF_RBX(%rsp)
movq %rbp,TF_RBP(%rsp)
movq %r10,TF_R10(%rsp)
movq %r11,TF_R11(%rsp)
movq %r12,TF_R12(%rsp)
movq %r13,TF_R13(%rsp)
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
SAVE_SEGS
movl $TF_HASSEGS,TF_FLAGS(%rsp)
pushfq
andq $~(PSL_D | PSL_AC),(%rsp)
popfq
testb $SEL_RPL_MASK,TF_CS(%rsp)
jnz dbg_fromuserspace
lfence
movq %cr2,%r15
movl $MSR_GSBASE,%ecx
rdmsr
movq %rax,%r12
shlq $32,%rdx
orq %rdx,%r12
movq TF_SIZE(%rsp),%rdx
movl %edx,%eax
shrq $32,%rdx
wrmsr
movq %cr3,%r13
movq PCPU(KCR3),%rax
cmpq $~0,%rax
je 1f
movq %rax,%cr3
1: testl $CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
je 2f
movl $MSR_IA32_SPEC_CTRL,%ecx
rdmsr
movl %eax,%r14d
call handle_ibrs_entry
2: movq %rsp,%rdi
call trap
testl $CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
je 3f
movl %r14d,%eax
xorl %edx,%edx
movl $MSR_IA32_SPEC_CTRL,%ecx
wrmsr
3: movl $MSR_GSBASE,%ecx
movq %r12,%rdx
movl %edx,%eax
shrq $32,%rdx
wrmsr
movq %r13,%cr3
movq %r15,%cr2
RESTORE_REGS
addq $TF_RIP,%rsp
jmp doreti_iret
dbg_fromuserspace:
swapgs
lfence
movq PCPU(KCR3),%rax
cmpq $~0,%rax
je 1f
movq %rax,%cr3
1: movq PCPU(RSP0),%rax
movl $TF_SIZE,%ecx
subq %rcx,%rax
movq %rax,%rdi
movq %rsp,%rsi
rep;movsb
movq %rax,%rsp
call handle_ibrs_entry
movq PCPU(CURPCB),%rdi
orl $PCB_FULL_IRET,PCB_FLAGS(%rdi)
testb $CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip)
jz 3f
rdfsbase %rax
movq %rax,PCB_FSBASE(%rdi)
movl $MSR_KGSBASE,%ecx
rdmsr
shlq $32,%rdx
orq %rdx,%rax
movq %rax,PCB_GSBASE(%rdi)
3: jmp calltrap
IDTVEC(nmi)
subq $TF_RIP,%rsp
movl $(T_NMI),TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
movq $0,TF_ERR(%rsp)
movq %rdi,TF_RDI(%rsp)
movq %rsi,TF_RSI(%rsp)
movq %rdx,TF_RDX(%rsp)
movq %rcx,TF_RCX(%rsp)
movq %r8,TF_R8(%rsp)
movq %r9,TF_R9(%rsp)
movq %rax,TF_RAX(%rsp)
movq %rbx,TF_RBX(%rsp)
movq %rbp,TF_RBP(%rsp)
movq %r10,TF_R10(%rsp)
movq %r11,TF_R11(%rsp)
movq %r12,TF_R12(%rsp)
movq %r13,TF_R13(%rsp)
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
SAVE_SEGS
movl $TF_HASSEGS,TF_FLAGS(%rsp)
pushfq
andq $~(PSL_D | PSL_AC),(%rsp)
popfq
xorl %ebx,%ebx
testb $SEL_RPL_MASK,TF_CS(%rsp)
jnz nmi_fromuserspace
lfence
movq %cr2,%r15
movl $MSR_GSBASE,%ecx
rdmsr
movq %rax,%r12
shlq $32,%rdx
orq %rdx,%r12
movq TF_SIZE(%rsp),%rdx
movl %edx,%eax
shrq $32,%rdx
wrmsr
movq %cr3,%r13
movq PCPU(KCR3),%rax
cmpq $~0,%rax
je 1f
movq %rax,%cr3
1: testl $CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
je nmi_calltrap
movl $MSR_IA32_SPEC_CTRL,%ecx
rdmsr
movl %eax,%r14d
call handle_ibrs_entry
jmp nmi_calltrap
nmi_fromuserspace:
incl %ebx
swapgs
lfence
movq %cr3,%r13
movq PCPU(KCR3),%rax
cmpq $~0,%rax
je 1f
movq %rax,%cr3
1: call handle_ibrs_entry
movq PCPU(CURPCB),%rdi
testq %rdi,%rdi
jz 3f
orl $PCB_FULL_IRET,PCB_FLAGS(%rdi)
testb $CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip)
jz 3f
rdfsbase %rax
movq %rax,PCB_FSBASE(%rdi)
movl $MSR_KGSBASE,%ecx
rdmsr
shlq $32,%rdx
orq %rdx,%rax
movq %rax,PCB_GSBASE(%rdi)
3:
nmi_calltrap:
KMSAN_ENTER
movq %rsp,%rdi
call trap
KMSAN_LEAVE
#ifdef HWPMC_HOOKS
testl %ebx,%ebx
jz nocallchain
movq PCPU(CURTHREAD),%rax
orq %rax,%rax
jz nocallchain
movq %rsp,%rsi
movq $TF_SIZE,%rcx
movq PCPU(RSP0),%rdx
subq %rcx,%rdx
movq %rdx,%rdi
shrq $3,%rcx
pushfq
andq $~(PSL_D | PSL_AC),(%rsp)
popfq
rep
movsq
movq %rdx,%rsp
testl $TDP_CALLCHAIN,TD_PFLAGS(%rax)
jz nocallchain
movl %ss,%eax
pushq %rax
pushq %rdx
pushfq
movl %cs,%eax
pushq %rax
pushq $outofnmi
iretq
outofnmi:
movq pmc_hook,%rax
orq %rax,%rax
jz nocallchain
movq PCPU(CURTHREAD),%rdi
movq $PMC_FN_USER_CALLCHAIN,%rsi
movq %rsp,%rdx
sti
call *%rax
cli
nocallchain:
#endif
testl %ebx,%ebx
jnz doreti_exit
testl $CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
je 1f
movl %r14d,%eax
xorl %edx,%edx
movl $MSR_IA32_SPEC_CTRL,%ecx
wrmsr
1: movl $MSR_GSBASE,%ecx
movq %r12,%rdx
movl %edx,%eax
shrq $32,%rdx
wrmsr
cmpb $0, nmi_flush_l1d_sw(%rip)
je 2f
call flush_l1d_sw
2: movq %r13,%cr3
movq %r15,%cr2
RESTORE_REGS
addq $TF_RIP,%rsp
jmp doreti_iret
IDTVEC(mchk)
subq $TF_RIP,%rsp
movl $(T_MCHK),TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
movq $0,TF_ERR(%rsp)
movq %rdi,TF_RDI(%rsp)
movq %rsi,TF_RSI(%rsp)
movq %rdx,TF_RDX(%rsp)
movq %rcx,TF_RCX(%rsp)
movq %r8,TF_R8(%rsp)
movq %r9,TF_R9(%rsp)
movq %rax,TF_RAX(%rsp)
movq %rbx,TF_RBX(%rsp)
movq %rbp,TF_RBP(%rsp)
movq %r10,TF_R10(%rsp)
movq %r11,TF_R11(%rsp)
movq %r12,TF_R12(%rsp)
movq %r13,TF_R13(%rsp)
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
SAVE_SEGS
movl $TF_HASSEGS,TF_FLAGS(%rsp)
pushfq
andq $~(PSL_D | PSL_AC),(%rsp)
popfq
xorl %ebx,%ebx
testb $SEL_RPL_MASK,TF_CS(%rsp)
jnz mchk_fromuserspace
movq %cr2,%r15
movl $MSR_GSBASE,%ecx
rdmsr
movq %rax,%r12
shlq $32,%rdx
orq %rdx,%r12
movq TF_SIZE(%rsp),%rdx
movl %edx,%eax
shrq $32,%rdx
wrmsr
movq %cr3,%r13
movq PCPU(KCR3),%rax
cmpq $~0,%rax
je 1f
movq %rax,%cr3
1: testl $CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
je mchk_calltrap
movl $MSR_IA32_SPEC_CTRL,%ecx
rdmsr
movl %eax,%r14d
call handle_ibrs_entry
jmp mchk_calltrap
mchk_fromuserspace:
incl %ebx
swapgs
movq %cr3,%r13
movq PCPU(KCR3),%rax
cmpq $~0,%rax
je 1f
movq %rax,%cr3
1: call handle_ibrs_entry
mchk_calltrap:
KMSAN_ENTER
movq %rsp,%rdi
call mca_intr
KMSAN_LEAVE
testl %ebx,%ebx
jnz doreti_exit
testl $CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip)
je 1f
movl %r14d,%eax
xorl %edx,%edx
movl $MSR_IA32_SPEC_CTRL,%ecx
wrmsr
1: movl $MSR_GSBASE,%ecx
movq %r12,%rdx
movl %edx,%eax
shrq $32,%rdx
wrmsr
movq %r13,%cr3
movq %r15,%cr2
RESTORE_REGS
addq $TF_RIP,%rsp
jmp doreti_iret
ENTRY(fork_trampoline)
movq %r12,%rdi
movq %rbx,%rsi
movq %rsp,%rdx
call fork_exit
jmp doreti
#ifdef COMPAT_FREEBSD32
.data
.p2align 4
.text
SUPERALIGN_TEXT
#include <amd64/ia32/ia32_exception.S>
#endif
.data
.p2align 4
.text
SUPERALIGN_TEXT
#include <amd64/amd64/apic_vector.S>
#ifdef DEV_ATPIC
.data
.p2align 4
.text
SUPERALIGN_TEXT
#include <amd64/amd64/atpic_vector.S>
#endif
.text
SUPERALIGN_TEXT
.type doreti,@function
.globl doreti
doreti:
testb $SEL_RPL_MASK,TF_CS(%rsp)
jz doreti_exit
doreti_ast:
cli
movq PCPU(CURTHREAD),%rax
cmpl $0,TD_AST(%rax)
je doreti_exit
sti
movq %rsp,%rdi
call ast
jmp doreti_ast
doreti_exit:
movq PCPU(CURPCB),%r8
testb $SEL_RPL_MASK,TF_CS(%rsp)
jz ld_regs
testl $PCB_FULL_IRET,PCB_FLAGS(%r8)
jz ld_regs
andl $~PCB_FULL_IRET,PCB_FLAGS(%r8)
testl $TF_HASSEGS,TF_FLAGS(%rsp)
je set_segs
do_segs:
movw TF_FS(%rsp),%ax
.globl ld_fs
ld_fs:
movw %ax,%fs
movl $MSR_FSBASE,%ecx
movl PCB_FSBASE(%r8),%eax
movl PCB_FSBASE+4(%r8),%edx
.globl ld_fsbase
ld_fsbase:
wrmsr
movw TF_GS(%rsp),%si
pushfq
cli
movl $MSR_GSBASE,%ecx
rdmsr
movl %eax,%r12d
movl %edx,%r13d
.globl ld_gs
ld_gs:
movw %si,%gs
movl %r12d,%eax
movl %r13d,%edx
wrmsr
popfq
movl $MSR_KGSBASE,%ecx
movl PCB_GSBASE(%r8),%eax
movl PCB_GSBASE+4(%r8),%edx
.globl ld_gsbase
ld_gsbase:
wrmsr
.globl ld_es
ld_es:
movw TF_ES(%rsp),%es
.globl ld_ds
ld_ds:
movw TF_DS(%rsp),%ds
ld_regs:
RESTORE_REGS
testb $SEL_RPL_MASK,TF_CS(%rsp)
jz 2f
cli
call handle_ibrs_exit_rs
callq *mds_handler
cmpq $~0,PCPU(UCR3)
je 1f
pushq %rdx
movq PCPU(PTI_RSP0),%rdx
subq $PTI_SIZE,%rdx
movq %rax,PTI_RAX(%rdx)
popq %rax
movq %rax,PTI_RDX(%rdx)
movq TF_RIP(%rsp),%rax
movq %rax,PTI_RIP(%rdx)
movq TF_CS(%rsp),%rax
movq %rax,PTI_CS(%rdx)
movq TF_RFLAGS(%rsp),%rax
movq %rax,PTI_RFLAGS(%rdx)
movq TF_RSP(%rsp),%rax
movq %rax,PTI_RSP(%rdx)
movq TF_SS(%rsp),%rax
movq %rax,PTI_SS(%rdx)
movq PCPU(UCR3),%rax
andq PCPU(UCR3_LOAD_MASK),%rax
movq $PMAP_UCR3_NOMASK,PCPU(UCR3_LOAD_MASK)
swapgs
movq %rdx,%rsp
movq %rax,%cr3
popq %rdx
popq %rax
addq $8,%rsp
jmp doreti_iret
1: swapgs
2: addq $TF_RIP,%rsp
.globl doreti_iret
doreti_iret:
iretq
set_segs:
movw $KUDSEL,%ax
movw %ax,TF_DS(%rsp)
movw %ax,TF_ES(%rsp)
movw $KUF32SEL,TF_FS(%rsp)
movw $KUG32SEL,TF_GS(%rsp)
jmp do_segs
ALIGN_TEXT
.globl doreti_iret_fault
doreti_iret_fault:
subq $TF_RIP,%rsp
movq %rax,TF_RAX(%rsp)
movq %rdx,TF_RDX(%rsp)
movq %rcx,TF_RCX(%rsp)
call handle_ibrs_entry
testb $SEL_RPL_MASK,TF_CS(%rsp)
jz 1f
sti
1:
SAVE_SEGS
movl $TF_HASSEGS,TF_FLAGS(%rsp)
movq %rdi,TF_RDI(%rsp)
movq %rsi,TF_RSI(%rsp)
movq %r8,TF_R8(%rsp)
movq %r9,TF_R9(%rsp)
movq %rbx,TF_RBX(%rsp)
movq %rbp,TF_RBP(%rsp)
movq %r10,TF_R10(%rsp)
movq %r11,TF_R11(%rsp)
movq %r12,TF_R12(%rsp)
movq %r13,TF_R13(%rsp)
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
movl $T_PROTFLT,TF_TRAPNO(%rsp)
movq $0,TF_ERR(%rsp)
movq $0,TF_ADDR(%rsp)
jmp calltrap
ALIGN_TEXT
.globl ds_load_fault
ds_load_fault:
movl $T_PROTFLT,TF_TRAPNO(%rsp)
testb $SEL_RPL_MASK,TF_CS(%rsp)
jz 1f
sti
1:
movq %rsp,%rdi
call trap
movw $KUDSEL,TF_DS(%rsp)
jmp doreti
ALIGN_TEXT
.globl es_load_fault
es_load_fault:
movl $T_PROTFLT,TF_TRAPNO(%rsp)
testl $PSL_I,TF_RFLAGS(%rsp)
jz 1f
sti
1:
movq %rsp,%rdi
call trap
movw $KUDSEL,TF_ES(%rsp)
jmp doreti
ALIGN_TEXT
.globl fs_load_fault
fs_load_fault:
testl $PSL_I,TF_RFLAGS(%rsp)
jz 1f
sti
1:
movl $T_PROTFLT,TF_TRAPNO(%rsp)
movq %rsp,%rdi
call trap
movw $KUF32SEL,TF_FS(%rsp)
jmp doreti
ALIGN_TEXT
.globl gs_load_fault
gs_load_fault:
popfq
movl $T_PROTFLT,TF_TRAPNO(%rsp)
testl $PSL_I,TF_RFLAGS(%rsp)
jz 1f
sti
1:
movq %rsp,%rdi
call trap
movw $KUG32SEL,TF_GS(%rsp)
jmp doreti
ALIGN_TEXT
.globl fsbase_load_fault
fsbase_load_fault:
movl $T_PROTFLT,TF_TRAPNO(%rsp)
testl $PSL_I,TF_RFLAGS(%rsp)
jz 1f
sti
1:
movq %rsp,%rdi
call trap
movq PCPU(CURTHREAD),%r8
movq TD_PCB(%r8),%r8
movq $0,PCB_FSBASE(%r8)
jmp doreti
ALIGN_TEXT
.globl gsbase_load_fault
gsbase_load_fault:
movl $T_PROTFLT,TF_TRAPNO(%rsp)
testl $PSL_I,TF_RFLAGS(%rsp)
jz 1f
sti
1:
movq %rsp,%rdi
call trap
movq PCPU(CURTHREAD),%r8
movq TD_PCB(%r8),%r8
movq $0,PCB_GSBASE(%r8)
jmp doreti
#ifdef HWPMC_HOOKS
ENTRY(end_exceptions)
#endif