162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Support cstate residency counters 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2015, Intel Corp. 562306a36Sopenharmony_ci * Author: Kan Liang (kan.liang@intel.com) 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This library is free software; you can redistribute it and/or 862306a36Sopenharmony_ci * modify it under the terms of the GNU Library General Public 962306a36Sopenharmony_ci * License as published by the Free Software Foundation; either 1062306a36Sopenharmony_ci * version 2 of the License, or (at your option) any later version. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * This library is distributed in the hope that it will be useful, 1362306a36Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 1462306a36Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1562306a36Sopenharmony_ci * Library General Public License for more details. 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* 2062306a36Sopenharmony_ci * This file export cstate related free running (read-only) counters 2162306a36Sopenharmony_ci * for perf. These counters may be use simultaneously by other tools, 2262306a36Sopenharmony_ci * such as turbostat. However, it still make sense to implement them 2362306a36Sopenharmony_ci * in perf. Because we can conveniently collect them together with 2462306a36Sopenharmony_ci * other events, and allow to use them from tools without special MSR 2562306a36Sopenharmony_ci * access code. 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * The events only support system-wide mode counting. There is no 2862306a36Sopenharmony_ci * sampling support because it is not supported by the hardware. 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * According to counters' scope and category, two PMUs are registered 3162306a36Sopenharmony_ci * with the perf_event core subsystem. 3262306a36Sopenharmony_ci * - 'cstate_core': The counter is available for each physical core. 3362306a36Sopenharmony_ci * The counters include CORE_C*_RESIDENCY. 3462306a36Sopenharmony_ci * - 'cstate_pkg': The counter is available for each physical package. 3562306a36Sopenharmony_ci * The counters include PKG_C*_RESIDENCY. 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * All of these counters are specified in the Intel® 64 and IA-32 3862306a36Sopenharmony_ci * Architectures Software Developer.s Manual Vol3b. 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci * Model specific counters: 4162306a36Sopenharmony_ci * MSR_CORE_C1_RES: CORE C1 Residency Counter 4262306a36Sopenharmony_ci * perf code: 0x00 4362306a36Sopenharmony_ci * Available model: SLM,AMT,GLM,CNL,ICX,TNT,ADL,RPL 4462306a36Sopenharmony_ci * MTL 4562306a36Sopenharmony_ci * Scope: Core (each processor core has a MSR) 4662306a36Sopenharmony_ci * MSR_CORE_C3_RESIDENCY: CORE C3 Residency Counter 4762306a36Sopenharmony_ci * perf code: 0x01 4862306a36Sopenharmony_ci * Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,GLM, 4962306a36Sopenharmony_ci * CNL,KBL,CML,TNT 5062306a36Sopenharmony_ci * Scope: Core 5162306a36Sopenharmony_ci * MSR_CORE_C6_RESIDENCY: CORE C6 Residency Counter 5262306a36Sopenharmony_ci * perf code: 0x02 5362306a36Sopenharmony_ci * Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW, 5462306a36Sopenharmony_ci * SKL,KNL,GLM,CNL,KBL,CML,ICL,ICX, 5562306a36Sopenharmony_ci * TGL,TNT,RKL,ADL,RPL,SPR,MTL 5662306a36Sopenharmony_ci * Scope: Core 5762306a36Sopenharmony_ci * MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter 5862306a36Sopenharmony_ci * perf code: 0x03 5962306a36Sopenharmony_ci * Available model: SNB,IVB,HSW,BDW,SKL,CNL,KBL,CML, 6062306a36Sopenharmony_ci * ICL,TGL,RKL,ADL,RPL,MTL 6162306a36Sopenharmony_ci * Scope: Core 6262306a36Sopenharmony_ci * MSR_PKG_C2_RESIDENCY: Package C2 Residency Counter. 6362306a36Sopenharmony_ci * perf code: 0x00 6462306a36Sopenharmony_ci * Available model: SNB,IVB,HSW,BDW,SKL,KNL,GLM,CNL, 6562306a36Sopenharmony_ci * KBL,CML,ICL,ICX,TGL,TNT,RKL,ADL, 6662306a36Sopenharmony_ci * RPL,SPR,MTL 6762306a36Sopenharmony_ci * Scope: Package (physical package) 6862306a36Sopenharmony_ci * MSR_PKG_C3_RESIDENCY: Package C3 Residency Counter. 6962306a36Sopenharmony_ci * perf code: 0x01 7062306a36Sopenharmony_ci * Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,KNL, 7162306a36Sopenharmony_ci * GLM,CNL,KBL,CML,ICL,TGL,TNT,RKL, 7262306a36Sopenharmony_ci * ADL,RPL,MTL 7362306a36Sopenharmony_ci * Scope: Package (physical package) 7462306a36Sopenharmony_ci * MSR_PKG_C6_RESIDENCY: Package C6 Residency Counter. 7562306a36Sopenharmony_ci * perf code: 0x02 7662306a36Sopenharmony_ci * Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW, 7762306a36Sopenharmony_ci * SKL,KNL,GLM,CNL,KBL,CML,ICL,ICX, 7862306a36Sopenharmony_ci * TGL,TNT,RKL,ADL,RPL,SPR,MTL 7962306a36Sopenharmony_ci * Scope: Package (physical package) 8062306a36Sopenharmony_ci * MSR_PKG_C7_RESIDENCY: Package C7 Residency Counter. 8162306a36Sopenharmony_ci * perf code: 0x03 8262306a36Sopenharmony_ci * Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,CNL, 8362306a36Sopenharmony_ci * KBL,CML,ICL,TGL,RKL,ADL,RPL,MTL 8462306a36Sopenharmony_ci * Scope: Package (physical package) 8562306a36Sopenharmony_ci * MSR_PKG_C8_RESIDENCY: Package C8 Residency Counter. 8662306a36Sopenharmony_ci * perf code: 0x04 8762306a36Sopenharmony_ci * Available model: HSW ULT,KBL,CNL,CML,ICL,TGL,RKL, 8862306a36Sopenharmony_ci * ADL,RPL,MTL 8962306a36Sopenharmony_ci * Scope: Package (physical package) 9062306a36Sopenharmony_ci * MSR_PKG_C9_RESIDENCY: Package C9 Residency Counter. 9162306a36Sopenharmony_ci * perf code: 0x05 9262306a36Sopenharmony_ci * Available model: HSW ULT,KBL,CNL,CML,ICL,TGL,RKL, 9362306a36Sopenharmony_ci * ADL,RPL,MTL 9462306a36Sopenharmony_ci * Scope: Package (physical package) 9562306a36Sopenharmony_ci * MSR_PKG_C10_RESIDENCY: Package C10 Residency Counter. 9662306a36Sopenharmony_ci * perf code: 0x06 9762306a36Sopenharmony_ci * Available model: HSW ULT,KBL,GLM,CNL,CML,ICL,TGL, 9862306a36Sopenharmony_ci * TNT,RKL,ADL,RPL,MTL 9962306a36Sopenharmony_ci * Scope: Package (physical package) 10062306a36Sopenharmony_ci * 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci#include <linux/module.h> 10462306a36Sopenharmony_ci#include <linux/slab.h> 10562306a36Sopenharmony_ci#include <linux/perf_event.h> 10662306a36Sopenharmony_ci#include <linux/nospec.h> 10762306a36Sopenharmony_ci#include <asm/cpu_device_id.h> 10862306a36Sopenharmony_ci#include <asm/intel-family.h> 10962306a36Sopenharmony_ci#include "../perf_event.h" 11062306a36Sopenharmony_ci#include "../probe.h" 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci#define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format) \ 11562306a36Sopenharmony_cistatic ssize_t __cstate_##_var##_show(struct device *dev, \ 11662306a36Sopenharmony_ci struct device_attribute *attr, \ 11762306a36Sopenharmony_ci char *page) \ 11862306a36Sopenharmony_ci{ \ 11962306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ 12062306a36Sopenharmony_ci return sprintf(page, _format "\n"); \ 12162306a36Sopenharmony_ci} \ 12262306a36Sopenharmony_cistatic struct device_attribute format_attr_##_var = \ 12362306a36Sopenharmony_ci __ATTR(_name, 0444, __cstate_##_var##_show, NULL) 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic ssize_t cstate_get_attr_cpumask(struct device *dev, 12662306a36Sopenharmony_ci struct device_attribute *attr, 12762306a36Sopenharmony_ci char *buf); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/* Model -> events mapping */ 13062306a36Sopenharmony_cistruct cstate_model { 13162306a36Sopenharmony_ci unsigned long core_events; 13262306a36Sopenharmony_ci unsigned long pkg_events; 13362306a36Sopenharmony_ci unsigned long quirks; 13462306a36Sopenharmony_ci}; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci/* Quirk flags */ 13762306a36Sopenharmony_ci#define SLM_PKG_C6_USE_C7_MSR (1UL << 0) 13862306a36Sopenharmony_ci#define KNL_CORE_C6_MSR (1UL << 1) 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistruct perf_cstate_msr { 14162306a36Sopenharmony_ci u64 msr; 14262306a36Sopenharmony_ci struct perf_pmu_events_attr *attr; 14362306a36Sopenharmony_ci}; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci/* cstate_core PMU */ 14762306a36Sopenharmony_cistatic struct pmu cstate_core_pmu; 14862306a36Sopenharmony_cistatic bool has_cstate_core; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cienum perf_cstate_core_events { 15162306a36Sopenharmony_ci PERF_CSTATE_CORE_C1_RES = 0, 15262306a36Sopenharmony_ci PERF_CSTATE_CORE_C3_RES, 15362306a36Sopenharmony_ci PERF_CSTATE_CORE_C6_RES, 15462306a36Sopenharmony_ci PERF_CSTATE_CORE_C7_RES, 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci PERF_CSTATE_CORE_EVENT_MAX, 15762306a36Sopenharmony_ci}; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ciPMU_EVENT_ATTR_STRING(c1-residency, attr_cstate_core_c1, "event=0x00"); 16062306a36Sopenharmony_ciPMU_EVENT_ATTR_STRING(c3-residency, attr_cstate_core_c3, "event=0x01"); 16162306a36Sopenharmony_ciPMU_EVENT_ATTR_STRING(c6-residency, attr_cstate_core_c6, "event=0x02"); 16262306a36Sopenharmony_ciPMU_EVENT_ATTR_STRING(c7-residency, attr_cstate_core_c7, "event=0x03"); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic unsigned long core_msr_mask; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_core_c1); 16762306a36Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_core_c3); 16862306a36Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_core_c6); 16962306a36Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_core_c7); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cistatic bool test_msr(int idx, void *data) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci return test_bit(idx, (unsigned long *) data); 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic struct perf_msr core_msr[] = { 17762306a36Sopenharmony_ci [PERF_CSTATE_CORE_C1_RES] = { MSR_CORE_C1_RES, &group_cstate_core_c1, test_msr }, 17862306a36Sopenharmony_ci [PERF_CSTATE_CORE_C3_RES] = { MSR_CORE_C3_RESIDENCY, &group_cstate_core_c3, test_msr }, 17962306a36Sopenharmony_ci [PERF_CSTATE_CORE_C6_RES] = { MSR_CORE_C6_RESIDENCY, &group_cstate_core_c6, test_msr }, 18062306a36Sopenharmony_ci [PERF_CSTATE_CORE_C7_RES] = { MSR_CORE_C7_RESIDENCY, &group_cstate_core_c7, test_msr }, 18162306a36Sopenharmony_ci}; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic struct attribute *attrs_empty[] = { 18462306a36Sopenharmony_ci NULL, 18562306a36Sopenharmony_ci}; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci/* 18862306a36Sopenharmony_ci * There are no default events, but we need to create 18962306a36Sopenharmony_ci * "events" group (with empty attrs) before updating 19062306a36Sopenharmony_ci * it with detected events. 19162306a36Sopenharmony_ci */ 19262306a36Sopenharmony_cistatic struct attribute_group core_events_attr_group = { 19362306a36Sopenharmony_ci .name = "events", 19462306a36Sopenharmony_ci .attrs = attrs_empty, 19562306a36Sopenharmony_ci}; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ciDEFINE_CSTATE_FORMAT_ATTR(core_event, event, "config:0-63"); 19862306a36Sopenharmony_cistatic struct attribute *core_format_attrs[] = { 19962306a36Sopenharmony_ci &format_attr_core_event.attr, 20062306a36Sopenharmony_ci NULL, 20162306a36Sopenharmony_ci}; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic struct attribute_group core_format_attr_group = { 20462306a36Sopenharmony_ci .name = "format", 20562306a36Sopenharmony_ci .attrs = core_format_attrs, 20662306a36Sopenharmony_ci}; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic cpumask_t cstate_core_cpu_mask; 20962306a36Sopenharmony_cistatic DEVICE_ATTR(cpumask, S_IRUGO, cstate_get_attr_cpumask, NULL); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic struct attribute *cstate_cpumask_attrs[] = { 21262306a36Sopenharmony_ci &dev_attr_cpumask.attr, 21362306a36Sopenharmony_ci NULL, 21462306a36Sopenharmony_ci}; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic struct attribute_group cpumask_attr_group = { 21762306a36Sopenharmony_ci .attrs = cstate_cpumask_attrs, 21862306a36Sopenharmony_ci}; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic const struct attribute_group *core_attr_groups[] = { 22162306a36Sopenharmony_ci &core_events_attr_group, 22262306a36Sopenharmony_ci &core_format_attr_group, 22362306a36Sopenharmony_ci &cpumask_attr_group, 22462306a36Sopenharmony_ci NULL, 22562306a36Sopenharmony_ci}; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci/* cstate_pkg PMU */ 22862306a36Sopenharmony_cistatic struct pmu cstate_pkg_pmu; 22962306a36Sopenharmony_cistatic bool has_cstate_pkg; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cienum perf_cstate_pkg_events { 23262306a36Sopenharmony_ci PERF_CSTATE_PKG_C2_RES = 0, 23362306a36Sopenharmony_ci PERF_CSTATE_PKG_C3_RES, 23462306a36Sopenharmony_ci PERF_CSTATE_PKG_C6_RES, 23562306a36Sopenharmony_ci PERF_CSTATE_PKG_C7_RES, 23662306a36Sopenharmony_ci PERF_CSTATE_PKG_C8_RES, 23762306a36Sopenharmony_ci PERF_CSTATE_PKG_C9_RES, 23862306a36Sopenharmony_ci PERF_CSTATE_PKG_C10_RES, 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci PERF_CSTATE_PKG_EVENT_MAX, 24162306a36Sopenharmony_ci}; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ciPMU_EVENT_ATTR_STRING(c2-residency, attr_cstate_pkg_c2, "event=0x00"); 24462306a36Sopenharmony_ciPMU_EVENT_ATTR_STRING(c3-residency, attr_cstate_pkg_c3, "event=0x01"); 24562306a36Sopenharmony_ciPMU_EVENT_ATTR_STRING(c6-residency, attr_cstate_pkg_c6, "event=0x02"); 24662306a36Sopenharmony_ciPMU_EVENT_ATTR_STRING(c7-residency, attr_cstate_pkg_c7, "event=0x03"); 24762306a36Sopenharmony_ciPMU_EVENT_ATTR_STRING(c8-residency, attr_cstate_pkg_c8, "event=0x04"); 24862306a36Sopenharmony_ciPMU_EVENT_ATTR_STRING(c9-residency, attr_cstate_pkg_c9, "event=0x05"); 24962306a36Sopenharmony_ciPMU_EVENT_ATTR_STRING(c10-residency, attr_cstate_pkg_c10, "event=0x06"); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic unsigned long pkg_msr_mask; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_pkg_c2); 25462306a36Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_pkg_c3); 25562306a36Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_pkg_c6); 25662306a36Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_pkg_c7); 25762306a36Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_pkg_c8); 25862306a36Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_pkg_c9); 25962306a36Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_pkg_c10); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic struct perf_msr pkg_msr[] = { 26262306a36Sopenharmony_ci [PERF_CSTATE_PKG_C2_RES] = { MSR_PKG_C2_RESIDENCY, &group_cstate_pkg_c2, test_msr }, 26362306a36Sopenharmony_ci [PERF_CSTATE_PKG_C3_RES] = { MSR_PKG_C3_RESIDENCY, &group_cstate_pkg_c3, test_msr }, 26462306a36Sopenharmony_ci [PERF_CSTATE_PKG_C6_RES] = { MSR_PKG_C6_RESIDENCY, &group_cstate_pkg_c6, test_msr }, 26562306a36Sopenharmony_ci [PERF_CSTATE_PKG_C7_RES] = { MSR_PKG_C7_RESIDENCY, &group_cstate_pkg_c7, test_msr }, 26662306a36Sopenharmony_ci [PERF_CSTATE_PKG_C8_RES] = { MSR_PKG_C8_RESIDENCY, &group_cstate_pkg_c8, test_msr }, 26762306a36Sopenharmony_ci [PERF_CSTATE_PKG_C9_RES] = { MSR_PKG_C9_RESIDENCY, &group_cstate_pkg_c9, test_msr }, 26862306a36Sopenharmony_ci [PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY, &group_cstate_pkg_c10, test_msr }, 26962306a36Sopenharmony_ci}; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cistatic struct attribute_group pkg_events_attr_group = { 27262306a36Sopenharmony_ci .name = "events", 27362306a36Sopenharmony_ci .attrs = attrs_empty, 27462306a36Sopenharmony_ci}; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ciDEFINE_CSTATE_FORMAT_ATTR(pkg_event, event, "config:0-63"); 27762306a36Sopenharmony_cistatic struct attribute *pkg_format_attrs[] = { 27862306a36Sopenharmony_ci &format_attr_pkg_event.attr, 27962306a36Sopenharmony_ci NULL, 28062306a36Sopenharmony_ci}; 28162306a36Sopenharmony_cistatic struct attribute_group pkg_format_attr_group = { 28262306a36Sopenharmony_ci .name = "format", 28362306a36Sopenharmony_ci .attrs = pkg_format_attrs, 28462306a36Sopenharmony_ci}; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_cistatic cpumask_t cstate_pkg_cpu_mask; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_cistatic const struct attribute_group *pkg_attr_groups[] = { 28962306a36Sopenharmony_ci &pkg_events_attr_group, 29062306a36Sopenharmony_ci &pkg_format_attr_group, 29162306a36Sopenharmony_ci &cpumask_attr_group, 29262306a36Sopenharmony_ci NULL, 29362306a36Sopenharmony_ci}; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic ssize_t cstate_get_attr_cpumask(struct device *dev, 29662306a36Sopenharmony_ci struct device_attribute *attr, 29762306a36Sopenharmony_ci char *buf) 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci struct pmu *pmu = dev_get_drvdata(dev); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci if (pmu == &cstate_core_pmu) 30262306a36Sopenharmony_ci return cpumap_print_to_pagebuf(true, buf, &cstate_core_cpu_mask); 30362306a36Sopenharmony_ci else if (pmu == &cstate_pkg_pmu) 30462306a36Sopenharmony_ci return cpumap_print_to_pagebuf(true, buf, &cstate_pkg_cpu_mask); 30562306a36Sopenharmony_ci else 30662306a36Sopenharmony_ci return 0; 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_cistatic int cstate_pmu_event_init(struct perf_event *event) 31062306a36Sopenharmony_ci{ 31162306a36Sopenharmony_ci u64 cfg = event->attr.config; 31262306a36Sopenharmony_ci int cpu; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci if (event->attr.type != event->pmu->type) 31562306a36Sopenharmony_ci return -ENOENT; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci /* unsupported modes and filters */ 31862306a36Sopenharmony_ci if (event->attr.sample_period) /* no sampling */ 31962306a36Sopenharmony_ci return -EINVAL; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci if (event->cpu < 0) 32262306a36Sopenharmony_ci return -EINVAL; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci if (event->pmu == &cstate_core_pmu) { 32562306a36Sopenharmony_ci if (cfg >= PERF_CSTATE_CORE_EVENT_MAX) 32662306a36Sopenharmony_ci return -EINVAL; 32762306a36Sopenharmony_ci cfg = array_index_nospec((unsigned long)cfg, PERF_CSTATE_CORE_EVENT_MAX); 32862306a36Sopenharmony_ci if (!(core_msr_mask & (1 << cfg))) 32962306a36Sopenharmony_ci return -EINVAL; 33062306a36Sopenharmony_ci event->hw.event_base = core_msr[cfg].msr; 33162306a36Sopenharmony_ci cpu = cpumask_any_and(&cstate_core_cpu_mask, 33262306a36Sopenharmony_ci topology_sibling_cpumask(event->cpu)); 33362306a36Sopenharmony_ci } else if (event->pmu == &cstate_pkg_pmu) { 33462306a36Sopenharmony_ci if (cfg >= PERF_CSTATE_PKG_EVENT_MAX) 33562306a36Sopenharmony_ci return -EINVAL; 33662306a36Sopenharmony_ci cfg = array_index_nospec((unsigned long)cfg, PERF_CSTATE_PKG_EVENT_MAX); 33762306a36Sopenharmony_ci if (!(pkg_msr_mask & (1 << cfg))) 33862306a36Sopenharmony_ci return -EINVAL; 33962306a36Sopenharmony_ci event->hw.event_base = pkg_msr[cfg].msr; 34062306a36Sopenharmony_ci cpu = cpumask_any_and(&cstate_pkg_cpu_mask, 34162306a36Sopenharmony_ci topology_die_cpumask(event->cpu)); 34262306a36Sopenharmony_ci } else { 34362306a36Sopenharmony_ci return -ENOENT; 34462306a36Sopenharmony_ci } 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci if (cpu >= nr_cpu_ids) 34762306a36Sopenharmony_ci return -ENODEV; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci event->cpu = cpu; 35062306a36Sopenharmony_ci event->hw.config = cfg; 35162306a36Sopenharmony_ci event->hw.idx = -1; 35262306a36Sopenharmony_ci return 0; 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic inline u64 cstate_pmu_read_counter(struct perf_event *event) 35662306a36Sopenharmony_ci{ 35762306a36Sopenharmony_ci u64 val; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci rdmsrl(event->hw.event_base, val); 36062306a36Sopenharmony_ci return val; 36162306a36Sopenharmony_ci} 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_cistatic void cstate_pmu_event_update(struct perf_event *event) 36462306a36Sopenharmony_ci{ 36562306a36Sopenharmony_ci struct hw_perf_event *hwc = &event->hw; 36662306a36Sopenharmony_ci u64 prev_raw_count, new_raw_count; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci prev_raw_count = local64_read(&hwc->prev_count); 36962306a36Sopenharmony_ci do { 37062306a36Sopenharmony_ci new_raw_count = cstate_pmu_read_counter(event); 37162306a36Sopenharmony_ci } while (!local64_try_cmpxchg(&hwc->prev_count, 37262306a36Sopenharmony_ci &prev_raw_count, new_raw_count)); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci local64_add(new_raw_count - prev_raw_count, &event->count); 37562306a36Sopenharmony_ci} 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_cistatic void cstate_pmu_event_start(struct perf_event *event, int mode) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci local64_set(&event->hw.prev_count, cstate_pmu_read_counter(event)); 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cistatic void cstate_pmu_event_stop(struct perf_event *event, int mode) 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci cstate_pmu_event_update(event); 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_cistatic void cstate_pmu_event_del(struct perf_event *event, int mode) 38862306a36Sopenharmony_ci{ 38962306a36Sopenharmony_ci cstate_pmu_event_stop(event, PERF_EF_UPDATE); 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic int cstate_pmu_event_add(struct perf_event *event, int mode) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci if (mode & PERF_EF_START) 39562306a36Sopenharmony_ci cstate_pmu_event_start(event, mode); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci return 0; 39862306a36Sopenharmony_ci} 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci/* 40162306a36Sopenharmony_ci * Check if exiting cpu is the designated reader. If so migrate the 40262306a36Sopenharmony_ci * events when there is a valid target available 40362306a36Sopenharmony_ci */ 40462306a36Sopenharmony_cistatic int cstate_cpu_exit(unsigned int cpu) 40562306a36Sopenharmony_ci{ 40662306a36Sopenharmony_ci unsigned int target; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci if (has_cstate_core && 40962306a36Sopenharmony_ci cpumask_test_and_clear_cpu(cpu, &cstate_core_cpu_mask)) { 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu); 41262306a36Sopenharmony_ci /* Migrate events if there is a valid target */ 41362306a36Sopenharmony_ci if (target < nr_cpu_ids) { 41462306a36Sopenharmony_ci cpumask_set_cpu(target, &cstate_core_cpu_mask); 41562306a36Sopenharmony_ci perf_pmu_migrate_context(&cstate_core_pmu, cpu, target); 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci if (has_cstate_pkg && 42062306a36Sopenharmony_ci cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask)) { 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci target = cpumask_any_but(topology_die_cpumask(cpu), cpu); 42362306a36Sopenharmony_ci /* Migrate events if there is a valid target */ 42462306a36Sopenharmony_ci if (target < nr_cpu_ids) { 42562306a36Sopenharmony_ci cpumask_set_cpu(target, &cstate_pkg_cpu_mask); 42662306a36Sopenharmony_ci perf_pmu_migrate_context(&cstate_pkg_pmu, cpu, target); 42762306a36Sopenharmony_ci } 42862306a36Sopenharmony_ci } 42962306a36Sopenharmony_ci return 0; 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_cistatic int cstate_cpu_init(unsigned int cpu) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci unsigned int target; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci /* 43762306a36Sopenharmony_ci * If this is the first online thread of that core, set it in 43862306a36Sopenharmony_ci * the core cpu mask as the designated reader. 43962306a36Sopenharmony_ci */ 44062306a36Sopenharmony_ci target = cpumask_any_and(&cstate_core_cpu_mask, 44162306a36Sopenharmony_ci topology_sibling_cpumask(cpu)); 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci if (has_cstate_core && target >= nr_cpu_ids) 44462306a36Sopenharmony_ci cpumask_set_cpu(cpu, &cstate_core_cpu_mask); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci /* 44762306a36Sopenharmony_ci * If this is the first online thread of that package, set it 44862306a36Sopenharmony_ci * in the package cpu mask as the designated reader. 44962306a36Sopenharmony_ci */ 45062306a36Sopenharmony_ci target = cpumask_any_and(&cstate_pkg_cpu_mask, 45162306a36Sopenharmony_ci topology_die_cpumask(cpu)); 45262306a36Sopenharmony_ci if (has_cstate_pkg && target >= nr_cpu_ids) 45362306a36Sopenharmony_ci cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci return 0; 45662306a36Sopenharmony_ci} 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cistatic const struct attribute_group *core_attr_update[] = { 45962306a36Sopenharmony_ci &group_cstate_core_c1, 46062306a36Sopenharmony_ci &group_cstate_core_c3, 46162306a36Sopenharmony_ci &group_cstate_core_c6, 46262306a36Sopenharmony_ci &group_cstate_core_c7, 46362306a36Sopenharmony_ci NULL, 46462306a36Sopenharmony_ci}; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cistatic const struct attribute_group *pkg_attr_update[] = { 46762306a36Sopenharmony_ci &group_cstate_pkg_c2, 46862306a36Sopenharmony_ci &group_cstate_pkg_c3, 46962306a36Sopenharmony_ci &group_cstate_pkg_c6, 47062306a36Sopenharmony_ci &group_cstate_pkg_c7, 47162306a36Sopenharmony_ci &group_cstate_pkg_c8, 47262306a36Sopenharmony_ci &group_cstate_pkg_c9, 47362306a36Sopenharmony_ci &group_cstate_pkg_c10, 47462306a36Sopenharmony_ci NULL, 47562306a36Sopenharmony_ci}; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_cistatic struct pmu cstate_core_pmu = { 47862306a36Sopenharmony_ci .attr_groups = core_attr_groups, 47962306a36Sopenharmony_ci .attr_update = core_attr_update, 48062306a36Sopenharmony_ci .name = "cstate_core", 48162306a36Sopenharmony_ci .task_ctx_nr = perf_invalid_context, 48262306a36Sopenharmony_ci .event_init = cstate_pmu_event_init, 48362306a36Sopenharmony_ci .add = cstate_pmu_event_add, 48462306a36Sopenharmony_ci .del = cstate_pmu_event_del, 48562306a36Sopenharmony_ci .start = cstate_pmu_event_start, 48662306a36Sopenharmony_ci .stop = cstate_pmu_event_stop, 48762306a36Sopenharmony_ci .read = cstate_pmu_event_update, 48862306a36Sopenharmony_ci .capabilities = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE, 48962306a36Sopenharmony_ci .module = THIS_MODULE, 49062306a36Sopenharmony_ci}; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_cistatic struct pmu cstate_pkg_pmu = { 49362306a36Sopenharmony_ci .attr_groups = pkg_attr_groups, 49462306a36Sopenharmony_ci .attr_update = pkg_attr_update, 49562306a36Sopenharmony_ci .name = "cstate_pkg", 49662306a36Sopenharmony_ci .task_ctx_nr = perf_invalid_context, 49762306a36Sopenharmony_ci .event_init = cstate_pmu_event_init, 49862306a36Sopenharmony_ci .add = cstate_pmu_event_add, 49962306a36Sopenharmony_ci .del = cstate_pmu_event_del, 50062306a36Sopenharmony_ci .start = cstate_pmu_event_start, 50162306a36Sopenharmony_ci .stop = cstate_pmu_event_stop, 50262306a36Sopenharmony_ci .read = cstate_pmu_event_update, 50362306a36Sopenharmony_ci .capabilities = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE, 50462306a36Sopenharmony_ci .module = THIS_MODULE, 50562306a36Sopenharmony_ci}; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_cistatic const struct cstate_model nhm_cstates __initconst = { 50862306a36Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C3_RES) | 50962306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C6_RES), 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C3_RES) | 51262306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES) | 51362306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C7_RES), 51462306a36Sopenharmony_ci}; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_cistatic const struct cstate_model snb_cstates __initconst = { 51762306a36Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C3_RES) | 51862306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C6_RES) | 51962306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C7_RES), 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | 52262306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C3_RES) | 52362306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES) | 52462306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C7_RES), 52562306a36Sopenharmony_ci}; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_cistatic const struct cstate_model hswult_cstates __initconst = { 52862306a36Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C3_RES) | 52962306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C6_RES) | 53062306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C7_RES), 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | 53362306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C3_RES) | 53462306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES) | 53562306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C7_RES) | 53662306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C8_RES) | 53762306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C9_RES) | 53862306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C10_RES), 53962306a36Sopenharmony_ci}; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_cistatic const struct cstate_model cnl_cstates __initconst = { 54262306a36Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C1_RES) | 54362306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C3_RES) | 54462306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C6_RES) | 54562306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C7_RES), 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | 54862306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C3_RES) | 54962306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES) | 55062306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C7_RES) | 55162306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C8_RES) | 55262306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C9_RES) | 55362306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C10_RES), 55462306a36Sopenharmony_ci}; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_cistatic const struct cstate_model icl_cstates __initconst = { 55762306a36Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C6_RES) | 55862306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C7_RES), 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | 56162306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C3_RES) | 56262306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES) | 56362306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C7_RES) | 56462306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C8_RES) | 56562306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C9_RES) | 56662306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C10_RES), 56762306a36Sopenharmony_ci}; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_cistatic const struct cstate_model icx_cstates __initconst = { 57062306a36Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C1_RES) | 57162306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C6_RES), 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | 57462306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES), 57562306a36Sopenharmony_ci}; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_cistatic const struct cstate_model adl_cstates __initconst = { 57862306a36Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C1_RES) | 57962306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C6_RES) | 58062306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C7_RES), 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | 58362306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C3_RES) | 58462306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES) | 58562306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C7_RES) | 58662306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C8_RES) | 58762306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C9_RES) | 58862306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C10_RES), 58962306a36Sopenharmony_ci}; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_cistatic const struct cstate_model slm_cstates __initconst = { 59262306a36Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C1_RES) | 59362306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C6_RES), 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C6_RES), 59662306a36Sopenharmony_ci .quirks = SLM_PKG_C6_USE_C7_MSR, 59762306a36Sopenharmony_ci}; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_cistatic const struct cstate_model knl_cstates __initconst = { 60162306a36Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C6_RES), 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | 60462306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C3_RES) | 60562306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES), 60662306a36Sopenharmony_ci .quirks = KNL_CORE_C6_MSR, 60762306a36Sopenharmony_ci}; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_cistatic const struct cstate_model glm_cstates __initconst = { 61162306a36Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C1_RES) | 61262306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C3_RES) | 61362306a36Sopenharmony_ci BIT(PERF_CSTATE_CORE_C6_RES), 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | 61662306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C3_RES) | 61762306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES) | 61862306a36Sopenharmony_ci BIT(PERF_CSTATE_PKG_C10_RES), 61962306a36Sopenharmony_ci}; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_cistatic const struct x86_cpu_id intel_cstates_match[] __initconst = { 62362306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(NEHALEM, &nhm_cstates), 62462306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EP, &nhm_cstates), 62562306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EX, &nhm_cstates), 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(WESTMERE, &nhm_cstates), 62862306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EP, &nhm_cstates), 62962306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EX, &nhm_cstates), 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE, &snb_cstates), 63262306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X, &snb_cstates), 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE, &snb_cstates), 63562306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE_X, &snb_cstates), 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(HASWELL, &snb_cstates), 63862306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X, &snb_cstates), 63962306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(HASWELL_G, &snb_cstates), 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(HASWELL_L, &hswult_cstates), 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT, &slm_cstates), 64462306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_D, &slm_cstates), 64562306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT, &slm_cstates), 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(BROADWELL, &snb_cstates), 64862306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_D, &snb_cstates), 64962306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_G, &snb_cstates), 65062306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X, &snb_cstates), 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, &snb_cstates), 65362306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, &snb_cstates), 65462306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X, &snb_cstates), 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, &hswult_cstates), 65762306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, &hswult_cstates), 65862306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE_L, &hswult_cstates), 65962306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, &hswult_cstates), 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(CANNONLAKE_L, &cnl_cstates), 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, &knl_cstates), 66462306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, &knl_cstates), 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, &glm_cstates), 66762306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_D, &glm_cstates), 66862306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS, &glm_cstates), 66962306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D, &glm_cstates), 67062306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT, &glm_cstates), 67162306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L, &glm_cstates), 67262306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_GRACEMONT, &adl_cstates), 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, &icl_cstates), 67562306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ICELAKE, &icl_cstates), 67662306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, &icx_cstates), 67762306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, &icx_cstates), 67862306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, &icx_cstates), 67962306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X, &icx_cstates), 68062306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_X, &icx_cstates), 68162306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_D, &icx_cstates), 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, &icl_cstates), 68462306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, &icl_cstates), 68562306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE, &icl_cstates), 68662306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, &adl_cstates), 68762306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, &adl_cstates), 68862306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, &adl_cstates), 68962306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, &adl_cstates), 69062306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, &adl_cstates), 69162306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE, &adl_cstates), 69262306a36Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE_L, &adl_cstates), 69362306a36Sopenharmony_ci { }, 69462306a36Sopenharmony_ci}; 69562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(x86cpu, intel_cstates_match); 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_cistatic int __init cstate_probe(const struct cstate_model *cm) 69862306a36Sopenharmony_ci{ 69962306a36Sopenharmony_ci /* SLM has different MSR for PKG C6 */ 70062306a36Sopenharmony_ci if (cm->quirks & SLM_PKG_C6_USE_C7_MSR) 70162306a36Sopenharmony_ci pkg_msr[PERF_CSTATE_PKG_C6_RES].msr = MSR_PKG_C7_RESIDENCY; 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci /* KNL has different MSR for CORE C6 */ 70462306a36Sopenharmony_ci if (cm->quirks & KNL_CORE_C6_MSR) 70562306a36Sopenharmony_ci pkg_msr[PERF_CSTATE_CORE_C6_RES].msr = MSR_KNL_CORE_C6_RESIDENCY; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci core_msr_mask = perf_msr_probe(core_msr, PERF_CSTATE_CORE_EVENT_MAX, 70962306a36Sopenharmony_ci true, (void *) &cm->core_events); 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci pkg_msr_mask = perf_msr_probe(pkg_msr, PERF_CSTATE_PKG_EVENT_MAX, 71262306a36Sopenharmony_ci true, (void *) &cm->pkg_events); 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci has_cstate_core = !!core_msr_mask; 71562306a36Sopenharmony_ci has_cstate_pkg = !!pkg_msr_mask; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci return (has_cstate_core || has_cstate_pkg) ? 0 : -ENODEV; 71862306a36Sopenharmony_ci} 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_cistatic inline void cstate_cleanup(void) 72162306a36Sopenharmony_ci{ 72262306a36Sopenharmony_ci cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_CSTATE_ONLINE); 72362306a36Sopenharmony_ci cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_CSTATE_STARTING); 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci if (has_cstate_core) 72662306a36Sopenharmony_ci perf_pmu_unregister(&cstate_core_pmu); 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci if (has_cstate_pkg) 72962306a36Sopenharmony_ci perf_pmu_unregister(&cstate_pkg_pmu); 73062306a36Sopenharmony_ci} 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_cistatic int __init cstate_init(void) 73362306a36Sopenharmony_ci{ 73462306a36Sopenharmony_ci int err; 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci cpuhp_setup_state(CPUHP_AP_PERF_X86_CSTATE_STARTING, 73762306a36Sopenharmony_ci "perf/x86/cstate:starting", cstate_cpu_init, NULL); 73862306a36Sopenharmony_ci cpuhp_setup_state(CPUHP_AP_PERF_X86_CSTATE_ONLINE, 73962306a36Sopenharmony_ci "perf/x86/cstate:online", NULL, cstate_cpu_exit); 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci if (has_cstate_core) { 74262306a36Sopenharmony_ci err = perf_pmu_register(&cstate_core_pmu, cstate_core_pmu.name, -1); 74362306a36Sopenharmony_ci if (err) { 74462306a36Sopenharmony_ci has_cstate_core = false; 74562306a36Sopenharmony_ci pr_info("Failed to register cstate core pmu\n"); 74662306a36Sopenharmony_ci cstate_cleanup(); 74762306a36Sopenharmony_ci return err; 74862306a36Sopenharmony_ci } 74962306a36Sopenharmony_ci } 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci if (has_cstate_pkg) { 75262306a36Sopenharmony_ci if (topology_max_die_per_package() > 1) { 75362306a36Sopenharmony_ci err = perf_pmu_register(&cstate_pkg_pmu, 75462306a36Sopenharmony_ci "cstate_die", -1); 75562306a36Sopenharmony_ci } else { 75662306a36Sopenharmony_ci err = perf_pmu_register(&cstate_pkg_pmu, 75762306a36Sopenharmony_ci cstate_pkg_pmu.name, -1); 75862306a36Sopenharmony_ci } 75962306a36Sopenharmony_ci if (err) { 76062306a36Sopenharmony_ci has_cstate_pkg = false; 76162306a36Sopenharmony_ci pr_info("Failed to register cstate pkg pmu\n"); 76262306a36Sopenharmony_ci cstate_cleanup(); 76362306a36Sopenharmony_ci return err; 76462306a36Sopenharmony_ci } 76562306a36Sopenharmony_ci } 76662306a36Sopenharmony_ci return 0; 76762306a36Sopenharmony_ci} 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_cistatic int __init cstate_pmu_init(void) 77062306a36Sopenharmony_ci{ 77162306a36Sopenharmony_ci const struct x86_cpu_id *id; 77262306a36Sopenharmony_ci int err; 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) 77562306a36Sopenharmony_ci return -ENODEV; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci id = x86_match_cpu(intel_cstates_match); 77862306a36Sopenharmony_ci if (!id) 77962306a36Sopenharmony_ci return -ENODEV; 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci err = cstate_probe((const struct cstate_model *) id->driver_data); 78262306a36Sopenharmony_ci if (err) 78362306a36Sopenharmony_ci return err; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci return cstate_init(); 78662306a36Sopenharmony_ci} 78762306a36Sopenharmony_cimodule_init(cstate_pmu_init); 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_cistatic void __exit cstate_pmu_exit(void) 79062306a36Sopenharmony_ci{ 79162306a36Sopenharmony_ci cstate_cleanup(); 79262306a36Sopenharmony_ci} 79362306a36Sopenharmony_cimodule_exit(cstate_pmu_exit); 794