public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] KVM: PPC: Book3S HV: Enable on little endian hosts
@ 2014-06-11 10:33 Alexander Graf
  2014-06-11 10:33 ` [PATCH 1/6] PPC: Add asm helpers for BE 32bit load/store Alexander Graf
                   ` (6 more replies)
  0 siblings, 7 replies; 16+ messages in thread
From: Alexander Graf @ 2014-06-11 10:33 UTC (permalink / raw)
  To: kvm-ppc; +Cc: kvm, anton

So far we've been able to successfully run HV KVM on big endian hosts, but
once you dive into little endian land things start to fall apart.

This patch set enables HV KVM for little endian hosts. This should be the
final piece left missing to get little endian systems fully en par with big
endian ones in the KVM world.


Alex

Alexander Graf (6):
  PPC: Add asm helpers for BE 32bit load/store
  KVM: PPC: Book3S HV: Make HTAB code LE host aware
  KVM: PPC: Book3S HV: Access guest VPA in BE
  KVM: PPC: Book3S HV: Access host lppaca and shadow slb in BE
  KVM: PPC: Book3S HV: Access XICS in BE
  KVM: PPC: Book3S HV: Enable for little endian hosts

 arch/powerpc/include/asm/asm-compat.h    |   4 ++
 arch/powerpc/include/asm/kvm_book3s_64.h |  14 +++-
 arch/powerpc/kvm/Kconfig                 |   1 -
 arch/powerpc/kvm/book3s_64_mmu_hv.c      |  95 +++++++++++++-------------
 arch/powerpc/kvm/book3s_hv.c             |  16 ++---
 arch/powerpc/kvm/book3s_hv_ras.c         |   6 +-
 arch/powerpc/kvm/book3s_hv_rm_mmu.c      | 111 ++++++++++++++++++-------------
 arch/powerpc/kvm/book3s_hv_rmhandlers.S  |  37 +++++++----
 8 files changed, 166 insertions(+), 118 deletions(-)

-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/6] PPC: Add asm helpers for BE 32bit load/store
  2014-06-11 10:33 [PATCH 0/6] KVM: PPC: Book3S HV: Enable on little endian hosts Alexander Graf
@ 2014-06-11 10:33 ` Alexander Graf
  2014-06-17  0:51   ` Paul Mackerras
  2014-06-11 10:33 ` [PATCH 2/6] KVM: PPC: Book3S HV: Make HTAB code LE host aware Alexander Graf
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Alexander Graf @ 2014-06-11 10:33 UTC (permalink / raw)
  To: kvm-ppc; +Cc: kvm, anton, Benjamin Herrenschmidt

>From assembly code we might not only have to explicitly BE access 64bit values,
but sometimes also 32bit ones. Add helpers that allow for easy use of lwzx/stwx
in their respective byte-reverse or native form.

Signed-off-by: Alexander Graf <agraf@suse.de>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/asm-compat.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/powerpc/include/asm/asm-compat.h b/arch/powerpc/include/asm/asm-compat.h
index 4b237aa..21164ff 100644
--- a/arch/powerpc/include/asm/asm-compat.h
+++ b/arch/powerpc/include/asm/asm-compat.h
@@ -34,10 +34,14 @@
 #define PPC_MIN_STKFRM	112
 
 #ifdef __BIG_ENDIAN__
+#define LWZX_BE	stringify_in_c(lwzx)
 #define LDX_BE	stringify_in_c(ldx)
+#define STDX_BE	stringify_in_c(stwx)
 #define STDX_BE	stringify_in_c(stdx)
 #else
+#define LWZX_BE	stringify_in_c(lwbrx)
 #define LDX_BE	stringify_in_c(ldbrx)
+#define STWX_BE	stringify_in_c(stwbrx)
 #define STDX_BE	stringify_in_c(stdbrx)
 #endif
 
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/6] KVM: PPC: Book3S HV: Make HTAB code LE host aware
  2014-06-11 10:33 [PATCH 0/6] KVM: PPC: Book3S HV: Enable on little endian hosts Alexander Graf
  2014-06-11 10:33 ` [PATCH 1/6] PPC: Add asm helpers for BE 32bit load/store Alexander Graf
@ 2014-06-11 10:33 ` Alexander Graf
  2014-06-11 10:33 ` [PATCH 3/6] KVM: PPC: Book3S HV: Access guest VPA in BE Alexander Graf
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Alexander Graf @ 2014-06-11 10:33 UTC (permalink / raw)
  To: kvm-ppc; +Cc: kvm, anton

When running on an LE host all data structures are kept in little endian
byte order. However, the HTAB still needs to be maintained in big endian.

So every time we access any HTAB we need to make sure we do so in the right
byte order. Fix up all accesses to manually byte swap.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/include/asm/kvm_book3s_64.h |  14 +++-
 arch/powerpc/kvm/book3s_64_mmu_hv.c      |  95 +++++++++++++-------------
 arch/powerpc/kvm/book3s_hv_rm_mmu.c      | 111 ++++++++++++++++++-------------
 3 files changed, 126 insertions(+), 94 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index fddb72b..2e99a3e 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -61,18 +61,26 @@ extern unsigned long kvm_rma_pages;
 
 static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits)
 {
-	unsigned long tmp, old;
+	unsigned long tmp, old, lockbit;
+
+	/*
+	 * We load/store in native endian, but the HTAB is in big endian. If
+	 * we byte swap all data we apply on the PTE we're implicitly correct
+	 * again.
+	 */
+	lockbit = cpu_to_be64(HPTE_V_HVLOCK);
+	bits = cpu_to_be64(bits);
 
 	asm volatile("	ldarx	%0,0,%2\n"
 		     "	and.	%1,%0,%3\n"
 		     "	bne	2f\n"
-		     "	ori	%0,%0,%4\n"
+		     "	or	%0,%0,%4\n"
 		     "  stdcx.	%0,0,%2\n"
 		     "	beq+	2f\n"
 		     "	mr	%1,%3\n"
 		     "2:	isync"
 		     : "=&r" (tmp), "=&r" (old)
-		     : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK)
+		     : "r" (hpte), "r" (bits), "r" (lockbit)
 		     : "cc", "memory");
 	return old == 0;
 }
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index 8056107..f53cf2e 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -474,12 +474,12 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
 		return -ENOENT;
 	}
 	hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
-	v = hptep[0] & ~HPTE_V_HVLOCK;
+	v = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK;
 	gr = kvm->arch.revmap[index].guest_rpte;
 
 	/* Unlock the HPTE */
 	asm volatile("lwsync" : : : "memory");
-	hptep[0] = v;
+	hptep[0] = cpu_to_be64(v);
 	preempt_enable();
 
 	gpte->eaddr = eaddr;
@@ -611,11 +611,11 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	preempt_disable();
 	while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
 		cpu_relax();
-	hpte[0] = hptep[0] & ~HPTE_V_HVLOCK;
-	hpte[1] = hptep[1];
+	hpte[0] = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK;
+	hpte[1] = be64_to_cpu(hptep[1]);
 	hpte[2] = r = rev->guest_rpte;
 	asm volatile("lwsync" : : : "memory");
-	hptep[0] = hpte[0];
+	hptep[0] = cpu_to_be64(hpte[0]);
 	preempt_enable();
 
 	if (hpte[0] != vcpu->arch.pgfault_hpte[0] ||
@@ -731,8 +731,9 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	preempt_disable();
 	while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
 		cpu_relax();
-	if ((hptep[0] & ~HPTE_V_HVLOCK) != hpte[0] || hptep[1] != hpte[1] ||
-	    rev->guest_rpte != hpte[2])
+	if ((be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK) != hpte[0] ||
+		be64_to_cpu(hptep[1]) != hpte[1] ||
+		rev->guest_rpte != hpte[2])
 		/* HPTE has been changed under us; let the guest retry */
 		goto out_unlock;
 	hpte[0] = (hpte[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID;
@@ -752,20 +753,20 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	rcbits = *rmap >> KVMPPC_RMAP_RC_SHIFT;
 	r &= rcbits | ~(HPTE_R_R | HPTE_R_C);
 
-	if (hptep[0] & HPTE_V_VALID) {
+	if (be64_to_cpu(hptep[0]) & HPTE_V_VALID) {
 		/* HPTE was previously valid, so we need to invalidate it */
 		unlock_rmap(rmap);
-		hptep[0] |= HPTE_V_ABSENT;
+		hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
 		kvmppc_invalidate_hpte(kvm, hptep, index);
 		/* don't lose previous R and C bits */
-		r |= hptep[1] & (HPTE_R_R | HPTE_R_C);
+		r |= be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C);
 	} else {
 		kvmppc_add_revmap_chain(kvm, rev, rmap, index, 0);
 	}
 
-	hptep[1] = r;
+	hptep[1] = cpu_to_be64(r);
 	eieio();
-	hptep[0] = hpte[0];
+	hptep[0] = cpu_to_be64(hpte[0]);
 	asm volatile("ptesync" : : : "memory");
 	preempt_enable();
 	if (page && hpte_is_writable(r))
@@ -784,7 +785,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	return ret;
 
  out_unlock:
-	hptep[0] &= ~HPTE_V_HVLOCK;
+	hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
 	preempt_enable();
 	goto out_put;
 }
@@ -880,7 +881,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
 		if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
 			/* unlock rmap before spinning on the HPTE lock */
 			unlock_rmap(rmapp);
-			while (hptep[0] & HPTE_V_HVLOCK)
+			while (be64_to_cpu(hptep[0]) & HPTE_V_HVLOCK)
 				cpu_relax();
 			continue;
 		}
@@ -899,14 +900,14 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
 
 		/* Now check and modify the HPTE */
 		ptel = rev[i].guest_rpte;
-		psize = hpte_page_size(hptep[0], ptel);
-		if ((hptep[0] & HPTE_V_VALID) &&
+		psize = hpte_page_size(be64_to_cpu(hptep[0]), ptel);
+		if ((be64_to_cpu(hptep[0]) & HPTE_V_VALID) &&
 		    hpte_rpn(ptel, psize) == gfn) {
 			if (kvm->arch.using_mmu_notifiers)
-				hptep[0] |= HPTE_V_ABSENT;
+				hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
 			kvmppc_invalidate_hpte(kvm, hptep, i);
 			/* Harvest R and C */
-			rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C);
+			rcbits = be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C);
 			*rmapp |= rcbits << KVMPPC_RMAP_RC_SHIFT;
 			if (rcbits & ~rev[i].guest_rpte) {
 				rev[i].guest_rpte = ptel | rcbits;
@@ -914,7 +915,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
 			}
 		}
 		unlock_rmap(rmapp);
-		hptep[0] &= ~HPTE_V_HVLOCK;
+		hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
 	}
 	return 0;
 }
@@ -981,19 +982,20 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
 		j = rev[i].forw;
 
 		/* If this HPTE isn't referenced, ignore it */
-		if (!(hptep[1] & HPTE_R_R))
+		if (!(be64_to_cpu(hptep[1]) & HPTE_R_R))
 			continue;
 
 		if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
 			/* unlock rmap before spinning on the HPTE lock */
 			unlock_rmap(rmapp);
-			while (hptep[0] & HPTE_V_HVLOCK)
+			while (be64_to_cpu(hptep[0]) & HPTE_V_HVLOCK)
 				cpu_relax();
 			goto retry;
 		}
 
 		/* Now check and modify the HPTE */
-		if ((hptep[0] & HPTE_V_VALID) && (hptep[1] & HPTE_R_R)) {
+		if ((be64_to_cpu(hptep[0]) & HPTE_V_VALID) &&
+		    (be64_to_cpu(hptep[1]) & HPTE_R_R)) {
 			kvmppc_clear_ref_hpte(kvm, hptep, i);
 			if (!(rev[i].guest_rpte & HPTE_R_R)) {
 				rev[i].guest_rpte |= HPTE_R_R;
@@ -1001,7 +1003,7 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
 			}
 			ret = 1;
 		}
-		hptep[0] &= ~HPTE_V_HVLOCK;
+		hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
 	} while ((i = j) != head);
 
 	unlock_rmap(rmapp);
@@ -1035,7 +1037,7 @@ static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
 		do {
 			hp = (unsigned long *)(kvm->arch.hpt_virt + (i << 4));
 			j = rev[i].forw;
-			if (hp[1] & HPTE_R_R)
+			if (be64_to_cpu(hp[1]) & HPTE_R_R)
 				goto out;
 		} while ((i = j) != head);
 	}
@@ -1091,6 +1093,7 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp)
 
 	i = head = *rmapp & KVMPPC_RMAP_INDEX;
 	do {
+		unsigned long hptep1;
 		hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
 		j = rev[i].forw;
 
@@ -1108,29 +1111,30 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp)
 		 * Otherwise we need to do the tlbie even if C==0 in
 		 * order to pick up any delayed writeback of C.
 		 */
-		if (!(hptep[1] & HPTE_R_C) &&
-		    (!hpte_is_writable(hptep[1]) || vcpus_running(kvm)))
+		hptep1 = be64_to_cpu(hptep[1]);
+		if (!(hptep1 & HPTE_R_C) &&
+		    (!hpte_is_writable(hptep1) || vcpus_running(kvm)))
 			continue;
 
 		if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
 			/* unlock rmap before spinning on the HPTE lock */
 			unlock_rmap(rmapp);
-			while (hptep[0] & HPTE_V_HVLOCK)
+			while (hptep[0] & cpu_to_be64(HPTE_V_HVLOCK))
 				cpu_relax();
 			goto retry;
 		}
 
 		/* Now check and modify the HPTE */
-		if (!(hptep[0] & HPTE_V_VALID))
+		if (!(hptep[0] & cpu_to_be64(HPTE_V_VALID)))
 			continue;
 
 		/* need to make it temporarily absent so C is stable */
-		hptep[0] |= HPTE_V_ABSENT;
+		hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
 		kvmppc_invalidate_hpte(kvm, hptep, i);
-		v = hptep[0];
-		r = hptep[1];
+		v = be64_to_cpu(hptep[0]);
+		r = be64_to_cpu(hptep[1]);
 		if (r & HPTE_R_C) {
-			hptep[1] = r & ~HPTE_R_C;
+			hptep[1] = cpu_to_be64(r & ~HPTE_R_C);
 			if (!(rev[i].guest_rpte & HPTE_R_C)) {
 				rev[i].guest_rpte |= HPTE_R_C;
 				note_hpte_modification(kvm, &rev[i]);
@@ -1143,7 +1147,7 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp)
 		}
 		v &= ~(HPTE_V_ABSENT | HPTE_V_HVLOCK);
 		v |= HPTE_V_VALID;
-		hptep[0] = v;
+		hptep[0] = cpu_to_be64(v);
 	} while ((i = j) != head);
 
 	unlock_rmap(rmapp);
@@ -1316,7 +1320,8 @@ static int hpte_dirty(struct revmap_entry *revp, unsigned long *hptp)
 
 	/* Also need to consider changes in reference and changed bits */
 	rcbits_unset = ~revp->guest_rpte & (HPTE_R_R | HPTE_R_C);
-	if ((hptp[0] & HPTE_V_VALID) && (hptp[1] & rcbits_unset))
+	if ((be64_to_cpu(hptp[0]) & HPTE_V_VALID) &&
+	    (be64_to_cpu(hptp[1]) & rcbits_unset))
 		return 1;
 
 	return 0;
@@ -1337,10 +1342,10 @@ static long record_hpte(unsigned long flags, unsigned long *hptp,
 		return 0;
 
 	valid = 0;
-	if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT)) {
+	if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT)) {
 		valid = 1;
 		if ((flags & KVM_GET_HTAB_BOLTED_ONLY) &&
-		    !(hptp[0] & HPTE_V_BOLTED))
+		    !(be64_to_cpu(hptp[0]) & HPTE_V_BOLTED))
 			valid = 0;
 	}
 	if (valid != want_valid)
@@ -1352,7 +1357,7 @@ static long record_hpte(unsigned long flags, unsigned long *hptp,
 		preempt_disable();
 		while (!try_lock_hpte(hptp, HPTE_V_HVLOCK))
 			cpu_relax();
-		v = hptp[0];
+		v = be64_to_cpu(hptp[0]);
 
 		/* re-evaluate valid and dirty from synchronized HPTE value */
 		valid = !!(v & HPTE_V_VALID);
@@ -1360,9 +1365,9 @@ static long record_hpte(unsigned long flags, unsigned long *hptp,
 
 		/* Harvest R and C into guest view if necessary */
 		rcbits_unset = ~revp->guest_rpte & (HPTE_R_R | HPTE_R_C);
-		if (valid && (rcbits_unset & hptp[1])) {
-			revp->guest_rpte |= (hptp[1] & (HPTE_R_R | HPTE_R_C)) |
-				HPTE_GR_MODIFIED;
+		if (valid && (rcbits_unset & be64_to_cpu(hptp[1]))) {
+			revp->guest_rpte |= (be64_to_cpu(hptp[1]) &
+				(HPTE_R_R | HPTE_R_C)) | HPTE_GR_MODIFIED;
 			dirty = 1;
 		}
 
@@ -1381,13 +1386,13 @@ static long record_hpte(unsigned long flags, unsigned long *hptp,
 			revp->guest_rpte = r;
 		}
 		asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
-		hptp[0] &= ~HPTE_V_HVLOCK;
+		hptp[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
 		preempt_enable();
 		if (!(valid == want_valid && (first_pass || dirty)))
 			ok = 0;
 	}
-	hpte[0] = v;
-	hpte[1] = r;
+	hpte[0] = cpu_to_be64(v);
+	hpte[1] = cpu_to_be64(r);
 	return ok;
 }
 
@@ -1551,7 +1556,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
 			lbuf += 2;
 			nb += HPTE_SIZE;
 
-			if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT))
+			if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT))
 				kvmppc_do_h_remove(kvm, 0, i, 0, tmp);
 			err = -EIO;
 			ret = kvmppc_virtmode_do_h_enter(kvm, H_EXACT, i, v, r,
@@ -1577,7 +1582,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
 		}
 
 		for (j = 0; j < hdr.n_invalid; ++j) {
-			if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT))
+			if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT))
 				kvmppc_do_h_remove(kvm, 0, i, 0, tmp);
 			++i;
 			hptp += 2;
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index ac840c6..87624ab 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -157,7 +157,7 @@ static pte_t lookup_linux_pte_and_update(pgd_t *pgdir, unsigned long hva,
 static inline void unlock_hpte(unsigned long *hpte, unsigned long hpte_v)
 {
 	asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
-	hpte[0] = hpte_v;
+	hpte[0] = cpu_to_be64(hpte_v);
 }
 
 long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
@@ -277,7 +277,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
 		pte_index &= ~7UL;
 		hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
 		for (i = 0; i < 8; ++i) {
-			if ((*hpte & HPTE_V_VALID) == 0 &&
+			if ((be64_to_cpu(*hpte) & HPTE_V_VALID) == 0 &&
 			    try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID |
 					  HPTE_V_ABSENT))
 				break;
@@ -292,11 +292,13 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
 			 */
 			hpte -= 16;
 			for (i = 0; i < 8; ++i) {
+				u64 pte;
 				while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
 					cpu_relax();
-				if (!(*hpte & (HPTE_V_VALID | HPTE_V_ABSENT)))
+				pte = be64_to_cpu(*hpte);
+				if (!(pte & (HPTE_V_VALID | HPTE_V_ABSENT)))
 					break;
-				*hpte &= ~HPTE_V_HVLOCK;
+				*hpte &= ~cpu_to_be64(HPTE_V_HVLOCK);
 				hpte += 2;
 			}
 			if (i == 8)
@@ -308,10 +310,13 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
 		if (!try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID |
 				   HPTE_V_ABSENT)) {
 			/* Lock the slot and check again */
+			u64 pte;
+
 			while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
 				cpu_relax();
-			if (*hpte & (HPTE_V_VALID | HPTE_V_ABSENT)) {
-				*hpte &= ~HPTE_V_HVLOCK;
+			pte = be64_to_cpu(*hpte);
+			if (pte & (HPTE_V_VALID | HPTE_V_ABSENT)) {
+				*hpte &= ~cpu_to_be64(HPTE_V_HVLOCK);
 				return H_PTEG_FULL;
 			}
 		}
@@ -347,11 +352,11 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
 		}
 	}
 
-	hpte[1] = ptel;
+	hpte[1] = cpu_to_be64(ptel);
 
 	/* Write the first HPTE dword, unlocking the HPTE and making it valid */
 	eieio();
-	hpte[0] = pteh;
+	hpte[0] = cpu_to_be64(pteh);
 	asm volatile("ptesync" : : : "memory");
 
 	*pte_idx_ret = pte_index;
@@ -471,34 +476,39 @@ long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags,
 	unsigned long *hpte;
 	unsigned long v, r, rb;
 	struct revmap_entry *rev;
+	u64 pte;
 
 	if (pte_index >= kvm->arch.hpt_npte)
 		return H_PARAMETER;
 	hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
 	while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
 		cpu_relax();
-	if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
-	    ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn) ||
-	    ((flags & H_ANDCOND) && (hpte[0] & avpn) != 0)) {
-		hpte[0] &= ~HPTE_V_HVLOCK;
+	pte = be64_to_cpu(hpte[0]);
+	if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
+	    ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn) ||
+	    ((flags & H_ANDCOND) && (pte & avpn) != 0)) {
+		hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
 		return H_NOT_FOUND;
 	}
 
 	rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
-	v = hpte[0] & ~HPTE_V_HVLOCK;
+	v = pte & ~HPTE_V_HVLOCK;
 	if (v & HPTE_V_VALID) {
-		hpte[0] &= ~HPTE_V_VALID;
-		rb = compute_tlbie_rb(v, hpte[1], pte_index);
+		u64 pte1;
+
+		pte1 = be64_to_cpu(hpte[1]);
+		hpte[0] &= ~cpu_to_be64(HPTE_V_VALID);
+		rb = compute_tlbie_rb(v, pte1, pte_index);
 		do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true);
 		/* Read PTE low word after tlbie to get final R/C values */
-		remove_revmap_chain(kvm, pte_index, rev, v, hpte[1]);
+		remove_revmap_chain(kvm, pte_index, rev, v, pte1);
 	}
 	r = rev->guest_rpte & ~HPTE_GR_RESERVED;
 	note_hpte_modification(kvm, rev);
 	unlock_hpte(hpte, 0);
 
