From patchwork Thu Feb 21 02:41:51 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 222167 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 6CE7D2C008C for ; Thu, 21 Feb 2013 13:42:39 +1100 (EST) Received: from localhost ([::1]:47483 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U8M7J-0003Y1-Jo for incoming@patchwork.ozlabs.org; Wed, 20 Feb 2013 21:42:37 -0500 Received: from eggs.gnu.org ([208.118.235.92]:39370) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U8M6x-0003E3-6q for qemu-devel@nongnu.org; Wed, 20 Feb 2013 21:42:20 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1U8M6n-0007n8-4A for qemu-devel@nongnu.org; Wed, 20 Feb 2013 21:42:15 -0500 Received: from ozlabs.org ([2402:b800:7003:1:1::1]:56767) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U8M6m-0007m0-Be; Wed, 20 Feb 2013 21:42:05 -0500 Received: by ozlabs.org (Postfix, from userid 1007) id 90B892C0091; Thu, 21 Feb 2013 13:41:55 +1100 (EST) From: David Gibson To: agraf@suse.de Date: Thu, 21 Feb 2013 13:41:51 +1100 Message-Id: <1361414512-11147-3-git-send-email-david@gibson.dropbear.id.au> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1361414512-11147-1-git-send-email-david@gibson.dropbear.id.au> References: <1361414512-11147-1-git-send-email-david@gibson.dropbear.id.au> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2402:b800:7003:1:1::1 Cc: qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Subject: [Qemu-devel] [PATCH 2/3] target-ppc: Synchronize FPU state with KVM X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Currently qemu does not get and put the state of the floating point and vector registers to KVM. This is obviously a problem for savevm, as well as possibly being problematic for debugging of FP-using guests. This patch fixes this by using new extensions to the ONE_REG interface to synchronize the qemu floating point state with KVM. Signed-off-by: David Gibson --- target-ppc/kvm.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index cf5fd9e..5a6f608 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -521,6 +521,132 @@ static void kvm_put_one_spr(CPUState *cs, uint64_t id, int spr) } } +static int kvm_put_fp(CPUState *cs) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + struct kvm_one_reg reg; + int i; + int ret; + + if (env->insns_flags & PPC_FLOAT) { + uint64_t fpscr = env->fpscr; + bool vsx = !!(env->insns_flags2 & PPC2_VSX); + + reg.id = KVM_REG_PPC_FPSCR; + reg.addr = (uintptr_t)&fpscr; + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to set FPSCR to KVM: %s\n", strerror(errno)); + return ret; + } + + for (i = 0; i < 32; i++) { + uint64_t vsr[2]; + + vsr[0] = float64_val(env->fpr[i]); + vsr[1] = env->vsr[i]; + reg.addr = (uintptr_t) &vsr; + reg.id = vsx ? KVM_REG_PPC_VSR(i) : KVM_REG_PPC_FPR(i); + + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to set %s%d to KVM: %s\n", vsx ? "VSR" : "FPR", + i, strerror(errno)); + return ret; + } + } + } + + if (env->insns_flags & PPC_ALTIVEC) { + reg.id = KVM_REG_PPC_VSCR; + reg.addr = (uintptr_t)&env->vscr; + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to set VSCR to KVM: %s\n", strerror(errno)); + return ret; + } + + for (i = 0; i < 32; i++) { + reg.id = KVM_REG_PPC_VR(i); + reg.addr = (uintptr_t)&env->avr[i]; + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to set VR%d to KVM: %s\n", i, strerror(errno)); + return ret; + } + } + } + + return 0; +} + +static int kvm_get_fp(CPUState *cs) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + struct kvm_one_reg reg; + int i; + int ret; + + if (env->insns_flags & PPC_FLOAT) { + uint64_t fpscr; + bool vsx = !!(env->insns_flags2 & PPC2_VSX); + + reg.id = KVM_REG_PPC_FPSCR; + reg.addr = (uintptr_t)&fpscr; + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to get FPSCR from KVM: %s\n", strerror(errno)); + return ret; + } else { + env->fpscr = fpscr; + } + + for (i = 0; i < 32; i++) { + uint64_t vsr[2]; + + reg.addr = (uintptr_t) &vsr; + reg.id = vsx ? KVM_REG_PPC_VSR(i) : KVM_REG_PPC_FPR(i); + + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to get %s%d from KVM: %s\n", + vsx ? "VSR" : "FPR", i, strerror(errno)); + return ret; + } else { + env->fpr[i] = vsr[0]; + if (vsx) { + env->vsr[i] = vsr[1]; + } + } + } + } + + if (env->insns_flags & PPC_ALTIVEC) { + reg.id = KVM_REG_PPC_VSCR; + reg.addr = (uintptr_t)&env->vscr; + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to get VSCR from KVM: %s\n", strerror(errno)); + return ret; + } + + for (i = 0; i < 32; i++) { + reg.id = KVM_REG_PPC_VR(i); + reg.addr = (uintptr_t)&env->avr[i]; + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to get VR%d from KVM: %s\n", + i, strerror(errno)); + return ret; + } + } + } + + return 0; +} + int kvm_arch_put_registers(CPUState *cs, int level) { PowerPCCPU *cpu = POWERPC_CPU(cs); @@ -561,6 +687,8 @@ int kvm_arch_put_registers(CPUState *cs, int level) if (ret < 0) return ret; + kvm_put_fp(cs); + if (env->tlb_dirty) { kvm_sw_tlb_put(cpu); env->tlb_dirty = false; @@ -666,6 +794,8 @@ int kvm_arch_get_registers(CPUState *cs) for (i = 0;i < 32; i++) env->gpr[i] = regs.gpr[i]; + kvm_get_fp(cs); + if (cap_booke_sregs) { ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs); if (ret < 0) {