qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/9] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests
@ 2015-03-11 15:22 James Hogan
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 1/9] mips/kvm: Drop KVM_REG_MIPS_COUNT_* definitions James Hogan
                   ` (8 more replies)
  0 siblings, 9 replies; 17+ messages in thread
From: James Hogan @ 2015-03-11 15:22 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: James Hogan, Leon Alrae, Aurelien Jarno, kvm

This patchset primarily adds support for FPU and MIPS SIMD Architecture
(MSA) in MIPS KVM guests to QEMU. It depends on the KVM patchset which I
recently submitted to add the corresponding hypervisor support to KVM
("[PATCH 00/20] MIPS: KVM: Guest FPU & SIMD (MSA) support").

All comments welcome.

James Hogan (9):
  mips/kvm: Drop KVM_REG_MIPS_COUNT_* definitions
  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: Add FP & MSA register definitions
  mips/kvm: Support FPU in MIPS KVM guests
  mips/kvm: Support MSA in MIPS KVM guests

 linux-headers/linux/kvm.h |   2 +
 target-mips/cpu.h         |   2 +
 target-mips/kvm.c         | 433 +++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 412 insertions(+), 25 deletions(-)

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Leon Alrae <leon.alrae@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
-- 
2.0.5

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

* [Qemu-devel] [PATCH 1/9] mips/kvm: Drop KVM_REG_MIPS_COUNT_* definitions
  2015-03-11 15:22 [Qemu-devel] [PATCH 0/9] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
@ 2015-03-11 15:22 ` James Hogan
  2015-03-12 16:28   ` Leon Alrae
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 2/9] mips/kvm: Remove a couple of noisy DPRINTFs James Hogan
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: James Hogan @ 2015-03-11 15:22 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: James Hogan, Leon Alrae, Aurelien Jarno, kvm

The KVM_REG_MIPS_COUNT_* definitions are now included in
linux-headers/asm-mips/kvm.h since commit b061808d39fa ("linux-headers:
update linux headers to kvm/next"), therefore the duplicate definitions
in target-mips/kvm.c can now be dropped.

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 | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index b68191c88e87..49e71b3791b7 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -226,17 +226,6 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
 #define KVM_REG_MIPS_CP0_EPC            MIPS_CP0_64(14, 0)
 #define KVM_REG_MIPS_CP0_ERROREPC       MIPS_CP0_64(30, 0)
 
-/* CP0_Count control */
-#define KVM_REG_MIPS_COUNT_CTL          (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
-                                         0x20000 | 0)
-#define KVM_REG_MIPS_COUNT_CTL_DC       0x00000001      /* master disable */
-/* CP0_Count resume monotonic nanoseconds */
-#define KVM_REG_MIPS_COUNT_RESUME       (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
-                                         0x20000 | 1)
-/* CP0_Count rate in Hz */
-#define KVM_REG_MIPS_COUNT_HZ           (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
-                                         0x20000 | 2)
-
 static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id,
                                        int32_t *addr)
 {
-- 
2.0.5

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

* [Qemu-devel] [PATCH 2/9] mips/kvm: Remove a couple of noisy DPRINTFs
  2015-03-11 15:22 [Qemu-devel] [PATCH 0/9] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 1/9] mips/kvm: Drop KVM_REG_MIPS_COUNT_* definitions James Hogan
@ 2015-03-11 15:22 ` James Hogan
  2015-03-12 16:29   ` Leon Alrae
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 3/9] mips/kvm: Implement PRid CP0 register James Hogan
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: James Hogan @ 2015-03-11 15:22 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>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Leon Alrae <leon.alrae@imgtec.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 49e71b3791b7..2ec7a6588568 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -87,7 +87,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));
 }
 
@@ -112,7 +111,6 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
 
 void kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
 {
-    DPRINTF("%s\n", __func__);
 }
 
 int kvm_arch_process_async_events(CPUState *cs)
-- 
2.0.5

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

* [Qemu-devel] [PATCH 3/9] mips/kvm: Implement PRid CP0 register
  2015-03-11 15:22 [Qemu-devel] [PATCH 0/9] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 1/9] mips/kvm: Drop KVM_REG_MIPS_COUNT_* definitions James Hogan
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 2/9] mips/kvm: Remove a couple of noisy DPRINTFs James Hogan
@ 2015-03-11 15:22 ` James Hogan
  2015-03-12 16:36   ` Leon Alrae
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 4/9] mips/kvm: Implement Config CP0 registers James Hogan
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: James Hogan @ 2015-03-11 15:22 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>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Leon Alrae <leon.alrae@imgtec.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 2ec7a6588568..730c67e247d8 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -222,6 +222,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,
@@ -521,6 +522,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) {
@@ -607,6 +613,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.0.5

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

* [Qemu-devel] [PATCH 4/9] mips/kvm: Implement Config CP0 registers
  2015-03-11 15:22 [Qemu-devel] [PATCH 0/9] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
                   ` (2 preceding siblings ...)
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 3/9] mips/kvm: Implement PRid CP0 register James Hogan
@ 2015-03-11 15:22 ` James Hogan
  2015-03-12 16:41   ` Leon Alrae
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 5/9] mips/kvm: Support unsigned KVM registers James Hogan
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: James Hogan @ 2015-03-11 15:22 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>
---
 target-mips/kvm.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index 730c67e247d8..b8813a2722a3 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -223,6 +223,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,
