OpenSBI Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/7] Introduce support for SBI Debug Trigger Extension
@ 2024-01-08  6:55 Himanshu Chauhan
  2024-01-08  6:55 ` [PATCH v2 1/7] include: sbi: Introduce common endianess conversion macro Himanshu Chauhan
                   ` (6 more replies)
  0 siblings, 7 replies; 17+ messages in thread
From: Himanshu Chauhan @ 2024-01-08  6:55 UTC (permalink / raw)
  To: opensbi

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

-- 
2.34.1



^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 1/7] include: sbi: Introduce common endianess conversion macro
  2024-01-08  6:55 [PATCH v2 0/7] Introduce support for SBI Debug Trigger Extension Himanshu Chauhan
@ 2024-01-08  6:55 ` Himanshu Chauhan
  2024-01-09 10:22   ` Anup Patel
  2024-01-08  6:55 ` [PATCH v2 2/7] include: sbi: Add TINFO debug trigger CSR Himanshu Chauhan
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Himanshu Chauhan @ 2024-01-08  6:55 UTC (permalink / raw)
  To: opensbi

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

Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
---
 include/sbi/sbi_byteorder.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/include/sbi/sbi_byteorder.h b/include/sbi/sbi_byteorder.h
index 15107e1..db6eb2b 100644
--- a/include/sbi/sbi_byteorder.h
+++ b/include/sbi/sbi_byteorder.h
@@ -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



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 2/7] include: sbi: Add TINFO debug trigger CSR
  2024-01-08  6:55 [PATCH v2 0/7] Introduce support for SBI Debug Trigger Extension Himanshu Chauhan
  2024-01-08  6:55 ` [PATCH v2 1/7] include: sbi: Introduce common endianess conversion macro Himanshu Chauhan
@ 2024-01-08  6:55 ` Himanshu Chauhan
  2024-01-09 10:23   ` Anup Patel
  2024-01-08  6:55 ` [PATCH v2 3/7] include: sbi: Introduce debug trigger register encodings Himanshu Chauhan
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Himanshu Chauhan @ 2024-01-08  6:55 UTC (permalink / raw)
  To: opensbi

Add the missing TINFO debug trigger CSR.

Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
---
 include/sbi/riscv_encoding.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h
index f20df76..e74cc0d 100644
--- a/include/sbi/riscv_encoding.h
+++ b/include/sbi/riscv_encoding.h
@@ -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



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 3/7] include: sbi: Introduce debug trigger register encodings
  2024-01-08  6:55 [PATCH v2 0/7] Introduce support for SBI Debug Trigger Extension Himanshu Chauhan
  2024-01-08  6:55 ` [PATCH v2 1/7] include: sbi: Introduce common endianess conversion macro Himanshu Chauhan
  2024-01-08  6:55 ` [PATCH v2 2/7] include: sbi: Add TINFO debug trigger CSR Himanshu Chauhan
@ 2024-01-08  6:55 ` Himanshu Chauhan
  2024-01-09 10:23   ` Anup Patel
  2024-01-08  6:55 ` [PATCH v2 4/7] lib: sbi: Introduce the SBI debug triggers extension support Himanshu Chauhan
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Himanshu Chauhan @ 2024-01-08  6:55 UTC (permalink / raw)
  To: opensbi

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

Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
---
 include/sbi/riscv_dbtr.h | 249 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 249 insertions(+)
 create mode 100644 include/sbi/riscv_dbtr.h

diff --git a/include/sbi/riscv_dbtr.h b/include/sbi/riscv_dbtr.h
new file mode 100644
index 0000000..96c7d3e
--- /dev/null
+++ b/include/sbi/riscv_dbtr.h
@@ -0,0 +1,249 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro System, Inc.
+ *
+ * Authors:
+ *   Himanshu Chauhan <hchauhan@ventanamicro.com>
+ */
+
+#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



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 4/7] lib: sbi: Introduce the SBI debug triggers extension support
  2024-01-08  6:55 [PATCH v2 0/7] Introduce support for SBI Debug Trigger Extension Himanshu Chauhan
                   ` (2 preceding siblings ...)
  2024-01-08  6:55 ` [PATCH v2 3/7] include: sbi: Introduce debug trigger register encodings Himanshu Chauhan
