qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests
@ 2016-02-03 17:16 James Hogan
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 1/7] mips/kvm: Remove a couple of noisy DPRINTFs James Hogan
                   ` (7 more replies)
  0 siblings, 8 replies; 10+ messages in thread
From: James Hogan @ 2016-02-03 17:16 UTC (permalink / raw)
  To: qemu-devel, Leon Alrae; +Cc: Paolo Bonzini, James Hogan, Aurelien Jarno, kvm

Here's a v5 refresh of my FPU/MSA patchset for v2.6. Thanks to all who
have taken the time to review it so far.

This patchset primarily adds support for FPU and MIPS SIMD Architecture
(MSA) in MIPS KVM guests to QEMU. It depends on Linux v4.1, specifically
my KVM patchset to add the corresponding hypervisor support to KVM
("[PATCH 00/20] MIPS: KVM: Guest FPU & SIMD (MSA) support").

All comments welcome.

Changes in v5:
- Rebase on master (fixed use of uint64 in patch 5).
- Use restore_fp_status(env) in patch 6.
- Restore MSA FP state using restore_msa_fp_status(env) in patch 7
  (Leon).

Changes in v4:
- Rebase on master (dropped patch 1 & 2).

Changes in v3 (patch 6 only):
- Fix big endian (the pointer passed to the kernel must be for the
  actual 32-bit value, not a temporary 64-bit value, otherwise on big
  endian systems the kernel will only interpret the upper half).

Changes in v2:
- Moved most of patch 7 and updates to linux-headers/linux/kvm.h from
  patches 8 and 9 into a new patch 1, which is purely for reference
  (Paolo).
- Add the changes to MIPS_CP0_{32,64} macros from v1 patch 7 to patch 2,
  since the rest of that patch is now unnecessary and the change is
  along the same lines as patch 2 (not added Leon's Reviewed-by to this
  patch due to that non-reviewed change).
- Fix line wrapping of kvm_mips_get_one_reg() calls from Config4 and
  Config5 in patch 5 (Leon).
- Change (1 << x) to (1U << x) in important places in patch 5, 8 & 9 to
  avoid compiler undefined behaviour (Leon).

James Hogan (7):
  mips/kvm: Remove a couple of noisy DPRINTFs
  mips/kvm: Implement PRid CP0 register
  mips/kvm: Implement Config CP0 registers
  mips/kvm: Support unsigned KVM registers
  mips/kvm: Support signed 64-bit KVM registers
  mips/kvm: Support FPU in MIPS KVM guests
  mips/kvm: Support MSA in MIPS KVM guests

 target-mips/kvm.c | 387 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 374 insertions(+), 13 deletions(-)

-- 
2.4.10

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v5 1/7] mips/kvm: Remove a couple of noisy DPRINTFs
  2016-02-03 17:16 [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
@ 2016-02-03 17:16 ` James Hogan
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 2/7] mips/kvm: Implement PRid CP0 register James Hogan
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: James Hogan @ 2016-02-03 17:16 UTC (permalink / raw)
  To: qemu-devel, Leon Alrae; +Cc: Paolo Bonzini, James Hogan, Aurelien Jarno, kvm

The DPRINTFs in cpu_mips_io_interrupts_pending() and kvm_arch_pre_run()
are particularly noisy during normal execution, and also not
particularly helpful. Remove them so that more important debug messages
can be more easily seen.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
 target-mips/kvm.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index a8b8b32c267b..8bd74385110b 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -88,7 +88,6 @@ static inline int cpu_mips_io_interrupts_pending(MIPSCPU *cpu)
 {
     CPUMIPSState *env = &cpu->env;
 
-    DPRINTF("%s: %#x\n", __func__, env->CP0_Cause & (1 << (2 + CP0Ca_IP)));
     return env->CP0_Cause & (0x1 << (2 + CP0Ca_IP));
 }
 
@@ -117,7 +116,6 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
 
 MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
 {
-    DPRINTF("%s\n", __func__);
     return MEMTXATTRS_UNSPECIFIED;
 }
 
-- 
2.4.10

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v5 2/7] mips/kvm: Implement PRid CP0 register
  2016-02-03 17:16 [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 1/7] mips/kvm: Remove a couple of noisy DPRINTFs James Hogan
