mirror of
https://github.com/torvalds/linux
synced 2024-09-06 09:51:23 +00:00
KVM: x86/mmu: Print SPTEs on unexpected #VE
Print the SPTEs that correspond to the faulting GPA on an unexpected EPT Violation #VE to help the user debug failures, e.g. to pinpoint which SPTE didn't have SUPPRESS_VE set. Opportunistically assert that the underlying exit reason was indeed an EPT Violation, as the CPU has *really* gone off the rails if a #VE occurs due to a completely unexpected exit reason. Signed-off-by: Sean Christopherson <seanjc@google.com> Message-ID: <20240518000430.1118488-7-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
743f177336
commit
bca99c0356
|
@ -2154,6 +2154,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
|
|||
|
||||
int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
|
||||
void *insn, int insn_len);
|
||||
void kvm_mmu_print_sptes(struct kvm_vcpu *vcpu, gpa_t gpa, const char *msg);
|
||||
void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva);
|
||||
void kvm_mmu_invalidate_addr(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
|
||||
u64 addr, unsigned long roots);
|
||||
|
|
|
@ -4104,6 +4104,22 @@ static int get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes, int *root_level
|
|||
return leaf;
|
||||
}
|
||||
|
||||
static int get_sptes_lockless(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes,
|
||||
int *root_level)
|
||||
{
|
||||
int leaf;
|
||||
|
||||
walk_shadow_page_lockless_begin(vcpu);
|
||||
|
||||
if (is_tdp_mmu_active(vcpu))
|
||||
leaf = kvm_tdp_mmu_get_walk(vcpu, addr, sptes, root_level);
|
||||
else
|
||||
leaf = get_walk(vcpu, addr, sptes, root_level);
|
||||
|
||||
walk_shadow_page_lockless_end(vcpu);
|
||||
return leaf;
|
||||
}
|
||||
|
||||
/* return true if reserved bit(s) are detected on a valid, non-MMIO SPTE. */
|
||||
static bool get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep)
|
||||
{
|
||||
|
@ -4112,15 +4128,7 @@ static bool get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep)
|
|||
int root, leaf, level;
|
||||
bool reserved = false;
|
||||
|
||||
walk_shadow_page_lockless_begin(vcpu);
|
||||
|
||||
if (is_tdp_mmu_active(vcpu))
|
||||
leaf = kvm_tdp_mmu_get_walk(vcpu, addr, sptes, &root);
|
||||
else
|
||||
leaf = get_walk(vcpu, addr, sptes, &root);
|
||||
|
||||
walk_shadow_page_lockless_end(vcpu);
|
||||
|
||||
leaf = get_sptes_lockless(vcpu, addr, sptes, &root);
|
||||
if (unlikely(leaf < 0)) {
|
||||
*sptep = 0ull;
|
||||
return reserved;
|
||||
|
@ -5924,6 +5932,22 @@ int noinline kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 err
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_mmu_page_fault);
|
||||
|
||||
void kvm_mmu_print_sptes(struct kvm_vcpu *vcpu, gpa_t gpa, const char *msg)
|
||||
{
|
||||
u64 sptes[PT64_ROOT_MAX_LEVEL + 1];
|
||||
int root_level, leaf, level;
|
||||
|
||||
leaf = get_sptes_lockless(vcpu, gpa, sptes, &root_level);
|
||||
if (unlikely(leaf < 0))
|
||||
return;
|
||||
|
||||
pr_err("%s %llx", msg, gpa);
|
||||
for (level = root_level; level >= leaf; level--)
|
||||
pr_cont(", spte[%d] = 0x%llx", level, sptes[level]);
|
||||
pr_cont("\n");
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_mmu_print_sptes);
|
||||
|
||||
static void __kvm_mmu_invalidate_addr(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
|
||||
u64 addr, hpa_t root_hpa)
|
||||
{
|
||||
|
|
|
@ -5218,7 +5218,12 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
|
|||
return handle_ud(vcpu);
|
||||
|
||||
if (WARN_ON_ONCE(is_ve_fault(intr_info))) {
|
||||
struct vmx_ve_information *ve_info = vmx->ve_info;
|
||||
|
||||
WARN_ONCE(ve_info->exit_reason != EXIT_REASON_EPT_VIOLATION,
|
||||
"Unexpected #VE on VM-Exit reason 0x%x", ve_info->exit_reason);
|
||||
dump_vmcs(vcpu);
|
||||
kvm_mmu_print_sptes(vcpu, ve_info->guest_physical_address, "#VE");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue