Patchwork [V3] KVM: PPC: BOOK3S: PR: Enable Little Endian PR guest

login
register
mail settings
Submitter Aneesh Kumar K.V
Date Jan. 28, 2014, 6:46 a.m.
Message ID <1390891569-21161-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/314608/
State New
Headers show

Comments

Aneesh Kumar K.V - Jan. 28, 2014, 6:46 a.m.
This patch make sure we inherit the LE bit correctly in different case
so that we can run Little Endian distro in PR mode

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
Changes from V2:
 * Move H_SET_MODE to qemu


 arch/powerpc/include/asm/kvm_host.h |  1 +
 arch/powerpc/kernel/asm-offsets.c   |  1 +
 arch/powerpc/kvm/book3s_64_mmu.c    |  2 +-
 arch/powerpc/kvm/book3s_pr.c        | 32 +++++++++++++++++++++++++++++++-
 4 files changed, 34 insertions(+), 2 deletions(-)
Alexander Graf - Feb. 6, 2014, 3:46 p.m.
On 28.01.2014, at 07:46, Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> wrote:

> This patch make sure we inherit the LE bit correctly in different case
> so that we can run Little Endian distro in PR mode
> 
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> ---
> Changes from V2:
> * Move H_SET_MODE to qemu
> 
> 
> arch/powerpc/include/asm/kvm_host.h |  1 +
> arch/powerpc/kernel/asm-offsets.c   |  1 +
> arch/powerpc/kvm/book3s_64_mmu.c    |  2 +-
> arch/powerpc/kvm/book3s_pr.c        | 32 +++++++++++++++++++++++++++++++-
> 4 files changed, 34 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
> index 207b7826c9b1..f4be7be14330 100644
> --- a/arch/powerpc/include/asm/kvm_host.h
> +++ b/arch/powerpc/include/asm/kvm_host.h
> @@ -550,6 +550,7 @@ struct kvm_vcpu_arch {
> #ifdef CONFIG_PPC_BOOK3S
> 	ulong fault_dar;
> 	u32 fault_dsisr;
> +	unsigned long intr_msr;

We already have a field with that name and semantics in the vcpu_arch struct. Just move that one to a more commonly accessible part of the struct.

> #endif
> 
> #ifdef CONFIG_BOOKE
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
> index b754f629a177..7484676b8f25 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -518,6 +518,7 @@ int main(void)
> 	DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr));
> 	DEFINE(VCPU_FAULT_DSISR, offsetof(struct kvm_vcpu, arch.fault_dsisr));
> 	DEFINE(VCPU_FAULT_DAR, offsetof(struct kvm_vcpu, arch.fault_dar));
> +	DEFINE(VCPU_INTR_MSR, offsetof(struct kvm_vcpu, arch.intr_msr));

Same here:

arch/powerpc/kernel/asm-offsets.c:      DEFINE(VCPU_INTR_MSR, offsetof(struct kvm_vcpu, arch.intr_msr));

> 	DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
> 	DEFINE(VCPU_TRAP, offsetof(struct kvm_vcpu, arch.trap));
> 	DEFINE(VCPU_PTID, offsetof(struct kvm_vcpu, arch.ptid));
> diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
> index 83da1f868fd5..8231b83c493b 100644
> --- a/arch/powerpc/kvm/book3s_64_mmu.c
> +++ b/arch/powerpc/kvm/book3s_64_mmu.c
> @@ -38,7 +38,7 @@
> 
> static void kvmppc_mmu_book3s_64_reset_msr(struct kvm_vcpu *vcpu)
> {
> -	kvmppc_set_msr(vcpu, MSR_SF);
> +	kvmppc_set_msr(vcpu, vcpu->arch.intr_msr);
> }
> 
> static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe(
> diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
> index eb070eb4da40..828056ec208f 100644
> --- a/arch/powerpc/kvm/book3s_pr.c
> +++ b/arch/powerpc/kvm/book3s_pr.c
> @@ -263,7 +263,7 @@ static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
> 	ulong smsr = vcpu->arch.shared->msr;
> 
> 	/* Guest MSR values */
> -	smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE;
> +	smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_LE;
> 	/* Process MSR values */
> 	smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
> 	/* External providers the guest reserved */
> @@ -1178,6 +1178,15 @@ static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
> 		break;
> 	}
> #endif /* CONFIG_VSX */
> +	case KVM_REG_PPC_LPCR:
> +		/*
> +		 * We are only interested in the LPCR_ILE bit
> +		 */
> +		if (vcpu->arch.intr_msr & MSR_LE)
> +			*val = get_reg_val(id, LPCR_ILE);
> +		else
> +			*val = get_reg_val(id, 0);
> +		break;
> 	default:
> 		r = -EINVAL;
> 		break;
> @@ -1186,6 +1195,23 @@ static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
> 	return r;
> }
> 
> +static void kvmppc_set_lpcr_pr(struct kvm_vcpu *vcpu, u64 new_lpcr)
> +{
> +	struct kvm *kvm = vcpu->kvm;
> +	/*
> +	 * If ILE (interrupt little-endian) has changed, update the
> +	 * MSR_LE bit in the intr_msr for each vcpu in this vcore.
> +	 */
> +	if ((new_lpcr & LPCR_ILE) != (vcpu->arch.intr_msr & MSR_LE)) {
> +		mutex_lock(&kvm->lock);

Why the lock?


Alex

> +		if (new_lpcr & LPCR_ILE)
> +			vcpu->arch.intr_msr |= MSR_LE;
> +		else
> +			vcpu->arch.intr_msr &= ~MSR_LE;
> +		mutex_unlock(&kvm->lock);
> +	}
> +}
> +
> static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
> 				 union kvmppc_one_reg *val)
> {
> @@ -1209,6 +1235,9 @@ static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
> 		break;
> 	}
> #endif /* CONFIG_VSX */
> +	case KVM_REG_PPC_LPCR:
> +		kvmppc_set_lpcr_pr(vcpu, set_reg_val(id, *val));
> +		break;
> 	default:
> 		r = -EINVAL;
> 		break;
> @@ -1261,6 +1290,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm,
> 	vcpu->arch.pvr = 0x3C0301;
> 	if (mmu_has_feature(MMU_FTR_1T_SEGMENT))
> 		vcpu->arch.pvr = mfspr(SPRN_PVR);
> +	vcpu->arch.intr_msr = MSR_SF;
> #else
> 	/* default to book3s_32 (750) */
> 	vcpu->arch.pvr = 0x84202;
> -- 
> 1.8.5.3
> 

--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 207b7826c9b1..f4be7be14330 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -550,6 +550,7 @@  struct kvm_vcpu_arch {
 #ifdef CONFIG_PPC_BOOK3S
 	ulong fault_dar;
 	u32 fault_dsisr;
+	unsigned long intr_msr;
 #endif
 
 #ifdef CONFIG_BOOKE
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index b754f629a177..7484676b8f25 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -518,6 +518,7 @@  int main(void)
 	DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr));
 	DEFINE(VCPU_FAULT_DSISR, offsetof(struct kvm_vcpu, arch.fault_dsisr));
 	DEFINE(VCPU_FAULT_DAR, offsetof(struct kvm_vcpu, arch.fault_dar));
+	DEFINE(VCPU_INTR_MSR, offsetof(struct kvm_vcpu, arch.intr_msr));
 	DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
 	DEFINE(VCPU_TRAP, offsetof(struct kvm_vcpu, arch.trap));
 	DEFINE(VCPU_PTID, offsetof(struct kvm_vcpu, arch.ptid));
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
index 83da1f868fd5..8231b83c493b 100644
--- a/arch/powerpc/kvm/book3s_64_mmu.c
+++ b/arch/powerpc/kvm/book3s_64_mmu.c
@@ -38,7 +38,7 @@ 
 
 static void kvmppc_mmu_book3s_64_reset_msr(struct kvm_vcpu *vcpu)
 {
-	kvmppc_set_msr(vcpu, MSR_SF);
+	kvmppc_set_msr(vcpu, vcpu->arch.intr_msr);
 }
 
 static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe(
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index eb070eb4da40..828056ec208f 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -263,7 +263,7 @@  static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
 	ulong smsr = vcpu->arch.shared->msr;
 
 	/* Guest MSR values */
-	smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE;
+	smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_LE;
 	/* Process MSR values */
 	smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
 	/* External providers the guest reserved */
@@ -1178,6 +1178,15 @@  static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
 		break;
 	}
 #endif /* CONFIG_VSX */
+	case KVM_REG_PPC_LPCR:
+		/*
+		 * We are only interested in the LPCR_ILE bit
+		 */
+		if (vcpu->arch.intr_msr & MSR_LE)
+			*val = get_reg_val(id, LPCR_ILE);
+		else
+			*val = get_reg_val(id, 0);
+		break;
 	default:
 		r = -EINVAL;
 		break;
@@ -1186,6 +1195,23 @@  static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
 	return r;
 }
 
+static void kvmppc_set_lpcr_pr(struct kvm_vcpu *vcpu, u64 new_lpcr)
+{
+	struct kvm *kvm = vcpu->kvm;
+	/*
+	 * If ILE (interrupt little-endian) has changed, update the
+	 * MSR_LE bit in the intr_msr for each vcpu in this vcore.
+	 */
+	if ((new_lpcr & LPCR_ILE) != (vcpu->arch.intr_msr & MSR_LE)) {
+		mutex_lock(&kvm->lock);
+		if (new_lpcr & LPCR_ILE)
+			vcpu->arch.intr_msr |= MSR_LE;
+		else
+			vcpu->arch.intr_msr &= ~MSR_LE;
+		mutex_unlock(&kvm->lock);
+	}
+}
+
 static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
 				 union kvmppc_one_reg *val)
 {
@@ -1209,6 +1235,9 @@  static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
 		break;
 	}
 #endif /* CONFIG_VSX */
+	case KVM_REG_PPC_LPCR:
+		kvmppc_set_lpcr_pr(vcpu, set_reg_val(id, *val));
+		break;
 	default:
 		r = -EINVAL;
 		break;
@@ -1261,6 +1290,7 @@  static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm,
 	vcpu->arch.pvr = 0x3C0301;
 	if (mmu_has_feature(MMU_FTR_1T_SEGMENT))
 		vcpu->arch.pvr = mfspr(SPRN_PVR);
+	vcpu->arch.intr_msr = MSR_SF;
 #else
 	/* default to book3s_32 (750) */
 	vcpu->arch.pvr = 0x84202;