OSDN Git Service

x86/virt: KVM: Move VMXOFF helpers into KVM VMX
[tomoyo/tomoyo-test1.git] / arch / x86 / kvm / vmx / vmx.c
index 4b9d688..64377fe 100644 (file)
@@ -47,7 +47,6 @@
 #include <asm/mshyperv.h>
 #include <asm/mwait.h>
 #include <asm/spec-ctrl.h>
-#include <asm/virtext.h>
 #include <asm/vmx.h>
 
 #include "capabilities.h"
@@ -725,6 +724,29 @@ static int vmx_set_guest_uret_msr(struct vcpu_vmx *vmx,
        return ret;
 }
 
+/*
+ * Disable VMX and clear CR4.VMXE (even if VMXOFF faults)
+ *
+ * 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 int kvm_cpu_vmxoff(void)
+{
+       asm_volatile_goto("1: vmxoff\n\t"
+                         _ASM_EXTABLE(1b, %l[fault])
+                         ::: "cc", "memory" : fault);
+
+       cr4_clear_bits(X86_CR4_VMXE);
+       return 0;
+
+fault:
+       cr4_clear_bits(X86_CR4_VMXE);
+       return -EIO;
+}
+
 static void vmx_emergency_disable(void)
 {
        int cpu = raw_smp_processor_id();
@@ -734,7 +756,8 @@ static void vmx_emergency_disable(void)
                            loaded_vmcss_on_cpu_link)
                vmcs_clear(v->vmcs);
 
-       __cpu_emergency_vmxoff();
+       if (__read_cr4() & X86_CR4_VMXE)
+               kvm_cpu_vmxoff();
 }
 
 static void __loaded_vmcs_clear(void *arg)
@@ -2799,7 +2822,7 @@ static void vmx_hardware_disable(void)
 {
        vmclear_local_loaded_vmcss();
 
-       if (cpu_vmxoff())
+       if (kvm_cpu_vmxoff())
                kvm_spurious_fault();
 
        hv_reset_evmcs();