@ 2024-01-08  6:55 ` Himanshu Chauhan
  2024-01-09 10:32   ` Anup Patel
  2024-01-08  6:55 ` [PATCH v2 5/7] include: sbi: Add SBI debug trigger extension related defines Himanshu Chauhan
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Himanshu Chauhan @ 2024-01-08  6:55 UTC (permalink / raw)
  To: opensbi

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

Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
---
 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

diff --git a/include/sbi/sbi_dbtr.h b/include/sbi/sbi_dbtr.h
new file mode 100644
index 0000000..20855ae
--- /dev/null
+++ b/include/sbi/sbi_dbtr.h
@@ -0,0 +1,127 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro Systems, Inc.
+ *
+ * Authors:
+ *   Himanshu Chauhan <hchauhan@ventanamicro.com>
+ */
+
+#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
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index c699187..c7de150 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -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
diff --git a/lib/sbi/sbi_dbtr.c b/lib/sbi/sbi_dbtr.c
new file mode 100644
index 0000000..1bd29c1
--- /dev/null
+++ b/lib/sbi/sbi_dbtr.c
@@ -0,0 +1,742 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro Systems, Inc.
+ *
+ * Author(s):
+ *   Himanshu Chauhan <hchauhan@ventanamicro.com>
+ */
+
+#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;
+
+	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;
+
+	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));
+		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++) {
+		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;
+}
+
+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;
+}
+
+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;
+	}
+
+	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();
+	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;
+	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;
+	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;
+	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;
+}
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index 6a98e13..0dcde27 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -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



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 5/7] include: sbi: Add SBI debug trigger extension related defines
  2024-01-08  6:55 [PATCH v2 0/7] Introduce support for SBI Debug Trigger Extension Himanshu Chauhan
                   ` (3 preceding siblings ...)
  2024-01-08  6:55 ` [PATCH v2 4/7] lib: sbi: Introduce the SBI debug triggers extension support Himanshu Chauhan
@ 2024-01-08  6:55 ` Himanshu Chauhan
  2024-01-09 10:33   ` Anup Patel
  2024-01-08  6:55 ` [PATCH v2 6/7] lib: sbi: Implement SBI debug trigger extension Himanshu Chauhan
  2024-01-08  6:55 ` [PATCH v2 7/7] lib: sbi: Print number of debug triggers found Himanshu Chauhan
  6 siblings, 1 reply; 17+ messages in thread
From: Himanshu Chauhan @ 2024-01-08  6:55 UTC (permalink / raw)
  To: opensbi

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

Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
---
 include/sbi/sbi_ecall_interface.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h
index d8c646d..690c31b 100644
--- a/include/sbi/sbi_ecall_interface.h
+++ b/include/sbi/sbi_ecall_interface.h
@@ -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



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 6/7] lib: sbi: Implement SBI debug trigger extension
  2024-01-08  6:55 [PATCH v2 0/7] Introduce support for SBI Debug Trigger Extension Himanshu Chauhan
                   ` (4 preceding siblings ...)
  2024-01-08  6:55 ` [PATCH v2 5/7] include: sbi: Add SBI debug trigger extension related defines Himanshu Chauhan
@ 2024-01-08  6:55 ` Himanshu Chauhan
  2024-01-09 10:33   ` Anup Patel
  2024-01-08  6:55 ` [PATCH v2 7/7] lib: sbi: Print number of debug triggers found Himanshu Chauhan
  6 siblings, 1 reply; 17+ messages in thread
From: Himanshu Chauhan @ 2024-01-08  6:55 UTC (permalink / raw)
  To: opensbi

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

Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
---
 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

diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
index 477775e..81dd2db 100644
--- a/lib/sbi/Kconfig
+++ b/lib/sbi/Kconfig
@@ -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
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index c7de150..0a50e95 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -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
diff --git a/lib/sbi/sbi_ecall_dbtr.c b/lib/sbi/sbi_ecall_dbtr.c
new file mode 100644
index 0000000..0d90043
--- /dev/null
+++ b/lib/sbi/sbi_ecall_dbtr.c
@@ -0,0 +1,73 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro Systems Inc.
+ *
+ * Author(s):
+ *   Himanshu Chauhan <hchauhan@ventanamicro.com>
+ */
+
+#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



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 7/7] lib: sbi: Print number of debug triggers found
  2024-01-08  6:55 [PATCH v2 0/7] Introduce support for SBI Debug Trigger Extension Himanshu Chauhan
                   ` (5 preceding siblings ...)
  2024-01-08  6:55 ` [PATCH v2 6/7] lib: sbi: Implement SBI debug trigger extension Himanshu Chauhan
@ 2024-01-08  6:55 ` Himanshu Chauhan
  2024-01-09 10:33   ` Anup Patel
  6 siblings, 1 reply; 17+ messages in thread
From: Himanshu Chauhan @ 2024-01-08  6:55 UTC (permalink / raw)
  To: opensbi

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

Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
---
 lib/sbi/sbi_init.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index 0dcde27..c5612a0 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -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



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 1/7] include: sbi: Introduce common endianess conversion macro
  2024-01-08  6:55 ` [PATCH v2 1/7] include: sbi: Introduce common endianess conversion macro Himanshu Chauhan
@ 2024-01-09 10:22   ` Anup Patel
  0 siblings, 0 replies; 17+ messages in thread
From: Anup Patel @ 2024-01-09 10:22 UTC (permalink / raw)
  To: opensbi

On Mon, Jan 8, 2024 at 12:25?PM Himanshu Chauhan
<hchauhan@ventanamicro.com> wrote:
>
> Introduce cpu_to_lle and lle_to_cpu macros which invoke
> correct word length cpu_to_le<64/32> conversion based on
> __riscv_xlen.
>
> Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>

Already reviewed previously.

Reviewed-by: Anup Patel <anup@brainfault.org>

Regards,
Anup

> ---
>  include/sbi/sbi_byteorder.h | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/include/sbi/sbi_byteorder.h b/include/sbi/sbi_byteorder.h
> index 15107e1..db6eb2b 100644
> --- a/include/sbi/sbi_byteorder.h
> +++ b/include/sbi/sbi_byteorder.h
> @@ -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


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 2/7] include: sbi: Add TINFO debug trigger CSR
  2024-01-08  6:55 ` [PATCH v2 2/7] include: sbi: Add TINFO debug trigger CSR Himanshu Chauhan
@ 2024-01-09 10:23   ` Anup Patel
  0 siblings, 0 replies; 17+ messages in thread
From: Anup Patel @ 2024-01-09 10:23 UTC (permalink / raw)
  To: opensbi

On Mon, Jan 8, 2024 at 12:25?PM Himanshu Chauhan
<hchauhan@ventanamicro.com> wrote:
>
> Add the missing TINFO debug trigger CSR.
>
> Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>

Already reviewed previously.

Reviewed-by: Anup Patel <anup@brainfault.org>

Regards,
Anup

> ---
>  include/sbi/riscv_encoding.h | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h
> index f20df76..e74cc0d 100644
> --- a/include/sbi/riscv_encoding.h
> +++ b/include/sbi/riscv_encoding.h
> @@ -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


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 3/7] include: sbi: Introduce debug trigger register encodings
  2024-01-08  6:55 ` [PATCH v2 3/7] include: sbi: Introduce debug trigger register encodings Himanshu Chauhan
@ 2024-01-09 10:23   ` Anup Patel
  0 siblings, 0 replies; 17+ messages in thread
From: Anup Patel @ 2024-01-09 10:23 UTC (permalink / raw)
  To: opensbi

On Mon, Jan 8, 2024 at 12:25?PM Himanshu Chauhan
<hchauhan@ventanamicro.com> wrote:
>
> This patch introduces Mcontrol and M6 control register
> encodings along with macros to manipulate them.
>
> Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>

Already reviewed previously.

Reviewed-by: Anup Patel <anup@brainfault.org>

Regards,
Anup

> ---
>  include/sbi/riscv_dbtr.h | 249 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 249 insertions(+)
>  create mode 100644 include/sbi/riscv_dbtr.h
>
> diff --git a/include/sbi/riscv_dbtr.h b/include/sbi/riscv_dbtr.h
> new file mode 100644
> index 0000000..96c7d3e
> --- /dev/null
> +++ b/include/sbi/riscv_dbtr.h
> @@ -0,0 +1,249 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2023 Ventana Micro System, Inc.
> + *
> + * Authors:
> + *   Himanshu Chauhan <hchauhan@ventanamicro.com>
> + */
> +
> +#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


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 4/7] lib: sbi: Introduce the SBI debug triggers extension support
  2024-01-08  6:55 ` [PATCH v2 4/7] lib: sbi: Introduce the SBI debug triggers extension support Himanshu Chauhan
@ 2024-01-09 10:32   ` Anup Patel
  2024-01-09 15:31     ` Himanshu Chauhan
  0 siblings, 1 reply; 17+ messages in thread
From: Anup Patel @ 2024-01-09 10:32 UTC (permalink / raw)
  To: opensbi

On Mon, Jan 8, 2024 at 12:25?PM Himanshu Chauhan
<hchauhan@ventanamicro.com> wrote:
>
> 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
>
> Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>

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.

> ---
>  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
>
> diff --git a/include/sbi/sbi_dbtr.h b/include/sbi/sbi_dbtr.h
> new file mode 100644
> index 0000000..20855ae
> --- /dev/null
> +++ b/include/sbi/sbi_dbtr.h
> @@ -0,0 +1,127 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2023 Ventana Micro Systems, Inc.
> + *
> + * Authors:
> + *   Himanshu Chauhan <hchauhan@ventanamicro.com>
> + */
> +
> +#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
> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> index c699187..c7de150 100644
> --- a/lib/sbi/objects.mk
> +++ b/lib/sbi/objects.mk
> @@ -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
> diff --git a/lib/sbi/sbi_dbtr.c b/lib/sbi/sbi_dbtr.c
> new file mode 100644
> index 0000000..1bd29c1
> --- /dev/null
> +++ b/lib/sbi/sbi_dbtr.c
> @@ -0,0 +1,742 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2023 Ventana Micro Systems, Inc.
> + *
> + * Author(s):
> + *   Himanshu Chauhan <hchauhan@ventanamicro.com>
> + */
> +
> +#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;
> +
> +       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.

> +
> +       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));
> +               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.

> +               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;
> +}
> +
> +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 ?

> +
> +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.

> +
> +       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();
> +       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.

> +       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;
> +       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.

> +       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;
> +}
> diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
> index 6a98e13..0dcde27 100644
> --- a/lib/sbi/sbi_init.c
> +++ b/lib/sbi/sbi_init.c
> @@ -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
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi

Regards,
Anup


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 5/7] include: sbi: Add SBI debug trigger extension related defines
  2024-01-08  6:55 ` [PATCH v2 5/7] include: sbi: Add SBI debug trigger extension related defines Himanshu Chauhan
@ 2024-01-09 10:33   ` Anup Patel
  0 siblings, 0 replies; 17+ messages in thread
From: Anup Patel @ 2024-01-09 10:33 UTC (permalink / raw)
  To: opensbi

On Mon, Jan 8, 2024 at 12:25?PM Himanshu Chauhan
<hchauhan@ventanamicro.com> wrote:
>
> This patch adds defines for SBI debug trigger extension and
> function IDs to access the extension.
>
> Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>

Already reviewed previously.

Reviewed-by: Anup Patel <anup@brainfault.org>

Regards,
Anup

> ---
>  include/sbi/sbi_ecall_interface.h | 11 +++++++++++
>  1 file changed, 11 insertions(+)
>
> diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h
> index d8c646d..690c31b 100644
> --- a/include/sbi/sbi_ecall_interface.h
> +++ b/include/sbi/sbi_ecall_interface.h
> @@ -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


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 6/7] lib: sbi: Implement SBI debug trigger extension
  2024-01-08  6:55 ` [PATCH v2 6/7] lib: sbi: Implement SBI debug trigger extension Himanshu Chauhan
@ 2024-01-09 10:33   ` Anup Patel
  0 siblings, 0 replies; 17+ messages in thread
From: Anup Patel @ 2024-01-09 10:33 UTC (permalink / raw)
  To: opensbi

On Mon, Jan 8, 2024 at 12:25?PM Himanshu Chauhan
<hchauhan@ventanamicro.com> wrote:
>
> This patch adds functions to register ecalls for debug triggers
> and handler to handle the debug trigger function IDs.
>
> Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>

Already reviewed previously.

Reviewed-by: Anup Patel <anup@brainfault.org>

Regards,
Anup

> ---
>  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
>
> diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
> index 477775e..81dd2db 100644
> --- a/lib/sbi/Kconfig
> +++ b/lib/sbi/Kconfig
> @@ -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
> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> index c7de150..0a50e95 100644
> --- a/lib/sbi/objects.mk
> +++ b/lib/sbi/objects.mk
> @@ -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
> diff --git a/lib/sbi/sbi_ecall_dbtr.c b/lib/sbi/sbi_ecall_dbtr.c
> new file mode 100644
> index 0000000..0d90043
> --- /dev/null
> +++ b/lib/sbi/sbi_ecall_dbtr.c
> @@ -0,0 +1,73 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2023 Ventana Micro Systems Inc.
> + *
> + * Author(s):
> + *   Himanshu Chauhan <hchauhan@ventanamicro.com>
> + */
> +
> +#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


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 7/7] lib: sbi: Print number of debug triggers found
  2024-01-08  6:55 ` [PATCH v2 7/7] lib: sbi: Print number of debug triggers found Himanshu Chauhan
@ 2024-01-09 10:33   ` Anup Patel
  0 siblings, 0 replies; 17+ messages in thread
From: Anup Patel @ 2024-01-09 10:33 UTC (permalink / raw)
  To: opensbi

On Mon, Jan 8, 2024 at 12:25?PM Himanshu Chauhan
<hchauhan@ventanamicro.com> wrote:
>
> Print the total number of triggers found on the boot hart.
>
> Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>

Already reviewed previously.

Reviewed-by: Anup Patel <anup@brainfault.org>

Regards,
Anup

> ---
>  lib/sbi/sbi_init.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
> index 0dcde27..c5612a0 100644
> --- a/lib/sbi/sbi_init.c
> +++ b/lib/sbi/sbi_init.c
> @@ -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


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 4/7] lib: sbi: Introduce the SBI debug triggers extension support
  2024-01-09 10:32   ` Anup Patel
@ 2024-01-09 15:31     ` Himanshu Chauhan
  2024-01-09 15:44       ` Anup Patel
  0 siblings, 1 reply; 17+ messages in thread
From: Himanshu Chauhan @ 2024-01-09 15:31 UTC (permalink / raw)
  To: opensbi

Hi Anup,

> On 09-Jan-2024, at 4:02?PM, Anup Patel <anup@brainfault.org> wrote:
> 
>> 

<snip>

>> +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;
>> +       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

> 
>> +       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;
>> +       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.
> 
>> +       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;
>> +}
>> diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
>> index 6a98e13..0dcde27 100644
>> --- a/lib/sbi/sbi_init.c
>> +++ b/lib/sbi/sbi_init.c
>> @@ -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
>> 
>> 
>> --
>> opensbi mailing list
>> opensbi at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/opensbi
> 
> Regards,
> Anup




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 4/7] lib: sbi: Introduce the SBI debug triggers extension support
  2024-01-09 15:31     ` Himanshu Chauhan
@ 2024-01-09 15:44       ` Anup Patel
  0 siblings, 0 replies; 17+ messages in thread
From: Anup Patel @ 2024-01-09 15:44 UTC (permalink / raw)
  To: opensbi

On Tue, Jan 9, 2024 at 9:01?PM Himanshu Chauhan
<hchauhan@ventanamicro.com> wrote:
>
> Hi Anup,
>
> > On 09-Jan-2024, at 4:02?PM, Anup Patel <anup@brainfault.org> wrote:
> >
> >>
>
> <snip>
>
> >> +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;
> >> +       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.

Okay, at least drop the sanity check.

Regards,
Anup

>
> Regards
> Himanshu
>
> >
> >> +       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;
> >> +       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.
> >
> >> +       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;
> >> +}
> >> diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
> >> index 6a98e13..0dcde27 100644
> >> --- a/lib/sbi/sbi_init.c
> >> +++ b/lib/sbi/sbi_init.c
> >> @@ -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
> >>
> >>
> >> --
> >> opensbi mailing list
> >> opensbi at lists.infradead.org
> >> http://lists.infradead.org/mailman/listinfo/opensbi
> >
> > Regards,
> > Anup
>
>


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2024-01-09 15:44 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-01-08  6:55 [PATCH v2 0/7] Introduce support for SBI Debug Trigger Extension Himanshu Chauhan
2024-01-08  6:55 ` [PATCH v2 1/7] include: sbi: Introduce common endianess conversion macro Himanshu Chauhan
2024-01-09 10:22   ` Anup Patel
2024-01-08  6:55 ` [PATCH v2 2/7] include: sbi: Add TINFO debug trigger CSR Himanshu Chauhan
2024-01-09 10:23   ` Anup Patel
2024-01-08  6:55 ` [PATCH v2 3/7] include: sbi: Introduce debug trigger register encodings Himanshu Chauhan
2024-01-09 10:23   ` Anup Patel
2024-01-08  6:55 ` [PATCH v2 4/7] lib: sbi: Introduce the SBI debug triggers extension support Himanshu Chauhan
2024-01-09 10:32   ` Anup Patel
2024-01-09 15:31     ` Himanshu Chauhan
2024-01-09 15:44       ` Anup Patel
2024-01-08  6:55 ` [PATCH v2 5/7] include: sbi: Add SBI debug trigger extension related defines Himanshu Chauhan
2024-01-09 10:33   ` Anup Patel
2024-01-08  6:55 ` [PATCH v2 6/7] lib: sbi: Implement SBI debug trigger extension Himanshu Chauhan
2024-01-09 10:33   ` Anup Patel
2024-01-08  6:55 ` [PATCH v2 7/7] lib: sbi: Print number of debug triggers found Himanshu Chauhan
2024-01-09 10:33   ` Anup Patel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox