Skip to contentSkip to conversation

Introduce support for SBI Debug Trigger Extension

PATCH Superseded Himanshu Chauhan 2 participants 17 messages Jan 8, 2024 – Jan 9, 2024 RISC-V

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

v2 cover Introduce support for SBI Debug Trigger Extension

RISC-V Debug specification includes Sdtrig ISA extension which describes Trigger Module. Triggers can cause a breakpoint exception or trace action without execution of a special instruction. They can be used to implement hardware breakpoints and watchpoints for native debugging.

The SBI Debug Trigger extension v6 can be found at:
https://lists.riscv.org/g/tech-debug/topic/99825362#1302

This patch is an initial implementation of SBI Debug Trigger Extension(v6) in OpenSBI. It is based on similar patchset from Sergey Matyukevich.
(http://lists.infradead.org/pipermail/opensbi/2022-October/003531.html)

The following features are supported:
* mcontrol, mcontrol6 triggers
* Breakpoint and trace actions

Linux Kernel Branch (Breakpoint driver support):
https://github.com/hschauhan/riscv-linux/tree/sdtrig-v6

NOTE: Chained triggers are not supported

Changes from v1:
- Rebased to latest OpenSBI master
- Other cosmetic changes as per the comments

Himanshu Chauhan (7):
include: sbi: Introduce common endianess conversion macro
include: sbi: Add TINFO debug trigger CSR
include: sbi: Introduce debug trigger register encodings
lib: sbi: Introduce the SBI debug triggers extension support
include: sbi: Add SBI debug trigger extension related defines
lib: sbi: Implement SBI debug trigger extension
lib: sbi: Print number of debug triggers found

 include/sbi/riscv_dbtr.h          | 249 ++++++++++
 include/sbi/riscv_encoding.h      |   1 +
 include/sbi/sbi_byteorder.h       |  10 +
 include/sbi/sbi_dbtr.h            | 127 +++++
 include/sbi/sbi_ecall_interface.h |  11 +
 lib/sbi/Kconfig                   |   4 +
 lib/sbi/objects.mk                |   4 +
 lib/sbi/sbi_dbtr.c                | 742 ++++++++++++++++++++++++++++++
 lib/sbi/sbi_ecall_dbtr.c          |  73 +++
 lib/sbi/sbi_init.c                |  11 +
 10 files changed, 1232 insertions(+)
 create mode 100644 include/sbi/riscv_dbtr.h
 create mode 100644 include/sbi/sbi_dbtr.h
 create mode 100644 lib/sbi/sbi_dbtr.c
 create mode 100644 lib/sbi/sbi_ecall_dbtr.c
Signature · 1 line
2.34.1
#1 lore raw

PATCH v2 1/7 include: sbi: Introduce common endianess conversion macro

Introduce cpu_to_lle and lle_to_cpu macros which invoke correct word length cpu_to_le<64/32> conversion based on __riscv_xlen.

---
 include/sbi/sbi_byteorder.h | 10 ++++++++++
 1 file changed, 10 insertions(+)
include/sbi/sbi_byteorder.h +10 -0
index 15107e1..db6eb2b 100644
@@ -58,4 +58,14 @@
 #define le64_to_cpu(x)		((uint64_t)BSWAP64(x))
 #endif
 
+#if __riscv_xlen == 64
+#define cpu_to_lle		cpu_to_le64
+#define lle_to_cpu		le64_to_cpu
+#elif __riscv_xlen == 32
+#define cpu_to_lle		cpu_to_le32
+#define lle_to_cpu		le32_to_cpu
+#else
+#error "Unknown __riscv_xlen"
+#endif
+
 #endif /* __SBI_BYTEORDER_H__ */
Signature · 1 line
2.34.1
#2 lore raw

PATCH v2 1/7 include: sbi: Introduce common endianess conversion macro

Quoted 6 lines · On Mon, Jan 8, 2024 at 12:25?PM Himanshu Chauhan <[email protected]>…

Introduce cpu_to_lle and lle_to_cpu macros which invoke correct word length cpu_to_le<64/32> conversion based on __riscv_xlen.

Already reviewed previously.

Regards,
Anup

Quoted 31 lines
---
 include/sbi/sbi_byteorder.h | 10 ++++++++++
 1 file changed, 10 insertions(+)
include/sbi/sbi_byteorder.h +10 -1
index 15107e1..db6eb2b 100644
@@ -58,4 +58,14 @@
 #define le64_to_cpu(x)         ((uint64_t)BSWAP64(x))
 #endif
 
+#if __riscv_xlen == 64
+#define cpu_to_lle             cpu_to_le64
+#define lle_to_cpu             le64_to_cpu
+#elif __riscv_xlen == 32
+#define cpu_to_lle             cpu_to_le32
+#define lle_to_cpu             le32_to_cpu
+#else
+#error "Unknown __riscv_xlen"
+#endif
+
 #endif /* __SBI_BYTEORDER_H__ */
--

2.34.1

--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

#3 lore raw

PATCH v2 2/7 include: sbi: Add TINFO debug trigger CSR

In reply to Himanshu Chauhan

Add the missing TINFO debug trigger CSR.

---
 include/sbi/riscv_encoding.h | 1 +
 1 file changed, 1 insertion(+)
include/sbi/riscv_encoding.h +1 -0
index f20df76..e74cc0d 100644
@@ -686,6 +686,7 @@
 #define CSR_TDATA1			0x7a1
 #define CSR_TDATA2			0x7a2
 #define CSR_TDATA3			0x7a3
+#define CSR_TINFO			0x7a4
 
 /* Debug Mode Registers */
 #define CSR_DCSR			0x7b0
Signature · 1 line
2.34.1
#4 lore raw

PATCH v2 2/7 include: sbi: Add TINFO debug trigger CSR

Quoted 4 lines · On Mon, Jan 8, 2024 at 12:25?PM Himanshu Chauhan <[email protected]>…

Add the missing TINFO debug trigger CSR.

Already reviewed previously.

Regards,
Anup

Quoted 24 lines
---
 include/sbi/riscv_encoding.h | 1 +
 1 file changed, 1 insertion(+)
include/sbi/riscv_encoding.h +1 -1
index f20df76..e74cc0d 100644
@@ -686,6 +686,7 @@
 #define CSR_TDATA1                     0x7a1
 #define CSR_TDATA2                     0x7a2
 #define CSR_TDATA3                     0x7a3
+#define CSR_TINFO                      0x7a4
 
 /* Debug Mode Registers */
 #define CSR_DCSR                       0x7b0
--

2.34.1

--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

#5 lore raw

PATCH v2 3/7 include: sbi: Introduce debug trigger register encodings

In reply to Himanshu Chauhan

This patch introduces Mcontrol and M6 control register encodings along with macros to manipulate them.

---
 include/sbi/riscv_dbtr.h | 249 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 249 insertions(+)
 create mode 100644 include/sbi/riscv_dbtr.h
include/sbi/riscv_dbtr.h new file +249 -0
new file mode 100644
index 0000000..96c7d3e
@@ -0,0 +1,249 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro System, Inc.
+ *
+ * Authors:
+ *   Himanshu Chauhan <[email protected]>
+ */
+
+#ifndef __RISCV_DBTR_H__
+#define __RISCV_DBTR_H__
+
+#define RV_MAX_TRIGGERS	32
+
+enum {
+	RISCV_DBTR_TRIG_NONE = 0,
+	RISCV_DBTR_TRIG_LEGACY,
+	RISCV_DBTR_TRIG_MCONTROL,
+	RISCV_DBTR_TRIG_ICOUNT,
+	RISCV_DBTR_TRIG_ITRIGGER,
+	RISCV_DBTR_TRIG_ETRIGGER,
+	RISCV_DBTR_TRIG_MCONTROL6,
+};
+
+#define RV_DBTR_BIT(_prefix, _name)		\
+	RV_DBTR_##_prefix##_##_name##_BIT
+
+#define RV_DBTR_BIT_MASK(_prefix, _name)	\
+	RV_DBTR_##_prefix##_name##_BIT_MASK
+
+#define RV_DBTR_DECLARE_BIT(_prefix, _name, _val)	\
+	RV_DBTR_BIT(_prefix, _name) = _val
+
+#define RV_DBTR_DECLARE_BIT_MASK(_prefix, _name, _width)		\
+	RV_DBTR_BIT_MASK(_prefix, _name) =				\
+		(((1UL << _width) - 1) << RV_DBTR_BIT(_prefix, _name))
+
+#define CLEAR_DBTR_BIT(_target, _prefix, _bit_name)		\
+	__clear_bit(RV_DBTR_BIT(_prefix, _bit_name), &_target)
+
+#define SET_DBTR_BIT(_target, _prefix, _bit_name)		\
+	__set_bit(RV_DBTR_BIT(_prefix, _bit_name), &_target)
+
+/* Trigger Data 1 */
+enum {
+	RV_DBTR_DECLARE_BIT(TDATA1, DATA,   0),
+#if __riscv_xlen == 64
+	RV_DBTR_DECLARE_BIT(TDATA1, DMODE,  59),
+	RV_DBTR_DECLARE_BIT(TDATA1, TYPE,   60),
+#elif __riscv_xlen == 32
+	RV_DBTR_DECLARE_BIT(TDATA1, DMODE,  27),
+	RV_DBTR_DECLARE_BIT(TDATA1, TYPE,   28),
+#else
+	#error "Unknown __riscv_xlen"
+#endif
+};
+
+enum {
+#if __riscv_xlen == 64
+	RV_DBTR_DECLARE_BIT_MASK(TDATA1, DATA,  59),
+#elif __riscv_xlen == 32
+	RV_DBTR_DECLARE_BIT_MASK(TDATA1, DATA,  27),
+#else
+	#error "Unknown __riscv_xlen"
+#endif
+	RV_DBTR_DECLARE_BIT_MASK(TDATA1, DMODE, 1),
+	RV_DBTR_DECLARE_BIT_MASK(TDATA1, TYPE,  4),
+};
+
+/* MC - Match Control Type Register */
+enum {
+	RV_DBTR_DECLARE_BIT(MC, LOAD,    0),
+	RV_DBTR_DECLARE_BIT(MC, STORE,   1),
+	RV_DBTR_DECLARE_BIT(MC, EXEC,    2),
+	RV_DBTR_DECLARE_BIT(MC, U,       3),
+	RV_DBTR_DECLARE_BIT(MC, S,       4),
+	RV_DBTR_DECLARE_BIT(MC, RES2,    5),
+	RV_DBTR_DECLARE_BIT(MC, M,       6),
+	RV_DBTR_DECLARE_BIT(MC, MATCH,   7),
+	RV_DBTR_DECLARE_BIT(MC, CHAIN,   11),
+	RV_DBTR_DECLARE_BIT(MC, ACTION,  12),
+	RV_DBTR_DECLARE_BIT(MC, SIZELO,  16),
+	RV_DBTR_DECLARE_BIT(MC, TIMING,  18),
+	RV_DBTR_DECLARE_BIT(MC, SELECT,  19),
+	RV_DBTR_DECLARE_BIT(MC, HIT,     20),
+#if __riscv_xlen >= 64
+	RV_DBTR_DECLARE_BIT(MC, SIZEHI,  21),
+#endif
+#if __riscv_xlen == 64
+	RV_DBTR_DECLARE_BIT(MC, MASKMAX, 53),
+	RV_DBTR_DECLARE_BIT(MC, DMODE,   59),
+	RV_DBTR_DECLARE_BIT(MC, TYPE,    60),
+#elif __riscv_xlen == 32
+	RV_DBTR_DECLARE_BIT(MC, MASKMAX, 21),
+	RV_DBTR_DECLARE_BIT(MC, DMODE,   27),
+	RV_DBTR_DECLARE_BIT(MC, TYPE,    28),
+#else
+	#error "Unknown __riscv_xlen"
+#endif
+};
+
+enum {
+	RV_DBTR_DECLARE_BIT_MASK(MC, LOAD,    1),
+	RV_DBTR_DECLARE_BIT_MASK(MC, STORE,   1),
+	RV_DBTR_DECLARE_BIT_MASK(MC, EXEC,    1),
+	RV_DBTR_DECLARE_BIT_MASK(MC, U,       1),
+	RV_DBTR_DECLARE_BIT_MASK(MC, S,       1),
+	RV_DBTR_DECLARE_BIT_MASK(MC, RES2,    1),
+	RV_DBTR_DECLARE_BIT_MASK(MC, M,       1),
+	RV_DBTR_DECLARE_BIT_MASK(MC, MATCH,   4),
+	RV_DBTR_DECLARE_BIT_MASK(MC, CHAIN,   1),
+	RV_DBTR_DECLARE_BIT_MASK(MC, ACTION,  4),
+	RV_DBTR_DECLARE_BIT_MASK(MC, SIZELO,  2),
+	RV_DBTR_DECLARE_BIT_MASK(MC, TIMING,  1),
+	RV_DBTR_DECLARE_BIT_MASK(MC, SELECT,  1),
+	RV_DBTR_DECLARE_BIT_MASK(MC, HIT,     1),
+#if __riscv_xlen >= 64
+	RV_DBTR_DECLARE_BIT_MASK(MC, SIZEHI,  2),
+#endif
+	RV_DBTR_DECLARE_BIT_MASK(MC, MASKMAX, 6),
+	RV_DBTR_DECLARE_BIT_MASK(MC, DMODE,   1),
+	RV_DBTR_DECLARE_BIT_MASK(MC, TYPE,    4),
+};
+
+/* MC6 - Match Control 6 Type Register */
+enum {
+	RV_DBTR_DECLARE_BIT(MC6, LOAD,   0),
+	RV_DBTR_DECLARE_BIT(MC6, STORE,  1),
+	RV_DBTR_DECLARE_BIT(MC6, EXEC,   2),
+	RV_DBTR_DECLARE_BIT(MC6, U,      3),
+	RV_DBTR_DECLARE_BIT(MC6, S,      4),
+	RV_DBTR_DECLARE_BIT(MC6, RES2,   5),
+	RV_DBTR_DECLARE_BIT(MC6, M,      6),
+	RV_DBTR_DECLARE_BIT(MC6, MATCH,  7),
+	RV_DBTR_DECLARE_BIT(MC6, CHAIN,  11),
+	RV_DBTR_DECLARE_BIT(MC6, ACTION, 12),
+	RV_DBTR_DECLARE_BIT(MC6, SIZE,   16),
+	RV_DBTR_DECLARE_BIT(MC6, TIMING, 20),
+	RV_DBTR_DECLARE_BIT(MC6, SELECT, 21),
+	RV_DBTR_DECLARE_BIT(MC6, HIT,    22),
+	RV_DBTR_DECLARE_BIT(MC6, VU,     23),
+	RV_DBTR_DECLARE_BIT(MC6, VS,     24),
+#if __riscv_xlen == 64
+	RV_DBTR_DECLARE_BIT(MC6, DMODE,  59),
+	RV_DBTR_DECLARE_BIT(MC6, TYPE,   60),
+#elif __riscv_xlen == 32
+	RV_DBTR_DECLARE_BIT(MC6, DMODE,  27),
+	RV_DBTR_DECLARE_BIT(MC6, TYPE,   28),
+#else
+	#error "Unknown __riscv_xlen"
+#endif
+};
+
+enum {
+	RV_DBTR_DECLARE_BIT_MASK(MC6, LOAD,   1),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, STORE,  1),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, EXEC,   1),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, U,      1),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, S,      1),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, RES2,   1),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, M,      1),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, MATCH,  4),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, CHAIN,  1),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, ACTION, 4),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, SIZE,   4),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, TIMING, 1),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, SELECT, 1),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, HIT,    1),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, VU,     1),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, VS,     1),
+#if __riscv_xlen == 64
+	RV_DBTR_DECLARE_BIT_MASK(MC6, DMODE,  1),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, TYPE,   4),
+#elif __riscv_xlen == 32
+	RV_DBTR_DECLARE_BIT_MASK(MC6, DMODE,  1),
+	RV_DBTR_DECLARE_BIT_MASK(MC6, TYPE,   4),
+#else
+	#error "Unknown __riscv_xlen"
+#endif
+};
+
+#define RV_DBTR_SET_TDATA1_TYPE(_t1, _type)				\
+	do {								\
+		_t1 &= ~RV_DBTR_BIT_MASK(TDATA1, TYPE);			\
+		_t1 |= (((unsigned long)_type				\
+			 << RV_DBTR_BIT(TDATA1, TYPE))			\
+			& RV_DBTR_BIT_MASK(TDATA1, TYPE));		\
+	}while (0);
+
+#define RV_DBTR_SET_MC_TYPE(_t1, _type)				\
+	do {							\
+		_t1 &= ~RV_DBTR_BIT_MASK(MC, TYPE);		\
+		_t1 |= (((unsigned long)_type			\
+			 << RV_DBTR_BIT(MC, TYPE))		\
+			& RV_DBTR_BIT_MASK(MC, TYPE));		\
+	}while (0);
+
+#define RV_DBTR_SET_MC6_TYPE(_t1, _type)			\
+	do {							\
+		_t1 &= ~RV_DBTR_BIT_MASK(MC6, TYPE);		\
+		_t1 |= (((unsigned long)_type			\
+			 << RV_DBTR_BIT(MC6, TYPE))		\
+			& RV_DBTR_BIT_MASK(MC6, TYPE));		\
+	}while (0);
+
+#define RV_DBTR_SET_MC_EXEC(_t1)		\
+	SET_DBTR_BIT(_t1, MC, EXEC)
+
+#define RV_DBTR_SET_MC_LOAD(_t1)		\
+	SET_DBTR_BIT(_t1, MC, LOAD)
+
+#define RV_DBTR_SET_MC_STORE(_t1)		\
+	SET_DBTR_BIT(_t1, MC, STORE)
+
+#define RV_DBTR_SET_MC_SIZELO(_t1, _val)			\
+	do {							\
+		_t1 &= ~RV_DBTR_BIT_MASK(MC, SIZELO);		\
+		_t1 |= ((_val << RV_DBTR_BIT(MC, SIZELO))	\
+			& RV_DBTR_BIT_MASK(MC, SIZELO));	\
+	} while(0);
+
+#define RV_DBTR_SET_MC_SIZEHI(_t1, _val)			\
+	do {							\
+		_t1 &= ~RV_DBTR_BIT_MASK(MC, SIZEHI);		\
+		_t1 |= ((_val << RV_DBTR_BIT(MC, SIZEHI))	\
+			& RV_DBTR_BIT_MASK(MC, SIZEHI));	\
+	} while(0);
+
+#define RV_DBTR_SET_MC6_EXEC(_t1)		\
+	SET_DBTR_BIT(_t1, MC6, EXEC)
+
+#define RV_DBTR_SET_MC6_LOAD(_t1)		\
+	SET_DBTR_BIT(_t1, MC6, LOAD)
+
+#define RV_DBTR_SET_MC6_STORE(_t1)		\
+	SET_DBTR_BIT(_t1, MC6, STORE)
+
+#define RV_DBTR_SET_MC6_SIZE(_t1, _val)				\
+	do {							\
+		_t1 &= ~RV_DBTR_BIT_MASK(MC6, SIZE);		\
+		_t1 |= ((_val << RV_DBTR_BIT(MC6, SIZE))	\
+			& RV_DBTR_BIT_MASK(MC6, SIZE));		\
+	} while(0);
+
+typedef unsigned long riscv_dbtr_tdata1_mcontrol_t;
+typedef unsigned long riscv_dbtr_tdata1_mcontrol6_t;
+typedef unsigned long riscv_dbtr_tdata1_t;
+
+#endif /* __RISCV_DBTR_H__ */
Signature · 1 line
2.34.1
#6 lore raw

