From patchwork Wed Dec 21 01:34:45 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Scott Wood X-Patchwork-Id: 132564 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id E46C0B7274 for ; Wed, 21 Dec 2011 12:35:02 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753618Ab1LUBe5 (ORCPT ); Tue, 20 Dec 2011 20:34:57 -0500 Received: from db3ehsobe006.messaging.microsoft.com ([213.199.154.144]:44888 "EHLO DB3EHSOBE006.bigfish.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753664Ab1LUBex (ORCPT ); Tue, 20 Dec 2011 20:34:53 -0500 Received: from mail70-db3-R.bigfish.com (10.3.81.251) by DB3EHSOBE006.bigfish.com (10.3.84.26) with Microsoft SMTP Server id 14.1.225.23; Wed, 21 Dec 2011 01:34:44 +0000 Received: from mail70-db3 (localhost [127.0.0.1]) by mail70-db3-R.bigfish.com (Postfix) with ESMTP id 0CA761800DE; Wed, 21 Dec 2011 01:35:12 +0000 (UTC) X-SpamScore: 0 X-BigFish: VS0(zzzz1202hzz8275bhz2dh2a8h668h839h944h) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI Received: from mail70-db3 (localhost.localdomain [127.0.0.1]) by mail70-db3 (MessageSwitch) id 1324431311803631_1953; Wed, 21 Dec 2011 01:35:11 +0000 (UTC) Received: from DB3EHSMHS018.bigfish.com (unknown [10.3.81.242]) by mail70-db3.bigfish.com (Postfix) with ESMTP id C0B97240045; Wed, 21 Dec 2011 01:35:11 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by DB3EHSMHS018.bigfish.com (10.3.87.118) with Microsoft SMTP Server (TLS) id 14.1.225.23; Wed, 21 Dec 2011 01:34:43 +0000 Received: from az33smr01.freescale.net (10.64.34.199) by 039-SN1MMR1-003.039d.mgd.msft.net (10.84.1.16) with Microsoft SMTP Server id 14.1.355.3; Tue, 20 Dec 2011 19:34:46 -0600 Received: from schlenkerla.am.freescale.net (schlenkerla.am.freescale.net [10.82.121.12]) by az33smr01.freescale.net (8.13.1/8.13.0) with ESMTP id pBL1YjcM018873; Tue, 20 Dec 2011 19:34:45 -0600 (CST) Date: Tue, 20 Dec 2011 19:34:45 -0600 From: Scott Wood To: CC: , , Subject: [RFC PATCH 15/16] KVM: PPC: booke: standard PPC floating point support Message-ID: <20111221013445.GO8378@schlenkerla.am.freescale.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20111221013340.GA8368@schlenkerla.am.freescale.net> User-Agent: Mutt/1.5.21 (2010-09-15) X-OriginatorOrg: freescale.com Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org e500mc has a normal PPC FPU, rather than SPE which is found on e500v1/v2. Based on code from Liu Yu . Signed-off-by: Scott Wood --- 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 + 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__ */