From: sashiko-bot@kernel.org
To: "Florian Fainelli" <f.fainelli@gmail.com>
Cc: "open list:PERFORMANCE EVENTS SUBSYSTEM"
<linux-perf-users@vger.kernel.org>
Subject: Re: [PATCH 3/3] MIPS: perf: Add SB1 and SB1A performance counter support
Date: Thu, 12 Nov 2026 19:38:16 +0000 [thread overview]
Message-ID: <sashiko-outbox-211771@kernel.org> (raw)
In-Reply-To: <20261112190916.3725141-4-f.fainelli@gmail.com>
Thank you for your contribution! Sashiko AI review found 4 potential
issues to consider:
- [High] MIPS: perf: double hw_perf_event_destroy() call when
validate_group() fails
- [Medium] MIPS: perf: IP7 left unmasked after irq_work_run() disables
last SB1 event
- [Medium] MIPS: perf: mipspmu_event_init() returns -EOPNOTSUPP before
checking attr.type
- [Low] docs: mips: sb1-pmu: heading underline too short for section
title
--
commit 4595e65c6c56d05599f7d396b72896c6da74a174
Author: Florian Fainelli <f.fainelli@gmail.com>
MIPS: perf: Add SB1 and SB1A performance counter support
This commit adds MIPS PMU support for the four CPU-local performance
counters on SB1 and SB1A processors, along with sysfs event aliases and
documentation.
> diff --git a/Documentation/arch/mips/sb1-pmu.rst b/Documentation/arch/mips/sb1-pmu.rst
> new file mode 100644
> index 0000000000000..d589a6262c65f
> --- /dev/null
> +++ b/Documentation/arch/mips/sb1-pmu.rst
> @@ -0,0 +1,162 @@
[ ... ]
> +Counter selection and mode filtering
> +-----------------------------------
[Severity: Low]
The hyphen underline here is 35 characters for a 36-character heading,
which triggers a Sphinx "Title underline too short" warning during
htmldocs builds.
> diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
> index 196a070349b09..765cdb6f8cae3 100644
> --- a/arch/mips/kernel/perf_event_mipsxx.c
> +++ b/arch/mips/kernel/perf_event_mipsxx.c
[ ... ]
> @@ -564,6 +627,14 @@ static void mipspmu_enable(struct pmu *pmu)
> write_unlock(&pmuint_rwlock);
> #endif
> resume_local_counters();
> + if (is_sb1_pmu() &&
> + !bitmap_empty(this_cpu_ptr(&cpu_hw_events)->used_mask,
> + mipspmu.num_counters) &&
> + !irq_percpu_is_enabled(mipspmu.irq)) {
> + /* Count/Compare shares IP7, but SiByte uses a separate timer. */
> + write_c0_compare(read_c0_count() - 1);
> + enable_percpu_irq(mipspmu.irq, IRQ_TYPE_NONE);
> + }
> }
>
> /*
> @@ -579,6 +650,8 @@ static void mipspmu_enable(struct pmu *pmu)
> */
> static void mipspmu_disable(struct pmu *pmu)
> {
> + if (is_sb1_pmu() && irq_percpu_is_enabled(mipspmu.irq))
> + disable_percpu_irq(mipspmu.irq);
> pause_local_counters();
> #ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS
> write_lock(&pmuint_rwlock);
[Severity: Medium]
Can this leave IP7 unmasked in hardware when the last event on a CPU is
disabled from inside the PMU interrupt handler?
handle_percpu_devid_irq()
chip->irq_ack() /* mask_mips_irq() masks IP7 */
mipsxx_pmu_handle_irq()
mipsxx_pmu_handle_shared_irq()
handle_associated_event()
perf_event_overflow() /* queues pending_disable_irq */
irq_work_run()
perf_pending_disable()
...
mipspmu_disable()
disable_percpu_irq() /* clears percpu_enabled, masks IP7 */
mipspmu_del() /* clears last bit in used_mask */
mipspmu_enable() /* used_mask empty, skips enable */
chip->irq_eoi()
unmask_mips_irq() <-- unmasks IP7 in CP0 Status
When a sampling event with a refresh limit (PERF_EVENT_IOC_REFRESH)
overflows and auto-disables via irq_work_run(), disable_percpu_irq()
clears the CPU in desc->percpu_enabled, but handle_percpu_devid_irq()
then runs chip->irq_eoi() (unmask_mips_irq()), which sets STATUSF_IP7
again. That leaves IP7 unmasked with no events scheduled while
irq_percpu_is_enabled() returns false, so spurious interrupts fire
whenever CP0 Count wraps past Compare and sb1_pmu_cpu_offline() will
also skip masking IP7.
[ ... ]
> @@ -657,6 +737,10 @@ static int mipspmu_event_init(struct perf_event *event)
> if (has_branch_stack(event))
> return -EOPNOTSUPP;
>
> + if (is_sb1_pmu() && (event->attr.precise_ip || event->attr.config1 ||
> + event->attr.config2))
> + return -EOPNOTSUPP;
> +
> switch (event->attr.type) {
> case PERF_TYPE_RAW:
> case PERF_TYPE_HARDWARE:
[Severity: Medium]
Should the precise_ip, config1 and config2 check come after the
event->attr.type switch?
Checking those fields first makes mipspmu_event_init() return
-EOPNOTSUPP instead of -ENOENT for events that do not target this PMU
(for example, PERF_TYPE_BREAKPOINT where bp_addr and bp_len union with
config1 and config2, or any PMU registered after mipspmu), causing
perf_init_event() to abort its PMU list walk early.
> @@ -683,7 +767,10 @@ static int mipspmu_event_init(struct perf_event *event)
> if (err)
> return err;
>
> - return __hw_perf_event_init(event);
> + err = __hw_perf_event_init(event);
> + if (err && is_sb1_pmu() && !event->destroy)
> + hw_perf_event_destroy(event);
> + return err;
> }
[Severity: High]
Does a failure in validate_group() cause hw_perf_event_destroy() to run
twice for the same event?
arch/mips/kernel/perf_event_mipsxx.c:__hw_perf_event_init() {
...
if (event->group_leader != event)
err = validate_group(event);
event->destroy = hw_perf_event_destroy;
if (err)
event->destroy(event);
return err;
}
When validate_group() fails (such as when a fourth non-cycle event is
added to a group), __hw_perf_event_init() calls event->destroy(event)
and returns err with event->destroy still set to hw_perf_event_destroy.
Because perf_try_init_event() skips clearing event->destroy on
event_init() failure, perf_event_alloc()'s __free(__free_event) cleanup
calls event->destroy(event) a second time. That decrements
active_events twice for one increment, dropping active_events to zero
while the group's earlier events are still open and resetting hardware
counters across all CPUs via on_each_cpu(reset_counters, ...).
Also, gating the !event->destroy cleanup on is_sb1_pmu() leaves
active_events leaked on non-SB1 MIPS PMUs when __hw_perf_event_init()
fails before setting event->destroy. If __hw_perf_event_init() only
sets event->destroy after validate_group() succeeds (or clears it after
calling it), mipspmu_event_init() can handle the error cleanup in one
place.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261112190916.3725141-1-f.fainelli@gmail.com?part=3
prev parent reply other threads:[~2026-11-12 19:38 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-12 19:09 [PATCH 0/3] MIPS: SiByte: Add HW PMU support Florian Fainelli
2026-11-12 19:09 ` [PATCH 1/3] MIPS: SiByte: Wire up the CPU interrupt controller Florian Fainelli
2026-11-12 19:35 ` sashiko-bot
2026-11-12 19:09 ` [PATCH 2/3] MIPS: perf: Add SB1 userspace callchain unwinding Florian Fainelli
2026-11-12 19:31 ` sashiko-bot
2026-11-12 19:09 ` [PATCH 3/3] MIPS: perf: Add SB1 and SB1A performance counter support Florian Fainelli
2026-11-12 19:18 ` Randy Dunlap
2026-11-12 19:38 ` sashiko-bot [this message]
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-211771@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=f.fainelli@gmail.com \
--cc=linux-perf-users@vger.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.