-	hpret[0] = v;
-	hpret[1] = r;
+	hpret[0] = cpu_to_be64(v);
+	hpret[1] = cpu_to_be64(r);
 	return H_SUCCESS;
 }
 EXPORT_SYMBOL_GPL(kvmppc_do_h_remove);
@@ -520,6 +530,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
 	int global;
 	long int ret = H_SUCCESS;
 	struct revmap_entry *rev, *revs[4];
+	u64 hp0;
 
 	global = global_invalidates(kvm, 0);
 	for (i = 0; i < 4 && ret == H_SUCCESS; ) {
@@ -552,23 +563,24 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
 					cpu_relax();
 			}
 			found = 0;
-			if (hp[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) {
+			hp0 = be64_to_cpu(hp[0]);
+			if (hp0 & (HPTE_V_ABSENT | HPTE_V_VALID)) {
 				switch (flags & 3) {
 				case 0:		/* absolute */
 					found = 1;
 					break;
 				case 1:		/* andcond */
-					if (!(hp[0] & args[j + 1]))
+					if (!(hp0 & args[j + 1]))
 						found = 1;
 					break;
 				case 2:		/* AVPN */
-					if ((hp[0] & ~0x7fUL) == args[j + 1])
+					if ((hp0 & ~0x7fUL) == args[j + 1])
 						found = 1;
 					break;
 				}
 			}
 			if (!found) {
-				hp[0] &= ~HPTE_V_HVLOCK;
+				hp[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
 				args[j] = ((0x90 | flags) << 56) + pte_index;
 				continue;
 			}
@@ -577,7 +589,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
 			rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
 			note_hpte_modification(kvm, rev);
 
-			if (!(hp[0] & HPTE_V_VALID)) {
+			if (!(hp0 & HPTE_V_VALID)) {
 				/* insert R and C bits from PTE */
 				rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
 				args[j] |= rcbits << (56 - 5);
@@ -585,8 +597,10 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
 				continue;
 			}
 
-			hp[0] &= ~HPTE_V_VALID;		/* leave it locked */
-			tlbrb[n] = compute_tlbie_rb(hp[0], hp[1], pte_index);
+			/* leave it locked */
+			hp[0] &= ~cpu_to_be64(HPTE_V_VALID);
+			tlbrb[n] = compute_tlbie_rb(be64_to_cpu(hp[0]),
+				be64_to_cpu(hp[1]), pte_index);
 			indexes[n] = j;
 			hptes[n] = hp;
 			revs[n] = rev;
@@ -605,7 +619,8 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
 			pte_index = args[j] & ((1ul << 56) - 1);
 			hp = hptes[k];
 			rev = revs[k];
-			remove_revmap_chain(kvm, pte_index, rev, hp[0], hp[1]);
+			remove_revmap_chain(kvm, pte_index, rev,
+				be64_to_cpu(hp[0]), be64_to_cpu(hp[1]));
 			rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
 			args[j] |= rcbits << (56 - 5);
 			hp[0] = 0;
@@ -623,6 +638,7 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
 	unsigned long *hpte;
 	struct revmap_entry *rev;
 	unsigned long v, r, rb, mask, bits;
+	u64 pte;
 
 	if (pte_index >= kvm->arch.hpt_npte)
 		return H_PARAMETER;
@@ -630,13 +646,14 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
 	hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
 	while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
 		cpu_relax();
-	if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
-	    ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn)) {
-		hpte[0] &= ~HPTE_V_HVLOCK;
+	pte = be64_to_cpu(hpte[0]);
+	if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
+	    ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn)) {
+		hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
 		return H_NOT_FOUND;
 	}
 
-	v = hpte[0];
+	v = pte;
 	bits = (flags << 55) & HPTE_R_PP0;
 	bits |= (flags << 48) & HPTE_R_KEY_HI;
 	bits |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
@@ -650,12 +667,12 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
 		rev->guest_rpte = r;
 		note_hpte_modification(kvm, rev);
 	}
-	r = (hpte[1] & ~mask) | bits;
+	r = (be64_to_cpu(hpte[1]) & ~mask) | bits;
 
 	/* Update HPTE */
 	if (v & HPTE_V_VALID) {
 		rb = compute_tlbie_rb(v, r, pte_index);
-		hpte[0] = v & ~HPTE_V_VALID;
+		hpte[0] = cpu_to_be64(v & ~HPTE_V_VALID);
 		do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true);
 		/*
 		 * If the host has this page as readonly but the guest
@@ -681,9 +698,9 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
 			}
 		}
 	}
-	hpte[1] = r;
+	hpte[1] = cpu_to_be64(r);
 	eieio();
-	hpte[0] = v & ~HPTE_V_HVLOCK;
+	hpte[0] = cpu_to_be64(v & ~HPTE_V_HVLOCK);
 	asm volatile("ptesync" : : : "memory");
 	return H_SUCCESS;
 }
@@ -705,8 +722,8 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
 	rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
 	for (i = 0; i < n; ++i, ++pte_index) {
 		hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
-		v = hpte[0] & ~HPTE_V_HVLOCK;
-		r = hpte[1];
+		v = be64_to_cpu(hpte[0]) & ~HPTE_V_HVLOCK;
+		r = be64_to_cpu(hpte[1]);
 		if (v & HPTE_V_ABSENT) {
 			v &= ~HPTE_V_ABSENT;
 			v |= HPTE_V_VALID;
@@ -726,8 +743,9 @@ void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep,
 {
 	unsigned long rb;
 
-	hptep[0] &= ~HPTE_V_VALID;
-	rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index);
+	hptep[0] &= ~cpu_to_be64(HPTE_V_VALID);
+	rb = compute_tlbie_rb(be64_to_cpu(hptep[0]), be64_to_cpu(hptep[1]),
+			      pte_index);
 	do_tlbies(kvm, &rb, 1, 1, true);
 }
 EXPORT_SYMBOL_GPL(kvmppc_invalidate_hpte);
@@ -738,8 +756,9 @@ void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep,
 	unsigned long rb;
 	unsigned char rbyte;
 
-	rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index);
-	rbyte = (hptep[1] & ~HPTE_R_R) >> 8;
+	rb = compute_tlbie_rb(be64_to_cpu(hptep[0]), be64_to_cpu(hptep[1]),
+			      pte_index);
+	rbyte = (be64_to_cpu(hptep[1]) & ~HPTE_R_R) >> 8;
 	/* modify only the second-last byte, which contains the ref bit */
 	*((char *)hptep + 14) = rbyte;
 	do_tlbies(kvm, &rb, 1, 1, false);
@@ -801,7 +820,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
 
 		for (i = 0; i < 16; i += 2) {
 			/* Read the PTE racily */
-			v = hpte[i] & ~HPTE_V_HVLOCK;
+			v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK;
 
 			/* Check valid/absent, hash, segment size and AVPN */
 			if (!(v & valid) || (v & mask) != val)
@@ -810,8 +829,8 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
 			/* Lock the PTE and read it under the lock */
 			while (!try_lock_hpte(&hpte[i], HPTE_V_HVLOCK))
 				cpu_relax();
-			v = hpte[i] & ~HPTE_V_HVLOCK;
-			r = hpte[i+1];
+			v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK;
+			r = be64_to_cpu(hpte[i+1]);
 
 			/*
 			 * Check the HPTE again, including large page size
@@ -825,7 +844,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
 				return (hash << 3) + (i >> 1);
 
 			/* Unlock and move on */
-			hpte[i] = v;
+			hpte[i] = cpu_to_be64(v);
 		}
 
 		if (val & HPTE_V_SECONDARY)
@@ -871,8 +890,8 @@ long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
 		return 0;		/* for prot fault, HPTE disappeared */
 	}
 	hpte = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
-	v = hpte[0] & ~HPTE_V_HVLOCK;
-	r = hpte[1];
+	v = be64_to_cpu(hpte[0]) & ~HPTE_V_HVLOCK;
+	r = be64_to_cpu(hpte[1]);
 	rev = real_vmalloc_addr(&kvm->arch.revmap[index]);
 	gr = rev->guest_rpte;
 
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/6] KVM: PPC: Book3S HV: Access guest VPA in BE
  2014-06-11 10:33 [PATCH 0/6] KVM: PPC: Book3S HV: Enable on little endian hosts Alexander Graf
  2014-06-11 10:33 ` [PATCH 1/6] PPC: Add asm helpers for BE 32bit load/store Alexander Graf
  2014-06-11 10:33 ` [PATCH 2/6] KVM: PPC: Book3S HV: Make HTAB code LE host aware Alexander Graf
@ 2014-06-11 10:33 ` Alexander Graf
  2014-06-11 10:33 ` [PATCH 4/6] KVM: PPC: Book3S HV: Access host lppaca and shadow slb " Alexander Graf
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Alexander Graf @ 2014-06-11 10:33 UTC (permalink / raw)
  To: kvm-ppc; +Cc: kvm, anton

There are a few shared data structures between the host and the guest. Most
of them get registered through the VPA interface.

These data structures are defined to always be in big endian byte order, so
let's make sure we always access them in big endian.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/kvm/book3s_hv.c     | 16 ++++++++--------
 arch/powerpc/kvm/book3s_hv_ras.c |  6 +++---
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index c38cf9f..f8640f4 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -270,7 +270,7 @@ struct kvm_vcpu *kvmppc_find_vcpu(struct kvm *kvm, int id)
 static void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa)
 {
 	vpa->__old_status |= LPPACA_OLD_SHARED_PROC;
-	vpa->yield_count = 1;
+	vpa->yield_count = cpu_to_be32(1);
 }
 
 static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v,
@@ -333,9 +333,9 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu,
 		if (va == NULL)
 			return H_PARAMETER;
 		if (subfunc == H_VPA_REG_VPA)
-			len = ((struct reg_vpa *)va)->length.hword;
+			len = be16_to_cpu(((struct reg_vpa *)va)->length.hword);
 		else
-			len = ((struct reg_vpa *)va)->length.word;
+			len = be32_to_cpu(((struct reg_vpa *)va)->length.word);
 		kvmppc_unpin_guest_page(kvm, va, vpa, false);
 
 		/* Check length */
@@ -540,11 +540,11 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu,
 		return;
 	memset(dt, 0, sizeof(struct dtl_entry));
 	dt->dispatch_reason = 7;
-	dt->processor_id = vc->pcpu + vcpu->arch.ptid;
-	dt->timebase = now + vc->tb_offset;
-	dt->enqueue_to_dispatch_time = stolen;
-	dt->srr0 = kvmppc_get_pc(vcpu);
-	dt->srr1 = vcpu->arch.shregs.msr;
+	dt->processor_id = cpu_to_be16(vc->pcpu + vcpu->arch.ptid);
+	dt->timebase = cpu_to_be64(now + vc->tb_offset);
+	dt->enqueue_to_dispatch_time = cpu_to_be32(stolen);
+	dt->srr0 = cpu_to_be64(kvmppc_get_pc(vcpu));
+	dt->srr1 = cpu_to_be64(vcpu->arch.shregs.msr);
 	++dt;
 	if (dt == vcpu->arch.dtl.pinned_end)
 		dt = vcpu->arch.dtl.pinned_addr;
diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c
index 768a9f9..6a3ba8a 100644
--- a/arch/powerpc/kvm/book3s_hv_ras.c
+++ b/arch/powerpc/kvm/book3s_hv_ras.c
@@ -45,14 +45,14 @@ static void reload_slb(struct kvm_vcpu *vcpu)
 		return;
 
 	/* Sanity check */
-	n = min_t(u32, slb->persistent, SLB_MIN_SIZE);
+	n = min_t(u32, be32_to_cpu(slb->persistent), SLB_MIN_SIZE);
 	if ((void *) &slb->save_area[n] > vcpu->arch.slb_shadow.pinned_end)
 		return;
 
 	/* Load up the SLB from that */
 	for (i = 0; i < n; ++i) {
-		unsigned long rb = slb->save_area[i].esid;
-		unsigned long rs = slb->save_area[i].vsid;
+		unsigned long rb = be64_to_cpu(slb->save_area[i].esid);
+		unsigned long rs = be64_to_cpu(slb->save_area[i].vsid);
 
 		rb = (rb & ~0xFFFul) | i;	/* insert entry number */
 		asm volatile("slbmte %0,%1" : : "r" (rs), "r" (rb));
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 4/6] KVM: PPC: Book3S HV: Access host lppaca and shadow slb in BE
  2014-06-11 10:33 [PATCH 0/6] KVM: PPC: Book3S HV: Enable on little endian hosts Alexander Graf
                   ` (2 preceding siblings ...)
  2014-06-11 10:33 ` [PATCH 3/6] KVM: PPC: Book3S HV: Access guest VPA in BE Alexander Graf
@ 2014-06-11 10:33 ` Alexander Graf
  2014-06-11 10:33 ` [PATCH 5/6] KVM: PPC: Book3S HV: Access XICS " Alexander Graf
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Alexander Graf @ 2014-06-11 10:33 UTC (permalink / raw)
  To: kvm-ppc; +Cc: kvm, anton

Some data structures are always stored in big endian. Among those are the LPPACA
fields as well as the shadow slb. These structures might be shared with a
hypervisor.

So whenever we access those fields, make sure we do so in big endian byte order.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/kvm/book3s_hv_rmhandlers.S | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 220aefb..3530d06 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -32,10 +32,6 @@
 
 #define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM)
 
-#ifdef __LITTLE_ENDIAN__
-#error Need to fix lppaca and SLB shadow accesses in little endian mode
-#endif
-
 /* Values in HSTATE_NAPPING(r13) */
 #define NAPPING_CEDE	1
 #define NAPPING_NOVCPU	2
@@ -585,9 +581,10 @@ kvmppc_got_guest:
 	ld	r3, VCPU_VPA(r4)
 	cmpdi	r3, 0
 	beq	25f
-	lwz	r5, LPPACA_YIELDCOUNT(r3)
+	li	r6, LPPACA_YIELDCOUNT
+	LWZX_BE	r5, r3, r6
 	addi	r5, r5, 1
-	stw	r5, LPPACA_YIELDCOUNT(r3)
+	STWX_BE	r5, r3, r6
 	li	r6, 1
 	stb	r6, VCPU_VPA_DIRTY(r4)
 25:
@@ -1328,9 +1325,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 	ld	r8, VCPU_VPA(r9)	/* do they have a VPA? */
 	cmpdi	r8, 0
 	beq	25f
-	lwz	r3, LPPACA_YIELDCOUNT(r8)
+	li	r4, LPPACA_YIELDCOUNT
+	LWZX_BE	r3, r8, r4
 	addi	r3, r3, 1
-	stw	r3, LPPACA_YIELDCOUNT(r8)
+	STWX_BE	r3, r8, r4
 	li	r3, 1
 	stb	r3, VCPU_VPA_DIRTY(r9)
 25:
