From: Nicholas Piggin <npiggin@gmail.com>
To: opensbi@lists.infradead.org
Cc: Nicholas Piggin <npiggin@gmail.com>,
Himanshu Chauhan <hchauhan@ventanamicro.com>
Subject: [PATCH 14/18] dbtr: Decouple dbtr trigger index from hardware trigger number
Date: Fri, 13 Mar 2026 15:19:43 +1000 [thread overview]
Message-ID: <20260313051948.4017134-15-npiggin@gmail.com> (raw)
In-Reply-To: <20260313051948.4017134-1-npiggin@gmail.com>
Some Sdtrig implementations have heterogeneous triggers, which require
the dbtr trigger index be decoupled from the hardware trigger allocated
to it.
The SBI interface supports this, prepare the implementation by creating
a new sbi_hw_trigger data structure that is mapped by the
sbi_dbtr_trigger with its HW_INDEX field.
The dbtr and hw triggers are still fixed to the same number.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
include/sbi/sbi_dbtr.h | 14 ++++++-
lib/sbi/sbi_dbtr.c | 87 ++++++++++++++++++++++++++++++------------
2 files changed, 76 insertions(+), 25 deletions(-)
diff --git a/include/sbi/sbi_dbtr.h b/include/sbi/sbi_dbtr.h
index b8b5c9ab..c0b9369e 100644
--- a/include/sbi/sbi_dbtr.h
+++ b/include/sbi/sbi_dbtr.h
@@ -48,9 +48,14 @@ struct sbi_dbtr_shmem {
unsigned long phys_hi;
};
+struct sbi_hw_trigger {
+ unsigned long index;
+ bool inuse; /* Allocated for a DBTR trigger */
+ unsigned long type_mask; /* Types supported by this trigger */
+};
+
struct sbi_dbtr_trigger {
unsigned long index;
- unsigned long type_mask;
unsigned long state;
unsigned long tdata1;
unsigned long tdata2;
@@ -69,6 +74,7 @@ struct sbi_dbtr_id_msg {
};
struct sbi_dbtr_hart_triggers_state {
+ struct sbi_hw_trigger hw_triggers[RV_MAX_TRIGGERS];
struct sbi_dbtr_trigger triggers[RV_MAX_TRIGGERS];
struct sbi_dbtr_shmem shmem;
u32 total_trigs;
@@ -89,6 +95,12 @@ struct sbi_dbtr_hart_triggers_state {
& RV_DBTR_BIT_MASK(TS, HW_IDX)); \
}while (0);
+#define GET_TRIG_HW_INDEX(_state) \
+ ({ \
+ (_state & RV_DBTR_BIT_MASK(TS, HW_IDX)) \
+ >> RV_DBTR_BIT(TS, HW_IDX); \
+ })
+
/** SBI shared mem messages layout */
union sbi_dbtr_shmem_entry {
struct sbi_dbtr_data_msg data;
diff --git a/lib/sbi/sbi_dbtr.c b/lib/sbi/sbi_dbtr.c
index 3aea486e..74b114b8 100644
--- a/lib/sbi/sbi_dbtr.c
+++ b/lib/sbi/sbi_dbtr.c
@@ -11,6 +11,7 @@
#include <sbi/sbi_csr_detect.h>
#include <sbi/sbi_platform.h>
#include <sbi/sbi_byteorder.h>
+#include <sbi/sbi_string.h>
#include <sbi/sbi_console.h>
#include <sbi/sbi_domain.h>
#include <sbi/sbi_trap.h>
@@ -43,6 +44,15 @@ static unsigned long hart_state_ptr_offset;
(__trg); \
})
+#define INDEX_TO_HW_TRIGGER(_index) \
+ ({ \
+ struct sbi_hw_trigger *__trg = NULL; \
+ struct sbi_dbtr_hart_triggers_state *__hs = NULL; \
+ __hs = dbtr_get_hart_state_ptr(sbi_scratch_thishart_ptr()); \
+ __trg = &__hs->hw_triggers[_index]; \
+ (__trg); \
+ })
+
#define for_each_trig_entry(_base, _max, _etype, _entry) \
for (int _idx = 0; _entry = ((_etype *)_base + _idx), \
_idx < _max; \
@@ -75,17 +85,6 @@ static inline void *hart_shmem_base(
hs->shmem.phys_hi, hs->shmem.phys_lo));
}
-static void sbi_trigger_init(struct sbi_dbtr_trigger *trig,
- unsigned long type_mask, unsigned long idx)
-{
- trig->type_mask = type_mask;
- trig->state = 0;
- trig->tdata1 = 0;
- trig->tdata2 = 0;
- trig->tdata3 = 0;
- trig->index = idx;
-}
-
static inline struct sbi_dbtr_trigger *sbi_alloc_trigger(void)
{
int i;
@@ -126,6 +125,16 @@ static inline void sbi_free_trigger(struct sbi_dbtr_trigger *trig)
if (!hart_state)
return;
+ if (trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)) {
+ unsigned long hw_index = GET_TRIG_HW_INDEX(trig->state);
+ struct sbi_hw_trigger *hw_trig = INDEX_TO_HW_TRIGGER(hw_index);
+ if (!hw_trig->inuse)
+ sbi_printf("DBTR error: Hardware trigger was not marked inuse\n");
+ if (hw_index != hw_trig->index)
+ sbi_printf("DBTR error: HW index mismatch\n");
+ hw_trig->inuse = false;
+ }
+
trig->state = 0;
trig->tdata1 = 0;
trig->tdata2 = 0;
@@ -136,10 +145,15 @@ static inline void sbi_free_trigger(struct sbi_dbtr_trigger *trig)
static bool sbi_hw_trigger_probe(int i)
{
+ struct sbi_hw_trigger *hw_trig = INDEX_TO_HW_TRIGGER(i);
struct sbi_trap_info trap = {0};
unsigned long tdata1;
unsigned long val;
+ sbi_memset(hw_trig, 0, sizeof(*hw_trig));
+
+ hw_trig->index = i;
+
csr_write_allowed(CSR_TSELECT, &trap, i);
if (trap.cause)
return false;
@@ -172,12 +186,12 @@ static bool sbi_hw_trigger_probe(int i)
if (type == 0)
return false;
- sbi_trigger_init(INDEX_TO_TRIGGER(i), BIT(type), i);
+ hw_trig->type_mask = BIT(type);
} else {
if (val == 1)
return false;
- sbi_trigger_init(INDEX_TO_TRIGGER(i), val, i);
+ hw_trig->type_mask = val;
}
return true;
@@ -213,6 +227,17 @@ int sbi_dbtr_init(struct sbi_scratch *scratch, bool coldboot)
if (hart_state->probed)
goto _probed;
+ /*
+ * dbtr triggers are what is exposed to the supervisor. hw triggers
+ * are what is selected by tselect. For now these are tied to the
+ * same index.
+ */
+ for (i = 0; i < RV_MAX_TRIGGERS; i++) {
+ struct sbi_dbtr_trigger *trig = INDEX_TO_TRIGGER(i);
+ sbi_memset(trig, 0, sizeof(*trig));
+ trig->index = i;
+ }
+
for (i = 0; i < RV_MAX_TRIGGERS; i++) {
if (sbi_hw_trigger_probe(i))
hart_state->total_trigs++;
@@ -304,6 +329,7 @@ int sbi_dbtr_setup_shmem(const struct sbi_domain *dom, unsigned long smode,
}
static void dbtr_trigger_setup(struct sbi_dbtr_trigger *trig,
+ struct sbi_hw_trigger *hw_trig,
struct sbi_dbtr_data_msg *recv)
{
unsigned long tdata1;
@@ -321,7 +347,9 @@ static void dbtr_trigger_setup(struct sbi_dbtr_trigger *trig,
__set_bit(RV_DBTR_BIT(TS, MAPPED), &trig->state);
- SET_TRIG_HW_INDEX(trig->state, trig->index);
+ SET_TRIG_HW_INDEX(trig->state, hw_trig->index);
+
+ hw_trig->inuse = true;
switch (TDATA1_GET_TYPE(tdata1)) {
case RISCV_DBTR_TRIG_MCONTROL:
@@ -423,7 +451,7 @@ static void dbtr_trigger_enable(struct sbi_dbtr_trigger *trig)
* where tdata2 and tdata3 can be written with any value that makes
* sense for any trigger type supported by this trigger.
*/
- csr_write(CSR_TSELECT, trig->index);
+ csr_write(CSR_TSELECT, GET_TRIG_HW_INDEX(state));
csr_write(CSR_TDATA1, 0x0);
csr_write(CSR_TDATA2, trig->tdata2);
csr_write(CSR_TDATA1, trig->tdata1);
@@ -459,7 +487,7 @@ static void dbtr_trigger_disable(struct sbi_dbtr_trigger *trig)
break;
}
- csr_write(CSR_TSELECT, trig->index);
+ csr_write(CSR_TSELECT, GET_TRIG_HW_INDEX(trig->state));
csr_write(CSR_TDATA1, trig->tdata1);
}
@@ -468,7 +496,7 @@ static void dbtr_trigger_clear(struct sbi_dbtr_trigger *trig)
if (!trig || !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
return;
- csr_write(CSR_TSELECT, trig->index);
+ csr_write(CSR_TSELECT, GET_TRIG_HW_INDEX(trig->state));
csr_write(CSR_TDATA1, 0x0);
csr_write(CSR_TDATA2, 0x0);
}
@@ -527,7 +555,7 @@ int sbi_dbtr_num_trig(unsigned long data, unsigned long *out)
unsigned long type = TDATA1_GET_TYPE(data);
u32 hartid = current_hartid();
unsigned long total = 0;
- struct sbi_dbtr_trigger *trig;
+ struct sbi_hw_trigger *hw_trig;
int i;
struct sbi_dbtr_hart_triggers_state *hs;
@@ -541,9 +569,9 @@ int sbi_dbtr_num_trig(unsigned long data, unsigned long *out)
}
for (i = 0; i < hs->total_trigs; i++) {
- trig = INDEX_TO_TRIGGER(i);
+ hw_trig = INDEX_TO_HW_TRIGGER(i);
- if (__test_bit(type, &trig->type_mask))
+ if (__test_bit(type, &hw_trig->type_mask))
total++;
}
@@ -589,7 +617,7 @@ int sbi_dbtr_read_trig(unsigned long smode,
xmit->tstate = cpu_to_lle(trig->state);
if (trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)) {
- csr_write(CSR_TSELECT, trig->index);
+ csr_write(CSR_TSELECT, GET_TRIG_HW_INDEX(trig->state));
trig->tdata1 = csr_read(CSR_TDATA1);
trig->tdata2 = csr_read_allowed(CSR_TDATA2, &trap);
trig->tdata3 = csr_read_allowed(CSR_TDATA3, &trap);
@@ -666,6 +694,7 @@ int sbi_dbtr_install_trig(unsigned long smode,
/* Install triggers */
for_each_trig_entry(shmem_base, trig_count, typeof(*entry), entry) {
+ struct sbi_hw_trigger *hw_trig;
/*
* Since we have already checked if enough triggers are
* available, trigger allocation must succeed.
@@ -675,10 +704,18 @@ int sbi_dbtr_install_trig(unsigned long smode,
recv = (struct sbi_dbtr_data_msg *)(&entry->data);
xmit = (struct sbi_dbtr_id_msg *)(&entry->id);
- dbtr_trigger_setup(trig, recv);
+ hw_trig = INDEX_TO_HW_TRIGGER(trig->index); /* 1:1 trig / HW idx */
+ if (hw_trig->inuse) {
+ *out = hs->available_trigs;
+ sbi_hart_protection_unmap_range((unsigned long)shmem_base,
+ trig_count * sizeof(*entry));
+ sbi_printf("DBTR error: Hardware trigger already inuse\n");
+ return SBI_ERR_FAILED;
+ }
+
+ dbtr_trigger_setup(trig, hw_trig, recv);
dbtr_trigger_enable(trig);
xmit->idx = cpu_to_lle(trig->index);
-
}
sbi_hart_protection_unmap_range((unsigned long)shmem_base,
@@ -771,6 +808,7 @@ int sbi_dbtr_update_trig(unsigned long smode,
unsigned long trig_count, unsigned long *out)
{
struct sbi_dbtr_trigger *trig;
+ struct sbi_hw_trigger *hw_trig;
union sbi_dbtr_shmem_entry *entry;
struct sbi_dbtr_data_msg *recv;
void *shmem_base = NULL;
@@ -835,7 +873,8 @@ int sbi_dbtr_update_trig(unsigned long smode,
/* Update triggers */
for_each_trig_entry(shmem_base, trig_count, typeof(*entry), entry) {
trig = INDEX_TO_TRIGGER(entry->id.idx);
- dbtr_trigger_setup(trig, &entry->data);
+ hw_trig = INDEX_TO_HW_TRIGGER(GET_TRIG_HW_INDEX(trig->state));
+ dbtr_trigger_setup(trig, hw_trig, &entry->data);
dbtr_trigger_enable(trig);
}
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
next prev parent reply other threads:[~2026-03-13 5:21 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-13 5:19 [PATCH 00/18] dbtr: Fixes and heterogeneous trigger types Nicholas Piggin
2026-03-13 5:19 ` [PATCH 01/18] dbtr: Add consistent range checks to trigger ecalls Nicholas Piggin
2026-03-20 12:46 ` Ilya Mamay
2026-04-07 5:22 ` Himanshu Chauhan
2026-03-13 5:19 ` [PATCH 02/18] dbtr: Trigger update should set sbiret.value on failure Nicholas Piggin
2026-03-13 5:19 ` [PATCH 03/18] dbtr: Fix endian conversion in trigger install handler Nicholas Piggin
2026-03-13 5:19 ` [PATCH 04/18] dbtr: Return correct error on install not supported Nicholas Piggin
2026-03-13 5:19 ` [PATCH 05/18] dbtr: Do not support chain bit Nicholas Piggin
2026-03-13 5:19 ` [PATCH 06/18] dbtr: Improve trigger update error checking Nicholas Piggin
2026-03-13 5:19 ` [PATCH 07/18] dbtr: Check for invalid and unsupported triggers in update Nicholas Piggin
2026-03-13 5:19 ` [PATCH 08/18] dbtr: Improve error handling for trigger enable, disable, uninstall Nicholas Piggin
2026-03-13 5:19 ` [PATCH 09/18] dbtr: Read triggers should not read HW trigger if not mapped Nicholas Piggin
2026-03-13 5:19 ` [PATCH 10/18] dbtr: Avoid crash in sbi_debug_read_triggers Nicholas Piggin
2026-03-13 5:19 ` [PATCH 11/18] dbtr: Succeed operations with no triggers in mask Nicholas Piggin
2026-03-13 5:19 ` [PATCH 12/18] dbtr: Move hardware trigger probing to a function Nicholas Piggin
2026-03-13 5:19 ` [PATCH 13/18] dbtr: Rework install and update error handling Nicholas Piggin
2026-03-13 5:19 ` Nicholas Piggin [this message]
2026-03-13 5:19 ` [PATCH 15/18] dbtr: Move trigger feature support test into a function Nicholas Piggin
2026-03-13 5:19 ` [PATCH 16/18] dbtr: Heterogeneous trigger type support Nicholas Piggin
2026-03-13 5:19 ` [PATCH 17/18] dbtr: Heterogeneous access type matching for mcontrol triggers Nicholas Piggin
2026-03-13 5:19 ` [PATCH 18/18] dbtr: Work around specification bug in range checks Nicholas Piggin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260313051948.4017134-15-npiggin@gmail.com \
--to=npiggin@gmail.com \
--cc=hchauhan@ventanamicro.com \
--cc=opensbi@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox