amd64: preserve %cr2 in NMI/MCE/DBG handlers.

These handlers could interrupt code which has interrupts disabled,
and if a spurious page fault occurs during exception handler run,
we get clobbered %cr2 in higher level stack.

This is mostly a speculation, but it is based on hints from good sources.

MFC after:	1 week
Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D27772
This commit is contained in:
Konstantin Belousov 2020-12-25 23:58:43 +02:00
parent 9dd48b87e6
commit d39f7430a6
2 changed files with 17 additions and 7 deletions

View File

@ -667,9 +667,10 @@ IDTVEC(dbg)
jnz dbg_fromuserspace
lfence
/*
* We've interrupted the kernel. Preserve GS.base in %r12,
* %cr3 in %r13, and possibly lower half of MSR_IA32_SPEC_CTL in %r14d.
* We've interrupted the kernel. See comment in NMI handler about
* registers use.
*/
movq %cr2,%r15
movl $MSR_GSBASE,%ecx
rdmsr
movq %rax,%r12
@ -710,6 +711,7 @@ IDTVEC(dbg)
shrq $32,%rdx
wrmsr
movq %r13,%cr3
movq %r15,%cr2
RESTORE_REGS
addq $TF_RIP,%rsp
jmp doreti_iret
@ -804,10 +806,14 @@ IDTVEC(nmi)
testb $SEL_RPL_MASK,TF_CS(%rsp)
jnz nmi_fromuserspace
/*
* We've interrupted the kernel. Preserve GS.base in %r12,
* %cr3 in %r13, and possibly lower half of MSR_IA32_SPEC_CTL in %r14d.
* We've interrupted the kernel. Preserve in callee-saved regs:
* GS.base in %r12,
* %cr3 in %r13,
* possibly lower half of MSR_IA32_SPEC_CTL in %r14d,
* %cr2 in %r15.
*/
lfence
movq %cr2,%r15
movl $MSR_GSBASE,%ecx
rdmsr
movq %rax,%r12
@ -957,6 +963,7 @@ nocallchain:
je 2f
call flush_l1d_sw /* bhyve L1TF assist */
2: movq %r13,%cr3
movq %r15,%cr2
RESTORE_REGS
addq $TF_RIP,%rsp
jmp doreti_iret
@ -1011,9 +1018,10 @@ IDTVEC(mchk)
testb $SEL_RPL_MASK,TF_CS(%rsp)
jnz mchk_fromuserspace
/*
* We've interrupted the kernel. Preserve GS.base in %r12,
* %cr3 in %r13, and possibly lower half of MSR_IA32_SPEC_CTL in %r14d.
* We've interrupted the kernel. See comment in NMI handler about
* registers use.
*/
movq %cr2,%r15
movl $MSR_GSBASE,%ecx
rdmsr
movq %rax,%r12
@ -1071,6 +1079,7 @@ mchk_calltrap:
shrq $32,%rdx
wrmsr
movq %r13,%cr3
movq %r15,%cr2
RESTORE_REGS
addq $TF_RIP,%rsp
jmp doreti_iret

View File

@ -1651,7 +1651,8 @@ END(handle_ibrs_exit_rs)
*
* N.B. The function does not follow ABI calling conventions, it corrupts %rbx.
* The vmm.ko caller expects that only %rax, %rdx, %rbx, %rcx, %r9, and %rflags
* registers are clobbered. The NMI handler caller only needs %r13 preserved.
* registers are clobbered. The NMI handler caller only needs %r13 and %r15
* preserved.
*/
ENTRY(flush_l1d_sw)
#define L1D_FLUSH_SIZE (64 * 1024)