@@ -1643,8 +1641,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 33:	ld	r8,PACA_SLBSHADOWPTR(r13)
 
 	.rept	SLB_NUM_BOLTED
-	ld	r5,SLBSHADOW_SAVEAREA(r8)
-	ld	r6,SLBSHADOW_SAVEAREA+8(r8)
+	li	r3, SLBSHADOW_SAVEAREA
+	LDX_BE	r5, r8, r3
+	addi	r3, r3, 8
+	LDX_BE	r6, r8, r3
 	andis.	r7,r5,SLB_ESID_V@h
 	beq	1f
 	slbmte	r6,r5
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 5/6] KVM: PPC: Book3S HV: Access XICS in BE
  2014-06-11 10:33 [PATCH 0/6] KVM: PPC: Book3S HV: Enable on little endian hosts Alexander Graf
                   ` (3 preceding siblings ...)
  2014-06-11 10:33 ` [PATCH 4/6] KVM: PPC: Book3S HV: Access host lppaca and shadow slb " Alexander Graf
@ 2014-06-11 10:33 ` Alexander Graf
  2014-06-17  1:02   ` Paul Mackerras
  2014-06-11 10:33 ` [PATCH 6/6] KVM: PPC: Book3S HV: Enable for little endian hosts Alexander Graf
  2014-06-16  4:22 ` [PATCH 0/6] KVM: PPC: Book3S HV: Enable on " Aneesh Kumar K.V
  6 siblings, 1 reply; 16+ messages in thread
From: Alexander Graf @ 2014-06-11 10:33 UTC (permalink / raw)
  To: kvm-ppc; +Cc: kvm, anton

On the exit path from the guest we check what type of interrupt we received
if we received one. This means we're doing hardware access to the XICS interrupt
controller.

However, when running on a little endian system, this access is byte reversed.

So let's make sure to swizzle the bytes back again and virtuall make XICS
accesses big endian.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/kvm/book3s_hv_rmhandlers.S | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 3530d06..40dec37 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -36,6 +36,13 @@
 #define NAPPING_CEDE	1
 #define NAPPING_NOVCPU	2
 
+.macro bswap32 regd, regs
+	srwi	\regd,\regs,24
+	rlwimi	\regd,\regs,24,16,23
+	rlwimi	\regd,\regs,8,8,15
+	rlwimi	\regd,\regs,24,0,7
+.endm
+
 /*
  * Call kvmppc_hv_entry in real mode.
  * Must be called with interrupts hard-disabled.
@@ -2206,7 +2213,12 @@ kvmppc_read_intr:
 	cmpdi	r6, 0
 	beq-	1f
 	lwzcix	r0, r6, r7
-	rlwinm.	r3, r0, 0, 0xffffff
+#ifdef __LITTLE_ENDIAN__
+	bswap32	r3, r0
+#else
+	mr	r3, r0
+#endif
+	rlwinm.	r3, r3, 0, 0xffffff
 	sync
 	beq	1f			/* if nothing pending in the ICP */
 
@@ -2241,7 +2253,8 @@ kvmppc_read_intr:
 42:	/* It's not an IPI and it's for the host, stash it in the PACA
 	 * before exit, it will be picked up by the host ICP driver
 	 */
-	stw	r0, HSTATE_SAVED_XIRR(r13)
+	li	r4, HSTATE_SAVED_XIRR
+	STWX_BE	r0, r13, r4
 	li	r3, 1
 	b	1b
 
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 6/6] KVM: PPC: Book3S HV: Enable for little endian hosts
  2014-06-11 10:33 [PATCH 0/6] KVM: PPC: Book3S HV: Enable on little endian hosts Alexander Graf
                   ` (4 preceding siblings ...)
  2014-06-11 10:33 ` [PATCH 5/6] KVM: PPC: Book3S HV: Access XICS " Alexander Graf
@ 2014-06-11 10:33 ` Alexander Graf
  2014-06-16  4:22 ` [PATCH 0/6] KVM: PPC: Book3S HV: Enable on " Aneesh Kumar K.V
  6 siblings, 0 replies; 16+ messages in thread
From: Alexander Graf @ 2014-06-11 10:33 UTC (permalink / raw)
  To: kvm-ppc; +Cc: kvm, anton

Now that we've fixed all the issues that HV KVM code had on little endian
hosts, we can enable it in the kernel configuration for users to play with.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/kvm/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index d6a53b9..8aeeda1 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -75,7 +75,6 @@ config KVM_BOOK3S_64
 config KVM_BOOK3S_64_HV
 	tristate "KVM support for POWER7 and PPC970 using hypervisor mode in host"
 	depends on KVM_BOOK3S_64
-	depends on !CPU_LITTLE_ENDIAN
 	select KVM_BOOK3S_HV_POSSIBLE
 	select MMU_NOTIFIER
 	select CMA
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH 0/6] KVM: PPC: Book3S HV: Enable on little endian hosts
  2014-06-11 10:33 [PATCH 0/6] KVM: PPC: Book3S HV: Enable on little endian hosts Alexander Graf
                   ` (5 preceding siblings ...)
  2014-06-11 10:33 ` [PATCH 6/6] KVM: PPC: Book3S HV: Enable for little endian hosts Alexander Graf
@ 2014-06-16  4:22 ` Aneesh Kumar K.V
  2014-06-16 12:17   ` Alexander Graf
  6 siblings, 1 reply; 16+ messages in thread
From: Aneesh Kumar K.V @ 2014-06-16  4:22 UTC (permalink / raw)
  To: Alexander Graf, kvm-ppc; +Cc: kvm, anton

Alexander Graf <agraf@suse.de> writes:

> So far we've been able to successfully run HV KVM on big endian hosts, but
> once you dive into little endian land things start to fall apart.
>
> This patch set enables HV KVM for little endian hosts. This should be the
> final piece left missing to get little endian systems fully en par with big
> endian ones in the KVM world.

Can we also use types like __be64 where we need them ? That will also
make sure that tools like sparse can catch errors ?

-aneesh

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 0/6] KVM: PPC: Book3S HV: Enable on little endian hosts
  2014-06-16  4:22 ` [PATCH 0/6] KVM: PPC: Book3S HV: Enable on " Aneesh Kumar K.V
@ 2014-06-16 12:17   ` Alexander Graf
  0 siblings, 0 replies; 16+ messages in thread
From: Alexander Graf @ 2014-06-16 12:17 UTC (permalink / raw)
  To: Aneesh Kumar K.V, kvm-ppc; +Cc: kvm, anton


On 16.06.14 06:22, Aneesh Kumar K.V wrote:
> Alexander Graf <agraf@suse.de> writes:
>
>> So far we've been able to successfully run HV KVM on big endian hosts, but
>> once you dive into little endian land things start to fall apart.
>>
>> This patch set enables HV KVM for little endian hosts. This should be the
>> final piece left missing to get little endian systems fully en par with big
>> endian ones in the KVM world.
> Can we also use types like __be64 where we need them ? That will also
> make sure that tools like sparse can catch errors ?

Great idea :). Will do.


