]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
perf/x86/intel: Fix ARCH_PERFMON_NUM_COUNTER_LEAF
authorKan Liang <kan.liang@linux.intel.com>
Wed, 29 Jan 2025 15:48:19 +0000 (07:48 -0800)
committerPeter Zijlstra <peterz@infradead.org>
Sat, 8 Feb 2025 14:47:25 +0000 (15:47 +0100)
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
arch/x86/events/intel/core.c
arch/x86/include/asm/perf_event.h

index 966f7832497decc2ab0951183bd54a0f82385191..f3d5b718f93f3ea3c9c6a4a0428d2bd8e57e364b 100644 (file)
@@ -4905,20 +4905,22 @@ static inline bool intel_pmu_broken_perf_cap(void)
 
 static void update_pmu_cap(struct x86_hybrid_pmu *pmu)
 {
-       unsigned int sub_bitmaps, eax, ebx, ecx, edx;
+       unsigned int cntr, fixed_cntr, ecx, edx;
+       union cpuid35_eax eax;
+       union cpuid35_ebx ebx;
 
-       cpuid(ARCH_PERFMON_EXT_LEAF, &sub_bitmaps, &ebx, &ecx, &edx);
+       cpuid(ARCH_PERFMON_EXT_LEAF, &eax.full, &ebx.full, &ecx, &edx);
 
-       if (ebx & ARCH_PERFMON_EXT_UMASK2)
+       if (ebx.split.umask2)
                pmu->config_mask |= ARCH_PERFMON_EVENTSEL_UMASK2;
-       if (ebx & ARCH_PERFMON_EXT_EQ)
+       if (ebx.split.eq)
                pmu->config_mask |= ARCH_PERFMON_EVENTSEL_EQ;
 
-       if (sub_bitmaps & ARCH_PERFMON_NUM_COUNTER_LEAF_BIT) {
+       if (eax.split.cntr_subleaf) {
                cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_NUM_COUNTER_LEAF,
-                           &eax, &ebx, &ecx, &edx);
-               pmu->cntr_mask64 = eax;
-               pmu->fixed_cntr_mask64 = ebx;
+                           &cntr, &fixed_cntr, &ecx, &edx);
+               pmu->cntr_mask64 = cntr;
+               pmu->fixed_cntr_mask64 = fixed_cntr;
        }
 
        if (!intel_pmu_broken_perf_cap()) {
index 1ac79f361645648417a0b200e35cc2c1c5074fb2..0ba8d20f2d1d5689701fd44f1a864640e77fbc23 100644 (file)
@@ -188,11 +188,33 @@ union cpuid10_edx {
  * detection/enumeration details:
  */
 #define ARCH_PERFMON_EXT_LEAF                  0x00000023
-#define ARCH_PERFMON_EXT_UMASK2                        0x1
-#define ARCH_PERFMON_EXT_EQ                    0x2
-#define ARCH_PERFMON_NUM_COUNTER_LEAF_BIT      0x1
 #define ARCH_PERFMON_NUM_COUNTER_LEAF          0x1
 
+union cpuid35_eax {
+       struct {
+               unsigned int    leaf0:1;
+               /* Counters Sub-Leaf */
+               unsigned int    cntr_subleaf:1;
+               /* Auto Counter Reload Sub-Leaf */
+               unsigned int    acr_subleaf:1;
+               /* Events Sub-Leaf */
+               unsigned int    events_subleaf:1;
+               unsigned int    reserved:28;
+       } split;
+       unsigned int            full;
+};
+
+union cpuid35_ebx {
+       struct {
+               /* UnitMask2 Supported */
+               unsigned int    umask2:1;
+               /* EQ-bit Supported */
+               unsigned int    eq:1;
+               unsigned int    reserved:30;
+       } split;
+       unsigned int            full;
+};
+
 /*
  * Intel Architectural LBR CPUID detection/enumeration details:
  */