]> Git Repo - qemu.git/commitdiff
target-arm: port ARM CPU save/load to use VMState
authorJuan Quintela <[email protected]>
Fri, 19 Apr 2013 11:24:19 +0000 (12:24 +0100)
committerPeter Maydell <[email protected]>
Fri, 19 Apr 2013 11:24:19 +0000 (12:24 +0100)
Port the ARM CPU save/load code to use VMState. Some state is
saved in a slightly different order to simplify things -- for
example arrays are saved one after the other rather than 'striped',
and we always save all 32 VFP registers even if the CPU happens
to only have 16.

Use one subsection for each feature.  This means that we don't need to
bump the version field each time that a new feature gets introduced.

Signed-off-by: Juan Quintela <[email protected]>
[PMM: fixed conflicts, updated to use cpu_class_set_vmsd(),  updated
 with new/removed fields since original patch, changed to use custom
 VMStateInfo for cpsr rather than presave/postload hooks, corrected
 subsection names so vmload doesn't fail]
Signed-off-by: Peter Maydell <[email protected]>
target-arm/cpu-qom.h
target-arm/cpu.c
target-arm/cpu.h
target-arm/machine.c

index 25895509befb5f9cd4c0a62c5ccbad7c9071d56f..12fcefe0c693fc36a53c0b49f4308cae56dccf47 100644 (file)
@@ -111,6 +111,10 @@ static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
 
 #define ENV_OFFSET offsetof(ARMCPU, env)
 
+#ifndef CONFIG_USER_ONLY
+extern const struct VMStateDescription vmstate_arm_cpu;
+#endif
+
 void register_cp_regs_for_features(ARMCPU *cpu);
 
 void arm_cpu_do_interrupt(CPUState *cpu);
index a1e90939d671983b300593855fe08dc663152029..496a59f5c0936d14c2875e6430c06ef5a3c4103a 100644 (file)
@@ -814,6 +814,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
 
     cc->class_by_name = arm_cpu_class_by_name;
     cc->do_interrupt = arm_cpu_do_interrupt;
+    cpu_class_set_vmsd(cc, &vmstate_arm_cpu);
 }
 
 static void cpu_register(const ARMCPUInfo *info)
index 2b972212095d0819c5e2a12e322bf8fa82c97d74..54384446b4d1735236c568b97532e7726b97e2e6 100644 (file)
@@ -640,8 +640,6 @@ static inline CPUARMState *cpu_init(const char *cpu_model)
 #define cpu_signal_handler cpu_arm_signal_handler
 #define cpu_list arm_cpu_list
 
-#define CPU_SAVE_VERSION 9
-
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
 #define MMU_MODE1_SUFFIX _user
index 68dca7ffb2b6c5bf2a77a4c3561d844b97dad600..3c41f06a756b6ea2ecc91d8040998b8528ebfb2d 100644 (file)
 #include "hw/hw.h"
 #include "hw/boards.h"
 
-void cpu_save(QEMUFile *f, void *opaque)
+static bool vfp_needed(void *opaque)
 {
-    int i;
-    CPUARMState *env = (CPUARMState *)opaque;
+    ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
 
-    for (i = 0; i < 16; i++) {
-        qemu_put_be32(f, env->regs[i]);
-    }
-    qemu_put_be32(f, cpsr_read(env));
-    qemu_put_be32(f, env->spsr);
-    for (i = 0; i < 6; i++) {
-        qemu_put_be32(f, env->banked_spsr[i]);
-        qemu_put_be32(f, env->banked_r13[i]);
-        qemu_put_be32(f, env->banked_r14[i]);
-    }
-    for (i = 0; i < 5; i++) {
-        qemu_put_be32(f, env->usr_regs[i]);
-        qemu_put_be32(f, env->fiq_regs[i]);
-    }
-    qemu_put_be32(f, env->cp15.c0_cpuid);
-    qemu_put_be32(f, env->cp15.c0_cssel);
-    qemu_put_be32(f, env->cp15.c1_sys);
-    qemu_put_be32(f, env->cp15.c1_coproc);
-    qemu_put_be32(f, env->cp15.c1_xscaleauxcr);
-    qemu_put_be32(f, env->cp15.c1_scr);
-    qemu_put_be32(f, env->cp15.c2_base0);
-    qemu_put_be32(f, env->cp15.c2_base0_hi);
-    qemu_put_be32(f, env->cp15.c2_base1);
-    qemu_put_be32(f, env->cp15.c2_base1_hi);
-    qemu_put_be32(f, env->cp15.c2_control);
-    qemu_put_be32(f, env->cp15.c2_mask);
-    qemu_put_be32(f, env->cp15.c2_base_mask);
-    qemu_put_be32(f, env->cp15.c2_data);
-    qemu_put_be32(f, env->cp15.c2_insn);
-    qemu_put_be32(f, env->cp15.c3);
-    qemu_put_be32(f, env->cp15.c5_insn);
-    qemu_put_be32(f, env->cp15.c5_data);
-    for (i = 0; i < 8; i++) {
-        qemu_put_be32(f, env->cp15.c6_region[i]);
-    }
-    qemu_put_be32(f, env->cp15.c6_insn);
-    qemu_put_be32(f, env->cp15.c6_data);
-    qemu_put_be32(f, env->cp15.c7_par);
-    qemu_put_be32(f, env->cp15.c7_par_hi);
-    qemu_put_be32(f, env->cp15.c9_insn);
-    qemu_put_be32(f, env->cp15.c9_data);
-    qemu_put_be32(f, env->cp15.c9_pmcr);
-    qemu_put_be32(f, env->cp15.c9_pmcnten);
-    qemu_put_be32(f, env->cp15.c9_pmovsr);
-    qemu_put_be32(f, env->cp15.c9_pmxevtyper);
-    qemu_put_be32(f, env->cp15.c9_pmuserenr);
-    qemu_put_be32(f, env->cp15.c9_pminten);
-    qemu_put_be32(f, env->cp15.c13_fcse);
-    qemu_put_be32(f, env->cp15.c13_context);
-    qemu_put_be32(f, env->cp15.c13_tls1);
-    qemu_put_be32(f, env->cp15.c13_tls2);
-    qemu_put_be32(f, env->cp15.c13_tls3);
-    qemu_put_be32(f, env->cp15.c15_cpar);
-    qemu_put_be32(f, env->cp15.c15_power_control);
-    qemu_put_be32(f, env->cp15.c15_diagnostic);
-    qemu_put_be32(f, env->cp15.c15_power_diagnostic);
-
-    qemu_put_be64(f, env->features);
-
-    if (arm_feature(env, ARM_FEATURE_VFP)) {
-        for (i = 0;  i < 16; i++) {
-            CPU_DoubleU u;
-            u.d = env->vfp.regs[i];
-            qemu_put_be32(f, u.l.upper);
-            qemu_put_be32(f, u.l.lower);
-        }
-        for (i = 0; i < 16; i++) {
-            qemu_put_be32(f, env->vfp.xregs[i]);
-        }
+    return arm_feature(env, ARM_FEATURE_VFP);
+}
 
+static const VMStateDescription vmstate_vfp = {
+    .name = "cpu/vfp",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_FLOAT64_ARRAY(env.vfp.regs, ARMCPU, 32),
+        VMSTATE_UINT32_ARRAY(env.vfp.xregs, ARMCPU, 16),
         /* TODO: Should use proper FPSCR access functions.  */
-        qemu_put_be32(f, env->vfp.vec_len);
-        qemu_put_be32(f, env->vfp.vec_stride);
-
-        if (arm_feature(env, ARM_FEATURE_VFP3)) {
-            for (i = 16;  i < 32; i++) {
-                CPU_DoubleU u;
-                u.d = env->vfp.regs[i];
-                qemu_put_be32(f, u.l.upper);
-                qemu_put_be32(f, u.l.lower);
-            }
-        }
+        VMSTATE_INT32(env.vfp.vec_len, ARMCPU),
+        VMSTATE_INT32(env.vfp.vec_stride, ARMCPU),
+        VMSTATE_END_OF_LIST()
     }
+};
 
-    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
-        for (i = 0; i < 16; i++) {
-            qemu_put_be64(f, env->iwmmxt.regs[i]);
-        }
-        for (i = 0; i < 16; i++) {
-            qemu_put_be32(f, env->iwmmxt.cregs[i]);
-        }
-    }
+static bool iwmmxt_needed(void *opaque)
+{
+    ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
 
-    if (arm_feature(env, ARM_FEATURE_M)) {
-        qemu_put_be32(f, env->v7m.other_sp);
-        qemu_put_be32(f, env->v7m.vecbase);
-        qemu_put_be32(f, env->v7m.basepri);
-        qemu_put_be32(f, env->v7m.control);
-        qemu_put_be32(f, env->v7m.current_sp);
-        qemu_put_be32(f, env->v7m.exception);
-    }
+    return arm_feature(env, ARM_FEATURE_IWMMXT);
+}
 
-    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
-        qemu_put_be32(f, env->teecr);
-        qemu_put_be32(f, env->teehbr);
+static const VMStateDescription vmstate_iwmmxt = {
+    .name = "cpu/iwmmxt",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64_ARRAY(env.iwmmxt.regs, ARMCPU, 16),
+        VMSTATE_UINT32_ARRAY(env.iwmmxt.cregs, ARMCPU, 16),
+        VMSTATE_END_OF_LIST()
     }
+};
+
+static bool m_needed(void *opaque)
+{
+    ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
+
+    return arm_feature(env, ARM_FEATURE_M);
 }
 
