KVM: vmx: Introduce handle_unexpected_vmexit and handle WAITPKG vmexit
authorTao Xu <tao3.xu@intel.com>
Tue, 16 Jul 2019 06:55:51 +0000 (14:55 +0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 24 Sep 2019 12:34:51 +0000 (14:34 +0200)
As the latest Intel 64 and IA-32 Architectures Software Developer's
Manual, UMWAIT and TPAUSE instructions cause a VM exit if the
RDTSC exiting and enable user wait and pause VM-execution
controls are both 1.

Because KVM never enable RDTSC exiting, the vm-exit for UMWAIT and TPAUSE
should never happen. Considering EXIT_REASON_XSAVES and
EXIT_REASON_XRSTORS is also unexpected VM-exit for KVM. Introduce a common
exit helper handle_unexpected_vmexit() to handle these unexpected VM-exit.

Suggested-by: Sean Christopherson <sean.j.christopherson@intel.com>
Co-developed-by: Jingqi Liu <jingqi.liu@intel.com>
Signed-off-by: Jingqi Liu <jingqi.liu@intel.com>
Signed-off-by: Tao Xu <tao3.xu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/include/uapi/asm/vmx.h
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmx.c

index f01950a..3eb8411 100644 (file)
@@ -86,6 +86,8 @@
 #define EXIT_REASON_PML_FULL            62
 #define EXIT_REASON_XSAVES              63
 #define EXIT_REASON_XRSTORS             64
+#define EXIT_REASON_UMWAIT              67
+#define EXIT_REASON_TPAUSE              68
 
 #define VMX_EXIT_REASONS \
        { EXIT_REASON_EXCEPTION_NMI,         "EXCEPTION_NMI" }, \
        { EXIT_REASON_RDSEED,                "RDSEED" }, \
        { EXIT_REASON_PML_FULL,              "PML_FULL" }, \
        { EXIT_REASON_XSAVES,                "XSAVES" }, \
-       { EXIT_REASON_XRSTORS,               "XRSTORS" }
+       { EXIT_REASON_XRSTORS,               "XRSTORS" }, \
+       { EXIT_REASON_UMWAIT,                "UMWAIT" }, \
+       { EXIT_REASON_TPAUSE,                "TPAUSE" }
 
 #define VMX_ABORT_SAVE_GUEST_MSR_FAIL        1
 #define VMX_ABORT_LOAD_HOST_PDPTE_FAIL       2
index c5b7ba7..77548ef 100644 (file)
@@ -5470,6 +5470,10 @@ bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason)
        case EXIT_REASON_ENCLS:
                /* SGX is never exposed to L1 */
                return false;
+       case EXIT_REASON_UMWAIT:
+       case EXIT_REASON_TPAUSE:
+               return nested_cpu_has2(vmcs12,
+                       SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE);
        default:
                return true;
        }
index 52dd224..a7c9922 100644 (file)
@@ -5007,20 +5007,6 @@ static int handle_xsetbv(struct kvm_vcpu *vcpu)
        return 1;
 }
 
-static int handle_xsaves(struct kvm_vcpu *vcpu)
-{
-       kvm_skip_emulated_instruction(vcpu);
-       WARN(1, "this should never happen\n");
-       return 1;
-}
-
-static int handle_xrstors(struct kvm_vcpu *vcpu)
-{
-       kvm_skip_emulated_instruction(vcpu);
-       WARN(1, "this should never happen\n");
-       return 1;
-}
-
 static int handle_apic_access(struct kvm_vcpu *vcpu)
 {
        if (likely(fasteoi)) {
@@ -5514,6 +5500,14 @@ static int handle_encls(struct kvm_vcpu *vcpu)
        return 1;
 }
 
+static int handle_unexpected_vmexit(struct kvm_vcpu *vcpu)
+{
+       kvm_skip_emulated_instruction(vcpu);
+       WARN_ONCE(1, "Unexpected VM-Exit Reason = 0x%x",
+               vmcs_read32(VM_EXIT_REASON));
+       return 1;
+}
+
 /*
  * The exit handlers return 1 if the exit was handled fully and guest execution
  * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
@@ -5565,13 +5559,15 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
        [EXIT_REASON_INVVPID]                 = handle_vmx_instruction,
        [EXIT_REASON_RDRAND]                  = handle_invalid_op,
        [EXIT_REASON_RDSEED]                  = handle_invalid_op,
-       [EXIT_REASON_XSAVES]                  = handle_xsaves,
-       [EXIT_REASON_XRSTORS]                 = handle_xrstors,
+       [EXIT_REASON_XSAVES]                  = handle_unexpected_vmexit,
+       [EXIT_REASON_XRSTORS]                 = handle_unexpected_vmexit,
        [EXIT_REASON_PML_FULL]                = handle_pml_full,
        [EXIT_REASON_INVPCID]                 = handle_invpcid,
        [EXIT_REASON_VMFUNC]                  = handle_vmx_instruction,
        [EXIT_REASON_PREEMPTION_TIMER]        = handle_preemption_timer,
        [EXIT_REASON_ENCLS]                   = handle_encls,
+       [EXIT_REASON_UMWAIT]                  = handle_unexpected_vmexit,
+       [EXIT_REASON_TPAUSE]                  = handle_unexpected_vmexit,
 };
 
 static const int kvm_vmx_max_exit_handlers =