[PATCH 14/37] KVM: PPC: booke: standard PPC floating point support

2012-02-24 Thread Alexander Graf
From: Scott Wood scottw...@freescale.com

e500mc has a normal PPC FPU, rather than SPE which is found
on e500v1/v2.

Based on code from Liu Yu yu@freescale.com.

Signed-off-by: Scott Wood scottw...@freescale.com
Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/system.h |1 +
 arch/powerpc/kvm/booke.c  |   44 +
 arch/powerpc/kvm/booke.h  |   30 +
 3 files changed, 75 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/system.h 
b/arch/powerpc/include/asm/system.h
index c377457..73eee86 100644
--- a/arch/powerpc/include/asm/system.h
+++ b/arch/powerpc/include/asm/system.h
@@ -140,6 +140,7 @@ extern void via_cuda_init(void);
 extern void read_rtc_time(void);
 extern void pmac_find_display(void);
 extern void giveup_fpu(struct task_struct *);
+extern void load_up_fpu(void);
 extern void disable_kernel_fp(void);
 extern void enable_kernel_fp(void);
 extern void flush_fp_to_thread(struct task_struct *);
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 75dbaeb..0b77be1 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -457,6 +457,11 @@ void kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
 int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
int ret;
+#ifdef CONFIG_PPC_FPU
+   unsigned int fpscr;
+   int fpexc_mode;
+   u64 fpr[32];
+#endif
 
if (!vcpu-arch.sane) {
kvm_run-exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -479,7 +484,46 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct 
kvm_vcpu *vcpu)
}
 
kvm_guest_enter();
+
+#ifdef CONFIG_PPC_FPU
+   /* Save userspace FPU state in stack */
+   enable_kernel_fp();
+   memcpy(fpr, current-thread.fpr, sizeof(current-thread.fpr));
+   fpscr = current-thread.fpscr.val;
+   fpexc_mode = current-thread.fpexc_mode;
+
+   /* Restore guest FPU state to thread */
+   memcpy(current-thread.fpr, vcpu-arch.fpr, sizeof(vcpu-arch.fpr));
+   current-thread.fpscr.val = vcpu-arch.fpscr;
+
+   /*
+* Since we can't trap on MSR_FP in GS-mode, we consider the guest
+* as always using the FPU.  Kernel usage of FP (via
+* enable_kernel_fp()) in this thread must not occur while
+* vcpu-fpu_active is set.
+*/
+   vcpu-fpu_active = 1;
+
+   kvmppc_load_guest_fp(vcpu);
+#endif
+
ret = __kvmppc_vcpu_run(kvm_run, vcpu);
+
+#ifdef CONFIG_PPC_FPU
+   kvmppc_save_guest_fp(vcpu);
+
+   vcpu-fpu_active = 0;
+
+   /* Save guest FPU state from thread */
+   memcpy(vcpu-arch.fpr, current-thread.fpr, sizeof(vcpu-arch.fpr));
+   vcpu-arch.fpscr = current-thread.fpscr.val;
+
+   /* Restore userspace FPU state from stack */
+   memcpy(current-thread.fpr, fpr, sizeof(current-thread.fpr));
+   current-thread.fpscr.val = fpscr;
+   current-thread.fpexc_mode = fpexc_mode;
+#endif
+
kvm_guest_exit();
 
 out:
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index d53bcf2..3bf5eda 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -96,4 +96,34 @@ enum int_class {
 
 void kvmppc_set_pending_interrupt(struct kvm_vcpu *vcpu, enum int_class type);
 
+/*
+ * Load up guest vcpu FP state if it's needed.
+ * It also set the MSR_FP in thread so that host know
+ * we're holding FPU, and then host can help to save
+ * guest vcpu FP state if other threads require to use FPU.
+ * This simulates an FP unavailable fault.
+ *
+ * It requires to be called with preemption disabled.
+ */
+static inline void kvmppc_load_guest_fp(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_PPC_FPU
+   if (vcpu-fpu_active  !(current-thread.regs-msr  MSR_FP)) {
+   load_up_fpu();
+   current-thread.regs-msr |= MSR_FP;
+   }
+#endif
+}
+
+/*
+ * Save guest vcpu FP state into thread.
+ * It requires to be called with preemption disabled.
+ */
+static inline void kvmppc_save_guest_fp(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_PPC_FPU
+   if (vcpu-fpu_active  (current-thread.regs-msr  MSR_FP))
+   giveup_fpu(current);
+#endif
+}
 #endif /* __KVM_BOOKE_H__ */
-- 
1.6.0.2

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


[PATCH 14/37] KVM: PPC: booke: standard PPC floating point support

2012-02-24 Thread Alexander Graf
From: Scott Wood scottw...@freescale.com

e500mc has a normal PPC FPU, rather than SPE which is found
on e500v1/v2.

Based on code from Liu Yu yu@freescale.com.

Signed-off-by: Scott Wood scottw...@freescale.com
Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/system.h |1 +
 arch/powerpc/kvm/booke.c  |   44 +
 arch/powerpc/kvm/booke.h  |   30 +
 3 files changed, 75 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/system.h 
b/arch/powerpc/include/asm/system.h
index c377457..73eee86 100644
--- a/arch/powerpc/include/asm/system.h
+++ b/arch/powerpc/include/asm/system.h
@@ -140,6 +140,7 @@ extern void via_cuda_init(void);
 extern void read_rtc_time(void);
 extern void pmac_find_display(void);
 extern void giveup_fpu(struct task_struct *);
+extern void load_up_fpu(void);
 extern void disable_kernel_fp(void);
 extern void enable_kernel_fp(void);
 extern void flush_fp_to_thread(struct task_struct *);
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 75dbaeb..0b77be1 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -457,6 +457,11 @@ void kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
 int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
int ret;
+#ifdef CONFIG_PPC_FPU
+   unsigned int fpscr;
+   int fpexc_mode;
+   u64 fpr[32];
+#endif
 
if (!vcpu-arch.sane) {
kvm_run-exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -479,7 +484,46 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct 
kvm_vcpu *vcpu)
}
 
kvm_guest_enter();
+
+#ifdef CONFIG_PPC_FPU
+   /* Save userspace FPU state in stack */
+   enable_kernel_fp();
+   memcpy(fpr, current-thread.fpr, sizeof(current-thread.fpr));
+   fpscr = current-thread.fpscr.val;
+   fpexc_mode = current-thread.fpexc_mode;
+
+   /* Restore guest FPU state to thread */
+   memcpy(current-thread.fpr, vcpu-arch.fpr, sizeof(vcpu-arch.fpr));
+   current-thread.fpscr.val = vcpu-arch.fpscr;
+
+   /*
+* Since we can't trap on MSR_FP in GS-mode, we consider the guest
+* as always using the FPU.  Kernel usage of FP (via
+* enable_kernel_fp()) in this thread must not occur while
+* vcpu-fpu_active is set.
+*/
+   vcpu-fpu_active = 1;
+
+   kvmppc_load_guest_fp(vcpu);
+#endif
+
ret = __kvmppc_vcpu_run(kvm_run, vcpu);
+
+#ifdef CONFIG_PPC_FPU
+   kvmppc_save_guest_fp(vcpu);
+
+   vcpu-fpu_active = 0;
+
+   /* Save guest FPU state from thread */
+   memcpy(vcpu-arch.fpr, current-thread.fpr, sizeof(vcpu-arch.fpr));
+   vcpu-arch.fpscr = current-thread.fpscr.val;
+
+   /* Restore userspace FPU state from stack */
+   memcpy(current-thread.fpr, fpr, sizeof(current-thread.fpr));
+   current-thread.fpscr.val = fpscr;
+   current-thread.fpexc_mode = fpexc_mode;
+#endif
+
kvm_guest_exit();
 
 out:
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index d53bcf2..3bf5eda 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -96,4 +96,34 @@ enum int_class {
 
 void kvmppc_set_pending_interrupt(struct kvm_vcpu *vcpu, enum int_class type);
 
+/*
+ * Load up guest vcpu FP state if it's needed.
+ * It also set the MSR_FP in thread so that host know
+ * we're holding FPU, and then host can help to save
+ * guest vcpu FP state if other threads require to use FPU.
+ * This simulates an FP unavailable fault.
+ *
+ * It requires to be called with preemption disabled.
+ */
+static inline void kvmppc_load_guest_fp(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_PPC_FPU
+   if (vcpu-fpu_active  !(current-thread.regs-msr  MSR_FP)) {
+   load_up_fpu();
+   current-thread.regs-msr |= MSR_FP;
+   }
+#endif
+}
+
+/*
+ * Save guest vcpu FP state into thread.
+ * It requires to be called with preemption disabled.
+ */
+static inline void kvmppc_save_guest_fp(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_PPC_FPU
+   if (vcpu-fpu_active  (current-thread.regs-msr  MSR_FP))
+   giveup_fpu(current);
+#endif
+}
 #endif /* __KVM_BOOKE_H__ */
-- 
1.6.0.2

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