-int cpu_load(QEMUFile *f, void *opaque, int version_id)
+const VMStateDescription vmstate_m = {
+    .name = "cpu/m",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(env.v7m.other_sp, ARMCPU),
+        VMSTATE_UINT32(env.v7m.vecbase, ARMCPU),
+        VMSTATE_UINT32(env.v7m.basepri, ARMCPU),
+        VMSTATE_UINT32(env.v7m.control, ARMCPU),
+        VMSTATE_INT32(env.v7m.current_sp, ARMCPU),
+        VMSTATE_INT32(env.v7m.exception, ARMCPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static bool thumb2ee_needed(void *opaque)
 {
-    CPUARMState *env = (CPUARMState *)opaque;
-    int i;
-    uint32_t val;
+    ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
 
-    if (version_id != CPU_SAVE_VERSION)
-        return -EINVAL;
+    return arm_feature(env, ARM_FEATURE_THUMB2EE);
+}
 
-    for (i = 0; i < 16; i++) {
-        env->regs[i] = qemu_get_be32(f);
+static const VMStateDescription vmstate_thumb2ee = {
+    .name = "cpu/thumb2ee",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(env.teecr, ARMCPU),
+        VMSTATE_UINT32(env.teehbr, ARMCPU),
+        VMSTATE_END_OF_LIST()
     }
-    val = qemu_get_be32(f);
-    /* Avoid mode switch when restoring CPSR.  */
+};
+
+static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
+{
+    ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
+    uint32_t val = qemu_get_be32(f);
+
+    /* Avoid mode switch when restoring CPSR */
     env->uncached_cpsr = val & CPSR_M;
     cpsr_write(env, val, 0xffffffff);
-    env->spsr = qemu_get_be32(f);
-    for (i = 0; i < 6; i++) {
-        env->banked_spsr[i] = qemu_get_be32(f);
-        env->banked_r13[i] = qemu_get_be32(f);
-        env->banked_r14[i] = qemu_get_be32(f);
-    }
-    for (i = 0; i < 5; i++) {
-        env->usr_regs[i] = qemu_get_be32(f);
-        env->fiq_regs[i] = qemu_get_be32(f);
-    }
-    env->cp15.c0_cpuid = qemu_get_be32(f);
-    env->cp15.c0_cssel = qemu_get_be32(f);
-    env->cp15.c1_sys = qemu_get_be32(f);
-    env->cp15.c1_coproc = qemu_get_be32(f);
-    env->cp15.c1_xscaleauxcr = qemu_get_be32(f);
-    env->cp15.c1_scr = qemu_get_be32(f);
-    env->cp15.c2_base0 = qemu_get_be32(f);
-    env->cp15.c2_base0_hi = qemu_get_be32(f);
-    env->cp15.c2_base1 = qemu_get_be32(f);
-    env->cp15.c2_base1_hi = qemu_get_be32(f);
-    env->cp15.c2_control = qemu_get_be32(f);
-    env->cp15.c2_mask = qemu_get_be32(f);
-    env->cp15.c2_base_mask = qemu_get_be32(f);
-    env->cp15.c2_data = qemu_get_be32(f);
-    env->cp15.c2_insn = qemu_get_be32(f);
-    env->cp15.c3 = qemu_get_be32(f);
-    env->cp15.c5_insn = qemu_get_be32(f);
-    env->cp15.c5_data = qemu_get_be32(f);
-    for (i = 0; i < 8; i++) {
-        env->cp15.c6_region[i] = qemu_get_be32(f);
-    }
-    env->cp15.c6_insn = qemu_get_be32(f);
-    env->cp15.c6_data = qemu_get_be32(f);
-    env->cp15.c7_par = qemu_get_be32(f);
-    env->cp15.c7_par_hi = qemu_get_be32(f);
-    env->cp15.c9_insn = qemu_get_be32(f);
-    env->cp15.c9_data = qemu_get_be32(f);
-    env->cp15.c9_pmcr = qemu_get_be32(f);
-    env->cp15.c9_pmcnten = qemu_get_be32(f);
-    env->cp15.c9_pmovsr = qemu_get_be32(f);
-    env->cp15.c9_pmxevtyper = qemu_get_be32(f);
-    env->cp15.c9_pmuserenr = qemu_get_be32(f);
-    env->cp15.c9_pminten = qemu_get_be32(f);
-    env->cp15.c13_fcse = qemu_get_be32(f);
-    env->cp15.c13_context = qemu_get_be32(f);
-    env->cp15.c13_tls1 = qemu_get_be32(f);
-    env->cp15.c13_tls2 = qemu_get_be32(f);
-    env->cp15.c13_tls3 = qemu_get_be32(f);
-    env->cp15.c15_cpar = qemu_get_be32(f);
-    env->cp15.c15_power_control = qemu_get_be32(f);
-    env->cp15.c15_diagnostic = qemu_get_be32(f);
-    env->cp15.c15_power_diagnostic = qemu_get_be32(f);
-
-    env->features = qemu_get_be64(f);
-
-    if (arm_feature(env, ARM_FEATURE_VFP)) {
-        for (i = 0;  i < 16; i++) {
-            CPU_DoubleU u;
-            u.l.upper = qemu_get_be32(f);
-            u.l.lower = qemu_get_be32(f);
-            env->vfp.regs[i] = u.d;
-        }
-        for (i = 0; i < 16; i++) {
-            env->vfp.xregs[i] = qemu_get_be32(f);
-        }
-
-        /* TODO: Should use proper FPSCR access functions.  */
-        env->vfp.vec_len = qemu_get_be32(f);
-        env->vfp.vec_stride = qemu_get_be32(f);
-
-        if (arm_feature(env, ARM_FEATURE_VFP3)) {
-            for (i = 16;  i < 32; i++) {
-                CPU_DoubleU u;
-                u.l.upper = qemu_get_be32(f);
-                u.l.lower = qemu_get_be32(f);
-                env->vfp.regs[i] = u.d;
-            }
-        }
-    }
+    return 0;
+}
 
-    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
-        for (i = 0; i < 16; i++) {
-            env->iwmmxt.regs[i] = qemu_get_be64(f);
-        }
-        for (i = 0; i < 16; i++) {
-            env->iwmmxt.cregs[i] = qemu_get_be32(f);
-        }
-    }
+static void put_cpsr(QEMUFile *f, void *opaque, size_t size)
+{
+    ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
 
-    if (arm_feature(env, ARM_FEATURE_M)) {
-        env->v7m.other_sp = qemu_get_be32(f);
-        env->v7m.vecbase = qemu_get_be32(f);
-        env->v7m.basepri = qemu_get_be32(f);
-        env->v7m.control = qemu_get_be32(f);
-        env->v7m.current_sp = qemu_get_be32(f);
-        env->v7m.exception = qemu_get_be32(f);
-    }
+    qemu_put_be32(f, cpsr_read(env));
+}
 
-    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
-        env->teecr = qemu_get_be32(f);
-        env->teehbr = qemu_get_be32(f);
+static const VMStateInfo vmstate_cpsr = {
+    .name = "cpsr",
+    .get = get_cpsr,
+    .put = put_cpsr,
+};
+
+const VMStateDescription vmstate_arm_cpu = {
+    .name = "cpu",
+    .version_id = 10,
+    .minimum_version_id = 10,
+    .minimum_version_id_old = 10,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(env.regs, ARMCPU, 16),
+        {
+            .name = "cpsr",
+            .version_id = 0,
+            .size = sizeof(uint32_t),
+            .info = &vmstate_cpsr,
+            .flags = VMS_SINGLE,
+            .offset = 0,
+        },
+        VMSTATE_UINT32(env.spsr, ARMCPU),
+        VMSTATE_UINT32_ARRAY(env.banked_spsr, ARMCPU, 6),
+        VMSTATE_UINT32_ARRAY(env.banked_r13, ARMCPU, 6),
+        VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 6),
+        VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
+        VMSTATE_UINT32_ARRAY(env.fiq_regs, ARMCPU, 5),
+        VMSTATE_UINT32(env.cp15.c0_cpuid, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c0_cssel, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c1_sys, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c1_coproc, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c1_xscaleauxcr, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c1_scr, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c2_base0, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c2_base0_hi, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c2_base1, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c2_base1_hi, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c2_control, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c2_mask, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c2_base_mask, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c2_data, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c2_insn, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c3, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c5_insn, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c5_data, ARMCPU),
+        VMSTATE_UINT32_ARRAY(env.cp15.c6_region, ARMCPU, 8),
+        VMSTATE_UINT32(env.cp15.c6_insn, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c6_data, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c7_par, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c7_par_hi, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c9_insn, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c9_data, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c9_pmcr, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c9_pmcnten, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c9_pmovsr, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c9_pmxevtyper, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c9_pmuserenr, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c9_pminten, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c13_fcse, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c13_context, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c13_tls1, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c13_tls2, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c13_tls3, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c15_cpar, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c15_power_control, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c15_diagnostic, ARMCPU),
+        VMSTATE_UINT32(env.cp15.c15_power_diagnostic, ARMCPU),
+        VMSTATE_UINT64(env.features, ARMCPU),
+        VMSTATE_END_OF_LIST()
+    },
+    .subsections = (VMStateSubsection[]) {
+        {
+            .vmsd = &vmstate_vfp,
+            .needed = vfp_needed,
+        } , {
+            .vmsd = &vmstate_iwmmxt,
+            .needed = iwmmxt_needed,
+        } , {
+            .vmsd = &vmstate_m,
+            .needed = m_needed,
+        } , {
+            .vmsd = &vmstate_thumb2ee,
+            .needed = thumb2ee_needed,
+        } , {
+            /* empty */
+        }
     }
-
-    return 0;
-}
+};
This page took 0.037764 seconds and 4 git commands to generate.