18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Support cstate residency counters 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2015, Intel Corp. 58c2ecf20Sopenharmony_ci * Author: Kan Liang (kan.liang@intel.com) 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This library is free software; you can redistribute it and/or 88c2ecf20Sopenharmony_ci * modify it under the terms of the GNU Library General Public 98c2ecf20Sopenharmony_ci * License as published by the Free Software Foundation; either 108c2ecf20Sopenharmony_ci * version 2 of the License, or (at your option) any later version. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * This library is distributed in the hope that it will be useful, 138c2ecf20Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 148c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 158c2ecf20Sopenharmony_ci * Library General Public License for more details. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* 208c2ecf20Sopenharmony_ci * This file export cstate related free running (read-only) counters 218c2ecf20Sopenharmony_ci * for perf. These counters may be use simultaneously by other tools, 228c2ecf20Sopenharmony_ci * such as turbostat. However, it still make sense to implement them 238c2ecf20Sopenharmony_ci * in perf. Because we can conveniently collect them together with 248c2ecf20Sopenharmony_ci * other events, and allow to use them from tools without special MSR 258c2ecf20Sopenharmony_ci * access code. 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * The events only support system-wide mode counting. There is no 288c2ecf20Sopenharmony_ci * sampling support because it is not supported by the hardware. 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * According to counters' scope and category, two PMUs are registered 318c2ecf20Sopenharmony_ci * with the perf_event core subsystem. 328c2ecf20Sopenharmony_ci * - 'cstate_core': The counter is available for each physical core. 338c2ecf20Sopenharmony_ci * The counters include CORE_C*_RESIDENCY. 348c2ecf20Sopenharmony_ci * - 'cstate_pkg': The counter is available for each physical package. 358c2ecf20Sopenharmony_ci * The counters include PKG_C*_RESIDENCY. 368c2ecf20Sopenharmony_ci * 378c2ecf20Sopenharmony_ci * All of these counters are specified in the Intel® 64 and IA-32 388c2ecf20Sopenharmony_ci * Architectures Software Developer.s Manual Vol3b. 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * Model specific counters: 418c2ecf20Sopenharmony_ci * MSR_CORE_C1_RES: CORE C1 Residency Counter 428c2ecf20Sopenharmony_ci * perf code: 0x00 438c2ecf20Sopenharmony_ci * Available model: SLM,AMT,GLM,CNL,TNT 448c2ecf20Sopenharmony_ci * Scope: Core (each processor core has a MSR) 458c2ecf20Sopenharmony_ci * MSR_CORE_C3_RESIDENCY: CORE C3 Residency Counter 468c2ecf20Sopenharmony_ci * perf code: 0x01 478c2ecf20Sopenharmony_ci * Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,GLM, 488c2ecf20Sopenharmony_ci * CNL,KBL,CML,TNT 498c2ecf20Sopenharmony_ci * Scope: Core 508c2ecf20Sopenharmony_ci * MSR_CORE_C6_RESIDENCY: CORE C6 Residency Counter 518c2ecf20Sopenharmony_ci * perf code: 0x02 528c2ecf20Sopenharmony_ci * Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW, 538c2ecf20Sopenharmony_ci * SKL,KNL,GLM,CNL,KBL,CML,ICL,TGL, 548c2ecf20Sopenharmony_ci * TNT 558c2ecf20Sopenharmony_ci * Scope: Core 568c2ecf20Sopenharmony_ci * MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter 578c2ecf20Sopenharmony_ci * perf code: 0x03 588c2ecf20Sopenharmony_ci * Available model: SNB,IVB,HSW,BDW,SKL,CNL,KBL,CML, 598c2ecf20Sopenharmony_ci * ICL,TGL 608c2ecf20Sopenharmony_ci * Scope: Core 618c2ecf20Sopenharmony_ci * MSR_PKG_C2_RESIDENCY: Package C2 Residency Counter. 628c2ecf20Sopenharmony_ci * perf code: 0x00 638c2ecf20Sopenharmony_ci * Available model: SNB,IVB,HSW,BDW,SKL,KNL,GLM,CNL, 648c2ecf20Sopenharmony_ci * KBL,CML,ICL,TGL,TNT 658c2ecf20Sopenharmony_ci * Scope: Package (physical package) 668c2ecf20Sopenharmony_ci * MSR_PKG_C3_RESIDENCY: Package C3 Residency Counter. 678c2ecf20Sopenharmony_ci * perf code: 0x01 688c2ecf20Sopenharmony_ci * Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,KNL, 698c2ecf20Sopenharmony_ci * GLM,CNL,KBL,CML,ICL,TGL,TNT 708c2ecf20Sopenharmony_ci * Scope: Package (physical package) 718c2ecf20Sopenharmony_ci * MSR_PKG_C6_RESIDENCY: Package C6 Residency Counter. 728c2ecf20Sopenharmony_ci * perf code: 0x02 738c2ecf20Sopenharmony_ci * Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW, 748c2ecf20Sopenharmony_ci * SKL,KNL,GLM,CNL,KBL,CML,ICL,TGL, 758c2ecf20Sopenharmony_ci * TNT 768c2ecf20Sopenharmony_ci * Scope: Package (physical package) 778c2ecf20Sopenharmony_ci * MSR_PKG_C7_RESIDENCY: Package C7 Residency Counter. 788c2ecf20Sopenharmony_ci * perf code: 0x03 798c2ecf20Sopenharmony_ci * Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,CNL, 808c2ecf20Sopenharmony_ci * KBL,CML,ICL,TGL 818c2ecf20Sopenharmony_ci * Scope: Package (physical package) 828c2ecf20Sopenharmony_ci * MSR_PKG_C8_RESIDENCY: Package C8 Residency Counter. 838c2ecf20Sopenharmony_ci * perf code: 0x04 848c2ecf20Sopenharmony_ci * Available model: HSW ULT,KBL,CNL,CML,ICL,TGL 858c2ecf20Sopenharmony_ci * Scope: Package (physical package) 868c2ecf20Sopenharmony_ci * MSR_PKG_C9_RESIDENCY: Package C9 Residency Counter. 878c2ecf20Sopenharmony_ci * perf code: 0x05 888c2ecf20Sopenharmony_ci * Available model: HSW ULT,KBL,CNL,CML,ICL,TGL 898c2ecf20Sopenharmony_ci * Scope: Package (physical package) 908c2ecf20Sopenharmony_ci * MSR_PKG_C10_RESIDENCY: Package C10 Residency Counter. 918c2ecf20Sopenharmony_ci * perf code: 0x06 928c2ecf20Sopenharmony_ci * Available model: HSW ULT,KBL,GLM,CNL,CML,ICL,TGL, 938c2ecf20Sopenharmony_ci * TNT 948c2ecf20Sopenharmony_ci * Scope: Package (physical package) 958c2ecf20Sopenharmony_ci * 968c2ecf20Sopenharmony_ci */ 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci#include <linux/module.h> 998c2ecf20Sopenharmony_ci#include <linux/slab.h> 1008c2ecf20Sopenharmony_ci#include <linux/perf_event.h> 1018c2ecf20Sopenharmony_ci#include <linux/nospec.h> 1028c2ecf20Sopenharmony_ci#include <asm/cpu_device_id.h> 1038c2ecf20Sopenharmony_ci#include <asm/intel-family.h> 1048c2ecf20Sopenharmony_ci#include "../perf_event.h" 1058c2ecf20Sopenharmony_ci#include "../probe.h" 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci#define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format) \ 1108c2ecf20Sopenharmony_cistatic ssize_t __cstate_##_var##_show(struct device *dev, \ 1118c2ecf20Sopenharmony_ci struct device_attribute *attr, \ 1128c2ecf20Sopenharmony_ci char *page) \ 1138c2ecf20Sopenharmony_ci{ \ 1148c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ 1158c2ecf20Sopenharmony_ci return sprintf(page, _format "\n"); \ 1168c2ecf20Sopenharmony_ci} \ 1178c2ecf20Sopenharmony_cistatic struct device_attribute format_attr_##_var = \ 1188c2ecf20Sopenharmony_ci __ATTR(_name, 0444, __cstate_##_var##_show, NULL) 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic ssize_t cstate_get_attr_cpumask(struct device *dev, 1218c2ecf20Sopenharmony_ci struct device_attribute *attr, 1228c2ecf20Sopenharmony_ci char *buf); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci/* Model -> events mapping */ 1258c2ecf20Sopenharmony_cistruct cstate_model { 1268c2ecf20Sopenharmony_ci unsigned long core_events; 1278c2ecf20Sopenharmony_ci unsigned long pkg_events; 1288c2ecf20Sopenharmony_ci unsigned long quirks; 1298c2ecf20Sopenharmony_ci}; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci/* Quirk flags */ 1328c2ecf20Sopenharmony_ci#define SLM_PKG_C6_USE_C7_MSR (1UL << 0) 1338c2ecf20Sopenharmony_ci#define KNL_CORE_C6_MSR (1UL << 1) 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistruct perf_cstate_msr { 1368c2ecf20Sopenharmony_ci u64 msr; 1378c2ecf20Sopenharmony_ci struct perf_pmu_events_attr *attr; 1388c2ecf20Sopenharmony_ci}; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci/* cstate_core PMU */ 1428c2ecf20Sopenharmony_cistatic struct pmu cstate_core_pmu; 1438c2ecf20Sopenharmony_cistatic bool has_cstate_core; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cienum perf_cstate_core_events { 1468c2ecf20Sopenharmony_ci PERF_CSTATE_CORE_C1_RES = 0, 1478c2ecf20Sopenharmony_ci PERF_CSTATE_CORE_C3_RES, 1488c2ecf20Sopenharmony_ci PERF_CSTATE_CORE_C6_RES, 1498c2ecf20Sopenharmony_ci PERF_CSTATE_CORE_C7_RES, 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci PERF_CSTATE_CORE_EVENT_MAX, 1528c2ecf20Sopenharmony_ci}; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ciPMU_EVENT_ATTR_STRING(c1-residency, attr_cstate_core_c1, "event=0x00"); 1558c2ecf20Sopenharmony_ciPMU_EVENT_ATTR_STRING(c3-residency, attr_cstate_core_c3, "event=0x01"); 1568c2ecf20Sopenharmony_ciPMU_EVENT_ATTR_STRING(c6-residency, attr_cstate_core_c6, "event=0x02"); 1578c2ecf20Sopenharmony_ciPMU_EVENT_ATTR_STRING(c7-residency, attr_cstate_core_c7, "event=0x03"); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistatic unsigned long core_msr_mask; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_core_c1); 1628c2ecf20Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_core_c3); 1638c2ecf20Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_core_c6); 1648c2ecf20Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_core_c7); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistatic bool test_msr(int idx, void *data) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci return test_bit(idx, (unsigned long *) data); 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cistatic struct perf_msr core_msr[] = { 1728c2ecf20Sopenharmony_ci [PERF_CSTATE_CORE_C1_RES] = { MSR_CORE_C1_RES, &group_cstate_core_c1, test_msr }, 1738c2ecf20Sopenharmony_ci [PERF_CSTATE_CORE_C3_RES] = { MSR_CORE_C3_RESIDENCY, &group_cstate_core_c3, test_msr }, 1748c2ecf20Sopenharmony_ci [PERF_CSTATE_CORE_C6_RES] = { MSR_CORE_C6_RESIDENCY, &group_cstate_core_c6, test_msr }, 1758c2ecf20Sopenharmony_ci [PERF_CSTATE_CORE_C7_RES] = { MSR_CORE_C7_RESIDENCY, &group_cstate_core_c7, test_msr }, 1768c2ecf20Sopenharmony_ci}; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic struct attribute *attrs_empty[] = { 1798c2ecf20Sopenharmony_ci NULL, 1808c2ecf20Sopenharmony_ci}; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci/* 1838c2ecf20Sopenharmony_ci * There are no default events, but we need to create 1848c2ecf20Sopenharmony_ci * "events" group (with empty attrs) before updating 1858c2ecf20Sopenharmony_ci * it with detected events. 1868c2ecf20Sopenharmony_ci */ 1878c2ecf20Sopenharmony_cistatic struct attribute_group core_events_attr_group = { 1888c2ecf20Sopenharmony_ci .name = "events", 1898c2ecf20Sopenharmony_ci .attrs = attrs_empty, 1908c2ecf20Sopenharmony_ci}; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ciDEFINE_CSTATE_FORMAT_ATTR(core_event, event, "config:0-63"); 1938c2ecf20Sopenharmony_cistatic struct attribute *core_format_attrs[] = { 1948c2ecf20Sopenharmony_ci &format_attr_core_event.attr, 1958c2ecf20Sopenharmony_ci NULL, 1968c2ecf20Sopenharmony_ci}; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic struct attribute_group core_format_attr_group = { 1998c2ecf20Sopenharmony_ci .name = "format", 2008c2ecf20Sopenharmony_ci .attrs = core_format_attrs, 2018c2ecf20Sopenharmony_ci}; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic cpumask_t cstate_core_cpu_mask; 2048c2ecf20Sopenharmony_cistatic DEVICE_ATTR(cpumask, S_IRUGO, cstate_get_attr_cpumask, NULL); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cistatic struct attribute *cstate_cpumask_attrs[] = { 2078c2ecf20Sopenharmony_ci &dev_attr_cpumask.attr, 2088c2ecf20Sopenharmony_ci NULL, 2098c2ecf20Sopenharmony_ci}; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic struct attribute_group cpumask_attr_group = { 2128c2ecf20Sopenharmony_ci .attrs = cstate_cpumask_attrs, 2138c2ecf20Sopenharmony_ci}; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic const struct attribute_group *core_attr_groups[] = { 2168c2ecf20Sopenharmony_ci &core_events_attr_group, 2178c2ecf20Sopenharmony_ci &core_format_attr_group, 2188c2ecf20Sopenharmony_ci &cpumask_attr_group, 2198c2ecf20Sopenharmony_ci NULL, 2208c2ecf20Sopenharmony_ci}; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci/* cstate_pkg PMU */ 2238c2ecf20Sopenharmony_cistatic struct pmu cstate_pkg_pmu; 2248c2ecf20Sopenharmony_cistatic bool has_cstate_pkg; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_cienum perf_cstate_pkg_events { 2278c2ecf20Sopenharmony_ci PERF_CSTATE_PKG_C2_RES = 0, 2288c2ecf20Sopenharmony_ci PERF_CSTATE_PKG_C3_RES, 2298c2ecf20Sopenharmony_ci PERF_CSTATE_PKG_C6_RES, 2308c2ecf20Sopenharmony_ci PERF_CSTATE_PKG_C7_RES, 2318c2ecf20Sopenharmony_ci PERF_CSTATE_PKG_C8_RES, 2328c2ecf20Sopenharmony_ci PERF_CSTATE_PKG_C9_RES, 2338c2ecf20Sopenharmony_ci PERF_CSTATE_PKG_C10_RES, 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci PERF_CSTATE_PKG_EVENT_MAX, 2368c2ecf20Sopenharmony_ci}; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ciPMU_EVENT_ATTR_STRING(c2-residency, attr_cstate_pkg_c2, "event=0x00"); 2398c2ecf20Sopenharmony_ciPMU_EVENT_ATTR_STRING(c3-residency, attr_cstate_pkg_c3, "event=0x01"); 2408c2ecf20Sopenharmony_ciPMU_EVENT_ATTR_STRING(c6-residency, attr_cstate_pkg_c6, "event=0x02"); 2418c2ecf20Sopenharmony_ciPMU_EVENT_ATTR_STRING(c7-residency, attr_cstate_pkg_c7, "event=0x03"); 2428c2ecf20Sopenharmony_ciPMU_EVENT_ATTR_STRING(c8-residency, attr_cstate_pkg_c8, "event=0x04"); 2438c2ecf20Sopenharmony_ciPMU_EVENT_ATTR_STRING(c9-residency, attr_cstate_pkg_c9, "event=0x05"); 2448c2ecf20Sopenharmony_ciPMU_EVENT_ATTR_STRING(c10-residency, attr_cstate_pkg_c10, "event=0x06"); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic unsigned long pkg_msr_mask; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_pkg_c2); 2498c2ecf20Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_pkg_c3); 2508c2ecf20Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_pkg_c6); 2518c2ecf20Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_pkg_c7); 2528c2ecf20Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_pkg_c8); 2538c2ecf20Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_pkg_c9); 2548c2ecf20Sopenharmony_ciPMU_EVENT_GROUP(events, cstate_pkg_c10); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_cistatic struct perf_msr pkg_msr[] = { 2578c2ecf20Sopenharmony_ci [PERF_CSTATE_PKG_C2_RES] = { MSR_PKG_C2_RESIDENCY, &group_cstate_pkg_c2, test_msr }, 2588c2ecf20Sopenharmony_ci [PERF_CSTATE_PKG_C3_RES] = { MSR_PKG_C3_RESIDENCY, &group_cstate_pkg_c3, test_msr }, 2598c2ecf20Sopenharmony_ci [PERF_CSTATE_PKG_C6_RES] = { MSR_PKG_C6_RESIDENCY, &group_cstate_pkg_c6, test_msr }, 2608c2ecf20Sopenharmony_ci [PERF_CSTATE_PKG_C7_RES] = { MSR_PKG_C7_RESIDENCY, &group_cstate_pkg_c7, test_msr }, 2618c2ecf20Sopenharmony_ci [PERF_CSTATE_PKG_C8_RES] = { MSR_PKG_C8_RESIDENCY, &group_cstate_pkg_c8, test_msr }, 2628c2ecf20Sopenharmony_ci [PERF_CSTATE_PKG_C9_RES] = { MSR_PKG_C9_RESIDENCY, &group_cstate_pkg_c9, test_msr }, 2638c2ecf20Sopenharmony_ci [PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY, &group_cstate_pkg_c10, test_msr }, 2648c2ecf20Sopenharmony_ci}; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic struct attribute_group pkg_events_attr_group = { 2678c2ecf20Sopenharmony_ci .name = "events", 2688c2ecf20Sopenharmony_ci .attrs = attrs_empty, 2698c2ecf20Sopenharmony_ci}; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ciDEFINE_CSTATE_FORMAT_ATTR(pkg_event, event, "config:0-63"); 2728c2ecf20Sopenharmony_cistatic struct attribute *pkg_format_attrs[] = { 2738c2ecf20Sopenharmony_ci &format_attr_pkg_event.attr, 2748c2ecf20Sopenharmony_ci NULL, 2758c2ecf20Sopenharmony_ci}; 2768c2ecf20Sopenharmony_cistatic struct attribute_group pkg_format_attr_group = { 2778c2ecf20Sopenharmony_ci .name = "format", 2788c2ecf20Sopenharmony_ci .attrs = pkg_format_attrs, 2798c2ecf20Sopenharmony_ci}; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_cistatic cpumask_t cstate_pkg_cpu_mask; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic const struct attribute_group *pkg_attr_groups[] = { 2848c2ecf20Sopenharmony_ci &pkg_events_attr_group, 2858c2ecf20Sopenharmony_ci &pkg_format_attr_group, 2868c2ecf20Sopenharmony_ci &cpumask_attr_group, 2878c2ecf20Sopenharmony_ci NULL, 2888c2ecf20Sopenharmony_ci}; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_cistatic ssize_t cstate_get_attr_cpumask(struct device *dev, 2918c2ecf20Sopenharmony_ci struct device_attribute *attr, 2928c2ecf20Sopenharmony_ci char *buf) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci struct pmu *pmu = dev_get_drvdata(dev); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci if (pmu == &cstate_core_pmu) 2978c2ecf20Sopenharmony_ci return cpumap_print_to_pagebuf(true, buf, &cstate_core_cpu_mask); 2988c2ecf20Sopenharmony_ci else if (pmu == &cstate_pkg_pmu) 2998c2ecf20Sopenharmony_ci return cpumap_print_to_pagebuf(true, buf, &cstate_pkg_cpu_mask); 3008c2ecf20Sopenharmony_ci else 3018c2ecf20Sopenharmony_ci return 0; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic int cstate_pmu_event_init(struct perf_event *event) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci u64 cfg = event->attr.config; 3078c2ecf20Sopenharmony_ci int cpu; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci if (event->attr.type != event->pmu->type) 3108c2ecf20Sopenharmony_ci return -ENOENT; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci /* unsupported modes and filters */ 3138c2ecf20Sopenharmony_ci if (event->attr.sample_period) /* no sampling */ 3148c2ecf20Sopenharmony_ci return -EINVAL; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci if (event->cpu < 0) 3178c2ecf20Sopenharmony_ci return -EINVAL; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci if (event->pmu == &cstate_core_pmu) { 3208c2ecf20Sopenharmony_ci if (cfg >= PERF_CSTATE_CORE_EVENT_MAX) 3218c2ecf20Sopenharmony_ci return -EINVAL; 3228c2ecf20Sopenharmony_ci cfg = array_index_nospec((unsigned long)cfg, PERF_CSTATE_CORE_EVENT_MAX); 3238c2ecf20Sopenharmony_ci if (!(core_msr_mask & (1 << cfg))) 3248c2ecf20Sopenharmony_ci return -EINVAL; 3258c2ecf20Sopenharmony_ci event->hw.event_base = core_msr[cfg].msr; 3268c2ecf20Sopenharmony_ci cpu = cpumask_any_and(&cstate_core_cpu_mask, 3278c2ecf20Sopenharmony_ci topology_sibling_cpumask(event->cpu)); 3288c2ecf20Sopenharmony_ci } else if (event->pmu == &cstate_pkg_pmu) { 3298c2ecf20Sopenharmony_ci if (cfg >= PERF_CSTATE_PKG_EVENT_MAX) 3308c2ecf20Sopenharmony_ci return -EINVAL; 3318c2ecf20Sopenharmony_ci cfg = array_index_nospec((unsigned long)cfg, PERF_CSTATE_PKG_EVENT_MAX); 3328c2ecf20Sopenharmony_ci if (!(pkg_msr_mask & (1 << cfg))) 3338c2ecf20Sopenharmony_ci return -EINVAL; 3348c2ecf20Sopenharmony_ci event->hw.event_base = pkg_msr[cfg].msr; 3358c2ecf20Sopenharmony_ci cpu = cpumask_any_and(&cstate_pkg_cpu_mask, 3368c2ecf20Sopenharmony_ci topology_die_cpumask(event->cpu)); 3378c2ecf20Sopenharmony_ci } else { 3388c2ecf20Sopenharmony_ci return -ENOENT; 3398c2ecf20Sopenharmony_ci } 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci if (cpu >= nr_cpu_ids) 3428c2ecf20Sopenharmony_ci return -ENODEV; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci event->cpu = cpu; 3458c2ecf20Sopenharmony_ci event->hw.config = cfg; 3468c2ecf20Sopenharmony_ci event->hw.idx = -1; 3478c2ecf20Sopenharmony_ci return 0; 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic inline u64 cstate_pmu_read_counter(struct perf_event *event) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci u64 val; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci rdmsrl(event->hw.event_base, val); 3558c2ecf20Sopenharmony_ci return val; 3568c2ecf20Sopenharmony_ci} 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistatic void cstate_pmu_event_update(struct perf_event *event) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci struct hw_perf_event *hwc = &event->hw; 3618c2ecf20Sopenharmony_ci u64 prev_raw_count, new_raw_count; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ciagain: 3648c2ecf20Sopenharmony_ci prev_raw_count = local64_read(&hwc->prev_count); 3658c2ecf20Sopenharmony_ci new_raw_count = cstate_pmu_read_counter(event); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, 3688c2ecf20Sopenharmony_ci new_raw_count) != prev_raw_count) 3698c2ecf20Sopenharmony_ci goto again; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci local64_add(new_raw_count - prev_raw_count, &event->count); 3728c2ecf20Sopenharmony_ci} 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic void cstate_pmu_event_start(struct perf_event *event, int mode) 3758c2ecf20Sopenharmony_ci{ 3768c2ecf20Sopenharmony_ci local64_set(&event->hw.prev_count, cstate_pmu_read_counter(event)); 3778c2ecf20Sopenharmony_ci} 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_cistatic void cstate_pmu_event_stop(struct perf_event *event, int mode) 3808c2ecf20Sopenharmony_ci{ 3818c2ecf20Sopenharmony_ci cstate_pmu_event_update(event); 3828c2ecf20Sopenharmony_ci} 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_cistatic void cstate_pmu_event_del(struct perf_event *event, int mode) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci cstate_pmu_event_stop(event, PERF_EF_UPDATE); 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_cistatic int cstate_pmu_event_add(struct perf_event *event, int mode) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci if (mode & PERF_EF_START) 3928c2ecf20Sopenharmony_ci cstate_pmu_event_start(event, mode); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci return 0; 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci/* 3988c2ecf20Sopenharmony_ci * Check if exiting cpu is the designated reader. If so migrate the 3998c2ecf20Sopenharmony_ci * events when there is a valid target available 4008c2ecf20Sopenharmony_ci */ 4018c2ecf20Sopenharmony_cistatic int cstate_cpu_exit(unsigned int cpu) 4028c2ecf20Sopenharmony_ci{ 4038c2ecf20Sopenharmony_ci unsigned int target; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci if (has_cstate_core && 4068c2ecf20Sopenharmony_ci cpumask_test_and_clear_cpu(cpu, &cstate_core_cpu_mask)) { 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu); 4098c2ecf20Sopenharmony_ci /* Migrate events if there is a valid target */ 4108c2ecf20Sopenharmony_ci if (target < nr_cpu_ids) { 4118c2ecf20Sopenharmony_ci cpumask_set_cpu(target, &cstate_core_cpu_mask); 4128c2ecf20Sopenharmony_ci perf_pmu_migrate_context(&cstate_core_pmu, cpu, target); 4138c2ecf20Sopenharmony_ci } 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci if (has_cstate_pkg && 4178c2ecf20Sopenharmony_ci cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask)) { 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci target = cpumask_any_but(topology_die_cpumask(cpu), cpu); 4208c2ecf20Sopenharmony_ci /* Migrate events if there is a valid target */ 4218c2ecf20Sopenharmony_ci if (target < nr_cpu_ids) { 4228c2ecf20Sopenharmony_ci cpumask_set_cpu(target, &cstate_pkg_cpu_mask); 4238c2ecf20Sopenharmony_ci perf_pmu_migrate_context(&cstate_pkg_pmu, cpu, target); 4248c2ecf20Sopenharmony_ci } 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci return 0; 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_cistatic int cstate_cpu_init(unsigned int cpu) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci unsigned int target; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci /* 4348c2ecf20Sopenharmony_ci * If this is the first online thread of that core, set it in 4358c2ecf20Sopenharmony_ci * the core cpu mask as the designated reader. 4368c2ecf20Sopenharmony_ci */ 4378c2ecf20Sopenharmony_ci target = cpumask_any_and(&cstate_core_cpu_mask, 4388c2ecf20Sopenharmony_ci topology_sibling_cpumask(cpu)); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci if (has_cstate_core && target >= nr_cpu_ids) 4418c2ecf20Sopenharmony_ci cpumask_set_cpu(cpu, &cstate_core_cpu_mask); 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci /* 4448c2ecf20Sopenharmony_ci * If this is the first online thread of that package, set it 4458c2ecf20Sopenharmony_ci * in the package cpu mask as the designated reader. 4468c2ecf20Sopenharmony_ci */ 4478c2ecf20Sopenharmony_ci target = cpumask_any_and(&cstate_pkg_cpu_mask, 4488c2ecf20Sopenharmony_ci topology_die_cpumask(cpu)); 4498c2ecf20Sopenharmony_ci if (has_cstate_pkg && target >= nr_cpu_ids) 4508c2ecf20Sopenharmony_ci cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci return 0; 4538c2ecf20Sopenharmony_ci} 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_cistatic const struct attribute_group *core_attr_update[] = { 4568c2ecf20Sopenharmony_ci &group_cstate_core_c1, 4578c2ecf20Sopenharmony_ci &group_cstate_core_c3, 4588c2ecf20Sopenharmony_ci &group_cstate_core_c6, 4598c2ecf20Sopenharmony_ci &group_cstate_core_c7, 4608c2ecf20Sopenharmony_ci NULL, 4618c2ecf20Sopenharmony_ci}; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_cistatic const struct attribute_group *pkg_attr_update[] = { 4648c2ecf20Sopenharmony_ci &group_cstate_pkg_c2, 4658c2ecf20Sopenharmony_ci &group_cstate_pkg_c3, 4668c2ecf20Sopenharmony_ci &group_cstate_pkg_c6, 4678c2ecf20Sopenharmony_ci &group_cstate_pkg_c7, 4688c2ecf20Sopenharmony_ci &group_cstate_pkg_c8, 4698c2ecf20Sopenharmony_ci &group_cstate_pkg_c9, 4708c2ecf20Sopenharmony_ci &group_cstate_pkg_c10, 4718c2ecf20Sopenharmony_ci NULL, 4728c2ecf20Sopenharmony_ci}; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_cistatic struct pmu cstate_core_pmu = { 4758c2ecf20Sopenharmony_ci .attr_groups = core_attr_groups, 4768c2ecf20Sopenharmony_ci .attr_update = core_attr_update, 4778c2ecf20Sopenharmony_ci .name = "cstate_core", 4788c2ecf20Sopenharmony_ci .task_ctx_nr = perf_invalid_context, 4798c2ecf20Sopenharmony_ci .event_init = cstate_pmu_event_init, 4808c2ecf20Sopenharmony_ci .add = cstate_pmu_event_add, 4818c2ecf20Sopenharmony_ci .del = cstate_pmu_event_del, 4828c2ecf20Sopenharmony_ci .start = cstate_pmu_event_start, 4838c2ecf20Sopenharmony_ci .stop = cstate_pmu_event_stop, 4848c2ecf20Sopenharmony_ci .read = cstate_pmu_event_update, 4858c2ecf20Sopenharmony_ci .capabilities = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE, 4868c2ecf20Sopenharmony_ci .module = THIS_MODULE, 4878c2ecf20Sopenharmony_ci}; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_cistatic struct pmu cstate_pkg_pmu = { 4908c2ecf20Sopenharmony_ci .attr_groups = pkg_attr_groups, 4918c2ecf20Sopenharmony_ci .attr_update = pkg_attr_update, 4928c2ecf20Sopenharmony_ci .name = "cstate_pkg", 4938c2ecf20Sopenharmony_ci .task_ctx_nr = perf_invalid_context, 4948c2ecf20Sopenharmony_ci .event_init = cstate_pmu_event_init, 4958c2ecf20Sopenharmony_ci .add = cstate_pmu_event_add, 4968c2ecf20Sopenharmony_ci .del = cstate_pmu_event_del, 4978c2ecf20Sopenharmony_ci .start = cstate_pmu_event_start, 4988c2ecf20Sopenharmony_ci .stop = cstate_pmu_event_stop, 4998c2ecf20Sopenharmony_ci .read = cstate_pmu_event_update, 5008c2ecf20Sopenharmony_ci .capabilities = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE, 5018c2ecf20Sopenharmony_ci .module = THIS_MODULE, 5028c2ecf20Sopenharmony_ci}; 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_cistatic const struct cstate_model nhm_cstates __initconst = { 5058c2ecf20Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C3_RES) | 5068c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_CORE_C6_RES), 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C3_RES) | 5098c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES) | 5108c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C7_RES), 5118c2ecf20Sopenharmony_ci}; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_cistatic const struct cstate_model snb_cstates __initconst = { 5148c2ecf20Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C3_RES) | 5158c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_CORE_C6_RES) | 5168c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_CORE_C7_RES), 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | 5198c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C3_RES) | 5208c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES) | 5218c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C7_RES), 5228c2ecf20Sopenharmony_ci}; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_cistatic const struct cstate_model hswult_cstates __initconst = { 5258c2ecf20Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C3_RES) | 5268c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_CORE_C6_RES) | 5278c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_CORE_C7_RES), 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | 5308c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C3_RES) | 5318c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES) | 5328c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C7_RES) | 5338c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C8_RES) | 5348c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C9_RES) | 5358c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C10_RES), 5368c2ecf20Sopenharmony_ci}; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_cistatic const struct cstate_model cnl_cstates __initconst = { 5398c2ecf20Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C1_RES) | 5408c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_CORE_C3_RES) | 5418c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_CORE_C6_RES) | 5428c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_CORE_C7_RES), 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | 5458c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C3_RES) | 5468c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES) | 5478c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C7_RES) | 5488c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C8_RES) | 5498c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C9_RES) | 5508c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C10_RES), 5518c2ecf20Sopenharmony_ci}; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistatic const struct cstate_model icl_cstates __initconst = { 5548c2ecf20Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C6_RES) | 5558c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_CORE_C7_RES), 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | 5588c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C3_RES) | 5598c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES) | 5608c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C7_RES) | 5618c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C8_RES) | 5628c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C9_RES) | 5638c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C10_RES), 5648c2ecf20Sopenharmony_ci}; 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_cistatic const struct cstate_model slm_cstates __initconst = { 5678c2ecf20Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C1_RES) | 5688c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_CORE_C6_RES), 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C6_RES), 5718c2ecf20Sopenharmony_ci .quirks = SLM_PKG_C6_USE_C7_MSR, 5728c2ecf20Sopenharmony_ci}; 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_cistatic const struct cstate_model knl_cstates __initconst = { 5768c2ecf20Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C6_RES), 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | 5798c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C3_RES) | 5808c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES), 5818c2ecf20Sopenharmony_ci .quirks = KNL_CORE_C6_MSR, 5828c2ecf20Sopenharmony_ci}; 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_cistatic const struct cstate_model glm_cstates __initconst = { 5868c2ecf20Sopenharmony_ci .core_events = BIT(PERF_CSTATE_CORE_C1_RES) | 5878c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_CORE_C3_RES) | 5888c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_CORE_C6_RES), 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | 5918c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C3_RES) | 5928c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C6_RES) | 5938c2ecf20Sopenharmony_ci BIT(PERF_CSTATE_PKG_C10_RES), 5948c2ecf20Sopenharmony_ci}; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cistatic const struct x86_cpu_id intel_cstates_match[] __initconst = { 5988c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(NEHALEM, &nhm_cstates), 5998c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EP, &nhm_cstates), 6008c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EX, &nhm_cstates), 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(WESTMERE, &nhm_cstates), 6038c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EP, &nhm_cstates), 6048c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EX, &nhm_cstates), 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE, &snb_cstates), 6078c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X, &snb_cstates), 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE, &snb_cstates), 6108c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE_X, &snb_cstates), 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(HASWELL, &snb_cstates), 6138c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X, &snb_cstates), 6148c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(HASWELL_G, &snb_cstates), 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(HASWELL_L, &hswult_cstates), 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT, &slm_cstates), 6198c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_D, &slm_cstates), 6208c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT, &slm_cstates), 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(BROADWELL, &snb_cstates), 6238c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_D, &snb_cstates), 6248c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_G, &snb_cstates), 6258c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X, &snb_cstates), 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, &snb_cstates), 6288c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, &snb_cstates), 6298c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X, &snb_cstates), 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, &hswult_cstates), 6328c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, &hswult_cstates), 6338c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE_L, &hswult_cstates), 6348c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, &hswult_cstates), 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(CANNONLAKE_L, &cnl_cstates), 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, &knl_cstates), 6398c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, &knl_cstates), 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, &glm_cstates), 6428c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_D, &glm_cstates), 6438c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS, &glm_cstates), 6448c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D, &glm_cstates), 6458c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT, &glm_cstates), 6468c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L, &glm_cstates), 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, &icl_cstates), 6498c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(ICELAKE, &icl_cstates), 6508c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, &icl_cstates), 6518c2ecf20Sopenharmony_ci X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, &icl_cstates), 6528c2ecf20Sopenharmony_ci { }, 6538c2ecf20Sopenharmony_ci}; 6548c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(x86cpu, intel_cstates_match); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_cistatic int __init cstate_probe(const struct cstate_model *cm) 6578c2ecf20Sopenharmony_ci{ 6588c2ecf20Sopenharmony_ci /* SLM has different MSR for PKG C6 */ 6598c2ecf20Sopenharmony_ci if (cm->quirks & SLM_PKG_C6_USE_C7_MSR) 6608c2ecf20Sopenharmony_ci pkg_msr[PERF_CSTATE_PKG_C6_RES].msr = MSR_PKG_C7_RESIDENCY; 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci /* KNL has different MSR for CORE C6 */ 6638c2ecf20Sopenharmony_ci if (cm->quirks & KNL_CORE_C6_MSR) 6648c2ecf20Sopenharmony_ci pkg_msr[PERF_CSTATE_CORE_C6_RES].msr = MSR_KNL_CORE_C6_RESIDENCY; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci core_msr_mask = perf_msr_probe(core_msr, PERF_CSTATE_CORE_EVENT_MAX, 6688c2ecf20Sopenharmony_ci true, (void *) &cm->core_events); 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci pkg_msr_mask = perf_msr_probe(pkg_msr, PERF_CSTATE_PKG_EVENT_MAX, 6718c2ecf20Sopenharmony_ci true, (void *) &cm->pkg_events); 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci has_cstate_core = !!core_msr_mask; 6748c2ecf20Sopenharmony_ci has_cstate_pkg = !!pkg_msr_mask; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci return (has_cstate_core || has_cstate_pkg) ? 0 : -ENODEV; 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cistatic inline void cstate_cleanup(void) 6808c2ecf20Sopenharmony_ci{ 6818c2ecf20Sopenharmony_ci cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_CSTATE_ONLINE); 6828c2ecf20Sopenharmony_ci cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_CSTATE_STARTING); 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci if (has_cstate_core) 6858c2ecf20Sopenharmony_ci perf_pmu_unregister(&cstate_core_pmu); 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci if (has_cstate_pkg) 6888c2ecf20Sopenharmony_ci perf_pmu_unregister(&cstate_pkg_pmu); 6898c2ecf20Sopenharmony_ci} 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_cistatic int __init cstate_init(void) 6928c2ecf20Sopenharmony_ci{ 6938c2ecf20Sopenharmony_ci int err; 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci cpuhp_setup_state(CPUHP_AP_PERF_X86_CSTATE_STARTING, 6968c2ecf20Sopenharmony_ci "perf/x86/cstate:starting", cstate_cpu_init, NULL); 6978c2ecf20Sopenharmony_ci cpuhp_setup_state(CPUHP_AP_PERF_X86_CSTATE_ONLINE, 6988c2ecf20Sopenharmony_ci "perf/x86/cstate:online", NULL, cstate_cpu_exit); 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci if (has_cstate_core) { 7018c2ecf20Sopenharmony_ci err = perf_pmu_register(&cstate_core_pmu, cstate_core_pmu.name, -1); 7028c2ecf20Sopenharmony_ci if (err) { 7038c2ecf20Sopenharmony_ci has_cstate_core = false; 7048c2ecf20Sopenharmony_ci pr_info("Failed to register cstate core pmu\n"); 7058c2ecf20Sopenharmony_ci cstate_cleanup(); 7068c2ecf20Sopenharmony_ci return err; 7078c2ecf20Sopenharmony_ci } 7088c2ecf20Sopenharmony_ci } 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci if (has_cstate_pkg) { 7118c2ecf20Sopenharmony_ci if (topology_max_die_per_package() > 1) { 7128c2ecf20Sopenharmony_ci err = perf_pmu_register(&cstate_pkg_pmu, 7138c2ecf20Sopenharmony_ci "cstate_die", -1); 7148c2ecf20Sopenharmony_ci } else { 7158c2ecf20Sopenharmony_ci err = perf_pmu_register(&cstate_pkg_pmu, 7168c2ecf20Sopenharmony_ci cstate_pkg_pmu.name, -1); 7178c2ecf20Sopenharmony_ci } 7188c2ecf20Sopenharmony_ci if (err) { 7198c2ecf20Sopenharmony_ci has_cstate_pkg = false; 7208c2ecf20Sopenharmony_ci pr_info("Failed to register cstate pkg pmu\n"); 7218c2ecf20Sopenharmony_ci cstate_cleanup(); 7228c2ecf20Sopenharmony_ci return err; 7238c2ecf20Sopenharmony_ci } 7248c2ecf20Sopenharmony_ci } 7258c2ecf20Sopenharmony_ci return 0; 7268c2ecf20Sopenharmony_ci} 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_cistatic int __init cstate_pmu_init(void) 7298c2ecf20Sopenharmony_ci{ 7308c2ecf20Sopenharmony_ci const struct x86_cpu_id *id; 7318c2ecf20Sopenharmony_ci int err; 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) 7348c2ecf20Sopenharmony_ci return -ENODEV; 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci id = x86_match_cpu(intel_cstates_match); 7378c2ecf20Sopenharmony_ci if (!id) 7388c2ecf20Sopenharmony_ci return -ENODEV; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci err = cstate_probe((const struct cstate_model *) id->driver_data); 7418c2ecf20Sopenharmony_ci if (err) 7428c2ecf20Sopenharmony_ci return err; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci return cstate_init(); 7458c2ecf20Sopenharmony_ci} 7468c2ecf20Sopenharmony_cimodule_init(cstate_pmu_init); 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_cistatic void __exit cstate_pmu_exit(void) 7498c2ecf20Sopenharmony_ci{ 7508c2ecf20Sopenharmony_ci cstate_cleanup(); 7518c2ecf20Sopenharmony_ci} 7528c2ecf20Sopenharmony_cimodule_exit(cstate_pmu_exit); 753