diff mbox

[4/6,v2] KVM: PPC: Book3E: Add AltiVec support

Message ID 1404142497-6430-5-git-send-email-mihai.caraman@freescale.com (mailing list archive)
State Not Applicable
Headers show

Commit Message

Mihai Caraman June 30, 2014, 3:34 p.m. UTC
Add KVM Book3E AltiVec support. KVM Book3E FPU support gracefully reuse host
infrastructure so follow the same approach for AltiVec.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v2:
 - integrate Paul's FP/VMX/VSX changes

 arch/powerpc/kvm/booke.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 65 insertions(+), 2 deletions(-)

Comments

Alexander Graf July 3, 2014, 12:32 p.m. UTC | #1
On 30.06.14 17:34, Mihai Caraman wrote:
> Add KVM Book3E AltiVec support. KVM Book3E FPU support gracefully reuse host
> infrastructure so follow the same approach for AltiVec.
>
> Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>

Same comment here - I fail to see how we refetch Altivec state after a 
context switch.


Alex
Mihai Caraman July 3, 2014, 3:58 p.m. UTC | #2
> -----Original Message-----
> From: Alexander Graf [mailto:agraf@suse.de]
> Sent: Thursday, July 03, 2014 3:32 PM
> To: Caraman Mihai Claudiu-B02008; kvm-ppc@vger.kernel.org
> Cc: kvm@vger.kernel.org; linuxppc-dev@lists.ozlabs.org
> Subject: Re: [PATCH 4/6 v2] KVM: PPC: Book3E: Add AltiVec support
> 
> 
> On 30.06.14 17:34, Mihai Caraman wrote:
> > Add KVM Book3E AltiVec support. KVM Book3E FPU support gracefully reuse
> host
> > infrastructure so follow the same approach for AltiVec.
> >
> > Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
> 
> Same comment here - I fail to see how we refetch Altivec state after a
> context switch.

See previous comment. I also run my usual Altivec stress test consisting in
a guest and host process running affine to a physical core an competing for
the same unit's resources using different data sets.

-Mike
Scott Wood July 3, 2014, 11:07 p.m. UTC | #3
On Mon, 2014-06-30 at 18:34 +0300, Mihai Caraman wrote:
> Add KVM Book3E AltiVec support. KVM Book3E FPU support gracefully reuse host
> infrastructure so follow the same approach for AltiVec.
> 
> Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
> ---
> v2:
>  - integrate Paul's FP/VMX/VSX changes
> 
>  arch/powerpc/kvm/booke.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 65 insertions(+), 2 deletions(-)

I had to apply the whole patchset to get proper context for reviewing
this, and found some nits:

>         case BOOKE_INTERRUPT_SPE_FP_DATA_ALTIVEC_ASSIST:
>                 if (kvmppc_supports_spe() || kvmppc_supports_altivec()) {
>                         kvmppc_booke_queue_irqprio(vcpu,
>                                 BOOKE_IRQPRIO_SPE_FP_DATA_ALTIVEC_ASSIST);
>                         r = RESUME_GUEST;
>                 } else { 
>                         /*
>                          * These really should never happen without CONFIG_SPE,
>                          * as we should never enable the real MSR[SPE] in the
>                          * guest.
>                          */

Besides the comment not being updated for Altivec, it's not true on HV,
where the guest can enable MSR[VEC] all by itself.  For HV, the reason
we shouldn't be able to get here is that we disable KVM on e6500 if
CONFIG_ALTIVEC is not enabled, and no other HV core supports either SPE
or Altivec.

>                         pr_crit("%s: unexpected SPE interrupt %u at %08lx\n",
>                                 __func__, exit_nr, vcpu->arch.pc);

Error string will say SPE regardless of what sort of chip you're on.
Given that this is explicitly on the "no support for Altivec or SPE"
path, "SPE/Altivec" phrasing seems appropriate.  Of course we have
bigger problems than that if we ever reach this code. :-)

-Scott
diff mbox

Patch

diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 4cc9b26..4ba75f6 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -100,6 +100,19 @@  static inline bool kvmppc_supports_spe(void)
 	return false;
 }
 
+/*
+ * Always returns true if AltiVec unit is present,
+ * see kvmppc_core_check_processor_compat().
+ */
+static inline bool kvmppc_supports_altivec(void)
+{
+#ifdef CONFIG_ALTIVEC
+	if (cpu_has_feature(CPU_FTR_ALTIVEC))
+		return true;
+#endif
+	return false;
+}
+
 #ifdef CONFIG_SPE
 void kvmppc_vcpu_disable_spe(struct kvm_vcpu *vcpu)
 {
@@ -178,6 +191,40 @@  static void kvmppc_vcpu_sync_fpu(struct kvm_vcpu *vcpu)
 #endif
 }
 
+/*
+ * Simulate AltiVec unavailable fault to load guest state
+ * from thread to AltiVec unit.
+ * It requires to be called with preemption disabled.
+ */
+static inline void kvmppc_load_guest_altivec(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_ALTIVEC
+	if (kvmppc_supports_altivec()) {
+		if (!(current->thread.regs->msr & MSR_VEC)) {
+			enable_kernel_altivec();
+			load_vr_state(&vcpu->arch.vr);
+			current->thread.vr_save_area = &vcpu->arch.vr;
+			current->thread.regs->msr |= MSR_VEC;
+		}
+	}
+#endif
+}
+
+/*
+ * Save guest vcpu AltiVec state into thread.
+ * It requires to be called with preemption disabled.
+ */
+static inline void kvmppc_save_guest_altivec(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_ALTIVEC
+	if (kvmppc_supports_altivec()) {
+		if (current->thread.regs->msr & MSR_VEC)
+			giveup_altivec(current);
+		current->thread.vr_save_area = NULL;
+	}
+#endif
+}
+
 static void kvmppc_vcpu_sync_debug(struct kvm_vcpu *vcpu)
 {
 	/* Synchronize guest's desire to get debug interrupts into shadow MSR */
@@ -749,6 +796,17 @@  int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	kvmppc_load_guest_fp(vcpu);
 #endif
 
+#ifdef CONFIG_ALTIVEC
+	/* Save userspace AltiVec state in stack */
+	if (kvmppc_supports_altivec())
+		enable_kernel_altivec();
+	/*
+	 * Since we can't trap on MSR_VEC in GS-mode, we consider the guest
+	 * as always using the AltiVec.
+	 */
+	kvmppc_load_guest_altivec(vcpu);
+#endif
+
 	/* Switch to guest debug context */
 	debug = vcpu->arch.shadow_dbg_reg;
 	switch_booke_debug_regs(&debug);
@@ -771,6 +829,10 @@  int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	kvmppc_save_guest_fp(vcpu);
 #endif
 
+#ifdef CONFIG_ALTIVEC
+	kvmppc_save_guest_altivec(vcpu);
+#endif
+
 out:
 	vcpu->mode = OUTSIDE_GUEST_MODE;
 	return ret;
@@ -1014,7 +1076,7 @@  int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		break;
 
 	case BOOKE_INTERRUPT_SPE_ALTIVEC_UNAVAIL: {
-		if (kvmppc_supports_spe()) {
+		if (kvmppc_supports_spe() || kvmppc_supports_altivec()) {
 			bool enabled = false;
 
 #if !defined(CONFIG_KVM_BOOKE_HV) && defined(CONFIG_SPE)
@@ -1040,7 +1102,7 @@  int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	}
 
 	case BOOKE_INTERRUPT_SPE_FP_DATA_ALTIVEC_ASSIST:
-		if (kvmppc_supports_spe()) {
+		if (kvmppc_supports_spe() || kvmppc_supports_altivec()) {
 			kvmppc_booke_queue_irqprio(vcpu,
 				BOOKE_IRQPRIO_SPE_FP_DATA_ALTIVEC_ASSIST);
 			r = RESUME_GUEST;
@@ -1249,6 +1311,7 @@  int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 			/* interrupts now hard-disabled */
 			kvmppc_fix_ee_before_entry();
 			kvmppc_load_guest_fp(vcpu);
+			kvmppc_load_guest_altivec(vcpu);
 		}
 	}