All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/7] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests
@ 2015-12-18 10:45 ` James Hogan
  0 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:45 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: kvm, Leon Alrae, Aurelien Jarno, James Hogan

Here's a v4 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 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 | 388 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 375 insertions(+), 13 deletions(-)

-- 
2.4.10


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

* [Qemu-devel] [PATCH v4 0/7] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests
@ 2015-12-18 10:45 ` James Hogan
  0 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:45 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: James Hogan, Leon Alrae, Aurelien Jarno, kvm

Here's a v4 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 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 | 388 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 375 insertions(+), 13 deletions(-)

-- 
2.4.10

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

* [PATCH v4 1/7] mips/kvm: Remove a couple of noisy DPRINTFs
  2015-12-18 10:45 ` [Qemu-devel] " James Hogan
@ 2015-12-18 10:45   ` James Hogan
  -1 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:45 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: kvm, Leon Alrae, Aurelien Jarno, James Hogan

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 12d7db311ece..5cd65ad201ca 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] 22+ messages in thread

* [Qemu-devel] [PATCH v4 1/7] mips/kvm: Remove a couple of noisy DPRINTFs
@ 2015-12-18 10:45   ` James Hogan
  0 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:45 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: James Hogan, Leon Alrae, 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 12d7db311ece..5cd65ad201ca 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] 22+ messages in thread

* [PATCH v4 2/7] mips/kvm: Implement PRid CP0 register
  2015-12-18 10:45 ` [Qemu-devel] " James Hogan
@ 2015-12-18 10:45   ` James Hogan
  -1 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:45 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: kvm, Leon Alrae, Aurelien Jarno, James Hogan

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 5cd65ad201ca..41abc8709d96 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] 22+ messages in thread

* [Qemu-devel] [PATCH v4 2/7] mips/kvm: Implement PRid CP0 register
@ 2015-12-18 10:45   ` James Hogan
  0 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:45 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: James Hogan, Leon Alrae, 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 5cd65ad201ca..41abc8709d96 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] 22+ messages in thread

* [PATCH v4 3/7] mips/kvm: Implement Config CP0 registers
  2015-12-18 10:45 ` [Qemu-devel] " James Hogan
@ 2015-12-18 10:46   ` James Hogan
  -1 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:46 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: kvm, Leon Alrae, Aurelien Jarno, James Hogan

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 41abc8709d96..b777a5e93fb1 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 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] 22+ messages in thread

* [Qemu-devel] [PATCH v4 3/7] mips/kvm: Implement Config CP0 registers
@ 2015-12-18 10:46   ` James Hogan
  0 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:46 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: James Hogan, Leon Alrae, 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 41abc8709d96..b777a5e93fb1 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 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] 22+ messages in thread

* [PATCH v4 4/7] mips/kvm: Support unsigned KVM registers
  2015-12-18 10:45 ` [Qemu-devel] " James Hogan
@ 2015-12-18 10:46   ` James Hogan
  -1 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:46 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: kvm, Leon Alrae, Aurelien Jarno, James Hogan

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 b777a5e93fb1..a11095f273f0 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 reg_id,
                                          target_ulong *addr)
 {
-- 
2.4.10


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

* [Qemu-devel] [PATCH v4 4/7] mips/kvm: Support unsigned KVM registers
@ 2015-12-18 10:46   ` James Hogan
  0 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:46 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: James Hogan, Leon Alrae, 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 b777a5e93fb1..a11095f273f0 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 reg_id,
                                          target_ulong *addr)
 {
-- 
2.4.10

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

* [PATCH v4 5/7] mips/kvm: Support signed 64-bit KVM registers
  2015-12-18 10:45 ` [Qemu-devel] " James Hogan
@ 2015-12-18 10:46   ` James Hogan
  -1 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:46 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: kvm, Leon Alrae, Aurelien Jarno, James Hogan

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 a11095f273f0..284b7a954ba2 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 reg_id,
 }
 
 static inline int kvm_mips_get_one_reg64(CPUState *cs, uint64 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 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] 22+ messages in thread

* [Qemu-devel] [PATCH v4 5/7] mips/kvm: Support signed 64-bit KVM registers
@ 2015-12-18 10:46   ` James Hogan
  0 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:46 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: James Hogan, Leon Alrae, 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 a11095f273f0..284b7a954ba2 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 reg_id,
 }
 
 static inline int kvm_mips_get_one_reg64(CPUState *cs, uint64 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 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] 22+ messages in thread

* [PATCH v4 6/7] mips/kvm: Support FPU in MIPS KVM guests
  2015-12-18 10:45 ` [Qemu-devel] " James Hogan
@ 2015-12-18 10:46   ` James Hogan
  -1 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:46 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: kvm, Leon Alrae, Aurelien Jarno, James Hogan

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 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 | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 120 insertions(+), 4 deletions(-)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index 284b7a954ba2..f66347b8250a 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 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,98 @@ 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 {
+            /* set rounding mode */
+            restore_rounding_mode(env);
+            /* set flush-to-zero mode */
+            restore_flush_mode(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 +915,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 +947,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] 22+ messages in thread

* [Qemu-devel] [PATCH v4 6/7] mips/kvm: Support FPU in MIPS KVM guests
@ 2015-12-18 10:46   ` James Hogan
  0 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:46 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: James Hogan, Leon Alrae, 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 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 | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 120 insertions(+), 4 deletions(-)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index 284b7a954ba2..f66347b8250a 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 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,98 @@ 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 {
+            /* set rounding mode */
+            restore_rounding_mode(env);
+            /* set flush-to-zero mode */
+            restore_flush_mode(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 +915,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 +947,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] 22+ messages in thread

* [PATCH v4 7/7] mips/kvm: Support MSA in MIPS KVM guests
  2015-12-18 10:45 ` [Qemu-devel] " James Hogan
@ 2015-12-18 10:46   ` James Hogan
  -1 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:46 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: kvm, Leon Alrae, Aurelien Jarno, James Hogan

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 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 | 127 +++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 107 insertions(+), 20 deletions(-)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index f66347b8250a..4404797261fd 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 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;
             }
         }
@@ -611,17 +664,51 @@ static int kvm_mips_get_fpu_registers(CPUState *cs)
             restore_flush_mode(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;
+        }
+
+        /* 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] 22+ messages in thread

* [Qemu-devel] [PATCH v4 7/7] mips/kvm: Support MSA in MIPS KVM guests
@ 2015-12-18 10:46   ` James Hogan
  0 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2015-12-18 10:46 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: James Hogan, Leon Alrae, 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 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 | 127 +++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 107 insertions(+), 20 deletions(-)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index f66347b8250a..4404797261fd 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 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;
             }
         }
@@ -611,17 +664,51 @@ static int kvm_mips_get_fpu_registers(CPUState *cs)
             restore_flush_mode(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;
+        }
+
+        /* 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] 22+ messages in thread

* Re: [PATCH v4 7/7] mips/kvm: Support MSA in MIPS KVM guests
  2015-12-18 10:46   ` [Qemu-devel] " James Hogan
@ 2016-02-02  9:58     ` Leon Alrae
  -1 siblings, 0 replies; 22+ messages in thread
From: Leon Alrae @ 2016-02-02  9:58 UTC (permalink / raw)
  To: James Hogan, qemu-devel, Paolo Bonzini; +Cc: kvm, Aurelien Jarno

Hi James,

On 18/12/15 10:46, James Hogan wrote:
> @@ -611,17 +664,51 @@ static int kvm_mips_get_fpu_registers(CPUState *cs)
>              restore_flush_mode(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;
> +        }

Shouldn't MSA's float_status (i.e. msa_fp_status) be restored to reflect
MSACSR?

Thanks,
Leon

> +        /* 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;
>              }
>          }
> 


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

* Re: [Qemu-devel] [PATCH v4 7/7] mips/kvm: Support MSA in MIPS KVM guests
@ 2016-02-02  9:58     ` Leon Alrae
  0 siblings, 0 replies; 22+ messages in thread
From: Leon Alrae @ 2016-02-02  9:58 UTC (permalink / raw)
  To: James Hogan, qemu-devel, Paolo Bonzini; +Cc: Aurelien Jarno, kvm

Hi James,

On 18/12/15 10:46, James Hogan wrote:
> @@ -611,17 +664,51 @@ static int kvm_mips_get_fpu_registers(CPUState *cs)
>              restore_flush_mode(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;
> +        }

Shouldn't MSA's float_status (i.e. msa_fp_status) be restored to reflect
MSACSR?

Thanks,
Leon

> +        /* 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;
>              }
>          }
> 

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

* Re: [PATCH v4 7/7] mips/kvm: Support MSA in MIPS KVM guests
  2016-02-02  9:58     ` [Qemu-devel] " Leon Alrae
@ 2016-02-02 12:39       ` James Hogan
  -1 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2016-02-02 12:39 UTC (permalink / raw)
  To: Leon Alrae; +Cc: qemu-devel, Paolo Bonzini, kvm, Aurelien Jarno

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

Hi Leon,

On Tue, Feb 02, 2016 at 09:58:46AM +0000, Leon Alrae wrote:
> Hi James,
> 
> On 18/12/15 10:46, James Hogan wrote:
> > @@ -611,17 +664,51 @@ static int kvm_mips_get_fpu_registers(CPUState *cs)
> >              restore_flush_mode(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;
> > +        }
> 
> Shouldn't MSA's float_status (i.e. msa_fp_status) be restored to reflect
> MSACSR?

Yes, it probably should. Good spot!

I can use restore_msa_fp_status(env); here, and actually the FP one
above (in previous patch) can change to restore_fp_status(env); too,
since it does the same thing.

I've rebased and resolved the uint64 thing too, would you like a resend?

Thanks
James

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

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

* Re: [Qemu-devel] [PATCH v4 7/7] mips/kvm: Support MSA in MIPS KVM guests
@ 2016-02-02 12:39       ` James Hogan
  0 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2016-02-02 12:39 UTC (permalink / raw)
  To: Leon Alrae; +Cc: Paolo Bonzini, Aurelien Jarno, qemu-devel, kvm

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

Hi Leon,

On Tue, Feb 02, 2016 at 09:58:46AM +0000, Leon Alrae wrote:
> Hi James,
> 
> On 18/12/15 10:46, James Hogan wrote:
> > @@ -611,17 +664,51 @@ static int kvm_mips_get_fpu_registers(CPUState *cs)
> >              restore_flush_mode(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;
> > +        }
> 
> Shouldn't MSA's float_status (i.e. msa_fp_status) be restored to reflect
> MSACSR?

Yes, it probably should. Good spot!

I can use restore_msa_fp_status(env); here, and actually the FP one
above (in previous patch) can change to restore_fp_status(env); too,
since it does the same thing.

I've rebased and resolved the uint64 thing too, would you like a resend?

Thanks
James

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

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

* Re: [PATCH v4 7/7] mips/kvm: Support MSA in MIPS KVM guests
  2016-02-02 12:39       ` [Qemu-devel] " James Hogan
@ 2016-02-02 13:56         ` Leon Alrae
  -1 siblings, 0 replies; 22+ messages in thread
From: Leon Alrae @ 2016-02-02 13:56 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Aurelien Jarno, qemu-devel, kvm

On 02/02/16 12:39, James Hogan wrote:
> I can use restore_msa_fp_status(env); here, and actually the FP one
> above (in previous patch) can change to restore_fp_status(env); too,
> since it does the same thing.

This sounds good.

> I've rebased and resolved the uint64 thing too, would you like a resend?

Yes, please.

Thanks,
Leon

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

* Re: [Qemu-devel] [PATCH v4 7/7] mips/kvm: Support MSA in MIPS KVM guests
@ 2016-02-02 13:56         ` Leon Alrae
  0 siblings, 0 replies; 22+ messages in thread
From: Leon Alrae @ 2016-02-02 13:56 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Aurelien Jarno, qemu-devel, kvm

On 02/02/16 12:39, James Hogan wrote:
> I can use restore_msa_fp_status(env); here, and actually the FP one
> above (in previous patch) can change to restore_fp_status(env); too,
> since it does the same thing.

This sounds good.

> I've rebased and resolved the uint64 thing too, would you like a resend?

Yes, please.

Thanks,
Leon

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

end of thread, other threads:[~2016-02-02 13:56 UTC | newest]

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.