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.
> 
> Based on code from Liu Yu <yu....@freescale.com>.
> 
> Signed-off-by: Scott Wood <scottw...@freescale.com>
> ---
> 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 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)
> 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;
> @@ -482,7 +487,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

Do you think it's possible to combine this with the book3s_pr code, so we don't 
duplicate too much here?

> +
>       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;

I'm having a hard time to grasp when shared->msr, shadow_msr and regs->msr is 
used in your code :).


Alex

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to