Devicetree
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Ian Rogers" <irogers@google.com>
Cc: linux-perf-users@vger.kernel.org, devicetree@vger.kernel.org,
	robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v15 2/3] perf: Add Raspberry Pi BCM2835 AXI PMU driver
Date: Tue, 03 Nov 2026 00:08:08 +0000	[thread overview]
Message-ID: <sashiko-outbox-194360@kernel.org> (raw)
In-Reply-To: <20261102234301.2242242-3-irogers@google.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] perf: rpi_axi_pmu: NULL ctx deref in rpi_axi_pmu__validate_group()
- [Low] perf: rpi_axi_pmu: enforce RPI_AXI_MAX_EVENTS limit in group validation
- [Low] perf: rpi_axi_pmu: Kconfig depends on undefined symbol RPI_AXIPERF
--

commit 3a239421611725bee7d8e283cbdeacf0ec2bf701
Author: Ian Rogers <irogers@google.com>

perf: Add Raspberry Pi BCM2835 AXI PMU driver

This commit adds a perf PMU driver for the Raspberry Pi System and VideoCore
AXI performance monitors on Broadcom BCM2835 and BCM2711 platforms.

> diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
> index 245e7bb763b99..c1d7d64caba28 100644
> --- a/drivers/perf/Kconfig
> +++ b/drivers/perf/Kconfig
> @@ -325,4 +325,18 @@ config NVIDIA_TEGRA410_C2C_PMU
>  	  Enable perf support for counters in NVIDIA C2C interface of NVIDIA
>  	  Tegra410 SoC.
>  
> +config RPI_AXI_PMU
> +	tristate "Raspberry Pi AXI Performance Monitor"
> +	depends on ARCH_BCM2835 || COMPILE_TEST
> +	depends on !RPI_AXIPERF

[Severity: Low]
Should this dependency on !RPI_AXIPERF be removed from the patch before it is
applied?

RPI_AXIPERF is not defined in the mainline kernel tree, and although the note
below the --- separator asks maintainers to delete this line when applying,
tools like git am and b4 strip the note and commit the undefined Kconfig
symbol directly, which triggers scripts/checkkconfigsymbols.py warnings.

[ ... ]

> diff --git a/drivers/perf/rpi_axi_pmu.c b/drivers/perf/rpi_axi_pmu.c
> new file mode 100644
> index 0000000000000..f194b8633e434
> --- /dev/null
> +++ b/drivers/perf/rpi_axi_pmu.c

[ ... ]

> +static bool rpi_axi_pmu__validate_group(struct perf_event *event)
> +{
> +	struct perf_event *sibling, *leader = event->group_leader;
> +	struct rpi_axi_hw_events fake_hw_events[MON_MAX];
> +
> +	rpi_axi_hw_events__init(&fake_hw_events[MON_SYSTEM]);
> +	rpi_axi_hw_events__init(&fake_hw_events[MON_VPU]);
> +	if (!rpi_axi_pmu__validate_event(event->pmu, fake_hw_events, leader))
> +		return false;
> +	for_each_sibling_event(sibling, leader) {
> +		if (!rpi_axi_pmu__validate_event(event->pmu, fake_hw_events, sibling))
> +			return false;
> +	}
> +	return rpi_axi_pmu__validate_event(event->pmu, fake_hw_events, event);
> +}

[Severity: High]
Can calling for_each_sibling_event(sibling, leader) when leader == event
cause a NULL pointer dereference under CONFIG_PROVE_LOCKING=y, and also
validate the group leader twice?

When userspace opens a standalone event or group leader via perf_event_open()
with group_fd == -1, perf_event_alloc() sets event->group_leader = event and
calls perf_init_event() -> perf_try_init_event() while event->ctx is still
NULL:

kernel/events/core.c:perf_try_init_event() {
	if (event->group_leader != event && pmu->task_ctx_nr != perf_sw_context) {
		ctx = perf_event_ctx_lock_nested(event->group_leader,
						 SINGLE_DEPTH_NESTING);
		BUG_ON(!ctx);
	}

	event->pmu = pmu;
	ret = pmu->event_init(event);
}

Because rpi_axi_pmu_event_init() -> rpi_axi_pmu__validate_group() does not
return early when leader == event, it proceeds to for_each_sibling_event():

include/linux/perf_event.h:
#define for_each_sibling_event(sibling, event)			\
	lockdep_assert_event_ctx(event);			\
	if ((event)->group_leader == (event))			\
		list_for_each_entry((sibling), &(event)->sibling_list, sibling_list)

With CONFIG_PROVE_LOCKING=y, lockdep_assert_event_ctx(leader) evaluates
lockdep_is_held(&leader->ctx->mutex) while leader->ctx is NULL, dereferencing
a near-NULL address inside lockdep. In addition, when leader == event, the
final rpi_axi_pmu__validate_event(event->pmu, fake_hw_events, event) call
validates the leader a second time.

Should rpi_axi_pmu__validate_group() return true immediately after validating
leader when leader == event (or skip calling rpi_axi_pmu__validate_group() in
rpi_axi_pmu_event_init() when event->group_leader == event)?

[ ... ]

> +static int rpi_axi_pmu_add(struct perf_event *event, int flags)
> +{
> +	struct rpi_axi_pmu *pmu = pmu_to_rpi_axi_pmu(event->pmu);
> +	enum monitor mon = config_to_monitor(event->attr.config);
> +	struct rpi_axi_hw_events *hw_events = &pmu->monitor[mon].hw_events;
> +	unsigned long spinflags;
> +	int idx, slot = -1;
> +
> +	raw_spin_lock_irqsave(&pmu->lock, spinflags);
> +	idx = rpi_axi_hw_events__get_alloc_event_idx(hw_events, event);
> +	if (idx < 0) {
> +		raw_spin_unlock_irqrestore(&pmu->lock, spinflags);
> +		return -EAGAIN;
> +	}
> +
> +	for (int i = 0; i < RPI_AXI_MAX_EVENTS; i++) {
> +		if (!pmu->events[i]) {
> +			slot = i;
> +			pmu->events[i] = event;
> +			break;
> +		}
> +	}
> +
> +	if (slot < 0) {

[Severity: Low]
What happens if userspace creates an event group with more than
RPI_AXI_MAX_EVENTS (66) hardware events targeting this PMU that share at most
3 (bus, filter) pairs per monitor?

In rpi_axi_pmu_event_init() -> rpi_axi_pmu__validate_group() ->
rpi_axi_pmu__validate_event() -> rpi_axi_hw_events__get_alloc_event_idx(),
events targeting the same (monitor, bus, filter) increment
fake_hw_events[mon].refcount[i] without checking the total number of PMU
events against RPI_AXI_MAX_EVENTS, so rpi_axi_pmu_event_init() succeeds.

However, when group_sched_in() attempts to schedule the group via
rpi_axi_pmu_add(), the 67th event will find no free slot in
pmu->events[RPI_AXI_MAX_EVENTS] and fail with -ENOSPC, causing
group_sched_in() to roll back all 66 previously added events on every
multiplexing rotation tick.

Should rpi_axi_pmu__validate_group() also reject groups whose total number of
events on this PMU exceeds RPI_AXI_MAX_EVENTS?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261102234301.2242242-1-irogers@google.com?part=2

  reply	other threads:[~2026-11-03  0:08 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-02 23:42 [PATCH v15 0/3] perf: Add Raspberry Pi AXI PMU driver Ian Rogers
2026-11-02 23:42 ` [PATCH v15 1/3] dt-bindings: perf: Add Broadcom Raspberry Pi AXI PMU definition Ian Rogers
2026-11-02 23:43 ` [PATCH v15 2/3] perf: Add Raspberry Pi BCM2835 AXI PMU driver Ian Rogers
2026-11-03  0:08   ` sashiko-bot [this message]
2026-11-02 23:43 ` [PATCH v15 3/3] perf: Add Raspberry Pi 5 (BCM2712) AXI PMU support Ian Rogers

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-194360@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=irogers@google.com \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox