From f1525664ff9da3241b3556594dc0b67506ae1ddd Mon Sep 17 00:00:00 2001 From: Dhananjay Ugwekar Date: Tue, 10 Sep 2024 14:25:05 +0530 Subject: perf/x86/rapl: Fix the energy-pkg event for AMD CPUs After commit ("x86/cpu/topology: Add support for the AMD 0x80000026 leaf"), on AMD processors that support extended CPUID leaf 0x80000026, the topology_die_cpumask() and topology_logical_die_id() macros, no longer return the package cpumask and package id, instead they return the CCD (Core Complex Die) mask and id respectively. This leads to the energy-pkg event scope to be modified to CCD instead of package. So, change the PMU scope for AMD and Hygon back to package. On a 12 CCD 1 Package AMD Zen4 Genoa machine: Before: $ cat /sys/devices/power/cpumask 0,8,16,24,32,40,48,56,64,72,80,88. The expected cpumask here is supposed to be just "0", as it is a package scope event, only one CPU will be collecting the event for all the CPUs in the package. After: $ cat /sys/devices/power/cpumask 0 Signed-off-by: Dhananjay Ugwekar --- arch/x86/events/rapl.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) --- a/arch/x86/events/rapl.c +++ b/arch/x86/events/rapl.c @@ -139,9 +139,32 @@ static unsigned int rapl_cntr_mask; static u64 rapl_timer_ms; static struct perf_msr *rapl_msrs; +/* + * RAPL Package energy counter scope: + * 1. AMD/HYGON platforms have a per-PKG package energy counter + * 2. For Intel platforms + * 2.1. CLX-AP is multi-die and its RAPL MSRs are die-scope + * 2.2. Other Intel platforms are single die systems so the scope can be + * considered as either pkg-scope or die-scope, and we are considering + * them as die-scope. + */ +#define rapl_pmu_is_pkg_scope() \ + (boot_cpu_data.x86_vendor == X86_VENDOR_AMD || \ + boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) + +/* + * Helper function to get the correct topology id according to the + * RAPL PMU scope. + */ +static inline unsigned int get_rapl_pmu_idx(int cpu) +{ + return rapl_pmu_is_pkg_scope() ? topology_logical_package_id(cpu) : + topology_logical_die_id(cpu); +} + static inline struct rapl_pmu *cpu_to_rapl_pmu(unsigned int cpu) { - unsigned int rapl_pmu_idx = topology_logical_die_id(cpu); + unsigned int rapl_pmu_idx = get_rapl_pmu_idx(cpu); /* * The unsigned check also catches the '-1' return value for non @@ -617,7 +640,7 @@ static void __init init_rapl_pmu(void) pmu->timer_interval = ms_to_ktime(rapl_timer_ms); rapl_hrtimer_init(pmu); - rapl_pmus->pmus[topology_logical_die_id(cpu)] = pmu; + rapl_pmus->pmus[get_rapl_pmu_idx(cpu)] = pmu; } cpus_read_unlock(); @@ -626,6 +649,12 @@ static void __init init_rapl_pmu(void) static int __init init_rapl_pmus(void) { int nr_rapl_pmu = topology_max_packages() * topology_max_dies_per_package(); + int rapl_pmu_scope = PERF_PMU_SCOPE_DIE; + + if (rapl_pmu_is_pkg_scope()) { + nr_rapl_pmu = topology_max_packages(); + rapl_pmu_scope = PERF_PMU_SCOPE_PKG; + } rapl_pmus = kzalloc(struct_size(rapl_pmus, pmus, nr_rapl_pmu), GFP_KERNEL); if (!rapl_pmus) @@ -641,8 +670,8 @@ static int __init init_rapl_pmus(void) rapl_pmus->pmu.start = rapl_pmu_event_start; rapl_pmus->pmu.stop = rapl_pmu_event_stop; rapl_pmus->pmu.read = rapl_pmu_event_read; + rapl_pmus->pmu.scope = rapl_pmu_scope; rapl_pmus->pmu.module = THIS_MODULE; - rapl_pmus->pmu.scope = PERF_PMU_SCOPE_DIE; rapl_pmus->pmu.capabilities = PERF_PMU_CAP_NO_EXCLUDE; init_rapl_pmu();