Skip to content

Commit

Permalink
KVM: x86/mmu: Cleanup sanity check of SPTEs at SP free
Browse files Browse the repository at this point in the history
Massage the error message for the sanity check on SPTEs when freeing a
shadow page to be more verbose, and to print out all shadow-present SPTEs,
not just the first SPTE encountered.  Printing all SPTEs can be quite
valuable for debug, e.g. highlights whether the leak is a one-off or
widepsread, or possibly the result of memory corruption (something else
in the kernel stomping on KVM's SPTEs).

Opportunistically move the MMU_WARN_ON() into the helper itself, which
will allow a future cleanup to use BUILD_BUG_ON_INVALID() as the stub for
MMU_WARN_ON().  BUILD_BUG_ON_INVALID() works as intended and results in
the compiler complaining about is_empty_shadow_page() not being declared.

Link: https://lore.kernel.org/r/20230729004722.1056172-6-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
  • Loading branch information
sean-jc committed Aug 3, 2023
1 parent c7784ee commit 064a5ab
Showing 1 changed file with 9 additions and 10 deletions.
19 changes: 9 additions & 10 deletions arch/x86/kvm/mmu/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1693,21 +1693,19 @@ bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
return young;
}

#ifdef MMU_DEBUG
static int is_empty_shadow_page(u64 *spt)
static void kvm_mmu_check_sptes_at_free(struct kvm_mmu_page *sp)
{
#ifdef MMU_DEBUG
int i;

for (i = 0; i < SPTE_ENT_PER_PAGE; i++) {
if (is_shadow_present_pte(spt[i])) {
printk(KERN_ERR "%s: %p %llx\n", __func__,
&spt[i], spt[i]);
return 0;
}
if (MMU_WARN_ON(is_shadow_present_pte(sp->spt[i])))
pr_err_ratelimited("SPTE %llx (@ %p) for gfn %llx shadow-present at free",
sp->spt[i], &sp->spt[i],
kvm_mmu_page_get_gfn(sp, i));
}
return 1;
}
#endif
}

/*
* This value is the sum of all of the kvm instances's
Expand Down Expand Up @@ -1735,7 +1733,8 @@ static void kvm_unaccount_mmu_page(struct kvm *kvm, struct kvm_mmu_page *sp)

static void kvm_mmu_free_shadow_page(struct kvm_mmu_page *sp)
{
MMU_WARN_ON(!is_empty_shadow_page(sp->spt));
kvm_mmu_check_sptes_at_free(sp);

hlist_del(&sp->hash_link);
list_del(&sp->link);
free_page((unsigned long)sp->spt);
Expand Down

0 comments on commit 064a5ab

Please sign in to comment.