perf/x86/intel: Fix ARCH_PERFMON_NUM_COUNTER_LEAF

The EAX of the CPUID Leaf 023H enumerates the mask of valid sub-leaves.
To tell the availability of the sub-leaf 1 (enumerate the counter mask),
perf should check the bit 1 (0x2) of EAS, rather than bit 0 (0x1).

The error is not user-visible on bare metal. Because the sub-leaf 0 and
the sub-leaf 1 are always available. However, it may bring issues in a
virtualization environment when a VMM only enumerates the sub-leaf 0.

Introduce the cpuid35_e?x to replace the macros, which makes the
implementation style consistent.

Fixes: eb467aaac21e ("perf/x86/intel: Support Architectural PerfMon Extension leaf")
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/20250129154820.3755948-3-kan.liang@linux.intel.com

authored by

Kan Liang and committed by
Peter Zijlstra
47a973fd 0a556150

+35 -11
+10 -8
arch/x86/events/intel/core.c
··· 4905 4905 4906 4906 static void update_pmu_cap(struct x86_hybrid_pmu *pmu) 4907 4907 { 4908 - unsigned int sub_bitmaps, eax, ebx, ecx, edx; 4908 + unsigned int cntr, fixed_cntr, ecx, edx; 4909 + union cpuid35_eax eax; 4910 + union cpuid35_ebx ebx; 4909 4911 4910 - cpuid(ARCH_PERFMON_EXT_LEAF, &sub_bitmaps, &ebx, &ecx, &edx); 4912 + cpuid(ARCH_PERFMON_EXT_LEAF, &eax.full, &ebx.full, &ecx, &edx); 4911 4913 4912 - if (ebx & ARCH_PERFMON_EXT_UMASK2) 4914 + if (ebx.split.umask2) 4913 4915 pmu->config_mask |= ARCH_PERFMON_EVENTSEL_UMASK2; 4914 - if (ebx & ARCH_PERFMON_EXT_EQ) 4916 + if (ebx.split.eq) 4915 4917 pmu->config_mask |= ARCH_PERFMON_EVENTSEL_EQ; 4916 4918 4917 - if (sub_bitmaps & ARCH_PERFMON_NUM_COUNTER_LEAF_BIT) { 4919 + if (eax.split.cntr_subleaf) { 4918 4920 cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_NUM_COUNTER_LEAF, 4919 - &eax, &ebx, &ecx, &edx); 4920 - pmu->cntr_mask64 = eax; 4921 - pmu->fixed_cntr_mask64 = ebx; 4921 + &cntr, &fixed_cntr, &ecx, &edx); 4922 + pmu->cntr_mask64 = cntr; 4923 + pmu->fixed_cntr_mask64 = fixed_cntr; 4922 4924 } 4923 4925 4924 4926 if (!intel_pmu_broken_perf_cap()) {
+25 -3
arch/x86/include/asm/perf_event.h
··· 188 188 * detection/enumeration details: 189 189 */ 190 190 #define ARCH_PERFMON_EXT_LEAF 0x00000023 191 - #define ARCH_PERFMON_EXT_UMASK2 0x1 192 - #define ARCH_PERFMON_EXT_EQ 0x2 193 - #define ARCH_PERFMON_NUM_COUNTER_LEAF_BIT 0x1 194 191 #define ARCH_PERFMON_NUM_COUNTER_LEAF 0x1 192 + 193 + union cpuid35_eax { 194 + struct { 195 + unsigned int leaf0:1; 196 + /* Counters Sub-Leaf */ 197 + unsigned int cntr_subleaf:1; 198 + /* Auto Counter Reload Sub-Leaf */ 199 + unsigned int acr_subleaf:1; 200 + /* Events Sub-Leaf */ 201 + unsigned int events_subleaf:1; 202 + unsigned int reserved:28; 203 + } split; 204 + unsigned int full; 205 + }; 206 + 207 + union cpuid35_ebx { 208 + struct { 209 + /* UnitMask2 Supported */ 210 + unsigned int umask2:1; 211 + /* EQ-bit Supported */ 212 + unsigned int eq:1; 213 + unsigned int reserved:30; 214 + } split; 215 + unsigned int full; 216 + }; 195 217 196 218 /* 197 219 * Intel Architectural LBR CPUID detection/enumeration details: