Skip to content

Commit bca99c0

Browse files
sean-jcbonzini
authored andcommitted
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 <[email protected]> Message-ID: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 743f177 commit bca99c0

File tree

3 files changed

+38
-8
lines changed

3 files changed

+38
-8
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2154,6 +2154,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
21542154

21552155
int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
21562156
void *insn, int insn_len);
2157+
void kvm_mmu_print_sptes(struct kvm_vcpu *vcpu, gpa_t gpa, const char *msg);
21572158
void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva);
21582159
void kvm_mmu_invalidate_addr(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
21592160
u64 addr, unsigned long roots);

arch/x86/kvm/mmu/mmu.c

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4104,23 +4104,31 @@ static int get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes, int *root_level
41044104
return leaf;
41054105
}
41064106

4107-
/* return true if reserved bit(s) are detected on a valid, non-MMIO SPTE. */
4108-
static bool get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep)
4107+
static int get_sptes_lockless(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes,
4108+
int *root_level)
41094109
{
4110-
u64 sptes[PT64_ROOT_MAX_LEVEL + 1];
4111-
struct rsvd_bits_validate *rsvd_check;
4112-
int root, leaf, level;
4113-
bool reserved = false;
4110+
int leaf;
41144111

41154112
walk_shadow_page_lockless_begin(vcpu);
41164113

41174114
if (is_tdp_mmu_active(vcpu))
4118-
leaf = kvm_tdp_mmu_get_walk(vcpu, addr, sptes, &root);
4115+
leaf = kvm_tdp_mmu_get_walk(vcpu, addr, sptes, root_level);
41194116
else
4120-
leaf = get_walk(vcpu, addr, sptes, &root);
4117+
leaf = get_walk(vcpu, addr, sptes, root_level);
41214118

41224119
walk_shadow_page_lockless_end(vcpu);
4120+
return leaf;
4121+
}
41234122

4123+
/* return true if reserved bit(s) are detected on a valid, non-MMIO SPTE. */
4124+
static bool get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep)
4125+
{
4126+
u64 sptes[PT64_ROOT_MAX_LEVEL + 1];
4127+
struct rsvd_bits_validate *rsvd_check;
4128+
int root, leaf, level;
4129+
bool reserved = false;
4130+
4131+
leaf = get_sptes_lockless(vcpu, addr, sptes, &root);
41244132
if (unlikely(leaf < 0)) {
41254133
*sptep = 0ull;
41264134
return reserved;
@@ -5924,6 +5932,22 @@ int noinline kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 err
59245932
}
59255933
EXPORT_SYMBOL_GPL(kvm_mmu_page_fault);
59265934

5935+
void kvm_mmu_print_sptes(struct kvm_vcpu *vcpu, gpa_t gpa, const char *msg)
5936+
{
5937+
u64 sptes[PT64_ROOT_MAX_LEVEL + 1];
5938+
int root_level, leaf, level;
5939+
5940+
leaf = get_sptes_lockless(vcpu, gpa, sptes, &root_level);
5941+
if (unlikely(leaf < 0))
5942+
return;
5943+
5944+
pr_err("%s %llx", msg, gpa);
5945+
for (level = root_level; level >= leaf; level--)
5946+
pr_cont(", spte[%d] = 0x%llx", level, sptes[level]);
5947+
pr_cont("\n");
5948+
}
5949+
EXPORT_SYMBOL_GPL(kvm_mmu_print_sptes);
5950+
59275951
static void __kvm_mmu_invalidate_addr(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
59285952
u64 addr, hpa_t root_hpa)
59295953
{

arch/x86/kvm/vmx/vmx.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5218,7 +5218,12 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
52185218
return handle_ud(vcpu);
52195219

52205220
if (WARN_ON_ONCE(is_ve_fault(intr_info))) {
5221+
struct vmx_ve_information *ve_info = vmx->ve_info;
5222+
5223+
WARN_ONCE(ve_info->exit_reason != EXIT_REASON_EPT_VIOLATION,
5224+
"Unexpected #VE on VM-Exit reason 0x%x", ve_info->exit_reason);
52215225
dump_vmcs(vcpu);
5226+
kvm_mmu_print_sptes(vcpu, ve_info->guest_physical_address, "#VE");
52225227
return 1;
52235228
}
52245229

0 commit comments

Comments
 (0)