@@ -305,6 +311,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    (1 << CP0C0_M)
+#define KVM_REG_MIPS_CP0_CONFIG1_MASK   (1 << CP0C1_M)
+#define KVM_REG_MIPS_CP0_CONFIG2_MASK   (1 << CP0C2_M)
+#define KVM_REG_MIPS_CP0_CONFIG3_MASK   (1 << CP0C3_M)
+#define KVM_REG_MIPS_CP0_CONFIG4_MASK   (1 << 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).
@@ -527,6 +561,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) {
@@ -618,6 +694,38 @@ 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.0.5

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

* [Qemu-devel] [PATCH 5/9] mips/kvm: Support unsigned KVM registers
  2015-03-11 15:22 [Qemu-devel] [PATCH 0/9] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
                   ` (3 preceding siblings ...)
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 4/9] mips/kvm: Implement Config CP0 registers James Hogan
@ 2015-03-11 15:22 ` James Hogan
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 6/9] mips/kvm: Support signed 64-bit " James Hogan
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: James Hogan @ 2015-03-11 15:22 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>
---
 target-mips/kvm.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index b8813a2722a3..f4ee22f3e998 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -243,6 +243,18 @@ 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)
+{
+    uint64_t val64 = *addr;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)&val64
+    };
+
+    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)
 {
@@ -283,6 +295,23 @@ static inline int kvm_mips_get_one_reg(CPUState *cs, uint64_t reg_id,
     return ret;
 }
 
+static inline int kvm_mips_get_one_ureg(CPUState *cs, uint64_t reg_id,
+                                        uint32_t *addr)
+{
+    int ret;
+    uint64_t val64 = 0;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)&val64
+    };
+
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
+    if (ret >= 0) {
+        *addr = val64;
+    }
+    return ret;
+}
+
 static inline int kvm_mips_get_one_ulreg(CPUState *cs, uint64 reg_id,
                                          target_ulong *addr)
 {
-- 
2.0.5

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

* [Qemu-devel] [PATCH 6/9] mips/kvm: Support signed 64-bit KVM registers
  2015-03-11 15:22 [Qemu-devel] [PATCH 0/9] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
                   ` (4 preceding siblings ...)
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 5/9] mips/kvm: Support unsigned KVM registers James Hogan
@ 2015-03-11 15:22 ` James Hogan
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 7/9] mips/kvm: Add FP & MSA register definitions James Hogan
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: James Hogan @ 2015-03-11 15:22 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 f4ee22f3e998..6abd391f2cd5 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -268,7 +268,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,
@@ -330,7 +341,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,
@@ -385,13 +407,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;
@@ -427,14 +449,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;
@@ -458,7 +480,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;
@@ -491,8 +513,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.0.5

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

* [Qemu-devel] [PATCH 7/9] mips/kvm: Add FP & MSA register definitions
  2015-03-11 15:22 [Qemu-devel] [PATCH 0/9] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
                   ` (5 preceding siblings ...)
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 6/9] mips/kvm: Support signed 64-bit " James Hogan
@ 2015-03-11 15:22 ` James Hogan
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 8/9] mips/kvm: Support FPU in MIPS KVM guests James Hogan
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 9/9] mips/kvm: Support MSA " James Hogan
  8 siblings, 0 replies; 17+ messages in thread
From: James Hogan @ 2015-03-11 15:22 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini; +Cc: James Hogan, Leon Alrae, Aurelien Jarno, kvm

Add the new floating point and MIPS SIMD Architecture (MSA) KVM register
definitions to kvm.c.

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 | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index 6abd391f2cd5..7f72d6fb511f 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -203,11 +203,16 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
     return 0;
 }
 
+#define KVM_REG_MIPS_GP         (KVM_REG_MIPS | 0x0000000000000000ULL)
+#define KVM_REG_MIPS_CP0        (KVM_REG_MIPS | 0x0000000000010000ULL)
+#define KVM_REG_MIPS_KVM        (KVM_REG_MIPS | 0x0000000000020000ULL)
+#define KVM_REG_MIPS_FPU        (KVM_REG_MIPS | 0x0000000000030000ULL)
+
 #define MIPS_CP0_32(_R, _S)                                     \
-    (KVM_REG_MIPS | KVM_REG_SIZE_U32 | 0x10000 | (8 * (_R) + (_S)))
+    (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U32 | (8 * (_R) + (_S)))
 
 #define MIPS_CP0_64(_R, _S)                                     \
-    (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 0x10000 | (8 * (_R) + (_S)))
+    (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U64 | (8 * (_R) + (_S)))
 
 #define KVM_REG_MIPS_CP0_INDEX          MIPS_CP0_32(0, 0)
 #define KVM_REG_MIPS_CP0_CONTEXT        MIPS_CP0_64(4, 0)
@@ -231,6 +236,24 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
 #define KVM_REG_MIPS_CP0_CONFIG5        MIPS_CP0_32(16, 5)
 #define KVM_REG_MIPS_CP0_ERROREPC       MIPS_CP0_64(30, 0)
 
+/* Floating Point and MIPS SIMD Architecture (MSA) registers. */
+#define KVM_REG_MIPS_FPR        (KVM_REG_MIPS_FPU | 0x0000000000000000ULL)
+#define KVM_REG_MIPS_FCR        (KVM_REG_MIPS_FPU | 0x0000000000000100ULL)
+#define KVM_REG_MIPS_MSACR      (KVM_REG_MIPS_FPU | 0x0000000000000200ULL)
+
+/* Floating point / Vector registers.  */
+#define KVM_REG_MIPS_FPR_32(n)  (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U32  | (n))
+#define KVM_REG_MIPS_FPR_64(n)  (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U64  | (n))
+#define KVM_REG_MIPS_VEC_128(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U128 | (n))
+
+/* Floating point control registers. */
+#define KVM_REG_MIPS_FCR_IR     (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 |  0)
+#define KVM_REG_MIPS_FCR_CSR    (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 31)
+
+/* MIPS SIMD Architecture (MSA) control registers. */
+#define KVM_REG_MIPS_MSA_IR      (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 |  0)
+#define KVM_REG_MIPS_MSA_CSR     (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 |  1)
+
 static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id,
                                        int32_t *addr)
 {
-- 
2.0.5

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

* [Qemu-devel] [PATCH 8/9] mips/kvm: Support FPU in MIPS KVM guests
  2015-03-11 15:22 [Qemu-devel] [PATCH 0/9] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
                   ` (6 preceding siblings ...)
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 7/9] mips/kvm: Add FP & MSA register definitions James Hogan
@ 2015-03-11 15:22 ` James Hogan
  2015-03-12 16:44   ` Paolo Bonzini
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 9/9] mips/kvm: Support MSA " James Hogan
  8 siblings, 1 reply; 17+ messages in thread
From: James Hogan @ 2015-03-11 15:22 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>
---
 linux-headers/linux/kvm.h |   1 +
 target-mips/cpu.h         |   2 +
 target-mips/kvm.c         | 124 ++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 123 insertions(+), 4 deletions(-)

diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 12045a11c036..410eb158f564 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -761,6 +761,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_PPC_FIXUP_HCALL 103
 #define KVM_CAP_PPC_ENABLE_HCALL 104
 #define KVM_CAP_CHECK_EXTENSION_VM 105
+#define KVM_CAP_MIPS_FPU 107
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 5ea61bceea42..07c1e0146ec9 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -462,6 +462,8 @@ struct CPUMIPSState {
 #define CP0C5_CV         29
 #define CP0C5_EVA        28
 #define CP0C5_MSAEn      27
+#define CP0C5_UFE        9
+#define CP0C5_FRE        8
 #define CP0C5_SBRI       6
 #define CP0C5_UFR        2
 #define CP0C5_NFExists   0
diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index 7f72d6fb511f..c0191a525171 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -29,6 +29,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
 };
@@ -45,16 +47,29 @@ int kvm_arch_init(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;
 }
@@ -63,8 +78,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);
     }
 
@@ -386,11 +401,14 @@ static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64 reg_id,
 }
 
 #define KVM_REG_MIPS_CP0_CONFIG_MASK    (1 << CP0C0_M)
-#define KVM_REG_MIPS_CP0_CONFIG1_MASK   (1 << CP0C1_M)
+#define KVM_REG_MIPS_CP0_CONFIG1_MASK   ((1 << CP0C1_M) | \
+                                         (1 << CP0C1_FP))
 #define KVM_REG_MIPS_CP0_CONFIG2_MASK   (1 << CP0C2_M)
 #define KVM_REG_MIPS_CP0_CONFIG3_MASK   (1 << CP0C3_M)
 #define KVM_REG_MIPS_CP0_CONFIG4_MASK   (1 << CP0C4_M)
-#define KVM_REG_MIPS_CP0_CONFIG5_MASK   0
+#define KVM_REG_MIPS_CP0_CONFIG5_MASK   ((1 << CP0C5_UFE) | \
+                                         (1 << CP0C5_FRE) | \
+                                         (1 << CP0C5_UFR))
 
 static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id,
                                           int32_t *addr, int32_t mask)
@@ -552,6 +570,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);
@@ -838,6 +948,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;
 }
 
@@ -865,6 +980,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.0.5

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

* [Qemu-devel] [PATCH 9/9] mips/kvm: Support MSA in MIPS KVM guests
  2015-03-11 15:22 [Qemu-devel] [PATCH 0/9] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
                   ` (7 preceding siblings ...)
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 8/9] mips/kvm: Support FPU in MIPS KVM guests James Hogan
@ 2015-03-11 15:22 ` James Hogan
  8 siblings, 0 replies; 17+ messages in thread
From: James Hogan @ 2015-03-11 15:22 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>
---
 linux-headers/linux/kvm.h |   1 +
 target-mips/kvm.c         | 127 ++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 108 insertions(+), 20 deletions(-)

diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 410eb158f564..0b2519332ac7 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -762,6 +762,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_PPC_ENABLE_HCALL 104
 #define KVM_CAP_CHECK_EXTENSION_VM 105
 #define KVM_CAP_MIPS_FPU 107
+#define KVM_CAP_MIPS_MSA 108
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index c0191a525171..a66e5eb44937 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -30,6 +30,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
@@ -48,6 +49,7 @@ int kvm_arch_init(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;
@@ -70,6 +72,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;
 }
@@ -82,6 +93,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__);
 }
@@ -404,9 +419,11 @@ static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64 reg_id,
 #define KVM_REG_MIPS_CP0_CONFIG1_MASK   ((1 << CP0C1_M) | \
                                          (1 << CP0C1_FP))
 #define KVM_REG_MIPS_CP0_CONFIG2_MASK   (1 << CP0C2_M)
-#define KVM_REG_MIPS_CP0_CONFIG3_MASK   (1 << CP0C3_M)
+#define KVM_REG_MIPS_CP0_CONFIG3_MASK   ((1 << CP0C3_M) | \
+                                         (1 << CP0C3_MSAP))
 #define KVM_REG_MIPS_CP0_CONFIG4_MASK   (1 << CP0C4_M)
-#define KVM_REG_MIPS_CP0_CONFIG5_MASK   ((1 << CP0C5_UFE) | \
+#define KVM_REG_MIPS_CP0_CONFIG5_MASK   ((1 << CP0C5_MSAEn) | \
+                                         (1 << CP0C5_UFE) | \
                                          (1 << CP0C5_FRE) | \
                                          (1 << CP0C5_UFR))
 
@@ -595,17 +612,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;
             }
         }
@@ -642,17 +695,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.0.5

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

* Re: [Qemu-devel] [PATCH 1/9] mips/kvm: Drop KVM_REG_MIPS_COUNT_* definitions
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 1/9] mips/kvm: Drop KVM_REG_MIPS_COUNT_* definitions James Hogan
@ 2015-03-12 16:28   ` Leon Alrae
  0 siblings, 0 replies; 17+ messages in thread
From: Leon Alrae @ 2015-03-12 16:28 UTC (permalink / raw)
  To: James Hogan, qemu-devel, Paolo Bonzini; +Cc: Aurelien Jarno, kvm

On 11/03/2015 15:22, James Hogan wrote:
> The KVM_REG_MIPS_COUNT_* definitions are now included in
> linux-headers/asm-mips/kvm.h since commit b061808d39fa ("linux-headers:
> update linux headers to kvm/next"), therefore the duplicate definitions
> in target-mips/kvm.c can now be dropped.
> 
> 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 | 11 -----------
>  1 file changed, 11 deletions(-)

Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>

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

* Re: [Qemu-devel] [PATCH 2/9] mips/kvm: Remove a couple of noisy DPRINTFs
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 2/9] mips/kvm: Remove a couple of noisy DPRINTFs James Hogan
@ 2015-03-12 16:29   ` Leon Alrae
  0 siblings, 0 replies; 17+ messages in thread
From: Leon Alrae @ 2015-03-12 16:29 UTC (permalink / raw)
  To: James Hogan, qemu-devel, Paolo Bonzini; +Cc: Aurelien Jarno, kvm

On 11/03/2015 15:22, James Hogan wrote:
> 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>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Leon Alrae <leon.alrae@imgtec.com>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
>  target-mips/kvm.c | 2 --
>  1 file changed, 2 deletions(-)

Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>

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

* Re: [Qemu-devel] [PATCH 3/9] mips/kvm: Implement PRid CP0 register
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 3/9] mips/kvm: Implement PRid CP0 register James Hogan
@ 2015-03-12 16:36   ` Leon Alrae
  0 siblings, 0 replies; 17+ messages in thread
From: Leon Alrae @ 2015-03-12 16:36 UTC (permalink / raw)
  To: James Hogan, qemu-devel, Paolo Bonzini; +Cc: Aurelien Jarno, kvm

On 11/03/2015 15:22, James Hogan wrote:
> 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>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Leon Alrae <leon.alrae@imgtec.com>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
>  target-mips/kvm.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)

Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>

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

* Re: [Qemu-devel] [PATCH 4/9] mips/kvm: Implement Config CP0 registers
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 4/9] mips/kvm: Implement Config CP0 registers James Hogan
@ 2015-03-12 16:41   ` Leon Alrae
  2015-03-12 16:47     ` James Hogan
  0 siblings, 1 reply; 17+ messages in thread
From: Leon Alrae @ 2015-03-12 16:41 UTC (permalink / raw)
  To: James Hogan, qemu-devel, Paolo Bonzini; +Cc: Aurelien Jarno, kvm

On 11/03/2015 15:22, James Hogan wrote:
> 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>
> ---
>  target-mips/kvm.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 108 insertions(+)
> 
> diff --git a/target-mips/kvm.c b/target-mips/kvm.c
> index 730c67e247d8..b8813a2722a3 100644
> --- a/target-mips/kvm.c
> +++ b/target-mips/kvm.c
> @@ -223,6 +223,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,
> @@ -305,6 +311,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    (1 << CP0C0_M)
> +#define KVM_REG_MIPS_CP0_CONFIG1_MASK   (1 << CP0C1_M)
> +#define KVM_REG_MIPS_CP0_CONFIG2_MASK   (1 << CP0C2_M)
> +#define KVM_REG_MIPS_CP0_CONFIG3_MASK   (1 << CP0C3_M)
> +#define KVM_REG_MIPS_CP0_CONFIG4_MASK   (1 << CP0C4_M)

CP0Cx_M is 31, thus without "U" suffix 1 is left shifted into sign bit
which is undefined behaviour.

> +#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).
> @@ -527,6 +561,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) {
> @@ -618,6 +694,38 @@ 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;
> +    }

There's a minor style inconsistency here - for Config4 and Config5 the
last argument has been moved to a new line whereas for Config{0,1,2,3}
all arguments are in the same line.

>      err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
>                                   &env->CP0_ErrorEPC);
>      if (err < 0) {
> 

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

* Re: [Qemu-devel] [PATCH 8/9] mips/kvm: Support FPU in MIPS KVM guests
  2015-03-11 15:22 ` [Qemu-devel] [PATCH 8/9] mips/kvm: Support FPU in MIPS KVM guests James Hogan
@ 2015-03-12 16:44   ` Paolo Bonzini
  2015-03-12 17:00     ` James Hogan
  0 siblings, 1 reply; 17+ messages in thread
From: Paolo Bonzini @ 2015-03-12 16:44 UTC (permalink / raw)
  To: James Hogan, qemu-devel; +Cc: Leon Alrae, Aurelien Jarno, kvm



On 11/03/2015 16:22, James Hogan wrote:
> diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
> index 12045a11c036..410eb158f564 100644
> --- a/linux-headers/linux/kvm.h
> +++ b/linux-headers/linux/kvm.h
> @@ -761,6 +761,7 @@ struct kvm_ppc_smmu_info {
>  #define KVM_CAP_PPC_FIXUP_HCALL 103
>  #define KVM_CAP_PPC_ENABLE_HCALL 104
>  #define KVM_CAP_CHECK_EXTENSION_VM 105
> +#define KVM_CAP_MIPS_FPU 107
>  

Changes to linux-headers/linux/kvm.h should go in through a complete
sync of the kernel headers.  The good thing is that then the series
becomes 100% MIPS-specific. :)

Paolo

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

* Re: [Qemu-devel] [PATCH 4/9] mips/kvm: Implement Config CP0 registers
  2015-03-12 16:41   ` Leon Alrae
@ 2015-03-12 16:47     ` James Hogan
  0 siblings, 0 replies; 17+ messages in thread
From: James Hogan @ 2015-03-12 16:47 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel, Paolo Bonzini; +Cc: Aurelien Jarno, kvm

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

On 12/03/15 16:41, Leon Alrae wrote:
> On 11/03/2015 15:22, James Hogan wrote:
>> 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>
>> ---
>>  target-mips/kvm.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 108 insertions(+)
>>
>> diff --git a/target-mips/kvm.c b/target-mips/kvm.c
>> index 730c67e247d8..b8813a2722a3 100644
>> --- a/target-mips/kvm.c
>> +++ b/target-mips/kvm.c
>> @@ -223,6 +223,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,
>> @@ -305,6 +311,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    (1 << CP0C0_M)
>> +#define KVM_REG_MIPS_CP0_CONFIG1_MASK   (1 << CP0C1_M)
>> +#define KVM_REG_MIPS_CP0_CONFIG2_MASK   (1 << CP0C2_M)
>> +#define KVM_REG_MIPS_CP0_CONFIG3_MASK   (1 << CP0C3_M)
>> +#define KVM_REG_MIPS_CP0_CONFIG4_MASK   (1 << CP0C4_M)
> 
> CP0Cx_M is 31, thus without "U" suffix 1 is left shifted into sign bit
> which is undefined behaviour.

Well spotted, I'll fix that.

> 
>> +#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).
>> @@ -527,6 +561,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) {
>> @@ -618,6 +694,38 @@ 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;
>> +    }
> 
> There's a minor style inconsistency here - for Config4 and Config5 the
> last argument has been moved to a new line whereas for Config{0,1,2,3}
> all arguments are in the same line.

Yes, Config4 and Config5 used to be unsigned prior to Maciej's patches,
so it used get_one_ureg, just enough to make it wrap. I'll fix.

Thanks for reviewing,

Cheers
James

> 
>>      err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
>>                                   &env->CP0_ErrorEPC);
>>      if (err < 0) {
>>
> 


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

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

* Re: [Qemu-devel] [PATCH 8/9] mips/kvm: Support FPU in MIPS KVM guests
  2015-03-12 16:44   ` Paolo Bonzini
@ 2015-03-12 17:00     ` James Hogan
  0 siblings, 0 replies; 17+ messages in thread
From: James Hogan @ 2015-03-12 17:00 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: Leon Alrae, Aurelien Jarno, kvm

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

On 12/03/15 16:44, Paolo Bonzini wrote:
> 
> 
> On 11/03/2015 16:22, James Hogan wrote:
>> diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
>> index 12045a11c036..410eb158f564 100644
>> --- a/linux-headers/linux/kvm.h
>> +++ b/linux-headers/linux/kvm.h
>> @@ -761,6 +761,7 @@ struct kvm_ppc_smmu_info {
>>  #define KVM_CAP_PPC_FIXUP_HCALL 103
>>  #define KVM_CAP_PPC_ENABLE_HCALL 104
>>  #define KVM_CAP_CHECK_EXTENSION_VM 105
>> +#define KVM_CAP_MIPS_FPU 107
>>  
> 
> Changes to linux-headers/linux/kvm.h should go in through a complete
> sync of the kernel headers.  The good thing is that then the series
> becomes 100% MIPS-specific. :)

Right. I'll maybe move all those changes in a preliminary "don't apply
me" patch for reference (there are some other duplicated definitions in
kvm.c too, similar to what patch 1 cleans up) and assume that one way or
another a sync will happen between the KVM changes being merged and the
QEMU patchset being applied.

Cheers
James


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

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

end of thread, other threads:[~2015-03-12 17:00 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-03-11 15:22 [Qemu-devel] [PATCH 0/9] mips/kvm: Support FPU & SIMD (MSA) in MIPS KVM guests James Hogan
2015-03-11 15:22 ` [Qemu-devel] [PATCH 1/9] mips/kvm: Drop KVM_REG_MIPS_COUNT_* definitions James Hogan
2015-03-12 16:28   ` Leon Alrae
2015-03-11 15:22 ` [Qemu-devel] [PATCH 2/9] mips/kvm: Remove a couple of noisy DPRINTFs James Hogan
2015-03-12 16:29   ` Leon Alrae
2015-03-11 15:22 ` [Qemu-devel] [PATCH 3/9] mips/kvm: Implement PRid CP0 register James Hogan
2015-03-12 16:36   ` Leon Alrae
2015-03-11 15:22 ` [Qemu-devel] [PATCH 4/9] mips/kvm: Implement Config CP0 registers James Hogan
2015-03-12 16:41   ` Leon Alrae
2015-03-12 16:47     ` James Hogan
2015-03-11 15:22 ` [Qemu-devel] [PATCH 5/9] mips/kvm: Support unsigned KVM registers James Hogan
2015-03-11 15:22 ` [Qemu-devel] [PATCH 6/9] mips/kvm: Support signed 64-bit " James Hogan
2015-03-11 15:22 ` [Qemu-devel] [PATCH 7/9] mips/kvm: Add FP & MSA register definitions James Hogan
2015-03-11 15:22 ` [Qemu-devel] [PATCH 8/9] mips/kvm: Support FPU in MIPS KVM guests James Hogan
2015-03-12 16:44   ` Paolo Bonzini
2015-03-12 17:00     ` James Hogan
2015-03-11 15:22 ` [Qemu-devel] [PATCH 9/9] mips/kvm: Support MSA " 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).