@ 2016-02-03 17:16 ` James Hogan
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 3/7] mips/kvm: Implement Config CP0 registers James Hogan
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: James Hogan @ 2016-02-03 17:16 UTC (permalink / raw)
  To: qemu-devel, Leon Alrae; +Cc: Paolo Bonzini, James Hogan, Aurelien Jarno, kvm

Implement saving and restoring to KVM state of the Processor ID (PRid)
CP0 register. This allows QEMU to control the PRid exposed to the guest
instead of using the default set by KVM.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
 target-mips/kvm.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index 8bd74385110b..c5bf44da9f02 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -228,6 +228,7 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
 #define KVM_REG_MIPS_CP0_STATUS         MIPS_CP0_32(12, 0)
 #define KVM_REG_MIPS_CP0_CAUSE          MIPS_CP0_32(13, 0)
 #define KVM_REG_MIPS_CP0_EPC            MIPS_CP0_64(14, 0)
+#define KVM_REG_MIPS_CP0_PRID           MIPS_CP0_32(15, 0)
 #define KVM_REG_MIPS_CP0_ERROREPC       MIPS_CP0_64(30, 0)
 
 static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id,
@@ -520,6 +521,11 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
         DPRINTF("%s: Failed to put CP0_EPC (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_PRID (%d)\n", __func__, err);
+        ret = err;
+    }
     err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
                                  &env->CP0_ErrorEPC);
     if (err < 0) {
@@ -606,6 +612,11 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
         DPRINTF("%s: Failed to get CP0_EPC (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_PRID (%d)\n", __func__, err);
+        ret = err;
+    }
     err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
                                  &env->CP0_ErrorEPC);
     if (err < 0) {
-- 
2.4.10

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v5 3/7] mips/kvm: Implement Config CP0 registers
  2016-02-03 17:16 [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 1/7] mips/kvm: Remove a couple of noisy DPRINTFs James Hogan
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 2/7] mips/kvm: Implement PRid CP0 register James Hogan
@ 2016-02-03 17:16 ` James Hogan
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 4/7] mips/kvm: Support unsigned KVM registers James Hogan
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: James Hogan @ 2016-02-03 17:16 UTC (permalink / raw)
  To: qemu-devel, Leon Alrae; +Cc: Paolo Bonzini, James Hogan, Aurelien Jarno, kvm

Implement saving and restoring to KVM state of the Config CP0 registers
(namely Config, Config1, Config2, Config3, Config4, and Config5). These
control the features available to a guest, and a few of the fields will
soon be writeable by a guest so QEMU needs to know about them so as not
to clobber them on migration/savevm.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Leon Alrae <leon.alrae@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v2:
- Fix line wrapping of kvm_mips_get_one_reg() calls from Config4 and
  Config5 (Leon).
- Change (1 << x) to (1U << x) in important places to avoid compiler
  defined behaviour (Leon).
---
 target-mips/kvm.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index c5bf44da9f02..57cde9dd4df6 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -229,6 +229,12 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
 #define KVM_REG_MIPS_CP0_CAUSE          MIPS_CP0_32(13, 0)
 #define KVM_REG_MIPS_CP0_EPC            MIPS_CP0_64(14, 0)
 #define KVM_REG_MIPS_CP0_PRID           MIPS_CP0_32(15, 0)
+#define KVM_REG_MIPS_CP0_CONFIG         MIPS_CP0_32(16, 0)
+#define KVM_REG_MIPS_CP0_CONFIG1        MIPS_CP0_32(16, 1)
+#define KVM_REG_MIPS_CP0_CONFIG2        MIPS_CP0_32(16, 2)
+#define KVM_REG_MIPS_CP0_CONFIG3        MIPS_CP0_32(16, 3)
+#define KVM_REG_MIPS_CP0_CONFIG4        MIPS_CP0_32(16, 4)
+#define KVM_REG_MIPS_CP0_CONFIG5        MIPS_CP0_32(16, 5)
 #define KVM_REG_MIPS_CP0_ERROREPC       MIPS_CP0_64(30, 0)
 
 static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id,
@@ -304,6 +310,34 @@ static inline int kvm_mips_get_one_reg64(CPUState *cs, uint64_t reg_id,
     return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
 }
 
+#define KVM_REG_MIPS_CP0_CONFIG_MASK    (1U << CP0C0_M)
+#define KVM_REG_MIPS_CP0_CONFIG1_MASK   (1U << CP0C1_M)
+#define KVM_REG_MIPS_CP0_CONFIG2_MASK   (1U << CP0C2_M)
+#define KVM_REG_MIPS_CP0_CONFIG3_MASK   (1U << CP0C3_M)
+#define KVM_REG_MIPS_CP0_CONFIG4_MASK   (1U << CP0C4_M)
+#define KVM_REG_MIPS_CP0_CONFIG5_MASK   0
+
+static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id,
+                                          int32_t *addr, int32_t mask)
+{
+    int err;
+    int32_t tmp, change;
+
+    err = kvm_mips_get_one_reg(cs, reg_id, &tmp);
+    if (err < 0) {
+        return err;
+    }
+
+    /* only change bits in mask */
+    change = (*addr ^ tmp) & mask;
+    if (!change) {
+        return 0;
+    }
+
+    tmp = tmp ^ change;
+    return kvm_mips_put_one_reg(cs, reg_id, &tmp);
+}
+
 /*
  * We freeze the KVM timer when either the VM clock is stopped or the state is
  * saved (the state is dirty).
@@ -526,6 +560,48 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
         DPRINTF("%s: Failed to put CP0_PRID (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG,
+                                  &env->CP0_Config0,
+                                  KVM_REG_MIPS_CP0_CONFIG_MASK);
+    if (err < 0) {
+        DPRINTF("%s: Failed to change CP0_CONFIG (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1,
+                                  &env->CP0_Config1,
+                                  KVM_REG_MIPS_CP0_CONFIG1_MASK);
+    if (err < 0) {
+        DPRINTF("%s: Failed to change CP0_CONFIG1 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2,
+                                  &env->CP0_Config2,
+                                  KVM_REG_MIPS_CP0_CONFIG2_MASK);
+    if (err < 0) {
+        DPRINTF("%s: Failed to change CP0_CONFIG2 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3,
+                                  &env->CP0_Config3,
+                                  KVM_REG_MIPS_CP0_CONFIG3_MASK);
+    if (err < 0) {
+        DPRINTF("%s: Failed to change CP0_CONFIG3 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4,
+                                  &env->CP0_Config4,
+                                  KVM_REG_MIPS_CP0_CONFIG4_MASK);
+    if (err < 0) {
+        DPRINTF("%s: Failed to change CP0_CONFIG4 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5,
+                                  &env->CP0_Config5,
+                                  KVM_REG_MIPS_CP0_CONFIG5_MASK);
+    if (err < 0) {
+        DPRINTF("%s: Failed to change CP0_CONFIG5 (%d)\n", __func__, err);
+        ret = err;
+    }
     err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
                                  &env->CP0_ErrorEPC);
     if (err < 0) {
@@ -617,6 +693,36 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
         DPRINTF("%s: Failed to get CP0_PRID (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, &env->CP0_Config0);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_CONFIG (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1, &env->CP0_Config1);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_CONFIG1 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2, &env->CP0_Config2);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_CONFIG2 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3, &env->CP0_Config3);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_CONFIG3 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4, &env->CP0_Config4);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_CONFIG4 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5, &env->CP0_Config5);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_CONFIG5 (%d)\n", __func__, err);
+        ret = err;
+    }
     err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
                                  &env->CP0_ErrorEPC);
     if (err < 0) {
-- 
2.4.10

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v5 4/7] mips/kvm: Support unsigned KVM registers
  2016-02-03 17:16 [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
                   ` (2 preceding siblings ...)
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 3/7] mips/kvm: Implement Config CP0 registers James Hogan
@ 2016-02-03 17:16 ` James Hogan
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 5/7] mips/kvm: Support signed 64-bit " James Hogan
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: James Hogan @ 2016-02-03 17:16 UTC (permalink / raw)
  To: qemu-devel, Leon Alrae; +Cc: Paolo Bonzini, James Hogan, Aurelien Jarno, kvm

Add KVM register access functions for the uint32_t type. This is
required for FP and MSA control registers, which are represented as
unsigned 32-bit integers.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Leon Alrae <leon.alrae@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v3:
- Fix big endian (the pointer passed to the kernel must be for the
  actual 32-bit value, not a temporary 64-bit value, otherwise on big
  endian systems the kernel will only interpret the upper half).
---
 target-mips/kvm.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index 57cde9dd4df6..abdd6b66256c 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -248,6 +248,17 @@ static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id,
     return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
 }
 
+static inline int kvm_mips_put_one_ureg(CPUState *cs, uint64_t reg_id,
+                                        uint32_t *addr)
+{
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)addr
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
+}
+
 static inline int kvm_mips_put_one_ulreg(CPUState *cs, uint64_t reg_id,
                                          target_ulong *addr)
 {
@@ -282,6 +293,17 @@ static inline int kvm_mips_get_one_reg(CPUState *cs, uint64_t reg_id,
     return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
 }
 
+static inline int kvm_mips_get_one_ureg(CPUState *cs, uint64_t reg_id,
+                                        uint32_t *addr)
+{
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)addr
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
+}
+
 static inline int kvm_mips_get_one_ulreg(CPUState *cs, uint64_t reg_id,
                                          target_ulong *addr)
 {
-- 
2.4.10

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v5 5/7] mips/kvm: Support signed 64-bit KVM registers
  2016-02-03 17:16 [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
                   ` (3 preceding siblings ...)
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 4/7] mips/kvm: Support unsigned KVM registers James Hogan
@ 2016-02-03 17:16 ` James Hogan
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 6/7] mips/kvm: Support FPU in MIPS KVM guests James Hogan
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: James Hogan @ 2016-02-03 17:16 UTC (permalink / raw)
  To: qemu-devel, Leon Alrae; +Cc: Paolo Bonzini, James Hogan, Aurelien Jarno, kvm

Rename kvm_mips_{get,put}_one_reg64() to kvm_mips_{get,put}_one_ureg64()
since they take an int64_t pointer, and add separate signed 64-bit
accessors. These will be used for double precision floating point
registers.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Leon Alrae <leon.alrae@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
 target-mips/kvm.c | 40 +++++++++++++++++++++++++++++++---------
 1 file changed, 31 insertions(+), 9 deletions(-)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index abdd6b66256c..a297b5a58339 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -272,7 +272,18 @@ static inline int kvm_mips_put_one_ulreg(CPUState *cs, uint64_t reg_id,
 }
 
 static inline int kvm_mips_put_one_reg64(CPUState *cs, uint64_t reg_id,
-                                         uint64_t *addr)
+                                         int64_t *addr)
+{
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)addr
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
+}
+
+static inline int kvm_mips_put_one_ureg64(CPUState *cs, uint64_t reg_id,
+                                          uint64_t *addr)
 {
     struct kvm_one_reg cp0reg = {
         .id = reg_id,
@@ -322,7 +333,18 @@ static inline int kvm_mips_get_one_ulreg(CPUState *cs, uint64_t reg_id,
 }
 
 static inline int kvm_mips_get_one_reg64(CPUState *cs, uint64_t reg_id,
-                                         uint64_t *addr)
+                                         int64_t *addr)
+{
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)addr
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
+}
+
+static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64_t reg_id,
+                                          uint64_t *addr)
 {
     struct kvm_one_reg cp0reg = {
         .id = reg_id,
@@ -377,13 +399,13 @@ static int kvm_mips_save_count(CPUState *cs)
     int err, ret = 0;
 
     /* freeze KVM timer */
