]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
KVM: nVMX: trace nested VM-Enter failures detected by H/W
authorSean Christopherson <sean.j.christopherson@intel.com>
Thu, 11 Jul 2019 15:58:30 +0000 (08:58 -0700)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 11 Sep 2019 15:34:17 +0000 (17:34 +0200)
Use the recently added tracepoint for logging nested VM-Enter failures
instead of spamming the kernel log when hardware detects a consistency
check failure.  Take the opportunity to print the name of the error code
instead of dumping the raw hex number, but limit the symbol table to
error codes that can reasonably be encountered by KVM.

Add an equivalent tracepoint in nested_vmx_check_vmentry_hw(), e.g. so
that tracing of "invalid control field" errors isn't suppressed when
nested early checks are enabled.

Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/include/asm/vmx.h
arch/x86/kvm/trace.h
arch/x86/kvm/vmx/nested.c

index a39136b0d509caacdf544b6ef719ba563be93623..b15e6465870f8c5fb99b34823dc86d1b7597ea89 100644 (file)
@@ -562,6 +562,20 @@ enum vm_instruction_error_number {
        VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID = 28,
 };
 
+/*
+ * VM-instruction errors that can be encountered on VM-Enter, used to trace
+ * nested VM-Enter failures reported by hardware.  Errors unique to VM-Enter
+ * from a SMI Transfer Monitor are not included as things have gone seriously
+ * sideways if we get one of those...
+ */
+#define VMX_VMENTER_INSTRUCTION_ERRORS \
+       { VMXERR_VMLAUNCH_NONCLEAR_VMCS,                "VMLAUNCH_NONCLEAR_VMCS" }, \
+       { VMXERR_VMRESUME_NONLAUNCHED_VMCS,             "VMRESUME_NONLAUNCHED_VMCS" }, \
+       { VMXERR_VMRESUME_AFTER_VMXOFF,                 "VMRESUME_AFTER_VMXOFF" }, \
+       { VMXERR_ENTRY_INVALID_CONTROL_FIELD,           "VMENTRY_INVALID_CONTROL_FIELD" }, \
+       { VMXERR_ENTRY_INVALID_HOST_STATE_FIELD,        "VMENTRY_INVALID_HOST_STATE_FIELD" }, \
+       { VMXERR_ENTRY_EVENTS_BLOCKED_BY_MOV_SS,        "VMENTRY_EVENTS_BLOCKED_BY_MOV_SS" }
+
 enum vmx_l1d_flush_state {
        VMENTER_L1D_FLUSH_AUTO,
        VMENTER_L1D_FLUSH_NEVER,
index 25ea92873e49bc4952e2f8de704552f98a30efa4..7c741a0c5f808466354c7e786d81f2e6acdf12ee 100644 (file)
@@ -1479,18 +1479,21 @@ TRACE_EVENT(kvm_pv_tlb_flush,
  * Tracepoint for failed nested VMX VM-Enter.
  */
 TRACE_EVENT(kvm_nested_vmenter_failed,
-       TP_PROTO(const char *msg),
-       TP_ARGS(msg),
+       TP_PROTO(const char *msg, u32 err),
+       TP_ARGS(msg, err),
 
        TP_STRUCT__entry(
                __field(const char *, msg)
+               __field(u32, err)
        ),
 
        TP_fast_assign(
                __entry->msg = msg;
+               __entry->err = err;
        ),
 
-       TP_printk("%s", __entry->msg)
+       TP_printk("%s%s", __entry->msg, !__entry->err ? "" :
+               __print_symbolic(__entry->err, VMX_VMENTER_INSTRUCTION_ERRORS))
 );
 
 #endif /* _TRACE_KVM_H */
index bdfc5570bab816792f739f2fcaef8a9e717c70f8..ad2453317c4ba4d4629aba31115668300095bcb1 100644 (file)
@@ -23,7 +23,7 @@ module_param(nested_early_check, bool, S_IRUGO);
 ({                                                                     \
        bool failed = (consistency_check);                              \
        if (failed)                                                     \
-               trace_kvm_nested_vmenter_failed(#consistency_check);    \
+               trace_kvm_nested_vmenter_failed(#consistency_check, 0); \
        failed;                                                         \
 })
 
@@ -2845,9 +2845,13 @@ static int nested_vmx_check_vmentry_hw(struct kvm_vcpu *vcpu)
                vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr);
 
        if (vm_fail) {
+               u32 error = vmcs_read32(VM_INSTRUCTION_ERROR);
+
                preempt_enable();
-               WARN_ON_ONCE(vmcs_read32(VM_INSTRUCTION_ERROR) !=
-                            VMXERR_ENTRY_INVALID_CONTROL_FIELD);
+
+               trace_kvm_nested_vmenter_failed(
+                       "early hardware check VM-instruction error: ", error);
+               WARN_ON_ONCE(error != VMXERR_ENTRY_INVALID_CONTROL_FIELD);
                return 1;
        }
 
@@ -5259,8 +5263,9 @@ bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason)
                return false;
 
        if (unlikely(vmx->fail)) {
-               pr_info_ratelimited("%s failed vm entry %x\n", __func__,
-                                   vmcs_read32(VM_INSTRUCTION_ERROR));
+               trace_kvm_nested_vmenter_failed(
+                       "hardware VM-instruction error: ",
+                       vmcs_read32(VM_INSTRUCTION_ERROR));
                return true;
        }