x86/spec-ctrl: Fix NMI race condition with VT-x MSR_SPEC_CTRL handling
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 12 Jan 2022 15:47:27 +0000 (15:47 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 20 Jan 2022 16:32:11 +0000 (16:32 +0000)
commit81f0eaadf84d273a6ff8df3660b874a02d0e7677
treef6e9f1df8c68a1c8de9a365c860da1dd5114ddf1
parent95b13fa43e0753b7514bef13abe28253e8614f62
x86/spec-ctrl: Fix NMI race condition with VT-x MSR_SPEC_CTRL handling

The logic was based on a mistaken understanding of how NMI blocking on vmexit
works.  NMIs are only blocked for EXIT_REASON_NMI, and not for general exits.
Therefore, an NMI can in general hit early in the vmx_asm_vmexit_handler path,
and the guest's value will be clobbered before it is saved.

Switch to using MSR load/save lists.  This causes the guest value to be saved
atomically with respect to NMIs/MCEs/etc.

First, update vmx_cpuid_policy_changed() to configure the load/save lists at
the same time as configuring the intercepts.  This function is always used in
remote context, so extend the vmx_vmcs_{enter,exit}() block to cover the whole
function, rather than having multiple remote acquisitions of the same VMCS.

Both of vmx_{add,del}_guest_msr() can fail.  The -ESRCH delete case is fine,
but all others are fatal to the running of the VM, so handle them using
domain_crash() - this path is only used during domain construction anyway.

Second, update vmx_{get,set}_reg() to use the MSR load/save lists rather than
vcpu_msrs, and update the vcpu_msrs comment to describe the new state
location.

Finally, adjust the entry/exit asm.

Because the guest value is saved and loaded atomically, we do not need to
manually load the guest value, nor do we need to enable SCF_use_shadow.  This
lets us remove the use of DO_SPEC_CTRL_EXIT_TO_GUEST.  Additionally,
SPEC_CTRL_ENTRY_FROM_PV gets removed too, because on an early entry failure,
we're no longer in the guest MSR_SPEC_CTRL context needing to switch back to
Xen's context.

The only action remaining is to load Xen's MSR_SPEC_CTRL value on vmexit.  We
could in principle use the host msr list, but is expected to complicated
future work.  Delete DO_SPEC_CTRL_ENTRY_FROM_HVM entirely, and use a shorter
code sequence to simply reload Xen's setting from the top-of-stack block.

Adjust the comment at the top of spec_ctrl_asm.h in light of this bugfix.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/hvm/vmx/entry.S
xen/arch/x86/hvm/vmx/vmx.c
xen/arch/x86/include/asm/msr.h
xen/arch/x86/include/asm/spec_ctrl_asm.h