[PATCH] dbtr: Add support for icount trigger type
Jesse Taube
jesse at rivosinc.com
Thu Jul 24 11:31:20 PDT 2025
The linux kernel needs icount to implement hardware breakpoints.
Signed-off-by: Jesse Taube <jesse at rivosinc.com>
---
include/sbi/riscv_dbtr.h | 44 ++++++++++++++++++++++++++++++++++++++++
lib/sbi/sbi_dbtr.c | 35 ++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
diff --git a/include/sbi/riscv_dbtr.h b/include/sbi/riscv_dbtr.h
index 96c7d3e3..e249eaed 100644
--- a/include/sbi/riscv_dbtr.h
+++ b/include/sbi/riscv_dbtr.h
@@ -122,6 +122,50 @@ enum {
RV_DBTR_DECLARE_BIT_MASK(MC, TYPE, 4),
};
+
+/* ICOUNT - Match Control Type Register */
+enum {
+ RV_DBTR_DECLARE_BIT(ICOUNT, ACTION, 0),
+ RV_DBTR_DECLARE_BIT(ICOUNT, U, 6),
+ RV_DBTR_DECLARE_BIT(ICOUNT, S, 7),
+ RV_DBTR_DECLARE_BIT(ICOUNT, PENDING, 8),
+ RV_DBTR_DECLARE_BIT(ICOUNT, M, 9),
+ RV_DBTR_DECLARE_BIT(ICOUNT, COUNT, 10),
+ RV_DBTR_DECLARE_BIT(ICOUNT, HIT, 24),
+ RV_DBTR_DECLARE_BIT(ICOUNT, VU, 25),
+ RV_DBTR_DECLARE_BIT(ICOUNT, VS, 26),
+#if __riscv_xlen == 64
+ RV_DBTR_DECLARE_BIT(ICOUNT, DMODE, 59),
+ RV_DBTR_DECLARE_BIT(ICOUNT, TYPE, 60),
+#elif __riscv_xlen == 32
+ RV_DBTR_DECLARE_BIT(ICOUNT, DMODE, 27),
+ RV_DBTR_DECLARE_BIT(ICOUNT, TYPE, 28),
+#else
+ #error "Unknown __riscv_xlen"
+#endif
+};
+
+enum {
+ RV_DBTR_DECLARE_BIT_MASK(ICOUNT, ACTION, 6),
+ RV_DBTR_DECLARE_BIT_MASK(ICOUNT, U, 1),
+ RV_DBTR_DECLARE_BIT_MASK(ICOUNT, S, 1),
+ RV_DBTR_DECLARE_BIT_MASK(ICOUNT, PENDING, 1),
+ RV_DBTR_DECLARE_BIT_MASK(ICOUNT, M, 1),
+ RV_DBTR_DECLARE_BIT_MASK(ICOUNT, COUNT, 14),
+ RV_DBTR_DECLARE_BIT_MASK(ICOUNT, HIT, 1),
+ RV_DBTR_DECLARE_BIT_MASK(ICOUNT, VU, 1),
+ RV_DBTR_DECLARE_BIT_MASK(ICOUNT, VS, 1),
+#if __riscv_xlen == 64
+ RV_DBTR_DECLARE_BIT_MASK(ICOUNT, DMODE, 1),
+ RV_DBTR_DECLARE_BIT_MASK(ICOUNT, TYPE, 4),
+#elif __riscv_xlen == 32
+ RV_DBTR_DECLARE_BIT_MASK(ICOUNT, DMODE, 1),
+ RV_DBTR_DECLARE_BIT_MASK(ICOUNT, TYPE, 4),
+#else
+ #error "Unknown __riscv_xlen"
+#endif
+};
+
/* MC6 - Match Control 6 Type Register */
enum {
RV_DBTR_DECLARE_BIT(MC6, LOAD, 0),
diff --git a/lib/sbi/sbi_dbtr.c b/lib/sbi/sbi_dbtr.c
index a832c7f1..c30c2fd6 100644
--- a/lib/sbi/sbi_dbtr.c
+++ b/lib/sbi/sbi_dbtr.c
@@ -336,6 +336,19 @@ static void dbtr_trigger_setup(struct sbi_dbtr_trigger *trig,
if (__test_bit(RV_DBTR_BIT(MC6, VS), &tdata1))
__set_bit(RV_DBTR_BIT(TS, VS), &trig->state);
break;
+ case RISCV_DBTR_TRIG_ICOUNT:
+ if (__test_bit(RV_DBTR_BIT(ICOUNT, U), &tdata1))
+ __set_bit(RV_DBTR_BIT(TS, U), &trig->state);
+
+ if (__test_bit(RV_DBTR_BIT(ICOUNT, S), &tdata1))
+ __set_bit(RV_DBTR_BIT(TS, S), &trig->state);
+
+ if (__test_bit(RV_DBTR_BIT(ICOUNT, VU), &tdata1))
+ __set_bit(RV_DBTR_BIT(TS, VU), &trig->state);
+
+ if (__test_bit(RV_DBTR_BIT(ICOUNT, VS), &tdata1))
+ __set_bit(RV_DBTR_BIT(TS, VS), &trig->state);
+ break;
default:
sbi_dprintf("%s: Unknown type (tdata1: 0x%lx Type: %ld)\n",
__func__, tdata1, TDATA1_GET_TYPE(tdata1));
@@ -379,6 +392,16 @@ static void dbtr_trigger_enable(struct sbi_dbtr_trigger *trig)
update_bit(state & RV_DBTR_BIT_MASK(TS, S),
RV_DBTR_BIT(MC6, S), &trig->tdata1);
break;
+ case RISCV_DBTR_TRIG_ICOUNT:
+ update_bit(state & RV_DBTR_BIT_MASK(TS, VU),
+ RV_DBTR_BIT(ICOUNT, VU), &trig->tdata1);
+ update_bit(state & RV_DBTR_BIT_MASK(TS, VS),
+ RV_DBTR_BIT(ICOUNT, VS), &trig->tdata1);
+ update_bit(state & RV_DBTR_BIT_MASK(TS, U),
+ RV_DBTR_BIT(ICOUNT, U), &trig->tdata1);
+ update_bit(state & RV_DBTR_BIT_MASK(TS, S),
+ RV_DBTR_BIT(ICOUNT, S), &trig->tdata1);
+ break;
default:
break;
}
@@ -418,6 +441,12 @@ static void dbtr_trigger_disable(struct sbi_dbtr_trigger *trig)
__clear_bit(RV_DBTR_BIT(MC6, U), &trig->tdata1);
__clear_bit(RV_DBTR_BIT(MC6, S), &trig->tdata1);
break;
+ case RISCV_DBTR_TRIG_ICOUNT:
+ __clear_bit(RV_DBTR_BIT(ICOUNT, VU), &trig->tdata1);
+ __clear_bit(RV_DBTR_BIT(ICOUNT, VS), &trig->tdata1);
+ __clear_bit(RV_DBTR_BIT(ICOUNT, U), &trig->tdata1);
+ __clear_bit(RV_DBTR_BIT(ICOUNT, S), &trig->tdata1);
+ break;
default:
break;
}
@@ -441,6 +470,7 @@ static int dbtr_trigger_supported(unsigned long type)
switch (type) {
case RISCV_DBTR_TRIG_MCONTROL:
case RISCV_DBTR_TRIG_MCONTROL6:
+ case RISCV_DBTR_TRIG_ICOUNT:
return 1;
default:
break;
@@ -462,6 +492,11 @@ static int dbtr_trigger_valid(unsigned long type, unsigned long tdata)
!(tdata & RV_DBTR_BIT_MASK(MC6, M)))
return 1;
break;
+ case RISCV_DBTR_TRIG_ICOUNT:
+ if (!(tdata & RV_DBTR_BIT_MASK(ICOUNT, DMODE)) &&
+ !(tdata & RV_DBTR_BIT_MASK(ICOUNT, M)))
+ return 1;
+ break;
default:
break;
}
--
2.43.0
More information about the opensbi
mailing list