Some Sdtrig implementations support more than 2 debug triggers,
but the Sdtrig vmstate is tied to 2 triggers. Extending this will
be a compatibility issue anyway, so move to a nicer layout and
provide state for all 32 architecturally possible triggers.

Signed-off-by: Nicholas Piggin <[email protected]>
---
 target/riscv/cpu.h         |  35 ++++++--
 target/riscv/csr.c         |   7 +-
 target/riscv/debug.c       | 167 +++++++++++++++++++++----------------
 target/riscv/debug.h       |   3 +-
 target/riscv/machine.c     |  31 ++++++-
 target/riscv/tcg/tcg-cpu.c |   3 +-
 6 files changed, 157 insertions(+), 89 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index a718287d41..44ed1665e2 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -194,6 +194,28 @@ FIELD(VTYPE, VMA, 7, 1)
 FIELD(VTYPE, VEDIV, 8, 2)
 FIELD(VTYPE, RESERVED, 10, sizeof(target_ulong) * 8 - 11)
 
+#ifndef CONFIG_USER_ONLY
+typedef struct SdtrigTrigger {
+    target_ulong tdata1;
+    target_ulong tdata2;
+    target_ulong tdata3;
+} SdtrigTrigger;
+
+typedef struct SdtrigState {
+    /* Architected state */
+    target_ulong trigger_cur; /* tselect */
+    SdtrigTrigger triggers[RV_MAX_SDTRIG_TRIGGERS];
+    target_ulong tcontrol;
+    target_ulong mcontext; /* hcontext */
+    target_ulong scontext;
+
+    /* QEMU state */
+    struct CPUBreakpoint *cpu_breakpoint[RV_MAX_SDTRIG_TRIGGERS];
+    struct CPUWatchpoint *cpu_watchpoint[RV_MAX_SDTRIG_TRIGGERS];
+    bool itrigger_enabled;
+} SdtrigState;
+#endif
+
 typedef struct PMUCTRState {
     /* Current value of a counter */
     uint64_t mhpmcounter_val;
@@ -443,14 +465,11 @@ struct CPUArchState {
     target_ulong mseccfg;
 
     /* trigger module */
-    target_ulong trigger_cur;
-    target_ulong tdata1[RV_MAX_TRIGGERS];
-    target_ulong tdata2[RV_MAX_TRIGGERS];
-    target_ulong tdata3[RV_MAX_TRIGGERS];
-    target_ulong mcontext;
-    struct CPUBreakpoint *cpu_breakpoint[RV_MAX_TRIGGERS];
-    struct CPUWatchpoint *cpu_watchpoint[RV_MAX_TRIGGERS];
-    bool itrigger_enabled;
+    SdtrigState sdtrig_state;
+    /* migration compat */
+    target_ulong old_tdata1[RV_DEFAULT_TRIGGERS];
+    target_ulong old_tdata2[RV_DEFAULT_TRIGGERS];
+    target_ulong old_tdata3[RV_DEFAULT_TRIGGERS];
 
     /* machine specific rdtime callback */
     uint64_t (*rdtime_fn)(void *);
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 05c7ec8352..ec70a47d0b 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -5311,7 +5311,8 @@ static RISCVException read_tdata(CPURISCVState *env, int 
csrno,
                                  target_ulong *val)
 {
     /* return 0 in tdata1 to end the trigger enumeration */
-    if (env->trigger_cur >= RV_MAX_TRIGGERS && csrno == CSR_TDATA1) {
+    if (env->sdtrig_state.trigger_cur >= RV_MAX_SDTRIG_TRIGGERS &&
+        csrno == CSR_TDATA1) {
         *val = 0;
         return RISCV_EXCP_NONE;
     }
@@ -5345,7 +5346,7 @@ static RISCVException read_tinfo(CPURISCVState *env, int 
csrno,
 static RISCVException read_mcontext(CPURISCVState *env, int csrno,
                                     target_ulong *val)
 {
-    *val = env->mcontext;
+    *val = env->sdtrig_state.mcontext;
     return RISCV_EXCP_NONE;
 }
 
@@ -5363,7 +5364,7 @@ static RISCVException write_mcontext(CPURISCVState *env, 
int csrno,
         mask = rv32 ? MCONTEXT32 : MCONTEXT64;
     }
 
-    env->mcontext = val & mask;
+    env->sdtrig_state.mcontext = val & mask;
     return RISCV_EXCP_NONE;
 }
 
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 96b00193e2..22f7958a79 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -90,13 +90,15 @@ static inline target_ulong 
extract_trigger_type(CPURISCVState *env,
 static inline target_ulong get_trigger_type(CPURISCVState *env,
                                             target_ulong trigger_index)
 {
-    return extract_trigger_type(env, env->tdata1[trigger_index]);
+    SdtrigTrigger *trigger = &env->sdtrig_state.triggers[trigger_index];
+    return extract_trigger_type(env, trigger->tdata1);
 }
 
 static trigger_action_t get_trigger_action(CPURISCVState *env,
                                            target_ulong trigger_index)
 {
-    target_ulong tdata1 = env->tdata1[trigger_index];
+    SdtrigTrigger *trigger = &env->sdtrig_state.triggers[trigger_index];
+    target_ulong tdata1 = trigger->tdata1;
     int trigger_type = get_trigger_type(env, trigger_index);
     trigger_action_t action = DBG_ACTION_NONE;
 
@@ -155,7 +157,7 @@ static inline target_ulong build_tdata1(CPURISCVState *env,
 
 bool tdata_available(CPURISCVState *env, int tdata_index)
 {
-    int trigger_type = get_trigger_type(env, env->trigger_cur);
+    int trigger_type = get_trigger_type(env, env->sdtrig_state.trigger_cur);
 
     if (unlikely(tdata_index >= TDATA_NUM)) {
         return false;
@@ -166,13 +168,13 @@ bool tdata_available(CPURISCVState *env, int tdata_index)
 
 target_ulong tselect_csr_read(CPURISCVState *env)
 {
-    return env->trigger_cur;
+    return env->sdtrig_state.trigger_cur;
 }
 
 void tselect_csr_write(CPURISCVState *env, target_ulong val)
 {
-    if (val < RV_MAX_TRIGGERS) {
-        env->trigger_cur = val;
+    if (val < RV_DEFAULT_TRIGGERS) {
+        env->sdtrig_state.trigger_cur = val;
     }
 }
 
@@ -342,7 +344,8 @@ static bool icount_priv_match(CPURISCVState *env, 
target_ulong tdata1)
 static bool trigger_priv_match(CPURISCVState *env, trigger_type_t type,
                                int trigger_index)
 {
-    target_ulong tdata1 = env->tdata1[trigger_index];
+    SdtrigTrigger *trigger = &env->sdtrig_state.triggers[trigger_index];
+    target_ulong tdata1 = trigger->tdata1;
 
     switch (type) {
     case TRIGGER_TYPE_AD_MATCH:
@@ -371,7 +374,8 @@ static bool trigger_priv_match(CPURISCVState *env, 
trigger_type_t type,
 static bool trigger_textra_match(CPURISCVState *env, trigger_type_t type,
                                  int trigger_index)
 {
-    target_ulong textra = env->tdata3[trigger_index];
+    SdtrigTrigger *trigger = &env->sdtrig_state.triggers[trigger_index];
+    target_ulong textra = trigger->tdata3;
     target_ulong mhvalue, mhselect;
 
     if (type < TRIGGER_TYPE_AD_MATCH || type > TRIGGER_TYPE_AD_MATCH6) {
@@ -399,7 +403,7 @@ static bool trigger_textra_match(CPURISCVState *env, 
trigger_type_t type,
         break;
     case MHSELECT_MCONTEXT:
         /* Match if the low bits of mcontext/hcontext equal mhvalue. */
-        if (mhvalue != env->mcontext) {
+        if (mhvalue != env->sdtrig_state.mcontext) {
             return false;
         }
         break;
@@ -477,8 +481,9 @@ static target_ulong type2_mcontrol_validate(CPURISCVState 
*env,
 
 static void type2_breakpoint_insert(CPURISCVState *env, target_ulong index)
 {
-    target_ulong ctrl = env->tdata1[index];
-    target_ulong addr = env->tdata2[index];
+    SdtrigTrigger *trigger = &env->sdtrig_state.triggers[index];
+    target_ulong ctrl = trigger->tdata1;
+    target_ulong addr = trigger->tdata2;
     bool enabled = type2_breakpoint_enabled(ctrl);
     CPUState *cs = env_cpu(env);
     int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
@@ -489,7 +494,8 @@ static void type2_breakpoint_insert(CPURISCVState *env, 
target_ulong index)
     }
 
     if (ctrl & TYPE2_EXEC) {
-        cpu_breakpoint_insert(cs, addr, flags, &env->cpu_breakpoint[index]);
+        cpu_breakpoint_insert(cs, addr, flags,
+                              &env->sdtrig_state.cpu_breakpoint[index]);
     }
 
     if (ctrl & TYPE2_LOAD) {
@@ -503,12 +509,12 @@ static void type2_breakpoint_insert(CPURISCVState *env, 
target_ulong index)
         size = type2_breakpoint_size(env, ctrl);
         if (size != 0) {
             cpu_watchpoint_insert(cs, addr, size, flags,
-                                  &env->cpu_watchpoint[index]);
+                                  &env->sdtrig_state.cpu_watchpoint[index]);
         } else {
             def_size = riscv_cpu_mxl(env) == MXL_RV64 ? 8 : 4;
 
             cpu_watchpoint_insert(cs, addr, def_size, flags,
-                                  &env->cpu_watchpoint[index]);
+                                  &env->sdtrig_state.cpu_watchpoint[index]);
         }
     }
 }
@@ -517,29 +523,32 @@ static void type2_breakpoint_remove(CPURISCVState *env, 
target_ulong index)
 {
     CPUState *cs = env_cpu(env);
 
-    if (env->cpu_breakpoint[index]) {
-        cpu_breakpoint_remove_by_ref(cs, env->cpu_breakpoint[index]);
-        env->cpu_breakpoint[index] = NULL;
+    if (env->sdtrig_state.cpu_breakpoint[index]) {
+        cpu_breakpoint_remove_by_ref(cs,
+                                     env->sdtrig_state.cpu_breakpoint[index]);
+        env->sdtrig_state.cpu_breakpoint[index] = NULL;
     }
 
-    if (env->cpu_watchpoint[index]) {
-        cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]);
-        env->cpu_watchpoint[index] = NULL;
+    if (env->sdtrig_state.cpu_watchpoint[index]) {
+        cpu_watchpoint_remove_by_ref(cs,
+                                     env->sdtrig_state.cpu_watchpoint[index]);
+        env->sdtrig_state.cpu_watchpoint[index] = NULL;
     }
 }
 
 static void type2_reg_write(CPURISCVState *env, target_ulong index,
                             int tdata_index, target_ulong val)
 {
+    SdtrigTrigger *trigger = &env->sdtrig_state.triggers[index];
     switch (tdata_index) {
     case TDATA1:
-        env->tdata1[index] = type2_mcontrol_validate(env, val);
+        trigger->tdata1 = type2_mcontrol_validate(env, val);
         break;
     case TDATA2:
-        env->tdata2[index] = val;
+        trigger->tdata2 = val;
         break;
     case TDATA3:
-        env->tdata3[index] = textra_validate(env, val);
+        trigger->tdata3 = textra_validate(env, val);
         break;
     default:
         g_assert_not_reached();
@@ -593,8 +602,9 @@ static target_ulong type6_mcontrol6_validate(CPURISCVState 
*env,
 
 static void type6_breakpoint_insert(CPURISCVState *env, target_ulong index)
 {
-    target_ulong ctrl = env->tdata1[index];
-    target_ulong addr = env->tdata2[index];
+    SdtrigTrigger *trigger = &env->sdtrig_state.triggers[index];
+    target_ulong ctrl = trigger->tdata1;
+    target_ulong addr = trigger->tdata2;
     bool enabled = type6_breakpoint_enabled(ctrl);
     CPUState *cs = env_cpu(env);
     int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
@@ -605,7 +615,8 @@ static void type6_breakpoint_insert(CPURISCVState *env, 
target_ulong index)
     }
 
     if (ctrl & TYPE6_EXEC) {
-        cpu_breakpoint_insert(cs, addr, flags, &env->cpu_breakpoint[index]);
+        cpu_breakpoint_insert(cs, addr, flags,
+                              &env->sdtrig_state.cpu_breakpoint[index]);
     }
 
     if (ctrl & TYPE6_LOAD) {
@@ -620,10 +631,10 @@ static void type6_breakpoint_insert(CPURISCVState *env, 
target_ulong index)
         size = extract32(ctrl, 16, 4);
         if (size != 0) {
             cpu_watchpoint_insert(cs, addr, size, flags,
-                                  &env->cpu_watchpoint[index]);
+                                  &env->sdtrig_state.cpu_watchpoint[index]);
         } else {
             cpu_watchpoint_insert(cs, addr, 8, flags,
-                                  &env->cpu_watchpoint[index]);
+                                  &env->sdtrig_state.cpu_watchpoint[index]);
         }
     }
 }
@@ -636,15 +647,16 @@ static void type6_breakpoint_remove(CPURISCVState *env, 
target_ulong index)
 static void type6_reg_write(CPURISCVState *env, target_ulong index,
                             int tdata_index, target_ulong val)
 {
+    SdtrigTrigger *trigger = &env->sdtrig_state.triggers[index];
     switch (tdata_index) {
     case TDATA1:
-        env->tdata1[index] = type6_mcontrol6_validate(env, val);
+        trigger->tdata1 = type6_mcontrol6_validate(env, val);
         break;
     case TDATA2:
-        env->tdata2[index] = val;
+        trigger->tdata2 = val;
         break;
     case TDATA3:
-        env->tdata3[index] = textra_validate(env, val);
+        trigger->tdata3 = textra_validate(env, val);
         break;
     default:
         g_assert_not_reached();
@@ -656,21 +668,22 @@ static void type6_reg_write(CPURISCVState *env, 
target_ulong index,
 static inline int
 itrigger_get_count(CPURISCVState *env, int index)
 {
-    return get_field(env->tdata1[index], ITRIGGER_COUNT);
+    SdtrigTrigger *trigger = &env->sdtrig_state.triggers[index];
+    return get_field(trigger->tdata1, ITRIGGER_COUNT);
 }
 
 static inline void
 itrigger_set_count(CPURISCVState *env, int index, int value)
 {
-    env->tdata1[index] = set_field(env->tdata1[index],
-                                   ITRIGGER_COUNT, value);
+    SdtrigTrigger *trigger = &env->sdtrig_state.triggers[index];
+    trigger->tdata1 = set_field(trigger->tdata1, ITRIGGER_COUNT, value);
 }
 
 static bool riscv_itrigger_enabled(CPURISCVState *env)
 {
     int count;
 
-    for (int i = 0; i < RV_MAX_TRIGGERS; i++) {
+    for (int i = 0; i < RV_MAX_SDTRIG_TRIGGERS; i++) {
         if (get_trigger_type(env, i) != TRIGGER_TYPE_INST_CNT) {
             continue;
         }
@@ -697,9 +710,9 @@ void helper_itrigger_match(CPURISCVState *env)
     int count;
     bool enabled = false;
 
-    g_assert(env->itrigger_enabled);
+    g_assert(env->sdtrig_state.itrigger_enabled);
 
-    for (int i = 0; i < RV_MAX_TRIGGERS; i++) {
+    for (int i = 0; i < RV_MAX_SDTRIG_TRIGGERS; i++) {
         if (get_trigger_type(env, i) != TRIGGER_TYPE_INST_CNT) {
             continue;
         }
@@ -719,7 +732,7 @@ void helper_itrigger_match(CPURISCVState *env)
             enabled = true;
         }
     }
-    env->itrigger_enabled = enabled;
+    env->sdtrig_state.itrigger_enabled = enabled;
 }
 
 static target_ulong itrigger_validate(CPURISCVState *env,
@@ -745,16 +758,17 @@ static target_ulong itrigger_validate(CPURISCVState *env,
 static void itrigger_reg_write(CPURISCVState *env, target_ulong index,
                                int tdata_index, target_ulong val)
 {
+    SdtrigTrigger *trigger = &env->sdtrig_state.triggers[index];
     switch (tdata_index) {
     case TDATA1:
-        env->tdata1[index] = itrigger_validate(env, val);
+        trigger->tdata1 = itrigger_validate(env, val);
         break;
     case TDATA2:
         qemu_log_mask(LOG_UNIMP,
                       "tdata2 is not supported for icount trigger\n");
         break;
     case TDATA3:
-        env->tdata3[index] = textra_validate(env, val);
+        trigger->tdata3 = textra_validate(env, val);
         break;
     default:
         g_assert_not_reached();
@@ -764,19 +778,21 @@ static void itrigger_reg_write(CPURISCVState *env, 
target_ulong index,
 static void anytype_reg_write(CPURISCVState *env, target_ulong index,
                               int tdata_index, target_ulong val)
 {
+    SdtrigTrigger *trigger = &env->sdtrig_state.triggers[index];
+
     /*
      * This should check the value is valid for at least one of the supported
      * trigger types.
      */
     switch (tdata_index) {
     case TDATA1:
-        env->tdata1[env->trigger_cur] = val;
+        trigger->tdata1 = val;
         break;
     case TDATA2:
-        env->tdata2[env->trigger_cur] = val;
+        trigger->tdata2 = val;
         break;
     case TDATA3:
-        env->tdata3[env->trigger_cur] = val;
+        trigger->tdata3 = val;
         break;
     default:
         g_assert_not_reached();
@@ -785,13 +801,16 @@ static void anytype_reg_write(CPURISCVState *env, 
target_ulong index,
 
 target_ulong tdata_csr_read(CPURISCVState *env, int tdata_index)
 {
+    target_ulong index = env->sdtrig_state.trigger_cur;
+    SdtrigTrigger *trigger = &env->sdtrig_state.triggers[index];
+
     switch (tdata_index) {
     case TDATA1:
-        return env->tdata1[env->trigger_cur];
+        return trigger->tdata1;
     case TDATA2:
-        return env->tdata2[env->trigger_cur];
+        return trigger->tdata2;
     case TDATA3:
-        return env->tdata3[env->trigger_cur];
+        return trigger->tdata3;
     default:
         g_assert_not_reached();
     }
@@ -799,15 +818,16 @@ target_ulong tdata_csr_read(CPURISCVState *env, int 
tdata_index)
 
 void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val)
 {
-    int trigger_type = get_trigger_type(env, env->trigger_cur);
+    target_ulong index = env->sdtrig_state.trigger_cur;
+    int trigger_type = get_trigger_type(env, index);
     bool check_itrigger = false;
 
     switch (trigger_type) {
     case TRIGGER_TYPE_AD_MATCH:
-        type2_breakpoint_remove(env, env->trigger_cur);
+        type2_breakpoint_remove(env, index);
         break;
     case TRIGGER_TYPE_AD_MATCH6:
-        type6_breakpoint_remove(env, env->trigger_cur);
+        type6_breakpoint_remove(env, index);
         break;
     case TRIGGER_TYPE_INST_CNT:
         /*
@@ -831,17 +851,17 @@ void tdata_csr_write(CPURISCVState *env, int tdata_index, 
target_ulong val)
 
     switch (trigger_type) {
     case TRIGGER_TYPE_AD_MATCH:
-        type2_reg_write(env, env->trigger_cur, tdata_index, val);
+        type2_reg_write(env, index, tdata_index, val);
         break;
     case TRIGGER_TYPE_AD_MATCH6:
-        type6_reg_write(env, env->trigger_cur, tdata_index, val);
+        type6_reg_write(env, index, tdata_index, val);
         break;
     case TRIGGER_TYPE_INST_CNT:
-        itrigger_reg_write(env, env->trigger_cur, tdata_index, val);
+        itrigger_reg_write(env, index, tdata_index, val);
         check_itrigger = true;
         break;
     case TRIGGER_TYPE_UNAVAIL:
-        anytype_reg_write(env, env->trigger_cur, tdata_index, val);
+        anytype_reg_write(env, index, tdata_index, val);
         break;
     case TRIGGER_TYPE_INT:
     case TRIGGER_TYPE_EXCP:
@@ -858,7 +878,7 @@ void tdata_csr_write(CPURISCVState *env, int tdata_index, 
target_ulong val)
     }
 
     if (check_itrigger) {
-        env->itrigger_enabled = riscv_itrigger_enabled(env);
+        env->sdtrig_state.itrigger_enabled = riscv_itrigger_enabled(env);
     }
 }
 
@@ -898,7 +918,8 @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
     int i;
 
     QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
-        for (i = 0; i < RV_MAX_TRIGGERS; i++) {
+        for (i = 0; i < RV_MAX_SDTRIG_TRIGGERS; i++) {
+            SdtrigTrigger *trigger = &env->sdtrig_state.triggers[i];
             trigger_type = get_trigger_type(env, i);
 
             switch (trigger_type) {
@@ -915,8 +936,8 @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
 
             switch (trigger_type) {
             case TRIGGER_TYPE_AD_MATCH:
-                ctrl = env->tdata1[i];
-                pc = env->tdata2[i];
+                ctrl = trigger->tdata1;
+                pc = trigger->tdata2;
 
                 if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) {
                     if (do_trigger_action(env, i)) {
@@ -926,8 +947,8 @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
                 }
                 break;
             case TRIGGER_TYPE_AD_MATCH6:
-                ctrl = env->tdata1[i];
-                pc = env->tdata2[i];
+                ctrl = trigger->tdata1;
+                pc = trigger->tdata2;
 
                 if ((ctrl & TYPE6_EXEC) && (bp->pc == pc)) {
                     if (do_trigger_action(env, i)) {
@@ -955,7 +976,8 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, 
CPUWatchpoint *wp)
     int flags;
     int i;
 
-    for (i = 0; i < RV_MAX_TRIGGERS; i++) {
+    for (i = 0; i < RV_MAX_SDTRIG_TRIGGERS; i++) {
+        SdtrigTrigger *trigger = &env->sdtrig_state.triggers[i];
         trigger_type = get_trigger_type(env, i);
 
         switch (trigger_type) {
@@ -972,8 +994,8 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, 
CPUWatchpoint *wp)
 
         switch (trigger_type) {
         case TRIGGER_TYPE_AD_MATCH:
-            ctrl = env->tdata1[i];
-            addr = env->tdata2[i];
+            ctrl = trigger->tdata1;
+            addr = trigger->tdata2;
             flags = 0;
 
             if (ctrl & TYPE2_LOAD) {
@@ -991,8 +1013,8 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, 
CPUWatchpoint *wp)
             }
             break;
         case TRIGGER_TYPE_AD_MATCH6:
-            ctrl = env->tdata1[i];
-            addr = env->tdata2[i];
+            ctrl = trigger->tdata1;
+            addr = trigger->tdata2;
             flags = 0;
 
             if (ctrl & TYPE6_LOAD) {
@@ -1019,12 +1041,12 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, 
CPUWatchpoint *wp)
 
 void riscv_cpu_debug_change_priv(CPURISCVState *env)
 {
-    env->itrigger_enabled = riscv_itrigger_enabled(env);
+    env->sdtrig_state.itrigger_enabled = riscv_itrigger_enabled(env);
 }
 
 void riscv_cpu_debug_post_load(CPURISCVState *env)
 {
-    for (int i = 0; i < RV_MAX_TRIGGERS; i++) {
+    for (int i = 0; i < RV_MAX_SDTRIG_TRIGGERS; i++) {
         int trigger_type = get_trigger_type(env, i);
 
         switch (trigger_type) {
@@ -1038,7 +1060,7 @@ void riscv_cpu_debug_post_load(CPURISCVState *env)
             break;
         }
     }
-    env->itrigger_enabled = riscv_itrigger_enabled(env);
+    env->sdtrig_state.itrigger_enabled = riscv_itrigger_enabled(env);
 }
 
 void riscv_trigger_reset_hold(CPURISCVState *env)
@@ -1047,7 +1069,8 @@ void riscv_trigger_reset_hold(CPURISCVState *env)
     int i;
 
     /* init to type 15 (unavailable) triggers */
-    for (i = 0; i < RV_MAX_TRIGGERS; i++) {
+    for (i = 0; i < RV_MAX_SDTRIG_TRIGGERS; i++) {
+        SdtrigTrigger *trigger = &env->sdtrig_state.triggers[i];
         int trigger_type = get_trigger_type(env, i);
 
         switch (trigger_type) {
@@ -1061,10 +1084,10 @@ void riscv_trigger_reset_hold(CPURISCVState *env)
             break;
         }
 
-        env->tdata1[i] = tdata1;
-        env->tdata2[i] = 0;
-        env->tdata3[i] = 0;
+        trigger->tdata1 = tdata1;
+        trigger->tdata2 = 0;
+        trigger->tdata3 = 0;
     }
 
-    env->mcontext = 0;
+    env->sdtrig_state.mcontext = 0;
 }
diff --git a/target/riscv/debug.h b/target/riscv/debug.h
index bee42b8593..8a047c8073 100644
--- a/target/riscv/debug.h
+++ b/target/riscv/debug.h
@@ -24,7 +24,8 @@
 
 #include "exec/breakpoint.h"
 
-#define RV_MAX_TRIGGERS         2
+#define RV_MAX_SDTRIG_TRIGGERS        32
+#define RV_DEFAULT_TRIGGERS            2
 
 /* register index of tdata CSRs */
 enum {
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index bee1445a31..fdd5e8b67b 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -225,10 +225,32 @@ static bool debug_needed(void *opaque)
     return cpu->cfg.debug;
 }
 
+static int debug_pre_save(void *opaque)
+{
+    RISCVCPU *cpu = opaque;
+    CPURISCVState *env = &cpu->env;
+    int i;
+
+    for (i = 0; i < RV_DEFAULT_TRIGGERS; i++) {
+        env->old_tdata1[i] = env->sdtrig_state.triggers[i].tdata1;
+        env->old_tdata2[i] = env->sdtrig_state.triggers[i].tdata2;
+        env->old_tdata3[i] = env->sdtrig_state.triggers[i].tdata3;
+    }
+
+    return 0;
+}
+
 static int debug_post_load(void *opaque, int version_id)
 {
     RISCVCPU *cpu = opaque;
     CPURISCVState *env = &cpu->env;
+    int i;
+
+    for (i = 0; i < RV_DEFAULT_TRIGGERS; i++) {
+        env->sdtrig_state.triggers[i].tdata1 = env->old_tdata1[i];
+        env->sdtrig_state.triggers[i].tdata2 = env->old_tdata2[i];
+        env->sdtrig_state.triggers[i].tdata3 = env->old_tdata3[i];
+    }
 
     riscv_cpu_debug_post_load(env);
 
@@ -240,12 +262,13 @@ static const VMStateDescription vmstate_debug = {
     .version_id = 2,
     .minimum_version_id = 2,
     .needed = debug_needed,
+    .pre_save = debug_pre_save,
     .post_load = debug_post_load,
     .fields = (const VMStateField[]) {
-        VMSTATE_UINTTL(env.trigger_cur, RISCVCPU),
-        VMSTATE_UINTTL_ARRAY(env.tdata1, RISCVCPU, RV_MAX_TRIGGERS),
-        VMSTATE_UINTTL_ARRAY(env.tdata2, RISCVCPU, RV_MAX_TRIGGERS),
-        VMSTATE_UINTTL_ARRAY(env.tdata3, RISCVCPU, RV_MAX_TRIGGERS),
+        VMSTATE_UINTTL(env.sdtrig_state.trigger_cur, RISCVCPU),
+        VMSTATE_UINTTL_ARRAY(env.old_tdata1, RISCVCPU, RV_DEFAULT_TRIGGERS),
+        VMSTATE_UINTTL_ARRAY(env.old_tdata2, RISCVCPU, RV_DEFAULT_TRIGGERS),
+        VMSTATE_UINTTL_ARRAY(env.old_tdata3, RISCVCPU, RV_DEFAULT_TRIGGERS),
         VMSTATE_END_OF_LIST()
     }
 };
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 677172ae2d..bcc8cfcece 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -178,7 +178,8 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
     }
 
     if (cpu->cfg.debug) {
-        flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
+        flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER,
+                           env->sdtrig_state.itrigger_enabled);
     }
 #endif
 
-- 
2.51.0


Reply via email to