qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-devel@nongnu.org
Cc: kvm@vger.kernel.org, patches@linaro.org,
	"Marcelo Tosatti" <mtosatti@redhat.com>,
	kvmarm@lists.cs.columbia.edu, "Blue Swirl" <blauwirbel@gmail.com>,
	"Avi Kivity" <avi@redhat.com>,
	"Andreas Färber" <afaerber@suse.de>
Subject: [Qemu-devel] [RFC v3 3/8] ARM KVM: save and load VFP registers from kernel
Date: Tue, 23 Oct 2012 11:50:23 +0100	[thread overview]
Message-ID: <1350989428-941-4-git-send-email-peter.maydell@linaro.org> (raw)
In-Reply-To: <1350989428-941-1-git-send-email-peter.maydell@linaro.org>

Add support for saving and restoring VFP register state from the
kernel. This includes a check that the KVM-created CPU has full
VFP support (as the TCG Cortex-A15 model always does), since for
the moment ARM QEMU doesn't have any way to tweak optional features
on created CPUs.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/kvm.c |   78 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 75 insertions(+), 3 deletions(-)

diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index f80c707..f7d2235 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -38,10 +38,28 @@ int kvm_arch_init(KVMState *s)
 int kvm_arch_init_vcpu(CPUARMState *env)
 {
     struct kvm_vcpu_init init;
+    int ret;
+    uint64_t v;
+    struct kvm_one_reg r;
 
     init.target = KVM_ARM_TARGET_CORTEX_A15;
     memset(init.features, 0, sizeof(init.features));
-    return kvm_vcpu_ioctl(env, KVM_ARM_VCPU_INIT, &init);
+    ret = kvm_vcpu_ioctl(env, KVM_ARM_VCPU_INIT, &init);
+    if (ret) {
+        return ret;
+    }
+    /* Query the kernel to make sure it supports 32 VFP
+     * registers: QEMU's "cortex-a15" CPU is always a
+     * VFP-D32 core. The simplest way to do this is just
+     * to attempt to read register d31.
+     */
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP | 31;
+    r.addr = (uintptr_t)(&v);
+    ret = kvm_vcpu_ioctl(env, KVM_GET_ONE_REG, &r);
+    if (ret == ENOENT) {
+        return EINVAL;
+    }
+    return ret;
 }
 
 typedef struct Reg {
@@ -67,6 +85,13 @@ typedef struct Reg {
         offsetof(CPUARMState, QEMUFIELD)         \
     }
 
+#define VFPSYSREG(R)                                       \
+    {                                                      \
+        KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP | \
+        KVM_REG_ARM_VFP_##R,                               \
+        offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R])      \
+    }
+
 static const Reg regs[] = {
     /* R0_usr .. R14_usr */
     COREREG(usr_regs[0], regs[0]),
@@ -114,6 +139,13 @@ static const Reg regs[] = {
     CP15REG(1, 0, 0, 0, cp15.c1_sys), /* SCTLR */
     CP15REG(2, 0, 0, 2, cp15.c2_control), /* TTBCR */
     CP15REG(3, 0, 0, 0, cp15.c3), /* DACR */
+    /* VFP system registers */
+    VFPSYSREG(FPSID),
+    VFPSYSREG(MVFR1),
+    VFPSYSREG(MVFR0),
+    VFPSYSREG(FPEXC),
+    VFPSYSREG(FPINST),
+    VFPSYSREG(FPINST2),
 };
 
 int kvm_arch_put_registers(CPUARMState *env, int level)
@@ -121,7 +153,7 @@ int kvm_arch_put_registers(CPUARMState *env, int level)
     struct kvm_one_reg r;
     int mode, bn;
     int ret, i;
-    uint32_t cpsr;
+    uint32_t cpsr, fpscr;
     uint64_t ttbr;
 
     /* Make sure the banked regs are properly set */
@@ -172,6 +204,26 @@ int kvm_arch_put_registers(CPUARMState *env, int level)
         (2 << KVM_REG_ARM_CRM_SHIFT) | (1 << KVM_REG_ARM_OPC1_SHIFT);
     r.addr = (uintptr_t)(&ttbr);
     ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, &r);
+    if (ret) {
+        return ret;
+    }
+
+    /* VFP registers */
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
+    for (i = 0; i < 32; i++) {
+        r.addr = (uintptr_t)(&env->vfp.regs[i]);
+        ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, &r);
+        if (ret) {
+            return ret;
+        }
+        r.id++;
+    }
+
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
+        KVM_REG_ARM_VFP_FPSCR;
+    fpscr = vfp_get_fpscr(env);
+    r.addr = (uintptr_t)&fpscr;
+    ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, &r);
 
     return ret;
 }
@@ -181,7 +233,7 @@ int kvm_arch_get_registers(CPUARMState *env)
     struct kvm_one_reg r;
     int mode, bn;
     int ret, i;
-    uint32_t cpsr;
+    uint32_t cpsr, fpscr;
     uint64_t ttbr;
 
     for (i = 0; i < ARRAY_SIZE(regs); i++) {
@@ -246,6 +298,26 @@ int kvm_arch_get_registers(CPUARMState *env)
     env->cp15.c2_mask = ~(0xffffffffu >> env->cp15.c2_control);
     env->cp15.c2_base_mask = ~(0x3fffu >> env->cp15.c2_control);
 
+    /* VFP registers */
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
+    for (i = 0; i < 32; i++) {
+        r.addr = (uintptr_t)(&env->vfp.regs[i]);
+        ret = kvm_vcpu_ioctl(env, KVM_GET_ONE_REG, &r);
+        if (ret) {
+            return ret;
+        }
+        r.id++;
+    }
+
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
+        KVM_REG_ARM_VFP_FPSCR;
+    r.addr = (uintptr_t)&fpscr;
+    ret = kvm_vcpu_ioctl(env, KVM_GET_ONE_REG, &r);
+    if (ret) {
+        return ret;
+    }
+    vfp_set_fpscr(env, fpscr);
+
     return 0;
 }
 
-- 
1.7.9.5

  parent reply	other threads:[~2012-10-23 10:56 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-23 10:50 [Qemu-devel] [RFC v3 0/8] QEMU: Support KVM on ARM Peter Maydell
2012-10-23 10:50 ` [Qemu-devel] [RFC v3 1/8] linux-headers: Add ARM KVM headers (not for upstream) Peter Maydell
2012-10-23 10:50 ` [Qemu-devel] [RFC v3 2/8] ARM: KVM: Add support for KVM on ARM architecture Peter Maydell
2012-10-23 10:50 ` Peter Maydell [this message]
2012-10-23 10:50 ` [Qemu-devel] [RFC v3 4/8] hw/arm_gic: Add presave/postload hooks Peter Maydell
2012-10-23 10:50 ` [Qemu-devel] [RFC v3 5/8] linux-headers: update with VGIC related headers (not for upstream) Peter Maydell
2012-10-23 10:50 ` [Qemu-devel] [RFC v3 6/8] target-arm: Use MemoryListener to identify GIC base address for KVM Peter Maydell
2012-10-23 10:50 ` [Qemu-devel] [RFC v3 7/8] hw/kvm/arm_gic: Implement support for KVM in-kernel ARM GIC Peter Maydell
2012-10-23 10:50 ` [Qemu-devel] [RFC v3 8/8] configure: Enable KVM on ARM Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1350989428-941-4-git-send-email-peter.maydell@linaro.org \
    --to=peter.maydell@linaro.org \
    --cc=afaerber@suse.de \
    --cc=avi@redhat.com \
    --cc=blauwirbel@gmail.com \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.cs.columbia.edu \
    --cc=mtosatti@redhat.com \
    --cc=patches@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).