diff options
-rw-r--r-- | arch/x86/kvm/mmu.c | 75 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 1 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 15 |
3 files changed, 54 insertions, 37 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 68575dc32ec7..0d91f60af1a8 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -3487,15 +3487,6 @@ EXPORT_SYMBOL_GPL(kvm_mmu_get_spte_hierarchy); | |||
3487 | 3487 | ||
3488 | static const char *audit_msg; | 3488 | static const char *audit_msg; |
3489 | 3489 | ||
3490 | static gva_t canonicalize(gva_t gva) | ||
3491 | { | ||
3492 | #ifdef CONFIG_X86_64 | ||
3493 | gva = (long long)(gva << 16) >> 16; | ||
3494 | #endif | ||
3495 | return gva; | ||
3496 | } | ||
3497 | |||
3498 | |||
3499 | typedef void (*inspect_spte_fn) (struct kvm *kvm, u64 *sptep); | 3490 | typedef void (*inspect_spte_fn) (struct kvm *kvm, u64 *sptep); |
3500 | 3491 | ||
3501 | static void __mmu_spte_walk(struct kvm *kvm, struct kvm_mmu_page *sp, | 3492 | static void __mmu_spte_walk(struct kvm *kvm, struct kvm_mmu_page *sp, |
@@ -3550,39 +3541,53 @@ static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte, | |||
3550 | gva_t va_delta = 1ul << (PAGE_SHIFT + 9 * (level - 1)); | 3541 | gva_t va_delta = 1ul << (PAGE_SHIFT + 9 * (level - 1)); |
3551 | 3542 | ||
3552 | for (i = 0; i < PT64_ENT_PER_PAGE; ++i, va += va_delta) { | 3543 | for (i = 0; i < PT64_ENT_PER_PAGE; ++i, va += va_delta) { |
3553 | u64 ent = pt[i]; | 3544 | u64 *sptep = pt + i; |
3545 | struct kvm_mmu_page *sp; | ||
3546 | gfn_t gfn; | ||
3547 | pfn_t pfn; | ||
3548 | hpa_t hpa; | ||
3554 | 3549 | ||
3555 | if (ent == shadow_trap_nonpresent_pte) | 3550 | sp = page_header(__pa(sptep)); |
3556 | continue; | ||
3557 | 3551 | ||
3558 | va = canonicalize(va); | 3552 | if (sp->unsync) { |
3559 | if (is_shadow_present_pte(ent) && !is_last_spte(ent, level)) | 3553 | if (level != PT_PAGE_TABLE_LEVEL) { |
3560 | audit_mappings_page(vcpu, ent, va, level - 1); | 3554 | printk(KERN_ERR "audit: (%s) error: unsync sp: %p level = %d\n", |
3561 | else { | 3555 | audit_msg, sp, level); |
3562 | gpa_t gpa = kvm_mmu_gva_to_gpa_read(vcpu, va, NULL); | 3556 | return; |
3563 | gfn_t gfn = gpa >> PAGE_SHIFT; | 3557 | } |
3564 | pfn_t pfn = gfn_to_pfn(vcpu->kvm, gfn); | ||
3565 | hpa_t hpa = (hpa_t)pfn << PAGE_SHIFT; | ||
3566 | 3558 | ||
3567 | if (is_error_pfn(pfn)) { | 3559 | if (*sptep == shadow_notrap_nonpresent_pte) { |
3568 | kvm_release_pfn_clean(pfn); | 3560 | printk(KERN_ERR "audit: (%s) error: notrap spte in unsync sp: %p\n", |
3569 | continue; | 3561 | audit_msg, sp); |
3562 | return; | ||
3570 | } | 3563 | } |
3564 | } | ||
3571 | 3565 | ||
3572 | if (is_shadow_present_pte(ent) | 3566 | if (sp->role.direct && *sptep == shadow_notrap_nonpresent_pte) { |
3573 | && (ent & PT64_BASE_ADDR_MASK) != hpa) | 3567 | printk(KERN_ERR "audit: (%s) error: notrap spte in direct sp: %p\n", |
3574 | printk(KERN_ERR "xx audit error: (%s) levels %d" | 3568 | audit_msg, sp); |
3575 | " gva %lx gpa %llx hpa %llx ent %llx %d\n", | 3569 | return; |
3576 | audit_msg, vcpu->arch.mmu.root_level, | 3570 | } |
3577 | va, gpa, hpa, ent, | 3571 | |
3578 | is_shadow_present_pte(ent)); | 3572 | if (!is_shadow_present_pte(*sptep) || |
3579 | else if (ent == shadow_notrap_nonpresent_pte | 3573 | !is_last_spte(*sptep, level)) |
3580 | && !is_error_hpa(hpa)) | 3574 | return; |
3581 | printk(KERN_ERR "audit: (%s) notrap shadow," | 3575 | |
3582 | " valid guest gva %lx\n", audit_msg, va); | 3576 | gfn = kvm_mmu_page_get_gfn(sp, sptep - sp->spt); |
3583 | kvm_release_pfn_clean(pfn); | 3577 | pfn = gfn_to_pfn_atomic(vcpu->kvm, gfn); |
3584 | 3578 | ||
3579 | if (is_error_pfn(pfn)) { | ||
3580 | kvm_release_pfn_clean(pfn); | ||
3581 | return; | ||
3585 | } | 3582 | } |
3583 | |||
3584 | hpa = pfn << PAGE_SHIFT; | ||
3585 | |||
3586 | if ((*sptep & PT64_BASE_ADDR_MASK) != hpa) | ||
3587 | printk(KERN_ERR "xx audit error: (%s) levels %d" | ||
3588 | " gva %lx pfn %llx hpa %llx ent %llxn", | ||
3589 | audit_msg, vcpu->arch.mmu.root_level, | ||
3590 | va, pfn, hpa, *sptep); | ||
3586 | } | 3591 | } |
3587 | } | 3592 | } |
3588 | 3593 | ||
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index b837ec80885d..f2ecdd52032b 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -300,6 +300,7 @@ void kvm_set_page_dirty(struct page *page); | |||
300 | void kvm_set_page_accessed(struct page *page); | 300 | void kvm_set_page_accessed(struct page *page); |
301 | 301 | ||
302 | pfn_t hva_to_pfn_atomic(struct kvm *kvm, unsigned long addr); | 302 | pfn_t hva_to_pfn_atomic(struct kvm *kvm, unsigned long addr); |
303 | pfn_t gfn_to_pfn_atomic(struct kvm *kvm, gfn_t gfn); | ||
303 | pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn); | 304 | pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn); |
304 | pfn_t gfn_to_pfn_memslot(struct kvm *kvm, | 305 | pfn_t gfn_to_pfn_memslot(struct kvm *kvm, |
305 | struct kvm_memory_slot *slot, gfn_t gfn); | 306 | struct kvm_memory_slot *slot, gfn_t gfn); |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 2eb0b7500a2a..c7a57b4feb39 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -999,7 +999,7 @@ pfn_t hva_to_pfn_atomic(struct kvm *kvm, unsigned long addr) | |||
999 | } | 999 | } |
1000 | EXPORT_SYMBOL_GPL(hva_to_pfn_atomic); | 1000 | EXPORT_SYMBOL_GPL(hva_to_pfn_atomic); |
1001 | 1001 | ||
1002 | pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn) | 1002 | static pfn_t __gfn_to_pfn(struct kvm *kvm, gfn_t gfn, bool atomic) |
1003 | { | 1003 | { |
1004 | unsigned long addr; | 1004 | unsigned long addr; |
1005 | 1005 | ||
@@ -1009,7 +1009,18 @@ pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn) | |||
1009 | return page_to_pfn(bad_page); | 1009 | return page_to_pfn(bad_page); |
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | return hva_to_pfn(kvm, addr, false); | 1012 | return hva_to_pfn(kvm, addr, atomic); |
1013 | } | ||
1014 | |||
1015 | pfn_t gfn_to_pfn_atomic(struct kvm *kvm, gfn_t gfn) | ||
1016 | { | ||
1017 | return __gfn_to_pfn(kvm, gfn, true); | ||
1018 | } | ||
1019 | EXPORT_SYMBOL_GPL(gfn_to_pfn_atomic); | ||
1020 | |||
1021 | pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn) | ||
1022 | { | ||
1023 | return __gfn_to_pfn(kvm, gfn, false); | ||
1013 | } | 1024 | } |
1014 | EXPORT_SYMBOL_GPL(gfn_to_pfn); | 1025 | EXPORT_SYMBOL_GPL(gfn_to_pfn); |
1015 | 1026 | ||