-    err = kvm_mips_get_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
+    err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
     if (err < 0) {
         DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err);
         ret = err;
     } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) {
         count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC;
-        err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
+        err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
         if (err < 0) {
             DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err);
             ret = err;
@@ -419,14 +441,14 @@ static int kvm_mips_restore_count(CPUState *cs)
     int err_dc, err, ret = 0;
 
     /* check the timer is frozen */
-    err_dc = kvm_mips_get_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
+    err_dc = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
     if (err_dc < 0) {
         DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err_dc);
         ret = err_dc;
     } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) {
         /* freeze timer (sets COUNT_RESUME for us) */
         count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC;
-        err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
+        err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
         if (err < 0) {
             DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err);
             ret = err;
@@ -450,7 +472,7 @@ static int kvm_mips_restore_count(CPUState *cs)
     /* resume KVM timer */
     if (err_dc >= 0) {
         count_ctl &= ~KVM_REG_MIPS_COUNT_CTL_DC;
-        err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
+        err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
         if (err < 0) {
             DPRINTF("%s: Failed to set COUNT_CTL.DC=0 (%d)\n", __func__, err);
             ret = err;
@@ -483,8 +505,8 @@ static void kvm_mips_update_state(void *opaque, int running, RunState state)
     } else {
         /* Set clock restore time to now */
         count_resume = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
-        ret = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_COUNT_RESUME,
-                                     &count_resume);
+        ret = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_RESUME,
+                                      &count_resume);
         if (ret < 0) {
             fprintf(stderr, "Failed setting COUNT_RESUME\n");
             return;
-- 
2.4.10

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v5 6/7] mips/kvm: Support FPU in MIPS KVM guests
  2016-02-03 17:16 [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
                   ` (4 preceding siblings ...)
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 5/7] mips/kvm: Support signed 64-bit " James Hogan
@ 2016-02-03 17:16 ` James Hogan
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 7/7] mips/kvm: Support MSA " James Hogan
  2016-02-04 10:04 ` [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) " Leon Alrae
  7 siblings, 0 replies; 10+ messages in thread
From: James Hogan @ 2016-02-03 17:16 UTC (permalink / raw)
  To: qemu-devel, Leon Alrae; +Cc: Paolo Bonzini, James Hogan, Aurelien Jarno, kvm

Support the new KVM_CAP_MIPS_FPU capability, which allows the host's FPU
to be exposed to the KVM guest.

The capability is enabled if the guest core has an FPU according to its
Config1 register. Various config bits are now writeable so that KVM is
aware of the configuration (Config1.FP) and so that QEMU can
save/restore the guest modifiable bits (Config5.FRE, Config5.UFR,
Config5.UFE). The FCSR/FIR registers and the floating point registers
are now saved/restored (depending on the FR mode bit).

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Leon Alrae <leon.alrae@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v5:
- Use restore_fp_status(env).

Changes in v2:
- Change (1 << x) to (1U << x) in important places to avoid compiler
  undefined behaviour (Leon).
- Removed update of linux-headers/linux/kvm.h (Paolo).
---
 target-mips/kvm.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 117 insertions(+), 4 deletions(-)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index a297b5a58339..a1f5b6012edd 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -30,6 +30,8 @@
 #define DPRINTF(fmt, ...) \
     do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0)
 
+static int kvm_mips_fpu_cap;
+
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_LAST_INFO
 };
@@ -46,16 +48,29 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
     /* MIPS has 128 signals */
     kvm_set_sigmask_len(s, 16);
 
+    kvm_mips_fpu_cap = kvm_check_extension(s, KVM_CAP_MIPS_FPU);
+
     DPRINTF("%s\n", __func__);
     return 0;
 }
 
 int kvm_arch_init_vcpu(CPUState *cs)
 {
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
     int ret = 0;
 
     qemu_add_vm_change_state_handler(kvm_mips_update_state, cs);
 
+    if (kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) {
+        ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_FPU, 0, 0);
+        if (ret < 0) {
+            /* mark unsupported so it gets disabled on reset */
+            kvm_mips_fpu_cap = 0;
+            ret = 0;
+        }
+    }
+
     DPRINTF("%s\n", __func__);
     return ret;
 }
@@ -64,8 +79,8 @@ void kvm_mips_reset_vcpu(MIPSCPU *cpu)
 {
     CPUMIPSState *env = &cpu->env;
 
-    if (env->CP0_Config1 & (1 << CP0C1_FP)) {
-        fprintf(stderr, "Warning: FPU not supported with KVM, disabling\n");
+    if (!kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) {
+        fprintf(stderr, "Warning: KVM does not support FPU, disabling\n");
         env->CP0_Config1 &= ~(1 << CP0C1_FP);
     }
 
@@ -355,11 +370,14 @@ static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64_t reg_id,
 }
 
 #define KVM_REG_MIPS_CP0_CONFIG_MASK    (1U << CP0C0_M)
-#define KVM_REG_MIPS_CP0_CONFIG1_MASK   (1U << CP0C1_M)
+#define KVM_REG_MIPS_CP0_CONFIG1_MASK   ((1U << CP0C1_M) | \
+                                         (1U << CP0C1_FP))
 #define KVM_REG_MIPS_CP0_CONFIG2_MASK   (1U << CP0C2_M)
 #define KVM_REG_MIPS_CP0_CONFIG3_MASK   (1U << CP0C3_M)
 #define KVM_REG_MIPS_CP0_CONFIG4_MASK   (1U << CP0C4_M)
-#define KVM_REG_MIPS_CP0_CONFIG5_MASK   0
+#define KVM_REG_MIPS_CP0_CONFIG5_MASK   ((1U << CP0C5_UFE) | \
+                                         (1U << CP0C5_FRE) | \
+                                         (1U << CP0C5_UFR))
 
 static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id,
                                           int32_t *addr, int32_t mask)
@@ -521,6 +539,95 @@ static void kvm_mips_update_state(void *opaque, int running, RunState state)
     }
 }
 
+static int kvm_mips_put_fpu_registers(CPUState *cs, int level)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+    int err, ret = 0;
+    unsigned int i;
+
+    /* Only put FPU state if we're emulating a CPU with an FPU */
+    if (env->CP0_Config1 & (1 << CP0C1_FP)) {
+        /* FPU Control Registers */
+        if (level == KVM_PUT_FULL_STATE) {
+            err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_IR,
+                                        &env->active_fpu.fcr0);
+            if (err < 0) {
+                DPRINTF("%s: Failed to put FCR_IR (%d)\n", __func__, err);
+                ret = err;
+            }
+        }
+        err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_CSR,
+                                    &env->active_fpu.fcr31);
+        if (err < 0) {
+            DPRINTF("%s: Failed to put FCR_CSR (%d)\n", __func__, err);
+            ret = err;
+        }
+
+        /* Floating point registers */
+        for (i = 0; i < 32; ++i) {
+            if (env->CP0_Status & (1 << CP0St_FR)) {
+                err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i),
+                                              &env->active_fpu.fpr[i].d);
+            } else {
+                err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i),
+                                      &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]);
+            }
+            if (err < 0) {
+                DPRINTF("%s: Failed to put FPR%u (%d)\n", __func__, i, err);
+                ret = err;
+            }
+        }
+    }
+
+    return ret;
+}
+
+static int kvm_mips_get_fpu_registers(CPUState *cs)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+    int err, ret = 0;
+    unsigned int i;
+
+    /* Only get FPU state if we're emulating a CPU with an FPU */
+    if (env->CP0_Config1 & (1 << CP0C1_FP)) {
+        /* FPU Control Registers */
+        err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_IR,
+                                    &env->active_fpu.fcr0);
+        if (err < 0) {
+            DPRINTF("%s: Failed to get FCR_IR (%d)\n", __func__, err);
+            ret = err;
+        }
+        err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_CSR,
+                                    &env->active_fpu.fcr31);
+        if (err < 0) {
+            DPRINTF("%s: Failed to get FCR_CSR (%d)\n", __func__, err);
+            ret = err;
+        } else {
+            restore_fp_status(env);
+        }
+
+        /* Floating point registers */
+        for (i = 0; i < 32; ++i) {
+            if (env->CP0_Status & (1 << CP0St_FR)) {
+                err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i),
+                                              &env->active_fpu.fpr[i].d);
+            } else {
+                err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i),
+                                      &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]);
+            }
+            if (err < 0) {
+                DPRINTF("%s: Failed to get FPR%u (%d)\n", __func__, i, err);
+                ret = err;
+            }
+        }
+    }
+
+    return ret;
+}
+
+
 static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
 {
     MIPSCPU *cpu = MIPS_CPU(cs);
@@ -805,6 +912,11 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         return ret;
     }
 
+    ret = kvm_mips_put_fpu_registers(cs, level);
+    if (ret < 0) {
+        return ret;
+    }
+
     return ret;
 }
 
@@ -832,6 +944,7 @@ int kvm_arch_get_registers(CPUState *cs)
     env->active_tc.PC = regs.pc;
 
     kvm_mips_get_cp0_registers(cs);
+    kvm_mips_get_fpu_registers(cs);
 
     return ret;
 }
-- 
2.4.10

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v5 7/7] mips/kvm: Support MSA in MIPS KVM guests
  2016-02-03 17:16 [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
                   ` (5 preceding siblings ...)
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 6/7] mips/kvm: Support FPU in MIPS KVM guests James Hogan
@ 2016-02-03 17:16 ` James Hogan
  2016-02-04 10:04 ` [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) " Leon Alrae
  7 siblings, 0 replies; 10+ messages in thread
From: James Hogan @ 2016-02-03 17:16 UTC (permalink / raw)
  To: qemu-devel, Leon Alrae; +Cc: Paolo Bonzini, James Hogan, Aurelien Jarno, kvm

Support the new KVM_CAP_MIPS_MSA capability, which allows MIPS SIMD
Architecture (MSA) to be exposed to the KVM guest.

The capability is enabled if the guest core has MSA according to its
Config3 register. Various config bits are now writeable so that KVM is
aware of the configuration (Config3.MSAP) and so that QEMU can
save/restore the guest modifiable bits (Config5.MSAEn). The MSACSR/MSAIR
registers and the MSA vector registers are now saved/restored. Since the
FP registers are a subset of the vector registers, they are omitted if
the guest has MSA.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Leon Alrae <leon.alrae@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v5:
- Restore MSA FP state using restore_msa_fp_status(env) (Leon).

Changes in v2:
- Change (1 << x) to (1U << x) in important places to avoid compiler
  undefined behaviour (Leon).
- Removed update of linux-headers/linux/kvm.h (Paolo).
---
 target-mips/kvm.c | 129 +++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 109 insertions(+), 20 deletions(-)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index a1f5b6012edd..950bc05b7c32 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -31,6 +31,7 @@
     do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0)
 
 static int kvm_mips_fpu_cap;
+static int kvm_mips_msa_cap;
 
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_LAST_INFO
@@ -49,6 +50,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
     kvm_set_sigmask_len(s, 16);
 
     kvm_mips_fpu_cap = kvm_check_extension(s, KVM_CAP_MIPS_FPU);
+    kvm_mips_msa_cap = kvm_check_extension(s, KVM_CAP_MIPS_MSA);
 
     DPRINTF("%s\n", __func__);
     return 0;
@@ -71,6 +73,15 @@ int kvm_arch_init_vcpu(CPUState *cs)
         }
     }
 
+    if (kvm_mips_msa_cap && env->CP0_Config3 & (1 << CP0C3_MSAP)) {
+        ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_MSA, 0, 0);
+        if (ret < 0) {
+            /* mark unsupported so it gets disabled on reset */
+            kvm_mips_msa_cap = 0;
+            ret = 0;
+        }
+    }
+
     DPRINTF("%s\n", __func__);
     return ret;
 }
@@ -83,6 +94,10 @@ void kvm_mips_reset_vcpu(MIPSCPU *cpu)
         fprintf(stderr, "Warning: KVM does not support FPU, disabling\n");
         env->CP0_Config1 &= ~(1 << CP0C1_FP);
     }
+    if (!kvm_mips_msa_cap && env->CP0_Config3 & (1 << CP0C3_MSAP)) {
+        fprintf(stderr, "Warning: KVM does not support MSA, disabling\n");
+        env->CP0_Config3 &= ~(1 << CP0C3_MSAP);
+    }
 
     DPRINTF("%s\n", __func__);
 }
@@ -373,9 +388,11 @@ static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64_t reg_id,
 #define KVM_REG_MIPS_CP0_CONFIG1_MASK   ((1U << CP0C1_M) | \
                                          (1U << CP0C1_FP))
 #define KVM_REG_MIPS_CP0_CONFIG2_MASK   (1U << CP0C2_M)
-#define KVM_REG_MIPS_CP0_CONFIG3_MASK   (1U << CP0C3_M)
+#define KVM_REG_MIPS_CP0_CONFIG3_MASK   ((1U << CP0C3_M) | \
+                                         (1U << CP0C3_MSAP))
 #define KVM_REG_MIPS_CP0_CONFIG4_MASK   (1U << CP0C4_M)
-#define KVM_REG_MIPS_CP0_CONFIG5_MASK   ((1U << CP0C5_UFE) | \
+#define KVM_REG_MIPS_CP0_CONFIG5_MASK   ((1U << CP0C5_MSAEn) | \
+                                         (1U << CP0C5_UFE) | \
                                          (1U << CP0C5_FRE) | \
                                          (1U << CP0C5_UFR))
 
@@ -564,17 +581,53 @@ static int kvm_mips_put_fpu_registers(CPUState *cs, int level)
             ret = err;
         }
 
-        /* Floating point registers */
+        /*
+         * FPU register state is a subset of MSA vector state, so don't put FPU
+         * registers if we're emulating a CPU with MSA.
+         */
+        if (!(env->CP0_Config3 & (1 << CP0C3_MSAP))) {
+            /* Floating point registers */
+            for (i = 0; i < 32; ++i) {
+                if (env->CP0_Status & (1 << CP0St_FR)) {
+                    err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i),
+                                                  &env->active_fpu.fpr[i].d);
+                } else {
+                    err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i),
+                                    &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]);
+                }
+                if (err < 0) {
+                    DPRINTF("%s: Failed to put FPR%u (%d)\n", __func__, i, err);
+                    ret = err;
+                }
+            }
+        }
+    }
+
+    /* Only put MSA state if we're emulating a CPU with MSA */
+    if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
+        /* MSA Control Registers */
+        if (level == KVM_PUT_FULL_STATE) {
+            err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_IR,
+                                       &env->msair);
+            if (err < 0) {
+                DPRINTF("%s: Failed to put MSA_IR (%d)\n", __func__, err);
+                ret = err;
+            }
+        }
+        err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_CSR,
+                                   &env->active_tc.msacsr);
+        if (err < 0) {
+            DPRINTF("%s: Failed to put MSA_CSR (%d)\n", __func__, err);
+            ret = err;
+        }
+
+        /* Vector registers (includes FP registers) */
         for (i = 0; i < 32; ++i) {
-            if (env->CP0_Status & (1 << CP0St_FR)) {
-                err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i),
-                                              &env->active_fpu.fpr[i].d);
-            } else {
-                err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i),
-                                      &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]);
-            }
+            /* Big endian MSA not supported by QEMU yet anyway */
+            err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_VEC_128(i),
+                                         env->active_fpu.fpr[i].wr.d);
             if (err < 0) {
-                DPRINTF("%s: Failed to put FPR%u (%d)\n", __func__, i, err);
+                DPRINTF("%s: Failed to put VEC%u (%d)\n", __func__, i, err);
                 ret = err;
             }
         }
