All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Atish Patra" <atish.patra@linux.dev>
Cc: linux-perf-users@vger.kernel.org, robh@kernel.org,
	conor+dt@kernel.org, devicetree@vger.kernel.org
Subject: Re: [PATCH v7 12/22] RISC-V: perf: Modify the counter discovery mechanism
Date: Mon, 22 Jun 2026 08:24:47 +0000	[thread overview]
Message-ID: <20260622082447.D0DC51F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260622-counter_delegation-v7-12-0ba2fd34614e@meta.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

New issues:
- [High] Hardware counter physical indices and SBI logical counter indices for firmware counters can overlap, causing array overwrites and state clobbering in `pmu_ctr_list` and the per-CPU `events` array.
- [Medium] Firmware counters are not stopped in `rvpmu_sbi_stop_all()` when counter delegation is disabled, leaving them running unexpectedly.

Pre-existing issues:
- [High] `cmask` and `firmware_cmask` are defined as `unsigned long` and accessed via `BIT(i)` and `for_each_set_bit()`, causing shift overflow and out-of-bounds memory reads on 32-bit architectures.
- [High] Missing `.remove` hook combined with global `pmu_ctr_list` overwrite causes a memory leak and a subsequent NULL pointer dereference on re-probe failure.
--

commit 98634f15c972a5ad2282dff7c8f2da3bfc47efa8
Author: Atish Patra <atishp@rivosinc.com>

RISC-V: perf: Modify the counter discovery mechanism

If both counter delegation and SBI PMU are present, counter delegation
is used for hardware counters while the SBI PMU is used for firmware
counters. The driver is updated to probe via SBI PMU to distinguish
the firmware counters and cache the discovery info.

> diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
> index 80c7249ee1662..d44f47613aa1a 100644
> --- a/drivers/perf/riscv_pmu_sbi.c
> +++ b/drivers/perf/riscv_pmu_sbi.c
[ ... ]
> @@ -101,6 +116,8 @@ static unsigned int riscv_pmu_irq;
>  
>  /* Cache the available counters in a bitmask */
>  static unsigned long cmask;
> +/* Cache the available firmware counters in another bitmask */
> +static unsigned long firmware_cmask;

[Severity: High]
This is a pre-existing issue, but on 32-bit architectures (RV32), unsigned
long is 32 bits wide, while RISCV_MAX_COUNTERS is 64.

Does this cause shift overflows when accessed via BIT(i) where i can reach
up to 63?

Additionally, does using for_each_set_bit() with this 32-bit mask cause
out-of-bounds memory reads, as the macro expects an array large enough for
64 bits?

[ ... ]
> @@ -868,34 +885,38 @@ static int rvpmu_sbi_find_num_ctrs(void)
[ ... ]
> -static int rvpmu_sbi_get_ctrinfo(int nctr, unsigned long *mask)
> +static int rvpmu_sbi_get_ctrinfo(u32 nsbi_ctr, u32 *num_fw_ctr, u32 *num_hw_ctr)
>  {
[ ... ]
> -	for (i = 0; i < nctr; i++) {
> +	for (i = 0; i < nsbi_ctr; i++) {
>  		ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_GET_INFO, i, 0, 0, 0, 0, 0);
>  		if (ret.error)
>  			/* The logical counter ids are not expected to be contiguous */
>  			continue;
>  
> -		*mask |= BIT(i);
> -
>  		cinfo.value = ret.value;
> -		if (cinfo.type == SBI_PMU_CTR_TYPE_FW)
> -			num_fw_ctr++;
> -		else
> -			num_hw_ctr++;
> -		pmu_ctr_list[i].value = cinfo.value;
> +		if (cinfo.type == SBI_PMU_CTR_TYPE_FW) {
> +			/* Track firmware counters in a different mask */
> +			firmware_cmask |= BIT(i);
> +			pmu_ctr_list[i].value = cinfo.value;

[Severity: High]
Can the hardware counter physical indices and the SBI logical counter
indices overlap, causing array overwrites in pmu_ctr_list?

When both counter delegation and the SBI PMU are available, pmu_ctr_list
is first populated using hardware physical CSR indices (0-31) in
rvpmu_deleg_find_ctrs().

Then, rvpmu_sbi_get_ctrinfo() populates firmware counters using the SBI
logical index i. Because the SBI specification allows logical indices to
start at 0, an SBI implementation might assign logical indices to firmware
counters that overlap with the physical CSR indices.

Could this silently overwrite the hardware counter definitions in
pmu_ctr_list[i], and later corrupt the active cpuc->events[idx] array when
both types of counters share overlapping indices?

[Severity: Medium]
Does splitting firmware counters into firmware_cmask and intentionally
excluding them from cmask leave firmware counters running unexpectedly?

In rvpmu_sbi_stop_all(), the code only stops counters present in pmu->cmask:

static inline void rvpmu_sbi_stop_all(struct riscv_pmu *pmu)
{
	...
	sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP,
		  0, pmu->cmask, SBI_PMU_STOP_FLAG_RESET, 0, 0, 0);
}

When counter delegation is disabled, the fallback path calls
rvpmu_sbi_stop_all(pmu), which now exclusively stops hardware counters.

Could this leave firmware counters running across CPU hotplug and PMU
initialization, potentially leading to stale counts and unexpected overflows?

> +			*num_fw_ctr = *num_fw_ctr + 1;
> +		} else if (cinfo.type == SBI_PMU_CTR_TYPE_HW &&
> +			   !riscv_pmu_cdeleg_available_boot()) {
> +			*num_hw_ctr = *num_hw_ctr + 1;
> +			cmask |= BIT(i);
> +			pmu_ctr_list[i].value = cinfo.value;
> +		}
>  	}
[ ... ]
> @@ -1159,16 +1180,48 @@ static void rvpmu_ctr_stop(struct perf_event *event, unsigned long flag)
[ ... ]
> -static int rvpmu_find_num_ctrs(void)
> +static int rvpmu_find_ctrs(void)
>  {
> -	return rvpmu_sbi_find_num_ctrs();
> -	/* TODO: Counter delegation implementation */
> -}
> +	int num_sbi_counters = 0;
> +	u32 num_deleg_counters = 0;
> +	u32 num_hw_ctr = 0, num_fw_ctr = 0, num_ctr = 0;
> +	/*
> +	 * We don't know how many firmware counters are available. Just allocate
> +	 * for maximum counters the driver can support. The default is 64 anyways.
> +	 */
> +	pmu_ctr_list = kcalloc(RISCV_MAX_COUNTERS, sizeof(*pmu_ctr_list),
> +			       GFP_KERNEL);

[Severity: High]
This is a pre-existing issue, but does missing a .remove hook combined with
this global pmu_ctr_list overwrite cause a memory leak and subsequent NULL
pointer dereference on re-probe failure?

The platform driver lacks a .remove callback and does not set
suppress_bind_attrs, meaning it can be unbound via sysfs, leaving the PMU
registered and active.

If the driver is rebound, rvpmu_device_probe() executes again and calls
rvpmu_find_ctrs(), which unconditionally allocates pmu_ctr_list via kcalloc,
overwriting the global pointer and leaking the original memory.

When perf_pmu_register() then fails because the PMU is already registered,
the error path in rvpmu_device_probe() calls kfree(pmu_ctr_list) and sets it
to NULL.

Could the still-active PMU from the first probe then dereference this NULL
pointer during any subsequent perf event operations?

> +	if (!pmu_ctr_list)
> +		return -ENOMEM;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260622-counter_delegation-v7-0-0ba2fd34614e@meta.com?part=12

  reply	other threads:[~2026-06-22  8:24 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-22  8:04 [PATCH v7 00/22] Add Counter delegation ISA extension support Atish Patra
2026-06-22  8:04 ` Atish Patra
2026-06-22  8:04 ` [PATCH v7 01/22] RISC-V: perf: fix resource cleanup on driver probe failure Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:24   ` sashiko-bot
2026-06-22  8:04 ` [PATCH v7 02/22] RISC-V: Add Sxcsrind ISA extension CSR definitions Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:04 ` [PATCH v7 03/22] RISC-V: Add Sxcsrind ISA extension definition and parsing Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:04 ` [PATCH v7 04/22] dt-bindings: riscv: add Sxcsrind ISA extension description Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:04 ` [PATCH v7 05/22] RISC-V: Define indirect CSR access helpers Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:17   ` sashiko-bot
2026-06-22  8:04 ` [PATCH v7 06/22] RISC-V: Add Smcntrpmf extension parsing Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:17   ` sashiko-bot
2026-06-22  8:04 ` [PATCH v7 07/22] dt-bindings: riscv: add Smcntrpmf ISA extension description Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:04 ` [PATCH v7 08/22] RISC-V: Add Sscfg extension CSR definition Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:04 ` [PATCH v7 09/22] RISC-V: Add Ssccfg/Smcdeleg ISA extension definition and parsing Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:18   ` sashiko-bot
2026-06-22  8:04 ` [PATCH v7 10/22] dt-bindings: riscv: add Counter delegation ISA extensions description Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:20   ` sashiko-bot
2026-06-22  8:04 ` [PATCH v7 11/22] RISC-V: perf: Restructure the SBI PMU code Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:04 ` [PATCH v7 12/22] RISC-V: perf: Modify the counter discovery mechanism Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:24   ` sashiko-bot [this message]
2026-06-22  8:04 ` [PATCH v7 13/22] RISC-V: perf: Add a mechanism to defined legacy event encoding Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:04 ` [PATCH v7 14/22] RISC-V: perf: Implement supervisor counter delegation support Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:33   ` sashiko-bot
2026-06-22  8:04 ` [PATCH v7 15/22] RISC-V: perf: Skip PMU SBI extension when not implemented Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:04 ` [PATCH v7 16/22] RISC-V: perf: Use config2/vendor table for event to counter mapping Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:30   ` sashiko-bot
2026-06-22  8:04 ` [PATCH v7 17/22] RISC-V: perf: Add legacy event encodings via sysfs Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:04 ` [PATCH v7 18/22] RISC-V: perf: Add Qemu virt machine events Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:39   ` sashiko-bot
2026-06-22  8:04 ` [PATCH v7 19/22] tools/perf: Support event code for arch standard events Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:34   ` sashiko-bot
2026-06-22  8:04 ` [PATCH v7 20/22] tools/perf: Add RISC-V CounterIDMask event field Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:04 ` [PATCH v7 21/22] TEST(do-not-upstream): fake qemu-virt PMU events for cdeleg counter-mask testing Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:32   ` sashiko-bot
2026-06-22  8:04 ` [PATCH v7 22/22] TEST(do-not-upstream): fake qemu vendor JSON + mapfile entry for CounterIDMask path Atish Patra
2026-06-22  8:04   ` Atish Patra
2026-06-22  8:35   ` sashiko-bot

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=20260622082447.D0DC51F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=atish.patra@linux.dev \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.