summaryrefslogtreecommitdiff
path: root/target-arm/machine.c
diff options
context:
space:
mode:
authorJuan Quintela <quintela@redhat.com>2013-04-19 12:24:19 +0100
committerPeter Maydell <peter.maydell@linaro.org>2013-04-19 12:24:19 +0100
commit3cc1d20823e8677038c5bb5db10910f6271b1883 (patch)
treed87ff547e6affa2312844d3b53221f0336116a8e /target-arm/machine.c
parent3b3284486be6898937395fac3ddbd2e68c5cb52f (diff)
downloadqemu-3cc1d20823e8677038c5bb5db10910f6271b1883.tar.gz
target-arm: port ARM CPU save/load to use VMState
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 <quintela@redhat.com> [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 <peter.maydell@linaro.org>
Diffstat (limited to 'target-arm/machine.c')
-rw-r--r--target-arm/machine.c387
1 files changed, 174 insertions, 213 deletions
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 68dca7ffb2..3c41f06a75 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -1,237 +1,198 @@
#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;
-}
+};