* [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 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 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 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 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 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 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 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 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
* [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 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 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 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 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 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