Unconditionnally save the segment registers - because we could have a
kernel %gs and a userland %es/%ds -, and explain why T_NMI is a special case. Note that checking %gs directly is not a good idea: recent CPUs have the FSGSBASE instruction set, which allows userland to directly modify %gs without going through the kernel. If we ever enable this set, we will have to change this function, since we won't be able to test %gs against VM_MIN_KERNEL_ADDRESS anymore.
This commit is contained in:
parent
5915ff2ca3
commit
de23205eb7
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: amd64_trap.S,v 1.4 2016/08/07 09:04:55 maxv Exp $ */
|
/* $NetBSD: amd64_trap.S,v 1.5 2017/03/24 18:03:32 maxv Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
|
* Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#include <machine/asm.h>
|
#include <machine/asm.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: amd64_trap.S,v 1.4 2016/08/07 09:04:55 maxv Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: amd64_trap.S,v 1.5 2017/03/24 18:03:32 maxv Exp $");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -103,39 +103,54 @@ IDTVEC(trap01)
|
||||||
ZTRAP(T_TRCTRAP)
|
ZTRAP(T_TRCTRAP)
|
||||||
IDTVEC_END(trap01)
|
IDTVEC_END(trap01)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Non Maskable Interrupts are a special case: they can be triggered even
|
||||||
|
* with interrupts disabled, and once triggered they block further NMIs
|
||||||
|
* until an 'iret' instruction is executed.
|
||||||
|
*
|
||||||
|
* Therefore we don't enable interrupts, because the CPU could switch to
|
||||||
|
* another LWP, call 'iret' and unintentionally leave the NMI mode.
|
||||||
|
*
|
||||||
|
* We need to be careful about %gs too, because it is possible that we were
|
||||||
|
* running in kernel mode with a userland %gs.
|
||||||
|
*/
|
||||||
IDTVEC(trap02)
|
IDTVEC(trap02)
|
||||||
#if defined(XEN)
|
#if defined(XEN)
|
||||||
ZTRAP(T_NMI)
|
ZTRAP(T_NMI)
|
||||||
#else /* defined(XEN) */
|
#else
|
||||||
pushq $0
|
pushq $0
|
||||||
pushq $T_NMI
|
pushq $T_NMI
|
||||||
subq $TF_REGSIZE,%rsp
|
subq $TF_REGSIZE,%rsp
|
||||||
INTR_SAVE_GPRS
|
INTR_SAVE_GPRS
|
||||||
movl $MSR_GSBASE,%ecx
|
|
||||||
rdmsr
|
|
||||||
cmpl $VM_MIN_KERNEL_ADDRESS_HIGH32,%edx
|
|
||||||
jae 1f
|
|
||||||
swapgs
|
|
||||||
movw %gs,TF_GS(%rsp)
|
movw %gs,TF_GS(%rsp)
|
||||||
movw %fs,TF_FS(%rsp)
|
movw %fs,TF_FS(%rsp)
|
||||||
movw %es,TF_ES(%rsp)
|
movw %es,TF_ES(%rsp)
|
||||||
movw %ds,TF_DS(%rsp)
|
movw %ds,TF_DS(%rsp)
|
||||||
|
|
||||||
|
movl $MSR_GSBASE,%ecx
|
||||||
|
rdmsr
|
||||||
|
cmpl $VM_MIN_KERNEL_ADDRESS_HIGH32,%edx
|
||||||
|
jae noswapgs
|
||||||
|
|
||||||
|
swapgs
|
||||||
movq %rsp,%rdi
|
movq %rsp,%rdi
|
||||||
incq CPUVAR(NTRAP)
|
incq CPUVAR(NTRAP)
|
||||||
call _C_LABEL(trap)
|
call _C_LABEL(trap)
|
||||||
|
swapgs
|
||||||
|
jmp nmileave
|
||||||
|
|
||||||
|
noswapgs:
|
||||||
|
movq %rsp,%rdi
|
||||||
|
incq CPUVAR(NTRAP)
|
||||||
|
call _C_LABEL(trap)
|
||||||
|
|
||||||
|
nmileave:
|
||||||
movw TF_ES(%rsp),%es
|
movw TF_ES(%rsp),%es
|
||||||
movw TF_DS(%rsp),%ds
|
movw TF_DS(%rsp),%ds
|
||||||
swapgs
|
|
||||||
jmp 2f
|
|
||||||
1:
|
|
||||||
movq %rsp,%rdi
|
|
||||||
incq CPUVAR(NTRAP)
|
|
||||||
call _C_LABEL(trap)
|
|
||||||
2:
|
|
||||||
INTR_RESTORE_GPRS
|
INTR_RESTORE_GPRS
|
||||||
addq $TF_REGSIZE+16,%rsp
|
addq $TF_REGSIZE+16,%rsp
|
||||||
iretq
|
iretq
|
||||||
#endif /* defined(XEN) */
|
#endif
|
||||||
IDTVEC_END(trap02)
|
IDTVEC_END(trap02)
|
||||||
|
|
||||||
IDTVEC(trap03)
|
IDTVEC(trap03)
|
||||||
|
|
Loading…
Reference in New Issue