@@ -79,6 +79,27 @@ static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
}
}
+static void cp_reg_check_reset(gpointer key, gpointer value, gpointer opaque)
+{
+ /* Purely an assertion check: we've already done reset once,
+ * so now check that running the reset for the cpreg doesn't
+ * change its value. This traps bugs where two different cpregs
+ * both try to reset the same state field but to different values.
+ */
+ ARMCPRegInfo *ri = value;
+ ARMCPU *cpu = opaque;
+ uint64_t oldvalue, newvalue;
+
+ if (ri->type & (ARM_CP_SPECIAL | ARM_CP_ALIAS | ARM_CP_NO_RAW)) {
+ return;
+ }
+
+ oldvalue = read_raw_cp_reg(&cpu->env, ri);
+ cp_reg_reset(key, value, opaque);
+ newvalue = read_raw_cp_reg(&cpu->env, ri);
+ assert(oldvalue == newvalue);
+}
+
/* CPUClass::reset() */
static void arm_cpu_reset(CPUState *s)
{
@@ -90,6 +111,8 @@ static void arm_cpu_reset(CPUState *s)
memset(env, 0, offsetof(CPUARMState, features));
g_hash_table_foreach(cpu->cp_regs, cp_reg_reset, cpu);
+ g_hash_table_foreach(cpu->cp_regs, cp_reg_check_reset, cpu);
+
env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid;
env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0;
env->vfp.xregs[ARM_VFP_MVFR1] = cpu->mvfr1;
@@ -1448,6 +1448,9 @@ static inline bool cp_access_ok(int current_el,
return (ri->access >> ((current_el * 2) + isread)) & 1;
}
+/* Raw read of a coprocessor register (as needed for migration, etc) */
+uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri);
+
/**
* write_list_to_cpustate
* @cpu: ARMCPU
@@ -144,7 +144,7 @@ static void *raw_ptr(CPUARMState *env, const ARMCPRegInfo *ri)
return (char *)env + ri->fieldoffset;
}
-static uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri)
+uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri)
{
/* Raw read of a coprocessor register (as needed for migration, etc). */
if (ri->type & ARM_CP_CONST) {