Commit 47a973fd authored by Kan Liang's avatar Kan Liang Committed by Peter Zijlstra
Browse files

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: eb467aaa ("perf/x86/intel: Support Architectural PerfMon Extension leaf")
Signed-off-by: default avatarKan Liang <kan.liang@linux.intel.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/20250129154820.3755948-3-kan.liang@linux.intel.com
parent 0a556150
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -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()) {
+25 −3
Original line number Diff line number Diff line
@@ -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:
 */