All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v6 0/5] QEMU ARM64 Migration Fixes
@ 2015-04-01 15:39 Alex Bennée
  2015-04-01 15:39 ` [Qemu-devel] [PATCH v6 1/5] target-arm: Store SPSR_EL1 state in banked_spsr[1] (SPSR_svc) Alex Bennée
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Alex Bennée @ 2015-04-01 15:39 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: Alex Bennée, christoffer.dall, greg.bellows

Hi,

Here is v6 of the migration fixes patch which addresses a bunch of
Peter's comments as well as a few of the v4 comments I missed out last
time.

v6:
  - Dropped env->spsr doc patch
  - save/restore mp_state
    - cache result of KVM_CAP_MP_STATE ioctl
    - reword commentary
    - invert errno for strerror
  - arm_gic_kvm
    - tweak wording referencing config register
  - sync FP register state
    - don't abuse softfloat's float128 type
  - save/restore SPSR
    - don't blat env->spsr in is_a64 mode
    - rm stray space

Branch: https://github.com/stsquad/qemu/tree/migration/fixes-v6

The kernel side migration fixes are now in the kvmarm/next tree:

GIT: git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git
Branch: next (tested against 4.0.0-rc1-ajb-00031-gd44758c)

Alex Bennée (4):
  target-arm: kvm: save/restore mp state
  hw/intc: arm_gic_kvm.c restore config first
  target-arm: kvm64 sync FP register state
  target-arm: kvm64 fix save/restore of SPSR regs

Peter Maydell (1):
  target-arm: Store SPSR_EL1 state in banked_spsr[1] (SPSR_svc)

 hw/intc/arm_gic_kvm.c   |   7 ++-
 target-arm/helper-a64.c |   2 +-
 target-arm/helper.c     |   2 +-
 target-arm/internals.h  |   5 +-
 target-arm/kvm.c        |  44 ++++++++++++++++++
 target-arm/kvm32.c      |   4 ++
 target-arm/kvm64.c      | 118 ++++++++++++++++++++++++++++++++++++++++++++++--
 target-arm/kvm_arm.h    |  17 +++++++
 8 files changed, 189 insertions(+), 10 deletions(-)

-- 
2.3.4

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

* [Qemu-devel] [PATCH v6 1/5] target-arm: Store SPSR_EL1 state in banked_spsr[1] (SPSR_svc)
  2015-04-01 15:39 [Qemu-devel] [PATCH v6 0/5] QEMU ARM64 Migration Fixes Alex Bennée
@ 2015-04-01 15:39 ` Alex Bennée
  2015-04-01 15:39   ` [Qemu-devel] " Alex Bennée
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Alex Bennée @ 2015-04-01 15:39 UTC (permalink / raw)
  To: qemu-devel, peter.maydell; +Cc: christoffer.dall, greg.bellows

From: Peter Maydell <peter.maydell@linaro.org>

The AArch64 SPSR_EL1 register is architecturally mandated to
be mapped to the AArch32 SPSR_svc register. This means its
state should live in QEMU's env->banked_spsr[1] field.
Correct the various places in the code that incorrectly
put it in banked_spsr[0].

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 7e0d038..861f6fa 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -523,7 +523,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
         aarch64_save_sp(env, arm_current_el(env));
         env->elr_el[new_el] = env->pc;
     } else {
-        env->banked_spsr[0] = cpsr_read(env);
+        env->banked_spsr[aarch64_banked_spsr_index(new_el)] = cpsr_read(env);
         if (!env->thumb) {
             env->cp15.esr_el[new_el] |= 1 << 25;
         }
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 10886c5..d77c6de 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2438,7 +2438,7 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
     { .name = "SPSR_EL1", .state = ARM_CP_STATE_AA64,
       .type = ARM_CP_ALIAS,
       .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 0,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[0]) },
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[1]) },
     /* We rely on the access checks not allowing the guest to write to the
      * state field when SPSel indicates that it's being used as the stack
      * pointer.
diff --git a/target-arm/internals.h b/target-arm/internals.h
index bb171a7..2cc3017 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -82,11 +82,14 @@ static inline void arm_log_exception(int idx)
 
 /*
  * For AArch64, map a given EL to an index in the banked_spsr array.
+ * Note that this mapping and the AArch32 mapping defined in bank_number()
+ * must agree such that the AArch64<->AArch32 SPSRs have the architecturally
+ * mandated mapping between each other.
  */
 static inline unsigned int aarch64_banked_spsr_index(unsigned int el)
 {
     static const unsigned int map[4] = {
-        [1] = 0, /* EL1.  */
+        [1] = 1, /* EL1.  */
         [2] = 6, /* EL2.  */
         [3] = 7, /* EL3.  */
     };
-- 
2.3.4

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

* [PATCH v6 2/5] target-arm: kvm: save/restore mp state
  2015-04-01 15:39 [Qemu-devel] [PATCH v6 0/5] QEMU ARM64 Migration Fixes Alex Bennée
@ 2015-04-01 15:39   ` Alex Bennée
  2015-04-01 15:39   ` [Qemu-devel] " Alex Bennée
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Alex Bennée @ 2015-04-01 15:39 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: christoffer.dall, greg.bellows, Alex Bennée, Paolo Bonzini,
	open list:Overall

This adds the saving and restore of the current Multi-Processing state
of the machine. While the KVM_GET/SET_MP_STATE API exposes a number of
potential states for x86 we only use two for ARM. Either the process is
running or not. We then save this state into the cpu_powered TCG state
to avoid changing the serialisation format.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
v2
  - make mpstate field runtime dependant (kvm_enabled())
  - drop initial KVM_CAP_MP_STATE requirement
  - re-use cpu_powered instead of new field

v4
  - s/HALTED/STOPPED/
  - move code from machine.c to kvm.

v6
  - cache KVM_CAP_MP_STATE ioctl at start-up
  - reword commentary, add some apostrophes
  - invert errno for strerror

diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index 72c1fa1..17371ca 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -28,6 +28,8 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_LAST_INFO
 };
 
+static bool cap_has_mp_state = false;
+
 int kvm_arm_vcpu_init(CPUState *cs)
 {
     ARMCPU *cpu = ARM_CPU(cs);
@@ -157,6 +159,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
      */
     kvm_async_interrupts_allowed = true;
 
+    cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
+
     type_register_static(&host_arm_cpu_type_info);
 
     return 0;
@@ -458,6 +462,46 @@ void kvm_arm_reset_vcpu(ARMCPU *cpu)
     }
 }
 
+/*
+ * Update KVM's MP_STATE based on what QEMU thinks it is
+ */
+int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu)
+{
+    if (cap_has_mp_state) {
+        struct kvm_mp_state mp_state = {
+            .mp_state =
+            cpu->powered_off ? KVM_MP_STATE_STOPPED : KVM_MP_STATE_RUNNABLE
+        };
+        int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MP_STATE, &mp_state);
+        if (ret) {
+            fprintf(stderr, "%s: failed to set MP_STATE %d/%s\n",
+                    __func__, ret, strerror(-ret));
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+/*
+ * Sync the KVM MP_STATE into QEMU
+ */
+int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu)
+{
+    if (cap_has_mp_state) {
+        struct kvm_mp_state mp_state;
+        int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MP_STATE, &mp_state);
+        if (ret) {
+            fprintf(stderr, "%s: failed to get MP_STATE %d/%s\n",
+                    __func__, ret, strerror(-ret));
+            abort();
+        }
+        cpu->powered_off = (mp_state.mp_state == KVM_MP_STATE_STOPPED);
+    }
+
+    return 0;
+}
+
 void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
 {
 }
diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c
index 94030d1..49b6bab 100644
--- a/target-arm/kvm32.c
+++ b/target-arm/kvm32.c
@@ -356,6 +356,8 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         return EINVAL;
     }
 
+    kvm_arm_sync_mpstate_to_kvm(cpu);
+
     return ret;
 }
 
@@ -427,5 +429,7 @@ int kvm_arch_get_registers(CPUState *cs)
      */
     write_list_to_cpustate(cpu);
 
+    kvm_arm_sync_mpstate_to_qemu(cpu);
+
     return 0;
 }
diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c
index 8cf3a62..fed03f2 100644
--- a/target-arm/kvm64.c
+++ b/target-arm/kvm64.c
@@ -211,6 +211,8 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         return EINVAL;
     }
 
+    kvm_arm_sync_mpstate_to_kvm(cpu);
+
     /* TODO:
      * FP state
      */
@@ -310,6 +312,8 @@ int kvm_arch_get_registers(CPUState *cs)
      */
     write_list_to_cpustate(cpu);
 
+    kvm_arm_sync_mpstate_to_qemu(cpu);
+
     /* TODO: other registers */
     return ret;
 }
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
index 455dea3..5abd591 100644
--- a/target-arm/kvm_arm.h
+++ b/target-arm/kvm_arm.h
@@ -162,6 +162,23 @@ typedef struct ARMHostCPUClass {
  */
 bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc);
 
+
+/**
+ * kvm_arm_sync_mpstate_to_kvm
+ * @cpu: ARMCPU
+ *
+ * If supported set the KVM MP_STATE based on QEMU's model.
+ */
+int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu);
+
+/**
+ * kvm_arm_sync_mpstate_to_qemu
+ * @cpu: ARMCPU
+ *
+ * If supported get the MP_STATE from KVM and store in QEMU's model.
+ */
+int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
+
 #endif
 
 #endif
-- 
2.3.4


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

* [Qemu-devel] [PATCH v6 2/5] target-arm: kvm: save/restore mp state
@ 2015-04-01 15:39   ` Alex Bennée
  0 siblings, 0 replies; 10+ messages in thread
From: Alex Bennée @ 2015-04-01 15:39 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: Paolo Bonzini, Alex Bennée, open list:Overall,
	christoffer.dall, greg.bellows

This adds the saving and restore of the current Multi-Processing state
of the machine. While the KVM_GET/SET_MP_STATE API exposes a number of
potential states for x86 we only use two for ARM. Either the process is
running or not. We then save this state into the cpu_powered TCG state
to avoid changing the serialisation format.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
v2
  - make mpstate field runtime dependant (kvm_enabled())
  - drop initial KVM_CAP_MP_STATE requirement
  - re-use cpu_powered instead of new field

v4
  - s/HALTED/STOPPED/
  - move code from machine.c to kvm.

v6
  - cache KVM_CAP_MP_STATE ioctl at start-up
  - reword commentary, add some apostrophes
  - invert errno for strerror

diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index 72c1fa1..17371ca 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -28,6 +28,8 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_LAST_INFO
 };
 
+static bool cap_has_mp_state = false;
+
 int kvm_arm_vcpu_init(CPUState *cs)
 {
     ARMCPU *cpu = ARM_CPU(cs);
@@ -157,6 +159,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
      */
     kvm_async_interrupts_allowed = true;
 
+    cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
+
     type_register_static(&host_arm_cpu_type_info);
 
     return 0;
@@ -458,6 +462,46 @@ void kvm_arm_reset_vcpu(ARMCPU *cpu)
     }
 }
 
+/*
+ * Update KVM's MP_STATE based on what QEMU thinks it is
+ */
+int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu)
+{
+    if (cap_has_mp_state) {
+        struct kvm_mp_state mp_state = {
+            .mp_state =
+            cpu->powered_off ? KVM_MP_STATE_STOPPED : KVM_MP_STATE_RUNNABLE
+        };
+        int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MP_STATE, &mp_state);
+        if (ret) {
+            fprintf(stderr, "%s: failed to set MP_STATE %d/%s\n",
+                    __func__, ret, strerror(-ret));
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+/*
+ * Sync the KVM MP_STATE into QEMU
+ */
+int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu)
+{
+    if (cap_has_mp_state) {
+        struct kvm_mp_state mp_state;
+        int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MP_STATE, &mp_state);
+        if (ret) {
+            fprintf(stderr, "%s: failed to get MP_STATE %d/%s\n",
+                    __func__, ret, strerror(-ret));
+            abort();
+        }
+        cpu->powered_off = (mp_state.mp_state == KVM_MP_STATE_STOPPED);
+    }
+
+    return 0;
+}
+
 void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
 {
 }
diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c
index 94030d1..49b6bab 100644
--- a/target-arm/kvm32.c
+++ b/target-arm/kvm32.c
@@ -356,6 +356,8 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         return EINVAL;
     }
 
+    kvm_arm_sync_mpstate_to_kvm(cpu);
+
     return ret;
 }
 
@@ -427,5 +429,7 @@ int kvm_arch_get_registers(CPUState *cs)
      */
     write_list_to_cpustate(cpu);
 
+    kvm_arm_sync_mpstate_to_qemu(cpu);
+
     return 0;
 }
diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c
index 8cf3a62..fed03f2 100644
--- a/target-arm/kvm64.c
+++ b/target-arm/kvm64.c
@@ -211,6 +211,8 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         return EINVAL;
     }
 
+    kvm_arm_sync_mpstate_to_kvm(cpu);
+
     /* TODO:
      * FP state
      */
@@ -310,6 +312,8 @@ int kvm_arch_get_registers(CPUState *cs)
      */
     write_list_to_cpustate(cpu);
 
+    kvm_arm_sync_mpstate_to_qemu(cpu);
+
     /* TODO: other registers */
     return ret;
 }
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
index 455dea3..5abd591 100644
--- a/target-arm/kvm_arm.h
+++ b/target-arm/kvm_arm.h
@@ -162,6 +162,23 @@ typedef struct ARMHostCPUClass {
  */
 bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc);
 
+
+/**
+ * kvm_arm_sync_mpstate_to_kvm
+ * @cpu: ARMCPU
+ *
+ * If supported set the KVM MP_STATE based on QEMU's model.
+ */
+int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu);
+
+/**
+ * kvm_arm_sync_mpstate_to_qemu
+ * @cpu: ARMCPU
+ *
+ * If supported get the MP_STATE from KVM and store in QEMU's model.
+ */
+int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
+
 #endif
 
 #endif
-- 
2.3.4

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

* [Qemu-devel] [PATCH v6 3/5] hw/intc: arm_gic_kvm.c restore config first
  2015-04-01 15:39 [Qemu-devel] [PATCH v6 0/5] QEMU ARM64 Migration Fixes Alex Bennée
  2015-04-01 15:39 ` [Qemu-devel] [PATCH v6 1/5] target-arm: Store SPSR_EL1 state in banked_spsr[1] (SPSR_svc) Alex Bennée
  2015-04-01 15:39   ` [Qemu-devel] " Alex Bennée
@ 2015-04-01 15:39 ` Alex Bennée
  2015-04-01 15:39 ` [Qemu-devel] [PATCH v6 4/5] target-arm: kvm64 sync FP register state Alex Bennée
  2015-04-01 15:39 ` [Qemu-devel] [PATCH v6 5/5] target-arm: kvm64 fix save/restore of SPSR regs Alex Bennée
  4 siblings, 0 replies; 10+ messages in thread
From: Alex Bennée @ 2015-04-01 15:39 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: Alex Bennée, christoffer.dall, greg.bellows

As there is logic to deal with the difference between edge and level
triggered interrupts in the kernel we must ensure it knows the
configuration of the IRQs before we restore the pending state.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

---
v6
  - tweak wording for configuration register

diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index 0d20750..e1952ad 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -370,6 +370,11 @@ static void kvm_arm_gic_put(GICState *s)
      * the appropriate CPU interfaces in the kernel) */
     kvm_dist_put(s, 0x800, 8, s->num_irq, translate_targets);
 
+    /* irq_state[n].trigger -> GICD_ICFGRn
+     * (restore configuration registers before pending IRQs so we treat
+     * level/edge correctly) */
+    kvm_dist_put(s, 0xc00, 2, s->num_irq, translate_trigger);
+
     /* irq_state[n].pending + irq_state[n].level -> GICD_ISPENDRn */
     kvm_dist_put(s, 0x280, 1, s->num_irq, translate_clear);
     kvm_dist_put(s, 0x200, 1, s->num_irq, translate_pending);
@@ -378,8 +383,6 @@ static void kvm_arm_gic_put(GICState *s)
     kvm_dist_put(s, 0x380, 1, s->num_irq, translate_clear);
     kvm_dist_put(s, 0x300, 1, s->num_irq, translate_active);
 
-    /* irq_state[n].trigger -> GICD_ICFRn */
-    kvm_dist_put(s, 0xc00, 2, s->num_irq, translate_trigger);
 
     /* s->priorityX[irq] -> ICD_IPRIORITYRn */
     kvm_dist_put(s, 0x400, 8, s->num_irq, translate_priority);
-- 
2.3.4

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

* [Qemu-devel] [PATCH v6 4/5] target-arm: kvm64 sync FP register state
  2015-04-01 15:39 [Qemu-devel] [PATCH v6 0/5] QEMU ARM64 Migration Fixes Alex Bennée
                   ` (2 preceding siblings ...)
  2015-04-01 15:39 ` [Qemu-devel] [PATCH v6 3/5] hw/intc: arm_gic_kvm.c restore config first Alex Bennée
@ 2015-04-01 15:39 ` Alex Bennée
  2015-04-01 15:39 ` [Qemu-devel] [PATCH v6 5/5] target-arm: kvm64 fix save/restore of SPSR regs Alex Bennée
  4 siblings, 0 replies; 10+ messages in thread
From: Alex Bennée @ 2015-04-01 15:39 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: Alex Bennée, christoffer.dall, greg.bellows

For migration to work we need to sync all of the register state. This is
especially noticeable when GCC starts using FP registers as spill
registers even with integer programs.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---

v4:
  - fixed merge conflicts
  - rm superfluous reg.id++
v5:
  - use interim float128 to deal with endianess
  - correctly map into vfp.regs[]
  - fix spacing around []s
v6:
  - don't use float128 when syncing FP registers

diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c
index fed03f2..d6c83b0 100644
--- a/target-arm/kvm64.c
+++ b/target-arm/kvm64.c
@@ -15,6 +15,7 @@
 
 #include <linux/kvm.h>
 
+#include "config-host.h"
 #include "qemu-common.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
@@ -126,9 +127,16 @@ bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx)
 #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
                  KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
 
+#define AARCH64_SIMD_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U128 | \
+                 KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
+
+#define AARCH64_SIMD_CTRL_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U32 | \
+                 KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
+
 int kvm_arch_put_registers(CPUState *cs, int level)
 {
     struct kvm_one_reg reg;
+    uint32_t fpr;
     uint64_t val;
     int i;
     int ret;
@@ -207,15 +215,48 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         }
     }
 
+    /* Advanced SIMD and FP registers
+     * We map Qn = regs[2n+1]:regs[2n]
+     */
+    for (i = 0; i < 32; i++) {
+        int rd = i << 1;
+        uint64_t fp_val[2];
+#ifdef HOST_WORDS_BIGENDIAN
+        fp_val[0] = env->vfp.regs[rd + 1];
+        fp_val[1] = env->vfp.regs[rd];
+#else
+        fp_val[1] = env->vfp.regs[rd + 1];
+        fp_val[0] = env->vfp.regs[rd];
+#endif
+        reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]);
+        reg.addr = (uintptr_t)(&fp_val);
+        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+        if (ret) {
+            return ret;
+        }
+    }
+
+    reg.addr = (uintptr_t)(&fpr);
+    fpr = vfp_get_fpsr(env);
+    reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr);
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+    if (ret) {
+        return ret;
+    }
+
+    fpr = vfp_get_fpcr(env);
+    reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr);
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+    if (ret) {
+        return ret;
+    }
+
     if (!write_list_to_kvmstate(cpu)) {
         return EINVAL;
     }
 
     kvm_arm_sync_mpstate_to_kvm(cpu);
 
-    /* TODO:
-     * FP state
-     */
     return ret;
 }
 
@@ -223,6 +264,7 @@ int kvm_arch_get_registers(CPUState *cs)
 {
     struct kvm_one_reg reg;
     uint64_t val;
+    uint32_t fpr;
     int i;
     int ret;
 
@@ -304,6 +346,43 @@ int kvm_arch_get_registers(CPUState *cs)
         }
     }
 
+    /* Advanced SIMD and FP registers
+     * We map Qn = regs[2n+1]:regs[2n]
+     */
+    for (i = 0; i < 32; i++) {
+        uint64_t fp_val[2];
+        reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]);
+        reg.addr = (uintptr_t)(&fp_val);
+        ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+        if (ret) {
+            return ret;
+        } else {
+            int rd = i << 1;
+#ifdef HOST_WORDS_BIGENDIAN
+            env->vfp.regs[rd + 1] = fp_val[0];
+            env->vfp.regs[rd] = fp_val[1];
+#else
+            env->vfp.regs[rd + 1] = fp_val[1];
+            env->vfp.regs[rd] = fp_val[0];
+#endif
+        }
+    }
+
+    reg.addr = (uintptr_t)(&fpr);
+    reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr);
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+    if (ret) {
+        return ret;
+    }
+    vfp_set_fpsr(env, fpr);
+
+    reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr);
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+    if (ret) {
+        return ret;
+    }
+    vfp_set_fpcr(env, fpr);
+
     if (!write_kvmstate_to_list(cpu)) {
         return EINVAL;
     }
-- 
2.3.4

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

* [Qemu-devel] [PATCH v6 5/5] target-arm: kvm64 fix save/restore of SPSR regs
  2015-04-01 15:39 [Qemu-devel] [PATCH v6 0/5] QEMU ARM64 Migration Fixes Alex Bennée
                   ` (3 preceding siblings ...)
  2015-04-01 15:39 ` [Qemu-devel] [PATCH v6 4/5] target-arm: kvm64 sync FP register state Alex Bennée
@ 2015-04-01 15:39 ` Alex Bennée
  2015-04-01 16:31   ` Peter Maydell
  4 siblings, 1 reply; 10+ messages in thread
From: Alex Bennée @ 2015-04-01 15:39 UTC (permalink / raw)
  To: qemu-devel, peter.maydell
  Cc: Alex Bennée, christoffer.dall, greg.bellows

The current code was negatively indexing the cpu state array and not
synchronizing banked spsr register state with the current mode's spsr
state, causing occasional failures with migration.

Some munging is done to take care of the aarch64 mapping and also to
ensure the most current value of the spsr is updated to the banked
registers (relevant for KVM<->TCG migration).

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
v2 (ajb)
  - minor tweaks and clarifications
v3
  - Use the correct bank index function for setting/getting env->spsr
  - only deal with spsrs in elevated exception levels
v4
 - try and make commentary clearer
 - ensure env->banked_spsr[0] = env->spsr before we sync
v5
 - fix banking index now banking fixed
 - keep wide spacing on [ ] forms
 - claimed authorship
v6
 - only save/restore env->spsr if not in aarch64 mode
 - rm stray space

diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c
index d6c83b0..b020b96 100644
--- a/target-arm/kvm64.c
+++ b/target-arm/kvm64.c
@@ -140,6 +140,7 @@ int kvm_arch_put_registers(CPUState *cs, int level)
     uint64_t val;
     int i;
     int ret;
+    unsigned int el;
 
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
@@ -206,9 +207,22 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         return ret;
     }
 
+    /* Saved Program State Registers
+     *
+     * Before we restore from the banked_spsr[] array we need to
+     * ensure that any modifications to env->spsr are correctly
+     * reflected in the banks.
+     */
+    el = arm_current_el(env);
+    if (el > 0 && !is_a64(env)) {
+        i = bank_number(env->uncached_cpsr & CPSR_M);
+        env->banked_spsr[i] = env->spsr;
+    }
+
+    /* KVM 0-4 map to QEMU banks 1-5 */
     for (i = 0; i < KVM_NR_SPSR; i++) {
         reg.id = AARCH64_CORE_REG(spsr[i]);
-        reg.addr = (uintptr_t) &env->banked_spsr[i - 1];
+        reg.addr = (uintptr_t) &env->banked_spsr[i + 1];
         ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
         if (ret) {
             return ret;
@@ -265,6 +279,7 @@ int kvm_arch_get_registers(CPUState *cs)
     struct kvm_one_reg reg;
     uint64_t val;
     uint32_t fpr;
+    unsigned int el;
     int i;
     int ret;
 
@@ -337,15 +352,25 @@ int kvm_arch_get_registers(CPUState *cs)
         return ret;
     }
 
+    /* Fetch the SPSR registers
+     *
+     * KVM SPSRs 0-4 map to QEMU banks 1-5
+     */
     for (i = 0; i < KVM_NR_SPSR; i++) {
         reg.id = AARCH64_CORE_REG(spsr[i]);
-        reg.addr = (uintptr_t) &env->banked_spsr[i - 1];
+        reg.addr = (uintptr_t) &env->banked_spsr[i + 1];
         ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
         if (ret) {
             return ret;
         }
     }
 
+    el = arm_current_el(env);
+    if (el > 0 && !is_a64(env)) {
+         i = bank_number(env->uncached_cpsr & CPSR_M);
+        env->spsr = env->banked_spsr[i];
+    }
+
     /* Advanced SIMD and FP registers
      * We map Qn = regs[2n+1]:regs[2n]
      */
-- 
2.3.4

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

* Re: [PATCH v6 2/5] target-arm: kvm: save/restore mp state
  2015-04-01 15:39   ` [Qemu-devel] " Alex Bennée
@ 2015-04-01 16:31     ` Peter Maydell
  -1 siblings, 0 replies; 10+ messages in thread
From: Peter Maydell @ 2015-04-01 16:31 UTC (permalink / raw)
  To: Alex Bennée
  Cc: QEMU Developers, Christoffer Dall, Greg Bellows, Paolo Bonzini,
	open list:Overall

On 1 April 2015 at 16:39, Alex Bennée <alex.bennee@linaro.org> wrote:
> --- a/target-arm/kvm.c
> +++ b/target-arm/kvm.c
> @@ -28,6 +28,8 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
>      KVM_CAP_LAST_INFO
>  };
>
> +static bool cap_has_mp_state = false;

This explicit init to false is unnecessary, and
checkpatch complains about it. I will fix this as I
apply to my tree.

-- PMM

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

* Re: [Qemu-devel] [PATCH v6 2/5] target-arm: kvm: save/restore mp state
@ 2015-04-01 16:31     ` Peter Maydell
  0 siblings, 0 replies; 10+ messages in thread
From: Peter Maydell @ 2015-04-01 16:31 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Paolo Bonzini, open list:Overall, QEMU Developers,
	Christoffer Dall, Greg Bellows

On 1 April 2015 at 16:39, Alex Bennée <alex.bennee@linaro.org> wrote:
> --- a/target-arm/kvm.c
> +++ b/target-arm/kvm.c
> @@ -28,6 +28,8 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
>      KVM_CAP_LAST_INFO
>  };
>
> +static bool cap_has_mp_state = false;

This explicit init to false is unnecessary, and
checkpatch complains about it. I will fix this as I
apply to my tree.

-- PMM

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

* Re: [Qemu-devel] [PATCH v6 5/5] target-arm: kvm64 fix save/restore of SPSR regs
  2015-04-01 15:39 ` [Qemu-devel] [PATCH v6 5/5] target-arm: kvm64 fix save/restore of SPSR regs Alex Bennée
@ 2015-04-01 16:31   ` Peter Maydell
  0 siblings, 0 replies; 10+ messages in thread
From: Peter Maydell @ 2015-04-01 16:31 UTC (permalink / raw)
  To: Alex Bennée; +Cc: QEMU Developers, Christoffer Dall, Greg Bellows

On 1 April 2015 at 16:39, Alex Bennée <alex.bennee@linaro.org> wrote:
> +    el = arm_current_el(env);
> +    if (el > 0 && !is_a64(env)) {
> +         i = bank_number(env->uncached_cpsr & CPSR_M);
> +        env->spsr = env->banked_spsr[i];
> +    }

Bad indent, spotted by checkpatch. I'll fix as I apply.

-- PMM

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

end of thread, other threads:[~2015-04-01 16:32 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-01 15:39 [Qemu-devel] [PATCH v6 0/5] QEMU ARM64 Migration Fixes Alex Bennée
2015-04-01 15:39 ` [Qemu-devel] [PATCH v6 1/5] target-arm: Store SPSR_EL1 state in banked_spsr[1] (SPSR_svc) Alex Bennée
2015-04-01 15:39 ` [PATCH v6 2/5] target-arm: kvm: save/restore mp state Alex Bennée
2015-04-01 15:39   ` [Qemu-devel] " Alex Bennée
2015-04-01 16:31   ` Peter Maydell
2015-04-01 16:31     ` [Qemu-devel] " Peter Maydell
2015-04-01 15:39 ` [Qemu-devel] [PATCH v6 3/5] hw/intc: arm_gic_kvm.c restore config first Alex Bennée
2015-04-01 15:39 ` [Qemu-devel] [PATCH v6 4/5] target-arm: kvm64 sync FP register state Alex Bennée
2015-04-01 15:39 ` [Qemu-devel] [PATCH v6 5/5] target-arm: kvm64 fix save/restore of SPSR regs Alex Bennée
2015-04-01 16:31   ` Peter Maydell

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.