[RFC PATCH 15/16] KVM: PPC: booke: standard PPC floating point support

Alexander Graf agraf at suse.de
Tue Jan 10 04:48:26 EST 2012


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.liu at freescale.com>.
> 
> Signed-off-by: Scott Wood <scottwood at 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



More information about the Linuxppc-dev mailing list