16aec1ad7SBorislav Petkov /* 26aec1ad7SBorislav Petkov * perf_event_intel_cstate.c: support cstate residency counters 36aec1ad7SBorislav Petkov * 46aec1ad7SBorislav Petkov * Copyright (C) 2015, Intel Corp. 56aec1ad7SBorislav Petkov * Author: Kan Liang (kan.liang@intel.com) 66aec1ad7SBorislav Petkov * 76aec1ad7SBorislav Petkov * This library is free software; you can redistribute it and/or 86aec1ad7SBorislav Petkov * modify it under the terms of the GNU Library General Public 96aec1ad7SBorislav Petkov * License as published by the Free Software Foundation; either 106aec1ad7SBorislav Petkov * version 2 of the License, or (at your option) any later version. 116aec1ad7SBorislav Petkov * 126aec1ad7SBorislav Petkov * This library is distributed in the hope that it will be useful, 136aec1ad7SBorislav Petkov * but WITHOUT ANY WARRANTY; without even the implied warranty of 146aec1ad7SBorislav Petkov * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 156aec1ad7SBorislav Petkov * Library General Public License for more details. 166aec1ad7SBorislav Petkov * 176aec1ad7SBorislav Petkov */ 186aec1ad7SBorislav Petkov 196aec1ad7SBorislav Petkov /* 206aec1ad7SBorislav Petkov * This file export cstate related free running (read-only) counters 216aec1ad7SBorislav Petkov * for perf. These counters may be use simultaneously by other tools, 226aec1ad7SBorislav Petkov * such as turbostat. However, it still make sense to implement them 236aec1ad7SBorislav Petkov * in perf. Because we can conveniently collect them together with 246aec1ad7SBorislav Petkov * other events, and allow to use them from tools without special MSR 256aec1ad7SBorislav Petkov * access code. 266aec1ad7SBorislav Petkov * 276aec1ad7SBorislav Petkov * The events only support system-wide mode counting. There is no 286aec1ad7SBorislav Petkov * sampling support because it is not supported by the hardware. 296aec1ad7SBorislav Petkov * 306aec1ad7SBorislav Petkov * According to counters' scope and category, two PMUs are registered 316aec1ad7SBorislav Petkov * with the perf_event core subsystem. 326aec1ad7SBorislav Petkov * - 'cstate_core': The counter is available for each physical core. 336aec1ad7SBorislav Petkov * The counters include CORE_C*_RESIDENCY. 346aec1ad7SBorislav Petkov * - 'cstate_pkg': The counter is available for each physical package. 356aec1ad7SBorislav Petkov * The counters include PKG_C*_RESIDENCY. 366aec1ad7SBorislav Petkov * 376aec1ad7SBorislav Petkov * All of these counters are specified in the Intel® 64 and IA-32 386aec1ad7SBorislav Petkov * Architectures Software Developer.s Manual Vol3b. 396aec1ad7SBorislav Petkov * 406aec1ad7SBorislav Petkov * Model specific counters: 416aec1ad7SBorislav Petkov * MSR_CORE_C1_RES: CORE C1 Residency Counter 426aec1ad7SBorislav Petkov * perf code: 0x00 436aec1ad7SBorislav Petkov * Available model: SLM,AMT 446aec1ad7SBorislav Petkov * Scope: Core (each processor core has a MSR) 456aec1ad7SBorislav Petkov * MSR_CORE_C3_RESIDENCY: CORE C3 Residency Counter 466aec1ad7SBorislav Petkov * perf code: 0x01 476aec1ad7SBorislav Petkov * Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL 486aec1ad7SBorislav Petkov * Scope: Core 496aec1ad7SBorislav Petkov * MSR_CORE_C6_RESIDENCY: CORE C6 Residency Counter 506aec1ad7SBorislav Petkov * perf code: 0x02 516aec1ad7SBorislav Petkov * Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,SKL 526aec1ad7SBorislav Petkov * Scope: Core 536aec1ad7SBorislav Petkov * MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter 546aec1ad7SBorislav Petkov * perf code: 0x03 556aec1ad7SBorislav Petkov * Available model: SNB,IVB,HSW,BDW,SKL 566aec1ad7SBorislav Petkov * Scope: Core 576aec1ad7SBorislav Petkov * MSR_PKG_C2_RESIDENCY: Package C2 Residency Counter. 586aec1ad7SBorislav Petkov * perf code: 0x00 596aec1ad7SBorislav Petkov * Available model: SNB,IVB,HSW,BDW,SKL 606aec1ad7SBorislav Petkov * Scope: Package (physical package) 616aec1ad7SBorislav Petkov * MSR_PKG_C3_RESIDENCY: Package C3 Residency Counter. 626aec1ad7SBorislav Petkov * perf code: 0x01 636aec1ad7SBorislav Petkov * Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL 646aec1ad7SBorislav Petkov * Scope: Package (physical package) 656aec1ad7SBorislav Petkov * MSR_PKG_C6_RESIDENCY: Package C6 Residency Counter. 666aec1ad7SBorislav Petkov * perf code: 0x02 676aec1ad7SBorislav Petkov * Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,SKL 686aec1ad7SBorislav Petkov * Scope: Package (physical package) 696aec1ad7SBorislav Petkov * MSR_PKG_C7_RESIDENCY: Package C7 Residency Counter. 706aec1ad7SBorislav Petkov * perf code: 0x03 716aec1ad7SBorislav Petkov * Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL 726aec1ad7SBorislav Petkov * Scope: Package (physical package) 736aec1ad7SBorislav Petkov * MSR_PKG_C8_RESIDENCY: Package C8 Residency Counter. 746aec1ad7SBorislav Petkov * perf code: 0x04 756aec1ad7SBorislav Petkov * Available model: HSW ULT only 766aec1ad7SBorislav Petkov * Scope: Package (physical package) 776aec1ad7SBorislav Petkov * MSR_PKG_C9_RESIDENCY: Package C9 Residency Counter. 786aec1ad7SBorislav Petkov * perf code: 0x05 796aec1ad7SBorislav Petkov * Available model: HSW ULT only 806aec1ad7SBorislav Petkov * Scope: Package (physical package) 816aec1ad7SBorislav Petkov * MSR_PKG_C10_RESIDENCY: Package C10 Residency Counter. 826aec1ad7SBorislav Petkov * perf code: 0x06 836aec1ad7SBorislav Petkov * Available model: HSW ULT only 846aec1ad7SBorislav Petkov * Scope: Package (physical package) 856aec1ad7SBorislav Petkov * 866aec1ad7SBorislav Petkov */ 876aec1ad7SBorislav Petkov 886aec1ad7SBorislav Petkov #include <linux/module.h> 896aec1ad7SBorislav Petkov #include <linux/slab.h> 906aec1ad7SBorislav Petkov #include <linux/perf_event.h> 916aec1ad7SBorislav Petkov #include <asm/cpu_device_id.h> 9227f6d22bSBorislav Petkov #include "../perf_event.h" 936aec1ad7SBorislav Petkov 946aec1ad7SBorislav Petkov #define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format) \ 956aec1ad7SBorislav Petkov static ssize_t __cstate_##_var##_show(struct kobject *kobj, \ 966aec1ad7SBorislav Petkov struct kobj_attribute *attr, \ 976aec1ad7SBorislav Petkov char *page) \ 986aec1ad7SBorislav Petkov { \ 996aec1ad7SBorislav Petkov BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ 1006aec1ad7SBorislav Petkov return sprintf(page, _format "\n"); \ 1016aec1ad7SBorislav Petkov } \ 1026aec1ad7SBorislav Petkov static struct kobj_attribute format_attr_##_var = \ 1036aec1ad7SBorislav Petkov __ATTR(_name, 0444, __cstate_##_var##_show, NULL) 1046aec1ad7SBorislav Petkov 1056aec1ad7SBorislav Petkov static ssize_t cstate_get_attr_cpumask(struct device *dev, 1066aec1ad7SBorislav Petkov struct device_attribute *attr, 1076aec1ad7SBorislav Petkov char *buf); 1086aec1ad7SBorislav Petkov 1096aec1ad7SBorislav Petkov struct perf_cstate_msr { 1106aec1ad7SBorislav Petkov u64 msr; 1116aec1ad7SBorislav Petkov struct perf_pmu_events_attr *attr; 1126aec1ad7SBorislav Petkov bool (*test)(int idx); 1136aec1ad7SBorislav Petkov }; 1146aec1ad7SBorislav Petkov 1156aec1ad7SBorislav Petkov 1166aec1ad7SBorislav Petkov /* cstate_core PMU */ 1176aec1ad7SBorislav Petkov 1186aec1ad7SBorislav Petkov static struct pmu cstate_core_pmu; 1196aec1ad7SBorislav Petkov static bool has_cstate_core; 1206aec1ad7SBorislav Petkov 1216aec1ad7SBorislav Petkov enum perf_cstate_core_id { 1226aec1ad7SBorislav Petkov /* 1236aec1ad7SBorislav Petkov * cstate_core events 1246aec1ad7SBorislav Petkov */ 1256aec1ad7SBorislav Petkov PERF_CSTATE_CORE_C1_RES = 0, 1266aec1ad7SBorislav Petkov PERF_CSTATE_CORE_C3_RES, 1276aec1ad7SBorislav Petkov PERF_CSTATE_CORE_C6_RES, 1286aec1ad7SBorislav Petkov PERF_CSTATE_CORE_C7_RES, 1296aec1ad7SBorislav Petkov 1306aec1ad7SBorislav Petkov PERF_CSTATE_CORE_EVENT_MAX, 1316aec1ad7SBorislav Petkov }; 1326aec1ad7SBorislav Petkov 1336aec1ad7SBorislav Petkov bool test_core(int idx) 1346aec1ad7SBorislav Petkov { 1356aec1ad7SBorislav Petkov if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || 1366aec1ad7SBorislav Petkov boot_cpu_data.x86 != 6) 1376aec1ad7SBorislav Petkov return false; 1386aec1ad7SBorislav Petkov 1396aec1ad7SBorislav Petkov switch (boot_cpu_data.x86_model) { 1406aec1ad7SBorislav Petkov case 30: /* 45nm Nehalem */ 1416aec1ad7SBorislav Petkov case 26: /* 45nm Nehalem-EP */ 1426aec1ad7SBorislav Petkov case 46: /* 45nm Nehalem-EX */ 1436aec1ad7SBorislav Petkov 1446aec1ad7SBorislav Petkov case 37: /* 32nm Westmere */ 1456aec1ad7SBorislav Petkov case 44: /* 32nm Westmere-EP */ 1466aec1ad7SBorislav Petkov case 47: /* 32nm Westmere-EX */ 1476aec1ad7SBorislav Petkov if (idx == PERF_CSTATE_CORE_C3_RES || 1486aec1ad7SBorislav Petkov idx == PERF_CSTATE_CORE_C6_RES) 1496aec1ad7SBorislav Petkov return true; 1506aec1ad7SBorislav Petkov break; 1516aec1ad7SBorislav Petkov case 42: /* 32nm SandyBridge */ 1526aec1ad7SBorislav Petkov case 45: /* 32nm SandyBridge-E/EN/EP */ 1536aec1ad7SBorislav Petkov 1546aec1ad7SBorislav Petkov case 58: /* 22nm IvyBridge */ 1556aec1ad7SBorislav Petkov case 62: /* 22nm IvyBridge-EP/EX */ 1566aec1ad7SBorislav Petkov 1576aec1ad7SBorislav Petkov case 60: /* 22nm Haswell Core */ 1586aec1ad7SBorislav Petkov case 63: /* 22nm Haswell Server */ 1596aec1ad7SBorislav Petkov case 69: /* 22nm Haswell ULT */ 1606aec1ad7SBorislav Petkov case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */ 1616aec1ad7SBorislav Petkov 1626aec1ad7SBorislav Petkov case 61: /* 14nm Broadwell Core-M */ 1636aec1ad7SBorislav Petkov case 86: /* 14nm Broadwell Xeon D */ 1646aec1ad7SBorislav Petkov case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */ 1656aec1ad7SBorislav Petkov case 79: /* 14nm Broadwell Server */ 1666aec1ad7SBorislav Petkov 1676aec1ad7SBorislav Petkov case 78: /* 14nm Skylake Mobile */ 1686aec1ad7SBorislav Petkov case 94: /* 14nm Skylake Desktop */ 1696aec1ad7SBorislav Petkov if (idx == PERF_CSTATE_CORE_C3_RES || 1706aec1ad7SBorislav Petkov idx == PERF_CSTATE_CORE_C6_RES || 1716aec1ad7SBorislav Petkov idx == PERF_CSTATE_CORE_C7_RES) 1726aec1ad7SBorislav Petkov return true; 1736aec1ad7SBorislav Petkov break; 1746aec1ad7SBorislav Petkov case 55: /* 22nm Atom "Silvermont" */ 1756aec1ad7SBorislav Petkov case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */ 1766aec1ad7SBorislav Petkov case 76: /* 14nm Atom "Airmont" */ 1776aec1ad7SBorislav Petkov if (idx == PERF_CSTATE_CORE_C1_RES || 1786aec1ad7SBorislav Petkov idx == PERF_CSTATE_CORE_C6_RES) 1796aec1ad7SBorislav Petkov return true; 1806aec1ad7SBorislav Petkov break; 1816aec1ad7SBorislav Petkov } 1826aec1ad7SBorislav Petkov 1836aec1ad7SBorislav Petkov return false; 1846aec1ad7SBorislav Petkov } 1856aec1ad7SBorislav Petkov 1866aec1ad7SBorislav Petkov PMU_EVENT_ATTR_STRING(c1-residency, evattr_cstate_core_c1, "event=0x00"); 1876aec1ad7SBorislav Petkov PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_core_c3, "event=0x01"); 1886aec1ad7SBorislav Petkov PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_core_c6, "event=0x02"); 1896aec1ad7SBorislav Petkov PMU_EVENT_ATTR_STRING(c7-residency, evattr_cstate_core_c7, "event=0x03"); 1906aec1ad7SBorislav Petkov 1916aec1ad7SBorislav Petkov static struct perf_cstate_msr core_msr[] = { 1926aec1ad7SBorislav Petkov [PERF_CSTATE_CORE_C1_RES] = { MSR_CORE_C1_RES, &evattr_cstate_core_c1, test_core, }, 1936aec1ad7SBorislav Petkov [PERF_CSTATE_CORE_C3_RES] = { MSR_CORE_C3_RESIDENCY, &evattr_cstate_core_c3, test_core, }, 1946aec1ad7SBorislav Petkov [PERF_CSTATE_CORE_C6_RES] = { MSR_CORE_C6_RESIDENCY, &evattr_cstate_core_c6, test_core, }, 1956aec1ad7SBorislav Petkov [PERF_CSTATE_CORE_C7_RES] = { MSR_CORE_C7_RESIDENCY, &evattr_cstate_core_c7, test_core, }, 1966aec1ad7SBorislav Petkov }; 1976aec1ad7SBorislav Petkov 1986aec1ad7SBorislav Petkov static struct attribute *core_events_attrs[PERF_CSTATE_CORE_EVENT_MAX + 1] = { 1996aec1ad7SBorislav Petkov NULL, 2006aec1ad7SBorislav Petkov }; 2016aec1ad7SBorislav Petkov 2026aec1ad7SBorislav Petkov static struct attribute_group core_events_attr_group = { 2036aec1ad7SBorislav Petkov .name = "events", 2046aec1ad7SBorislav Petkov .attrs = core_events_attrs, 2056aec1ad7SBorislav Petkov }; 2066aec1ad7SBorislav Petkov 2076aec1ad7SBorislav Petkov DEFINE_CSTATE_FORMAT_ATTR(core_event, event, "config:0-63"); 2086aec1ad7SBorislav Petkov static struct attribute *core_format_attrs[] = { 2096aec1ad7SBorislav Petkov &format_attr_core_event.attr, 2106aec1ad7SBorislav Petkov NULL, 2116aec1ad7SBorislav Petkov }; 2126aec1ad7SBorislav Petkov 2136aec1ad7SBorislav Petkov static struct attribute_group core_format_attr_group = { 2146aec1ad7SBorislav Petkov .name = "format", 2156aec1ad7SBorislav Petkov .attrs = core_format_attrs, 2166aec1ad7SBorislav Petkov }; 2176aec1ad7SBorislav Petkov 2186aec1ad7SBorislav Petkov static cpumask_t cstate_core_cpu_mask; 2196aec1ad7SBorislav Petkov static DEVICE_ATTR(cpumask, S_IRUGO, cstate_get_attr_cpumask, NULL); 2206aec1ad7SBorislav Petkov 2216aec1ad7SBorislav Petkov static struct attribute *cstate_cpumask_attrs[] = { 2226aec1ad7SBorislav Petkov &dev_attr_cpumask.attr, 2236aec1ad7SBorislav Petkov NULL, 2246aec1ad7SBorislav Petkov }; 2256aec1ad7SBorislav Petkov 2266aec1ad7SBorislav Petkov static struct attribute_group cpumask_attr_group = { 2276aec1ad7SBorislav Petkov .attrs = cstate_cpumask_attrs, 2286aec1ad7SBorislav Petkov }; 2296aec1ad7SBorislav Petkov 2306aec1ad7SBorislav Petkov static const struct attribute_group *core_attr_groups[] = { 2316aec1ad7SBorislav Petkov &core_events_attr_group, 2326aec1ad7SBorislav Petkov &core_format_attr_group, 2336aec1ad7SBorislav Petkov &cpumask_attr_group, 2346aec1ad7SBorislav Petkov NULL, 2356aec1ad7SBorislav Petkov }; 2366aec1ad7SBorislav Petkov 2376aec1ad7SBorislav Petkov /* cstate_core PMU end */ 2386aec1ad7SBorislav Petkov 2396aec1ad7SBorislav Petkov 2406aec1ad7SBorislav Petkov /* cstate_pkg PMU */ 2416aec1ad7SBorislav Petkov 2426aec1ad7SBorislav Petkov static struct pmu cstate_pkg_pmu; 2436aec1ad7SBorislav Petkov static bool has_cstate_pkg; 2446aec1ad7SBorislav Petkov 2456aec1ad7SBorislav Petkov enum perf_cstate_pkg_id { 2466aec1ad7SBorislav Petkov /* 2476aec1ad7SBorislav Petkov * cstate_pkg events 2486aec1ad7SBorislav Petkov */ 2496aec1ad7SBorislav Petkov PERF_CSTATE_PKG_C2_RES = 0, 2506aec1ad7SBorislav Petkov PERF_CSTATE_PKG_C3_RES, 2516aec1ad7SBorislav Petkov PERF_CSTATE_PKG_C6_RES, 2526aec1ad7SBorislav Petkov PERF_CSTATE_PKG_C7_RES, 2536aec1ad7SBorislav Petkov PERF_CSTATE_PKG_C8_RES, 2546aec1ad7SBorislav Petkov PERF_CSTATE_PKG_C9_RES, 2556aec1ad7SBorislav Petkov PERF_CSTATE_PKG_C10_RES, 2566aec1ad7SBorislav Petkov 2576aec1ad7SBorislav Petkov PERF_CSTATE_PKG_EVENT_MAX, 2586aec1ad7SBorislav Petkov }; 2596aec1ad7SBorislav Petkov 2606aec1ad7SBorislav Petkov bool test_pkg(int idx) 2616aec1ad7SBorislav Petkov { 2626aec1ad7SBorislav Petkov if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || 2636aec1ad7SBorislav Petkov boot_cpu_data.x86 != 6) 2646aec1ad7SBorislav Petkov return false; 2656aec1ad7SBorislav Petkov 2666aec1ad7SBorislav Petkov switch (boot_cpu_data.x86_model) { 2676aec1ad7SBorislav Petkov case 30: /* 45nm Nehalem */ 2686aec1ad7SBorislav Petkov case 26: /* 45nm Nehalem-EP */ 2696aec1ad7SBorislav Petkov case 46: /* 45nm Nehalem-EX */ 2706aec1ad7SBorislav Petkov 2716aec1ad7SBorislav Petkov case 37: /* 32nm Westmere */ 2726aec1ad7SBorislav Petkov case 44: /* 32nm Westmere-EP */ 2736aec1ad7SBorislav Petkov case 47: /* 32nm Westmere-EX */ 2746aec1ad7SBorislav Petkov if (idx == PERF_CSTATE_CORE_C3_RES || 2756aec1ad7SBorislav Petkov idx == PERF_CSTATE_CORE_C6_RES || 2766aec1ad7SBorislav Petkov idx == PERF_CSTATE_CORE_C7_RES) 2776aec1ad7SBorislav Petkov return true; 2786aec1ad7SBorislav Petkov break; 2796aec1ad7SBorislav Petkov case 42: /* 32nm SandyBridge */ 2806aec1ad7SBorislav Petkov case 45: /* 32nm SandyBridge-E/EN/EP */ 2816aec1ad7SBorislav Petkov 2826aec1ad7SBorislav Petkov case 58: /* 22nm IvyBridge */ 2836aec1ad7SBorislav Petkov case 62: /* 22nm IvyBridge-EP/EX */ 2846aec1ad7SBorislav Petkov 2856aec1ad7SBorislav Petkov case 60: /* 22nm Haswell Core */ 2866aec1ad7SBorislav Petkov case 63: /* 22nm Haswell Server */ 2876aec1ad7SBorislav Petkov case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */ 2886aec1ad7SBorislav Petkov 2896aec1ad7SBorislav Petkov case 61: /* 14nm Broadwell Core-M */ 2906aec1ad7SBorislav Petkov case 86: /* 14nm Broadwell Xeon D */ 2916aec1ad7SBorislav Petkov case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */ 2926aec1ad7SBorislav Petkov case 79: /* 14nm Broadwell Server */ 2936aec1ad7SBorislav Petkov 2946aec1ad7SBorislav Petkov case 78: /* 14nm Skylake Mobile */ 2956aec1ad7SBorislav Petkov case 94: /* 14nm Skylake Desktop */ 2966aec1ad7SBorislav Petkov if (idx == PERF_CSTATE_PKG_C2_RES || 2976aec1ad7SBorislav Petkov idx == PERF_CSTATE_PKG_C3_RES || 2986aec1ad7SBorislav Petkov idx == PERF_CSTATE_PKG_C6_RES || 2996aec1ad7SBorislav Petkov idx == PERF_CSTATE_PKG_C7_RES) 3006aec1ad7SBorislav Petkov return true; 3016aec1ad7SBorislav Petkov break; 3026aec1ad7SBorislav Petkov case 55: /* 22nm Atom "Silvermont" */ 3036aec1ad7SBorislav Petkov case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */ 3046aec1ad7SBorislav Petkov case 76: /* 14nm Atom "Airmont" */ 3056aec1ad7SBorislav Petkov if (idx == PERF_CSTATE_CORE_C6_RES) 3066aec1ad7SBorislav Petkov return true; 3076aec1ad7SBorislav Petkov break; 3086aec1ad7SBorislav Petkov case 69: /* 22nm Haswell ULT */ 3096aec1ad7SBorislav Petkov if (idx == PERF_CSTATE_PKG_C2_RES || 3106aec1ad7SBorislav Petkov idx == PERF_CSTATE_PKG_C3_RES || 3116aec1ad7SBorislav Petkov idx == PERF_CSTATE_PKG_C6_RES || 3126aec1ad7SBorislav Petkov idx == PERF_CSTATE_PKG_C7_RES || 3136aec1ad7SBorislav Petkov idx == PERF_CSTATE_PKG_C8_RES || 3146aec1ad7SBorislav Petkov idx == PERF_CSTATE_PKG_C9_RES || 3156aec1ad7SBorislav Petkov idx == PERF_CSTATE_PKG_C10_RES) 3166aec1ad7SBorislav Petkov return true; 3176aec1ad7SBorislav Petkov break; 3186aec1ad7SBorislav Petkov } 3196aec1ad7SBorislav Petkov 3206aec1ad7SBorislav Petkov return false; 3216aec1ad7SBorislav Petkov } 3226aec1ad7SBorislav Petkov 3236aec1ad7SBorislav Petkov PMU_EVENT_ATTR_STRING(c2-residency, evattr_cstate_pkg_c2, "event=0x00"); 3246aec1ad7SBorislav Petkov PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_pkg_c3, "event=0x01"); 3256aec1ad7SBorislav Petkov PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_pkg_c6, "event=0x02"); 3266aec1ad7SBorislav Petkov PMU_EVENT_ATTR_STRING(c7-residency, evattr_cstate_pkg_c7, "event=0x03"); 3276aec1ad7SBorislav Petkov PMU_EVENT_ATTR_STRING(c8-residency, evattr_cstate_pkg_c8, "event=0x04"); 3286aec1ad7SBorislav Petkov PMU_EVENT_ATTR_STRING(c9-residency, evattr_cstate_pkg_c9, "event=0x05"); 3296aec1ad7SBorislav Petkov PMU_EVENT_ATTR_STRING(c10-residency, evattr_cstate_pkg_c10, "event=0x06"); 3306aec1ad7SBorislav Petkov 3316aec1ad7SBorislav Petkov static struct perf_cstate_msr pkg_msr[] = { 3326aec1ad7SBorislav Petkov [PERF_CSTATE_PKG_C2_RES] = { MSR_PKG_C2_RESIDENCY, &evattr_cstate_pkg_c2, test_pkg, }, 3336aec1ad7SBorislav Petkov [PERF_CSTATE_PKG_C3_RES] = { MSR_PKG_C3_RESIDENCY, &evattr_cstate_pkg_c3, test_pkg, }, 3346aec1ad7SBorislav Petkov [PERF_CSTATE_PKG_C6_RES] = { MSR_PKG_C6_RESIDENCY, &evattr_cstate_pkg_c6, test_pkg, }, 3356aec1ad7SBorislav Petkov [PERF_CSTATE_PKG_C7_RES] = { MSR_PKG_C7_RESIDENCY, &evattr_cstate_pkg_c7, test_pkg, }, 3366aec1ad7SBorislav Petkov [PERF_CSTATE_PKG_C8_RES] = { MSR_PKG_C8_RESIDENCY, &evattr_cstate_pkg_c8, test_pkg, }, 3376aec1ad7SBorislav Petkov [PERF_CSTATE_PKG_C9_RES] = { MSR_PKG_C9_RESIDENCY, &evattr_cstate_pkg_c9, test_pkg, }, 3386aec1ad7SBorislav Petkov [PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY, &evattr_cstate_pkg_c10, test_pkg, }, 3396aec1ad7SBorislav Petkov }; 3406aec1ad7SBorislav Petkov 3416aec1ad7SBorislav Petkov static struct attribute *pkg_events_attrs[PERF_CSTATE_PKG_EVENT_MAX + 1] = { 3426aec1ad7SBorislav Petkov NULL, 3436aec1ad7SBorislav Petkov }; 3446aec1ad7SBorislav Petkov 3456aec1ad7SBorislav Petkov static struct attribute_group pkg_events_attr_group = { 3466aec1ad7SBorislav Petkov .name = "events", 3476aec1ad7SBorislav Petkov .attrs = pkg_events_attrs, 3486aec1ad7SBorislav Petkov }; 3496aec1ad7SBorislav Petkov 3506aec1ad7SBorislav Petkov DEFINE_CSTATE_FORMAT_ATTR(pkg_event, event, "config:0-63"); 3516aec1ad7SBorislav Petkov static struct attribute *pkg_format_attrs[] = { 3526aec1ad7SBorislav Petkov &format_attr_pkg_event.attr, 3536aec1ad7SBorislav Petkov NULL, 3546aec1ad7SBorislav Petkov }; 3556aec1ad7SBorislav Petkov static struct attribute_group pkg_format_attr_group = { 3566aec1ad7SBorislav Petkov .name = "format", 3576aec1ad7SBorislav Petkov .attrs = pkg_format_attrs, 3586aec1ad7SBorislav Petkov }; 3596aec1ad7SBorislav Petkov 3606aec1ad7SBorislav Petkov static cpumask_t cstate_pkg_cpu_mask; 3616aec1ad7SBorislav Petkov 3626aec1ad7SBorislav Petkov static const struct attribute_group *pkg_attr_groups[] = { 3636aec1ad7SBorislav Petkov &pkg_events_attr_group, 3646aec1ad7SBorislav Petkov &pkg_format_attr_group, 3656aec1ad7SBorislav Petkov &cpumask_attr_group, 3666aec1ad7SBorislav Petkov NULL, 3676aec1ad7SBorislav Petkov }; 3686aec1ad7SBorislav Petkov 3696aec1ad7SBorislav Petkov /* cstate_pkg PMU end*/ 3706aec1ad7SBorislav Petkov 3716aec1ad7SBorislav Petkov static ssize_t cstate_get_attr_cpumask(struct device *dev, 3726aec1ad7SBorislav Petkov struct device_attribute *attr, 3736aec1ad7SBorislav Petkov char *buf) 3746aec1ad7SBorislav Petkov { 3756aec1ad7SBorislav Petkov struct pmu *pmu = dev_get_drvdata(dev); 3766aec1ad7SBorislav Petkov 3776aec1ad7SBorislav Petkov if (pmu == &cstate_core_pmu) 3786aec1ad7SBorislav Petkov return cpumap_print_to_pagebuf(true, buf, &cstate_core_cpu_mask); 3796aec1ad7SBorislav Petkov else if (pmu == &cstate_pkg_pmu) 3806aec1ad7SBorislav Petkov return cpumap_print_to_pagebuf(true, buf, &cstate_pkg_cpu_mask); 3816aec1ad7SBorislav Petkov else 3826aec1ad7SBorislav Petkov return 0; 3836aec1ad7SBorislav Petkov } 3846aec1ad7SBorislav Petkov 3856aec1ad7SBorislav Petkov static int cstate_pmu_event_init(struct perf_event *event) 3866aec1ad7SBorislav Petkov { 3876aec1ad7SBorislav Petkov u64 cfg = event->attr.config; 3886aec1ad7SBorislav Petkov int ret = 0; 3896aec1ad7SBorislav Petkov 3906aec1ad7SBorislav Petkov if (event->attr.type != event->pmu->type) 3916aec1ad7SBorislav Petkov return -ENOENT; 3926aec1ad7SBorislav Petkov 3936aec1ad7SBorislav Petkov /* unsupported modes and filters */ 3946aec1ad7SBorislav Petkov if (event->attr.exclude_user || 3956aec1ad7SBorislav Petkov event->attr.exclude_kernel || 3966aec1ad7SBorislav Petkov event->attr.exclude_hv || 3976aec1ad7SBorislav Petkov event->attr.exclude_idle || 3986aec1ad7SBorislav Petkov event->attr.exclude_host || 3996aec1ad7SBorislav Petkov event->attr.exclude_guest || 4006aec1ad7SBorislav Petkov event->attr.sample_period) /* no sampling */ 4016aec1ad7SBorislav Petkov return -EINVAL; 4026aec1ad7SBorislav Petkov 4036aec1ad7SBorislav Petkov if (event->pmu == &cstate_core_pmu) { 4046aec1ad7SBorislav Petkov if (cfg >= PERF_CSTATE_CORE_EVENT_MAX) 4056aec1ad7SBorislav Petkov return -EINVAL; 4066aec1ad7SBorislav Petkov if (!core_msr[cfg].attr) 4076aec1ad7SBorislav Petkov return -EINVAL; 4086aec1ad7SBorislav Petkov event->hw.event_base = core_msr[cfg].msr; 4096aec1ad7SBorislav Petkov } else if (event->pmu == &cstate_pkg_pmu) { 4106aec1ad7SBorislav Petkov if (cfg >= PERF_CSTATE_PKG_EVENT_MAX) 4116aec1ad7SBorislav Petkov return -EINVAL; 4126aec1ad7SBorislav Petkov if (!pkg_msr[cfg].attr) 4136aec1ad7SBorislav Petkov return -EINVAL; 4146aec1ad7SBorislav Petkov event->hw.event_base = pkg_msr[cfg].msr; 4156aec1ad7SBorislav Petkov } else 4166aec1ad7SBorislav Petkov return -ENOENT; 4176aec1ad7SBorislav Petkov 4186aec1ad7SBorislav Petkov /* must be done before validate_group */ 4196aec1ad7SBorislav Petkov event->hw.config = cfg; 4206aec1ad7SBorislav Petkov event->hw.idx = -1; 4216aec1ad7SBorislav Petkov 4226aec1ad7SBorislav Petkov return ret; 4236aec1ad7SBorislav Petkov } 4246aec1ad7SBorislav Petkov 4256aec1ad7SBorislav Petkov static inline u64 cstate_pmu_read_counter(struct perf_event *event) 4266aec1ad7SBorislav Petkov { 4276aec1ad7SBorislav Petkov u64 val; 4286aec1ad7SBorislav Petkov 4296aec1ad7SBorislav Petkov rdmsrl(event->hw.event_base, val); 4306aec1ad7SBorislav Petkov return val; 4316aec1ad7SBorislav Petkov } 4326aec1ad7SBorislav Petkov 4336aec1ad7SBorislav Petkov static void cstate_pmu_event_update(struct perf_event *event) 4346aec1ad7SBorislav Petkov { 4356aec1ad7SBorislav Petkov struct hw_perf_event *hwc = &event->hw; 4366aec1ad7SBorislav Petkov u64 prev_raw_count, new_raw_count; 4376aec1ad7SBorislav Petkov 4386aec1ad7SBorislav Petkov again: 4396aec1ad7SBorislav Petkov prev_raw_count = local64_read(&hwc->prev_count); 4406aec1ad7SBorislav Petkov new_raw_count = cstate_pmu_read_counter(event); 4416aec1ad7SBorislav Petkov 4426aec1ad7SBorislav Petkov if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, 4436aec1ad7SBorislav Petkov new_raw_count) != prev_raw_count) 4446aec1ad7SBorislav Petkov goto again; 4456aec1ad7SBorislav Petkov 4466aec1ad7SBorislav Petkov local64_add(new_raw_count - prev_raw_count, &event->count); 4476aec1ad7SBorislav Petkov } 4486aec1ad7SBorislav Petkov 4496aec1ad7SBorislav Petkov static void cstate_pmu_event_start(struct perf_event *event, int mode) 4506aec1ad7SBorislav Petkov { 4516aec1ad7SBorislav Petkov local64_set(&event->hw.prev_count, cstate_pmu_read_counter(event)); 4526aec1ad7SBorislav Petkov } 4536aec1ad7SBorislav Petkov 4546aec1ad7SBorislav Petkov static void cstate_pmu_event_stop(struct perf_event *event, int mode) 4556aec1ad7SBorislav Petkov { 4566aec1ad7SBorislav Petkov cstate_pmu_event_update(event); 4576aec1ad7SBorislav Petkov } 4586aec1ad7SBorislav Petkov 4596aec1ad7SBorislav Petkov static void cstate_pmu_event_del(struct perf_event *event, int mode) 4606aec1ad7SBorislav Petkov { 4616aec1ad7SBorislav Petkov cstate_pmu_event_stop(event, PERF_EF_UPDATE); 4626aec1ad7SBorislav Petkov } 4636aec1ad7SBorislav Petkov 4646aec1ad7SBorislav Petkov static int cstate_pmu_event_add(struct perf_event *event, int mode) 4656aec1ad7SBorislav Petkov { 4666aec1ad7SBorislav Petkov if (mode & PERF_EF_START) 4676aec1ad7SBorislav Petkov cstate_pmu_event_start(event, mode); 4686aec1ad7SBorislav Petkov 4696aec1ad7SBorislav Petkov return 0; 4706aec1ad7SBorislav Petkov } 4716aec1ad7SBorislav Petkov 4726aec1ad7SBorislav Petkov static void cstate_cpu_exit(int cpu) 4736aec1ad7SBorislav Petkov { 4746aec1ad7SBorislav Petkov int i, id, target; 4756aec1ad7SBorislav Petkov 4766aec1ad7SBorislav Petkov /* cpu exit for cstate core */ 4776aec1ad7SBorislav Petkov if (has_cstate_core) { 4786aec1ad7SBorislav Petkov id = topology_core_id(cpu); 4796aec1ad7SBorislav Petkov target = -1; 4806aec1ad7SBorislav Petkov 4816aec1ad7SBorislav Petkov for_each_online_cpu(i) { 4826aec1ad7SBorislav Petkov if (i == cpu) 4836aec1ad7SBorislav Petkov continue; 4846aec1ad7SBorislav Petkov if (id == topology_core_id(i)) { 4856aec1ad7SBorislav Petkov target = i; 4866aec1ad7SBorislav Petkov break; 4876aec1ad7SBorislav Petkov } 4886aec1ad7SBorislav Petkov } 4896aec1ad7SBorislav Petkov if (cpumask_test_and_clear_cpu(cpu, &cstate_core_cpu_mask) && target >= 0) 4906aec1ad7SBorislav Petkov cpumask_set_cpu(target, &cstate_core_cpu_mask); 4916aec1ad7SBorislav Petkov WARN_ON(cpumask_empty(&cstate_core_cpu_mask)); 4926aec1ad7SBorislav Petkov if (target >= 0) 4936aec1ad7SBorislav Petkov perf_pmu_migrate_context(&cstate_core_pmu, cpu, target); 4946aec1ad7SBorislav Petkov } 4956aec1ad7SBorislav Petkov 4966aec1ad7SBorislav Petkov /* cpu exit for cstate pkg */ 4976aec1ad7SBorislav Petkov if (has_cstate_pkg) { 4986aec1ad7SBorislav Petkov id = topology_physical_package_id(cpu); 4996aec1ad7SBorislav Petkov target = -1; 5006aec1ad7SBorislav Petkov 5016aec1ad7SBorislav Petkov for_each_online_cpu(i) { 5026aec1ad7SBorislav Petkov if (i == cpu) 5036aec1ad7SBorislav Petkov continue; 5046aec1ad7SBorislav Petkov if (id == topology_physical_package_id(i)) { 5056aec1ad7SBorislav Petkov target = i; 5066aec1ad7SBorislav Petkov break; 5076aec1ad7SBorislav Petkov } 5086aec1ad7SBorislav Petkov } 5096aec1ad7SBorislav Petkov if (cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask) && target >= 0) 5106aec1ad7SBorislav Petkov cpumask_set_cpu(target, &cstate_pkg_cpu_mask); 5116aec1ad7SBorislav Petkov WARN_ON(cpumask_empty(&cstate_pkg_cpu_mask)); 5126aec1ad7SBorislav Petkov if (target >= 0) 5136aec1ad7SBorislav Petkov perf_pmu_migrate_context(&cstate_pkg_pmu, cpu, target); 5146aec1ad7SBorislav Petkov } 5156aec1ad7SBorislav Petkov } 5166aec1ad7SBorislav Petkov 5176aec1ad7SBorislav Petkov static void cstate_cpu_init(int cpu) 5186aec1ad7SBorislav Petkov { 5196aec1ad7SBorislav Petkov int i, id; 5206aec1ad7SBorislav Petkov 5216aec1ad7SBorislav Petkov /* cpu init for cstate core */ 5226aec1ad7SBorislav Petkov if (has_cstate_core) { 5236aec1ad7SBorislav Petkov id = topology_core_id(cpu); 5246aec1ad7SBorislav Petkov for_each_cpu(i, &cstate_core_cpu_mask) { 5256aec1ad7SBorislav Petkov if (id == topology_core_id(i)) 5266aec1ad7SBorislav Petkov break; 5276aec1ad7SBorislav Petkov } 5286aec1ad7SBorislav Petkov if (i >= nr_cpu_ids) 5296aec1ad7SBorislav Petkov cpumask_set_cpu(cpu, &cstate_core_cpu_mask); 5306aec1ad7SBorislav Petkov } 5316aec1ad7SBorislav Petkov 5326aec1ad7SBorislav Petkov /* cpu init for cstate pkg */ 5336aec1ad7SBorislav Petkov if (has_cstate_pkg) { 5346aec1ad7SBorislav Petkov id = topology_physical_package_id(cpu); 5356aec1ad7SBorislav Petkov for_each_cpu(i, &cstate_pkg_cpu_mask) { 5366aec1ad7SBorislav Petkov if (id == topology_physical_package_id(i)) 5376aec1ad7SBorislav Petkov break; 5386aec1ad7SBorislav Petkov } 5396aec1ad7SBorislav Petkov if (i >= nr_cpu_ids) 5406aec1ad7SBorislav Petkov cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask); 5416aec1ad7SBorislav Petkov } 5426aec1ad7SBorislav Petkov } 5436aec1ad7SBorislav Petkov 5446aec1ad7SBorislav Petkov static int cstate_cpu_notifier(struct notifier_block *self, 5456aec1ad7SBorislav Petkov unsigned long action, void *hcpu) 5466aec1ad7SBorislav Petkov { 5476aec1ad7SBorislav Petkov unsigned int cpu = (long)hcpu; 5486aec1ad7SBorislav Petkov 5496aec1ad7SBorislav Petkov switch (action & ~CPU_TASKS_FROZEN) { 5506aec1ad7SBorislav Petkov case CPU_UP_PREPARE: 5516aec1ad7SBorislav Petkov break; 5526aec1ad7SBorislav Petkov case CPU_STARTING: 5536aec1ad7SBorislav Petkov cstate_cpu_init(cpu); 5546aec1ad7SBorislav Petkov break; 5556aec1ad7SBorislav Petkov case CPU_UP_CANCELED: 5566aec1ad7SBorislav Petkov case CPU_DYING: 5576aec1ad7SBorislav Petkov break; 5586aec1ad7SBorislav Petkov case CPU_ONLINE: 5596aec1ad7SBorislav Petkov case CPU_DEAD: 5606aec1ad7SBorislav Petkov break; 5616aec1ad7SBorislav Petkov case CPU_DOWN_PREPARE: 5626aec1ad7SBorislav Petkov cstate_cpu_exit(cpu); 5636aec1ad7SBorislav Petkov break; 5646aec1ad7SBorislav Petkov default: 5656aec1ad7SBorislav Petkov break; 5666aec1ad7SBorislav Petkov } 5676aec1ad7SBorislav Petkov 5686aec1ad7SBorislav Petkov return NOTIFY_OK; 5696aec1ad7SBorislav Petkov } 5706aec1ad7SBorislav Petkov 5716aec1ad7SBorislav Petkov /* 5726aec1ad7SBorislav Petkov * Probe the cstate events and insert the available one into sysfs attrs 5736aec1ad7SBorislav Petkov * Return false if there is no available events. 5746aec1ad7SBorislav Petkov */ 5756aec1ad7SBorislav Petkov static bool cstate_probe_msr(struct perf_cstate_msr *msr, 5766aec1ad7SBorislav Petkov struct attribute **events_attrs, 5776aec1ad7SBorislav Petkov int max_event_nr) 5786aec1ad7SBorislav Petkov { 5796aec1ad7SBorislav Petkov int i, j = 0; 5806aec1ad7SBorislav Petkov u64 val; 5816aec1ad7SBorislav Petkov 5826aec1ad7SBorislav Petkov /* Probe the cstate events. */ 5836aec1ad7SBorislav Petkov for (i = 0; i < max_event_nr; i++) { 5846aec1ad7SBorislav Petkov if (!msr[i].test(i) || rdmsrl_safe(msr[i].msr, &val)) 5856aec1ad7SBorislav Petkov msr[i].attr = NULL; 5866aec1ad7SBorislav Petkov } 5876aec1ad7SBorislav Petkov 5886aec1ad7SBorislav Petkov /* List remaining events in the sysfs attrs. */ 5896aec1ad7SBorislav Petkov for (i = 0; i < max_event_nr; i++) { 5906aec1ad7SBorislav Petkov if (msr[i].attr) 5916aec1ad7SBorislav Petkov events_attrs[j++] = &msr[i].attr->attr.attr; 5926aec1ad7SBorislav Petkov } 5936aec1ad7SBorislav Petkov events_attrs[j] = NULL; 5946aec1ad7SBorislav Petkov 5956aec1ad7SBorislav Petkov return (j > 0) ? true : false; 5966aec1ad7SBorislav Petkov } 5976aec1ad7SBorislav Petkov 5986aec1ad7SBorislav Petkov static int __init cstate_init(void) 5996aec1ad7SBorislav Petkov { 6006aec1ad7SBorislav Petkov /* SLM has different MSR for PKG C6 */ 6016aec1ad7SBorislav Petkov switch (boot_cpu_data.x86_model) { 6026aec1ad7SBorislav Petkov case 55: 6036aec1ad7SBorislav Petkov case 76: 6046aec1ad7SBorislav Petkov case 77: 6056aec1ad7SBorislav Petkov pkg_msr[PERF_CSTATE_PKG_C6_RES].msr = MSR_PKG_C7_RESIDENCY; 6066aec1ad7SBorislav Petkov } 6076aec1ad7SBorislav Petkov 6086aec1ad7SBorislav Petkov if (cstate_probe_msr(core_msr, core_events_attrs, PERF_CSTATE_CORE_EVENT_MAX)) 6096aec1ad7SBorislav Petkov has_cstate_core = true; 6106aec1ad7SBorislav Petkov 6116aec1ad7SBorislav Petkov if (cstate_probe_msr(pkg_msr, pkg_events_attrs, PERF_CSTATE_PKG_EVENT_MAX)) 6126aec1ad7SBorislav Petkov has_cstate_pkg = true; 6136aec1ad7SBorislav Petkov 6146aec1ad7SBorislav Petkov return (has_cstate_core || has_cstate_pkg) ? 0 : -ENODEV; 6156aec1ad7SBorislav Petkov } 6166aec1ad7SBorislav Petkov 6176aec1ad7SBorislav Petkov static void __init cstate_cpumask_init(void) 6186aec1ad7SBorislav Petkov { 6196aec1ad7SBorislav Petkov int cpu; 6206aec1ad7SBorislav Petkov 6216aec1ad7SBorislav Petkov cpu_notifier_register_begin(); 6226aec1ad7SBorislav Petkov 6236aec1ad7SBorislav Petkov for_each_online_cpu(cpu) 6246aec1ad7SBorislav Petkov cstate_cpu_init(cpu); 6256aec1ad7SBorislav Petkov 6266aec1ad7SBorislav Petkov __perf_cpu_notifier(cstate_cpu_notifier); 6276aec1ad7SBorislav Petkov 6286aec1ad7SBorislav Petkov cpu_notifier_register_done(); 6296aec1ad7SBorislav Petkov } 6306aec1ad7SBorislav Petkov 6316aec1ad7SBorislav Petkov static struct pmu cstate_core_pmu = { 6326aec1ad7SBorislav Petkov .attr_groups = core_attr_groups, 6336aec1ad7SBorislav Petkov .name = "cstate_core", 6346aec1ad7SBorislav Petkov .task_ctx_nr = perf_invalid_context, 6356aec1ad7SBorislav Petkov .event_init = cstate_pmu_event_init, 6366aec1ad7SBorislav Petkov .add = cstate_pmu_event_add, /* must have */ 6376aec1ad7SBorislav Petkov .del = cstate_pmu_event_del, /* must have */ 6386aec1ad7SBorislav Petkov .start = cstate_pmu_event_start, 6396aec1ad7SBorislav Petkov .stop = cstate_pmu_event_stop, 6406aec1ad7SBorislav Petkov .read = cstate_pmu_event_update, 6416aec1ad7SBorislav Petkov .capabilities = PERF_PMU_CAP_NO_INTERRUPT, 6426aec1ad7SBorislav Petkov }; 6436aec1ad7SBorislav Petkov 6446aec1ad7SBorislav Petkov static struct pmu cstate_pkg_pmu = { 6456aec1ad7SBorislav Petkov .attr_groups = pkg_attr_groups, 6466aec1ad7SBorislav Petkov .name = "cstate_pkg", 6476aec1ad7SBorislav Petkov .task_ctx_nr = perf_invalid_context, 6486aec1ad7SBorislav Petkov .event_init = cstate_pmu_event_init, 6496aec1ad7SBorislav Petkov .add = cstate_pmu_event_add, /* must have */ 6506aec1ad7SBorislav Petkov .del = cstate_pmu_event_del, /* must have */ 6516aec1ad7SBorislav Petkov .start = cstate_pmu_event_start, 6526aec1ad7SBorislav Petkov .stop = cstate_pmu_event_stop, 6536aec1ad7SBorislav Petkov .read = cstate_pmu_event_update, 6546aec1ad7SBorislav Petkov .capabilities = PERF_PMU_CAP_NO_INTERRUPT, 6556aec1ad7SBorislav Petkov }; 6566aec1ad7SBorislav Petkov 6576aec1ad7SBorislav Petkov static void __init cstate_pmus_register(void) 6586aec1ad7SBorislav Petkov { 6596aec1ad7SBorislav Petkov int err; 6606aec1ad7SBorislav Petkov 6616aec1ad7SBorislav Petkov if (has_cstate_core) { 6626aec1ad7SBorislav Petkov err = perf_pmu_register(&cstate_core_pmu, cstate_core_pmu.name, -1); 6636aec1ad7SBorislav Petkov if (WARN_ON(err)) 6646aec1ad7SBorislav Petkov pr_info("Failed to register PMU %s error %d\n", 6656aec1ad7SBorislav Petkov cstate_core_pmu.name, err); 6666aec1ad7SBorislav Petkov } 6676aec1ad7SBorislav Petkov 6686aec1ad7SBorislav Petkov if (has_cstate_pkg) { 6696aec1ad7SBorislav Petkov err = perf_pmu_register(&cstate_pkg_pmu, cstate_pkg_pmu.name, -1); 6706aec1ad7SBorislav Petkov if (WARN_ON(err)) 6716aec1ad7SBorislav Petkov pr_info("Failed to register PMU %s error %d\n", 6726aec1ad7SBorislav Petkov cstate_pkg_pmu.name, err); 6736aec1ad7SBorislav Petkov } 6746aec1ad7SBorislav Petkov } 6756aec1ad7SBorislav Petkov 6766aec1ad7SBorislav Petkov static int __init cstate_pmu_init(void) 6776aec1ad7SBorislav Petkov { 6786aec1ad7SBorislav Petkov int err; 6796aec1ad7SBorislav Petkov 6806aec1ad7SBorislav Petkov if (cpu_has_hypervisor) 6816aec1ad7SBorislav Petkov return -ENODEV; 6826aec1ad7SBorislav Petkov 6836aec1ad7SBorislav Petkov err = cstate_init(); 6846aec1ad7SBorislav Petkov if (err) 6856aec1ad7SBorislav Petkov return err; 6866aec1ad7SBorislav Petkov 6876aec1ad7SBorislav Petkov cstate_cpumask_init(); 6886aec1ad7SBorislav Petkov 6896aec1ad7SBorislav Petkov cstate_pmus_register(); 6906aec1ad7SBorislav Petkov 6916aec1ad7SBorislav Petkov return 0; 6926aec1ad7SBorislav Petkov } 6936aec1ad7SBorislav Petkov 6946aec1ad7SBorislav Petkov device_initcall(cstate_pmu_init); 695