* [PATCH] perf: RISC-V: check cpu_hw_evt before dereference in overflow IRQ
@ 2026-08-07 0:59 Xixin Liu
2026-08-07 3:46 ` sashiko-bot
2026-08-08 0:45 ` Paul Walmsley
0 siblings, 2 replies; 3+ messages in thread
From: Xixin Liu @ 2026-08-07 0:59 UTC (permalink / raw)
To: linux-riscv
Cc: atish.patra, anup, will, mark.rutland, pjw, palmer, aou, alex,
linux-arm-kernel, linux-perf-users, linux-kernel, liuxixin
The overflow IRQ handler dereferences cpu_hw_evt before the null check.
Move the check first. Defensive only; the cookie is valid on the normal
path today.
Signed-off-by: Xixin Liu <liuxixin@kylinos.cn>
---
drivers/perf/riscv_pmu_sbi.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
index dfc886dee5ad..f0dd9d2645b4 100644
--- a/drivers/perf/riscv_pmu_sbi.c
+++ b/drivers/perf/riscv_pmu_sbi.c
@@ -1050,11 +1050,13 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
u64 overflowed_ctrs = 0;
struct cpu_hw_events *cpu_hw_evt = dev;
u64 start_clock = sched_clock();
- struct riscv_pmu_snapshot_data *sdata = cpu_hw_evt->snapshot_addr;
+ struct riscv_pmu_snapshot_data *sdata;
if (WARN_ON_ONCE(!cpu_hw_evt))
return IRQ_NONE;
+ sdata = cpu_hw_evt->snapshot_addr;
+
/* Firmware counter don't support overflow yet */
fidx = find_first_bit(cpu_hw_evt->used_hw_ctrs, RISCV_MAX_COUNTERS);
if (fidx == RISCV_MAX_COUNTERS) {
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] perf: RISC-V: check cpu_hw_evt before dereference in overflow IRQ
2026-08-07 0:59 [PATCH] perf: RISC-V: check cpu_hw_evt before dereference in overflow IRQ Xixin Liu
@ 2026-08-07 3:46 ` sashiko-bot
2026-08-08 0:45 ` Paul Walmsley
1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-08-07 3:46 UTC (permalink / raw)
To: Xixin Liu; +Cc: linux-perf-users
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
Pre-existing issues:
- [High] This problem wasn't introduced by this patch, but skipping non-sampling events during overflow handling fails to clear their hardware overflow state, causing an interrupt storm.
- [High] This problem wasn't introduced by this patch, but the `BIT()` macro is improperly used with 64-bit masks, causing undefined behavior and corruption on RV32 systems when counter indices are >= 32.
- [High] This problem wasn't introduced by this patch, but incorrect interrupt pending bit clearance bypasses alternative instructions, causing interrupt storms on custom PMUs (e.g., Andes).
- [High] This problem wasn't introduced by this patch, but global variable `cmask` is defined as a 32-bit `unsigned long` on RV32 but is processed as a 64-bit bitmap, causing out-of-bounds memory reads.
- [High] This problem wasn't introduced by this patch, but restarting overflowed hardware counters incorrectly mixes `unsigned long` arrays with `u64` masks, breaking counter isolation for indices >= 32 on RV32 systems.
--
--- Patch [1]: [PATCH] perf: RISC-V: check cpu_hw_evt before dereference in overflow IRQ ---
commit 4fa941d0eec411e362522077608e4fec275e7349
Author: Xixin Liu <liuxixin@kylinos.cn>
perf: RISC-V: check cpu_hw_evt before dereference in overflow IRQ
The overflow IRQ handler dereferences cpu_hw_evt before the null check.
Move the check first. Defensive only; the cookie is valid on the normal
path today.
> diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
> index 50220f7b46d9b..cb7148d0c87ad 100644
> --- a/drivers/perf/riscv_pmu_sbi.c
> +++ b/drivers/perf/riscv_pmu_sbi.c
> @@ -1050,11 +1050,13 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
> u64 overflowed_ctrs = 0;
> struct cpu_hw_events *cpu_hw_evt = dev;
> u64 start_clock = sched_clock();
> - struct riscv_pmu_snapshot_data *sdata = cpu_hw_evt->snapshot_addr;
> + struct riscv_pmu_snapshot_data *sdata;
>
> if (WARN_ON_ONCE(!cpu_hw_evt))
> return IRQ_NONE;
>
> + sdata = cpu_hw_evt->snapshot_addr;
> +
> /* Firmware counter don't support overflow yet */
> fidx = find_first_bit(cpu_hw_evt->used_hw_ctrs, RISCV_MAX_COUNTERS);
> if (fidx == RISCV_MAX_COUNTERS) {
[Severity: High]
This isn't a bug introduced by this patch, but does clearing the interrupt
pending bit manually here bypass alternative instructions?
For the Andes custom PMU, riscv_pmu_irq_num evaluates to 274. Using
BIT(274) on a 64-bit integer overflows and wraps to BIT(18), which would
erroneously clear bit 18 in the standard CSR_SIP register instead of using
the custom register.
Could this cause an interrupt storm on custom PMUs like Andes?
[Severity: High]
This problem wasn't introduced by this patch, but looking further down in
pmu_sbi_ovf_handler(), does skipping non-sampling events during overflow
handling fail to clear their hardware overflow state?
drivers/perf/riscv_pmu_sbi.c:pmu_sbi_ovf_handler() {
...
/* Skip if invalid event or user did not request a sampling */
if (!event || !is_sampling_event(event))
continue;
...
}
When a non-sampling counting event overflows, its bit isn't added to
overflowed_ctrs.
Consequently, when restarting the counter, the
SBI_PMU_START_FLAG_SET_INIT_VALUE flag isn't set, which means the hardware
overflow state (scountovf) isn't cleared and the interrupt is immediately
re-asserted.
Will this cause an interrupt storm?
[Severity: High]
This is a pre-existing issue, but does using the BIT() macro against 64-bit
variables like overflow and overflowed_ctrs cause undefined behavior on
32-bit RISC-V systems?
drivers/perf/riscv_pmu_sbi.c:pmu_sbi_ovf_handler() {
...
/* check if the corresponding bit is set in scountovf or overflow mask in shmem */
if (!(overflow & BIT(hidx)))
continue;
/*
* Keep a track of overflowed counters so that they can be started
* with updated initial value.
*/
overflowed_ctrs |= BIT(lidx);
...
}
On RV32, BIT() resolves to a 32-bit unsigned long, so shifting by 32 or more
results in truncation or wrapping.
Should this use BIT_ULL() instead?
[Severity: High]
This problem wasn't introduced by this patch, but is cmask undersized
for a 64-bit bitmap on 32-bit architectures?
drivers/perf/riscv_pmu_sbi.c:
...
static unsigned long cmask;
...
drivers/perf/riscv_pmu_sbi.c:pmu_sbi_event_map() {
...
for_each_set_bit(i, &cmask, RISCV_MAX_COUNTERS) {
...
}
On RV32, unsigned long is 4 bytes, but for_each_set_bit() with
RISCV_MAX_COUNTERS (64) expects an 8-byte buffer, which would cause an
out-of-bounds read into adjacent memory.
Should this be defined using DECLARE_BITMAP(cmask, RISCV_MAX_COUNTERS)?
[Severity: High]
This is a pre-existing issue, but does this bitwise operation incorrectly mix
a 32-bit unsigned long element (on RV32) with a 64-bit u64 mask?
drivers/perf/riscv_pmu_sbi.c:pmu_sbi_start_ovf_ctrs_sbi() {
...
ctr_start_mask = cpu_hw_evt->used_hw_ctrs[i] & ~ctr_ovf_mask;
...
}
For i=1 (handling counters 32-63), the 64-bit result is truncated when
assigned to the 32-bit ctr_start_mask, erroneously evaluating against the
lower 32 bits of ctr_ovf_mask instead of the upper 32 bits.
Could this break counter isolation for indices >= 32?
--
Sashiko AI review · https://sashiko.dev/#/patchset/prp0001riscv.1786064390.git.liuxixin@kylinos.cn?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] perf: RISC-V: check cpu_hw_evt before dereference in overflow IRQ
2026-08-07 0:59 [PATCH] perf: RISC-V: check cpu_hw_evt before dereference in overflow IRQ Xixin Liu
2026-08-07 3:46 ` sashiko-bot
@ 2026-08-08 0:45 ` Paul Walmsley
1 sibling, 0 replies; 3+ messages in thread
From: Paul Walmsley @ 2026-08-08 0:45 UTC (permalink / raw)
To: Xixin Liu
Cc: linux-riscv, atish.patra, anup, will, mark.rutland, pjw, palmer,
aou, alex, linux-arm-kernel, linux-perf-users, linux-kernel
Hi,
On Fri, 7 Aug 2026, Xixin Liu wrote:
> The overflow IRQ handler dereferences cpu_hw_evt before the null check.
> Move the check first. Defensive only; the cookie is valid on the normal
> path today.
>
> Signed-off-by: Xixin Liu <liuxixin@kylinos.cn>
Could you please add a Fixes: tag? Also, if it was written with LLM
assistance, please add the appropriate Assisted-by: tag.
thanks
- Paul
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-08 0:45 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-07 0:59 [PATCH] perf: RISC-V: check cpu_hw_evt before dereference in overflow IRQ Xixin Liu
2026-08-07 3:46 ` sashiko-bot
2026-08-08 0:45 ` Paul Walmsley
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).