From: sashiko-bot@kernel.org
To: "Himanshu Chauhan" <himanshu.chauhan@oss.qualcomm.com>,
"Paul Walmsley" <pjw@kernel.org>,
"Palmer Dabbelt" <palmer@dabbelt.com>,
"Albert Ou" <aou@eecs.berkeley.edu>
Cc: "Alexandre Ghiti" <alex@ghiti.fr>,
"Jesse Taube" <jtaubepe@redhat.com>,
"Oleg Nesterov" <oleg@redhat.com>, "Kees Cook" <kees@kernel.org>,
"Peter Zijlstra" <peterz@infradead.org>,
"Ingo Molnar" <mingo@redhat.com>,
"Arnaldo Carvalho de Melo" <acme@kernel.org>,
"Namhyung Kim" <namhyung@kernel.org>,
"Mark Rutland" <mark.rutland@arm.com>,
"Alexander Shishkin" <alexander.shishkin@linux.intel.com>,
"Jiri Olsa" <jolsa@kernel.org>, "Ian Rogers" <irogers@google.com>,
"Adrian Hunter" <adrian.hunter@intel.com>,
"James Clark" <james.clark@linaro.org>,
"Shuah Khan" <shuah@kernel.org>,
linux-mm@kvack.org, linux-perf-users@vger.kernel.org
Subject: Re: [PATCH v8 3/8] riscv: add ptrace requests for hardware breakpoints
Date: Sun, 08 Nov 2026 02:41:36 +0000 [thread overview]
Message-ID: <sashiko-outbox-203524@kernel.org> (raw)
In-Reply-To: <20261107023917.40606-4-himanshu.chauhan@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 5 potential
issues to consider:
- [High] riscv: ptrace: PTRACE_GETHBPREGS/SETHBPREGS collide with
generic SUD requests
- [High] riscv: hw_breakpoint: duplicate flush_ptrace_hw_breakpoint()
stub breaks build
- [Medium] riscv: ptrace: switching slot type in riscv_ptrace_bp_set()
fails with -ENOSPC
- [Medium] riscv: ptrace: sleeping lock in riscv_ptrace_hbptriggered()
with IRQs off
- [Low] riscv: unused clear_ptrace_hw_breakpoint() prototype and
debug_info fields
--
commit 99a21b5687d9bebf111bc51526d0fe5d8bd289d6
Author: Himanshu Chauhan <himanshu.chauhan@oss.qualcomm.com>
riscv: add ptrace requests for hardware breakpoints
This commit adds support for the PTRACE_GETHBPREGS and PTRACE_SETHBPREGS
ptrace requests on RISC-V, storing per-task perf hardware breakpoint events
and reporting hits via SIGTRAP/TRAP_HWBKPT.
> diff --git a/arch/riscv/include/asm/hw_breakpoint.h b/arch/riscv/include/asm/hw_breakpoint.h
> index dcce20ba3faab..6e8913d69df23 100644
> --- a/arch/riscv/include/asm/hw_breakpoint.h
> +++ b/arch/riscv/include/asm/hw_breakpoint.h
[ ... ]
> @@ -42,8 +49,14 @@ void arch_disable_hw_breakpoint(struct perf_event *bp);
> 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);
> +void clear_ptrace_hw_breakpoint(struct task_struct *tsk);
> +void flush_ptrace_hw_breakpoint(struct task_struct *tsk);
> +void ptrace_hw_copy_thread(struct task_struct *task);
>
> #else
>
> +static inline void flush_ptrace_hw_breakpoint(struct task_struct *task) { }
> +static inline void ptrace_hw_copy_thread(struct task_struct *task) { }
> +
> #endif /* CONFIG_HAVE_HW_BREAKPOINT */
> #endif /* __RISCV_HW_BREAKPOINT_H */
[Severity: High]
Does defining flush_ptrace_hw_breakpoint() here break the build when
CONFIG_HAVE_HW_BREAKPOINT is disabled?
include/linux/hw_breakpoint.h already defines a static inline stub for
flush_ptrace_hw_breakpoint() when CONFIG_HAVE_HW_BREAKPOINT is not set
(and declares the prototype when it is set). Since asm/processor.h now
includes asm/hw_breakpoint.h, any translation unit including both
linux/sched.h and linux/hw_breakpoint.h (such as arch/riscv/kernel/ptrace.c)
fails to compile due to the redefinition.
> diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
> index e9d339bcb7e9f..a124ea48d8058 100644
> --- a/arch/riscv/include/asm/processor.h
> +++ b/arch/riscv/include/asm/processor.h
[ ... ]
> @@ -111,6 +112,19 @@ struct pt_regs;
> #define RISCV_PREEMPT_V_NEED_RESTORE 0x40000000
> #define RISCV_PREEMPT_V_IN_SCHEDULE 0x20000000
>
> +struct debug_info {
> +#ifdef CONFIG_HAVE_HW_BREAKPOINT
> + /* Have we suspended stepping by a debugger? */
> + int suspended_step;
> + /* Allow breakpoints and watchpoints to be disabled for this thread. */
> + int bp_disabled;
> + int wp_disabled;
> + /* Hardware breakpoints pinned to this task. */
> + struct perf_event *hbp_break[RISCV_MAX_BP];
> + struct perf_event *hbp_watch[RISCV_MAX_BP];
> +#endif
> +};
[Severity: Low]
This isn't a bug, but suspended_step, bp_disabled, and wp_disabled in
struct debug_info, along with the clear_ptrace_hw_breakpoint() prototype in
asm/hw_breakpoint.h, are never used in this patch or later in the series.
> diff --git a/arch/riscv/include/uapi/asm/ptrace.h b/arch/riscv/include/uapi/asm/ptrace.h
> index 3de2b7124aff3..373a1c14f2073 100644
> --- a/arch/riscv/include/uapi/asm/ptrace.h
> +++ b/arch/riscv/include/uapi/asm/ptrace.h
> @@ -15,6 +15,8 @@
>
> #define PTRACE_GETFDPIC_EXEC 0
> #define PTRACE_GETFDPIC_INTERP 1
> +#define PTRACE_GETHBPREGS 0x4210
> +#define PTRACE_SETHBPREGS 0x4211
[Severity: High]
As reported by Rui Qi on v6 [1], do these values collide with the generic
PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG (0x4210) and
PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG (0x4211) requests in
include/uapi/linux/ptrace.h, where 0x4200-0x4300 is reserved for
architecture-independent additions?
Because arch_ptrace() and compat_arch_ptrace() intercept 0x4210 and 0x4211
before calling ptrace_request(), a tracer calling
PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG when CONFIG_HAVE_HW_BREAKPOINT=y is
routed to riscv_ptrace_gethbpregs(), which overwrites the caller's input
buffer via copy_to_user(), while PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG is
routed to riscv_ptrace_sethbpregs().
> diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
> index a0055743d3ba5..be076865d02d0 100644
> --- a/arch/riscv/kernel/ptrace.c
> +++ b/arch/riscv/kernel/ptrace.c
[ ... ]
> @@ -380,6 +382,152 @@ static int riscv_cfi_set(struct task_struct *target,
> }
> #endif
>
> +#ifdef CONFIG_HAVE_HW_BREAKPOINT
> +enum riscv_hbp_type {
> + RISCV_HBP_BREAK,
> + RISCV_HBP_WATCH,
> +};
> +
> +/*
> + * Handle hitting a HW-breakpoint.
> + */
> +static void riscv_ptrace_hbptriggered(struct perf_event *bp,
> + struct perf_sample_data *data,
> + struct pt_regs *regs)
> +{
> + struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
> +
> + force_sig_fault(SIGTRAP, TRAP_HWBKPT, (void __user *)bkpt->address);
> +}
[Severity: Medium]
Can calling force_sig_fault() from riscv_ptrace_hbptriggered() sleep with
interrupts disabled on PREEMPT_RT?
When a breakpoint triggers, hw_breakpoint_handler() -> perf_bp_event() ->
perf_swevent_event() disables hardware interrupts via guard(irqsave)()
before invoking the overflow handler:
perf_swevent_event() [guard(irqsave)()]
-> perf_swevent_overflow()
-> __perf_event_overflow()
-> riscv_ptrace_hbptriggered()
-> force_sig_fault()
-> force_sig_info_to_task()
-> spin_lock_irqsave(&t->sighand->siglock, flags)
On PREEMPT_RT (RISC-V selects ARCH_SUPPORTS_RT), sighand->siglock is a
sleeping rt_spin_lock, so acquiring it with interrupts disabled triggers a
sleeping-in-atomic warning and blocks with IRQs off if contended.
[ ... ]
> @@ -549,12 +697,173 @@ void ptrace_disable(struct task_struct *child)
[ ... ]
> +static int riscv_ptrace_bp_set(struct task_struct *child, unsigned long idx,
> + struct __riscv_hwdebug_state *state)
> +{
> + struct perf_event *bp;
> + struct perf_event_attr attr;
> + enum riscv_hbp_type hbp_type, other_hbp_type;
> + int ret;
> + bool created = false;
> +
> + if (idx >= RISCV_MAX_BP)
> + return -EINVAL;
> +
> + idx = array_index_nospec(idx, RISCV_MAX_BP);
> +
> + ret = riscv_ptrace_bp_type_to_hbp(state->type, &hbp_type);
> + if (ret)
> + return ret;
> +
> + /* The legacy request exposes ctrl as a disabled/enabled boolean. */
> + if (state->ctrl > 1)
> + return -EINVAL;
> +
> + other_hbp_type = hbp_type == RISCV_HBP_BREAK ?
> + RISCV_HBP_WATCH : RISCV_HBP_BREAK;
> +
> + bp = ptrace_hbp_get_event(hbp_type, child, idx);
> + if (IS_ERR(bp))
> + return PTR_ERR(bp);
> + if (!bp) {
> + bp = ptrace_hbp_create(hbp_type, child, idx);
> + if (IS_ERR(bp))
> + return PTR_ERR(bp);
> + created = true;
> + }
> +
> + attr = bp->attr;
> +
> + attr.bp_addr = state->addr;
> + attr.bp_len = state->len;
> + attr.bp_type = state->type;
> + /* Enable or disable as requested by ctrl (0 = enabled, 1 = disabled) */
> + attr.disabled = state->ctrl == 1;
> + ret = modify_user_hw_breakpoint(bp, &attr);
> + if (ret) {
> + /* Drop only events allocated by this failed request. */
> + if (created)
> + riscv_ptrace_bp_clear_event(child, hbp_type, idx);
> + return ret;
> + }
> +
> + /*
> + * If the same index changed from breakpoint to watchpoint, or back,
> + * clear the old opposite-type slot after the new event is valid so a
> + * failed update does not destroy the previous state.
> + */
> + return riscv_ptrace_bp_clear_event(child, other_hbp_type, idx);
> +}
[Severity: Medium]
Can switching an existing slot between a breakpoint and a watchpoint fail
with -ENOSPC when all hardware triggers are already in use?
RISC-V selects CONFIG_HAVE_MIXED_BREAKPOINTS_REGS, so breakpoints and
watchpoints share a single pool of dbtr_total_num slots in
reserve_bp_slot(). Because debug_info splits storage into hbp_break[] and
hbp_watch[], changing the type at index idx causes ptrace_hbp_get_event()
to return NULL and ptrace_hbp_create() to allocate a second perf_event
from the shared pool before riscv_ptrace_bp_clear_event() frees the
existing event at the same index. Modifying the existing perf_event in
place via modify_user_hw_breakpoint() (or storing unified trigger slots in
a single array) would avoid needing a spare hardware slot.
[1] https://lore.kernel.org/r/5a7c08bd-4313-4424-b649-a19ffe5242e4@bytedance.com
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261107023917.40606-1-himanshu.chauhan@oss.qualcomm.com?part=3
next prev parent reply other threads:[~2026-11-08 2:41 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-07 2:39 [PATCH v8 0/8] riscv: Introduce support for hardware break/watchpoints Himanshu Chauhan
2026-11-07 2:39 ` [PATCH v8 1/8] " Himanshu Chauhan
2026-11-08 2:41 ` sashiko-bot
2026-11-07 2:39 ` [PATCH v8 2/8] riscv: Add breakpoint and watchpoint test for riscv Himanshu Chauhan
2026-11-08 2:41 ` sashiko-bot
2026-11-07 2:39 ` [PATCH v8 3/8] riscv: add ptrace requests for hardware breakpoints Himanshu Chauhan
2026-11-07 7:04 ` kernel test robot
2026-11-08 2:41 ` sashiko-bot [this message]
2026-11-07 2:39 ` [PATCH v8 4/8] riscv: add regset access " Himanshu Chauhan
2026-11-08 2:41 ` sashiko-bot
2026-11-07 2:39 ` [PATCH v8 5/8] selftests/breakpoints: extend riscv test for ptrace hw break/watchpoints Himanshu Chauhan
2026-11-08 2:41 ` sashiko-bot
2026-11-07 2:39 ` [PATCH v8 6/8] riscv: Add shared instruction fetch and decode helpers Himanshu Chauhan
2026-11-08 2:41 ` sashiko-bot
2026-11-07 2:39 ` [PATCH v8 7/8] riscv: Add software supported single stepping with mc/mc6 triggers Himanshu Chauhan
2026-11-08 2:41 ` sashiko-bot
2026-11-07 2:39 ` [PATCH v8 8/8] perf tests: keep bp_signal memory accesses visible Himanshu Chauhan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-203524@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=alex@ghiti.fr \
--cc=alexander.shishkin@linux.intel.com \
--cc=aou@eecs.berkeley.edu \
--cc=himanshu.chauhan@oss.qualcomm.com \
--cc=irogers@google.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=jtaubepe@redhat.com \
--cc=kees@kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=oleg@redhat.com \
--cc=palmer@dabbelt.com \
--cc=peterz@infradead.org \
--cc=pjw@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=shuah@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox