Skip to content

Commit

Permalink
KVM: nVMX: trace nested VM-Enter failures detected by H/W
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Sean Christopherson authored and bonzini committed Sep 11, 2019
1 parent 5497b95 commit 380e005
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 8 deletions.
14 changes: 14 additions & 0 deletions arch/x86/include/asm/vmx.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
9 changes: 6 additions & 3 deletions arch/x86/kvm/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
15 changes: 10 additions & 5 deletions arch/x86/kvm/vmx/nested.c
Original file line number Diff line number Diff line change
Expand Up @@ -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; \
})

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit 380e005

Please sign in to comment.