* [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support
@ 2026-11-03 10:14 Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 01/13] dt-bindings: arm: pmu: Add Apple M3/M4/A18 Pro SoC CPU PMU compatibles Myria Sarvay via B4 Relay
` (12 more replies)
0 siblings, 13 replies; 19+ messages in thread
From: Myria Sarvay via B4 Relay @ 2026-11-03 10:14 UTC (permalink / raw)
To: Will Deacon, Mark Rutland, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sven Peter, Janne Grunau, Neal Gompa, Marc Zyngier
Cc: linux-arm-kernel, linux-perf-users, devicetree, linux-kernel,
asahi, Yuvan Shen, Myria Sarvay, Nick Chan
This series adds support for the CPU PMU in the new M3, M4 and A18 SoCs
presed in apple devices. These PMUs have new encodings for events, along
with larger codes for these events. All of these events are as Apple
describes them in the various kpep files found under /usr/share/kpep on
macOS 27. More events may exist, but we have no idea of their affinity,
or what they actually count, so we don't include them here.
These patches have been tested on my own M2 (t8133-j413) and M3
(t6031-j514c) devices, as well as by Yuvan on their M4 (t8132-j713)
device.
If possible, the device tree changes should probably go through
apple-soc, as this is where the recently picked up M4 Pro/Max dts are.
Tested-by: Yuvan Shen <yuvanshen09@gmail.com> # on t8132-j713
Signed-off-by: Myria Sarvay <myrialsarvay@gmail.com>
---
Myria Sarvay (12):
dt-bindings: arm: pmu: Add Apple M3/M4/A18 Pro SoC CPU PMU compatibles
drivers/perf: apple_m1: Remove unused variables
drivers/perf: apple_m1: Support per-implementation event size
drivers/perf: apple_m1: Use macros for per-implementation init functions
drivers/perf: apple_m1: Add Apple M3 Series Support
drivers/perf: apple_m1: Add Apple M4 Series Support
drivers/perf: apple_m1: Add Apple A18 Support
arm64: dts: apple: t603x: Add PMU Device Nodes
arm64: dts: apple: t8122: Add PMU Device Nodes
arm64: dts: apple: t604x: Add PMU Device Nodes
arm64: dts: apple: t8132: Add PMU Device Nodes
arm64: dts: apple: t8140: Add PMU Device Nodes
Nick Chan (1):
drivers/perf: apple_m1: Support per-implementation event tables
Documentation/devicetree/bindings/arm/pmu.yaml | 8 +
arch/arm64/boot/dts/apple/t6030.dtsi | 12 +
arch/arm64/boot/dts/apple/t6031-base.dtsi | 12 +
arch/arm64/boot/dts/apple/t6041.dtsi | 12 +
arch/arm64/boot/dts/apple/t8122.dtsi | 12 +
arch/arm64/boot/dts/apple/t8132.dtsi | 12 +
arch/arm64/boot/dts/apple/t8140.dtsi | 12 +
drivers/perf/apple_m1_cpu_pmu.c | 664 ++++++++++++++++++++++---
8 files changed, 662 insertions(+), 82 deletions(-)
---
base-commit: acb925da49876e74b806ccd48a7518d2d3368e5d
change-id: 20260929-m3-plus-pmu-events-e4010ab44135
Best regards,
--
Myria Sarvay <myrialsarvay@gmail.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 01/13] dt-bindings: arm: pmu: Add Apple M3/M4/A18 Pro SoC CPU PMU compatibles
2026-11-03 10:14 [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support Myria Sarvay via B4 Relay
@ 2026-11-03 10:14 ` Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 02/13] drivers/perf: apple_m1: Remove unused variables Myria Sarvay via B4 Relay
` (11 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Myria Sarvay via B4 Relay @ 2026-11-03 10:14 UTC (permalink / raw)
To: Will Deacon, Mark Rutland, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sven Peter, Janne Grunau, Neal Gompa, Marc Zyngier
Cc: linux-arm-kernel, linux-perf-users, devicetree, linux-kernel,
asahi, Yuvan Shen, Myria Sarvay
From: Myria Sarvay <myrialsarvay@gmail.com>
Document the compatibles for all current M3, M4 and A18 Pro SoC PMU
variants. Note that the M4+ are split out by chip codenames, instead of
name for the types of cores, as they no longer have individual names for
the performance and efficiency cores.
Signed-off-by: Myria Sarvay <myrialsarvay@gmail.com>
---
Documentation/devicetree/bindings/arm/pmu.yaml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/pmu.yaml b/Documentation/devicetree/bindings/arm/pmu.yaml
index f47baaefcdac..c27f06e82de1 100644
--- a/Documentation/devicetree/bindings/arm/pmu.yaml
+++ b/Documentation/devicetree/bindings/arm/pmu.yaml
@@ -22,8 +22,16 @@ properties:
- apm,potenza-pmu
- apple,avalanche-pmu
- apple,blizzard-pmu
+ - apple,brava-e-pmu
+ - apple,brava-p-pmu
+ - apple,donan-e-pmu
+ - apple,donan-p-pmu
+ - apple,everest-pmu
- apple,firestorm-pmu
- apple,icestorm-pmu
+ - apple,sawtooth-pmu
+ - apple,tahiti-e-pmu
+ - apple,tahiti-p-pmu
- arm,armv8-pmuv3 # Only for s/w models
- arm,arm1136-pmu
- arm,arm1176-pmu
--
2.56.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 02/13] drivers/perf: apple_m1: Remove unused variables
2026-11-03 10:14 [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 01/13] dt-bindings: arm: pmu: Add Apple M3/M4/A18 Pro SoC CPU PMU compatibles Myria Sarvay via B4 Relay
@ 2026-11-03 10:14 ` Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 03/13] drivers/perf: apple_m1: Support per-implementation event tables Myria Sarvay via B4 Relay
` (10 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Myria Sarvay via B4 Relay @ 2026-11-03 10:14 UTC (permalink / raw)
To: Will Deacon, Mark Rutland, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sven Peter, Janne Grunau, Neal Gompa, Marc Zyngier
Cc: linux-arm-kernel, linux-perf-users, devicetree, linux-kernel,
asahi, Yuvan Shen, Myria Sarvay
From: Myria Sarvay <myrialsarvay@gmail.com>
These variables are calculated elsewhere as well, remove the extra dead
code.
Signed-off-by: Myria Sarvay <myrialsarvay@gmail.com>
Fixes: a639027a1be1 ("drivers/perf: Add Apple icestorm/firestorm CPU PMU driver")
---
drivers/perf/apple_m1_cpu_pmu.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index 1f73c8a77462..de4026c63afd 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -421,13 +421,6 @@ static void m1_pmu_configure_counter(unsigned int index, unsigned long config_ba
/* arm_pmu backend */
static void m1_pmu_enable_event(struct perf_event *event)
{
- bool user, kernel;
- u8 evt;
-
- evt = event->hw.config_base & M1_PMU_CFG_EVENT;
- user = event->hw.config_base & M1_PMU_CFG_COUNT_USER;
- kernel = event->hw.config_base & M1_PMU_CFG_COUNT_KERNEL;
-
m1_pmu_configure_counter(event->hw.idx, event->hw.config_base);
m1_pmu_enable_counter(event->hw.idx);
m1_pmu_enable_counter_interrupt(event->hw.idx);
--
2.56.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 03/13] drivers/perf: apple_m1: Support per-implementation event tables
2026-11-03 10:14 [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 01/13] dt-bindings: arm: pmu: Add Apple M3/M4/A18 Pro SoC CPU PMU compatibles Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 02/13] drivers/perf: apple_m1: Remove unused variables Myria Sarvay via B4 Relay
@ 2026-11-03 10:14 ` Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 04/13] drivers/perf: apple_m1: Support per-implementation event size Myria Sarvay via B4 Relay
` (9 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Myria Sarvay via B4 Relay @ 2026-11-03 10:14 UTC (permalink / raw)
To: Will Deacon, Mark Rutland, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sven Peter, Janne Grunau, Neal Gompa, Marc Zyngier
Cc: linux-arm-kernel, linux-perf-users, devicetree, linux-kernel,
asahi, Yuvan Shen, Myria Sarvay, Nick Chan
From: Nick Chan <towinchenmi@gmail.com>
Use per-implementation event tables to allow supporting implementations
with a different list of events and event affinities.
Signed-off-by: Nick Chan <towinchenmi@gmail.com>
Co-developed-by: Myria Sarvay <myrialsarvay@gmail.com>
Signed-off-by: Myria Sarvay <myrialsarvay@gmail.com>
---
drivers/perf/apple_m1_cpu_pmu.c | 113 ++++++++++++++++++++++++----------------
1 file changed, 69 insertions(+), 44 deletions(-)
diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index de4026c63afd..2ff0c2e0b737 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -43,9 +43,6 @@
* moment, we don't really need to distinguish between the two because we
* know next to nothing about the events themselves, and we already have
* per cpu-type PMU abstractions.
- *
- * If we eventually find out that the events are different across
- * implementations, we'll have to introduce per cpu-type tables.
*/
enum m1_pmu_events {
M1_PMU_PERFCTR_RETIRE_UOP = 0x1,
@@ -167,7 +164,7 @@ static const u16 m1_pmu_event_affinity[M1_PMU_PERFCTR_LAST + 1] = {
[M1_PMU_PERFCTR_UNKNOWN_fd] = ONLY_2_4_6,
};
-static const unsigned m1_pmu_perf_map[PERF_COUNT_HW_MAX] = {
+static const unsigned int m1_pmu_perf_map[PERF_COUNT_HW_MAX] = {
PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = M1_PMU_PERFCTR_CORE_ACTIVE_CYCLE,
[PERF_COUNT_HW_INSTRUCTIONS] = M1_PMU_PERFCTR_INST_ALL,
@@ -486,11 +483,12 @@ static void m1_pmu_write_counter(struct perf_event *event, u64 value)
isb();
}
-static int m1_pmu_get_event_idx(struct pmu_hw_events *cpuc,
- struct perf_event *event)
+static int apple_pmu_get_event_idx(struct pmu_hw_events *cpuc,
+ struct perf_event *event,
+ const u16 event_affinities[])
{
unsigned long evtype = event->hw.config_base & M1_PMU_CFG_EVENT;
- unsigned long affinity = m1_pmu_event_affinity[evtype];
+ unsigned long affinity = event_affinities[evtype];
int idx;
/*
@@ -509,6 +507,12 @@ static int m1_pmu_get_event_idx(struct pmu_hw_events *cpuc,
return -EAGAIN;
}
+static int m1_pmu_get_event_idx(struct pmu_hw_events *cpuc,
+ struct perf_event *event)
+{
+ return apple_pmu_get_event_idx(cpuc, event, m1_pmu_event_affinity);
+}
+
static void m1_pmu_clear_event_idx(struct pmu_hw_events *cpuc,
struct perf_event *event)
{
@@ -536,44 +540,52 @@ static void m1_pmu_stop(struct arm_pmu *cpu_pmu)
__m1_pmu_set_mode(PMCR0_IMODE_OFF);
}
+static int apple_pmu_map_event(struct perf_event *event,
+ const unsigned int (*perf_map)[],
+ unsigned int flags)
+{
+ event->hw.flags |= flags;
+ return armpmu_map_event(event, perf_map, NULL, M1_PMU_CFG_EVENT);
+}
+
+/*
+ * Apple PMU counters have been observed to be either 48 or
+ * 64 bits wide, depending on the SoC. However, the MSB is
+ * what triggers an overflow interrupt, so we advertise the
+ * counters as being 1-bit smaller than hardware so as to
+ * mimick ARM PMU behaviour
+ */
static int m1_pmu_map_event(struct perf_event *event)
{
- /*
- * Although the counters are 48bit wide, bit 47 is what
- * triggers the overflow interrupt. Advertise the counters
- * being 47bit wide to mimick the behaviour of the ARM PMU.
- */
- event->hw.flags |= ARMPMU_EVT_47BIT;
- return armpmu_map_event(event, &m1_pmu_perf_map, NULL, M1_PMU_CFG_EVENT);
+ return apple_pmu_map_event(event, &m1_pmu_perf_map, ARMPMU_EVT_47BIT);
}
static int m2_pmu_map_event(struct perf_event *event)
{
- /*
- * Same deal as the above, except that M2 has 64bit counters.
- * Which, as far as we're concerned, actually means 63 bits.
- * Yes, this is getting awkward.
- */
- event->hw.flags |= ARMPMU_EVT_63BIT;
- return armpmu_map_event(event, &m1_pmu_perf_map, NULL, M1_PMU_CFG_EVENT);
+ return apple_pmu_map_event(event, &m1_pmu_perf_map, ARMPMU_EVT_63BIT);
}
-static int m1_pmu_map_pmuv3_event(unsigned int eventsel)
+static int apple_pmu_map_pmuv3_event(unsigned int eventsel, const u16 pmceid_map[])
{
- u16 m1_event = HW_OP_UNSUPPORTED;
+ u16 apple_event = HW_OP_UNSUPPORTED;
if (eventsel < ARMV8_PMUV3_MAX_COMMON_EVENTS)
- m1_event = m1_pmu_pmceid_map[eventsel];
+ apple_event = pmceid_map[eventsel];
- return m1_event == HW_OP_UNSUPPORTED ? -EOPNOTSUPP : m1_event;
+ return apple_event == HW_OP_UNSUPPORTED ? -EOPNOTSUPP : apple_event;
}
-static void m1_pmu_init_pmceid(struct arm_pmu *pmu)
+static int m1_pmu_map_pmuv3_event(unsigned int eventsel)
+{
+ return apple_pmu_map_pmuv3_event(eventsel, m1_pmu_pmceid_map);
+}
+
+static void apple_pmu_init_pmceid(struct arm_pmu *pmu)
{
unsigned int event;
for (event = 0; event < ARMV8_PMUV3_MAX_COMMON_EVENTS; event++) {
- if (m1_pmu_map_pmuv3_event(event) >= 0)
+ if (pmu->map_pmuv3_event(event) >= 0)
set_bit(event, pmu->pmceid_bitmap);
}
}
@@ -616,33 +628,22 @@ static int m1_pmu_set_event_filter(struct hw_perf_event *event,
return 0;
}
-static int m1_pmu_init(struct arm_pmu *cpu_pmu, u32 flags)
+static int apple_pmu_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->handle_irq = m1_pmu_handle_irq;
cpu_pmu->enable = m1_pmu_enable_event;
cpu_pmu->disable = m1_pmu_disable_event;
cpu_pmu->read_counter = m1_pmu_read_counter;
cpu_pmu->write_counter = m1_pmu_write_counter;
- cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
cpu_pmu->clear_event_idx = m1_pmu_clear_event_idx;
cpu_pmu->start = m1_pmu_start;
cpu_pmu->stop = m1_pmu_stop;
-
- if (flags & ARMPMU_EVT_47BIT)
- cpu_pmu->map_event = m1_pmu_map_event;
- else if (flags & ARMPMU_EVT_63BIT)
- cpu_pmu->map_event = m2_pmu_map_event;
- else
- return WARN_ON(-EINVAL);
-
cpu_pmu->reset = m1_pmu_reset;
cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
- cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
- m1_pmu_init_pmceid(cpu_pmu);
+ apple_pmu_init_pmceid(cpu_pmu);
bitmap_set(cpu_pmu->cntr_mask, 0, M1_PMU_NR_COUNTERS);
- cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
return 0;
}
@@ -651,25 +652,49 @@ static int m1_pmu_init(struct arm_pmu *cpu_pmu, u32 flags)
static int m1_pmu_ice_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->name = "apple_icestorm_pmu";
- return m1_pmu_init(cpu_pmu, ARMPMU_EVT_47BIT);
+ cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
+ cpu_pmu->map_event = m1_pmu_map_event;
+
+ cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
+
+ cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
+ return apple_pmu_init(cpu_pmu);
}
static int m1_pmu_fire_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->name = "apple_firestorm_pmu";
- return m1_pmu_init(cpu_pmu, ARMPMU_EVT_47BIT);
+ cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
+ cpu_pmu->map_event = m1_pmu_map_event;
+
+ cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
+
+ cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
+ return apple_pmu_init(cpu_pmu);
}
static int m2_pmu_avalanche_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->name = "apple_avalanche_pmu";
- return m1_pmu_init(cpu_pmu, ARMPMU_EVT_63BIT);
+ cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
+ cpu_pmu->map_event = m2_pmu_map_event;
+
+ cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
+
+ cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
+ return apple_pmu_init(cpu_pmu);
}
static int m2_pmu_blizzard_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->name = "apple_blizzard_pmu";
- return m1_pmu_init(cpu_pmu, ARMPMU_EVT_63BIT);
+ cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
+ cpu_pmu->map_event = m2_pmu_map_event;
+
+ cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
+
+ cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
+ return apple_pmu_init(cpu_pmu);
}
static const struct of_device_id m1_pmu_of_device_ids[] = {
--
2.56.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 04/13] drivers/perf: apple_m1: Support per-implementation event size
2026-11-03 10:14 [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support Myria Sarvay via B4 Relay
` (2 preceding siblings ...)
2026-11-03 10:14 ` [PATCH 03/13] drivers/perf: apple_m1: Support per-implementation event tables Myria Sarvay via B4 Relay
@ 2026-11-03 10:14 ` Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 05/13] drivers/perf: apple_m1: Use macros for per-implementation init functions Myria Sarvay via B4 Relay
` (8 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Myria Sarvay via B4 Relay @ 2026-11-03 10:14 UTC (permalink / raw)
To: Will Deacon, Mark Rutland, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sven Peter, Janne Grunau, Neal Gompa, Marc Zyngier
Cc: linux-arm-kernel, linux-perf-users, devicetree, linux-kernel,
asahi, Yuvan Shen, Myria Sarvay
From: Myria Sarvay <myrialsarvay@gmail.com>
On M3 and later silicon, events are 16-bits instead of the 8-bits of
earlier implementations.
Co-developed-by: Yuvan Shen <yuvanshen09@gmail.com>
Signed-off-by: Yuvan Shen <yuvanshen09@gmail.com>
Signed-off-by: Myria Sarvay <myrialsarvay@gmail.com>
---
drivers/perf/apple_m1_cpu_pmu.c | 54 ++++++++++++++++++++++++++---------------
1 file changed, 35 insertions(+), 19 deletions(-)
diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index 2ff0c2e0b737..a14864263bf1 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -209,10 +209,13 @@ static const struct attribute_group m1_pmu_events_attr_group = {
.attrs = m1_pmu_event_attrs,
};
-PMU_FORMAT_ATTR(event, "config:0-7");
+PMU_FORMAT_ATTR_SHOW(event_8b, "config:0-7");
+
+static struct device_attribute format_attr_event_8b =
+ __ATTR(event, 0444, event_8b_show, NULL);
static struct attribute *m1_pmu_format_attrs[] = {
- &format_attr_event.attr,
+ &format_attr_event_8b.attr,
NULL,
};
@@ -373,7 +376,8 @@ static void __m1_pmu_configure_event_filter(unsigned int index, bool user,
sysreg_clear_set_s(SYS_IMP_APL_PMCR1_EL12, clear, set);
}
-static void __m1_pmu_configure_eventsel(unsigned int index, u8 event)
+static void __apple_pmu_configure_eventsel(unsigned int index, u16 event,
+ unsigned int size, u64 mask)
{
u64 clear = 0, set = 0;
int shift;
@@ -388,14 +392,14 @@ static void __m1_pmu_configure_eventsel(unsigned int index, u8 event)
case 0 ... 1:
break;
case 2 ... 5:
- shift = (index - 2) * 8;
- clear |= (u64)0xff << shift;
+ shift = (index - 2) * size;
+ clear |= mask << shift;
set |= (u64)event << shift;
sysreg_clear_set_s(SYS_IMP_APL_PMESR0_EL1, clear, set);
break;
case 6 ... 9:
- shift = (index - 6) * 8;
- clear |= (u64)0xff << shift;
+ shift = (index - 6) * size;
+ clear |= mask << shift;
set |= (u64)event << shift;
sysreg_clear_set_s(SYS_IMP_APL_PMESR1_EL1, clear, set);
break;
@@ -412,7 +416,7 @@ static void m1_pmu_configure_counter(unsigned int index, unsigned long config_ba
__m1_pmu_configure_event_filter(index, user && host, kernel && host, true);
__m1_pmu_configure_event_filter(index, user && guest, kernel && guest, false);
- __m1_pmu_configure_eventsel(index, evt);
+ __apple_pmu_configure_eventsel(index, evt, 8, M1_PMU_CFG_EVENT);
}
/* arm_pmu backend */
@@ -485,10 +489,8 @@ static void m1_pmu_write_counter(struct perf_event *event, u64 value)
static int apple_pmu_get_event_idx(struct pmu_hw_events *cpuc,
struct perf_event *event,
- const u16 event_affinities[])
+ unsigned long affinity)
{
- unsigned long evtype = event->hw.config_base & M1_PMU_CFG_EVENT;
- unsigned long affinity = event_affinities[evtype];
int idx;
/*
@@ -510,7 +512,10 @@ static int apple_pmu_get_event_idx(struct pmu_hw_events *cpuc,
static int m1_pmu_get_event_idx(struct pmu_hw_events *cpuc,
struct perf_event *event)
{
- return apple_pmu_get_event_idx(cpuc, event, m1_pmu_event_affinity);
+ unsigned long evtype = event->hw.config_base & M1_PMU_CFG_EVENT;
+ unsigned long affinity = m1_pmu_event_affinity[evtype];
+
+ return apple_pmu_get_event_idx(cpuc, event, affinity);
}
static void m1_pmu_clear_event_idx(struct pmu_hw_events *cpuc,
@@ -542,10 +547,10 @@ static void m1_pmu_stop(struct arm_pmu *cpu_pmu)
static int apple_pmu_map_event(struct perf_event *event,
const unsigned int (*perf_map)[],
- unsigned int flags)
+ unsigned int flags, u32 mask)
{
event->hw.flags |= flags;
- return armpmu_map_event(event, perf_map, NULL, M1_PMU_CFG_EVENT);
+ return armpmu_map_event(event, perf_map, NULL, mask);
}
/*
@@ -557,12 +562,14 @@ static int apple_pmu_map_event(struct perf_event *event,
*/
static int m1_pmu_map_event(struct perf_event *event)
{
- return apple_pmu_map_event(event, &m1_pmu_perf_map, ARMPMU_EVT_47BIT);
+ return apple_pmu_map_event(event, &m1_pmu_perf_map, ARMPMU_EVT_47BIT,
+ M1_PMU_CFG_EVENT);
}
static int m2_pmu_map_event(struct perf_event *event)
{
- return apple_pmu_map_event(event, &m1_pmu_perf_map, ARMPMU_EVT_63BIT);
+ return apple_pmu_map_event(event, &m1_pmu_perf_map, ARMPMU_EVT_63BIT,
+ M1_PMU_CFG_EVENT);
}
static int apple_pmu_map_pmuv3_event(unsigned int eventsel, const u16 pmceid_map[])
@@ -631,7 +638,6 @@ static int m1_pmu_set_event_filter(struct hw_perf_event *event,
static int apple_pmu_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->handle_irq = m1_pmu_handle_irq;
- cpu_pmu->enable = m1_pmu_enable_event;
cpu_pmu->disable = m1_pmu_disable_event;
cpu_pmu->read_counter = m1_pmu_read_counter;
cpu_pmu->write_counter = m1_pmu_write_counter;
@@ -639,12 +645,10 @@ static int apple_pmu_init(struct arm_pmu *cpu_pmu)
cpu_pmu->start = m1_pmu_start;
cpu_pmu->stop = m1_pmu_stop;
cpu_pmu->reset = m1_pmu_reset;
- cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
apple_pmu_init_pmceid(cpu_pmu);
bitmap_set(cpu_pmu->cntr_mask, 0, M1_PMU_NR_COUNTERS);
- cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
return 0;
}
@@ -652,48 +656,60 @@ static int apple_pmu_init(struct arm_pmu *cpu_pmu)
static int m1_pmu_ice_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->name = "apple_icestorm_pmu";
+ cpu_pmu->enable = m1_pmu_enable_event;
cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
cpu_pmu->map_event = m1_pmu_map_event;
+ cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
+ cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
return apple_pmu_init(cpu_pmu);
}
static int m1_pmu_fire_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->name = "apple_firestorm_pmu";
+ cpu_pmu->enable = m1_pmu_enable_event;
cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
cpu_pmu->map_event = m1_pmu_map_event;
+ cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
+ cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
return apple_pmu_init(cpu_pmu);
}
static int m2_pmu_avalanche_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->name = "apple_avalanche_pmu";
+ cpu_pmu->enable = m1_pmu_enable_event;
cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
cpu_pmu->map_event = m2_pmu_map_event;
+ cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
+ cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
return apple_pmu_init(cpu_pmu);
}
static int m2_pmu_blizzard_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->name = "apple_blizzard_pmu";
+ cpu_pmu->enable = m1_pmu_enable_event;
cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
cpu_pmu->map_event = m2_pmu_map_event;
+ cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
+ cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
return apple_pmu_init(cpu_pmu);
}
--
2.56.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 05/13] drivers/perf: apple_m1: Use macros for per-implementation init functions
2026-11-03 10:14 [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support Myria Sarvay via B4 Relay
` (3 preceding siblings ...)
2026-11-03 10:14 ` [PATCH 04/13] drivers/perf: apple_m1: Support per-implementation event size Myria Sarvay via B4 Relay
@ 2026-11-03 10:14 ` Myria Sarvay via B4 Relay
2026-11-03 10:31 ` sashiko-bot
2026-11-03 10:14 ` [PATCH 06/13] drivers/perf: apple_m1: Add Apple M3 Series Support Myria Sarvay via B4 Relay
` (7 subsequent siblings)
12 siblings, 1 reply; 19+ messages in thread
From: Myria Sarvay via B4 Relay @ 2026-11-03 10:14 UTC (permalink / raw)
To: Will Deacon, Mark Rutland, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sven Peter, Janne Grunau, Neal Gompa, Marc Zyngier
Cc: linux-arm-kernel, linux-perf-users, devicetree, linux-kernel,
asahi, Yuvan Shen, Myria Sarvay
From: Myria Sarvay <myrialsarvay@gmail.com>
6 generations of apple silicon, with at least 2 init functions for each
lead to at least 12 init functions. Template them with macros to save
boilterplate code.
Signed-off-by: Myria Sarvay <myrialsarvay@gmail.com>
---
drivers/perf/apple_m1_cpu_pmu.c | 91 ++++++++++++++---------------------------
1 file changed, 30 insertions(+), 61 deletions(-)
diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index a14864263bf1..e7e9b51ffadc 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -653,71 +653,40 @@ static int apple_pmu_init(struct arm_pmu *cpu_pmu)
}
/* Device driver gunk */
-static int m1_pmu_ice_init(struct arm_pmu *cpu_pmu)
-{
- cpu_pmu->name = "apple_icestorm_pmu";
- cpu_pmu->enable = m1_pmu_enable_event;
- cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
- cpu_pmu->map_event = m1_pmu_map_event;
- cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
-
- cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
-
- cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
- cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
- return apple_pmu_init(cpu_pmu);
-}
-
-static int m1_pmu_fire_init(struct arm_pmu *cpu_pmu)
-{
- cpu_pmu->name = "apple_firestorm_pmu";
- cpu_pmu->enable = m1_pmu_enable_event;
- cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
- cpu_pmu->map_event = m1_pmu_map_event;
- cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
-
- cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
-
- cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
- cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
- return apple_pmu_init(cpu_pmu);
-}
-
-static int m2_pmu_avalanche_init(struct arm_pmu *cpu_pmu)
-{
- cpu_pmu->name = "apple_avalanche_pmu";
- cpu_pmu->enable = m1_pmu_enable_event;
- cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
- cpu_pmu->map_event = m2_pmu_map_event;
- cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
-
- cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
-
- cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
- cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
- return apple_pmu_init(cpu_pmu);
-}
-
-static int m2_pmu_blizzard_init(struct arm_pmu *cpu_pmu)
-{
- cpu_pmu->name = "apple_blizzard_pmu";
- cpu_pmu->enable = m1_pmu_enable_event;
- cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
- cpu_pmu->map_event = m2_pmu_map_event;
- cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
-
- cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
-
- cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
- cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
- return apple_pmu_init(cpu_pmu);
-}
+#define APPLE_PMU_INIT(gen, family) \
+static int gen ## _pmu_ ## family ## _init(struct arm_pmu *cpu_pmu) \
+{ \
+ cpu_pmu->name = "apple_" #family "_pmu"; \
+ cpu_pmu->enable = gen ## _pmu_enable_event; \
+ cpu_pmu->get_event_idx = gen ## _pmu_get_event_idx; \
+ cpu_pmu->map_event = gen ## _pmu_map_event; \
+ cpu_pmu->set_event_filter = gen ## _pmu_set_event_filter; \
+ \
+ cpu_pmu->map_pmuv3_event = gen ## _pmu_map_pmuv3_event; \
+ \
+ cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &gen ## _pmu_events_attr_group; \
+ cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &gen ## _pmu_format_attr_group; \
+ return apple_pmu_init(cpu_pmu); \
+}
+
+#define m2_pmu_enable_event m1_pmu_enable_event
+#define m2_pmu_get_event_idx m1_pmu_get_event_idx
+#define m2_pmu_set_event_filter m1_pmu_set_event_filter
+#define m2_pmu_map_pmuv3_event m1_pmu_map_pmuv3_event
+#define m2_pmu_init_pmceid m1_pmu_init_pmceid
+#define m2_pmu_events_attr_group m1_pmu_events_attr_group
+#define m2_pmu_format_attr_group m1_pmu_format_attr_group
+
+APPLE_PMU_INIT(m1, icestorm)
+APPLE_PMU_INIT(m1, firestorm)
+APPLE_PMU_INIT(m2, avalanche)
+APPLE_PMU_INIT(m2, blizzard)
static const struct of_device_id m1_pmu_of_device_ids[] = {
{ .compatible = "apple,avalanche-pmu", .data = m2_pmu_avalanche_init, },
{ .compatible = "apple,blizzard-pmu", .data = m2_pmu_blizzard_init, },
- { .compatible = "apple,icestorm-pmu", .data = m1_pmu_ice_init, },
- { .compatible = "apple,firestorm-pmu", .data = m1_pmu_fire_init, },
+ { .compatible = "apple,icestorm-pmu", .data = m1_pmu_icestorm_init, },
+ { .compatible = "apple,firestorm-pmu", .data = m1_pmu_firestorm_init, },
{ },
};
MODULE_DEVICE_TABLE(of, m1_pmu_of_device_ids);
--
2.56.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 06/13] drivers/perf: apple_m1: Add Apple M3 Series Support
2026-11-03 10:14 [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support Myria Sarvay via B4 Relay
` (4 preceding siblings ...)
2026-11-03 10:14 ` [PATCH 05/13] drivers/perf: apple_m1: Use macros for per-implementation init functions Myria Sarvay via B4 Relay
@ 2026-11-03 10:14 ` Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 07/13] drivers/perf: apple_m1: Add Apple M4 " Myria Sarvay via B4 Relay
` (6 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Myria Sarvay via B4 Relay @ 2026-11-03 10:14 UTC (permalink / raw)
To: Will Deacon, Mark Rutland, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sven Peter, Janne Grunau, Neal Gompa, Marc Zyngier
Cc: linux-arm-kernel, linux-perf-users, devicetree, linux-kernel,
asahi, Yuvan Shen, Myria Sarvay
From: Myria Sarvay <myrialsarvay@gmail.com>
Add support for the CPU PMU in the M3 Series chips. These events are
encoded with 16 bits, and similar events have different codes when
compared to the M1.
Signed-off-by: Myria Sarvay <myrialsarvay@gmail.com>
---
drivers/perf/apple_m1_cpu_pmu.c | 266 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 263 insertions(+), 3 deletions(-)
diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index e7e9b51ffadc..ac9373126054 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -22,6 +22,7 @@
#define M1_PMU_NR_COUNTERS 10
#define M1_PMU_CFG_EVENT GENMASK(7, 0)
+#define M3_PMU_CFG_EVENT GENMASK(15, 0)
#define ANY_BUT_0_1 GENMASK(9, 2)
#define ONLY_2_TO_7 GENMASK(7, 2)
@@ -122,6 +123,84 @@ enum m1_pmu_events {
M1_PMU_CFG_COUNT_GUEST = BIT(11),
};
+enum m3_pmu_events {
+ M3_PMU_PERFCTR_RETIRE_UOP = 0x1,
+ M3_PMU_PERFCTR_CORE_ACTIVE_CYCLE = 0x2,
+ M3_PMU_PERFCTR_FLUSH_RESTART_OTHER_NONSPEC = 0x84,
+ M3_PMU_PERFCTR_INST_ALL = 0x8c,
+ M3_PMU_PERFCTR_INST_BRANCH = 0x8d,
+ M3_PMU_PERFCTR_INST_BRANCH_CALL = 0x8e,
+ M3_PMU_PERFCTR_INST_BRANCH_RET = 0x8f,
+ M3_PMU_PERFCTR_INST_BRANCH_TAKEN = 0x90,
+ M3_PMU_PERFCTR_INST_BRANCH_INDIR = 0x93,
+ M3_PMU_PERFCTR_INST_INT_LD = 0x95,
+ M3_PMU_PERFCTR_INST_INT_ST = 0x96,
+ M3_PMU_PERFCTR_INST_INT_ALU = 0x97,
+ M3_PMU_PERFCTR_INST_SIMD_LD = 0x98,
+ M3_PMU_PERFCTR_INST_SIMD_ST = 0x99,
+ M3_PMU_PERFCTR_INST_SIMD_ALU = 0x9a,
+ M3_PMU_PERFCTR_INST_LDST = 0x9b,
+ M3_PMU_PERFCTR_INST_BARRIER = 0x9c,
+ M3_PMU_PERFCTR_INST_SIMD_ALU_VEC = 0x9f,
+ M3_PMU_PERFCTR_L1D_CACHE_MISS_LD_NONSPEC = 0xbf,
+ M3_PMU_PERFCTR_L1D_CACHE_MISS_ST_NONSPEC = 0xc0,
+ M3_PMU_PERFCTR_L1D_TLB_MISS_NONSPEC = 0xc1,
+ M3_PMU_PERFCTR_ST_MEM_ORDER_VIOL_LD_NONSPEC = 0xc4,
+ M3_PMU_PERFCTR_BRANCH_COND_MISPRED_NONSPEC = 0xc5,
+ M3_PMU_PERFCTR_BRANCH_INDIR_MISPRED_NONSPEC = 0xc6,
+ M3_PMU_PERFCTR_BRANCH_RET_INDIR_MISPRED_NONSPEC = 0xc8,
+ M3_PMU_PERFCTR_BRANCH_CALL_INDIR_MISPRED_NONSPEC = 0xca,
+ M3_PMU_PERFCTR_BRANCH_MISPRED_NONSPEC = 0xcb,
+ M3_PMU_PERFCTR_MAP_DISPATCH_BUBBLE_IC = 0x182,
+ M3_PMU_PERFCTR_MAP_DISPATCH_BUBBLE_ITLB = 0x183,
+ M3_PMU_PERFCTR_DECODE_UOP = 0x186,
+ M3_PMU_PERFCTR_L1I_TLB_MISS_DEMAND = 0x1d4,
+ M3_PMU_PERFCTR_MAP_DISPATCH_BUBBLE = 0x1d6,
+ M3_PMU_PERFCTR_L1I_CACHE_MISS_DEMAND = 0x1db,
+ M3_PMU_PERFCTR_FETCH_RESTART = 0x1de,
+ M3_PMU_PERFCTR_MAP_UOP = 0x269,
+ M3_PMU_PERFCTR_INTERRUPT_PENDING = 0x26c,
+ M3_PMU_PERFCTR_MAP_STALL_DISPATCH = 0x270,
+ M3_PMU_PERFCTR_MAP_REWIND = 0x275,
+ M3_PMU_PERFCTR_MAP_STALL = 0x276,
+ M3_PMU_PERFCTR_MAP_INT_UOP = 0x27c,
+ M3_PMU_PERFCTR_MAP_LDST_UOP = 0x27d,
+ M3_PMU_PERFCTR_MAP_SIMD_UOP = 0x27e,
+ M3_PMU_PERFCTR_SCHEDULE_UOP_ANY = 0x283,
+ M3_PMU_PERFCTR_LDST_UNIT_OLD_L1D_CACHE_MISS = 0x290,
+ M3_PMU_PERFCTR_LDST_UNIT_WAITING_OLD_L1D_CACHE_MISS = 0x291,
+ M3_PMU_PERFCTR_SCHEDULE_EMPTY = 0x351,
+ M3_PMU_PERFCTR_L1I_TLB_FILL = 0x404,
+ M3_PMU_PERFCTR_L1D_TLB_FILL = 0x405,
+ M3_PMU_PERFCTR_MMU_TABLE_WALK_INSTRUCTION = 0x407,
+ M3_PMU_PERFCTR_MMU_TABLE_WALK_DATA = 0x408,
+ M3_PMU_PERFCTR_L2_TLB_MISS_INSTRUCTION = 0x40a,
+ M3_PMU_PERFCTR_L2_TLB_MISS_DATA = 0x40b,
+ M3_PMU_PERFCTR_L1D_TLB_ACCESS = 0x5a0,
+ M3_PMU_PERFCTR_L1D_TLB_MISS = 0x5a1,
+ M3_PMU_PERFCTR_L1D_CACHE_MISS_ST = 0x5a2,
+ M3_PMU_PERFCTR_L1D_CACHE_MISS_LD = 0x5a3,
+ M3_PMU_PERFCTR_LD_UNIT_UOP = 0x5a6,
+ M3_PMU_PERFCTR_ST_UNIT_UOP = 0x5a7,
+ M3_PMU_PERFCTR_L1D_CACHE_WRITEBACK = 0x5a8,
+ M3_PMU_PERFCTR_LDST_X64_UOP = 0x5b1,
+ M3_PMU_PERFCTR_LDST_XPG_UOP = 0x5b2,
+ M3_PMU_PERFCTR_ATOMIC_OR_EXCLUSIVE_SUCC = 0x5b3,
+ M3_PMU_PERFCTR_ATOMIC_OR_EXCLUSIVE_FAIL = 0x5b4,
+ M3_PMU_PERFCTR_ST_NT_UOP = 0x5e5,
+ M3_PMU_PERFCTR_LD_NT_UOP = 0x5e6,
+ M3_PMU_PERFCTR_LAST = M3_PMU_CFG_EVENT,
+
+ /*
+ * From this point onwards, these are not actual HW events,
+ * but attributes that get stored in hw->config_base.
+ */
+ M3_PMU_CFG_COUNT_USER = BIT(16),
+ M3_PMU_CFG_COUNT_KERNEL = BIT(17),
+ M3_PMU_CFG_COUNT_HOST = BIT(18),
+ M3_PMU_CFG_COUNT_GUEST = BIT(19),
+};
+
/*
* Per-event affinity table. Most events can be installed on counter
* 2-9, but there are a number of exceptions. Note that this table
@@ -164,6 +243,40 @@ static const u16 m1_pmu_event_affinity[M1_PMU_PERFCTR_LAST + 1] = {
[M1_PMU_PERFCTR_UNKNOWN_fd] = ONLY_2_4_6,
};
+struct event_affinity_16 {
+ u16 event_code;
+ u16 affinity;
+};
+
+static const struct event_affinity_16 m3_pmu_event_affinity[] = {
+ { M3_PMU_PERFCTR_RETIRE_UOP, BIT(7) },
+ { M3_PMU_PERFCTR_CORE_ACTIVE_CYCLE, ANY_BUT_0_1 | BIT(0) },
+ { M3_PMU_PERFCTR_INST_ALL, BIT(7) | BIT(1) },
+ { M3_PMU_PERFCTR_INST_BRANCH, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_INST_BRANCH_CALL, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_INST_BRANCH_RET, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_INST_BRANCH_TAKEN, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_INST_BRANCH_INDIR, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_INST_INT_LD, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_INST_INT_ST, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_INST_INT_ALU, BIT(7) },
+ { M3_PMU_PERFCTR_INST_SIMD_LD, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_INST_SIMD_ST, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_INST_SIMD_ALU, BIT(7) },
+ { M3_PMU_PERFCTR_INST_LDST, BIT(7) },
+ { M3_PMU_PERFCTR_INST_BARRIER, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_INST_SIMD_ALU_VEC, BIT(7) },
+ { M3_PMU_PERFCTR_L1D_CACHE_MISS_LD_NONSPEC, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_L1D_CACHE_MISS_ST_NONSPEC, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_L1D_TLB_MISS_NONSPEC, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_ST_MEM_ORDER_VIOL_LD_NONSPEC, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_BRANCH_COND_MISPRED_NONSPEC, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_BRANCH_INDIR_MISPRED_NONSPEC, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_BRANCH_RET_INDIR_MISPRED_NONSPEC, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_BRANCH_CALL_INDIR_MISPRED_NONSPEC, ONLY_5_6_7 },
+ { M3_PMU_PERFCTR_BRANCH_MISPRED_NONSPEC, ONLY_5_6_7 },
+};
+
static const unsigned int m1_pmu_perf_map[PERF_COUNT_HW_MAX] = {
PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = M1_PMU_PERFCTR_CORE_ACTIVE_CYCLE,
@@ -172,9 +285,20 @@ static const unsigned int m1_pmu_perf_map[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_BRANCH_MISSES] = M1_PMU_PERFCTR_BRANCH_MISPRED_NONSPEC,
};
+static const unsigned int m3_pmu_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
+ [PERF_COUNT_HW_CPU_CYCLES] = M3_PMU_PERFCTR_CORE_ACTIVE_CYCLE,
+ [PERF_COUNT_HW_INSTRUCTIONS] = M3_PMU_PERFCTR_INST_ALL,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = M3_PMU_PERFCTR_INST_BRANCH,
+ [PERF_COUNT_HW_BRANCH_MISSES] = M3_PMU_PERFCTR_BRANCH_MISPRED_NONSPEC,
+};
+
#define M1_PMUV3_EVENT_MAP(pmuv3_event, m1_event) \
[ARMV8_PMUV3_PERFCTR_##pmuv3_event] = M1_PMU_PERFCTR_##m1_event
+#define M3_PMUV3_EVENT_MAP(pmuv3_event, m3_event) \
+ [ARMV8_PMUV3_PERFCTR_##pmuv3_event] = M3_PMU_PERFCTR_##m3_event
+
static const u16 m1_pmu_pmceid_map[ARMV8_PMUV3_MAX_COMMON_EVENTS] = {
[0 ... ARMV8_PMUV3_MAX_COMMON_EVENTS - 1] = HW_OP_UNSUPPORTED,
M1_PMUV3_EVENT_MAP(INST_RETIRED, INST_ALL),
@@ -183,6 +307,14 @@ static const u16 m1_pmu_pmceid_map[ARMV8_PMUV3_MAX_COMMON_EVENTS] = {
M1_PMUV3_EVENT_MAP(BR_MIS_PRED_RETIRED, BRANCH_MISPRED_NONSPEC),
};
+static const u16 m3_pmu_pmceid_map[ARMV8_PMUV3_MAX_COMMON_EVENTS] = {
+ [0 ... ARMV8_PMUV3_MAX_COMMON_EVENTS - 1] = HW_OP_UNSUPPORTED,
+ M3_PMUV3_EVENT_MAP(INST_RETIRED, INST_ALL),
+ M3_PMUV3_EVENT_MAP(CPU_CYCLES, CORE_ACTIVE_CYCLE),
+ M3_PMUV3_EVENT_MAP(BR_RETIRED, INST_BRANCH),
+ M3_PMUV3_EVENT_MAP(BR_MIS_PRED_RETIRED, BRANCH_MISPRED_NONSPEC),
+};
+
/* sysfs definitions */
static ssize_t m1_pmu_events_sysfs_show(struct device *dev,
struct device_attribute *attr,
@@ -192,38 +324,76 @@ static ssize_t m1_pmu_events_sysfs_show(struct device *dev,
pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+ return sprintf(page, "event=0x%02llx\n", pmu_attr->id);
+}
+
+static ssize_t m3_pmu_events_sysfs_show(struct device *dev,
+ struct device_attribute *attr,
+ char *page)
+{
+ struct perf_pmu_events_attr *pmu_attr;
+
+ pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+
return sprintf(page, "event=0x%04llx\n", pmu_attr->id);
}
#define M1_PMU_EVENT_ATTR(name, config) \
PMU_EVENT_ATTR_ID(name, m1_pmu_events_sysfs_show, config)
+#define M3_PMU_EVENT_ATTR(name, config) \
+ PMU_EVENT_ATTR_ID(name, m3_pmu_events_sysfs_show, config)
+
static struct attribute *m1_pmu_event_attrs[] = {
M1_PMU_EVENT_ATTR(cycles, M1_PMU_PERFCTR_CORE_ACTIVE_CYCLE),
M1_PMU_EVENT_ATTR(instructions, M1_PMU_PERFCTR_INST_ALL),
NULL,
};
+static struct attribute *m3_pmu_event_attrs[] = {
+ M3_PMU_EVENT_ATTR(cycles, M3_PMU_PERFCTR_CORE_ACTIVE_CYCLE),
+ M3_PMU_EVENT_ATTR(instructions, M3_PMU_PERFCTR_INST_ALL),
+ NULL,
+};
+
static const struct attribute_group m1_pmu_events_attr_group = {
.name = "events",
.attrs = m1_pmu_event_attrs,
};
+static const struct attribute_group m3_pmu_events_attr_group = {
+ .name = "events",
+ .attrs = m3_pmu_event_attrs,
+};
+
PMU_FORMAT_ATTR_SHOW(event_8b, "config:0-7");
+PMU_FORMAT_ATTR_SHOW(event_16b, "config:0-15");
static struct device_attribute format_attr_event_8b =
__ATTR(event, 0444, event_8b_show, NULL);
+static struct device_attribute format_attr_event_16b =
+ __ATTR(event, 0444, event_16b_show, NULL);
static struct attribute *m1_pmu_format_attrs[] = {
&format_attr_event_8b.attr,
NULL,
};
+static struct attribute *m3_pmu_format_attrs[] = {
+ &format_attr_event_16b.attr,
+ NULL,
+};
+
static const struct attribute_group m1_pmu_format_attr_group = {
.name = "format",
.attrs = m1_pmu_format_attrs,
};
+static const struct attribute_group m3_pmu_format_attr_group = {
+ .name = "format",
+ .attrs = m3_pmu_format_attrs,
+};
+
/* Low level accessors. No synchronisation. */
#define PMU_READ_COUNTER(_idx) \
case _idx: return read_sysreg_s(SYS_IMP_APL_PMC## _idx ##_EL1)
@@ -419,6 +589,19 @@ static void m1_pmu_configure_counter(unsigned int index, unsigned long config_ba
__apple_pmu_configure_eventsel(index, evt, 8, M1_PMU_CFG_EVENT);
}
+static void m3_pmu_configure_counter(unsigned int index, unsigned long config_base)
+{
+ bool kernel = config_base & M3_PMU_CFG_COUNT_KERNEL;
+ bool guest = config_base & M3_PMU_CFG_COUNT_GUEST;
+ bool host = config_base & M3_PMU_CFG_COUNT_HOST;
+ bool user = config_base & M3_PMU_CFG_COUNT_USER;
+ u16 evt = config_base & M3_PMU_CFG_EVENT;
+
+ __m1_pmu_configure_event_filter(index, user && host, kernel && host, true);
+ __m1_pmu_configure_event_filter(index, user && guest, kernel && guest, false);
+ __apple_pmu_configure_eventsel(index, evt, 16, M3_PMU_CFG_EVENT);
+}
+
/* arm_pmu backend */
static void m1_pmu_enable_event(struct perf_event *event)
{
@@ -428,6 +611,14 @@ static void m1_pmu_enable_event(struct perf_event *event)
isb();
}
+static void m3_pmu_enable_event(struct perf_event *event)
+{
+ m3_pmu_configure_counter(event->hw.idx, event->hw.config_base);
+ m1_pmu_enable_counter(event->hw.idx);
+ m1_pmu_enable_counter_interrupt(event->hw.idx);
+ isb();
+}
+
static void m1_pmu_disable_event(struct perf_event *event)
{
m1_pmu_disable_counter_interrupt(event->hw.idx);
@@ -509,15 +700,46 @@ static int apple_pmu_get_event_idx(struct pmu_hw_events *cpuc,
return -EAGAIN;
}
-static int m1_pmu_get_event_idx(struct pmu_hw_events *cpuc,
- struct perf_event *event)
+static int apple_pmu_get_event_idx_8(struct pmu_hw_events *cpuc,
+ struct perf_event *event,
+ const u16 event_affinities[M1_PMU_CFG_EVENT + 1])
{
unsigned long evtype = event->hw.config_base & M1_PMU_CFG_EVENT;
- unsigned long affinity = m1_pmu_event_affinity[evtype];
+ unsigned long affinity = event_affinities[evtype];
return apple_pmu_get_event_idx(cpuc, event, affinity);
}
+static int apple_pmu_get_event_idx_16(struct pmu_hw_events *cpuc,
+ struct perf_event *event,
+ unsigned long event_affinities_size,
+ const struct event_affinity_16 event_affinities[])
+{
+ unsigned long evtype = event->hw.config_base & M3_PMU_CFG_EVENT;
+ unsigned long affinity = ANY_BUT_0_1;
+
+ for (int idx = 0; idx < event_affinities_size; idx++) {
+ if (event_affinities[idx].event_code == evtype) {
+ affinity = event_affinities[idx].affinity;
+ break;
+ }
+ }
+ return apple_pmu_get_event_idx(cpuc, event, affinity);
+}
+
+static int m1_pmu_get_event_idx(struct pmu_hw_events *cpuc,
+ struct perf_event *event)
+{
+ return apple_pmu_get_event_idx_8(cpuc, event, m1_pmu_event_affinity);
+}
+
+static int m3_pmu_get_event_idx(struct pmu_hw_events *cpuc,
+ struct perf_event *event)
+{
+ return apple_pmu_get_event_idx_16(cpuc, event, ARRAY_SIZE(m3_pmu_event_affinity),
+ m3_pmu_event_affinity);
+}
+
static void m1_pmu_clear_event_idx(struct pmu_hw_events *cpuc,
struct perf_event *event)
{
@@ -572,6 +794,12 @@ static int m2_pmu_map_event(struct perf_event *event)
M1_PMU_CFG_EVENT);
}
+static int m3_pmu_map_event(struct perf_event *event)
+{
+ return apple_pmu_map_event(event, &m3_pmu_perf_map, ARMPMU_EVT_63BIT,
+ M3_PMU_CFG_EVENT);
+}
+
static int apple_pmu_map_pmuv3_event(unsigned int eventsel, const u16 pmceid_map[])
{
u16 apple_event = HW_OP_UNSUPPORTED;
@@ -587,6 +815,11 @@ static int m1_pmu_map_pmuv3_event(unsigned int eventsel)
return apple_pmu_map_pmuv3_event(eventsel, m1_pmu_pmceid_map);
}
+static int m3_pmu_map_pmuv3_event(unsigned int eventsel)
+{
+ return apple_pmu_map_pmuv3_event(eventsel, m3_pmu_pmceid_map);
+}
+
static void apple_pmu_init_pmceid(struct arm_pmu *pmu)
{
unsigned int event;
@@ -635,6 +868,29 @@ static int m1_pmu_set_event_filter(struct hw_perf_event *event,
return 0;
}
+static int m3_pmu_set_event_filter(struct hw_perf_event *event,
+ struct perf_event_attr *attr)
+{
+ unsigned long config_base = 0;
+
+ if (!attr->exclude_guest && !is_kernel_in_hyp_mode()) {
+ pr_debug("ARM performance counters do not support mode exclusion\n");
+ return -EOPNOTSUPP;
+ }
+ if (!attr->exclude_kernel)
+ config_base |= M3_PMU_CFG_COUNT_KERNEL;
+ if (!attr->exclude_user)
+ config_base |= M3_PMU_CFG_COUNT_USER;
+ if (!attr->exclude_host)
+ config_base |= M3_PMU_CFG_COUNT_HOST;
+ if (!attr->exclude_guest)
+ config_base |= M3_PMU_CFG_COUNT_GUEST;
+
+ event->config_base = config_base;
+
+ return 0;
+}
+
static int apple_pmu_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->handle_irq = m1_pmu_handle_irq;
@@ -681,8 +937,12 @@ APPLE_PMU_INIT(m1, icestorm)
APPLE_PMU_INIT(m1, firestorm)
APPLE_PMU_INIT(m2, avalanche)
APPLE_PMU_INIT(m2, blizzard)
+APPLE_PMU_INIT(m3, sawtooth)
+APPLE_PMU_INIT(m3, everest)
static const struct of_device_id m1_pmu_of_device_ids[] = {
+ { .compatible = "apple,sawtooth-pmu", .data = m3_pmu_sawtooth_init, },
+ { .compatible = "apple,everest-pmu", .data = m3_pmu_everest_init, },
{ .compatible = "apple,avalanche-pmu", .data = m2_pmu_avalanche_init, },
{ .compatible = "apple,blizzard-pmu", .data = m2_pmu_blizzard_init, },
{ .compatible = "apple,icestorm-pmu", .data = m1_pmu_icestorm_init, },
--
2.56.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 07/13] drivers/perf: apple_m1: Add Apple M4 Series Support
2026-11-03 10:14 [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support Myria Sarvay via B4 Relay
` (5 preceding siblings ...)
2026-11-03 10:14 ` [PATCH 06/13] drivers/perf: apple_m1: Add Apple M3 Series Support Myria Sarvay via B4 Relay
@ 2026-11-03 10:14 ` Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 08/13] drivers/perf: apple_m1: Add Apple A18 Support Myria Sarvay via B4 Relay
` (5 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Myria Sarvay via B4 Relay @ 2026-11-03 10:14 UTC (permalink / raw)
To: Will Deacon, Mark Rutland, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sven Peter, Janne Grunau, Neal Gompa, Marc Zyngier
Cc: linux-arm-kernel, linux-perf-users, devicetree, linux-kernel,
asahi, Yuvan Shen, Myria Sarvay
From: Myria Sarvay <myrialsarvay@gmail.com>
Add support for the CPU PMU found in the various M4 SoCs. This PMU is
almost exactly the same as the M3 PMU, just with different event
encodings.
One notable difference, is the addition of the various ARM_* events,
which appear to implement the PMUv3 specific events that the arm PMU
specification provides. Hook them up with the various perf events so
that more can easily be counted on M4+ devices.
Signed-off-by: Myria Sarvay <myrialsarvay@gmail.com>
---
drivers/perf/apple_m1_cpu_pmu.c | 224 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 224 insertions(+)
diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index ac9373126054..bdbd138cf1db 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -201,6 +201,121 @@ enum m3_pmu_events {
M3_PMU_CFG_COUNT_GUEST = BIT(19),
};
+enum m4_pmu_events {
+ M4_PMU_PERFCTR_ARM_L1D_CACHE_REFILL = 0x03,
+ M4_PMU_PERFCTR_ARM_L1D_CACHE = 0x04,
+ M4_PMU_PERFCTR_INST_ALL = 0x08,
+ M4_PMU_PERFCTR_ARM_BR_MIS_PRED = 0x10,
+ M4_PMU_PERFCTR_CORE_ACTIVE_CYCLE = 0x11,
+ M4_PMU_PERFCTR_ARM_BR_PRED = 0x12,
+ M4_PMU_PERFCTR_INST_BRANCH = 0x21,
+ M4_PMU_PERFCTR_BRANCH_MISPRED_NONSPEC = 0x22,
+ M4_PMU_PERFCTR_ARM_STALL_FRONTEND = 0x23,
+ M4_PMU_PERFCTR_ARM_STALL_BACKEND = 0x24,
+ M4_PMU_PERFCTR_ARM_L1D_CACHE_LMISS_RD = 0x39,
+ M4_PMU_PERFCTR_RETIRE_UOP = 0x3a,
+ M4_PMU_PERFCTR_MAP_UOP = 0x3b,
+ M4_PMU_PERFCTR_ARM_STALL = 0x3c,
+ M4_PMU_PERFCTR_ARM_STALL_SLOT_BACKEND = 0x3d,
+ M4_PMU_PERFCTR_ARM_STALL_SLOT_FRONTEND = 0x3e,
+ M4_PMU_PERFCTR_ARM_STALL_SLOT = 0x3f,
+ M4_PMU_PERFCTR_ARM_L1D_CACHE_RD = 0x40,
+ M4_PMU_PERFCTR_MAP_DISPATCH_BUBBLE_IC = 0x182,
+ M4_PMU_PERFCTR_MAP_DISPATCH_BUBBLE_ITLB = 0x183,
+ M4_PMU_PERFCTR_DECODE_UOP = 0x186,
+ M4_PMU_PERFCTR_L1I_TLB_MISS_DEMAND = 0x1d4,
+ M4_PMU_PERFCTR_MAP_DISPATCH_BUBBLE = 0x1d6,
+ M4_PMU_PERFCTR_FETCH_RESTART = 0x1de,
+ M4_PMU_PERFCTR_MAP_DISPATCH_BUBBLE_SLOT = 0x1e1,
+ M4_PMU_PERFCTR_INTERRUPT_PENDING = 0x26c,
+ M4_PMU_PERFCTR_MAP_STALL_DISPATCH = 0x270,
+ M4_PMU_PERFCTR_MAP_REWIND = 0x275,
+ M4_PMU_PERFCTR_MAP_STALL = 0x276,
+ M4_PMU_PERFCTR_MAP_INT_UOP = 0x27c,
+ M4_PMU_PERFCTR_MAP_LDST_UOP = 0x27d,
+ M4_PMU_PERFCTR_MAP_SIMD_UOP = 0x27e,
+ M4_PMU_PERFCTR_SCHEDULE_UOP_ANY = 0x283,
+ M4_PMU_PERFCTR_MAP_INT_SME_UOP = 0x285,
+ M4_PMU_PERFCTR_SME_ENGINE_SM_ENABLE = 0x286,
+ M4_PMU_PERFCTR_SME_ENGINE_SM_ZA_ENABLE = 0x287,
+ M4_PMU_PERFCTR_SME_ENGINE_ZA_ENABLED_SM_DISABLED = 0x288,
+ M4_PMU_PERFCTR_LDST_UNIT_WAITING_SME_ENGINE_INST_QUEUE_FULL = 0x28c,
+ M4_PMU_PERFCTR_SCHEDULE_WAITING_SME_ENGINE_REG_DATA = 0x28e,
+ M4_PMU_PERFCTR_LDST_UNIT_WAITING_SME_ENGINE_MEM_DATA = 0x28f,
+ M4_PMU_PERFCTR_LDST_UNIT_OLD_L1D_CACHE_MISS = 0x290,
+ M4_PMU_PERFCTR_LDST_UNIT_WAITING_OLD_L1D_CACHE_MISS = 0x291,
+ M4_PMU_PERFCTR_LD_UNIT_WAITING_YOUNG_L1D_CACHE_MISS = 0x294,
+ M4_PMU_PERFCTR_MAP_RECOVERY = 0x2ad,
+ M4_PMU_PERFCTR_MAP_STALL_NONRECOVERY = 0x2ae,
+ M4_PMU_PERFCTR_SCHEDULE_EMPTY = 0x351,
+ M4_PMU_PERFCTR_L1I_TLB_FILL = 0x404,
+ M4_PMU_PERFCTR_L1D_TLB_FILL = 0x405,
+ M4_PMU_PERFCTR_MMU_TABLE_WALK_INSTRUCTION = 0x407,
+ M4_PMU_PERFCTR_MMU_TABLE_WALK_DATA = 0x408,
+ M4_PMU_PERFCTR_L2_TLB_MISS_INSTRUCTION = 0x40a,
+ M4_PMU_PERFCTR_L2_TLB_MISS_DATA = 0x40b,
+ M4_PMU_PERFCTR_LDST_SME_XPG_UOP = 0x508,
+ M4_PMU_PERFCTR_INST_SME_ENGINE_PACKING_FUSED = 0x529,
+ M4_PMU_PERFCTR_LD_BLOCKED_BY_SME_LDST = 0x52c,
+ M4_PMU_PERFCTR_ST_BARRIER_BLOCKED_BY_SME_LDST = 0x52e,
+ M4_PMU_PERFCTR_LD_SME_NT_UOP = 0x573,
+ M4_PMU_PERFCTR_ST_SME_NT_UOP = 0x574,
+ M4_PMU_PERFCTR_LD_SME_NORMAL_UOP = 0x575,
+ M4_PMU_PERFCTR_ST_SME_NORMAL_UOP = 0x576,
+ M4_PMU_PERFCTR_LDST_SME_PRED_INACTIVE = 0x577,
+ M4_PMU_PERFCTR_L1D_TLB_ACCESS = 0x5a0,
+ M4_PMU_PERFCTR_L1D_TLB_MISS = 0x5a1,
+ M4_PMU_PERFCTR_L1D_CACHE_MISS_ST = 0x5a2,
+ M4_PMU_PERFCTR_L1D_CACHE_MISS_LD = 0x5a3,
+ M4_PMU_PERFCTR_LD_UNIT_UOP = 0x5a6,
+ M4_PMU_PERFCTR_ST_UNIT_UOP = 0x5a7,
+ M4_PMU_PERFCTR_L1D_CACHE_WRITEBACK = 0x5a8,
+ M4_PMU_PERFCTR_LDST_X64_UOP = 0x5b1,
+ M4_PMU_PERFCTR_LDST_XPG_UOP = 0x5b2,
+ M4_PMU_PERFCTR_ATOMIC_OR_EXCLUSIVE_SUCC = 0x5b3,
+ M4_PMU_PERFCTR_ATOMIC_OR_EXCLUSIVE_FAIL = 0x5b4,
+ M4_PMU_PERFCTR_ST_NT_UOP = 0x5e5,
+ M4_PMU_PERFCTR_LD_NT_UOP = 0x5e6,
+ M4_PMU_PERFCTR_FLUSH_RESTART_OTHER_NONSPEC = 0x884,
+ M4_PMU_PERFCTR_INST_BRANCH_CALL = 0x88e,
+ M4_PMU_PERFCTR_INST_BRANCH_RET = 0x88f,
+ M4_PMU_PERFCTR_INST_BRANCH_TAKEN = 0x890,
+ M4_PMU_PERFCTR_INST_BRANCH_INDIR = 0x893,
+ M4_PMU_PERFCTR_INST_BRANCH_COND = 0x894,
+ M4_PMU_PERFCTR_INST_INT_LD = 0x895,
+ M4_PMU_PERFCTR_INST_INT_ST = 0x896,
+ M4_PMU_PERFCTR_INST_INT_ALU = 0x897,
+ M4_PMU_PERFCTR_INST_SIMD_LD = 0x898,
+ M4_PMU_PERFCTR_INST_SIMD_ST = 0x899,
+ M4_PMU_PERFCTR_INST_SIMD_ALU = 0x89a,
+ M4_PMU_PERFCTR_INST_LDST = 0x89b,
+ M4_PMU_PERFCTR_INST_BARRIER = 0x89c,
+ M4_PMU_PERFCTR_INST_SIMD_ALU_VEC = 0x89f,
+ M4_PMU_PERFCTR_INST_SME_ENGINE_SCALARFP = 0x8a0,
+ M4_PMU_PERFCTR_INST_SME_ENGINE_LD = 0x8a1,
+ M4_PMU_PERFCTR_INST_SME_ENGINE_ST = 0x8a2,
+ M4_PMU_PERFCTR_INST_SME_ENGINE_ALU = 0x8a3,
+ M4_PMU_PERFCTR_L1D_CACHE_MISS_LD_NONSPEC = 0x8bf,
+ M4_PMU_PERFCTR_L1D_CACHE_MISS_ST_NONSPEC = 0x8c0,
+ M4_PMU_PERFCTR_L1D_TLB_MISS_NONSPEC = 0x8c1,
+ M4_PMU_PERFCTR_ST_MEM_ORDER_VIOL_LD_NONSPEC = 0x8c4,
+ M4_PMU_PERFCTR_BRANCH_COND_MISPRED_NONSPEC = 0x8c5,
+ M4_PMU_PERFCTR_BRANCH_INDIR_MISPRED_NONSPEC = 0x8c6,
+ M4_PMU_PERFCTR_BRANCH_RET_INDIR_MISPRED_NONSPEC = 0x8c8,
+ M4_PMU_PERFCTR_BRANCH_CALL_INDIR_MISPRED_NONSPEC = 0x8ca,
+ M4_PMU_PERFCTR_L1I_CACHE_MISS_DEMAND = 0x4006,
+ M4_PMU_PERFCTR_LAST = M3_PMU_CFG_EVENT,
+
+ /*
+ * From this point onwards, these are not actual HW events,
+ * but attributes that get stored in hw->config_base.
+ */
+ M4_PMU_CFG_COUNT_USER = BIT(16),
+ M4_PMU_CFG_COUNT_KERNEL = BIT(17),
+ M4_PMU_CFG_COUNT_HOST = BIT(18),
+ M4_PMU_CFG_COUNT_GUEST = BIT(19),
+};
+
/*
* Per-event affinity table. Most events can be installed on counter
* 2-9, but there are a number of exceptions. Note that this table
@@ -277,6 +392,40 @@ static const struct event_affinity_16 m3_pmu_event_affinity[] = {
{ M3_PMU_PERFCTR_BRANCH_MISPRED_NONSPEC, ONLY_5_6_7 },
};
+static const struct event_affinity_16 m4_pmu_event_affinity[] = {
+ { M4_PMU_PERFCTR_INST_ALL, ONLY_2_TO_7 | BIT(1) },
+ { M4_PMU_PERFCTR_CORE_ACTIVE_CYCLE, ANY_BUT_0_1 | BIT(0) },
+ { M4_PMU_PERFCTR_INST_BRANCH, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_BRANCH_MISPRED_NONSPEC, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_RETIRE_UOP, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_INST_BRANCH_CALL, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_INST_BRANCH_RET, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_INST_BRANCH_TAKEN, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_INST_BRANCH_INDIR, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_INST_BRANCH_COND, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_INST_INT_LD, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_INST_INT_ST, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_INST_INT_ALU, BIT(7) },
+ { M4_PMU_PERFCTR_INST_SIMD_LD, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_INST_SIMD_ST, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_INST_SIMD_ALU, BIT(7) },
+ { M4_PMU_PERFCTR_INST_LDST, BIT(7) },
+ { M4_PMU_PERFCTR_INST_BARRIER, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_INST_SIMD_ALU_VEC, BIT(7) },
+ { M4_PMU_PERFCTR_INST_SME_ENGINE_SCALARFP, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_INST_SME_ENGINE_LD, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_INST_SME_ENGINE_ST, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_INST_SME_ENGINE_ALU, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_L1D_CACHE_MISS_LD_NONSPEC, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_L1D_CACHE_MISS_ST_NONSPEC, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_L1D_TLB_MISS_NONSPEC, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_ST_MEM_ORDER_VIOL_LD_NONSPEC, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_BRANCH_COND_MISPRED_NONSPEC, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_BRANCH_INDIR_MISPRED_NONSPEC, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_BRANCH_RET_INDIR_MISPRED_NONSPEC, ONLY_2_TO_7 },
+ { M4_PMU_PERFCTR_BRANCH_CALL_INDIR_MISPRED_NONSPEC, ONLY_2_TO_7 },
+};
+
static const unsigned int m1_pmu_perf_map[PERF_COUNT_HW_MAX] = {
PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = M1_PMU_PERFCTR_CORE_ACTIVE_CYCLE,
@@ -293,12 +442,27 @@ static const unsigned int m3_pmu_perf_map[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_BRANCH_MISSES] = M3_PMU_PERFCTR_BRANCH_MISPRED_NONSPEC,
};
+static const unsigned int m4_pmu_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
+ [PERF_COUNT_HW_CPU_CYCLES] = M4_PMU_PERFCTR_CORE_ACTIVE_CYCLE,
+ [PERF_COUNT_HW_INSTRUCTIONS] = M4_PMU_PERFCTR_INST_ALL,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = M4_PMU_PERFCTR_ARM_L1D_CACHE,
+ [PERF_COUNT_HW_CACHE_MISSES] = M4_PMU_PERFCTR_ARM_L1D_CACHE_REFILL,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = M4_PMU_PERFCTR_INST_BRANCH,
+ [PERF_COUNT_HW_BRANCH_MISSES] = M4_PMU_PERFCTR_ARM_BR_MIS_PRED,
+ [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = M4_PMU_PERFCTR_ARM_STALL_FRONTEND,
+ [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = M4_PMU_PERFCTR_ARM_STALL_BACKEND,
+};
+
#define M1_PMUV3_EVENT_MAP(pmuv3_event, m1_event) \
[ARMV8_PMUV3_PERFCTR_##pmuv3_event] = M1_PMU_PERFCTR_##m1_event
#define M3_PMUV3_EVENT_MAP(pmuv3_event, m3_event) \
[ARMV8_PMUV3_PERFCTR_##pmuv3_event] = M3_PMU_PERFCTR_##m3_event
+#define M4_PMUV3_EVENT_MAP(pmuv3_event, m4_event) \
+ [ARMV8_PMUV3_PERFCTR_##pmuv3_event] = M4_PMU_PERFCTR_##m4_event
+
static const u16 m1_pmu_pmceid_map[ARMV8_PMUV3_MAX_COMMON_EVENTS] = {
[0 ... ARMV8_PMUV3_MAX_COMMON_EVENTS - 1] = HW_OP_UNSUPPORTED,
M1_PMUV3_EVENT_MAP(INST_RETIRED, INST_ALL),
@@ -315,6 +479,25 @@ static const u16 m3_pmu_pmceid_map[ARMV8_PMUV3_MAX_COMMON_EVENTS] = {
M3_PMUV3_EVENT_MAP(BR_MIS_PRED_RETIRED, BRANCH_MISPRED_NONSPEC),
};
+static const u16 m4_pmu_pmceid_map[ARMV8_PMUV3_MAX_COMMON_EVENTS] = {
+ [0 ... ARMV8_PMUV3_MAX_COMMON_EVENTS - 1] = HW_OP_UNSUPPORTED,
+ M4_PMUV3_EVENT_MAP(L1D_CACHE_REFILL, ARM_L1D_CACHE_REFILL),
+ M4_PMUV3_EVENT_MAP(L1D_CACHE, ARM_L1D_CACHE),
+ M4_PMUV3_EVENT_MAP(INST_RETIRED, INST_ALL),
+ M4_PMUV3_EVENT_MAP(BR_MIS_PRED, ARM_BR_MIS_PRED),
+ M4_PMUV3_EVENT_MAP(CPU_CYCLES, CORE_ACTIVE_CYCLE),
+ M4_PMUV3_EVENT_MAP(BR_PRED, ARM_BR_PRED),
+ M4_PMUV3_EVENT_MAP(BR_RETIRED, INST_BRANCH),
+ M4_PMUV3_EVENT_MAP(STALL_FRONTEND, ARM_STALL_FRONTEND),
+ M4_PMUV3_EVENT_MAP(STALL_BACKEND, ARM_STALL_BACKEND),
+ M4_PMUV3_EVENT_MAP(L1D_CACHE_LMISS_RD, ARM_L1D_CACHE_LMISS_RD),
+ M4_PMUV3_EVENT_MAP(STALL, ARM_STALL),
+ M4_PMUV3_EVENT_MAP(STALL_SLOT_BACKEND, ARM_STALL_SLOT_BACKEND),
+ M4_PMUV3_EVENT_MAP(STALL_SLOT_FRONTEND, ARM_STALL_SLOT_FRONTEND),
+ M4_PMUV3_EVENT_MAP(STALL_SLOT, ARM_STALL_SLOT),
+ M4_PMUV3_EVENT_MAP(BR_MIS_PRED_RETIRED, BRANCH_MISPRED_NONSPEC),
+};
+
/* sysfs definitions */
static ssize_t m1_pmu_events_sysfs_show(struct device *dev,
struct device_attribute *attr,
@@ -356,6 +539,12 @@ static struct attribute *m3_pmu_event_attrs[] = {
NULL,
};
+static struct attribute *m4_pmu_event_attrs[] = {
+ M3_PMU_EVENT_ATTR(cycles, M4_PMU_PERFCTR_CORE_ACTIVE_CYCLE),
+ M3_PMU_EVENT_ATTR(instructions, M4_PMU_PERFCTR_INST_ALL),
+ NULL,
+};
+
static const struct attribute_group m1_pmu_events_attr_group = {
.name = "events",
.attrs = m1_pmu_event_attrs,
@@ -366,6 +555,11 @@ static const struct attribute_group m3_pmu_events_attr_group = {
.attrs = m3_pmu_event_attrs,
};
+static const struct attribute_group m4_pmu_events_attr_group = {
+ .name = "events",
+ .attrs = m4_pmu_event_attrs,
+};
+
PMU_FORMAT_ATTR_SHOW(event_8b, "config:0-7");
PMU_FORMAT_ATTR_SHOW(event_16b, "config:0-15");
@@ -740,6 +934,13 @@ static int m3_pmu_get_event_idx(struct pmu_hw_events *cpuc,
m3_pmu_event_affinity);
}
+static int m4_pmu_get_event_idx(struct pmu_hw_events *cpuc,
+ struct perf_event *event)
+{
+ return apple_pmu_get_event_idx_16(cpuc, event, ARRAY_SIZE(m4_pmu_event_affinity),
+ m4_pmu_event_affinity);
+}
+
static void m1_pmu_clear_event_idx(struct pmu_hw_events *cpuc,
struct perf_event *event)
{
@@ -800,6 +1001,12 @@ static int m3_pmu_map_event(struct perf_event *event)
M3_PMU_CFG_EVENT);
}
+static int m4_pmu_map_event(struct perf_event *event)
+{
+ return apple_pmu_map_event(event, &m4_pmu_perf_map, ARMPMU_EVT_63BIT,
+ M3_PMU_CFG_EVENT);
+}
+
static int apple_pmu_map_pmuv3_event(unsigned int eventsel, const u16 pmceid_map[])
{
u16 apple_event = HW_OP_UNSUPPORTED;
@@ -820,6 +1027,11 @@ static int m3_pmu_map_pmuv3_event(unsigned int eventsel)
return apple_pmu_map_pmuv3_event(eventsel, m3_pmu_pmceid_map);
}
+static int m4_pmu_map_pmuv3_event(unsigned int eventsel)
+{
+ return apple_pmu_map_pmuv3_event(eventsel, m4_pmu_pmceid_map);
+}
+
static void apple_pmu_init_pmceid(struct arm_pmu *pmu)
{
unsigned int event;
@@ -933,14 +1145,26 @@ static int gen ## _pmu_ ## family ## _init(struct arm_pmu *cpu_pmu) \
#define m2_pmu_events_attr_group m1_pmu_events_attr_group
#define m2_pmu_format_attr_group m1_pmu_format_attr_group
+#define m4_pmu_enable_event m3_pmu_enable_event
+#define m4_pmu_set_event_filter m3_pmu_set_event_filter
+#define m4_pmu_format_attr_group m3_pmu_format_attr_group
+
APPLE_PMU_INIT(m1, icestorm)
APPLE_PMU_INIT(m1, firestorm)
APPLE_PMU_INIT(m2, avalanche)
APPLE_PMU_INIT(m2, blizzard)
APPLE_PMU_INIT(m3, sawtooth)
APPLE_PMU_INIT(m3, everest)
+APPLE_PMU_INIT(m4, donan_e)
+APPLE_PMU_INIT(m4, donan_p)
+APPLE_PMU_INIT(m4, brava_e)
+APPLE_PMU_INIT(m4, brava_p)
static const struct of_device_id m1_pmu_of_device_ids[] = {
+ { .compatible = "apple,brava-e-pmu", .data = m4_pmu_brava_e_init, },
+ { .compatible = "apple,brava-p-pmu", .data = m4_pmu_brava_p_init, },
+ { .compatible = "apple,donan-e-pmu", .data = m4_pmu_donan_e_init, },
+ { .compatible = "apple,donan-p-pmu", .data = m4_pmu_donan_p_init, },
{ .compatible = "apple,sawtooth-pmu", .data = m3_pmu_sawtooth_init, },
{ .compatible = "apple,everest-pmu", .data = m3_pmu_everest_init, },
{ .compatible = "apple,avalanche-pmu", .data = m2_pmu_avalanche_init, },
--
2.56.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 08/13] drivers/perf: apple_m1: Add Apple A18 Support
2026-11-03 10:14 [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support Myria Sarvay via B4 Relay
` (6 preceding siblings ...)
2026-11-03 10:14 ` [PATCH 07/13] drivers/perf: apple_m1: Add Apple M4 " Myria Sarvay via B4 Relay
@ 2026-11-03 10:14 ` Myria Sarvay via B4 Relay
2026-11-03 10:47 ` sashiko-bot
2026-11-03 10:14 ` [PATCH 09/13] arm64: dts: apple: t603x: Add PMU Device Nodes Myria Sarvay via B4 Relay
` (4 subsequent siblings)
12 siblings, 1 reply; 19+ messages in thread
From: Myria Sarvay via B4 Relay @ 2026-11-03 10:14 UTC (permalink / raw)
To: Will Deacon, Mark Rutland, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sven Peter, Janne Grunau, Neal Gompa, Marc Zyngier
Cc: linux-arm-kernel, linux-perf-users, devicetree, linux-kernel,
asahi, Yuvan Shen, Myria Sarvay
From: Myria Sarvay <myrialsarvay@gmail.com>
The A18 has events and affinities identical to the M4, so use it.
Signed-off-by: Myria Sarvay <myrialsarvay@gmail.com>
---
drivers/perf/apple_m1_cpu_pmu.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index bdbd138cf1db..775f3d5aba7e 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -1149,12 +1149,23 @@ static int gen ## _pmu_ ## family ## _init(struct arm_pmu *cpu_pmu) \
#define m4_pmu_set_event_filter m3_pmu_set_event_filter
#define m4_pmu_format_attr_group m3_pmu_format_attr_group
+#define a18_pmu_enable_event m4_pmu_enable_event
+#define a18_pmu_map_event m4_pmu_map_event
+#define a18_pmu_get_event_idx m4_pmu_get_event_idx
+#define a18_pmu_set_event_filter m4_pmu_set_event_filter
+#define a18_pmu_map_pmuv3_event m4_pmu_map_pmuv3_event
+#define a18_pmu_init_pmceid m4_pmu_init_pmceid
+#define a18_pmu_events_attr_group m4_pmu_events_attr_group
+#define a18_pmu_format_attr_group m4_pmu_format_attr_group
+
APPLE_PMU_INIT(m1, icestorm)
APPLE_PMU_INIT(m1, firestorm)
APPLE_PMU_INIT(m2, avalanche)
APPLE_PMU_INIT(m2, blizzard)
APPLE_PMU_INIT(m3, sawtooth)
APPLE_PMU_INIT(m3, everest)
+APPLE_PMU_INIT(a18, tahiti_e)
+APPLE_PMU_INIT(a18, tahiti_p)
APPLE_PMU_INIT(m4, donan_e)
APPLE_PMU_INIT(m4, donan_p)
APPLE_PMU_INIT(m4, brava_e)
@@ -1165,6 +1176,8 @@ static const struct of_device_id m1_pmu_of_device_ids[] = {
{ .compatible = "apple,brava-p-pmu", .data = m4_pmu_brava_p_init, },
{ .compatible = "apple,donan-e-pmu", .data = m4_pmu_donan_e_init, },
{ .compatible = "apple,donan-p-pmu", .data = m4_pmu_donan_p_init, },
+ { .compatible = "apple,tahiti-e-pmu", .data = a18_pmu_tahiti_e_init, },
+ { .compatible = "apple,tahiti-p-pmu", .data = a18_pmu_tahiti_p_init, },
{ .compatible = "apple,sawtooth-pmu", .data = m3_pmu_sawtooth_init, },
{ .compatible = "apple,everest-pmu", .data = m3_pmu_everest_init, },
{ .compatible = "apple,avalanche-pmu", .data = m2_pmu_avalanche_init, },
--
2.56.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 09/13] arm64: dts: apple: t603x: Add PMU Device Nodes
2026-11-03 10:14 [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support Myria Sarvay via B4 Relay
` (7 preceding siblings ...)
2026-11-03 10:14 ` [PATCH 08/13] drivers/perf: apple_m1: Add Apple A18 Support Myria Sarvay via B4 Relay
@ 2026-11-03 10:14 ` Myria Sarvay via B4 Relay
2026-11-03 10:54 ` sashiko-bot
2026-11-03 10:14 ` [PATCH 10/13] arm64: dts: apple: t8122: " Myria Sarvay via B4 Relay
` (3 subsequent siblings)
12 siblings, 1 reply; 19+ messages in thread
From: Myria Sarvay via B4 Relay @ 2026-11-03 10:14 UTC (permalink / raw)
To: Will Deacon, Mark Rutland, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sven Peter, Janne Grunau, Neal Gompa, Marc Zyngier
Cc: linux-arm-kernel, linux-perf-users, devicetree, linux-kernel,
asahi, Yuvan Shen, Myria Sarvay
From: Myria Sarvay <myrialsarvay@gmail.com>
Adds the PMU nodes to all t603x devices.
Signed-off-by: Myria Sarvay <myrialsarvay@gmail.com>
---
arch/arm64/boot/dts/apple/t6030.dtsi | 12 ++++++++++++
arch/arm64/boot/dts/apple/t6031-base.dtsi | 12 ++++++++++++
2 files changed, 24 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t6030.dtsi b/arch/arm64/boot/dts/apple/t6030.dtsi
index 85a16d03e22f..c3779e1584c2 100644
--- a/arch/arm64/boot/dts/apple/t6030.dtsi
+++ b/arch/arm64/boot/dts/apple/t6030.dtsi
@@ -239,6 +239,18 @@ l2_cache_1: l2-cache-1 {
};
};
+ pmu-e {
+ compatible = "apple,sawtooth-pmu";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_FIQ AIC_CPU_PMU_E IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pmu-p {
+ compatible = "apple,everest-pmu";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_FIQ AIC_CPU_PMU_P IRQ_TYPE_LEVEL_HIGH>;
+ };
+
reserved-memory {
ranges;
#address-cells = <2>;
diff --git a/arch/arm64/boot/dts/apple/t6031-base.dtsi b/arch/arm64/boot/dts/apple/t6031-base.dtsi
index f62ce0690182..3b97c1240934 100644
--- a/arch/arm64/boot/dts/apple/t6031-base.dtsi
+++ b/arch/arm64/boot/dts/apple/t6031-base.dtsi
@@ -308,6 +308,18 @@ l2_cache_2: l2-cache-2 {
};
};
+ pmu-e {
+ compatible = "apple,sawtooth-pmu";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_FIQ 0 AIC_CPU_PMU_E IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pmu-p {
+ compatible = "apple,everest-pmu";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_FIQ 0 AIC_CPU_PMU_P IRQ_TYPE_LEVEL_HIGH>;
+ };
+
reserved-memory {
ranges;
#address-cells = <2>;
--
2.56.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 10/13] arm64: dts: apple: t8122: Add PMU Device Nodes
2026-11-03 10:14 [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support Myria Sarvay via B4 Relay
` (8 preceding siblings ...)
2026-11-03 10:14 ` [PATCH 09/13] arm64: dts: apple: t603x: Add PMU Device Nodes Myria Sarvay via B4 Relay
@ 2026-11-03 10:14 ` Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 11/13] arm64: dts: apple: t604x: " Myria Sarvay via B4 Relay
` (2 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Myria Sarvay via B4 Relay @ 2026-11-03 10:14 UTC (permalink / raw)
To: Will Deacon, Mark Rutland, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sven Peter, Janne Grunau, Neal Gompa, Marc Zyngier
Cc: linux-arm-kernel, linux-perf-users, devicetree, linux-kernel,
asahi, Yuvan Shen, Myria Sarvay
From: Myria Sarvay <myrialsarvay@gmail.com>
Adds the PMU nodes to all t8122 devices.
Signed-off-by: Myria Sarvay <myrialsarvay@gmail.com>
---
arch/arm64/boot/dts/apple/t8122.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t8122.dtsi b/arch/arm64/boot/dts/apple/t8122.dtsi
index 959ddf36efa1..c9e81a6cc9b7 100644
--- a/arch/arm64/boot/dts/apple/t8122.dtsi
+++ b/arch/arm64/boot/dts/apple/t8122.dtsi
@@ -180,6 +180,18 @@ l2_cache_1: l2-cache-1 {
};
};
+ pmu-e {
+ compatible = "apple,sawtooth-pmu";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_FIQ AIC_CPU_PMU_E IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pmu-p {
+ compatible = "apple,everest-pmu";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_FIQ AIC_CPU_PMU_P IRQ_TYPE_LEVEL_HIGH>;
+ };
+
soc {
compatible = "simple-bus";
ranges;
--
2.56.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 11/13] arm64: dts: apple: t604x: Add PMU Device Nodes
2026-11-03 10:14 [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support Myria Sarvay via B4 Relay
` (9 preceding siblings ...)
2026-11-03 10:14 ` [PATCH 10/13] arm64: dts: apple: t8122: " Myria Sarvay via B4 Relay
@ 2026-11-03 10:14 ` Myria Sarvay via B4 Relay
2026-11-03 11:12 ` sashiko-bot
2026-11-03 10:14 ` [PATCH 12/13] arm64: dts: apple: t8132: " Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 13/13] arm64: dts: apple: t8140: " Myria Sarvay via B4 Relay
12 siblings, 1 reply; 19+ messages in thread
From: Myria Sarvay via B4 Relay @ 2026-11-03 10:14 UTC (permalink / raw)
To: Will Deacon, Mark Rutland, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sven Peter, Janne Grunau, Neal Gompa, Marc Zyngier
Cc: linux-arm-kernel, linux-perf-users, devicetree, linux-kernel,
asahi, Yuvan Shen, Myria Sarvay
From: Myria Sarvay <myrialsarvay@gmail.com>
Adds the PMU nodes to all t604x devices.
Signed-off-by: Myria Sarvay <myrialsarvay@gmail.com>
---
arch/arm64/boot/dts/apple/t6041.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t6041.dtsi b/arch/arm64/boot/dts/apple/t6041.dtsi
index 9110d05c896d..2c72972d1219 100644
--- a/arch/arm64/boot/dts/apple/t6041.dtsi
+++ b/arch/arm64/boot/dts/apple/t6041.dtsi
@@ -314,6 +314,18 @@ l2_cache_2: l2-cache-2 {
};
};
+ pmu-e {
+ compatible = "apple,brava-e-pmu";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_FIQ 0 AIC_CPU_PMU_E IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pmu-p {
+ compatible = "apple,brava-p-pmu";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_FIQ 0 AIC_CPU_PMU_P IRQ_TYPE_LEVEL_HIGH>;
+ };
+
soc {
compatible = "simple-bus";
ranges;
--
2.56.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 12/13] arm64: dts: apple: t8132: Add PMU Device Nodes
2026-11-03 10:14 [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support Myria Sarvay via B4 Relay
` (10 preceding siblings ...)
2026-11-03 10:14 ` [PATCH 11/13] arm64: dts: apple: t604x: " Myria Sarvay via B4 Relay
@ 2026-11-03 10:14 ` Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 13/13] arm64: dts: apple: t8140: " Myria Sarvay via B4 Relay
12 siblings, 0 replies; 19+ messages in thread
From: Myria Sarvay via B4 Relay @ 2026-11-03 10:14 UTC (permalink / raw)
To: Will Deacon, Mark Rutland, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sven Peter, Janne Grunau, Neal Gompa, Marc Zyngier
Cc: linux-arm-kernel, linux-perf-users, devicetree, linux-kernel,
asahi, Yuvan Shen, Myria Sarvay
From: Myria Sarvay <myrialsarvay@gmail.com>
Adds the PMU nodes to all t8132 devices.
Signed-off-by: Myria Sarvay <myrialsarvay@gmail.com>
---
arch/arm64/boot/dts/apple/t8132.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t8132.dtsi b/arch/arm64/boot/dts/apple/t8132.dtsi
index afec92a06015..d0f8a40097ee 100644
--- a/arch/arm64/boot/dts/apple/t8132.dtsi
+++ b/arch/arm64/boot/dts/apple/t8132.dtsi
@@ -189,6 +189,18 @@ clkref: clock-ref {
clock-output-names = "clkref";
};
+ pmu-e {
+ compatible = "apple,donan-e-pmu";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_FIQ AIC_CPU_PMU_E IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pmu-p {
+ compatible = "apple,donan-p-pmu";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_FIQ AIC_CPU_PMU_P IRQ_TYPE_LEVEL_HIGH>;
+ };
+
soc: soc {
compatible = "simple-bus";
#address-cells = <2>;
--
2.56.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 13/13] arm64: dts: apple: t8140: Add PMU Device Nodes
2026-11-03 10:14 [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support Myria Sarvay via B4 Relay
` (11 preceding siblings ...)
2026-11-03 10:14 ` [PATCH 12/13] arm64: dts: apple: t8132: " Myria Sarvay via B4 Relay
@ 2026-11-03 10:14 ` Myria Sarvay via B4 Relay
2026-11-03 11:23 ` sashiko-bot
12 siblings, 1 reply; 19+ messages in thread
From: Myria Sarvay via B4 Relay @ 2026-11-03 10:14 UTC (permalink / raw)
To: Will Deacon, Mark Rutland, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sven Peter, Janne Grunau, Neal Gompa, Marc Zyngier
Cc: linux-arm-kernel, linux-perf-users, devicetree, linux-kernel,
asahi, Yuvan Shen, Myria Sarvay
From: Myria Sarvay <myrialsarvay@gmail.com>
Adds the PMU nodes to all t8140 devices.
Signed-off-by: Myria Sarvay <myrialsarvay@gmail.com>
---
arch/arm64/boot/dts/apple/t8140.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t8140.dtsi b/arch/arm64/boot/dts/apple/t8140.dtsi
index 150d91bdf6fc..6e6fd5754406 100644
--- a/arch/arm64/boot/dts/apple/t8140.dtsi
+++ b/arch/arm64/boot/dts/apple/t8140.dtsi
@@ -136,6 +136,18 @@ l2_cache_1: l2-cache-1 {
};
};
+ pmu-e {
+ compatible = "apple,tahiti-e-pmu";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_FIQ AIC_CPU_PMU_E IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pmu-p {
+ compatible = "apple,tahiti-p-pmu";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_FIQ AIC_CPU_PMU_P IRQ_TYPE_LEVEL_HIGH>;
+ };
+
soc: soc {
compatible = "simple-bus";
ranges;
--
2.56.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH 05/13] drivers/perf: apple_m1: Use macros for per-implementation init functions
2026-11-03 10:14 ` [PATCH 05/13] drivers/perf: apple_m1: Use macros for per-implementation init functions Myria Sarvay via B4 Relay
@ 2026-11-03 10:31 ` sashiko-bot
0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-11-03 10:31 UTC (permalink / raw)
To: Myria Sarvay; +Cc: linux-perf-users, devicetree, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Low] drivers/perf: apple_m1: unused macro m2_pmu_init_pmceid aliases removed symbol
- [Low] perf: apple_m1: redundant macro aliasing and duplication in APPLE_PMU_INIT()
--
commit b798f559facbfb19db0eef028f7f7e42ebc0042c
Author: Myria Sarvay <myrialsarvay@gmail.com>
drivers/perf: apple_m1: Use macros for per-implementation init functions
This commit replaces the per-core-family PMU initialization functions in
drivers/perf/apple_m1_cpu_pmu.c with an APPLE_PMU_INIT() macro and adds
compatibility macro aliases for M2 callbacks and attribute groups.
> diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
> index a14864263bf1f..e7e9b51ffadcc 100644
> --- a/drivers/perf/apple_m1_cpu_pmu.c
> +++ b/drivers/perf/apple_m1_cpu_pmu.c
> @@ -653,71 +653,40 @@ static int apple_pmu_init(struct arm_pmu *cpu_pmu)
> }
>
> /* Device driver gunk */
> -static int m1_pmu_ice_init(struct arm_pmu *cpu_pmu)
> -{
> - cpu_pmu->name = "apple_icestorm_pmu";
> - cpu_pmu->enable = m1_pmu_enable_event;
> - cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
> - cpu_pmu->map_event = m1_pmu_map_event;
> - cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
> -
> - cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
> -
> - cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
> - cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
> - return apple_pmu_init(cpu_pmu);
> -}
[ ... ]
> +#define APPLE_PMU_INIT(gen, family) \
> +static int gen ## _pmu_ ## family ## _init(struct arm_pmu *cpu_pmu) \
> +{ \
> + cpu_pmu->name = "apple_" #family "_pmu"; \
> + cpu_pmu->enable = gen ## _pmu_enable_event; \
> + cpu_pmu->get_event_idx = gen ## _pmu_get_event_idx; \
> + cpu_pmu->map_event = gen ## _pmu_map_event; \
> + cpu_pmu->set_event_filter = gen ## _pmu_set_event_filter; \
> + \
> + cpu_pmu->map_pmuv3_event = gen ## _pmu_map_pmuv3_event; \
> + \
> + cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &gen ## _pmu_events_attr_group; \
> + cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &gen ## _pmu_format_attr_group; \
> + return apple_pmu_init(cpu_pmu); \
> +}
[Severity: Low]
This isn't a bug, but APPLE_PMU_INIT(gen, family) expands all seven callback
and attr_groups assignments into every per-family init function (such as
m1_pmu_icestorm_init() and m1_pmu_firestorm_init()), even though core
families within the same generation only differ in cpu_pmu->name.
Because APPLE_PMU_INIT() unconditionally token-pastes gen ## _pmu_* for
every field, any generation that shares callbacks or attribute groups with
an earlier generation also requires a block of #define aliases to satisfy
token pasting (including in subsequent patches for m4 and a18).
Would it be cleaner to follow the pattern in drivers/perf/arm_pmuv3.c
(PMUV3_INIT_SIMPLE calling armv8_pmu_init), or have per-generation init
helpers called by a small per-family wrapper that only sets cpu_pmu->name,
to avoid both the #define alias blocks and the repeated per-family
assignments?
> +
> +#define m2_pmu_enable_event m1_pmu_enable_event
> +#define m2_pmu_get_event_idx m1_pmu_get_event_idx
> +#define m2_pmu_set_event_filter m1_pmu_set_event_filter
> +#define m2_pmu_map_pmuv3_event m1_pmu_map_pmuv3_event
> +#define m2_pmu_init_pmceid m1_pmu_init_pmceid
[Severity: Low]
Is m2_pmu_init_pmceid needed here?
Earlier in the series ("drivers/perf: apple_m1: Support per-implementation
event tables"), m1_pmu_init_pmceid() was replaced by apple_pmu_init_pmceid(),
which is called directly from apple_pmu_init():
static int apple_pmu_init(struct arm_pmu *cpu_pmu)
{
...
apple_pmu_init_pmceid(cpu_pmu);
bitmap_set(cpu_pmu->cntr_mask, 0, M1_PMU_NR_COUNTERS);
return 0;
}
APPLE_PMU_INIT() does not reference gen ## _pmu_init_pmceid, so
m2_pmu_init_pmceid (and a18_pmu_init_pmceid in "drivers/perf: apple_m1: Add
Apple A18 Support") is unused and aliases a non-existent symbol. Can this
macro definition be dropped?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261103-m3-plus-pmu-events-v1-0-a8eb6c1139fe@gmail.com?part=5
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 08/13] drivers/perf: apple_m1: Add Apple A18 Support
2026-11-03 10:14 ` [PATCH 08/13] drivers/perf: apple_m1: Add Apple A18 Support Myria Sarvay via B4 Relay
@ 2026-11-03 10:47 ` sashiko-bot
0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-11-03 10:47 UTC (permalink / raw)
To: Myria Sarvay; +Cc: linux-perf-users, devicetree, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] drivers/perf: apple_m1: redundant a18_pmu_* aliases and unused macro
--
commit 96c1a110d959d59196297459a3c8bd2316dfaece
Author: Myria Sarvay <myrialsarvay@gmail.com>
drivers/perf: apple_m1: Add Apple A18 Support
This commit adds CPU PMU support for the Apple A18 (Tahiti) cores by
reusing the M4 PMU event mappings and callbacks.
> diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
> index bdbd138cf1db8..775f3d5aba7ea 100644
> --- a/drivers/perf/apple_m1_cpu_pmu.c
> +++ b/drivers/perf/apple_m1_cpu_pmu.c
> @@ -1149,12 +1149,23 @@ static int gen ## _pmu_ ## family ## _init(struct arm_pmu *cpu_pmu) \
> #define m4_pmu_set_event_filter m3_pmu_set_event_filter
> #define m4_pmu_format_attr_group m3_pmu_format_attr_group
>
> +#define a18_pmu_enable_event m4_pmu_enable_event
> +#define a18_pmu_map_event m4_pmu_map_event
> +#define a18_pmu_get_event_idx m4_pmu_get_event_idx
> +#define a18_pmu_set_event_filter m4_pmu_set_event_filter
> +#define a18_pmu_map_pmuv3_event m4_pmu_map_pmuv3_event
> +#define a18_pmu_init_pmceid m4_pmu_init_pmceid
> +#define a18_pmu_events_attr_group m4_pmu_events_attr_group
> +#define a18_pmu_format_attr_group m4_pmu_format_attr_group
> +
> APPLE_PMU_INIT(m1, icestorm)
> APPLE_PMU_INIT(m1, firestorm)
> APPLE_PMU_INIT(m2, avalanche)
> APPLE_PMU_INIT(m2, blizzard)
> APPLE_PMU_INIT(m3, sawtooth)
> APPLE_PMU_INIT(m3, everest)
> +APPLE_PMU_INIT(a18, tahiti_e)
> +APPLE_PMU_INIT(a18, tahiti_p)
[Severity: Low]
This isn't a bug, but since APPLE_PMU_INIT(gen, family) only uses the gen
argument to select the gen_pmu_* callbacks and attribute groups (while
cpu_pmu->name is constructed solely from family), are the a18_pmu_* alias
macros needed here?
Unlike m2 and m4, which define generation-specific callbacks or attribute
groups and only alias the remaining symbols from an earlier generation, a18
aliases every symbol to m4_pmu_*. In addition, a18_pmu_init_pmceid is never
used by APPLE_PMU_INIT() and expands to m4_pmu_init_pmceid, which does not
exist.
Could this use APPLE_PMU_INIT(m4, tahiti_e) and APPLE_PMU_INIT(m4, tahiti_p)
directly (with m4_pmu_tahiti_e_init and m4_pmu_tahiti_p_init in
m1_pmu_of_device_ids) and drop the a18_pmu_* macro definitions?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261103-m3-plus-pmu-events-v1-0-a8eb6c1139fe@gmail.com?part=8
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 09/13] arm64: dts: apple: t603x: Add PMU Device Nodes
2026-11-03 10:14 ` [PATCH 09/13] arm64: dts: apple: t603x: Add PMU Device Nodes Myria Sarvay via B4 Relay
@ 2026-11-03 10:54 ` sashiko-bot
0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-11-03 10:54 UTC (permalink / raw)
To: Myria Sarvay; +Cc: linux-perf-users, devicetree, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] arm64: dts: apple: missing AIC PMU affinities in t6030 and t6031-base
--
commit b22393aa51d5b877175fc97e743f45d90d0a09a1
Author: Myria Sarvay <myrialsarvay@gmail.com>
arm64: dts: apple: t603x: Add PMU Device Nodes
This commit adds the pmu-e (apple,sawtooth-pmu) and pmu-p (apple,everest-pmu)
device tree nodes to t6030.dtsi and t6031-base.dtsi.
> diff --git a/arch/arm64/boot/dts/apple/t6030.dtsi b/arch/arm64/boot/dts/apple/t6030.dtsi
> index 85a16d03e22f3..c3779e1584c2a 100644
> --- a/arch/arm64/boot/dts/apple/t6030.dtsi
> +++ b/arch/arm64/boot/dts/apple/t6030.dtsi
> @@ -239,6 +239,18 @@ l2_cache_1: l2-cache-1 {
> };
> };
>
> + pmu-e {
> + compatible = "apple,sawtooth-pmu";
> + interrupt-parent = <&aic>;
> + interrupts = <AIC_FIQ AIC_CPU_PMU_E IRQ_TYPE_LEVEL_HIGH>;
> + };
> +
> + pmu-p {
> + compatible = "apple,everest-pmu";
> + interrupt-parent = <&aic>;
> + interrupts = <AIC_FIQ AIC_CPU_PMU_P IRQ_TYPE_LEVEL_HIGH>;
> + };
> +
> reserved-memory {
> ranges;
> #address-cells = <2>;
> diff --git a/arch/arm64/boot/dts/apple/t6031-base.dtsi b/arch/arm64/boot/dts/apple/t6031-base.dtsi
> index f62ce0690182b..3b97c12409340 100644
> --- a/arch/arm64/boot/dts/apple/t6031-base.dtsi
> +++ b/arch/arm64/boot/dts/apple/t6031-base.dtsi
> @@ -308,6 +308,18 @@ l2_cache_2: l2-cache-2 {
> };
> };
>
> + pmu-e {
> + compatible = "apple,sawtooth-pmu";
> + interrupt-parent = <&aic>;
> + interrupts = <AIC_FIQ 0 AIC_CPU_PMU_E IRQ_TYPE_LEVEL_HIGH>;
> + };
> +
> + pmu-p {
> + compatible = "apple,everest-pmu";
> + interrupt-parent = <&aic>;
> + interrupts = <AIC_FIQ 0 AIC_CPU_PMU_P IRQ_TYPE_LEVEL_HIGH>;
> + };
[Severity: High]
Do the aic nodes for t6030 and the t6031-based SoCs (t6031, t6032, and t6034)
also need affinities child nodes mapping AIC_CPU_PMU_E and AIC_CPU_PMU_P to
their respective E-core and P-core CPU phandles?
In drivers/irqchip/irq-apple-aic.c, aic_irq_domain_translate() merges
AIC_CPU_PMU_E and AIC_CPU_PMU_P onto a single Linux percpu_devid IRQ
(AIC_CPU_PMU_P), and relies on the affinities subnode under aic (parsed by
aic_of_ic_init() -> build_fiq_affinity() into aic_irqc->fiq_aff[]) to report
the CPU mask for each PMU in aic_irq_get_fwspec_info():
drivers/irqchip/irq-apple-aic.c:aic_irq_get_fwspec_info() {
...
if (aic_irqc->fiq_aff[intid])
mask = &aic_irqc->fiq_aff[intid]->aff;
else
mask = cpu_possible_mask;
...
}
Because neither arch/arm64/boot/dts/apple/t6030.dtsi nor
arch/arm64/boot/dts/apple/t6031-die0.dtsi (or t6031.dtsi / t6032.dtsi)
defines an affinities subnode under aic, aic_irqc->fiq_aff[AIC_CPU_PMU_E] and
aic_irqc->fiq_aff[AIC_CPU_PMU_P] remain NULL, causing both PMUs to receive
cpu_possible_mask via:
m1_pmu_device_probe()
-> arm_pmu_device_probe()
-> pmu_parse_irqs()
-> platform_get_irq_affinity()
-> of_irq_get_affinity()
-> aic_irq_get_fwspec_info()
When pmu-e probes first, pmu_parse_percpu_irq() sets pmu-e's supported_cpus
to cpu_possible_mask, and armpmu_request_irq() registers pmu-e's per-CPU IRQ
across all CPUs and sets per_cpu(cpu_irq, cpu) = irq on every CPU.
When pmu-p probes second with the same merged virq and affinity equal to
cpu_possible_mask, armpmu_count_irq_users(affinity, irq) returns non-zero in
armpmu_request_irq():
drivers/perf/arm_pmu.c:armpmu_request_irq() {
...
} else if (armpmu_count_irq_users(affinity, irq) == 0) {
err = request_percpu_nmi(irq, handler, "arm-pmu", affinity, pcpu_armpmu);
/* If cannot get an NMI, get a normal interrupt */
if (err) {
err = request_percpu_irq_affinity(irq, handler, "arm-pmu",
affinity, pcpu_armpmu);
irq_ops = &percpu_pmuirq_ops;
} else {
has_nmi = true;
irq_ops = &percpu_pmunmi_ops;
}
} else {
/* Per cpudevid irq was already requested by another CPU */
irq_ops = armpmu_find_irq_ops(affinity, irq);
...
}
As a result, pmu-p skips calling request_percpu_irq_affinity() and never
registers its per-CPU irqaction on the shared PMU FIQ line. P-core PMU
counter overflow FIQs will be routed to pmu-e (leaving the P-core overflow
status and PMCR0_IACT uncleared when PMCR0_IMODE_FIQ is re-enabled), and
teardown in armpmu_free_irqs() will trigger a warning in __free_percpu_irq()
because pmu-p's dev_id was never registered.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261103-m3-plus-pmu-events-v1-0-a8eb6c1139fe@gmail.com?part=9
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 11/13] arm64: dts: apple: t604x: Add PMU Device Nodes
2026-11-03 10:14 ` [PATCH 11/13] arm64: dts: apple: t604x: " Myria Sarvay via B4 Relay
@ 2026-11-03 11:12 ` sashiko-bot
0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-11-03 11:12 UTC (permalink / raw)
To: Myria Sarvay; +Cc: linux-perf-users, devicetree, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] arm64: dts: apple: t6041: 4-cell PMU interrupts with 3-cell aic parent
--
commit d0216cee20998d9364fd46a4827e945211d4e88a
Author: Myria Sarvay <myrialsarvay@gmail.com>
arm64: dts: apple: t604x: Add PMU Device Nodes
This commit adds the pmu-e and pmu-p device tree nodes for the Apple M4
Pro/Max (t6041) SoC.
> diff --git a/arch/arm64/boot/dts/apple/t6041.dtsi b/arch/arm64/boot/dts/apple/t6041.dtsi
> index 9110d05c896da..2c72972d12192 100644
> --- a/arch/arm64/boot/dts/apple/t6041.dtsi
> +++ b/arch/arm64/boot/dts/apple/t6041.dtsi
> @@ -314,6 +314,18 @@ l2_cache_2: l2-cache-2 {
> };
> };
>
> + pmu-e {
> + compatible = "apple,brava-e-pmu";
> + interrupt-parent = <&aic>;
> + interrupts = <AIC_FIQ 0 AIC_CPU_PMU_E IRQ_TYPE_LEVEL_HIGH>;
> + };
> +
> + pmu-p {
> + compatible = "apple,brava-p-pmu";
> + interrupt-parent = <&aic>;
> + interrupts = <AIC_FIQ 0 AIC_CPU_PMU_P IRQ_TYPE_LEVEL_HIGH>;
> + };
[Severity: High]
Should the interrupts properties in pmu-e and pmu-p use 3 cells instead of 4?
In arch/arm64/boot/dts/apple/t6041.dtsi, the parent aic controller declares
3 interrupt cells:
aic: interrupt-controller@502400000 {
compatible = "apple,t6041-aic3", "apple,t8122-aic3";
...
#interrupt-cells = <3>;
When arm_pmu_device_probe() -> pmu_parse_irqs() ->
platform_get_irq_affinity() -> of_irq_parse_one() parses these 4-cell
specifiers against the 3-cell parent, only the first 3 cells are read into
fwspec->param[0..2] with fwspec->param_count = 3.
In drivers/irqchip/irq-apple-aic.c, both aic_irq_get_fwspec_info() and
aic_irq_domain_translate() then read param[1] (which is 0, matching
AIC_TMR_HV_PHYS) as the FIQ index and param[2] (AIC_CPU_PMU_E or
AIC_CPU_PMU_P) as the trigger type:
if (fwspec->param_count == 3)
intid = fwspec->param[1];
else
intid = fwspec->param[2];
and:
args = &fwspec->param[1];
if (fwspec->param_count == 4) {
die = args[0];
args++;
}
As a result, the PMU affinity masks at AIC_CPU_PMU_E and AIC_CPU_PMU_P are
missed, and interrupt translation or registration fails for both PMU nodes
(returning -ENOENT in EL1, or colliding with the hyp-phys timer FIQ / failing
aic_fiq_set_type() with -EINVAL in EL2). When platform_get_irq_affinity()
fails in pmu_parse_irqs(), it triggers WARN_ON(irq <= 0) and leaves
pmu->supported_cpus empty, causing armpmu_register() to pass nr_cpu_ids to
topology_core_has_smt() and read past the end of cpu_topology[].
Should these be:
interrupts = <AIC_FIQ AIC_CPU_PMU_E IRQ_TYPE_LEVEL_HIGH>;
and:
interrupts = <AIC_FIQ AIC_CPU_PMU_P IRQ_TYPE_LEVEL_HIGH>;
matching the timer node in t6041.dtsi and the PMU nodes in t8132.dtsi and
t8140.dtsi?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261103-m3-plus-pmu-events-v1-0-a8eb6c1139fe@gmail.com?part=11
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 13/13] arm64: dts: apple: t8140: Add PMU Device Nodes
2026-11-03 10:14 ` [PATCH 13/13] arm64: dts: apple: t8140: " Myria Sarvay via B4 Relay
@ 2026-11-03 11:23 ` sashiko-bot
0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-11-03 11:23 UTC (permalink / raw)
To: Myria Sarvay; +Cc: linux-perf-users, devicetree, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] arm64: dts: apple: t8140: missing aic affinities node for pmu-e and pmu-p
--
commit 4dff2446440e6919eaaded721e0e1ce1b3461270
Author: Myria Sarvay <myrialsarvay@gmail.com>
arm64: dts: apple: t8140: Add PMU Device Nodes
This commit adds the pmu-e and pmu-p device nodes for the efficiency and
performance core PMUs to the Apple t8140 device tree.
> diff --git a/arch/arm64/boot/dts/apple/t8140.dtsi b/arch/arm64/boot/dts/apple/t8140.dtsi
> index 150d91bdf6fcc..6e6fd5754406b 100644
> --- a/arch/arm64/boot/dts/apple/t8140.dtsi
> +++ b/arch/arm64/boot/dts/apple/t8140.dtsi
> @@ -136,6 +136,18 @@ l2_cache_1: l2-cache-1 {
> };
> };
>
> + pmu-e {
> + compatible = "apple,tahiti-e-pmu";
> + interrupt-parent = <&aic>;
> + interrupts = <AIC_FIQ AIC_CPU_PMU_E IRQ_TYPE_LEVEL_HIGH>;
> + };
> +
> + pmu-p {
> + compatible = "apple,tahiti-p-pmu";
> + interrupt-parent = <&aic>;
> + interrupts = <AIC_FIQ AIC_CPU_PMU_P IRQ_TYPE_LEVEL_HIGH>;
> + };
[Severity: High]
Does adding pmu-e and pmu-p also require an affinities child node under the
aic interrupt controller in arch/arm64/boot/dts/apple/t8140.dtsi (matching
t8122.dtsi and t8132.dtsi)?
Currently, the aic node in t8140.dtsi does not define an affinities subnode:
aic: interrupt-controller@301000000 {
compatible = "apple,t8140-aic3", "apple,t8122-aic3";
reg = <0x3 0x01000000 0x0 0x1cc000>,
<0x3 0x01040000 0x0 0x4000>;
reg-names = "core", "event";
#interrupt-cells = <3>;
interrupt-controller;
power-domains = <&ps_aic>;
};
Without the affinities node, aic_of_ic_init() in
drivers/irqchip/irq-apple-aic.c leaves aic_irqc->fiq_aff[AIC_CPU_PMU_E] and
aic_irqc->fiq_aff[AIC_CPU_PMU_P] as NULL. When arm_pmu_device_probe() ->
pmu_parse_irqs() -> platform_get_irq_affinity() queries the interrupt
affinity, aic_irq_get_fwspec_info() falls back to cpu_possible_mask for both
PMUs:
if (aic_irqc->fiq_aff[intid])
mask = &aic_irqc->fiq_aff[intid]->aff;
else
mask = cpu_possible_mask;
This causes pmu_parse_percpu_irq() to populate pmu->supported_cpus with all
CPUs (both E-cores and P-cores) on both PMU instances, breaking heterogeneous
CPU filtering in armpmu_filter() and armpmu_event_init().
In addition, because aic_irq_domain_translate() merges AIC_CPU_PMU_E onto
AIC_CPU_PMU_P so both PMUs share the same Linux virq, the second PMU to probe
sees armpmu_count_irq_users(affinity, irq) != 0 in armpmu_request_irq()
(drivers/perf/arm_pmu.c) and skips registering its per-CPU interrupt handler:
} else if (armpmu_count_irq_users(affinity, irq) == 0) {
err = request_percpu_nmi(irq, handler, "arm-pmu", affinity, pcpu_armpmu);
/* If cannot get an NMI, get a normal interrupt */
if (err) {
err = request_percpu_irq_affinity(irq, handler, "arm-pmu",
affinity, pcpu_armpmu);
irq_ops = &percpu_pmuirq_ops;
} else {
has_nmi = true;
irq_ops = &percpu_pmunmi_ops;
}
} else {
/* Per cpudevid irq was already requested by another CPU */
irq_ops = armpmu_find_irq_ops(affinity, irq);
When a P-core PMU counter overflow FIQ fires, handle_percpu_devid_irq()
dispatches it to pmu-e's handler instead of pmu-p's, leaving the P-core
counter unhandled and triggering an FIQ storm.
Should the aic node in t8140.dtsi include an affinities subnode mapping
AIC_CPU_PMU_E to <&cpu_e0>, <&cpu_e1>, <&cpu_e2>, <&cpu_e3> and AIC_CPU_PMU_P
to <&cpu_p0>, <&cpu_p1>?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261103-m3-plus-pmu-events-v1-0-a8eb6c1139fe@gmail.com?part=13
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-11-03 11:23 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-03 10:14 [PATCH 00/13] drivers/perf: apple_m1: Add M3/M4/A18 Pro Support Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 01/13] dt-bindings: arm: pmu: Add Apple M3/M4/A18 Pro SoC CPU PMU compatibles Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 02/13] drivers/perf: apple_m1: Remove unused variables Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 03/13] drivers/perf: apple_m1: Support per-implementation event tables Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 04/13] drivers/perf: apple_m1: Support per-implementation event size Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 05/13] drivers/perf: apple_m1: Use macros for per-implementation init functions Myria Sarvay via B4 Relay
2026-11-03 10:31 ` sashiko-bot
2026-11-03 10:14 ` [PATCH 06/13] drivers/perf: apple_m1: Add Apple M3 Series Support Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 07/13] drivers/perf: apple_m1: Add Apple M4 " Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 08/13] drivers/perf: apple_m1: Add Apple A18 Support Myria Sarvay via B4 Relay
2026-11-03 10:47 ` sashiko-bot
2026-11-03 10:14 ` [PATCH 09/13] arm64: dts: apple: t603x: Add PMU Device Nodes Myria Sarvay via B4 Relay
2026-11-03 10:54 ` sashiko-bot
2026-11-03 10:14 ` [PATCH 10/13] arm64: dts: apple: t8122: " Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 11/13] arm64: dts: apple: t604x: " Myria Sarvay via B4 Relay
2026-11-03 11:12 ` sashiko-bot
2026-11-03 10:14 ` [PATCH 12/13] arm64: dts: apple: t8132: " Myria Sarvay via B4 Relay
2026-11-03 10:14 ` [PATCH 13/13] arm64: dts: apple: t8140: " Myria Sarvay via B4 Relay
2026-11-03 11:23 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox