The debug migration state does not include mcontext. Change to using
a new sdtrig vmstate format that allows for all architectural state
if mcontext != 0.

This means a machine is sometimes-migratable, which on second
thoughts is probably bad. Is there a better way to do this, or could
we just break compat and move to the new vmstate?

Not yet signed off.
---
 target/riscv/machine.c | 58 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index fdd5e8b67b..23a5f60d2a 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -221,8 +221,10 @@ static const VMStateDescription vmstate_kvmtimer = {
 static bool debug_needed(void *opaque)
 {
     RISCVCPU *cpu = opaque;
+    CPURISCVState *env = &cpu->env;
 
-    return cpu->cfg.debug;
+    return cpu->cfg.debug &&
+           env->sdtrig_state.mcontext == 0;
 }
 
 static int debug_pre_save(void *opaque)
@@ -273,6 +275,59 @@ static const VMStateDescription vmstate_debug = {
     }
 };
 
+/*
+ * This is a newer version of the debug (sdtrig) state, required
+ * to migrate hcontext/mcontext.
+ */
+static bool sdtrig_needed(void *opaque)
+{
+    RISCVCPU *cpu = opaque;
+    CPURISCVState *env = &cpu->env;
+
+    return cpu->cfg.debug &&
+           env->sdtrig_state.mcontext != 0;
+}
+
+static int sdtrig_post_load(void *opaque, int version_id)
+{
+    RISCVCPU *cpu = opaque;
+    CPURISCVState *env = &cpu->env;
+
+    riscv_cpu_debug_post_load(env);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_sdtrig_trigger = {
+    .name = "cpu/sdtrig/trigger",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINTTL(tdata1, SdtrigTrigger),
+        VMSTATE_UINTTL(tdata2, SdtrigTrigger),
+        VMSTATE_UINTTL(tdata3, SdtrigTrigger),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_sdtrig = {
+    .name = "cpu/sdtrig",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = sdtrig_needed,
+    .post_load = sdtrig_post_load,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINTTL(env.sdtrig_state.trigger_cur, RISCVCPU),
+        VMSTATE_UINTTL(env.sdtrig_state.tcontrol, RISCVCPU),
+        VMSTATE_UINTTL(env.sdtrig_state.mcontext, RISCVCPU),
+        VMSTATE_UINTTL(env.sdtrig_state.scontext, RISCVCPU),
+        VMSTATE_STRUCT_ARRAY(env.sdtrig_state.triggers, RISCVCPU,
+                             RV_MAX_SDTRIG_TRIGGERS,
+                             0, vmstate_sdtrig_trigger, SdtrigTrigger),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static int riscv_cpu_post_load(void *opaque, int version_id)
 {
     RISCVCPU *cpu = opaque;
@@ -514,6 +569,7 @@ const VMStateDescription vmstate_riscv_cpu = {
 #endif
         &vmstate_envcfg,
         &vmstate_debug,
+        &vmstate_sdtrig,
         &vmstate_smstateen,
         &vmstate_jvt,
         &vmstate_elp,
-- 
2.51.0


Reply via email to