aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2012-09-20 15:39:21 -0400
committerAlexander Graf <agraf@suse.de>2012-10-05 17:38:53 -0400
commit70bddfefbdcdbfdebd81d8b59ff8a7fa5d450ccc (patch)
tree64196d1bffa4379dfcf6ed6c4e809ba138ae44cc /arch
parent964ee98ccde0534548565a201827cf06d813180f (diff)
KVM: PPC: Book3S HV: Fix calculation of guest phys address for MMIO emulation
In the case where the host kernel is using a 64kB base page size and the guest uses a 4k HPTE (hashed page table entry) to map an emulated MMIO device, we were calculating the guest physical address wrongly. We were calculating a gfn as the guest physical address shifted right 16 bits (PAGE_SHIFT) but then only adding back in 12 bits from the effective address, since the HPTE had a 4k page size. Thus the gpa reported to userspace was missing 4 bits. Instead, we now compute the guest physical address from the HPTE without reference to the host page size, and then compute the gfn by shifting the gpa right PAGE_SHIFT bits. Reported-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_hv.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index f598366e51c6..7a4aae99ac5b 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -571,7 +571,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
571 struct kvm *kvm = vcpu->kvm; 571 struct kvm *kvm = vcpu->kvm;
572 unsigned long *hptep, hpte[3], r; 572 unsigned long *hptep, hpte[3], r;
573 unsigned long mmu_seq, psize, pte_size; 573 unsigned long mmu_seq, psize, pte_size;
574 unsigned long gfn, hva, pfn; 574 unsigned long gpa, gfn, hva, pfn;
575 struct kvm_memory_slot *memslot; 575 struct kvm_memory_slot *memslot;
576 unsigned long *rmap; 576 unsigned long *rmap;
577 struct revmap_entry *rev; 577 struct revmap_entry *rev;
@@ -609,15 +609,14 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
609 609
610 /* Translate the logical address and get the page */ 610 /* Translate the logical address and get the page */
611 psize = hpte_page_size(hpte[0], r); 611 psize = hpte_page_size(hpte[0], r);
612 gfn = hpte_rpn(r, psize); 612 gpa = (r & HPTE_R_RPN & ~(psize - 1)) | (ea & (psize - 1));
613 gfn = gpa >> PAGE_SHIFT;
613 memslot = gfn_to_memslot(kvm, gfn); 614 memslot = gfn_to_memslot(kvm, gfn);
614 615
615 /* No memslot means it's an emulated MMIO region */ 616 /* No memslot means it's an emulated MMIO region */
616 if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) { 617 if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
617 unsigned long gpa = (gfn << PAGE_SHIFT) | (ea & (psize - 1));
618 return kvmppc_hv_emulate_mmio(run, vcpu, gpa, ea, 618 return kvmppc_hv_emulate_mmio(run, vcpu, gpa, ea,
619 dsisr & DSISR_ISSTORE); 619 dsisr & DSISR_ISSTORE);
620 }
621 620
622 if (!kvm->arch.using_mmu_notifiers) 621 if (!kvm->arch.using_mmu_notifiers)
623 return -EFAULT; /* should never get here */ 622 return -EFAULT; /* should never get here */