|
@@ -266,7 +266,7 @@ static bool raw_accessors_invalid(const ARMCPRegInfo *ri)
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-bool write_cpustate_to_list(ARMCPU *cpu)
|
|
|
|
|
|
+bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
|
|
{
|
|
{
|
|
/* Write the coprocessor state from cpu->env to the (index,value) list. */
|
|
/* Write the coprocessor state from cpu->env to the (index,value) list. */
|
|
int i;
|
|
int i;
|
|
@@ -275,6 +275,7 @@ bool write_cpustate_to_list(ARMCPU *cpu)
|
|
for (i = 0; i < cpu->cpreg_array_len; i++) {
|
|
for (i = 0; i < cpu->cpreg_array_len; i++) {
|
|
uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
|
|
uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
|
|
const ARMCPRegInfo *ri;
|
|
const ARMCPRegInfo *ri;
|
|
|
|
+ uint64_t newval;
|
|
|
|
|
|
ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
|
|
ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
|
|
if (!ri) {
|
|
if (!ri) {
|
|
@@ -284,7 +285,29 @@ bool write_cpustate_to_list(ARMCPU *cpu)
|
|
if (ri->type & ARM_CP_NO_RAW) {
|
|
if (ri->type & ARM_CP_NO_RAW) {
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
- cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
|
|
|
|
|
|
+
|
|
|
|
+ newval = read_raw_cp_reg(&cpu->env, ri);
|
|
|
|
+ if (kvm_sync) {
|
|
|
|
+ /*
|
|
|
|
+ * Only sync if the previous list->cpustate sync succeeded.
|
|
|
|
+ * Rather than tracking the success/failure state for every
|
|
|
|
+ * item in the list, we just recheck "does the raw write we must
|
|
|
|
+ * have made in write_list_to_cpustate() read back OK" here.
|
|
|
|
+ */
|
|
|
|
+ uint64_t oldval = cpu->cpreg_values[i];
|
|
|
|
+
|
|
|
|
+ if (oldval == newval) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ write_raw_cp_reg(&cpu->env, ri, oldval);
|
|
|
|
+ if (read_raw_cp_reg(&cpu->env, ri) != oldval) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ write_raw_cp_reg(&cpu->env, ri, newval);
|
|
|
|
+ }
|
|
|
|
+ cpu->cpreg_values[i] = newval;
|
|
}
|
|
}
|
|
return ok;
|
|
return ok;
|
|
}
|
|
}
|