PATCH v2 3/7 include: sbi: Introduce debug trigger register encodings

Quoted 5 lines · On Mon, Jan 8, 2024 at 12:25?PM Himanshu Chauhan <[email protected]>…

This patch introduces Mcontrol and M6 control register encodings along with macros to manipulate them.

Already reviewed previously.

Regards,
Anup

Quoted 268 lines
---
 include/sbi/riscv_dbtr.h | 249 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 249 insertions(+)
 create mode 100644 include/sbi/riscv_dbtr.h
include/sbi/riscv_dbtr.h new file +249 -1
new file mode 100644
index 0000000..96c7d3e
@@ -0,0 +1,249 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro System, Inc.
+ *
+ * Authors:
+ *   Himanshu Chauhan <[email protected]>
+ */
+
+#ifndef __RISCV_DBTR_H__
+#define __RISCV_DBTR_H__
+
+#define RV_MAX_TRIGGERS        32
+
+enum {
+       RISCV_DBTR_TRIG_NONE = 0,
+       RISCV_DBTR_TRIG_LEGACY,
+       RISCV_DBTR_TRIG_MCONTROL,
+       RISCV_DBTR_TRIG_ICOUNT,
+       RISCV_DBTR_TRIG_ITRIGGER,
+       RISCV_DBTR_TRIG_ETRIGGER,
+       RISCV_DBTR_TRIG_MCONTROL6,
+};
+
+#define RV_DBTR_BIT(_prefix, _name)            \
+       RV_DBTR_##_prefix##_##_name##_BIT
+
+#define RV_DBTR_BIT_MASK(_prefix, _name)       \
+       RV_DBTR_##_prefix##_name##_BIT_MASK
+
+#define RV_DBTR_DECLARE_BIT(_prefix, _name, _val)      \
+       RV_DBTR_BIT(_prefix, _name) = _val
+
+#define RV_DBTR_DECLARE_BIT_MASK(_prefix, _name, _width)               \
+       RV_DBTR_BIT_MASK(_prefix, _name) =                              \
+               (((1UL << _width) - 1) << RV_DBTR_BIT(_prefix, _name))
+
+#define CLEAR_DBTR_BIT(_target, _prefix, _bit_name)            \
+       __clear_bit(RV_DBTR_BIT(_prefix, _bit_name), &_target)
+
+#define SET_DBTR_BIT(_target, _prefix, _bit_name)              \
+       __set_bit(RV_DBTR_BIT(_prefix, _bit_name), &_target)
+
+/* Trigger Data 1 */
+enum {
+       RV_DBTR_DECLARE_BIT(TDATA1, DATA,   0),
+#if __riscv_xlen == 64
+       RV_DBTR_DECLARE_BIT(TDATA1, DMODE,  59),
+       RV_DBTR_DECLARE_BIT(TDATA1, TYPE,   60),
+#elif __riscv_xlen == 32
+       RV_DBTR_DECLARE_BIT(TDATA1, DMODE,  27),
+       RV_DBTR_DECLARE_BIT(TDATA1, TYPE,   28),
+#else
+       #error "Unknown __riscv_xlen"
+#endif
+};
+
+enum {
+#if __riscv_xlen == 64
+       RV_DBTR_DECLARE_BIT_MASK(TDATA1, DATA,  59),
+#elif __riscv_xlen == 32
+       RV_DBTR_DECLARE_BIT_MASK(TDATA1, DATA,  27),
+#else
+       #error "Unknown __riscv_xlen"
+#endif
+       RV_DBTR_DECLARE_BIT_MASK(TDATA1, DMODE, 1),
+       RV_DBTR_DECLARE_BIT_MASK(TDATA1, TYPE,  4),
+};
+
+/* MC - Match Control Type Register */
+enum {
+       RV_DBTR_DECLARE_BIT(MC, LOAD,    0),
+       RV_DBTR_DECLARE_BIT(MC, STORE,   1),
+       RV_DBTR_DECLARE_BIT(MC, EXEC,    2),
+       RV_DBTR_DECLARE_BIT(MC, U,       3),
+       RV_DBTR_DECLARE_BIT(MC, S,       4),
+       RV_DBTR_DECLARE_BIT(MC, RES2,    5),
+       RV_DBTR_DECLARE_BIT(MC, M,       6),
+       RV_DBTR_DECLARE_BIT(MC, MATCH,   7),
+       RV_DBTR_DECLARE_BIT(MC, CHAIN,   11),
+       RV_DBTR_DECLARE_BIT(MC, ACTION,  12),
+       RV_DBTR_DECLARE_BIT(MC, SIZELO,  16),
+       RV_DBTR_DECLARE_BIT(MC, TIMING,  18),
+       RV_DBTR_DECLARE_BIT(MC, SELECT,  19),
+       RV_DBTR_DECLARE_BIT(MC, HIT,     20),
+#if __riscv_xlen >= 64
+       RV_DBTR_DECLARE_BIT(MC, SIZEHI,  21),
+#endif
+#if __riscv_xlen == 64
+       RV_DBTR_DECLARE_BIT(MC, MASKMAX, 53),
+       RV_DBTR_DECLARE_BIT(MC, DMODE,   59),
+       RV_DBTR_DECLARE_BIT(MC, TYPE,    60),
+#elif __riscv_xlen == 32
+       RV_DBTR_DECLARE_BIT(MC, MASKMAX, 21),
+       RV_DBTR_DECLARE_BIT(MC, DMODE,   27),
+       RV_DBTR_DECLARE_BIT(MC, TYPE,    28),
+#else
+       #error "Unknown __riscv_xlen"
+#endif
+};
+
+enum {
+       RV_DBTR_DECLARE_BIT_MASK(MC, LOAD,    1),
+       RV_DBTR_DECLARE_BIT_MASK(MC, STORE,   1),
+       RV_DBTR_DECLARE_BIT_MASK(MC, EXEC,    1),
+       RV_DBTR_DECLARE_BIT_MASK(MC, U,       1),
+       RV_DBTR_DECLARE_BIT_MASK(MC, S,       1),
+       RV_DBTR_DECLARE_BIT_MASK(MC, RES2,    1),
+       RV_DBTR_DECLARE_BIT_MASK(MC, M,       1),
+       RV_DBTR_DECLARE_BIT_MASK(MC, MATCH,   4),
+       RV_DBTR_DECLARE_BIT_MASK(MC, CHAIN,   1),
+       RV_DBTR_DECLARE_BIT_MASK(MC, ACTION,  4),
+       RV_DBTR_DECLARE_BIT_MASK(MC, SIZELO,  2),
+       RV_DBTR_DECLARE_BIT_MASK(MC, TIMING,  1),
+       RV_DBTR_DECLARE_BIT_MASK(MC, SELECT,  1),
+       RV_DBTR_DECLARE_BIT_MASK(MC, HIT,     1),
+#if __riscv_xlen >= 64
+       RV_DBTR_DECLARE_BIT_MASK(MC, SIZEHI,  2),
+#endif
+       RV_DBTR_DECLARE_BIT_MASK(MC, MASKMAX, 6),
+       RV_DBTR_DECLARE_BIT_MASK(MC, DMODE,   1),
+       RV_DBTR_DECLARE_BIT_MASK(MC, TYPE,    4),
+};
+
+/* MC6 - Match Control 6 Type Register */
+enum {
+       RV_DBTR_DECLARE_BIT(MC6, LOAD,   0),
+       RV_DBTR_DECLARE_BIT(MC6, STORE,  1),
+       RV_DBTR_DECLARE_BIT(MC6, EXEC,   2),
+       RV_DBTR_DECLARE_BIT(MC6, U,      3),
+       RV_DBTR_DECLARE_BIT(MC6, S,      4),
+       RV_DBTR_DECLARE_BIT(MC6, RES2,   5),
+       RV_DBTR_DECLARE_BIT(MC6, M,      6),
+       RV_DBTR_DECLARE_BIT(MC6, MATCH,  7),
+       RV_DBTR_DECLARE_BIT(MC6, CHAIN,  11),
+       RV_DBTR_DECLARE_BIT(MC6, ACTION, 12),
+       RV_DBTR_DECLARE_BIT(MC6, SIZE,   16),
+       RV_DBTR_DECLARE_BIT(MC6, TIMING, 20),
+       RV_DBTR_DECLARE_BIT(MC6, SELECT, 21),
+       RV_DBTR_DECLARE_BIT(MC6, HIT,    22),
+       RV_DBTR_DECLARE_BIT(MC6, VU,     23),
+       RV_DBTR_DECLARE_BIT(MC6, VS,     24),
+#if __riscv_xlen == 64
+       RV_DBTR_DECLARE_BIT(MC6, DMODE,  59),
+       RV_DBTR_DECLARE_BIT(MC6, TYPE,   60),
+#elif __riscv_xlen == 32
+       RV_DBTR_DECLARE_BIT(MC6, DMODE,  27),
+       RV_DBTR_DECLARE_BIT(MC6, TYPE,   28),
+#else
+       #error "Unknown __riscv_xlen"
+#endif
+};
+
+enum {
+       RV_DBTR_DECLARE_BIT_MASK(MC6, LOAD,   1),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, STORE,  1),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, EXEC,   1),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, U,      1),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, S,      1),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, RES2,   1),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, M,      1),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, MATCH,  4),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, CHAIN,  1),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, ACTION, 4),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, SIZE,   4),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, TIMING, 1),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, SELECT, 1),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, HIT,    1),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, VU,     1),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, VS,     1),
+#if __riscv_xlen == 64
+       RV_DBTR_DECLARE_BIT_MASK(MC6, DMODE,  1),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, TYPE,   4),
+#elif __riscv_xlen == 32
+       RV_DBTR_DECLARE_BIT_MASK(MC6, DMODE,  1),
+       RV_DBTR_DECLARE_BIT_MASK(MC6, TYPE,   4),
+#else
+       #error "Unknown __riscv_xlen"
+#endif
+};
+
+#define RV_DBTR_SET_TDATA1_TYPE(_t1, _type)                            \
+       do {                                                            \
+               _t1 &= ~RV_DBTR_BIT_MASK(TDATA1, TYPE);                 \
+               _t1 |= (((unsigned long)_type                           \
+                        << RV_DBTR_BIT(TDATA1, TYPE))                  \
+                       & RV_DBTR_BIT_MASK(TDATA1, TYPE));              \
+       }while (0);
+
+#define RV_DBTR_SET_MC_TYPE(_t1, _type)                                \
+       do {                                                    \
+               _t1 &= ~RV_DBTR_BIT_MASK(MC, TYPE);             \
+               _t1 |= (((unsigned long)_type                   \
+                        << RV_DBTR_BIT(MC, TYPE))              \
+                       & RV_DBTR_BIT_MASK(MC, TYPE));          \
+       }while (0);
+
+#define RV_DBTR_SET_MC6_TYPE(_t1, _type)                       \
+       do {                                                    \
+               _t1 &= ~RV_DBTR_BIT_MASK(MC6, TYPE);            \
+               _t1 |= (((unsigned long)_type                   \
+                        << RV_DBTR_BIT(MC6, TYPE))             \
+                       & RV_DBTR_BIT_MASK(MC6, TYPE));         \
+       }while (0);
+
+#define RV_DBTR_SET_MC_EXEC(_t1)               \
+       SET_DBTR_BIT(_t1, MC, EXEC)
+
+#define RV_DBTR_SET_MC_LOAD(_t1)               \
+       SET_DBTR_BIT(_t1, MC, LOAD)
+
+#define RV_DBTR_SET_MC_STORE(_t1)              \
+       SET_DBTR_BIT(_t1, MC, STORE)
+
+#define RV_DBTR_SET_MC_SIZELO(_t1, _val)                       \
+       do {                                                    \
+               _t1 &= ~RV_DBTR_BIT_MASK(MC, SIZELO);           \
+               _t1 |= ((_val << RV_DBTR_BIT(MC, SIZELO))       \
+                       & RV_DBTR_BIT_MASK(MC, SIZELO));        \
+       } while(0);
+
+#define RV_DBTR_SET_MC_SIZEHI(_t1, _val)                       \
+       do {                                                    \
+               _t1 &= ~RV_DBTR_BIT_MASK(MC, SIZEHI);           \
+               _t1 |= ((_val << RV_DBTR_BIT(MC, SIZEHI))       \
+                       & RV_DBTR_BIT_MASK(MC, SIZEHI));        \
+       } while(0);
+
+#define RV_DBTR_SET_MC6_EXEC(_t1)              \
+       SET_DBTR_BIT(_t1, MC6, EXEC)
+
+#define RV_DBTR_SET_MC6_LOAD(_t1)              \
+       SET_DBTR_BIT(_t1, MC6, LOAD)
+
+#define RV_DBTR_SET_MC6_STORE(_t1)             \
+       SET_DBTR_BIT(_t1, MC6, STORE)
+
+#define RV_DBTR_SET_MC6_SIZE(_t1, _val)                                \
+       do {                                                    \
+               _t1 &= ~RV_DBTR_BIT_MASK(MC6, SIZE);            \
+               _t1 |= ((_val << RV_DBTR_BIT(MC6, SIZE))        \
+                       & RV_DBTR_BIT_MASK(MC6, SIZE));         \
+       } while(0);
+
+typedef unsigned long riscv_dbtr_tdata1_mcontrol_t;
+typedef unsigned long riscv_dbtr_tdata1_mcontrol6_t;
+typedef unsigned long riscv_dbtr_tdata1_t;
+
+#endif /* __RISCV_DBTR_H__ */
--