Alex


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/6] PPC: Add asm helpers for BE 32bit load/store
  2014-06-11 10:33 ` [PATCH 1/6] PPC: Add asm helpers for BE 32bit load/store Alexander Graf
@ 2014-06-17  0:51   ` Paul Mackerras
  2014-06-17  8:34     ` Alexander Graf
  0 siblings, 1 reply; 16+ messages in thread
From: Paul Mackerras @ 2014-06-17  0:51 UTC (permalink / raw)
  To: Alexander Graf; +Cc: kvm-ppc, kvm, anton, Benjamin Herrenschmidt

On Wed, Jun 11, 2014 at 12:33:46PM +0200, Alexander Graf wrote:
> >From assembly code we might not only have to explicitly BE access 64bit values,
> but sometimes also 32bit ones. Add helpers that allow for easy use of lwzx/stwx
> in their respective byte-reverse or native form.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
>  arch/powerpc/include/asm/asm-compat.h | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/arch/powerpc/include/asm/asm-compat.h b/arch/powerpc/include/asm/asm-compat.h
> index 4b237aa..21164ff 100644
> --- a/arch/powerpc/include/asm/asm-compat.h
> +++ b/arch/powerpc/include/asm/asm-compat.h
> @@ -34,10 +34,14 @@
>  #define PPC_MIN_STKFRM	112
>  
>  #ifdef __BIG_ENDIAN__
> +#define LWZX_BE	stringify_in_c(lwzx)
>  #define LDX_BE	stringify_in_c(ldx)
> +#define STDX_BE	stringify_in_c(stwx)

This should be STWX_BE, shouldn't it?

>  #define STDX_BE	stringify_in_c(stdx)
>  #else
> +#define LWZX_BE	stringify_in_c(lwbrx)
>  #define LDX_BE	stringify_in_c(ldbrx)
> +#define STWX_BE	stringify_in_c(stwbrx)
>  #define STDX_BE	stringify_in_c(stdbrx)
>  #endif

Paul.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 5/6] KVM: PPC: Book3S HV: Access XICS in BE
  2014-06-11 10:33 ` [PATCH 5/6] KVM: PPC: Book3S HV: Access XICS " Alexander Graf
@ 2014-06-17  1:02   ` Paul Mackerras
  2014-06-17  8:37     ` Alexander Graf
  0 siblings, 1 reply; 16+ messages in thread
From: Paul Mackerras @ 2014-06-17  1:02 UTC (permalink / raw)
  To: Alexander Graf; +Cc: kvm-ppc, kvm, anton

On Wed, Jun 11, 2014 at 12:33:50PM +0200, Alexander Graf wrote:
> On the exit path from the guest we check what type of interrupt we received
> if we received one. This means we're doing hardware access to the XICS interrupt
> controller.
> 
> However, when running on a little endian system, this access is byte reversed.
> 
> So let's make sure to swizzle the bytes back again and virtuall make XICS
> accesses big endian.
...

> @@ -2241,7 +2253,8 @@ kvmppc_read_intr:
>  42:	/* It's not an IPI and it's for the host, stash it in the PACA
>  	 * before exit, it will be picked up by the host ICP driver
>  	 */
> -	stw	r0, HSTATE_SAVED_XIRR(r13)
> +	li	r4, HSTATE_SAVED_XIRR
> +	STWX_BE	r0, r13, r4

This is a paca field, not something mandated by PAPR or shared with
the guest, so why do we need to keep it BE?  If you do make it BE,
don't you also need to fix kvmppc_get_xics_latch()?

Paul.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/6] PPC: Add asm helpers for BE 32bit load/store
  2014-06-17  0:51   ` Paul Mackerras
@ 2014-06-17  8:34     ` Alexander Graf
  0 siblings, 0 replies; 16+ messages in thread
From: Alexander Graf @ 2014-06-17  8:34 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: kvm-ppc, kvm, anton, Benjamin Herrenschmidt


On 17.06.14 02:51, Paul Mackerras wrote:
> On Wed, Jun 11, 2014 at 12:33:46PM +0200, Alexander Graf wrote:
>> >From assembly code we might not only have to explicitly BE access 64bit values,
>> but sometimes also 32bit ones. Add helpers that allow for easy use of lwzx/stwx
>> in their respective byte-reverse or native form.
>>
>> Signed-off-by: Alexander Graf <agraf@suse.de>
>> CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> ---
>>   arch/powerpc/include/asm/asm-compat.h | 4 ++++
>>   1 file changed, 4 insertions(+)
>>
>> diff --git a/arch/powerpc/include/asm/asm-compat.h b/arch/powerpc/include/asm/asm-compat.h
>> index 4b237aa..21164ff 100644
>> --- a/arch/powerpc/include/asm/asm-compat.h
>> +++ b/arch/powerpc/include/asm/asm-compat.h
>> @@ -34,10 +34,14 @@
>>   #define PPC_MIN_STKFRM	112
>>   
>>   #ifdef __BIG_ENDIAN__
>> +#define LWZX_BE	stringify_in_c(lwzx)
>>   #define LDX_BE	stringify_in_c(ldx)
>> +#define STDX_BE	stringify_in_c(stwx)
> This should be STWX_BE, shouldn't it?

And there I thought I would get away without anyone noticing it :). Yes, 
of course.


Alex


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 5/6] KVM: PPC: Book3S HV: Access XICS in BE
  2014-06-17  1:02   ` Paul Mackerras
@ 2014-06-17  8:37     ` Alexander Graf
  2014-06-17 10:22       ` Alexander Graf
  0 siblings, 1 reply; 16+ messages in thread
From: Alexander Graf @ 2014-06-17  8:37 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: kvm-ppc, kvm, anton


On 17.06.14 03:02, Paul Mackerras wrote:
> On Wed, Jun 11, 2014 at 12:33:50PM +0200, Alexander Graf wrote:
>> On the exit path from the guest we check what type of interrupt we received
>> if we received one. This means we're doing hardware access to the XICS interrupt
>> controller.
>>
>> However, when running on a little endian system, this access is byte reversed.
>>
>> So let's make sure to swizzle the bytes back again and virtuall make XICS
>> accesses big endian.
> ...
>
>> @@ -2241,7 +2253,8 @@ kvmppc_read_intr:
>>   42:	/* It's not an IPI and it's for the host, stash it in the PACA
>>   	 * before exit, it will be picked up by the host ICP driver
>>   	 */
>> -	stw	r0, HSTATE_SAVED_XIRR(r13)
>> +	li	r4, HSTATE_SAVED_XIRR
>> +	STWX_BE	r0, r13, r4
> This is a paca field, not something mandated by PAPR or shared with
> the guest, so why do we need to keep it BE?  If you do make it BE,
> don't you also need to fix kvmppc_get_xics_latch()?

Yikes. Yes. Thanks a lot for the catch!


Alex

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 5/6] KVM: PPC: Book3S HV: Access XICS in BE
  2014-06-17  8:37     ` Alexander Graf
@ 2014-06-17 10:22       ` Alexander Graf
  2014-06-17 12:13         ` Paul Mackerras
  0 siblings, 1 reply; 16+ messages in thread
From: Alexander Graf @ 2014-06-17 10:22 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: kvm-ppc, kvm, anton


On 17.06.14 10:37, Alexander Graf wrote:
>
> On 17.06.14 03:02, Paul Mackerras wrote:
>> On Wed, Jun 11, 2014 at 12:33:50PM +0200, Alexander Graf wrote:
>>> On the exit path from the guest we check what type of interrupt we 
>>> received
>>> if we received one. This means we're doing hardware access to the 
>>> XICS interrupt
>>> controller.
>>>
>>> However, when running on a little endian system, this access is byte 
>>> reversed.
>>>
>>> So let's make sure to swizzle the bytes back again and virtuall make 
>>> XICS
>>> accesses big endian.
>> ...
>>
>>> @@ -2241,7 +2253,8 @@ kvmppc_read_intr:
>>>   42:    /* It's not an IPI and it's for the host, stash it in the PACA
>>>        * before exit, it will be picked up by the host ICP driver
>>>        */
>>> -    stw    r0, HSTATE_SAVED_XIRR(r13)
>>> +    li    r4, HSTATE_SAVED_XIRR
>>> +    STWX_BE    r0, r13, r4
>> This is a paca field, not something mandated by PAPR or shared with
>> the guest, so why do we need to keep it BE?  If you do make it BE,
>> don't you also need to fix kvmppc_get_xics_latch()?
>
> Yikes. Yes. Thanks a lot for the catch!

Eh, no. What we do is we read (good on BE, byte reversed) into r0. Then 
we swab32() from r0 to r3 on LE, mr from r0 to r3 on BE.

r3 gets truncated along the way.

The reason we maintain r0 as wrong-endian is that we write it back using 
the cache inhibited stwcix instruction:

>         stwcix  r0, r6, r7              /* EOI it */

So during the lifetime of r0 as XIRR it's always byte-reversed on LE. 
That's why we store it using STWX_BE into hstate, because that's the 
time when we actually swab32() it for further interpretation.

Alternatively I could clobber a different register and maintain the byte 
swapped variant in there if you prefer.


Alex

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 5/6] KVM: PPC: Book3S HV: Access XICS in BE
  2014-06-17 10:22       ` Alexander Graf
@ 2014-06-17 12:13         ` Paul Mackerras
  2014-06-17 12:14           ` Alexander Graf
  0 siblings, 1 reply; 16+ messages in thread
From: Paul Mackerras @ 2014-06-17 12:13 UTC (permalink / raw)
  To: Alexander Graf; +Cc: kvm-ppc, kvm, anton

On Tue, Jun 17, 2014 at 12:22:32PM +0200, Alexander Graf wrote:
> 
> Eh, no. What we do is we read (good on BE, byte reversed) into r0. Then we
> swab32() from r0 to r3 on LE, mr from r0 to r3 on BE.
> 
> r3 gets truncated along the way.
> 
> The reason we maintain r0 as wrong-endian is that we write it back using the
> cache inhibited stwcix instruction:
> 
> >        stwcix  r0, r6, r7              /* EOI it */
> 
> So during the lifetime of r0 as XIRR it's always byte-reversed on LE. That's
> why we store it using STWX_BE into hstate, because that's the time when we
> actually swab32() it for further interpretation.

So the STWX_BE is more like a be32_to_cpu than a cpu_to_be32, which is
what the name STWX_BE would suggest.  Sounds like it at least deserves
a comment, or (as you suggest) rearrange the register usage so a
normal store works.

Paul.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 5/6] KVM: PPC: Book3S HV: Access XICS in BE
  2014-06-17 12:13         ` Paul Mackerras
@ 2014-06-17 12:14           ` Alexander Graf
  0 siblings, 0 replies; 16+ messages in thread
From: Alexander Graf @ 2014-06-17 12:14 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: kvm-ppc, kvm, anton


On 17.06.14 14:13, Paul Mackerras wrote:
> On Tue, Jun 17, 2014 at 12:22:32PM +0200, Alexander Graf wrote:
>> Eh, no. What we do is we read (good on BE, byte reversed) into r0. Then we
>> swab32() from r0 to r3 on LE, mr from r0 to r3 on BE.
>>
>> r3 gets truncated along the way.
>>
>> The reason we maintain r0 as wrong-endian is that we write it back using the
>> cache inhibited stwcix instruction:
>>
>>>         stwcix  r0, r6, r7              /* EOI it */
>> So during the lifetime of r0 as XIRR it's always byte-reversed on LE. That's
>> why we store it using STWX_BE into hstate, because that's the time when we
>> actually swab32() it for further interpretation.
> So the STWX_BE is more like a be32_to_cpu than a cpu_to_be32, which is
> what the name STWX_BE would suggest.  Sounds like it at least deserves
> a comment, or (as you suggest) rearrange the register usage so a
> normal store works.

Yes, I have this now:


 From a94a66437ec714ec5650f6d8fec050a33e4477ca Mon Sep 17 00:00:00 2001
From: Alexander Graf <agraf@suse.de>
Date: Wed, 11 Jun 2014 10:37:52 +0200
Subject: [PATCH] KVM: PPC: Book3S HV: Access XICS in BE

On the exit path from the guest we check what type of interrupt we received
if we received one. This means we're doing hardware access to the XICS 
interrupt
controller.

However, when running on a little endian system, this access is byte 
reversed.

So let's make sure to swizzle the bytes back again and virtually make XICS
accesses big endian.

Signed-off-by: Alexander Graf <agraf@suse.de>

---

v1 -> v2:

   - Make code easier to follow

diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S 
b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 1a2f471..9829e18 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -36,6 +36,13 @@
  #define NAPPING_CEDE    1
  #define NAPPING_NOVCPU    2

+.macro bswap32 regd, regs
+    srwi    \regd,\regs,24
+    rlwimi    \regd,\regs,24,16,23
+    rlwimi    \regd,\regs,8,8,15
+    rlwimi    \regd,\regs,24,0,7
+.endm
+
  /*
   * Call kvmppc_hv_entry in real mode.
   * Must be called with interrupts hard-disabled.
@@ -2325,7 +2332,12 @@ kvmppc_read_intr:
      cmpdi    r6, 0
      beq-    1f
      lwzcix    r0, r6, r7
-    rlwinm.    r3, r0, 0, 0xffffff
+#ifdef __LITTLE_ENDIAN__
+    bswap32    r4, r0
+#else
+    mr    r4, r0
+#endif
+    rlwinm.    r3, r4, 0, 0xffffff
      sync
      beq    1f            /* if nothing pending in the ICP */

@@ -2360,7 +2372,7 @@ kvmppc_read_intr:
  42:    /* It's not an IPI and it's for the host, stash it in the PACA
       * before exit, it will be picked up by the host ICP driver
       */
-    stw    r0, HSTATE_SAVED_XIRR(r13)
+    stw    r4, HSTATE_SAVED_XIRR(r13)
      li    r3, 1
      b    1b


Alex

^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2014-06-17 12:14 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-11 10:33 [PATCH 0/6] KVM: PPC: Book3S HV: Enable on little endian hosts Alexander Graf
2014-06-11 10:33 ` [PATCH 1/6] PPC: Add asm helpers for BE 32bit load/store Alexander Graf
2014-06-17  0:51   ` Paul Mackerras
2014-06-17  8:34     ` Alexander Graf
2014-06-11 10:33 ` [PATCH 2/6] KVM: PPC: Book3S HV: Make HTAB code LE host aware Alexander Graf
2014-06-11 10:33 ` [PATCH 3/6] KVM: PPC: Book3S HV: Access guest VPA in BE Alexander Graf
2014-06-11 10:33 ` [PATCH 4/6] KVM: PPC: Book3S HV: Access host lppaca and shadow slb " Alexander Graf
2014-06-11 10:33 ` [PATCH 5/6] KVM: PPC: Book3S HV: Access XICS " Alexander Graf
2014-06-17  1:02   ` Paul Mackerras
2014-06-17  8:37     ` Alexander Graf
2014-06-17 10:22       ` Alexander Graf
2014-06-17 12:13         ` Paul Mackerras
2014-06-17 12:14           ` Alexander Graf
2014-06-11 10:33 ` [PATCH 6/6] KVM: PPC: Book3S HV: Enable for little endian hosts Alexander Graf
2014-06-16  4:22 ` [PATCH 0/6] KVM: PPC: Book3S HV: Enable on " Aneesh Kumar K.V
2014-06-16 12:17   ` Alexander Graf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox