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 <npiggin@gmail.com>
---
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
© 2016 - 2026 Red Hat, Inc.