2.34.1

--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

#7 lore raw

PATCH v2 4/7 lib: sbi: Introduce the SBI debug triggers extension support

In reply to Himanshu Chauhan

RISC-V Debug specification includes Sdtrig ISA extension which describes Trigger Module. Triggers can cause a breakpoint exception or trace action without execution of a special instruction. They can be used to implement hardware breakpoints and watchpoints for native debugging.

The SBI Debut Trigger extension (Draft v6) can be found at:
https://lists.riscv.org/g/tech-debug/topic/99825362#1302

This patch is an initial implementation of SBI Debug Trigger Extension (Draft v6) in OpenSBI.

The following features are supported:
* mcontrol, mcontrol6 triggers
* Breakpoint and trace actions

NOTE: Chained triggers are not supported

---
 include/sbi/sbi_dbtr.h | 127 +++++++
 lib/sbi/objects.mk     |   1 +
 lib/sbi/sbi_dbtr.c     | 742 +++++++++++++++++++++++++++++++++++++++++
 lib/sbi/sbi_init.c     |   9 +
 4 files changed, 879 insertions(+)
 create mode 100644 include/sbi/sbi_dbtr.h
 create mode 100644 lib/sbi/sbi_dbtr.c
include/sbi/sbi_dbtr.h new file +127 -0
new file mode 100644
index 0000000..20855ae
@@ -0,0 +1,127 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro Systems, Inc.
+ *
+ * Authors:
+ *   Himanshu Chauhan <[email protected]>
+ */
+
+#ifndef __SBI_DBTR_H__
+#define __SBI_DBTR_H__
+
+#include <sbi/riscv_dbtr.h>
+
+#include <sbi/sbi_hartmask.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_types.h>
+#include <sbi/sbi_byteorder.h>
+
+enum {
+	RV_DBTR_DECLARE_BIT(TS, MAPPED, 0), /* trigger mapped to hw trigger */
+	RV_DBTR_DECLARE_BIT(TS, U, 1),
+	RV_DBTR_DECLARE_BIT(TS, S, 2),
+	RV_DBTR_DECLARE_BIT(TS, VU, 3),
+	RV_DBTR_DECLARE_BIT(TS, VS, 4),
+	RV_DBTR_DECLARE_BIT(TS, HAVE_TRIG, 5), /* H/w dbtr details available */
+	RV_DBTR_DECLARE_BIT(TS, HW_IDX, 8), /* Hardware index of trigger */
+};
+
+enum {
+	RV_DBTR_DECLARE_BIT_MASK(TS, MAPPED, 1),
+	RV_DBTR_DECLARE_BIT_MASK(TS, U, 1),
+	RV_DBTR_DECLARE_BIT_MASK(TS, S, 1),
+	RV_DBTR_DECLARE_BIT_MASK(TS, VU, 1),
+	RV_DBTR_DECLARE_BIT_MASK(TS, VS, 1),
+	RV_DBTR_DECLARE_BIT_MASK(TS, HAVE_TRIG, 1),
+	RV_DBTR_DECLARE_BIT_MASK(TS, HW_IDX, (__riscv_xlen-9)),
+};
+
+#if __riscv_xlen == 64
+#define SBI_DBTR_SHMEM_INVALID_ADDR	0xFFFFFFFFFFFFFFFFUL
+#elif __riscv_xlen == 32
+#define SBI_DBTR_SHMEM_INVALID_ADDR	0xFFFFFFFFUL
+#error "Unexpected __riscv_xlen"
+#endif
+
+struct sbi_dbtr_shmem {
+	unsigned long phys_lo;
+	unsigned long phys_hi;
+};
+
+struct sbi_dbtr_trigger {
+	unsigned long index;
+	unsigned long type_mask;
+	unsigned long state;
+	unsigned long tdata1;
+	unsigned long tdata2;
+	unsigned long tdata3;
+};
+
+struct sbi_dbtr_data_msg {
+	unsigned long tstate;
+	unsigned long tdata1;
+	unsigned long tdata2;
+	unsigned long tdata3;
+};
+
+struct sbi_dbtr_id_msg {
+	unsigned long idx;
+};
+
+struct sbi_dbtr_hart_triggers_state {
+	struct sbi_dbtr_trigger triggers[RV_MAX_TRIGGERS];
+	struct sbi_dbtr_shmem shmem;
+	u32 total_trigs;
+	u32 available_trigs;
+	u32 hartid;
+};
+
+#define TDATA1_GET_TYPE(_t1)					\
+	EXTRACT_FIELD(_t1, RV_DBTR_BIT_MASK(TDATA1, TYPE))
+
+/* Set the hardware index of trigger in logical trigger state */
+#define SET_TRIG_HW_INDEX(_state, _idx)				\
+	do {							\
+		_state &= ~RV_DBTR_BIT_MASK(TS, HW_IDX);	\
+		_state |= (((unsigned long)_idx			\
+			    << RV_DBTR_BIT(TS, HW_IDX))		\
+			   & RV_DBTR_BIT_MASK(TS, HW_IDX));	\
+	}while (0);
+
+/** SBI shared mem messages layout */
+struct sbi_dbtr_shmem_entry {
+	struct sbi_dbtr_data_msg data;
+	struct sbi_dbtr_id_msg id;
+};
+
+#define SBI_DBTR_SHMEM_ALIGN_MASK               ((__riscv_xlen / 8) - 1)
+
+/** Initialize debug triggers */
+int sbi_dbtr_init(struct sbi_scratch *scratch, bool coldboot);
+
+/** SBI DBTR extension functions */
+int sbi_dbtr_supported(void);
+int sbi_dbtr_setup_shmem(const struct sbi_domain *dom, unsigned long smode,
+			 unsigned long shmem_phys_lo,
+			 unsigned long shmem_phys_hi);
+int sbi_dbtr_num_trig(unsigned long trig_tdata1, unsigned long *out);
+int sbi_dbtr_read_trig(const struct sbi_domain *dom, unsigned long smode,
+		       unsigned long trig_idx_base, unsigned long trig_count);
+int sbi_dbtr_install_trig(const struct sbi_domain *dom, unsigned long smode,
+			  unsigned long trig_count, unsigned long *out);
+int sbi_dbtr_uninstall_trig(unsigned long trig_idx_base,
+			    unsigned long trig_idx_mask);
+int sbi_dbtr_enable_trig(unsigned long trig_idx_base,
+			 unsigned long trig_idx_mask);
+int sbi_dbtr_update_trig(const struct sbi_domain *dom,
+			 unsigned long smode,
+			 unsigned long trig_idx_base,
+			 unsigned long trig_idx_mask);
+int sbi_dbtr_disable_trig(unsigned long trig_idx_base,
+			  unsigned long trig_idx_mask);
+
+int sbi_dbtr_get_total_triggers(void);
+
+#endif
lib/sbi/objects.mk +1 -0
index c699187..c7de150 100644
@@ -70,6 +70,7 @@ libsbi-objs-y += sbi_irqchip.o
 libsbi-objs-y += sbi_misaligned_ldst.o
 libsbi-objs-y += sbi_platform.o
 libsbi-objs-y += sbi_pmu.o
+libsbi-objs-y += sbi_dbtr.o
 libsbi-objs-y += sbi_scratch.o
 libsbi-objs-y += sbi_string.o
 libsbi-objs-y += sbi_system.o
lib/sbi/sbi_dbtr.c new file +742 -0

742 lines not on this page · raw message

lib/sbi/sbi_init.c +9 -0
index 6a98e13..0dcde27 100644
@@ -23,6 +23,7 @@
 #include <sbi/sbi_irqchip.h>
 #include <sbi/sbi_platform.h>
 #include <sbi/sbi_pmu.h>
+#include <sbi/sbi_dbtr.h>
 #include <sbi/sbi_system.h>
 #include <sbi/sbi_string.h>
 #include <sbi/sbi_timer.h>
@@ -322,6 +323,10 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
 		sbi_hart_hang();
 	}
 
+	rc = sbi_dbtr_init(scratch, true);
+	if (rc)
+		sbi_hart_hang();
+
 	sbi_boot_print_banner(scratch);
 
 	rc = sbi_irqchip_init(scratch, true);
@@ -439,6 +444,10 @@ static void __noreturn init_warm_startup(struct sbi_scratch *scratch,
 	if (rc)
 		sbi_hart_hang();
 
+	rc = sbi_dbtr_init(scratch, false);
+	if (rc)
+		sbi_hart_hang();
+
 	rc = sbi_irqchip_init(scratch, false);
 	if (rc)
 		sbi_hart_hang();
Signature · 1 line
2.34.1
#8 lore raw

PATCH v2 4/7 lib: sbi: Introduce the SBI debug triggers extension support

Quoted 13 lines · On Mon, Jan 8, 2024 at 12:25?PM Himanshu Chauhan <[email protected]>…

RISC-V Debug specification includes Sdtrig ISA extension which describes Trigger Module. Triggers can cause a breakpoint exception or trace action without execution of a special instruction. They can be used to implement hardware breakpoints and watchpoints for native debugging.

The SBI Debut Trigger extension (Draft v6) can be found at:
https://lists.riscv.org/g/tech-debug/topic/99825362#1302

This patch is an initial implementation of SBI Debug Trigger Extension (Draft v6) in OpenSBI.

Quoted 7 lines

The following features are supported:
* mcontrol, mcontrol6 triggers
* Breakpoint and trace actions

NOTE: Chained triggers are not supported

We need another patch just before this patch which detects the presence of Sdtrig extension based on ISA string. The Txyz CSRs are only available when the Sdtrig extension is available.

Quoted 319 lines
---
 include/sbi/sbi_dbtr.h | 127 +++++++
 lib/sbi/objects.mk     |   1 +
 lib/sbi/sbi_dbtr.c     | 742 +++++++++++++++++++++++++++++++++++++++++
 lib/sbi/sbi_init.c     |   9 +
 4 files changed, 879 insertions(+)
 create mode 100644 include/sbi/sbi_dbtr.h
 create mode 100644 lib/sbi/sbi_dbtr.c
include/sbi/sbi_dbtr.h new file +127 -0
new file mode 100644
index 0000000..20855ae
@@ -0,0 +1,127 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro Systems, Inc.
+ *
+ * Authors:
+ *   Himanshu Chauhan <[email protected]>
+ */
+
+#ifndef __SBI_DBTR_H__
+#define __SBI_DBTR_H__
+
+#include <sbi/riscv_dbtr.h>
+
+#include <sbi/sbi_hartmask.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_types.h>
+#include <sbi/sbi_byteorder.h>
+
+enum {
+       RV_DBTR_DECLARE_BIT(TS, MAPPED, 0), /* trigger mapped to hw trigger */
+       RV_DBTR_DECLARE_BIT(TS, U, 1),
+       RV_DBTR_DECLARE_BIT(TS, S, 2),
+       RV_DBTR_DECLARE_BIT(TS, VU, 3),
+       RV_DBTR_DECLARE_BIT(TS, VS, 4),
+       RV_DBTR_DECLARE_BIT(TS, HAVE_TRIG, 5), /* H/w dbtr details available */
+       RV_DBTR_DECLARE_BIT(TS, HW_IDX, 8), /* Hardware index of trigger */
+};
+
+enum {
+       RV_DBTR_DECLARE_BIT_MASK(TS, MAPPED, 1),
+       RV_DBTR_DECLARE_BIT_MASK(TS, U, 1),
+       RV_DBTR_DECLARE_BIT_MASK(TS, S, 1),
+       RV_DBTR_DECLARE_BIT_MASK(TS, VU, 1),
+       RV_DBTR_DECLARE_BIT_MASK(TS, VS, 1),
+       RV_DBTR_DECLARE_BIT_MASK(TS, HAVE_TRIG, 1),
+       RV_DBTR_DECLARE_BIT_MASK(TS, HW_IDX, (__riscv_xlen-9)),
+};
+
+#if __riscv_xlen == 64
+#define SBI_DBTR_SHMEM_INVALID_ADDR    0xFFFFFFFFFFFFFFFFUL
+#elif __riscv_xlen == 32
+#define SBI_DBTR_SHMEM_INVALID_ADDR    0xFFFFFFFFUL
+#error "Unexpected __riscv_xlen"
+#endif
+
+struct sbi_dbtr_shmem {
+       unsigned long phys_lo;
+       unsigned long phys_hi;
+};
+
+struct sbi_dbtr_trigger {
+       unsigned long index;
+       unsigned long type_mask;
+       unsigned long state;
+       unsigned long tdata1;
+       unsigned long tdata2;
+       unsigned long tdata3;
+};
+
+struct sbi_dbtr_data_msg {
+       unsigned long tstate;
+       unsigned long tdata1;
+       unsigned long tdata2;
+       unsigned long tdata3;
+};
+
+struct sbi_dbtr_id_msg {
+       unsigned long idx;
+};
+
+struct sbi_dbtr_hart_triggers_state {
+       struct sbi_dbtr_trigger triggers[RV_MAX_TRIGGERS];
+       struct sbi_dbtr_shmem shmem;
+       u32 total_trigs;
+       u32 available_trigs;
+       u32 hartid;
+};
+
+#define TDATA1_GET_TYPE(_t1)                                   \
+       EXTRACT_FIELD(_t1, RV_DBTR_BIT_MASK(TDATA1, TYPE))
+
+/* Set the hardware index of trigger in logical trigger state */
+#define SET_TRIG_HW_INDEX(_state, _idx)                                \
+       do {                                                    \
+               _state &= ~RV_DBTR_BIT_MASK(TS, HW_IDX);        \
+               _state |= (((unsigned long)_idx                 \
+                           << RV_DBTR_BIT(TS, HW_IDX))         \
+                          & RV_DBTR_BIT_MASK(TS, HW_IDX));     \
+       }while (0);
+
+/** SBI shared mem messages layout */
+struct sbi_dbtr_shmem_entry {
+       struct sbi_dbtr_data_msg data;
+       struct sbi_dbtr_id_msg id;
+};
+
+#define SBI_DBTR_SHMEM_ALIGN_MASK               ((__riscv_xlen / 8) - 1)
+
+/** Initialize debug triggers */
+int sbi_dbtr_init(struct sbi_scratch *scratch, bool coldboot);
+
+/** SBI DBTR extension functions */
+int sbi_dbtr_supported(void);
+int sbi_dbtr_setup_shmem(const struct sbi_domain *dom, unsigned long smode,
+                        unsigned long shmem_phys_lo,
+                        unsigned long shmem_phys_hi);
+int sbi_dbtr_num_trig(unsigned long trig_tdata1, unsigned long *out);
+int sbi_dbtr_read_trig(const struct sbi_domain *dom, unsigned long smode,
+                      unsigned long trig_idx_base, unsigned long trig_count);
+int sbi_dbtr_install_trig(const struct sbi_domain *dom, unsigned long smode,
+                         unsigned long trig_count, unsigned long *out);
+int sbi_dbtr_uninstall_trig(unsigned long trig_idx_base,
+                           unsigned long trig_idx_mask);
+int sbi_dbtr_enable_trig(unsigned long trig_idx_base,
+                        unsigned long trig_idx_mask);
+int sbi_dbtr_update_trig(const struct sbi_domain *dom,
+                        unsigned long smode,
+                        unsigned long trig_idx_base,
+                        unsigned long trig_idx_mask);
+int sbi_dbtr_disable_trig(unsigned long trig_idx_base,
+                         unsigned long trig_idx_mask);
+
+int sbi_dbtr_get_total_triggers(void);
+
+#endif
lib/sbi/objects.mk +1 -0
index c699187..c7de150 100644
@@ -70,6 +70,7 @@ libsbi-objs-y += sbi_irqchip.o
 libsbi-objs-y += sbi_misaligned_ldst.o
 libsbi-objs-y += sbi_platform.o
 libsbi-objs-y += sbi_pmu.o
+libsbi-objs-y += sbi_dbtr.o
 libsbi-objs-y += sbi_scratch.o
 libsbi-objs-y += sbi_string.o
 libsbi-objs-y += sbi_system.o
lib/sbi/sbi_dbtr.c new file +159 -0
new file mode 100644
index 0000000..1bd29c1
@@ -0,0 +1,742 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro Systems, Inc.
+ *
+ * Author(s):
+ *   Himanshu Chauhan <[email protected]>
+ */
+
+#include <sbi/sbi_ecall_interface.h>
+#include <sbi/sbi_csr_detect.h>
+#include <sbi/sbi_platform.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_trap.h>
+#include <sbi/sbi_dbtr.h>
+#include <sbi/sbi_heap.h>
+#include <sbi/riscv_encoding.h>
+#include <sbi/riscv_asm.h>
+
+
+/** Offset of pointer to HART's debug triggers info in scratch space */
+static unsigned long hart_state_ptr_offset;
+
+#define dbtr_get_hart_state_ptr(__scratch)                             \
+       sbi_scratch_read_type((__scratch), void *, hart_state_ptr_offset)
+
+#define dbtr_thishart_state_ptr()                              \
+       dbtr_get_hart_state_ptr(sbi_scratch_thishart_ptr())
+
+#define dbtr_set_hart_state_ptr(__scratch, __hart_state)               \
+       sbi_scratch_write_type((__scratch), void *, hart_state_ptr_offset, \
+                              (__hart_state))
+
+#define INDEX_TO_TRIGGER(_index)                                       \
+       ({                                                              \
+               struct sbi_dbtr_trigger *__trg = NULL;                  \
+               struct sbi_dbtr_hart_triggers_state *__hs = NULL;       \
+               __hs = dbtr_get_hart_state_ptr(sbi_scratch_thishart_ptr()); \
+               __trg = &__hs->triggers[_index];                        \
+               (__trg);                                                \
+       })
+
+#define for_each_trig_entry(_base, _max, _etype, _entry)               \
+       for (int _idx = 0; _entry = ((_etype *)_base + _idx),           \
+            _idx < _max;                                               \
+            _idx++, _entry = ((_etype *)_base + _idx))
+
+#if __riscv_xlen == 64
+#define DBTR_SHMEM_MAKE_PHYS(_p_hi, _p_lo) (((u64)(_p_hi) << 32) | (_p_lo))
+#elif __riscv_xlen == 32
+#define DBTR_SHMEM_MAKE_PHYS(_p_hi, _p_lo) (((u64)(_p_hi) << 32) | (_p_lo))
+#else
+#error "Undefined XLEN"
+#endif
+
+static inline int sbi_dbtr_shmem_disabled(void)
+{
+       struct sbi_dbtr_hart_triggers_state *hs = NULL;
+
+       hs = dbtr_get_hart_state_ptr(sbi_scratch_thishart_ptr());
+
+       if (!hs)
+               return 1;
+
+       return (hs->shmem.phys_lo == SBI_DBTR_SHMEM_INVALID_ADDR &&
+               hs->shmem.phys_hi == SBI_DBTR_SHMEM_INVALID_ADDR
+               ? 1 : 0);
+}
+
+static inline void sbi_dbtr_disable_shmem(void)
+{
+       struct sbi_dbtr_hart_triggers_state *hs = NULL;
+
+       hs = dbtr_get_hart_state_ptr(sbi_scratch_thishart_ptr());
+
+       if (!hs)
+               return;
+
+       hs->shmem.phys_lo = SBI_DBTR_SHMEM_INVALID_ADDR;
+       hs->shmem.phys_hi = SBI_DBTR_SHMEM_INVALID_ADDR;
+}
+
+static inline void *hart_shmem_base(void)
+{
+       struct sbi_dbtr_shmem* shmem;
+       unsigned long phys_hi, phys_lo;
+       struct sbi_dbtr_hart_triggers_state *hs = NULL;
+
+       hs = dbtr_get_hart_state_ptr(sbi_scratch_thishart_ptr());
+
+       if (!hs)
+               return NULL;
+
+       shmem = &hs->shmem;
+
+       phys_hi = (shmem->phys_hi == SBI_DBTR_SHMEM_INVALID_ADDR
+                  ? shmem->phys_hi : 0);
+       phys_lo = (shmem->phys_lo == SBI_DBTR_SHMEM_INVALID_ADDR
+                  ? 0 : shmem->phys_lo);
+
+       return ((void *)DBTR_SHMEM_MAKE_PHYS(phys_hi, 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;
+       struct sbi_dbtr_trigger *f_trig = NULL;
+       struct sbi_dbtr_hart_triggers_state *hart_state;
+
+       hart_state = dbtr_thishart_state_ptr();
+       if (!hart_state)
+               return NULL;
+
+       if (hart_state->available_trigs <= 0)
+               return NULL;
+
+       for (i = 0; i < hart_state->total_trigs; i++) {
+               f_trig = INDEX_TO_TRIGGER(i);
+               if (f_trig->state & RV_DBTR_BIT(TS, MAPPED))
+                       continue;
+               hart_state->available_trigs--;
+               break;
+       }
+
+       if (i == hart_state->total_trigs)
+               return NULL;
+
+       __set_bit(RV_DBTR_BIT(TS, MAPPED), &f_trig->state);
+
+       return f_trig;
+}
+
+static inline void sbi_free_trigger(struct sbi_dbtr_trigger *trig)
+{
+       struct sbi_dbtr_hart_triggers_state *hart_state;
+
+       if (trig == NULL)
+               return;
+
+       hart_state = dbtr_thishart_state_ptr();
+       if (!hart_state)
+               return;
+
+       trig->state = 0;
+       trig->tdata1 = 0;
+       trig->tdata2 = 0;
+       trig->tdata3 = 0;
+

lib/sbi/sbi_dbtr.c line 169

Quoted 10 lines
lib/sbi/sbi_dbtr.c new file +10 -0
+       hart_state->available_trigs++;
+}
+
+int sbi_dbtr_init(struct sbi_scratch *scratch, bool coldboot)
+{
+       struct sbi_trap_info trap = {0};
+       unsigned long tdata1;
+       unsigned long val;
+       int i;
+       struct sbi_dbtr_hart_triggers_state *hart_state = NULL;

Do nothing is Sdtrig extension is not available.

Quoted 10 lines
lib/sbi/sbi_dbtr.c new file +10 -0
+
+       if (coldboot) {
+               hart_state_ptr_offset = sbi_scratch_alloc_type_offset(void *);
+               if (!hart_state_ptr_offset)
+                       return SBI_ENOMEM;
+       }
+
+       hart_state = dbtr_get_hart_state_ptr(scratch);
+       if (!hart_state) {
+               hart_state = sbi_zalloc(sizeof(*hart_state));

lib/sbi/sbi_dbtr.c line 189

Quoted 10 lines
lib/sbi/sbi_dbtr.c new file +10 -0
+               if (!hart_state)
+                       return SBI_ENOMEM;
+               hart_state->hartid = current_hartid();
+               dbtr_set_hart_state_ptr(scratch, hart_state);
+       }
+
+       /* disable the shared memory */
+       sbi_dbtr_disable_shmem();
+
+       for (i = 0; i < RV_MAX_TRIGGERS; i++) {

This for-loop should only be done once on each HART otherwise it will increase the HART bring-up time for runtime HART hotplug.

Quoted 59 lines
lib/sbi/sbi_dbtr.c new file +59 -0
+               csr_write_allowed(CSR_TSELECT, (ulong)&trap, i);
+               if (trap.cause)
+                       break;
+
+               val = csr_read_allowed(CSR_TSELECT, (ulong)&trap);
+               if (trap.cause)
+                       break;
+
+               /*
+                * Read back tselect and check that it contains the
+                * written value
+                */
+               if (val != i)
+                       break;
+
+               val = csr_read_allowed(CSR_TINFO, (ulong)&trap);
+               if (trap.cause) {
+                       /*
+                        * If reading tinfo caused an exception, the
+                        * debugger must read tdata1 to discover the
+                        * type.
+                        */
+                       tdata1 = csr_read_allowed(CSR_TDATA1,
+                                                 (ulong)&trap);
+                       if (trap.cause)
+                               break;
+
+                       if (TDATA1_GET_TYPE(tdata1) == 0)
+                               break;
+
+                       sbi_trigger_init(INDEX_TO_TRIGGER(i),
+                                        BIT(TDATA1_GET_TYPE(tdata1)),
+                                        i);
+                       hart_state->total_trigs++;
+               } else {
+                       if (val == 1)
+                               break;
+
+                       sbi_trigger_init(INDEX_TO_TRIGGER(i), val, i);
+                       hart_state->total_trigs++;
+               }
+       }
+
+       hart_state->available_trigs = hart_state->total_trigs;
+
+       return 0;
+}
+
+int sbi_dbtr_supported(void)
+{
+       struct sbi_dbtr_hart_triggers_state *hs;
+
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return 0;
+
+       return !!hs->total_trigs;
+}
+

lib/sbi/sbi_dbtr.c line 258

Quoted 10 lines
lib/sbi/sbi_dbtr.c new file +10 -0
+int sbi_dbtr_get_total_triggers(void)
+{
+       struct sbi_dbtr_hart_triggers_state *hs;
+
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return 0;
+
+       return hs->total_trigs;
+}

sbi_dbtr_supported() and sbi_dbtr_get_total_triggers() are doing the same thing. Why not keep only one of them ?

lib/sbi/sbi_dbtr.c line 271

Quoted 13 lines
lib/sbi/sbi_dbtr.c new file +13 -0
+
+int sbi_dbtr_setup_shmem(const struct sbi_domain *dom, unsigned long smode,
+                        unsigned long shmem_phys_lo,
+                        unsigned long shmem_phys_hi)
+{
+       u32 hartid = current_hartid();
+       struct sbi_dbtr_hart_triggers_state *hart_state;
+
+       if (smode != PRV_S) {
+               sbi_dprintf("%s: Non supervisor mode. Access denied\n",
+                          __func__);
+               return SBI_ERR_DENIED;
+       }

Drop the smode parameter and check over here because on HART with just M-mode and U-mode we should allow this function.

Quoted 295 lines
lib/sbi/sbi_dbtr.c new file +295 -0
+
+       if (dom && !sbi_domain_is_assigned_hart(dom, hartid)) {
+               sbi_dprintf("%s: calling hart not assigned to this domain\n",
+                          __func__);
+               return SBI_ERR_DENIED;
+       }
+
+       /* call is to disable shared memory */
+       if (shmem_phys_lo == SBI_DBTR_SHMEM_INVALID_ADDR
+           && shmem_phys_hi == SBI_DBTR_SHMEM_INVALID_ADDR) {
+               sbi_dbtr_disable_shmem();
+               return SBI_SUCCESS;
+       }
+
+       /* the shared memory must be disabled on this hart */
+       if (!sbi_dbtr_shmem_disabled())
+               return SBI_ERR_ALREADY_AVAILABLE;
+
+       /* lower physical address must be XLEN/8 bytes aligned */
+       if (shmem_phys_lo & SBI_DBTR_SHMEM_ALIGN_MASK)
+               return SBI_ERR_INVALID_PARAM;
+
+       if (dom && !sbi_domain_check_addr(dom, shmem_phys_lo, smode,
+                                         SBI_DOMAIN_READ | SBI_DOMAIN_WRITE))
+               return SBI_ERR_INVALID_ADDRESS;
+
+       if (shmem_phys_hi != SBI_DBTR_SHMEM_INVALID_ADDR) {
+               if (dom &&
+                   !sbi_domain_check_addr(dom, shmem_phys_hi, smode,
+                                          SBI_DOMAIN_READ | SBI_DOMAIN_WRITE))
+                       return SBI_ERR_INVALID_ADDRESS;
+       }
+
+       hart_state = dbtr_thishart_state_ptr();
+       if (!hart_state)
+               return SBI_ERR_FAILED;
+
+       hart_state->shmem.phys_lo = shmem_phys_lo;
+       hart_state->shmem.phys_hi = shmem_phys_hi;
+
+       return SBI_SUCCESS;
+}
+
+static void dbtr_trigger_setup(struct sbi_dbtr_trigger *trig,
+                              struct sbi_dbtr_data_msg *recv)
+{
+       unsigned long tdata1;
+
+       if (!trig)
+               return;
+
+       trig->tdata1 = lle_to_cpu(recv->tdata1);
+       trig->tdata2 = lle_to_cpu(recv->tdata2);
+       trig->tdata3 = lle_to_cpu(recv->tdata3);
+
+       tdata1 = lle_to_cpu(recv->tdata1);
+
+       trig->state = 0;
+
+       __set_bit(RV_DBTR_BIT(TS, MAPPED), &trig->state);
+
+       SET_TRIG_HW_INDEX(trig->state, trig->index);
+
+       switch (TDATA1_GET_TYPE(tdata1)) {
+       case RISCV_DBTR_TRIG_MCONTROL:
+               if (__test_bit(RV_DBTR_BIT(MC, U), &tdata1))
+                       __set_bit(RV_DBTR_BIT(TS, U), &trig->state);
+
+               if (__test_bit(RV_DBTR_BIT(MC, S), &tdata1))
+                       __set_bit(RV_DBTR_BIT(TS, S), &trig->state);
+               break;
+       case RISCV_DBTR_TRIG_MCONTROL6:
+               if (__test_bit(RV_DBTR_BIT(MC6, U), &tdata1))
+                       __set_bit(RV_DBTR_BIT(TS, U), &trig->state);
+
+               if (__test_bit(RV_DBTR_BIT(MC6, S), &tdata1))
+                       __set_bit(RV_DBTR_BIT(TS, S), &trig->state);
+
+               if (__test_bit(RV_DBTR_BIT(MC6, VU), &tdata1))
+                       __set_bit(RV_DBTR_BIT(TS, VU), &trig->state);
+
+               if (__test_bit(RV_DBTR_BIT(MC6, 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));
+               break;
+       }
+}
+
+static inline void update_bit(unsigned long new, int nr, volatile unsigned long *addr)
+{
+       if (new)
+               __set_bit(nr, addr);
+       else
+               __clear_bit(nr, addr);
+}
+
+static void dbtr_trigger_enable(struct sbi_dbtr_trigger *trig)
+{
+       unsigned long state;
+       unsigned long tdata1;
+
+       if (!trig && !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
+               return;
+
+       state = trig->state;
+       tdata1 = trig->tdata1;
+
+       switch (TDATA1_GET_TYPE(tdata1)) {
+       case RISCV_DBTR_TRIG_MCONTROL:
+               update_bit(state & RV_DBTR_BIT_MASK(TS, U),
+                          RV_DBTR_BIT(MC, U), &trig->tdata1);
+               update_bit(state & RV_DBTR_BIT_MASK(TS, S),
+                          RV_DBTR_BIT(MC, S), &trig->tdata1);
+               break;
+       case RISCV_DBTR_TRIG_MCONTROL6:
+               update_bit(state & RV_DBTR_BIT_MASK(TS, VU),
+                          RV_DBTR_BIT(MC6, VU), &trig->tdata1);
+               update_bit(state & RV_DBTR_BIT_MASK(TS, VS),
+                          RV_DBTR_BIT(MC6, VS), &trig->tdata1);
+               update_bit(state & RV_DBTR_BIT_MASK(TS, U),
+                          RV_DBTR_BIT(MC6, U), &trig->tdata1);
+               update_bit(state & RV_DBTR_BIT_MASK(TS, S),
+                          RV_DBTR_BIT(MC6, S), &trig->tdata1);
+               break;
+       default:
+               break;
+       }
+
+       /*
+        * RISC-V Debug Support v1.0.0 section 5.5:
+        * Debugger cannot simply set a trigger by writing tdata1, then tdata2,
+        * etc. The current value of tdata2 might not be legal with the new
+        * value of tdata1. To help with this situation, it is guaranteed that
+        * writing 0 to tdata1 disables the trigger, and leaves it in a state
+        * 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_TDATA1, 0x0);
+       csr_write(CSR_TDATA2, trig->tdata2);
+       csr_write(CSR_TDATA1, trig->tdata1);
+}
+
+static void dbtr_trigger_disable(struct sbi_dbtr_trigger *trig)
+{
+       unsigned long tdata1;
+
+       if (!trig && !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
+               return;
+
+       tdata1 = trig->tdata1;
+
+       switch (TDATA1_GET_TYPE(tdata1)) {
+       case RISCV_DBTR_TRIG_MCONTROL:
+               __clear_bit(RV_DBTR_BIT(MC, U), &trig->tdata1);
+               __clear_bit(RV_DBTR_BIT(MC, S), &trig->tdata1);
+               break;
+       case RISCV_DBTR_TRIG_MCONTROL6:
+               __clear_bit(RV_DBTR_BIT(MC6, VU), &trig->tdata1);
+               __clear_bit(RV_DBTR_BIT(MC6, VS), &trig->tdata1);
+               __clear_bit(RV_DBTR_BIT(MC6, U), &trig->tdata1);
+               __clear_bit(RV_DBTR_BIT(MC6, S), &trig->tdata1);
+               break;
+       default:
+               break;
+       }
+
+       csr_write(CSR_TSELECT, trig->index);
+       csr_write(CSR_TDATA1, trig->tdata1);
+}
+
+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_TDATA1, 0x0);
+       csr_write(CSR_TDATA2, 0x0);
+}
+
+static int dbtr_trigger_supported(unsigned long type)
+{
+       switch (type) {
+       case RISCV_DBTR_TRIG_MCONTROL:
+       case RISCV_DBTR_TRIG_MCONTROL6:
+               return 1;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int dbtr_trigger_valid(unsigned long type, unsigned long tdata)
+{
+       switch (type) {
+       case RISCV_DBTR_TRIG_MCONTROL:
+               if (!(tdata & RV_DBTR_BIT_MASK(MC, DMODE)) &&
+                   !(tdata & RV_DBTR_BIT_MASK(MC, M)))
+                       return 1;
+               break;
+       case RISCV_DBTR_TRIG_MCONTROL6:
+               if (!(tdata & RV_DBTR_BIT_MASK(MC6, DMODE)) &&
+                   !(tdata & RV_DBTR_BIT_MASK(MC6, M)))
+                       return 1;
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+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;
+       int i;
+       struct sbi_dbtr_hart_triggers_state *hs;
+
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return SBI_ERR_FAILED;
+
+       if (data == 0) {
+               *out = hs->total_trigs;
+               return SBI_SUCCESS;
+       }
+
+       for (i = 0; i < hs->total_trigs; i++) {
+               trig = INDEX_TO_TRIGGER(i);
+
+               if (__test_bit(type, &trig->type_mask))
+                       total++;
+       }
+
+       sbi_dprintf("%s: hart%d: total triggers of type %lu: %lu\n",
+                   __func__, hartid, type, total);
+
+       *out = total;
+       return SBI_SUCCESS;
+}
+
+int sbi_dbtr_read_trig(const struct sbi_domain *dom, unsigned long smode,
+                      unsigned long trig_idx_base, unsigned long trig_count)
+{
+       struct sbi_dbtr_data_msg *xmit;
+       u32 hartid = current_hartid();
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_shmem_entry *entry;
+       void *shmem_base = NULL;
+       struct sbi_dbtr_hart_triggers_state *hs = NULL;
+
+       if (smode != PRV_S)
+               return SBI_ERR_DENIED;
+       if (dom && !sbi_domain_is_assigned_hart(dom, hartid))
+               return SBI_ERR_DENIED;
+
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return SBI_ERR_FAILED;
+
+       if (trig_idx_base >= hs->total_trigs ||
+           trig_idx_base + trig_count >= hs->total_trigs)
+               return SBI_ERR_INVALID_PARAM;
+
+       if (sbi_dbtr_shmem_disabled())
+               return SBI_ERR_NO_SHMEM;
+
+       shmem_base = hart_shmem_base();
+
+       for_each_trig_entry(shmem_base, trig_count, typeof(*entry), entry) {
+               sbi_hart_map_saddr((unsigned long)entry, sizeof(*entry));
+               xmit = &entry->data;
+               trig = INDEX_TO_TRIGGER((_idx + trig_idx_base));
+               xmit->tstate = cpu_to_lle(trig->state);
+               xmit->tdata1 = cpu_to_lle(trig->tdata1);
+               xmit->tdata2 = cpu_to_lle(trig->tdata2);
+               xmit->tdata3 = cpu_to_lle(trig->tdata3);
+               sbi_hart_unmap_saddr();
+       }
+
+       return SBI_SUCCESS;
+}
+
+int sbi_dbtr_install_trig(const struct sbi_domain *dom, unsigned long smode,
+                         unsigned long trig_count, unsigned long *out)
+{
+       u32 hartid = current_hartid();

lib/sbi/sbi_dbtr.c line 576

Quoted 10 lines
lib/sbi/sbi_dbtr.c new file +10 -0
+       void *shmem_base = NULL;
+       struct sbi_dbtr_shmem_entry *entry;
+       struct sbi_dbtr_data_msg *recv;
+       struct sbi_dbtr_id_msg *xmit;
+       unsigned long ctrl;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_hart_triggers_state *hs = NULL;
+
+       if (smode != PRV_S)
+               return SBI_ERR_DENIED;

Same as above, drop the smode check and parameter.

Quoted 109 lines
lib/sbi/sbi_dbtr.c new file +109 -0
+       if (dom && !sbi_domain_is_assigned_hart(dom, hartid))
+               return SBI_ERR_DENIED;
+
+       if (sbi_dbtr_shmem_disabled())
+               return SBI_ERR_NO_SHMEM;
+
+       shmem_base = hart_shmem_base();
+       hs = dbtr_thishart_state_ptr();
+
+       /* Check requested triggers configuration */
+       for_each_trig_entry(shmem_base, trig_count, typeof(*entry), entry) {
+               sbi_hart_map_saddr((unsigned long)entry, sizeof(*entry));
+               recv = (struct sbi_dbtr_data_msg *)(&entry->data);
+               ctrl = recv->tdata1;
+
+               if (!dbtr_trigger_supported(TDATA1_GET_TYPE(ctrl))) {
+                       *out = _idx;
+                       sbi_hart_unmap_saddr();
+                       return SBI_ERR_FAILED;
+               }
+
+               if (!dbtr_trigger_valid(TDATA1_GET_TYPE(ctrl), ctrl)) {
+                       *out = _idx;
+                       sbi_hart_unmap_saddr();
+                       return SBI_ERR_FAILED;
+               }
+               sbi_hart_unmap_saddr();
+       }
+
+       if (hs->available_trigs < trig_count) {
+               *out = hs->available_trigs;
+               return SBI_ERR_FAILED;
+       }
+
+       /* Install triggers */
+       for_each_trig_entry(shmem_base, trig_count, typeof(*entry), entry) {
+               /*
+                * Since we have already checked if enough triggers are
+                * available, trigger allocation must succeed.
+                */
+               trig = sbi_alloc_trigger();
+
+               sbi_hart_map_saddr((unsigned long)entry, sizeof(*entry));
+
+               recv = (struct sbi_dbtr_data_msg *)(&entry->data);
+               xmit = (struct sbi_dbtr_id_msg *)(&entry->id);
+
+               dbtr_trigger_setup(trig,  recv);
+               dbtr_trigger_enable(trig);
+               xmit->idx = cpu_to_lle(trig->index);
+               sbi_hart_unmap_saddr();
+       }
+
+       return SBI_SUCCESS;
+}
+
+int sbi_dbtr_uninstall_trig(unsigned long trig_idx_base,
+                           unsigned long trig_idx_mask)
+{
+       unsigned long trig_mask = trig_idx_mask << trig_idx_base;
+       unsigned long idx = trig_idx_base;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_hart_triggers_state *hs;
+
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return SBI_ERR_FAILED;
+
+       for_each_set_bit_from(idx, &trig_mask, hs->total_trigs) {
+               trig = INDEX_TO_TRIGGER(idx);
+               if (!(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
+                       return SBI_ERR_INVALID_PARAM;
+
+               dbtr_trigger_clear(trig);
+
+               sbi_free_trigger(trig);
+       }
+
+       return SBI_SUCCESS;
+}
+
+int sbi_dbtr_enable_trig(unsigned long trig_idx_base,
+                        unsigned long trig_idx_mask)
+{
+       unsigned long trig_mask = trig_idx_mask << trig_idx_base;
+       unsigned long idx = trig_idx_base;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_hart_triggers_state *hs;
+
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return SBI_ERR_FAILED;
+
+       for_each_set_bit_from(idx, &trig_mask, hs->total_trigs) {
+               trig = INDEX_TO_TRIGGER(idx);
+               sbi_dprintf("%s: enable trigger %lu\n", __func__, idx);
+               dbtr_trigger_enable(trig);
+       }
+
+       return SBI_SUCCESS;
+}
+
+int sbi_dbtr_update_trig(const struct sbi_domain *dom,
+                        unsigned long smode,
+                        unsigned long trig_idx_base,
+                        unsigned long trig_idx_mask)
+{
+       unsigned long trig_mask = trig_idx_mask << trig_idx_base;
+       unsigned long idx = trig_idx_base;

lib/sbi/sbi_dbtr.c line 695

Quoted 10 lines
lib/sbi/sbi_dbtr.c new file +10 -0
+       u32 hartid = current_hartid();
+       struct sbi_dbtr_data_msg *recv;
+       unsigned long uidx = 0;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_shmem_entry *entry;
+       void *shmem_base = NULL;
+       struct sbi_dbtr_hart_triggers_state *hs = NULL;
+
+       if (smode != PRV_S)
+               return SBI_ERR_DENIED;

Same as above, drop the smode check and parameter.

Quoted 85 lines
lib/sbi/sbi_dbtr.c new file +47 -0
+       if (dom && !sbi_domain_is_assigned_hart(dom, hartid))
+               return SBI_ERR_DENIED;
+
+       if (sbi_dbtr_shmem_disabled())
+               return SBI_ERR_NO_SHMEM;
+
+       shmem_base = hart_shmem_base();
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return SBI_ERR_FAILED;
+
+       for_each_set_bit_from(idx, &trig_mask, hs->total_trigs) {
+               trig = INDEX_TO_TRIGGER(idx);
+
+               if (!(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
+                       return SBI_ERR_INVALID_PARAM;
+
+               entry = (shmem_base + uidx * sizeof(*entry));
+               recv = &entry->data;
+
+               trig->tdata2 = lle_to_cpu(recv->tdata2);
+               dbtr_trigger_enable(trig);
+               uidx++;
+       }
+
+       return SBI_SUCCESS;
+}
+
+int sbi_dbtr_disable_trig(unsigned long trig_idx_base,
+                         unsigned long trig_idx_mask)
+{
+       unsigned long trig_mask = trig_idx_mask << trig_idx_base;
+       unsigned long idx = trig_idx_base;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_hart_triggers_state *hs;
+
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return SBI_ERR_FAILED;
+
+       for_each_set_bit_from(idx, &trig_mask, hs->total_trigs) {
+               trig = INDEX_TO_TRIGGER(idx);
+               dbtr_trigger_disable(trig);
+       }
+
+       return SBI_SUCCESS;
+}
lib/sbi/sbi_init.c +9 -1
index 6a98e13..0dcde27 100644
@@ -23,6 +23,7 @@
 #include <sbi/sbi_irqchip.h>
 #include <sbi/sbi_platform.h>
 #include <sbi/sbi_pmu.h>
+#include <sbi/sbi_dbtr.h>
 #include <sbi/sbi_system.h>
 #include <sbi/sbi_string.h>
 #include <sbi/sbi_timer.h>
@@ -322,6 +323,10 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
                sbi_hart_hang();
        }
 
+       rc = sbi_dbtr_init(scratch, true);
+       if (rc)
+               sbi_hart_hang();
+
        sbi_boot_print_banner(scratch);
 
        rc = sbi_irqchip_init(scratch, true);
@@ -439,6 +444,10 @@ static void __noreturn init_warm_startup(struct sbi_scratch *scratch,
        if (rc)
                sbi_hart_hang();
 
+       rc = sbi_dbtr_init(scratch, false);
+       if (rc)
+               sbi_hart_hang();
+
        rc = sbi_irqchip_init(scratch, false);
        if (rc)
                sbi_hart_hang();
--

2.34.1

Quoted 4 lines

--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

Regards,
Anup

#9 lore raw

PATCH v2 4/7 lib: sbi: Introduce the SBI debug triggers extension support

Hi Anup,

Quoted 3 lines · Anup Patel
Quoted 2 lines

<snip>

Quoted 8 lines
Quoted 8 lines
lib/sbi/sbi_dbtr.c new file +8 -0
+int sbi_dbtr_install_trig(const struct sbi_domain *dom, unsigned long smode,
+                         unsigned long trig_count, unsigned long *out)
+{
+       u32 hartid = current_hartid();
+       void *shmem_base = NULL;
+       struct sbi_dbtr_shmem_entry *entry;
+       struct sbi_dbtr_data_msg *recv;
+       struct sbi_dbtr_id_msg *xmit;
Quoted 8 lines

lib/sbi/sbi_dbtr.c line 576

Quoted 6 lines
lib/sbi/sbi_dbtr.c new file +6 -0
+       unsigned long ctrl;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_hart_triggers_state *hs = NULL;
+
+       if (smode != PRV_S)
+               return SBI_ERR_DENIED;

Same as above, drop the smode check and parameter.

We cannot completely drop the smode parameter here because it is used for domain address access validation. The check of S_PRV can be dropped.

Regards
Himanshu

Quoted 215 lines
Quoted 110 lines
lib/sbi/sbi_dbtr.c new file +109 -0
+       if (dom && !sbi_domain_is_assigned_hart(dom, hartid))
+               return SBI_ERR_DENIED;
+
+       if (sbi_dbtr_shmem_disabled())
+               return SBI_ERR_NO_SHMEM;
+
+       shmem_base = hart_shmem_base();
+       hs = dbtr_thishart_state_ptr();
+
+       /* Check requested triggers configuration */
+       for_each_trig_entry(shmem_base, trig_count, typeof(*entry), entry) {
+               sbi_hart_map_saddr((unsigned long)entry, sizeof(*entry));
+               recv = (struct sbi_dbtr_data_msg *)(&entry->data);
+               ctrl = recv->tdata1;
+
+               if (!dbtr_trigger_supported(TDATA1_GET_TYPE(ctrl))) {
+                       *out = _idx;
+                       sbi_hart_unmap_saddr();
+                       return SBI_ERR_FAILED;
+               }
+
+               if (!dbtr_trigger_valid(TDATA1_GET_TYPE(ctrl), ctrl)) {
+                       *out = _idx;
+                       sbi_hart_unmap_saddr();
+                       return SBI_ERR_FAILED;
+               }
+               sbi_hart_unmap_saddr();
+       }
+
+       if (hs->available_trigs < trig_count) {
+               *out = hs->available_trigs;
+               return SBI_ERR_FAILED;
+       }
+
+       /* Install triggers */
+       for_each_trig_entry(shmem_base, trig_count, typeof(*entry), entry) {
+               /*
+                * Since we have already checked if enough triggers are
+                * available, trigger allocation must succeed.
+                */
+               trig = sbi_alloc_trigger();
+
+               sbi_hart_map_saddr((unsigned long)entry, sizeof(*entry));
+
+               recv = (struct sbi_dbtr_data_msg *)(&entry->data);
+               xmit = (struct sbi_dbtr_id_msg *)(&entry->id);
+
+               dbtr_trigger_setup(trig,  recv);
+               dbtr_trigger_enable(trig);
+               xmit->idx = cpu_to_lle(trig->index);
+               sbi_hart_unmap_saddr();
+       }
+
+       return SBI_SUCCESS;
+}
+
+int sbi_dbtr_uninstall_trig(unsigned long trig_idx_base,
+                           unsigned long trig_idx_mask)
+{
+       unsigned long trig_mask = trig_idx_mask << trig_idx_base;
+       unsigned long idx = trig_idx_base;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_hart_triggers_state *hs;
+
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return SBI_ERR_FAILED;
+
+       for_each_set_bit_from(idx, &trig_mask, hs->total_trigs) {
+               trig = INDEX_TO_TRIGGER(idx);
+               if (!(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
+                       return SBI_ERR_INVALID_PARAM;
+
+               dbtr_trigger_clear(trig);
+
+               sbi_free_trigger(trig);
+       }
+
+       return SBI_SUCCESS;
+}
+
+int sbi_dbtr_enable_trig(unsigned long trig_idx_base,
+                        unsigned long trig_idx_mask)
+{
+       unsigned long trig_mask = trig_idx_mask << trig_idx_base;
+       unsigned long idx = trig_idx_base;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_hart_triggers_state *hs;
+
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return SBI_ERR_FAILED;
+
+       for_each_set_bit_from(idx, &trig_mask, hs->total_trigs) {
+               trig = INDEX_TO_TRIGGER(idx);
+               sbi_dprintf("%s: enable trigger %lu\n", __func__, idx);
+               dbtr_trigger_enable(trig);
+       }
+
+       return SBI_SUCCESS;
+}
+
+int sbi_dbtr_update_trig(const struct sbi_domain *dom,
+                        unsigned long smode,
+                        unsigned long trig_idx_base,
+                        unsigned long trig_idx_mask)
+{
+       unsigned long trig_mask = trig_idx_mask << trig_idx_base;
+       unsigned long idx = trig_idx_base;

lib/sbi/sbi_dbtr.c line 695

Quoted 10 lines
lib/sbi/sbi_dbtr.c new file +10 -0
+       u32 hartid = current_hartid();
+       struct sbi_dbtr_data_msg *recv;
+       unsigned long uidx = 0;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_shmem_entry *entry;
+       void *shmem_base = NULL;
+       struct sbi_dbtr_hart_triggers_state *hs = NULL;
+
+       if (smode != PRV_S)
+               return SBI_ERR_DENIED;

Same as above, drop the smode check and parameter.

Quoted 85 lines
lib/sbi/sbi_dbtr.c new file +47 -0
+       if (dom && !sbi_domain_is_assigned_hart(dom, hartid))
+               return SBI_ERR_DENIED;
+
+       if (sbi_dbtr_shmem_disabled())
+               return SBI_ERR_NO_SHMEM;
+
+       shmem_base = hart_shmem_base();
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return SBI_ERR_FAILED;
+
+       for_each_set_bit_from(idx, &trig_mask, hs->total_trigs) {
+               trig = INDEX_TO_TRIGGER(idx);
+
+               if (!(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
+                       return SBI_ERR_INVALID_PARAM;
+
+               entry = (shmem_base + uidx * sizeof(*entry));
+               recv = &entry->data;
+
+               trig->tdata2 = lle_to_cpu(recv->tdata2);
+               dbtr_trigger_enable(trig);
+               uidx++;
+       }
+
+       return SBI_SUCCESS;
+}
+
+int sbi_dbtr_disable_trig(unsigned long trig_idx_base,
+                         unsigned long trig_idx_mask)
+{
+       unsigned long trig_mask = trig_idx_mask << trig_idx_base;
+       unsigned long idx = trig_idx_base;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_hart_triggers_state *hs;
+
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return SBI_ERR_FAILED;
+
+       for_each_set_bit_from(idx, &trig_mask, hs->total_trigs) {
+               trig = INDEX_TO_TRIGGER(idx);
+               dbtr_trigger_disable(trig);
+       }
+
+       return SBI_SUCCESS;
+}
lib/sbi/sbi_init.c +9 -1
index 6a98e13..0dcde27 100644
@@ -23,6 +23,7 @@
 #include <sbi/sbi_irqchip.h>
 #include <sbi/sbi_platform.h>
 #include <sbi/sbi_pmu.h>
+#include <sbi/sbi_dbtr.h>
 #include <sbi/sbi_system.h>
 #include <sbi/sbi_string.h>
 #include <sbi/sbi_timer.h>
@@ -322,6 +323,10 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
               sbi_hart_hang();
       }
 
+       rc = sbi_dbtr_init(scratch, true);
+       if (rc)
+               sbi_hart_hang();
+
       sbi_boot_print_banner(scratch);
 
       rc = sbi_irqchip_init(scratch, true);
@@ -439,6 +444,10 @@ static void __noreturn init_warm_startup(struct sbi_scratch *scratch,
       if (rc)
               sbi_hart_hang();
 
+       rc = sbi_dbtr_init(scratch, false);
+       if (rc)
+               sbi_hart_hang();
+
       rc = sbi_irqchip_init(scratch, false);
       if (rc)
               sbi_hart_hang();
--

2.34.1

Quoted 4 lines

--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

Regards,
Anup

#10 lore raw

PATCH v2 4/7 lib: sbi: Introduce the SBI debug triggers extension support

Quoted 26 lines · On Tue, Jan 9, 2024 at 9:01?PM Himanshu Chauhan <[email protected]>…

Hi Anup,

Quoted 3 lines · Anup Patel
Quoted 2 lines

<snip>

Quoted 8 lines
Quoted 8 lines
lib/sbi/sbi_dbtr.c new file +8 -0
+int sbi_dbtr_install_trig(const struct sbi_domain *dom, unsigned long smode,
+                         unsigned long trig_count, unsigned long *out)
+{
+       u32 hartid = current_hartid();
+       void *shmem_base = NULL;
+       struct sbi_dbtr_shmem_entry *entry;
+       struct sbi_dbtr_data_msg *recv;
+       struct sbi_dbtr_id_msg *xmit;
Quoted 8 lines

lib/sbi/sbi_dbtr.c line 576

Quoted 6 lines
lib/sbi/sbi_dbtr.c new file +6 -0
+       unsigned long ctrl;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_hart_triggers_state *hs = NULL;
+
+       if (smode != PRV_S)
+               return SBI_ERR_DENIED;

Same as above, drop the smode check and parameter.

Quoted 1 line

We cannot completely drop the smode parameter here because it is used for domain address access validation. The check of S_PRV can be dropped.

Okay, at least drop the sanity check.

Regards,
Anup

Quoted 221 lines

Regards
Himanshu

Quoted 215 lines
Quoted 110 lines
lib/sbi/sbi_dbtr.c new file +109 -0
+       if (dom && !sbi_domain_is_assigned_hart(dom, hartid))
+               return SBI_ERR_DENIED;
+
+       if (sbi_dbtr_shmem_disabled())
+               return SBI_ERR_NO_SHMEM;
+
+       shmem_base = hart_shmem_base();
+       hs = dbtr_thishart_state_ptr();
+
+       /* Check requested triggers configuration */
+       for_each_trig_entry(shmem_base, trig_count, typeof(*entry), entry) {
+               sbi_hart_map_saddr((unsigned long)entry, sizeof(*entry));
+               recv = (struct sbi_dbtr_data_msg *)(&entry->data);
+               ctrl = recv->tdata1;
+
+               if (!dbtr_trigger_supported(TDATA1_GET_TYPE(ctrl))) {
+                       *out = _idx;
+                       sbi_hart_unmap_saddr();
+                       return SBI_ERR_FAILED;
+               }
+
+               if (!dbtr_trigger_valid(TDATA1_GET_TYPE(ctrl), ctrl)) {
+                       *out = _idx;
+                       sbi_hart_unmap_saddr();
+                       return SBI_ERR_FAILED;
+               }
+               sbi_hart_unmap_saddr();
+       }
+
+       if (hs->available_trigs < trig_count) {
+               *out = hs->available_trigs;
+               return SBI_ERR_FAILED;
+       }
+
+       /* Install triggers */
+       for_each_trig_entry(shmem_base, trig_count, typeof(*entry), entry) {
+               /*
+                * Since we have already checked if enough triggers are
+                * available, trigger allocation must succeed.
+                */
+               trig = sbi_alloc_trigger();
+
+               sbi_hart_map_saddr((unsigned long)entry, sizeof(*entry));
+
+               recv = (struct sbi_dbtr_data_msg *)(&entry->data);
+               xmit = (struct sbi_dbtr_id_msg *)(&entry->id);
+
+               dbtr_trigger_setup(trig,  recv);
+               dbtr_trigger_enable(trig);
+               xmit->idx = cpu_to_lle(trig->index);
+               sbi_hart_unmap_saddr();
+       }
+
+       return SBI_SUCCESS;
+}
+
+int sbi_dbtr_uninstall_trig(unsigned long trig_idx_base,
+                           unsigned long trig_idx_mask)
+{
+       unsigned long trig_mask = trig_idx_mask << trig_idx_base;
+       unsigned long idx = trig_idx_base;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_hart_triggers_state *hs;
+
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return SBI_ERR_FAILED;
+
+       for_each_set_bit_from(idx, &trig_mask, hs->total_trigs) {
+               trig = INDEX_TO_TRIGGER(idx);
+               if (!(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
+                       return SBI_ERR_INVALID_PARAM;
+
+               dbtr_trigger_clear(trig);
+
+               sbi_free_trigger(trig);
+       }
+
+       return SBI_SUCCESS;
+}
+
+int sbi_dbtr_enable_trig(unsigned long trig_idx_base,
+                        unsigned long trig_idx_mask)
+{
+       unsigned long trig_mask = trig_idx_mask << trig_idx_base;
+       unsigned long idx = trig_idx_base;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_hart_triggers_state *hs;
+
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return SBI_ERR_FAILED;
+
+       for_each_set_bit_from(idx, &trig_mask, hs->total_trigs) {
+               trig = INDEX_TO_TRIGGER(idx);
+               sbi_dprintf("%s: enable trigger %lu\n", __func__, idx);
+               dbtr_trigger_enable(trig);
+       }
+
+       return SBI_SUCCESS;
+}
+
+int sbi_dbtr_update_trig(const struct sbi_domain *dom,
+                        unsigned long smode,
+                        unsigned long trig_idx_base,
+                        unsigned long trig_idx_mask)
+{
+       unsigned long trig_mask = trig_idx_mask << trig_idx_base;
+       unsigned long idx = trig_idx_base;

lib/sbi/sbi_dbtr.c line 695

Quoted 10 lines
lib/sbi/sbi_dbtr.c new file +10 -0
+       u32 hartid = current_hartid();
+       struct sbi_dbtr_data_msg *recv;
+       unsigned long uidx = 0;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_shmem_entry *entry;
+       void *shmem_base = NULL;
+       struct sbi_dbtr_hart_triggers_state *hs = NULL;
+
+       if (smode != PRV_S)
+               return SBI_ERR_DENIED;

Same as above, drop the smode check and parameter.

Quoted 85 lines
lib/sbi/sbi_dbtr.c new file +47 -0
+       if (dom && !sbi_domain_is_assigned_hart(dom, hartid))
+               return SBI_ERR_DENIED;
+
+       if (sbi_dbtr_shmem_disabled())
+               return SBI_ERR_NO_SHMEM;
+
+       shmem_base = hart_shmem_base();
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return SBI_ERR_FAILED;
+
+       for_each_set_bit_from(idx, &trig_mask, hs->total_trigs) {
+               trig = INDEX_TO_TRIGGER(idx);
+
+               if (!(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
+                       return SBI_ERR_INVALID_PARAM;
+
+               entry = (shmem_base + uidx * sizeof(*entry));
+               recv = &entry->data;
+
+               trig->tdata2 = lle_to_cpu(recv->tdata2);
+               dbtr_trigger_enable(trig);
+               uidx++;
+       }
+
+       return SBI_SUCCESS;
+}
+
+int sbi_dbtr_disable_trig(unsigned long trig_idx_base,
+                         unsigned long trig_idx_mask)
+{
+       unsigned long trig_mask = trig_idx_mask << trig_idx_base;
+       unsigned long idx = trig_idx_base;
+       struct sbi_dbtr_trigger *trig;
+       struct sbi_dbtr_hart_triggers_state *hs;
+
+       hs = dbtr_thishart_state_ptr();
+       if (!hs)
+               return SBI_ERR_FAILED;
+
+       for_each_set_bit_from(idx, &trig_mask, hs->total_trigs) {
+               trig = INDEX_TO_TRIGGER(idx);
+               dbtr_trigger_disable(trig);
+       }
+
+       return SBI_SUCCESS;
+}
lib/sbi/sbi_init.c +9 -1
index 6a98e13..0dcde27 100644
@@ -23,6 +23,7 @@
 #include <sbi/sbi_irqchip.h>
 #include <sbi/sbi_platform.h>
 #include <sbi/sbi_pmu.h>
+#include <sbi/sbi_dbtr.h>
 #include <sbi/sbi_system.h>
 #include <sbi/sbi_string.h>
 #include <sbi/sbi_timer.h>
@@ -322,6 +323,10 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
               sbi_hart_hang();
       }
 
+       rc = sbi_dbtr_init(scratch, true);
+       if (rc)
+               sbi_hart_hang();
+
       sbi_boot_print_banner(scratch);
 
       rc = sbi_irqchip_init(scratch, true);
@@ -439,6 +444,10 @@ static void __noreturn init_warm_startup(struct sbi_scratch *scratch,
       if (rc)
               sbi_hart_hang();
 
+       rc = sbi_dbtr_init(scratch, false);
+       if (rc)
+               sbi_hart_hang();
+
       rc = sbi_irqchip_init(scratch, false);
       if (rc)
               sbi_hart_hang();
--

2.34.1

Quoted 4 lines

--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

Regards,
Anup

#11 lore raw

PATCH v2 5/7 include: sbi: Add SBI debug trigger extension related defines

In reply to Himanshu Chauhan

This patch adds defines for SBI debug trigger extension and function IDs to access the extension.

---
 include/sbi/sbi_ecall_interface.h | 11 +++++++++++
 1 file changed, 11 insertions(+)
include/sbi/sbi_ecall_interface.h +11 -0
index d8c646d..690c31b 100644
@@ -32,6 +32,7 @@
 #define SBI_EXT_DBCN				0x4442434E
 #define SBI_EXT_SUSP				0x53555350
 #define SBI_EXT_CPPC				0x43505043
+#define SBI_EXT_DBTR				0x44425452
 
 /* SBI function IDs for BASE extension*/
 #define SBI_EXT_BASE_GET_SPEC_VERSION		0x0
@@ -105,6 +106,16 @@
 #define SBI_EXT_PMU_COUNTER_FW_READ_HI	0x6
 #define SBI_EXT_PMU_SNAPSHOT_SET_SHMEM	0x7
 
+/* SBI function IDs for DBTR extension */
+#define SBI_EXT_DBTR_NUM_TRIGGERS	0x0
+#define SBI_EXT_DBTR_SETUP_SHMEM	0x1
+#define SBI_EXT_DBTR_TRIGGER_READ	0x2
+#define SBI_EXT_DBTR_TRIGGER_INSTALL	0x3
+#define SBI_EXT_DBTR_TRIGGER_UPDATE	0x4
+#define SBI_EXT_DBTR_TRIGGER_UNINSTALL	0x5
+#define SBI_EXT_DBTR_TRIGGER_ENABLE	0x6
+#define SBI_EXT_DBTR_TRIGGER_DISABLE	0x7
+
 /** General pmu event codes specified in SBI PMU extension */
 enum sbi_pmu_hw_generic_events_t {
 	SBI_PMU_HW_NO_EVENT			= 0,
Signature · 1 line
2.34.1
#12 lore raw

PATCH v2 5/7 include: sbi: Add SBI debug trigger extension related defines

Quoted 5 lines · On Mon, Jan 8, 2024 at 12:25?PM Himanshu Chauhan <[email protected]>…

This patch adds defines for SBI debug trigger extension and function IDs to access the extension.

Already reviewed previously.

Regards,
Anup

Quoted 41 lines
---
 include/sbi/sbi_ecall_interface.h | 11 +++++++++++
 1 file changed, 11 insertions(+)
include/sbi/sbi_ecall_interface.h +11 -1
index d8c646d..690c31b 100644
@@ -32,6 +32,7 @@
 #define SBI_EXT_DBCN                           0x4442434E
 #define SBI_EXT_SUSP                           0x53555350
 #define SBI_EXT_CPPC                           0x43505043
+#define SBI_EXT_DBTR                           0x44425452
 
 /* SBI function IDs for BASE extension*/
 #define SBI_EXT_BASE_GET_SPEC_VERSION          0x0
@@ -105,6 +106,16 @@
 #define SBI_EXT_PMU_COUNTER_FW_READ_HI 0x6
 #define SBI_EXT_PMU_SNAPSHOT_SET_SHMEM 0x7
 
+/* SBI function IDs for DBTR extension */
+#define SBI_EXT_DBTR_NUM_TRIGGERS      0x0
+#define SBI_EXT_DBTR_SETUP_SHMEM       0x1
+#define SBI_EXT_DBTR_TRIGGER_READ      0x2
+#define SBI_EXT_DBTR_TRIGGER_INSTALL   0x3
+#define SBI_EXT_DBTR_TRIGGER_UPDATE    0x4
+#define SBI_EXT_DBTR_TRIGGER_UNINSTALL 0x5
+#define SBI_EXT_DBTR_TRIGGER_ENABLE    0x6
+#define SBI_EXT_DBTR_TRIGGER_DISABLE   0x7
+
 /** General pmu event codes specified in SBI PMU extension */
 enum sbi_pmu_hw_generic_events_t {
        SBI_PMU_HW_NO_EVENT                     = 0,
--

2.34.1

--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

#13 lore raw

PATCH v2 6/7 lib: sbi: Implement SBI debug trigger extension

In reply to Himanshu Chauhan

This patch adds functions to register ecalls for debug triggers and handler to handle the debug trigger function IDs.

---
 lib/sbi/Kconfig          |  4 +++
 lib/sbi/objects.mk       |  3 ++
 lib/sbi/sbi_ecall_dbtr.c | 73 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+)
 create mode 100644 lib/sbi/sbi_ecall_dbtr.c
lib/sbi/Kconfig +4 -0
index 477775e..81dd2db 100644
@@ -46,4 +46,8 @@ config SBI_ECALL_VENDOR
 	bool "Platform-defined vendor extensions"
 	default y
 
+config SBI_ECALL_DBTR
+	bool "Debug Trigger Extension"
+	default y
+
 endmenu
lib/sbi/objects.mk +3 -0
index c7de150..0a50e95 100644
@@ -52,6 +52,9 @@ libsbi-objs-$(CONFIG_SBI_ECALL_LEGACY) += sbi_ecall_legacy.o
 carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_VENDOR) += ecall_vendor
 libsbi-objs-$(CONFIG_SBI_ECALL_VENDOR) += sbi_ecall_vendor.o
 
+carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_DBTR) += ecall_dbtr
+libsbi-objs-$(CONFIG_SBI_ECALL_DBTR) += sbi_ecall_dbtr.o
+
 libsbi-objs-y += sbi_bitmap.o
 libsbi-objs-y += sbi_bitops.o
 libsbi-objs-y += sbi_console.o
lib/sbi/sbi_ecall_dbtr.c new file +73 -0

73 lines not on this page · raw message

Signature · 1 line
2.34.1
#14 lore raw

PATCH v2 6/7 lib: sbi: Implement SBI debug trigger extension

Quoted 5 lines · On Mon, Jan 8, 2024 at 12:25?PM Himanshu Chauhan <[email protected]>…

This patch adds functions to register ecalls for debug triggers and handler to handle the debug trigger function IDs.

Already reviewed previously.

Regards,
Anup

Quoted 121 lines
---
 lib/sbi/Kconfig          |  4 +++
 lib/sbi/objects.mk       |  3 ++
 lib/sbi/sbi_ecall_dbtr.c | 73 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+)
 create mode 100644 lib/sbi/sbi_ecall_dbtr.c
lib/sbi/Kconfig +4 -0
index 477775e..81dd2db 100644
@@ -46,4 +46,8 @@ config SBI_ECALL_VENDOR
        bool "Platform-defined vendor extensions"
        default y
 
+config SBI_ECALL_DBTR
+       bool "Debug Trigger Extension"
+       default y
+
 endmenu
lib/sbi/objects.mk +3 -0
index c7de150..0a50e95 100644
@@ -52,6 +52,9 @@ libsbi-objs-$(CONFIG_SBI_ECALL_LEGACY) += sbi_ecall_legacy.o
 carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_VENDOR) += ecall_vendor
 libsbi-objs-$(CONFIG_SBI_ECALL_VENDOR) += sbi_ecall_vendor.o
 
+carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_DBTR) += ecall_dbtr
+libsbi-objs-$(CONFIG_SBI_ECALL_DBTR) += sbi_ecall_dbtr.o
+
 libsbi-objs-y += sbi_bitmap.o
 libsbi-objs-y += sbi_bitops.o
 libsbi-objs-y += sbi_console.o
lib/sbi/sbi_ecall_dbtr.c new file +73 -1
new file mode 100644
index 0000000..0d90043
@@ -0,0 +1,73 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro Systems Inc.
+ *
+ * Author(s):
+ *   Himanshu Chauhan <[email protected]>
+ */
+
+#include <sbi/sbi_ecall.h>
+#include <sbi/sbi_ecall_interface.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_trap.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_dbtr.h>
+
+static int sbi_ecall_dbtr_handler(unsigned long extid, unsigned long funcid,
+                                 struct sbi_trap_regs *regs,
+                                 struct sbi_ecall_return *out)
+{
+       unsigned long smode = (csr_read(CSR_MSTATUS) & MSTATUS_MPP) >>
+                       MSTATUS_MPP_SHIFT;
+       const struct sbi_domain *dom = sbi_domain_thishart_ptr();
+       int ret = 0;
+
+       switch (funcid) {
+       case SBI_EXT_DBTR_NUM_TRIGGERS:
+               ret = sbi_dbtr_num_trig(regs->a0, &out->value);
+               break;
+       case SBI_EXT_DBTR_SETUP_SHMEM:
+               ret = sbi_dbtr_setup_shmem(dom, smode, regs->a0, regs->a1);
+               break;
+       case SBI_EXT_DBTR_TRIGGER_READ:
+               ret = sbi_dbtr_read_trig(dom, smode, regs->a0, regs->a1);
+               break;
+       case SBI_EXT_DBTR_TRIGGER_INSTALL:
+               ret = sbi_dbtr_install_trig(dom, smode, regs->a0, &out->value);
+               break;
+       case SBI_EXT_DBTR_TRIGGER_UNINSTALL:
+               ret = sbi_dbtr_uninstall_trig(regs->a0, regs->a1);
+               break;
+       case SBI_EXT_DBTR_TRIGGER_ENABLE:
+               ret = sbi_dbtr_enable_trig(regs->a0, regs->a1);
+               break;
+       case SBI_EXT_DBTR_TRIGGER_UPDATE:
+               ret = sbi_dbtr_update_trig(dom, smode, regs->a0, regs->a1);
+               break;
+       case SBI_EXT_DBTR_TRIGGER_DISABLE:
+               ret = sbi_dbtr_disable_trig(regs->a0, regs->a1);
+               break;
+       default:
+               ret = SBI_ENOTSUPP;
+       };
+
+       return ret;
+}
+
+struct sbi_ecall_extension ecall_dbtr;
+
+static int sbi_ecall_dbtr_register_extensions(void)
+{
+       if (!sbi_dbtr_supported())
+               return 0;
+
+       return sbi_ecall_register_extension(&ecall_dbtr);
+}
+
+struct sbi_ecall_extension ecall_dbtr = {
+       .extid_start = SBI_EXT_DBTR,
+       .extid_end = SBI_EXT_DBTR,
+       .handle = sbi_ecall_dbtr_handler,
+       .register_extensions = sbi_ecall_dbtr_register_extensions,
+};
--

2.34.1

--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

#15 lore raw

PATCH v2 7/7 lib: sbi: Print number of debug triggers found

In reply to Himanshu Chauhan

Print the total number of triggers found on the boot hart.

---
 lib/sbi/sbi_init.c | 2 ++
 1 file changed, 2 insertions(+)
lib/sbi/sbi_init.c +2 -0
index 0dcde27..c5612a0 100644
@@ -184,6 +184,8 @@ static void sbi_boot_print_hart(struct sbi_scratch *scratch, u32 hartid)
 	sbi_printf("Boot HART MHPM Info       : %lu (0x%08x)\n",
 		   sbi_popcount(sbi_hart_mhpm_mask(scratch)),
 		   sbi_hart_mhpm_mask(scratch));
+	sbi_printf("Boot HART Debug Triggers  : %d trigger(s) found.\n",
+		   sbi_dbtr_get_total_triggers());
 	sbi_hart_delegation_dump(scratch, "Boot HART ", "         ");
 }
 
Signature · 1 line
2.34.1
#16 lore raw

PATCH v2 7/7 lib: sbi: Print number of debug triggers found

Quoted 4 lines · On Mon, Jan 8, 2024 at 12:25?PM Himanshu Chauhan <[email protected]>…

Print the total number of triggers found on the boot hart.

Already reviewed previously.

Regards,
Anup

Quoted 25 lines
---
 lib/sbi/sbi_init.c | 2 ++
 1 file changed, 2 insertions(+)
lib/sbi/sbi_init.c +2 -1
index 0dcde27..c5612a0 100644
@@ -184,6 +184,8 @@ static void sbi_boot_print_hart(struct sbi_scratch *scratch, u32 hartid)
        sbi_printf("Boot HART MHPM Info       : %lu (0x%08x)\n",
                   sbi_popcount(sbi_hart_mhpm_mask(scratch)),
                   sbi_hart_mhpm_mask(scratch));
+       sbi_printf("Boot HART Debug Triggers  : %d trigger(s) found.\n",
+                  sbi_dbtr_get_total_triggers());
        sbi_hart_delegation_dump(scratch, "Boot HART ", "         ");
 }
 
--

2.34.1

--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi