[PATCH v2 0/2] perf: Add Raspberry Pi AXI PMU driver

Ian Rogers <[email protected]>
Newsgroups org.kernel.vger.linux-perf-users,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
This patch series adds an uncore Performance Monitoring Unit (PMU) driver
for Broadcom AXI system and VideoCore VPU performance monitors found on
Raspberry Pi SoCs (BCM2835 through BCM2712 / Raspberry Pi 1 through 5).

Motivation & Background
------------------------
Currently, Linux lacks a standard perf-API compatible driver for the
Broadcom AXI performance counter blocks on Raspberry Pi platforms. Prior
out-of-tree vendor solutions relied on custom debugfs nodes and ad-hoc
kthreads, preventing integration with standard Linux perf tooling (`perf stat`,
`perf list`, etc.).

This driver implements standard `struct pmu` hardware uncore callbacks
under `drivers/perf/`, exposing human-readable sysfs event aliases, unit
scaling (`Bytes`), and bus filtering directly to user space.

Key Architectural Improvements & Features
------------------------------------------
1. Standard Linux Perf Integration:
   - Exposes uncore AXI interconnect events via `/sys/bus/event_source/devices/rpi_axi_pmu/`.
   - Supports event sampling and hardware counter accumulation (`local64_add`),
     automatically managing 31-bit hardware counter wraparound across high-bandwidth
     interconnect transfers.

2. CPU Hotplug Support (`cpuhp`):
   - Registers dynamic CPU hotplug notifiers (`CPUHP_AP_ONLINE_DYN`).
   - Automatically migrates PMU context (`perf_pmu_migrate_context`) to an online
     CPU core when a designated CPU goes offline, avoiding stale uncore state.

3. Hybrid Memory-Mapped & Mailbox Work Queue Architecture:
   - System Monitor (MMIO): Performs fast atomic-safe memory reads (~15ns)
     directly mapped over ARM physical memory space (`MON__SYSTEM`).
   - VPU Monitor (Mailbox IPC): For Broadcom BCM2835-BCM2711 platforms (RPi 1-4),
     VideoCore VPU monitor IPC calls are offloaded to process context via a dedicated
     workqueue (`vpu_work`) and serialized under `vpu_mutex`. This avoids atomic
     sleeps or blocking in timer/interrupt context.

4. SoC Generation Support:
   - Patch 1 adds core driver support for Broadcom BCM2835-BCM2711 (RPi 1-4).
   - Patch 2 expands support for Broadcom BCM2712 (Raspberry Pi 5), adding PCIe RP1
     Southbridge links, HEVC decoder, HVS display engine, and Cortex-A76 DSU L3
     interconnect monitoring.

Hardware Validation
-------------------
The driver has been validated on real hardware across multiple SoC generations:
- Raspberry Pi 400 (BCM2711): Validated System L2, ARM CPU, and VideoCore VPU
  firmware mailbox IPC performance counters.
- Raspberry Pi 5 (BCM2712): Validated live byte throughput across HVS display
  refresh cycles, Cortex-A76 DSU L3 interconnect memory traffic, and PCIe RP1
  Southbridge transfers.

Changes in v2
-------------
- Match Data Initialization: In rpi_axi_pmu__init(), set pmu->chip via
  of_device_get_match_data(dev) to ensure BCM2712 match data is correctly parsed.
- Sysfs Event Visibility Filtering: Updated rpi_axi_pmu_events_is_visible() to
  properly filter all 7 BCM2712 master filtered event aliases (arm_, pcie0_,
  hvs_filtered, emmc0_) on BCM2835-BCM2711 systems, and hide legacy RPi 1-4
  aliases on BCM2712 systems.
- Unmapped Monitor Check: Added monitor base_address and initialization check to
  config_is_valid(). Events targeting uninitialized or unmapped monitors (e.g. missing
  memory resource or monitor=1 on BCM2712) are properly rejected with -EINVAL.
- CPU Affinity Enforcement: Restrict uncore events in event_init() to event->cpu == pmu->cpu
  to prevent orphaned uncore events when a non-PMU CPU goes offline.
- 31-bit Counter Wrap Delta: Mask counter accumulation with delta = (new_count - prev_count) & 0x7FFFFFFF
  in read(), timer_handler(), and vpu_work_handler() to prevent 2B+ event spikes on counter overflow.
- Stopped Event Guard: Return early in rpi_axi_pmu_read() if event->hw.state & PERF_HES_STOPPED.
- Lockless Race Fix: Pass bus and filter explicitly to rpi_axi_pmu_enable_bus_watcher()
  under spinlock to prevent lockless read races in vpu_work_handler().
- Slot Reuse Clean: Set enabled[idx] = false in rpi_axi_pmu_del() when refcount[idx] == 0 so
  re-allocated watcher slots properly enable hardware watchers.
- Events Array Bounds: Return -ENOSPC in rpi_axi_pmu_add() if pmu->events array is full.
- Timer Cancel Race Fix: Re-acquire pmu->lock after hrtimer_cancel() in rpi_axi_pmu_del()
  and re-verify active_events > 0 before returning.
- Hotplug Timer Migration: Cancel and re-pin pmu->hrtimer to target CPU in rpi_axi_pmu_offline_cpu().
- Registration Order: Call perf_pmu_register() before cpuhp_state_add_instance() in probe,
  and cancel hrtimer before cancel_work_sync() and unregister in exit teardown.
- Header & Style Cleanups: Removed <linux/mod_devicetable.h> and <linux/version.h>,
  updated rpi_axi_pmu_match[] terminator to { }, and fixed C variable declaration style.

Ian Rogers (2):
  perf: Add Raspberry Pi BCM2835 AXI PMU driver
  perf: Add Raspberry Pi 5 (BCM2712) AXI PMU support

 drivers/perf/Kconfig       |   10 +
 drivers/perf/Makefile      |    1 +
 drivers/perf/rpi_axi_pmu.c | 2001 ++++++++++++++++++++++++++++++++++++
 3 files changed, 2012 insertions(+)
 create mode 100644 drivers/perf/rpi_axi_pmu.c

-- 
2.55.0.679.g6767b8d81c-goog
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.