@@ -608,17 +661,53 @@ static int kvm_mips_get_fpu_registers(CPUState *cs)
             restore_fp_status(env);
         }
 
-        /* Floating point registers */
-        for (i = 0; i < 32; ++i) {
-            if (env->CP0_Status & (1 << CP0St_FR)) {
-                err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i),
-                                              &env->active_fpu.fpr[i].d);
-            } else {
-                err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i),
-                                      &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]);
+        /*
+         * FPU register state is a subset of MSA vector state, so don't save FPU
+         * registers if we're emulating a CPU with MSA.
+         */
+        if (!(env->CP0_Config3 & (1 << CP0C3_MSAP))) {
+            /* Floating point registers */
+            for (i = 0; i < 32; ++i) {
+                if (env->CP0_Status & (1 << CP0St_FR)) {
+                    err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i),
+                                                  &env->active_fpu.fpr[i].d);
+                } else {
+                    err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i),
+                                    &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]);
+                }
+                if (err < 0) {
+                    DPRINTF("%s: Failed to get FPR%u (%d)\n", __func__, i, err);
+                    ret = err;
+                }
             }
+        }
+    }
+
+    /* Only get MSA state if we're emulating a CPU with MSA */
+    if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
+        /* MSA Control Registers */
+        err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_IR,
+                                   &env->msair);
+        if (err < 0) {
+            DPRINTF("%s: Failed to get MSA_IR (%d)\n", __func__, err);
+            ret = err;
+        }
+        err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_CSR,
+                                   &env->active_tc.msacsr);
+        if (err < 0) {
+            DPRINTF("%s: Failed to get MSA_CSR (%d)\n", __func__, err);
+            ret = err;
+        } else {
+            restore_msa_fp_status(env);
+        }
+
+        /* Vector registers (includes FP registers) */
+        for (i = 0; i < 32; ++i) {
+            /* Big endian MSA not supported by QEMU yet anyway */
+            err = kvm_mips_get_one_reg64(cs, KVM_REG_MIPS_VEC_128(i),
+                                         env->active_fpu.fpr[i].wr.d);
             if (err < 0) {
-                DPRINTF("%s: Failed to get FPR%u (%d)\n", __func__, i, err);
+                DPRINTF("%s: Failed to get VEC%u (%d)\n", __func__, i, err);
                 ret = err;
             }
         }
-- 
2.4.10

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests
  2016-02-03 17:16 [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
                   ` (6 preceding siblings ...)
  2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 7/7] mips/kvm: Support MSA " James Hogan
@ 2016-02-04 10:04 ` Leon Alrae
  2016-02-05 10:46   ` James Hogan
  7 siblings, 1 reply; 10+ messages in thread
From: Leon Alrae @ 2016-02-04 10:04 UTC (permalink / raw)
  To: James Hogan, qemu-devel; +Cc: Paolo Bonzini, Aurelien Jarno, kvm

On 03/02/16 17:16, James Hogan wrote:
> Here's a v5 refresh of my FPU/MSA patchset for v2.6. Thanks to all who
> have taken the time to review it so far.
> 
> This patchset primarily adds support for FPU and MIPS SIMD Architecture
> (MSA) in MIPS KVM guests to QEMU. It depends on Linux v4.1, specifically
> my KVM patchset to add the corresponding hypervisor support to KVM
> ("[PATCH 00/20] MIPS: KVM: Guest FPU & SIMD (MSA) support").
> 
> All comments welcome.
> 
> Changes in v5:
> - Rebase on master (fixed use of uint64 in patch 5).
> - Use restore_fp_status(env) in patch 6.
> - Restore MSA FP state using restore_msa_fp_status(env) in patch 7
>   (Leon).
> 
> Changes in v4:
> - Rebase on master (dropped patch 1 & 2).
> 
> Changes in v3 (patch 6 only):
> - Fix big endian (the pointer passed to the kernel must be for the
>   actual 32-bit value, not a temporary 64-bit value, otherwise on big
>   endian systems the kernel will only interpret the upper half).
> 
> Changes in v2:
> - Moved most of patch 7 and updates to linux-headers/linux/kvm.h from
>   patches 8 and 9 into a new patch 1, which is purely for reference
>   (Paolo).
> - Add the changes to MIPS_CP0_{32,64} macros from v1 patch 7 to patch 2,
>   since the rest of that patch is now unnecessary and the change is
>   along the same lines as patch 2 (not added Leon's Reviewed-by to this
>   patch due to that non-reviewed change).
> - Fix line wrapping of kvm_mips_get_one_reg() calls from Config4 and
>   Config5 in patch 5 (Leon).
> - Change (1 << x) to (1U << x) in important places in patch 5, 8 & 9 to
>   avoid compiler undefined behaviour (Leon).
> 
> James Hogan (7):
>   mips/kvm: Remove a couple of noisy DPRINTFs
>   mips/kvm: Implement PRid CP0 register
>   mips/kvm: Implement Config CP0 registers
>   mips/kvm: Support unsigned KVM registers
>   mips/kvm: Support signed 64-bit KVM registers
>   mips/kvm: Support FPU in MIPS KVM guests
>   mips/kvm: Support MSA in MIPS KVM guests
> 
>  target-mips/kvm.c | 387 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 374 insertions(+), 13 deletions(-)
> 

I've applied the series to my target-mips queue, thanks.

Leon

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests
  2016-02-04 10:04 ` [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) " Leon Alrae
@ 2016-02-05 10:46   ` James Hogan
  0 siblings, 0 replies; 10+ messages in thread
From: James Hogan @ 2016-02-05 10:46 UTC (permalink / raw)
  To: Leon Alrae; +Cc: Paolo Bonzini, Aurelien Jarno, qemu-devel, kvm

[-- Attachment #1: Type: text/plain, Size: 2424 bytes --]

On Thu, Feb 04, 2016 at 10:04:11AM +0000, Leon Alrae wrote:
> On 03/02/16 17:16, James Hogan wrote:
> > Here's a v5 refresh of my FPU/MSA patchset for v2.6. Thanks to all who
> > have taken the time to review it so far.
> > 
> > This patchset primarily adds support for FPU and MIPS SIMD Architecture
> > (MSA) in MIPS KVM guests to QEMU. It depends on Linux v4.1, specifically
> > my KVM patchset to add the corresponding hypervisor support to KVM
> > ("[PATCH 00/20] MIPS: KVM: Guest FPU & SIMD (MSA) support").
> > 
> > All comments welcome.
> > 
> > Changes in v5:
> > - Rebase on master (fixed use of uint64 in patch 5).
> > - Use restore_fp_status(env) in patch 6.
> > - Restore MSA FP state using restore_msa_fp_status(env) in patch 7
> >   (Leon).
> > 
> > Changes in v4:
> > - Rebase on master (dropped patch 1 & 2).
> > 
> > Changes in v3 (patch 6 only):
> > - Fix big endian (the pointer passed to the kernel must be for the
> >   actual 32-bit value, not a temporary 64-bit value, otherwise on big
> >   endian systems the kernel will only interpret the upper half).
> > 
> > Changes in v2:
> > - Moved most of patch 7 and updates to linux-headers/linux/kvm.h from
> >   patches 8 and 9 into a new patch 1, which is purely for reference
> >   (Paolo).
> > - Add the changes to MIPS_CP0_{32,64} macros from v1 patch 7 to patch 2,
> >   since the rest of that patch is now unnecessary and the change is
> >   along the same lines as patch 2 (not added Leon's Reviewed-by to this
> >   patch due to that non-reviewed change).
> > - Fix line wrapping of kvm_mips_get_one_reg() calls from Config4 and
> >   Config5 in patch 5 (Leon).
> > - Change (1 << x) to (1U << x) in important places in patch 5, 8 & 9 to
> >   avoid compiler undefined behaviour (Leon).
> > 
> > James Hogan (7):
> >   mips/kvm: Remove a couple of noisy DPRINTFs
> >   mips/kvm: Implement PRid CP0 register
> >   mips/kvm: Implement Config CP0 registers
> >   mips/kvm: Support unsigned KVM registers
> >   mips/kvm: Support signed 64-bit KVM registers
> >   mips/kvm: Support FPU in MIPS KVM guests
> >   mips/kvm: Support MSA in MIPS KVM guests
> > 
> >  target-mips/kvm.c | 387 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 374 insertions(+), 13 deletions(-)
> > 
> 
> I've applied the series to my target-mips queue, thanks.

Thanks Leon!

Cheers
James

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2016-02-05 10:46 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-03 17:16 [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 1/7] mips/kvm: Remove a couple of noisy DPRINTFs James Hogan
2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 2/7] mips/kvm: Implement PRid CP0 register James Hogan
2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 3/7] mips/kvm: Implement Config CP0 registers James Hogan
2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 4/7] mips/kvm: Support unsigned KVM registers James Hogan
2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 5/7] mips/kvm: Support signed 64-bit " James Hogan
2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 6/7] mips/kvm: Support FPU in MIPS KVM guests James Hogan
2016-02-03 17:16 ` [Qemu-devel] [PATCH v5 7/7] mips/kvm: Support MSA " James Hogan
2016-02-04 10:04 ` [Qemu-devel] [PATCH v5 0/7] mips/kvm: Support FPU & SIMD (MSA) " Leon Alrae
2016-02-05 10:46   ` James Hogan

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).