Patchwork [12/15] KVM: PPC: Book3S HV: Add H_SET_MODE address translation setting

login
register
mail settings
Submitter Paul Mackerras
Date Nov. 9, 2013, 11:05 a.m.
Message ID <1383995103-24732-13-git-send-email-paulus@samba.org>
Download mbox | patch
Permalink /patch/289981/
State New
Headers show

Comments

Paul Mackerras - Nov. 9, 2013, 11:05 a.m.
From: Michael Neuling <mikey@neuling.org>

Add setting the address translation mode controlled by the AIL bits in the
LPCR.  Traditional untranslated mode is 0.  The new mode used by Linux is 3,
where exceptions will come in at 0xc000000000004000.

This is set system wide hence we kick all cpus to ensure they've picked up this
setting before returning.

This also adds a kvmppc_power8_compatible() function to test to see if a guest
is compatible with POWER8 or not.

Note that interrupts synthesized by KVM are still delivered with
relocation off to the vectors starting at 0.

Modified by paulus to use kvmppc_update_lpcr().

Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
 arch/powerpc/include/asm/reg.h |  1 +
 arch/powerpc/kvm/book3s_hv.c   | 30 ++++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+)

Patch

diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index e86b008..bf57326 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -301,6 +301,7 @@ 
 #define	  LPCR_RMLS_SH	(63-37)
 #define   LPCR_ILE     0x02000000      /* !HV irqs set MSR:LE */
 #define   LPCR_AIL	0x01800000	/* Alternate interrupt location */
+#define   LPCR_AIL_SH	(63-40)
 #define   LPCR_AIL_0	0x00000000	/* MMU off exception offset 0x0 */
 #define   LPCR_AIL_3	0x01800000	/* MMU on exception offset 0xc00...4xxx */
 #define   LPCR_ONL	0x00040000	/* online - PURR/SPURR count */
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 2473400..0c309d9 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -549,6 +549,16 @@  static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu,
 	vcpu->arch.dtl.dirty = true;
 }
 
+static bool kvmppc_power8_compatible(struct kvm_vcpu *vcpu)
+{
+	if (vcpu->arch.vcore->arch_compat >= PVR_ARCH_207)
+		return true;
+	if ((!vcpu->arch.vcore->arch_compat) &&
+	    cpu_has_feature(CPU_FTR_ARCH_207S))
+		return true;
+	return false;
+}
+
 static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags,
 			     unsigned long resource, unsigned long value1,
 			     unsigned long value2)
@@ -558,6 +568,26 @@  static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags,
 	int n;
 
 	switch (resource) {
+	case H_SET_MODE_RESOURCE_ADDR_TRANS_MODE:
+		if (!kvmppc_power8_compatible(vcpu))
+			return H_P2;
+		if (value1)
+			return H_P3;
+		if (value2)
+			return H_P4;
+		switch (mflags) {
+		case 0:
+		case 2:
+		case 3:
+			mutex_lock(&kvm->lock);
+			kvmppc_update_lpcr(kvm, mflags << LPCR_AIL_SH,
+					   LPCR_AIL);
+			mutex_unlock(&kvm->lock);
+			kick_all_cpus_sync();
+			return H_SUCCESS;
+		default:
+			return H_UNSUPPORTED_FLAG_START;
+		}
 	case H_SET_MODE_RESOURCE_LE:
 		if (value1)
 			return H_P3;