On Fri, Aug 22, 2025 at 11:17 PM Jesse Taube <[email protected]> wrote: > > From: Himanshu Chauhan <[email protected]> > > RISC-V hardware breakpoint framework is built on top of perf subsystem and > uses > SBI debug trigger extension to install/uninstall/update/enable/disable > hardware > triggers as specified in Sdtrig ISA extension. > > Signed-off-by: Himanshu Chauhan <[email protected]> > Signed-off-by: Jesse Taube <[email protected]> > --- > RFC -> V1: > - Add dbtr_mode to rv_init_mcontrol(6)_trigger > - Add select HAVE_MIXED_BREAKPOINTS_REGS > - Add TDATA1_MCTRL_SZ and TDATA1_MCTRL6_SZ > - Capitalize F in Fallback comment > - Fix in_callback code to allow multiple breakpoints > - Move perf_bp_event above setup_singlestep to save the correct state > - Use sbi_err_map_linux_errno for arch_smp_teardown/setup_sbi_shmem > V1 -> V2: > - No change > --- > arch/riscv/Kconfig | 2 + > arch/riscv/include/asm/hw_breakpoint.h | 59 +++ > arch/riscv/include/asm/kdebug.h | 3 +- > arch/riscv/include/asm/sbi.h | 4 +- > arch/riscv/kernel/Makefile | 1 + > arch/riscv/kernel/hw_breakpoint.c | 614 +++++++++++++++++++++++++ > arch/riscv/kernel/traps.c | 6 + > 7 files changed, 687 insertions(+), 2 deletions(-) > create mode 100644 arch/riscv/include/asm/hw_breakpoint.h > create mode 100644 arch/riscv/kernel/hw_breakpoint.c > > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig > index bbec87b79309..fd8b62cdc6f5 100644 > --- a/arch/riscv/Kconfig > +++ b/arch/riscv/Kconfig > @@ -163,6 +163,7 @@ config RISCV > select HAVE_FUNCTION_ERROR_INJECTION > select HAVE_GCC_PLUGINS > select HAVE_GENERIC_VDSO if MMU && 64BIT > + select HAVE_HW_BREAKPOINT if PERF_EVENTS && RISCV_SBI > select HAVE_IRQ_TIME_ACCOUNTING > select HAVE_KERNEL_BZIP2 if !XIP_KERNEL && !EFI_ZBOOT > select HAVE_KERNEL_GZIP if !XIP_KERNEL && !EFI_ZBOOT > @@ -176,6 +177,7 @@ config RISCV > select HAVE_KRETPROBES if !XIP_KERNEL > # https://github.com/ClangBuiltLinux/linux/issues/1881 > select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if !LD_IS_LLD > + select HAVE_MIXED_BREAKPOINTS_REGS > select HAVE_MOVE_PMD > select HAVE_MOVE_PUD > select HAVE_PAGE_SIZE_4KB > diff --git a/arch/riscv/include/asm/hw_breakpoint.h > b/arch/riscv/include/asm/hw_breakpoint.h > new file mode 100644 > index 000000000000..cde6688b91d2 > --- /dev/null > +++ b/arch/riscv/include/asm/hw_breakpoint.h > @@ -0,0 +1,59 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Copyright (C) 2024 Ventana Micro Systems Inc. > + */ > + > +#ifndef __RISCV_HW_BREAKPOINT_H > +#define __RISCV_HW_BREAKPOINT_H > + > +struct task_struct; > + > +#ifdef CONFIG_HAVE_HW_BREAKPOINT > + > +#include <uapi/linux/hw_breakpoint.h> > + > +#if __riscv_xlen == 64 > +#define cpu_to_le cpu_to_le64 > +#define le_to_cpu le64_to_cpu > +#elif __riscv_xlen == 32 > +#define cpu_to_le cpu_to_le32 > +#define le_to_cpu le32_to_cpu > +#else > +#error "Unexpected __riscv_xlen" > +#endif > + > +struct arch_hw_breakpoint { > + unsigned long address; > + unsigned long len; > + > + /* Callback info */ > + unsigned long next_addr; > + bool in_callback; > + > + /* Trigger configuration data */ > + unsigned long tdata1; > + unsigned long tdata2; > + unsigned long tdata3; > +}; > + > +/* Maximum number of hardware breakpoints supported */ > +#define RV_MAX_TRIGGERS 32 > + > +struct perf_event_attr; > +struct notifier_block; > +struct perf_event; > +struct pt_regs; > + > +int hw_breakpoint_slots(int type); > +int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw); > +int hw_breakpoint_arch_parse(struct perf_event *bp, > + const struct perf_event_attr *attr, > + struct arch_hw_breakpoint *hw); > +int hw_breakpoint_exceptions_notify(struct notifier_block *unused, > + unsigned long val, void *data); > +int arch_install_hw_breakpoint(struct perf_event *bp); > +void arch_uninstall_hw_breakpoint(struct perf_event *bp); > +void hw_breakpoint_pmu_read(struct perf_event *bp); > + > +#endif /* CONFIG_HAVE_HW_BREAKPOINT */ > +#endif /* __RISCV_HW_BREAKPOINT_H */ > diff --git a/arch/riscv/include/asm/kdebug.h b/arch/riscv/include/asm/kdebug.h > index 85ac00411f6e..53e989781aa1 100644 > --- a/arch/riscv/include/asm/kdebug.h > +++ b/arch/riscv/include/asm/kdebug.h > @@ -6,7 +6,8 @@ > enum die_val { > DIE_UNUSED, > DIE_TRAP, > - DIE_OOPS > + DIE_OOPS, > + DIE_DEBUG > }; > > #endif > diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h > index be2ca8e8a49e..64fa7a82aa45 100644 > --- a/arch/riscv/include/asm/sbi.h > +++ b/arch/riscv/include/asm/sbi.h > @@ -282,7 +282,9 @@ struct sbi_sta_struct { > u8 pad[47]; > } __packed; > > -#define SBI_SHMEM_DISABLE -1 > +#define SBI_SHMEM_DISABLE (-1UL) > +#define SBI_SHMEM_LO(pa) ((unsigned long)lower_32_bits(pa)) > +#define SBI_SHMEM_HI(pa) ((unsigned long)upper_32_bits(pa))
These definitions of SBI_SHMEM_LO() and SBI_SHMEM_HI() are broken for RV64 platforms where a good amount of RAM is beyond first 4GB. This should be: #ifdef CONFIG_32BIT #define SBI_SHMEM_LO(pa) ((unsigned long)lower_32_bits(pa)) #define SBI_SHMEM_HI(pa) ((unsigned long)upper_32_bits(pa)) #else #define SBI_SHMEM_LO(pa) ((unsigned long)pa) #define SBI_SHMEM_HI(pa) 0UL #endif Regards, Anup

