[PATCH 13/15] perf/x86: Validate event type before topdown/mem-loads classification

From: Dapeng Mi

Date: Mon Sep 28 2026 - 03:55:55 EST


Software events can be grouped with x86 PMU events. While iterating an
x86 event group, a non-x86 event may be misclassified as a SLOTS,
topdown metric or mem-loads{,-aux} events if its config bits happen to
match the x86 masks.

Require is_x86_event() before classifying SLOTS, topdown metric or
mem-loads{,-aux} events to avoid false matches on software events.

Fixes: 7b2c05a15d29 ("perf/x86/intel: Generic support for hardware TopDown metrics")
Fixes: 61b985e3e775 ("perf/x86/intel: Add perf core PMU support for Sapphire Rapids")
Signed-off-by: Dapeng Mi <dapeng1.mi@xxxxxxxxxxxxxxx>
---
arch/x86/events/intel/core.c | 8 ++++++--
arch/x86/events/perf_event.h | 14 ++++++++------
2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 0d360fba4b79..6cc1462c9c82 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -4809,12 +4809,16 @@ static bool is_available_metric_event(struct perf_event *event)

static inline bool is_mem_loads_event(struct perf_event *event)
{
- return (event->attr.config & INTEL_ARCH_EVENT_MASK) == X86_CONFIG(.event=0xcd, .umask=0x01);
+ return is_x86_event(event) &&
+ ((event->attr.config & INTEL_ARCH_EVENT_MASK) ==
+ X86_CONFIG(.event = 0xcd, .umask = 0x01));
}

static inline bool is_mem_loads_aux_event(struct perf_event *event)
{
- return (event->attr.config & INTEL_ARCH_EVENT_MASK) == X86_CONFIG(.event=0x03, .umask=0x82);
+ return is_x86_event(event) &&
+ ((event->attr.config & INTEL_ARCH_EVENT_MASK) ==
+ X86_CONFIG(.event = 0x03, .umask = 0x82));
}

static inline bool require_mem_loads_aux_event(struct perf_event *event)
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index e274802ef062..55f9684152c9 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -96,18 +96,22 @@ static inline bool is_topdown_count(struct perf_event *event)
return event->hw.flags & PERF_X86_EVENT_TOPDOWN;
}

+int is_x86_event(struct perf_event *event);
+
static inline bool is_metric_event(struct perf_event *event)
{
u64 config = event->attr.config;

- return ((config & ARCH_PERFMON_EVENTSEL_EVENT) == 0) &&
- ((config & INTEL_ARCH_EVENT_MASK) >= INTEL_TD_METRIC_RETIRING) &&
- ((config & INTEL_ARCH_EVENT_MASK) <= INTEL_TD_METRIC_MAX);
+ return is_x86_event(event) &&
+ ((config & ARCH_PERFMON_EVENTSEL_EVENT) == 0) &&
+ ((config & INTEL_ARCH_EVENT_MASK) >= INTEL_TD_METRIC_RETIRING) &&
+ ((config & INTEL_ARCH_EVENT_MASK) <= INTEL_TD_METRIC_MAX);
}

static inline bool is_slots_event(struct perf_event *event)
{
- return (event->attr.config & INTEL_ARCH_EVENT_MASK) == INTEL_TD_SLOTS;
+ return is_x86_event(event) &&
+ (event->attr.config & INTEL_ARCH_EVENT_MASK) == INTEL_TD_SLOTS;
}

static inline bool is_topdown_event(struct perf_event *event)
@@ -115,8 +119,6 @@ static inline bool is_topdown_event(struct perf_event *event)
return is_metric_event(event) || is_slots_event(event);
}

-int is_x86_event(struct perf_event *event);
-
static inline bool check_leader_group(struct perf_event *leader, int flags)
{
return is_x86_event(leader) ? !!(leader->hw.flags & flags) : false;
--
2.34.1