diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 759ac088f..ad692630a 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -139,8 +139,6 @@ typedef struct { // unique_id of the breakpoint/watchpoint that is using it. int trigger_unique_id[MAX_HWBPS]; - unsigned int trigger_count; - // Number of run-test/idle cycles the target requests we do after each dbus // access. unsigned int dtmcontrol_idle; @@ -929,11 +927,12 @@ static void deinit_target(struct target *target) static int add_trigger(struct target *target, struct trigger *trigger) { riscv013_info_t *info = get_info(target); + RISCV_INFO(r); maybe_read_tselect(target); unsigned int i; - for (i = 0; i < info->trigger_count; i++) { + for (i = 0; i < riscv_count_triggers(target); i++) { if (info->trigger_unique_id[i] != -1) { continue; } @@ -994,7 +993,7 @@ static int add_trigger(struct target *target, struct trigger *trigger) info->trigger_unique_id[i] = trigger->unique_id; break; } - if (i >= info->trigger_count) { + if (i >= riscv_count_triggers(target)) { LOG_ERROR("Couldn't find an available hardware trigger."); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1009,12 +1008,12 @@ static int remove_trigger(struct target *target, struct trigger *trigger) maybe_read_tselect(target); unsigned int i; - for (i = 0; i < info->trigger_count; i++) { + for (i = 0; i < riscv_count_triggers(target); i++) { if (info->trigger_unique_id[i] == trigger->unique_id) { break; } } - if (i >= info->trigger_count) { + if (i >= riscv_count_triggers(target)) { LOG_ERROR("Couldn't find the hardware resources used by hardware " "trigger."); return ERROR_FAIL; @@ -1239,7 +1238,6 @@ static int examine(struct target *target) /* Examines every hart, first checking XLEN. */ for (int i = 0; i < riscv_count_harts(target); ++i) { - RISCV_INFO(r); riscv_set_current_hartid(target, i); if (abstract_read_register(target, NULL, S0, 128) == ERROR_OK) { @@ -1254,8 +1252,19 @@ static int examine(struct target *target) } } - /* FIXME: Are there 2 triggers? */ - info->trigger_count = 2; + /* Then we check the number of triggers availiable to each hart. */ + for (int i = 0; i < riscv_count_harts(target); ++i) { + for (int t = 0; t < RISCV_MAX_TRIGGERS; ++t) { + riscv_set_current_hartid(target, i); + + r->trigger_count[i] = t; + register_write_direct(target, GDB_REGNO_TSELECT, t); + uint64_t tselect = t+1; + register_read_direct(target, &tselect, GDB_REGNO_TSELECT); + if (tselect != t) + break; + } + } /* Resumes all the harts, so the debugger can later pause them. */ riscv_resume_all_harts(target); diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index d64115503..bb132d60d 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -1008,3 +1008,15 @@ enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid) assert(riscv_is_halted(target)); return r->halt_reason(target); } + +int riscv_count_triggers(struct target *target) +{ + return riscv_count_triggers_of_hart(target, riscv_current_hartid(target)); +} + +int riscv_count_triggers_of_hart(struct target *target, int hartid) +{ + RISCV_INFO(r); + assert(hartid < riscv_count_harts(target)); + return r->trigger_count[hartid]; +} diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 3b83a08ad..73fee415e 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -7,6 +7,7 @@ /* The register cache is staticly allocated. */ #define RISCV_MAX_HARTS 32 #define RISCV_MAX_REGISTERS 5000 +#define RISCV_MAX_TRIGGERS 32 extern struct target_type riscv011_target; extern struct target_type riscv013_target; @@ -64,6 +65,9 @@ typedef struct { /* The state of every hart. */ enum riscv_hart_state hart_state[RISCV_MAX_HARTS]; + /* The number of triggers per hart. */ + int trigger_count[RISCV_MAX_HARTS]; + /* Helper functions that target the various RISC-V debug spec * implementations. */ riscv_reg_t (*get_register)(struct target *, int, int); @@ -177,4 +181,9 @@ bool riscv_is_halted(struct target *target); bool riscv_was_halted(struct target *target); enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid); +/* Returns the number of triggers availiable to either the current hart or to + * the given hart. */ +int riscv_count_triggers(struct target *target); +int riscv_count_triggers_of_hart(struct target *target, int hartid); + #endif