[PATCH v1 10/13] KVM: PPC: Fix kvmppc_gpa_to_hva_and_get() to return host physical address

Alexey Kardashevskiy aik at ozlabs.ru
Tue Jul 15 19:25:30 EST 2014

The existing support of emulated devices does not need to calculate
a host physical address as the translation is performed by the userspace.

The upcoming support of VFIO needs it as it stores host physical
addresses in the real hardware TCE table which hardware uses during DMA
transfer. This translation could be done using page struct object
which is returned by kvmppc_gpa_to_hva_and_get().

However kvmppc_gpa_to_hva_and_get() does not return valid page struct
for huge pages to avoid possible bugs with excessive page releases.

This extends kvmppc_gpa_to_hva_and_get() to return a physical page address.

Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
 arch/powerpc/kvm/book3s_64_vio.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c
index 8250521..573fd6d 100644
--- a/arch/powerpc/kvm/book3s_64_vio.c
+++ b/arch/powerpc/kvm/book3s_64_vio.c
@@ -321,7 +321,7 @@ fail:
  * and returns ERROR_ADDR if failed.
 static void __user *kvmppc_gpa_to_hva_and_get(struct kvm_vcpu *vcpu,
-		unsigned long gpa, struct page **pg)
+		unsigned long gpa, struct page **pg, unsigned long *phpa)
 	unsigned long hva, gfn = gpa >> PAGE_SHIFT;
 	struct kvm_memory_slot *memslot;
@@ -337,6 +337,10 @@ static void __user *kvmppc_gpa_to_hva_and_get(struct kvm_vcpu *vcpu,
 		if (get_user_pages_fast(hva & PAGE_MASK, 1, is_write, pg) != 1)
 			return ERROR_ADDR;
+		if (phpa)
+			*phpa = __pa((unsigned long) page_address(*pg)) |
+				(hva & ~PAGE_MASK);
 		 * Check if this GPA is taken care of by the hash table.
 		 * If this is the case, do not show the caller page struct
@@ -404,7 +408,7 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
 		return ret;
 	idx = srcu_read_lock(&vcpu->kvm->srcu);
-	tces = kvmppc_gpa_to_hva_and_get(vcpu, tce_list, NULL);
+	tces = kvmppc_gpa_to_hva_and_get(vcpu, tce_list, NULL, NULL);
 	if (tces == ERROR_ADDR) {
 		ret = H_TOO_HARD;
 		goto unlock_exit;

More information about the Linuxppc-dev mailing list