aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2022-04-27 12:58:09 -0700
committerTim Newsome <tim@sifive.com>2022-04-27 12:58:09 -0700
commita6f32126846a4094c60c60b31393b9e1ab0b22fe (patch)
tree54f517dcfbaf853df5c93c5b00c52ae792dd719b
parentdc320d26f03d2a9932947c3eb2f065bd35c80f44 (diff)
downloadriscv-openocd-a6f32126846a4094c60c60b31393b9e1ab0b22fe.zip
riscv-openocd-a6f32126846a4094c60c60b31393b9e1ab0b22fe.tar.gz
riscv-openocd-a6f32126846a4094c60c60b31393b9e1ab0b22fe.tar.bz2
Create riscv_hit_trigger_hit_bit() function.
This goes through the triggers OpenOCD set to find out if one of them has the hit bit set. Change-Id: I5b9f1c19273c7d40392a0cc278277ca6c94d2eae
-rw-r--r--src/target/riscv/riscv.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 174568f..51ec64c 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -1017,6 +1017,67 @@ int riscv_remove_watchpoint(struct target *target,
return ERROR_OK;
}
+/**
+ * Look at the trigger hit bits to find out which trigger is the reason we're
+ * halted. Sets *unique_id to the unique ID of that trigger. If *unique_id is
+ * ~0, no match was found.
+ */
+static int riscv_hit_trigger_hit_bit(struct target *target, uint32_t *unique_id)
+{
+ RISCV_INFO(r);
+
+ riscv_reg_t tselect;
+ if (riscv_get_register(target, &tselect, GDB_REGNO_TSELECT) != ERROR_OK)
+ return ERROR_FAIL;
+
+ *unique_id = ~0;
+ for (unsigned int i = 0; i < r->trigger_count; i++) {
+ if (r->trigger_unique_id[i] == -1)
+ continue;
+
+ if (riscv_set_register(target, GDB_REGNO_TSELECT, i) != ERROR_OK)
+ return ERROR_FAIL;
+
+ uint64_t tdata1;
+ if (riscv_get_register(target, &tdata1, GDB_REGNO_TDATA1) != ERROR_OK)
+ return ERROR_FAIL;
+ int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target)));
+
+ uint64_t hit_mask = 0;
+ switch (type) {
+ case 1:
+ /* Doesn't support hit bit. */
+ break;
+ case 2:
+ hit_mask = CSR_MCONTROL_HIT;
+ break;
+ case 6:
+ hit_mask = CSR_MCONTROL6_HIT;
+ break;
+ default:
+ LOG_DEBUG("trigger %d has unknown type %d", i, type);
+ continue;
+ }
+
+ /* Note: If we ever use chained triggers, then this logic needs
+ * to be changed to ignore triggers that are not the last one in
+ * the chain. */
+ if (tdata1 & hit_mask) {
+ LOG_DEBUG("Trigger %d (unique_id=%d) has hit bit set.", i, r->trigger_unique_id[i]);
+ if (riscv_set_register(target, GDB_REGNO_TDATA1, tdata1 & ~hit_mask) != ERROR_OK)
+ return ERROR_FAIL;
+
+ *unique_id = r->trigger_unique_id[i];
+ break;
+ }
+ }
+
+ if (riscv_set_register(target, GDB_REGNO_TSELECT, tselect) != ERROR_OK)
+ return ERROR_FAIL;
+
+ return ERROR_OK;
+}
+
/* Sets *hit_watchpoint to the first watchpoint identified as causing the
* current halt.
*