In current implementation, the number of debug triggers was hardcoded as RV_MAX_TRIGGERS macro. This commit replaces the fixed value with a new "num_triggers" configuration, allowing platforms to configure the number of debug triggers they want.
If no specific option is provided, the default number of debug triggers remains 2 as before. A new CPU property "num-triggers" is added to let users configure the number of debug triggers from the command line. For example: -cpu max,num-triggers=8 Signed-off-by: Alvin Chang <[email protected]> Reviewed-by: Yu-Ming Chang <[email protected]> --- target/riscv/cpu.c | 34 +++++++++++++++++++++++++++++++ target/riscv/cpu.h | 12 +++++------ target/riscv/cpu_cfg_fields.h.inc | 1 + target/riscv/csr.c | 3 ++- target/riscv/debug.c | 23 +++++++++++++-------- target/riscv/debug.h | 2 -- target/riscv/machine.c | 16 ++++++++++----- 7 files changed, 69 insertions(+), 22 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 73d4280..5996d13 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1122,6 +1122,7 @@ static void riscv_cpu_init(Object *obj) cpu->cfg.cboz_blocksize = 64; cpu->cfg.pmp_regions = 16; cpu->cfg.pmp_granularity = MIN_RISCV_PMP_GRANULARITY; + cpu->cfg.num_triggers = 2; cpu->env.vext_ver = VEXT_VERSION_1_00_0; cpu->cfg.max_satp_mode = -1; @@ -1644,6 +1645,38 @@ static const PropertyInfo prop_pmp_granularity = { .set = prop_pmp_granularity_set, }; +static void prop_num_triggers_set(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + RISCVCPU *cpu = RISCV_CPU(obj); + uint32_t value; + + visit_type_uint32(v, name, &value, errp); + + if (cpu->cfg.num_triggers != value && riscv_cpu_is_vendor(obj)) { + cpu_set_prop_err(cpu, name, errp); + return; + } + + cpu_option_add_user_setting(name, value); + cpu->cfg.num_triggers = value; +} + +static void prop_num_triggers_get(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + uint32_t value = RISCV_CPU(obj)->cfg.pmp_regions; + + visit_type_uint32(v, name, &value, errp); +} + +static const PropertyInfo prop_num_triggers = { + .type = "uint32", + .description = "num-triggers", + .get = prop_num_triggers_get, + .set = prop_num_triggers_set, +}; + static int priv_spec_from_str(const char *priv_spec_str) { int priv_version = -1; @@ -2645,6 +2678,7 @@ static const Property riscv_cpu_properties[] = { {.name = "pmp", .info = &prop_pmp}, {.name = "num-pmp-regions", .info = &prop_num_pmp_regions}, {.name = "pmp-granularity", .info = &prop_pmp_granularity}, + {.name = "num-triggers", .info = &prop_num_triggers}, {.name = "priv_spec", .info = &prop_priv_spec}, {.name = "vext_spec", .info = &prop_vext_spec}, diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 36e7f10..b32ed78 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -450,13 +450,13 @@ struct CPUArchState { /* 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 *tdata1; + target_ulong *tdata2; + target_ulong *tdata3; target_ulong mcontext; - struct CPUBreakpoint *cpu_breakpoint[RV_MAX_TRIGGERS]; - struct CPUWatchpoint *cpu_watchpoint[RV_MAX_TRIGGERS]; - QEMUTimer *itrigger_timer[RV_MAX_TRIGGERS]; + struct CPUBreakpoint **cpu_breakpoint; + struct CPUWatchpoint **cpu_watchpoint; + QEMUTimer **itrigger_timer; int64_t last_icount; bool itrigger_enabled; diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc index a154ecd..840e8c4 100644 --- a/target/riscv/cpu_cfg_fields.h.inc +++ b/target/riscv/cpu_cfg_fields.h.inc @@ -167,6 +167,7 @@ TYPED_FIELD(uint16_t, cbop_blocksize, 0) TYPED_FIELD(uint16_t, cboz_blocksize, 0) TYPED_FIELD(uint8_t, pmp_regions, 0) TYPED_FIELD(uint32_t, pmp_granularity, 0) +TYPED_FIELD(uint32_t, num_triggers, 0) TYPED_FIELD(int8_t, max_satp_mode, -1) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 5c91658..fce5f94 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -5346,7 +5346,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->trigger_cur >= riscv_cpu_cfg(env)->num_triggers && + csrno == CSR_TDATA1) { *val = 0; return RISCV_EXCP_NONE; } diff --git a/target/riscv/debug.c b/target/riscv/debug.c index 5664466..460363f 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -171,7 +171,7 @@ target_ulong tselect_csr_read(CPURISCVState *env) void tselect_csr_write(CPURISCVState *env, target_ulong val) { - if (val < RV_MAX_TRIGGERS) { + if (val < riscv_cpu_cfg(env)->num_triggers) { env->trigger_cur = val; } } @@ -700,7 +700,7 @@ static bool check_itrigger_priv(CPURISCVState *env, int index) bool riscv_itrigger_enabled(CPURISCVState *env) { int count; - for (int i = 0; i < RV_MAX_TRIGGERS; i++) { + for (int i = 0; i < riscv_cpu_cfg(env)->num_triggers; i++) { if (get_trigger_type(env, i) != TRIGGER_TYPE_INST_CNT) { continue; } @@ -720,7 +720,7 @@ bool riscv_itrigger_enabled(CPURISCVState *env) void helper_itrigger_match(CPURISCVState *env) { int count; - for (int i = 0; i < RV_MAX_TRIGGERS; i++) { + for (int i = 0; i < riscv_cpu_cfg(env)->num_triggers; i++) { if (get_trigger_type(env, i) != TRIGGER_TYPE_INST_CNT) { continue; } @@ -749,7 +749,7 @@ static void riscv_itrigger_update_count(CPURISCVState *env) int64_t last_icount = env->last_icount, current_icount; current_icount = env->last_icount = icount_get_raw(); - for (int i = 0; i < RV_MAX_TRIGGERS; i++) { + for (int i = 0; i < riscv_cpu_cfg(env)->num_triggers; i++) { if (get_trigger_type(env, i) != TRIGGER_TYPE_INST_CNT) { continue; } @@ -949,7 +949,7 @@ 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 < riscv_cpu_cfg(env)->num_triggers; i++) { trigger_type = get_trigger_type(env, i); if (!trigger_common_match(env, trigger_type, i)) { @@ -995,7 +995,7 @@ 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 < riscv_cpu_cfg(env)->num_triggers; i++) { trigger_type = get_trigger_type(env, i); if (!trigger_common_match(env, trigger_type, i)) { @@ -1046,9 +1046,16 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) void riscv_trigger_realize(CPURISCVState *env) { + uint32_t num_triggers = riscv_cpu_cfg(env)->num_triggers; int i; - for (i = 0; i < RV_MAX_TRIGGERS; i++) { + env->tdata1 = g_new0(target_ulong, num_triggers); + env->tdata2 = g_new0(target_ulong, num_triggers); + env->tdata3 = g_new0(target_ulong, num_triggers); + env->cpu_breakpoint = g_new0(struct CPUBreakpoint *, num_triggers); + env->cpu_watchpoint = g_new0(struct CPUWatchpoint *, num_triggers); + env->itrigger_timer = g_new0(QEMUTimer *, num_triggers); + for (i = 0; i < num_triggers; i++) { env->itrigger_timer[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL, riscv_itrigger_timer_cb, env); } @@ -1060,7 +1067,7 @@ void riscv_trigger_reset_hold(CPURISCVState *env) int i; /* init to type 2 triggers */ - for (i = 0; i < RV_MAX_TRIGGERS; i++) { + for (i = 0; i < riscv_cpu_cfg(env)->num_triggers; i++) { /* * type = TRIGGER_TYPE_AD_MATCH * dmode = 0 (both debug and M-mode can write tdata) diff --git a/target/riscv/debug.h b/target/riscv/debug.h index f76b8f9..d3aae61 100644 --- a/target/riscv/debug.h +++ b/target/riscv/debug.h @@ -24,8 +24,6 @@ #include "exec/breakpoint.h" -#define RV_MAX_TRIGGERS 2 - /* register index of tdata CSRs */ enum { TDATA1 = 0, diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 18d790a..c7244b7 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -239,15 +239,21 @@ static int debug_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_debug = { .name = "cpu/debug", - .version_id = 2, - .minimum_version_id = 2, + .version_id = 3, + .minimum_version_id = 3, .needed = debug_needed, .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_VARRAY_UINT32(env.tdata1, RISCVCPU, + cfg.num_triggers, 0, + vmstate_info_uinttl, target_ulong), + VMSTATE_VARRAY_UINT32(env.tdata2, RISCVCPU, + cfg.num_triggers, 0, + vmstate_info_uinttl, target_ulong), + VMSTATE_VARRAY_UINT32(env.tdata3, RISCVCPU, + cfg.num_triggers, 0, + vmstate_info_uinttl, target_ulong), VMSTATE_END_OF_LIST() } }; -- 2.43.0
