Re: [RFC PATCH 15/16] KVM: PPC: booke: standard PPC floating point support
From: Alexander Graf <hidden>
Date: 2012-01-09 17:48:31
Also in:
kvm
On 21.12.2011, at 02:34, Scott Wood wrote:
e500mc has a normal PPC FPU, rather than SPE which is found on e500v1/v2. =20 Based on code from Liu Yu [off-list ref]. =20 Signed-off-by: Scott Wood <redacted> --- arch/powerpc/include/asm/system.h | 1 + arch/powerpc/kvm/booke.c | 44 =
+++++++++++++++++++++++++++++++++++++
quoted hunk ↗ jump to hunk
arch/powerpc/kvm/booke.h | 30 +++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 0 deletions(-) =20diff --git a/arch/powerpc/include/asm/system.h =
b/arch/powerpc/include/asm/system.h
quoted hunk ↗ jump to hunk
index e30a13d..0561356 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 cf63b93..4bf43f9 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c@@ -460,6 +460,11 @@ void kvmppc_core_prepare_to_enter(struct kvm_vcpu =
*vcpu)
quoted hunk ↗ jump to hunk
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 =20 if (!vcpu->arch.sane) { kvm_run->exit_reason =3D KVM_EXIT_INTERNAL_ERROR;@@ -482,7 +487,46 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, =
struct kvm_vcpu *vcpu)
} =20 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 =3D current->thread.fpscr.val; + fpexc_mode =3D 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 =3D 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 =3D 1; + + kvmppc_load_guest_fp(vcpu); +#endif
Do you think it's possible to combine this with the book3s_pr code, so = we don't duplicate too much here?
+ ret =3D __kvmppc_vcpu_run(kvm_run, vcpu); + +#ifdef CONFIG_PPC_FPU + kvmppc_save_guest_fp(vcpu); + + vcpu->fpu_active =3D 0; + + /* Save guest FPU state from thread */ + memcpy(vcpu->arch.fpr, current->thread.fpr, =
sizeof(vcpu->arch.fpr));
quoted hunk ↗ jump to hunk
+ vcpu->arch.fpscr =3D current->thread.fpscr.val; + + /* Restore userspace FPU state from stack */ + memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr)); + current->thread.fpscr.val =3D fpscr; + current->thread.fpexc_mode =3D fpexc_mode; +#endif + kvm_guest_exit(); =20 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 {=20 void kvmppc_set_pending_interrupt(struct kvm_vcpu *vcpu, enum =
int_class type);
=20
+/*
+ * 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 |=3D MSR_FP;I'm having a hard time to grasp when shared->msr, shadow_msr and = regs->msr is used in your code :). Alex