aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorXiao Guangrong <xiaoguangrong@cn.fujitsu.com>2010-08-28 07:24:13 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:51:48 -0400
commit365fb3fdf6769d3553999d8eb6cc2a8c56c747c1 (patch)
treee8ac38a587a4cf2cac88df4580e7112c15b13e14 /arch
parentbc32ce2152406431acf4daf4a81dc1664bb7b91b (diff)
KVM: MMU: rewrite audit_mappings_page() function
There is a bugs in this function, we call gfn_to_pfn() and kvm_mmu_gva_to_gpa_read() in atomic context(kvm_mmu_audit() is called under the spinlock(mmu_lock)'s protection). This patch fix it by: - introduce gfn_to_pfn_atomic instead of gfn_to_pfn - get the mapping gfn from kvm_mmu_page_get_gfn() And it adds 'notrap' ptes check in unsync/direct sps Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/mmu.c75
1 files changed, 40 insertions, 35 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
3488static const char *audit_msg; 3488static const char *audit_msg;
3489 3489
3490static 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
3499typedef void (*inspect_spte_fn) (struct kvm *kvm, u64 *sptep); 3490typedef void (*inspect_spte_fn) (struct kvm *kvm, u64 *sptep);
3500 3491
3501static void __mmu_spte_walk(struct kvm *kvm, struct kvm_mmu_page *sp, 3492static 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