Commit aec511ad authored by Sean Christopherson's avatar Sean Christopherson Committed by Paolo Bonzini

x86/virt: Eat faults on VMXOFF in reboot flows

Silently ignore all faults on VMXOFF in the reboot flows as such faults
are all but guaranteed to be due to the CPU not being in VMX root.
Because (a) VMXOFF may be executed in NMI context, e.g. after VMXOFF but
before CR4.VMXE is cleared, (b) there's no way to query the CPU's VMX
state without faulting, and (c) the whole point is to get out of VMX
root, eating faults is the simplest way to achieve the desired behaior.

Technically, VMXOFF can fault (or fail) for other reasons, but all other
fault and failure scenarios are mode related, i.e. the kernel would have
to magically end up in RM, V86, compat mode, at CPL>0, or running with
the SMI Transfer Monitor active.  The kernel is beyond hosed if any of
those scenarios are encountered; trying to do something fancy in the
error path to handle them cleanly is pointless.

Fixes: 1e993114 ("x86: asm/virtext.h: add cpu_vmxoff() inline function")
Reported-by: default avatarDavid P. Reed <dpreed@deepplum.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
Message-Id: <20201231002702.22237077-2-seanjc@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent b3646477
...@@ -30,15 +30,22 @@ static inline int cpu_has_vmx(void) ...@@ -30,15 +30,22 @@ static inline int cpu_has_vmx(void)
} }
/** Disable VMX on the current CPU /**
* cpu_vmxoff() - Disable VMX on the current CPU
* *
* vmxoff causes a undefined-opcode exception if vmxon was not run * Disable VMX and clear CR4.VMXE (even if VMXOFF faults)
* on the CPU previously. Only call this function if you know VMX *
* is enabled. * Note, VMXOFF causes a #UD if the CPU is !post-VMXON, but it's impossible to
* atomically track post-VMXON state, e.g. this may be called in NMI context.
* Eat all faults as all other faults on VMXOFF faults are mode related, i.e.
* faults are guaranteed to be due to the !post-VMXON check unless the CPU is
* magically in RM, VM86, compat mode, or at CPL>0.
*/ */
static inline void cpu_vmxoff(void) static inline void cpu_vmxoff(void)
{ {
asm volatile ("vmxoff"); asm_volatile_goto("1: vmxoff\n\t"
_ASM_EXTABLE(1b, %l[fault]) :::: fault);
fault:
cr4_clear_bits(X86_CR4_VMXE); cr4_clear_bits(X86_CR4_VMXE);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment