1103a8feaSLen Brown /* 2103a8feaSLen Brown * turbostat -- show CPU frequency and C-state residency 3103a8feaSLen Brown * on modern Intel turbo-capable processors. 4103a8feaSLen Brown * 5144b44b1SLen Brown * Copyright (c) 2013 Intel Corporation. 6103a8feaSLen Brown * Len Brown <len.brown@intel.com> 7103a8feaSLen Brown * 8103a8feaSLen Brown * This program is free software; you can redistribute it and/or modify it 9103a8feaSLen Brown * under the terms and conditions of the GNU General Public License, 10103a8feaSLen Brown * version 2, as published by the Free Software Foundation. 11103a8feaSLen Brown * 12103a8feaSLen Brown * This program is distributed in the hope it will be useful, but WITHOUT 13103a8feaSLen Brown * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14103a8feaSLen Brown * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15103a8feaSLen Brown * more details. 16103a8feaSLen Brown * 17103a8feaSLen Brown * You should have received a copy of the GNU General Public License along with 18103a8feaSLen Brown * this program; if not, write to the Free Software Foundation, Inc., 19103a8feaSLen Brown * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 20103a8feaSLen Brown */ 21103a8feaSLen Brown 2288c3281fSLen Brown #define _GNU_SOURCE 23b731f311SJosh Triplett #include MSRHEADER 24869ce69eSLen Brown #include INTEL_FAMILY_HEADER 2595aebc44SJosh Triplett #include <stdarg.h> 26103a8feaSLen Brown #include <stdio.h> 27b2c95d90SJosh Triplett #include <err.h> 28103a8feaSLen Brown #include <unistd.h> 29103a8feaSLen Brown #include <sys/types.h> 30103a8feaSLen Brown #include <sys/wait.h> 31103a8feaSLen Brown #include <sys/stat.h> 32103a8feaSLen Brown #include <sys/resource.h> 33103a8feaSLen Brown #include <fcntl.h> 34103a8feaSLen Brown #include <signal.h> 35103a8feaSLen Brown #include <sys/time.h> 36103a8feaSLen Brown #include <stdlib.h> 37d8af6f5fSLen Brown #include <getopt.h> 38103a8feaSLen Brown #include <dirent.h> 39103a8feaSLen Brown #include <string.h> 40103a8feaSLen Brown #include <ctype.h> 4188c3281fSLen Brown #include <sched.h> 422a0609c0SLen Brown #include <time.h> 432b92865eSJosh Triplett #include <cpuid.h> 4498481e79SLen Brown #include <linux/capability.h> 4598481e79SLen Brown #include <errno.h> 46103a8feaSLen Brown 47103a8feaSLen Brown char *proc_stat = "/proc/stat"; 48b7d8c148SLen Brown FILE *outf; 4936229897SLen Brown int *fd_percpu; 502a0609c0SLen Brown struct timespec interval_ts = {5, 0}; 51d8af6f5fSLen Brown unsigned int debug; 52d8af6f5fSLen Brown unsigned int rapl_joules; 53d8af6f5fSLen Brown unsigned int summary_only; 54d8af6f5fSLen Brown unsigned int dump_only; 55103a8feaSLen Brown unsigned int do_snb_cstates; 56fb5d4327SDasaratharaman Chandramouli unsigned int do_knl_cstates; 57ee7e38e3SLen Brown unsigned int do_pc2; 58ee7e38e3SLen Brown unsigned int do_pc3; 59ee7e38e3SLen Brown unsigned int do_pc6; 60ee7e38e3SLen Brown unsigned int do_pc7; 61ca58710fSKristen Carlson Accardi unsigned int do_c8_c9_c10; 620b2bb692SLen Brown unsigned int do_skl_residency; 63144b44b1SLen Brown unsigned int do_slm_cstates; 64144b44b1SLen Brown unsigned int use_c1_residency_msr; 65103a8feaSLen Brown unsigned int has_aperf; 66889facbeSLen Brown unsigned int has_epb; 675a63426eSLen Brown unsigned int do_irtl_snb; 685a63426eSLen Brown unsigned int do_irtl_hsw; 69fc04cc67SLen Brown unsigned int units = 1000000; /* MHz etc */ 70103a8feaSLen Brown unsigned int genuine_intel; 71103a8feaSLen Brown unsigned int has_invariant_tsc; 72d7899447SLen Brown unsigned int do_nhm_platform_info; 73b2b34dfeSHubert Chrzaniuk unsigned int aperf_mperf_multiplier = 1; 74103a8feaSLen Brown double bclk; 75a2b7b749SLen Brown double base_hz; 7621ed5574SLen Brown unsigned int has_base_hz; 77a2b7b749SLen Brown double tsc_tweak = 1.0; 78c98d5d94SLen Brown unsigned int show_pkg_only; 79c98d5d94SLen Brown unsigned int show_core_only; 80c98d5d94SLen Brown char *output_buffer, *outp; 81889facbeSLen Brown unsigned int do_rapl; 82889facbeSLen Brown unsigned int do_dts; 83889facbeSLen Brown unsigned int do_ptm; 84fdf676e5SLen Brown unsigned long long gfx_cur_rc6_ms; 8527d47356SLen Brown unsigned int gfx_cur_mhz; 86889facbeSLen Brown unsigned int tcc_activation_temp; 87889facbeSLen Brown unsigned int tcc_activation_temp_override; 8840ee8e3bSAndrey Semin double rapl_power_units, rapl_time_units; 8940ee8e3bSAndrey Semin double rapl_dram_energy_units, rapl_energy_units; 90889facbeSLen Brown double rapl_joule_counter_range; 913a9a941dSLen Brown unsigned int do_core_perf_limit_reasons; 923a9a941dSLen Brown unsigned int do_gfx_perf_limit_reasons; 933a9a941dSLen Brown unsigned int do_ring_perf_limit_reasons; 948a5bdf41SLen Brown unsigned int crystal_hz; 958a5bdf41SLen Brown unsigned long long tsc_hz; 967ce7d5deSPrarit Bhargava int base_cpu; 9721ed5574SLen Brown double discover_bclk(unsigned int family, unsigned int model); 987f5c258eSLen Brown unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */ 997f5c258eSLen Brown /* IA32_HWP_REQUEST, IA32_HWP_STATUS */ 1007f5c258eSLen Brown unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */ 1017f5c258eSLen Brown unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */ 1027f5c258eSLen Brown unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */ 1037f5c258eSLen Brown unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */ 104889facbeSLen Brown 105889facbeSLen Brown #define RAPL_PKG (1 << 0) 106e6f9bb3cSLen Brown /* 0x610 MSR_PKG_POWER_LIMIT */ 107e6f9bb3cSLen Brown /* 0x611 MSR_PKG_ENERGY_STATUS */ 108e6f9bb3cSLen Brown #define RAPL_PKG_PERF_STATUS (1 << 1) 109e6f9bb3cSLen Brown /* 0x613 MSR_PKG_PERF_STATUS */ 110e6f9bb3cSLen Brown #define RAPL_PKG_POWER_INFO (1 << 2) 111e6f9bb3cSLen Brown /* 0x614 MSR_PKG_POWER_INFO */ 112e6f9bb3cSLen Brown 113889facbeSLen Brown #define RAPL_DRAM (1 << 3) 114e6f9bb3cSLen Brown /* 0x618 MSR_DRAM_POWER_LIMIT */ 115e6f9bb3cSLen Brown /* 0x619 MSR_DRAM_ENERGY_STATUS */ 116e6f9bb3cSLen Brown #define RAPL_DRAM_PERF_STATUS (1 << 4) 117e6f9bb3cSLen Brown /* 0x61b MSR_DRAM_PERF_STATUS */ 1180b2bb692SLen Brown #define RAPL_DRAM_POWER_INFO (1 << 5) 1190b2bb692SLen Brown /* 0x61c MSR_DRAM_POWER_INFO */ 120e6f9bb3cSLen Brown 1219148494cSJacob Pan #define RAPL_CORES_POWER_LIMIT (1 << 6) 122e6f9bb3cSLen Brown /* 0x638 MSR_PP0_POWER_LIMIT */ 1230b2bb692SLen Brown #define RAPL_CORE_POLICY (1 << 7) 124e6f9bb3cSLen Brown /* 0x63a MSR_PP0_POLICY */ 125e6f9bb3cSLen Brown 1260b2bb692SLen Brown #define RAPL_GFX (1 << 8) 127e6f9bb3cSLen Brown /* 0x640 MSR_PP1_POWER_LIMIT */ 128e6f9bb3cSLen Brown /* 0x641 MSR_PP1_ENERGY_STATUS */ 129e6f9bb3cSLen Brown /* 0x642 MSR_PP1_POLICY */ 1309148494cSJacob Pan 1319148494cSJacob Pan #define RAPL_CORES_ENERGY_STATUS (1 << 9) 1329148494cSJacob Pan /* 0x639 MSR_PP0_ENERGY_STATUS */ 1339148494cSJacob Pan #define RAPL_CORES (RAPL_CORES_ENERGY_STATUS | RAPL_CORES_POWER_LIMIT) 134889facbeSLen Brown #define TJMAX_DEFAULT 100 135889facbeSLen Brown 136889facbeSLen Brown #define MAX(a, b) ((a) > (b) ? (a) : (b)) 137103a8feaSLen Brown 138388e9c81SLen Brown /* 139388e9c81SLen Brown * buffer size used by sscanf() for added column names 140388e9c81SLen Brown * Usually truncated to 7 characters, but also handles 18 columns for raw 64-bit counters 141388e9c81SLen Brown */ 142388e9c81SLen Brown #define NAME_BYTES 20 143388e9c81SLen Brown 144103a8feaSLen Brown int backwards_count; 145103a8feaSLen Brown char *progname; 146103a8feaSLen Brown 147c98d5d94SLen Brown cpu_set_t *cpu_present_set, *cpu_affinity_set; 148c98d5d94SLen Brown size_t cpu_present_setsize, cpu_affinity_setsize; 149678a3bd1SLen Brown #define MAX_ADDED_COUNTERS 16 150c98d5d94SLen Brown 151c98d5d94SLen Brown struct thread_data { 152c98d5d94SLen Brown unsigned long long tsc; 153c98d5d94SLen Brown unsigned long long aperf; 154c98d5d94SLen Brown unsigned long long mperf; 155144b44b1SLen Brown unsigned long long c1; 156562a2d37SLen Brown unsigned int irq_count; 1571ed51011SLen Brown unsigned int smi_count; 158c98d5d94SLen Brown unsigned int cpu_id; 159c98d5d94SLen Brown unsigned int flags; 160c98d5d94SLen Brown #define CPU_IS_FIRST_THREAD_IN_CORE 0x2 161c98d5d94SLen Brown #define CPU_IS_FIRST_CORE_IN_PACKAGE 0x4 162678a3bd1SLen Brown unsigned long long counter[MAX_ADDED_COUNTERS]; 163c98d5d94SLen Brown } *thread_even, *thread_odd; 164c98d5d94SLen Brown 165c98d5d94SLen Brown struct core_data { 166c98d5d94SLen Brown unsigned long long c3; 167c98d5d94SLen Brown unsigned long long c6; 168c98d5d94SLen Brown unsigned long long c7; 169889facbeSLen Brown unsigned int core_temp_c; 170c98d5d94SLen Brown unsigned int core_id; 171678a3bd1SLen Brown unsigned long long counter[MAX_ADDED_COUNTERS]; 172c98d5d94SLen Brown } *core_even, *core_odd; 173c98d5d94SLen Brown 174c98d5d94SLen Brown struct pkg_data { 175c98d5d94SLen Brown unsigned long long pc2; 176c98d5d94SLen Brown unsigned long long pc3; 177c98d5d94SLen Brown unsigned long long pc6; 178c98d5d94SLen Brown unsigned long long pc7; 179ca58710fSKristen Carlson Accardi unsigned long long pc8; 180ca58710fSKristen Carlson Accardi unsigned long long pc9; 181ca58710fSKristen Carlson Accardi unsigned long long pc10; 1820b2bb692SLen Brown unsigned long long pkg_wtd_core_c0; 1830b2bb692SLen Brown unsigned long long pkg_any_core_c0; 1840b2bb692SLen Brown unsigned long long pkg_any_gfxe_c0; 1850b2bb692SLen Brown unsigned long long pkg_both_core_gfxe_c0; 1869185e988SLen Brown long long gfx_rc6_ms; 18727d47356SLen Brown unsigned int gfx_mhz; 188c98d5d94SLen Brown unsigned int package_id; 189889facbeSLen Brown unsigned int energy_pkg; /* MSR_PKG_ENERGY_STATUS */ 190889facbeSLen Brown unsigned int energy_dram; /* MSR_DRAM_ENERGY_STATUS */ 191889facbeSLen Brown unsigned int energy_cores; /* MSR_PP0_ENERGY_STATUS */ 192889facbeSLen Brown unsigned int energy_gfx; /* MSR_PP1_ENERGY_STATUS */ 193889facbeSLen Brown unsigned int rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */ 194889facbeSLen Brown unsigned int rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */ 195889facbeSLen Brown unsigned int pkg_temp_c; 196678a3bd1SLen Brown unsigned long long counter[MAX_ADDED_COUNTERS]; 197c98d5d94SLen Brown } *package_even, *package_odd; 198c98d5d94SLen Brown 199c98d5d94SLen Brown #define ODD_COUNTERS thread_odd, core_odd, package_odd 200c98d5d94SLen Brown #define EVEN_COUNTERS thread_even, core_even, package_even 201c98d5d94SLen Brown 202c98d5d94SLen Brown #define GET_THREAD(thread_base, thread_no, core_no, pkg_no) \ 203c98d5d94SLen Brown (thread_base + (pkg_no) * topo.num_cores_per_pkg * \ 204c98d5d94SLen Brown topo.num_threads_per_core + \ 205c98d5d94SLen Brown (core_no) * topo.num_threads_per_core + (thread_no)) 206c98d5d94SLen Brown #define GET_CORE(core_base, core_no, pkg_no) \ 207c98d5d94SLen Brown (core_base + (pkg_no) * topo.num_cores_per_pkg + (core_no)) 208c98d5d94SLen Brown #define GET_PKG(pkg_base, pkg_no) (pkg_base + pkg_no) 209c98d5d94SLen Brown 210388e9c81SLen Brown enum counter_scope {SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE}; 211388e9c81SLen Brown enum counter_type {COUNTER_CYCLES, COUNTER_SECONDS}; 212388e9c81SLen Brown enum counter_format {FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT}; 213388e9c81SLen Brown 214388e9c81SLen Brown struct msr_counter { 215388e9c81SLen Brown unsigned int msr_num; 216388e9c81SLen Brown char name[NAME_BYTES]; 217388e9c81SLen Brown unsigned int width; 218388e9c81SLen Brown enum counter_type type; 219388e9c81SLen Brown enum counter_format format; 220388e9c81SLen Brown struct msr_counter *next; 221*812db3f7SLen Brown unsigned int flags; 222*812db3f7SLen Brown #define FLAGS_HIDE (1 << 0) 223*812db3f7SLen Brown #define FLAGS_SHOW (1 << 1) 224388e9c81SLen Brown }; 225388e9c81SLen Brown 226388e9c81SLen Brown struct sys_counters { 227678a3bd1SLen Brown unsigned int added_thread_counters; 228678a3bd1SLen Brown unsigned int added_core_counters; 229678a3bd1SLen Brown unsigned int added_package_counters; 230388e9c81SLen Brown struct msr_counter *tp; 231388e9c81SLen Brown struct msr_counter *cp; 232388e9c81SLen Brown struct msr_counter *pp; 233388e9c81SLen Brown } sys; 234388e9c81SLen Brown 235c98d5d94SLen Brown struct system_summary { 236c98d5d94SLen Brown struct thread_data threads; 237c98d5d94SLen Brown struct core_data cores; 238c98d5d94SLen Brown struct pkg_data packages; 239388e9c81SLen Brown } average; 240c98d5d94SLen Brown 241c98d5d94SLen Brown 242c98d5d94SLen Brown struct topo_params { 243c98d5d94SLen Brown int num_packages; 244103a8feaSLen Brown int num_cpus; 245c98d5d94SLen Brown int num_cores; 246c98d5d94SLen Brown int max_cpu_num; 247c98d5d94SLen Brown int num_cores_per_pkg; 248c98d5d94SLen Brown int num_threads_per_core; 249c98d5d94SLen Brown } topo; 250103a8feaSLen Brown 251c98d5d94SLen Brown struct timeval tv_even, tv_odd, tv_delta; 252103a8feaSLen Brown 253562a2d37SLen Brown int *irq_column_2_cpu; /* /proc/interrupts column numbers */ 254562a2d37SLen Brown int *irqs_per_cpu; /* indexed by cpu_num */ 255562a2d37SLen Brown 256c98d5d94SLen Brown void setup_all_buffers(void); 257103a8feaSLen Brown 258c98d5d94SLen Brown int cpu_is_not_present(int cpu) 259d15cf7c1SLen Brown { 260c98d5d94SLen Brown return !CPU_ISSET_S(cpu, cpu_present_setsize, cpu_present_set); 261c98d5d94SLen Brown } 262c98d5d94SLen Brown /* 263c98d5d94SLen Brown * run func(thread, core, package) in topology order 264c98d5d94SLen Brown * skip non-present cpus 265c98d5d94SLen Brown */ 266c98d5d94SLen Brown 267c98d5d94SLen Brown int for_all_cpus(int (func)(struct thread_data *, struct core_data *, struct pkg_data *), 268c98d5d94SLen Brown struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base) 269c98d5d94SLen Brown { 270c98d5d94SLen Brown int retval, pkg_no, core_no, thread_no; 271c98d5d94SLen Brown 272c98d5d94SLen Brown for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) { 273c98d5d94SLen Brown for (core_no = 0; core_no < topo.num_cores_per_pkg; ++core_no) { 274c98d5d94SLen Brown for (thread_no = 0; thread_no < 275c98d5d94SLen Brown topo.num_threads_per_core; ++thread_no) { 276c98d5d94SLen Brown struct thread_data *t; 277c98d5d94SLen Brown struct core_data *c; 278c98d5d94SLen Brown struct pkg_data *p; 279c98d5d94SLen Brown 280c98d5d94SLen Brown t = GET_THREAD(thread_base, thread_no, core_no, pkg_no); 281c98d5d94SLen Brown 282c98d5d94SLen Brown if (cpu_is_not_present(t->cpu_id)) 283c98d5d94SLen Brown continue; 284c98d5d94SLen Brown 285c98d5d94SLen Brown c = GET_CORE(core_base, core_no, pkg_no); 286c98d5d94SLen Brown p = GET_PKG(pkg_base, pkg_no); 287c98d5d94SLen Brown 288c98d5d94SLen Brown retval = func(t, c, p); 289c98d5d94SLen Brown if (retval) 290c98d5d94SLen Brown return retval; 291c98d5d94SLen Brown } 292c98d5d94SLen Brown } 293c98d5d94SLen Brown } 294d15cf7c1SLen Brown return 0; 295d15cf7c1SLen Brown } 296d15cf7c1SLen Brown 29788c3281fSLen Brown int cpu_migrate(int cpu) 29888c3281fSLen Brown { 299c98d5d94SLen Brown CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set); 300c98d5d94SLen Brown CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set); 301c98d5d94SLen Brown if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1) 30288c3281fSLen Brown return -1; 30388c3281fSLen Brown else 30488c3281fSLen Brown return 0; 30588c3281fSLen Brown } 30636229897SLen Brown int get_msr_fd(int cpu) 307103a8feaSLen Brown { 308103a8feaSLen Brown char pathname[32]; 309103a8feaSLen Brown int fd; 310103a8feaSLen Brown 31136229897SLen Brown fd = fd_percpu[cpu]; 31236229897SLen Brown 31336229897SLen Brown if (fd) 31436229897SLen Brown return fd; 31536229897SLen Brown 316103a8feaSLen Brown sprintf(pathname, "/dev/cpu/%d/msr", cpu); 317103a8feaSLen Brown fd = open(pathname, O_RDONLY); 31815aaa346SLen Brown if (fd < 0) 31998481e79SLen Brown err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname); 320103a8feaSLen Brown 32136229897SLen Brown fd_percpu[cpu] = fd; 32236229897SLen Brown 32336229897SLen Brown return fd; 32436229897SLen Brown } 32536229897SLen Brown 32636229897SLen Brown int get_msr(int cpu, off_t offset, unsigned long long *msr) 32736229897SLen Brown { 32836229897SLen Brown ssize_t retval; 32936229897SLen Brown 33036229897SLen Brown retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset); 33115aaa346SLen Brown 33298481e79SLen Brown if (retval != sizeof *msr) 33336229897SLen Brown err(-1, "msr %d offset 0x%llx read failed", cpu, (unsigned long long)offset); 33415aaa346SLen Brown 33515aaa346SLen Brown return 0; 336103a8feaSLen Brown } 337103a8feaSLen Brown 338fc04cc67SLen Brown /* 339*812db3f7SLen Brown * Each string in this array is compared in --show and --hide cmdline. 340*812db3f7SLen Brown * Thus, strings that are proper sub-sets must follow their more specific peers. 341fc04cc67SLen Brown */ 342*812db3f7SLen Brown struct msr_counter bic[] = { 343*812db3f7SLen Brown { 0x0, "Package" }, 344*812db3f7SLen Brown { 0x0, "Avg_MHz" }, 345*812db3f7SLen Brown { 0x0, "Bzy_MHz" }, 346*812db3f7SLen Brown { 0x0, "TSC_MHz" }, 347*812db3f7SLen Brown { 0x0, "IRQ" }, 348*812db3f7SLen Brown { 0x0, "SMI", 32, 0, FORMAT_DELTA, NULL}, 349*812db3f7SLen Brown { 0x0, "Busy%" }, 350*812db3f7SLen Brown { 0x0, "CPU%c1" }, 351*812db3f7SLen Brown { 0x0, "CPU%c3" }, 352*812db3f7SLen Brown { 0x0, "CPU%c6" }, 353*812db3f7SLen Brown { 0x0, "CPU%c7" }, 354*812db3f7SLen Brown { 0x0, "ThreadC" }, 355*812db3f7SLen Brown { 0x0, "CoreTmp" }, 356*812db3f7SLen Brown { 0x0, "CoreCnt" }, 357*812db3f7SLen Brown { 0x0, "PkgTmp" }, 358*812db3f7SLen Brown { 0x0, "GFX%rc6" }, 359*812db3f7SLen Brown { 0x0, "GFXMHz" }, 360*812db3f7SLen Brown { 0x0, "Pkg%pc2" }, 361*812db3f7SLen Brown { 0x0, "Pkg%pc3" }, 362*812db3f7SLen Brown { 0x0, "Pkg%pc6" }, 363*812db3f7SLen Brown { 0x0, "Pkg%pc7" }, 364*812db3f7SLen Brown { 0x0, "PkgWatt" }, 365*812db3f7SLen Brown { 0x0, "CorWatt" }, 366*812db3f7SLen Brown { 0x0, "GFXWatt" }, 367*812db3f7SLen Brown { 0x0, "PkgCnt" }, 368*812db3f7SLen Brown { 0x0, "RAMWatt" }, 369*812db3f7SLen Brown { 0x0, "PKG_%" }, 370*812db3f7SLen Brown { 0x0, "RAM_%" }, 371*812db3f7SLen Brown { 0x0, "Pkg_J" }, 372*812db3f7SLen Brown { 0x0, "Cor_J" }, 373*812db3f7SLen Brown { 0x0, "GFX_J" }, 374*812db3f7SLen Brown { 0x0, "RAM_J" }, 375*812db3f7SLen Brown { 0x0, "Core" }, 376*812db3f7SLen Brown { 0x0, "CPU" }, 377*812db3f7SLen Brown }; 378*812db3f7SLen Brown 379*812db3f7SLen Brown #define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter)) 380*812db3f7SLen Brown #define BIC_Package (1ULL << 0) 381*812db3f7SLen Brown #define BIC_Avg_MHz (1ULL << 1) 382*812db3f7SLen Brown #define BIC_Bzy_MHz (1ULL << 2) 383*812db3f7SLen Brown #define BIC_TSC_MHz (1ULL << 3) 384*812db3f7SLen Brown #define BIC_IRQ (1ULL << 4) 385*812db3f7SLen Brown #define BIC_SMI (1ULL << 5) 386*812db3f7SLen Brown #define BIC_Busy (1ULL << 6) 387*812db3f7SLen Brown #define BIC_CPU_c1 (1ULL << 7) 388*812db3f7SLen Brown #define BIC_CPU_c3 (1ULL << 8) 389*812db3f7SLen Brown #define BIC_CPU_c6 (1ULL << 9) 390*812db3f7SLen Brown #define BIC_CPU_c7 (1ULL << 10) 391*812db3f7SLen Brown #define BIC_ThreadC (1ULL << 11) 392*812db3f7SLen Brown #define BIC_CoreTmp (1ULL << 12) 393*812db3f7SLen Brown #define BIC_CoreCnt (1ULL << 13) 394*812db3f7SLen Brown #define BIC_PkgTmp (1ULL << 14) 395*812db3f7SLen Brown #define BIC_GFX_rc6 (1ULL << 15) 396*812db3f7SLen Brown #define BIC_GFXMHz (1ULL << 16) 397*812db3f7SLen Brown #define BIC_Pkgpc2 (1ULL << 17) 398*812db3f7SLen Brown #define BIC_Pkgpc3 (1ULL << 18) 399*812db3f7SLen Brown #define BIC_Pkgpc6 (1ULL << 19) 400*812db3f7SLen Brown #define BIC_Pkgpc7 (1ULL << 20) 401*812db3f7SLen Brown #define BIC_PkgWatt (1ULL << 21) 402*812db3f7SLen Brown #define BIC_CorWatt (1ULL << 22) 403*812db3f7SLen Brown #define BIC_GFXWatt (1ULL << 23) 404*812db3f7SLen Brown #define BIC_PkgCnt (1ULL << 24) 405*812db3f7SLen Brown #define BIC_RAMWatt (1ULL << 27) 406*812db3f7SLen Brown #define BIC_PKG__ (1ULL << 28) 407*812db3f7SLen Brown #define BIC_RAM__ (1ULL << 29) 408*812db3f7SLen Brown #define BIC_Pkg_J (1ULL << 30) 409*812db3f7SLen Brown #define BIC_Cor_J (1ULL << 31) 410*812db3f7SLen Brown #define BIC_GFX_J (1ULL << 30) 411*812db3f7SLen Brown #define BIC_RAM_J (1ULL << 31) 412*812db3f7SLen Brown #define BIC_Core (1ULL << 32) 413*812db3f7SLen Brown #define BIC_CPU (1ULL << 33) 414*812db3f7SLen Brown 415*812db3f7SLen Brown unsigned long long bic_enabled = 0xFFFFFFFFFFFFFFFFULL; 416*812db3f7SLen Brown unsigned long long bic_present; 417*812db3f7SLen Brown 418*812db3f7SLen Brown #define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME) 419*812db3f7SLen Brown #define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT) 420*812db3f7SLen Brown 421*812db3f7SLen Brown /* 422*812db3f7SLen Brown * bic_lookup 423*812db3f7SLen Brown * for all the strings in comma separate name_list, 424*812db3f7SLen Brown * set the approprate bit in return value. 425*812db3f7SLen Brown */ 426*812db3f7SLen Brown unsigned long long bic_lookup(char *name_list) 427*812db3f7SLen Brown { 428*812db3f7SLen Brown int i; 429*812db3f7SLen Brown unsigned long long retval = 0; 430*812db3f7SLen Brown 431*812db3f7SLen Brown while (name_list) { 432*812db3f7SLen Brown char *comma; 433*812db3f7SLen Brown 434*812db3f7SLen Brown comma = strchr(name_list, ','); 435*812db3f7SLen Brown 436*812db3f7SLen Brown if (comma) 437*812db3f7SLen Brown *comma = '\0'; 438*812db3f7SLen Brown 439*812db3f7SLen Brown for (i = 0; i < MAX_BIC; ++i) { 440*812db3f7SLen Brown if (!strcmp(name_list, bic[i].name)) { 441*812db3f7SLen Brown retval |= (1ULL << i); 442*812db3f7SLen Brown break; 443*812db3f7SLen Brown } 444*812db3f7SLen Brown } 445*812db3f7SLen Brown if (i == MAX_BIC) { 446*812db3f7SLen Brown fprintf(stderr, "Invalid counter name: %s\n", name_list); 447*812db3f7SLen Brown exit(-1); 448*812db3f7SLen Brown } 449*812db3f7SLen Brown 450*812db3f7SLen Brown name_list = comma; 451*812db3f7SLen Brown if (name_list) 452*812db3f7SLen Brown name_list++; 453*812db3f7SLen Brown 454*812db3f7SLen Brown } 455*812db3f7SLen Brown return retval; 456*812db3f7SLen Brown } 457fc04cc67SLen Brown 458a829eb4dSLen Brown void print_header(void) 459103a8feaSLen Brown { 460388e9c81SLen Brown struct msr_counter *mp; 461388e9c81SLen Brown 462*812db3f7SLen Brown if (DO_BIC(BIC_Package)) 4633d109de2SLen Brown outp += sprintf(outp, "\tPackage"); 464*812db3f7SLen Brown if (DO_BIC(BIC_Core)) 4653d109de2SLen Brown outp += sprintf(outp, "\tCore"); 466*812db3f7SLen Brown if (DO_BIC(BIC_CPU)) 4673d109de2SLen Brown outp += sprintf(outp, "\tCPU"); 468*812db3f7SLen Brown if (DO_BIC(BIC_Avg_MHz)) 4693d109de2SLen Brown outp += sprintf(outp, "\tAvg_MHz"); 470*812db3f7SLen Brown if (DO_BIC(BIC_Busy)) 4713d109de2SLen Brown outp += sprintf(outp, "\tBusy%%"); 472*812db3f7SLen Brown if (DO_BIC(BIC_Bzy_MHz)) 4733d109de2SLen Brown outp += sprintf(outp, "\tBzy_MHz"); 474*812db3f7SLen Brown if (DO_BIC(BIC_TSC_MHz)) 4753d109de2SLen Brown outp += sprintf(outp, "\tTSC_MHz"); 4761cc21f7bSLen Brown 4771cc21f7bSLen Brown if (!debug) 4781cc21f7bSLen Brown goto done; 4791cc21f7bSLen Brown 480*812db3f7SLen Brown if (DO_BIC(BIC_IRQ)) 4813d109de2SLen Brown outp += sprintf(outp, "\tIRQ"); 482*812db3f7SLen Brown if (DO_BIC(BIC_SMI)) 4833d109de2SLen Brown outp += sprintf(outp, "\tSMI"); 4841cc21f7bSLen Brown 485*812db3f7SLen Brown if (DO_BIC(BIC_CPU_c1)) 4863d109de2SLen Brown outp += sprintf(outp, "\tCPU%%c1"); 487889facbeSLen Brown 488388e9c81SLen Brown for (mp = sys.tp; mp; mp = mp->next) { 489388e9c81SLen Brown if (mp->format == FORMAT_RAW) { 490388e9c81SLen Brown if (mp->width == 64) 491388e9c81SLen Brown outp += sprintf(outp, "\t%18.18s", mp->name); 492388e9c81SLen Brown else 493388e9c81SLen Brown outp += sprintf(outp, "\t%10.10s", mp->name); 494388e9c81SLen Brown } else { 495388e9c81SLen Brown outp += sprintf(outp, "\t%-7.7s", mp->name); 496388e9c81SLen Brown } 497388e9c81SLen Brown } 498388e9c81SLen Brown 499*812db3f7SLen Brown if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates) 500678a3bd1SLen Brown outp += sprintf(outp, "\tCPU%%c3"); 501*812db3f7SLen Brown if (DO_BIC(BIC_CPU_c6)) 502678a3bd1SLen Brown outp += sprintf(outp, "\tCPU%%c6"); 503*812db3f7SLen Brown if (DO_BIC(BIC_CPU_c7)) 504678a3bd1SLen Brown outp += sprintf(outp, "\tCPU%%c7"); 505678a3bd1SLen Brown 506678a3bd1SLen Brown 507*812db3f7SLen Brown if (DO_BIC(BIC_CoreTmp)) 5083d109de2SLen Brown outp += sprintf(outp, "\tCoreTmp"); 509388e9c81SLen Brown 510388e9c81SLen Brown for (mp = sys.cp; mp; mp = mp->next) { 511388e9c81SLen Brown if (mp->format == FORMAT_RAW) { 512388e9c81SLen Brown if (mp->width == 64) 513388e9c81SLen Brown outp += sprintf(outp, "\t%18.18s", mp->name); 514388e9c81SLen Brown else 515388e9c81SLen Brown outp += sprintf(outp, "\t%10.10s", mp->name); 516388e9c81SLen Brown } else { 517388e9c81SLen Brown outp += sprintf(outp, "\t%-7.7s", mp->name); 518388e9c81SLen Brown } 519388e9c81SLen Brown } 520388e9c81SLen Brown 521*812db3f7SLen Brown if (DO_BIC(BIC_PkgTmp)) 5223d109de2SLen Brown outp += sprintf(outp, "\tPkgTmp"); 523889facbeSLen Brown 524*812db3f7SLen Brown if (DO_BIC(BIC_GFX_rc6)) 5253d109de2SLen Brown outp += sprintf(outp, "\tGFX%%rc6"); 526fdf676e5SLen Brown 527*812db3f7SLen Brown if (DO_BIC(BIC_GFXMHz)) 5283d109de2SLen Brown outp += sprintf(outp, "\tGFXMHz"); 52927d47356SLen Brown 5300b2bb692SLen Brown if (do_skl_residency) { 5313d109de2SLen Brown outp += sprintf(outp, "\tTotl%%C0"); 5323d109de2SLen Brown outp += sprintf(outp, "\tAny%%C0"); 5333d109de2SLen Brown outp += sprintf(outp, "\tGFX%%C0"); 5343d109de2SLen Brown outp += sprintf(outp, "\tCPUGFX%%"); 5350b2bb692SLen Brown } 5360b2bb692SLen Brown 537ee7e38e3SLen Brown if (do_pc2) 5383d109de2SLen Brown outp += sprintf(outp, "\tPkg%%pc2"); 539ee7e38e3SLen Brown if (do_pc3) 5403d109de2SLen Brown outp += sprintf(outp, "\tPkg%%pc3"); 541ee7e38e3SLen Brown if (do_pc6) 5423d109de2SLen Brown outp += sprintf(outp, "\tPkg%%pc6"); 543ee7e38e3SLen Brown if (do_pc7) 5443d109de2SLen Brown outp += sprintf(outp, "\tPkg%%pc7"); 545ca58710fSKristen Carlson Accardi if (do_c8_c9_c10) { 5463d109de2SLen Brown outp += sprintf(outp, "\tPkg%%pc8"); 5473d109de2SLen Brown outp += sprintf(outp, "\tPkg%%pc9"); 5483d109de2SLen Brown outp += sprintf(outp, "\tPk%%pc10"); 549ca58710fSKristen Carlson Accardi } 550103a8feaSLen Brown 5515c56be9aSDirk Brandewie if (do_rapl && !rapl_joules) { 552*812db3f7SLen Brown if (DO_BIC(BIC_PkgWatt)) 5533d109de2SLen Brown outp += sprintf(outp, "\tPkgWatt"); 554*812db3f7SLen Brown if (DO_BIC(BIC_CorWatt)) 5553d109de2SLen Brown outp += sprintf(outp, "\tCorWatt"); 556*812db3f7SLen Brown if (DO_BIC(BIC_GFXWatt)) 5573d109de2SLen Brown outp += sprintf(outp, "\tGFXWatt"); 558*812db3f7SLen Brown if (DO_BIC(BIC_RAMWatt)) 5593d109de2SLen Brown outp += sprintf(outp, "\tRAMWatt"); 560*812db3f7SLen Brown if (DO_BIC(BIC_PKG__)) 5613d109de2SLen Brown outp += sprintf(outp, "\tPKG_%%"); 562*812db3f7SLen Brown if (DO_BIC(BIC_RAM__)) 5633d109de2SLen Brown outp += sprintf(outp, "\tRAM_%%"); 564d7899447SLen Brown } else if (do_rapl && rapl_joules) { 565*812db3f7SLen Brown if (DO_BIC(BIC_Pkg_J)) 5663d109de2SLen Brown outp += sprintf(outp, "\tPkg_J"); 567*812db3f7SLen Brown if (DO_BIC(BIC_Cor_J)) 5683d109de2SLen Brown outp += sprintf(outp, "\tCor_J"); 569*812db3f7SLen Brown if (DO_BIC(BIC_GFX_J)) 5703d109de2SLen Brown outp += sprintf(outp, "\tGFX_J"); 571*812db3f7SLen Brown if (DO_BIC(BIC_RAM_J)) 5723d109de2SLen Brown outp += sprintf(outp, "\tRAM_J"); 573*812db3f7SLen Brown if (DO_BIC(BIC_PKG__)) 5743d109de2SLen Brown outp += sprintf(outp, "\tPKG_%%"); 575*812db3f7SLen Brown if (DO_BIC(BIC_RAM__)) 5763d109de2SLen Brown outp += sprintf(outp, "\tRAM_%%"); 5775c56be9aSDirk Brandewie } 578388e9c81SLen Brown for (mp = sys.pp; mp; mp = mp->next) { 579388e9c81SLen Brown if (mp->format == FORMAT_RAW) { 580388e9c81SLen Brown if (mp->width == 64) 581388e9c81SLen Brown outp += sprintf(outp, "\t%18.18s", mp->name); 582388e9c81SLen Brown else 583388e9c81SLen Brown outp += sprintf(outp, "\t%10.10s", mp->name); 584388e9c81SLen Brown } else { 585388e9c81SLen Brown outp += sprintf(outp, "\t%-7.7s", mp->name); 586388e9c81SLen Brown } 587388e9c81SLen Brown } 588388e9c81SLen Brown 5891cc21f7bSLen Brown done: 590c98d5d94SLen Brown outp += sprintf(outp, "\n"); 591103a8feaSLen Brown } 592103a8feaSLen Brown 593c98d5d94SLen Brown int dump_counters(struct thread_data *t, struct core_data *c, 594c98d5d94SLen Brown struct pkg_data *p) 595103a8feaSLen Brown { 596388e9c81SLen Brown int i; 597388e9c81SLen Brown struct msr_counter *mp; 598388e9c81SLen Brown 5993b4d5c7fSAndy Shevchenko outp += sprintf(outp, "t %p, c %p, p %p\n", t, c, p); 600c98d5d94SLen Brown 601c98d5d94SLen Brown if (t) { 6023b4d5c7fSAndy Shevchenko outp += sprintf(outp, "CPU: %d flags 0x%x\n", 6033b4d5c7fSAndy Shevchenko t->cpu_id, t->flags); 6043b4d5c7fSAndy Shevchenko outp += sprintf(outp, "TSC: %016llX\n", t->tsc); 6053b4d5c7fSAndy Shevchenko outp += sprintf(outp, "aperf: %016llX\n", t->aperf); 6063b4d5c7fSAndy Shevchenko outp += sprintf(outp, "mperf: %016llX\n", t->mperf); 6073b4d5c7fSAndy Shevchenko outp += sprintf(outp, "c1: %016llX\n", t->c1); 6086886fee4SLen Brown 609*812db3f7SLen Brown if (DO_BIC(BIC_IRQ)) 610562a2d37SLen Brown outp += sprintf(outp, "IRQ: %08X\n", t->irq_count); 611*812db3f7SLen Brown if (DO_BIC(BIC_SMI)) 6123b4d5c7fSAndy Shevchenko outp += sprintf(outp, "SMI: %08X\n", t->smi_count); 613388e9c81SLen Brown 614388e9c81SLen Brown for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 615388e9c81SLen Brown outp += sprintf(outp, "tADDED [%d] msr0x%x: %08llX\n", 616388e9c81SLen Brown i, mp->msr_num, t->counter[i]); 617388e9c81SLen Brown } 618103a8feaSLen Brown } 619103a8feaSLen Brown 620c98d5d94SLen Brown if (c) { 6213b4d5c7fSAndy Shevchenko outp += sprintf(outp, "core: %d\n", c->core_id); 6223b4d5c7fSAndy Shevchenko outp += sprintf(outp, "c3: %016llX\n", c->c3); 6233b4d5c7fSAndy Shevchenko outp += sprintf(outp, "c6: %016llX\n", c->c6); 6243b4d5c7fSAndy Shevchenko outp += sprintf(outp, "c7: %016llX\n", c->c7); 6253b4d5c7fSAndy Shevchenko outp += sprintf(outp, "DTS: %dC\n", c->core_temp_c); 626388e9c81SLen Brown 627388e9c81SLen Brown for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 628388e9c81SLen Brown outp += sprintf(outp, "cADDED [%d] msr0x%x: %08llX\n", 629388e9c81SLen Brown i, mp->msr_num, c->counter[i]); 630388e9c81SLen Brown } 631c98d5d94SLen Brown } 632103a8feaSLen Brown 633c98d5d94SLen Brown if (p) { 6343b4d5c7fSAndy Shevchenko outp += sprintf(outp, "package: %d\n", p->package_id); 6350b2bb692SLen Brown 6360b2bb692SLen Brown outp += sprintf(outp, "Weighted cores: %016llX\n", p->pkg_wtd_core_c0); 6370b2bb692SLen Brown outp += sprintf(outp, "Any cores: %016llX\n", p->pkg_any_core_c0); 6380b2bb692SLen Brown outp += sprintf(outp, "Any GFX: %016llX\n", p->pkg_any_gfxe_c0); 6390b2bb692SLen Brown outp += sprintf(outp, "CPU + GFX: %016llX\n", p->pkg_both_core_gfxe_c0); 6400b2bb692SLen Brown 6413b4d5c7fSAndy Shevchenko outp += sprintf(outp, "pc2: %016llX\n", p->pc2); 642ee7e38e3SLen Brown if (do_pc3) 6433b4d5c7fSAndy Shevchenko outp += sprintf(outp, "pc3: %016llX\n", p->pc3); 644ee7e38e3SLen Brown if (do_pc6) 6453b4d5c7fSAndy Shevchenko outp += sprintf(outp, "pc6: %016llX\n", p->pc6); 646ee7e38e3SLen Brown if (do_pc7) 6473b4d5c7fSAndy Shevchenko outp += sprintf(outp, "pc7: %016llX\n", p->pc7); 6483b4d5c7fSAndy Shevchenko outp += sprintf(outp, "pc8: %016llX\n", p->pc8); 6493b4d5c7fSAndy Shevchenko outp += sprintf(outp, "pc9: %016llX\n", p->pc9); 6503b4d5c7fSAndy Shevchenko outp += sprintf(outp, "pc10: %016llX\n", p->pc10); 6513b4d5c7fSAndy Shevchenko outp += sprintf(outp, "Joules PKG: %0X\n", p->energy_pkg); 6523b4d5c7fSAndy Shevchenko outp += sprintf(outp, "Joules COR: %0X\n", p->energy_cores); 6533b4d5c7fSAndy Shevchenko outp += sprintf(outp, "Joules GFX: %0X\n", p->energy_gfx); 6543b4d5c7fSAndy Shevchenko outp += sprintf(outp, "Joules RAM: %0X\n", p->energy_dram); 6553b4d5c7fSAndy Shevchenko outp += sprintf(outp, "Throttle PKG: %0X\n", 6563b4d5c7fSAndy Shevchenko p->rapl_pkg_perf_status); 6573b4d5c7fSAndy Shevchenko outp += sprintf(outp, "Throttle RAM: %0X\n", 6583b4d5c7fSAndy Shevchenko p->rapl_dram_perf_status); 6593b4d5c7fSAndy Shevchenko outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c); 660388e9c81SLen Brown 661388e9c81SLen Brown for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 662388e9c81SLen Brown outp += sprintf(outp, "pADDED [%d] msr0x%x: %08llX\n", 663388e9c81SLen Brown i, mp->msr_num, p->counter[i]); 664388e9c81SLen Brown } 665c98d5d94SLen Brown } 6663b4d5c7fSAndy Shevchenko 6673b4d5c7fSAndy Shevchenko outp += sprintf(outp, "\n"); 6683b4d5c7fSAndy Shevchenko 669c98d5d94SLen Brown return 0; 670103a8feaSLen Brown } 671103a8feaSLen Brown 672e23da037SLen Brown /* 673e23da037SLen Brown * column formatting convention & formats 674e23da037SLen Brown */ 675c98d5d94SLen Brown int format_counters(struct thread_data *t, struct core_data *c, 676c98d5d94SLen Brown struct pkg_data *p) 677103a8feaSLen Brown { 678103a8feaSLen Brown double interval_float; 679fc04cc67SLen Brown char *fmt8; 680388e9c81SLen Brown int i; 681388e9c81SLen Brown struct msr_counter *mp; 682103a8feaSLen Brown 683c98d5d94SLen Brown /* if showing only 1st thread in core and this isn't one, bail out */ 684c98d5d94SLen Brown if (show_core_only && !(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 685c98d5d94SLen Brown return 0; 686c98d5d94SLen Brown 687c98d5d94SLen Brown /* if showing only 1st thread in pkg and this isn't one, bail out */ 688c98d5d94SLen Brown if (show_pkg_only && !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 689c98d5d94SLen Brown return 0; 690c98d5d94SLen Brown 691103a8feaSLen Brown interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0; 692103a8feaSLen Brown 693c98d5d94SLen Brown /* topo columns, print blanks on 1st (average) line */ 694c98d5d94SLen Brown if (t == &average.threads) { 695*812db3f7SLen Brown if (DO_BIC(BIC_Package)) 6963d109de2SLen Brown outp += sprintf(outp, "\t-"); 697*812db3f7SLen Brown if (DO_BIC(BIC_Core)) 6983d109de2SLen Brown outp += sprintf(outp, "\t-"); 699*812db3f7SLen Brown if (DO_BIC(BIC_CPU)) 7003d109de2SLen Brown outp += sprintf(outp, "\t-"); 701103a8feaSLen Brown } else { 702*812db3f7SLen Brown if (DO_BIC(BIC_Package)) { 703c98d5d94SLen Brown if (p) 7043d109de2SLen Brown outp += sprintf(outp, "\t%d", p->package_id); 705c98d5d94SLen Brown else 7063d109de2SLen Brown outp += sprintf(outp, "\t-"); 707c98d5d94SLen Brown } 708*812db3f7SLen Brown if (DO_BIC(BIC_Core)) { 709c98d5d94SLen Brown if (c) 7103d109de2SLen Brown outp += sprintf(outp, "\t%d", c->core_id); 711c98d5d94SLen Brown else 7123d109de2SLen Brown outp += sprintf(outp, "\t-"); 713c98d5d94SLen Brown } 714*812db3f7SLen Brown if (DO_BIC(BIC_CPU)) 7153d109de2SLen Brown outp += sprintf(outp, "\t%d", t->cpu_id); 716103a8feaSLen Brown } 717fc04cc67SLen Brown 718*812db3f7SLen Brown if (DO_BIC(BIC_Avg_MHz)) 7193d109de2SLen Brown outp += sprintf(outp, "\t%.0f", 720fc04cc67SLen Brown 1.0 / units * t->aperf / interval_float); 721fc04cc67SLen Brown 722*812db3f7SLen Brown if (DO_BIC(BIC_Busy)) 7233d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * t->mperf/t->tsc/tsc_tweak); 724103a8feaSLen Brown 725*812db3f7SLen Brown if (DO_BIC(BIC_Bzy_MHz)) { 72621ed5574SLen Brown if (has_base_hz) 7273d109de2SLen Brown outp += sprintf(outp, "\t%.0f", base_hz / units * t->aperf / t->mperf); 72821ed5574SLen Brown else 7293d109de2SLen Brown outp += sprintf(outp, "\t%.0f", 73021ed5574SLen Brown 1.0 * t->tsc / units * t->aperf / t->mperf / interval_float); 73121ed5574SLen Brown } 732103a8feaSLen Brown 733*812db3f7SLen Brown if (DO_BIC(BIC_TSC_MHz)) 7343d109de2SLen Brown outp += sprintf(outp, "\t%.0f", 1.0 * t->tsc/units/interval_float); 735103a8feaSLen Brown 7361cc21f7bSLen Brown if (!debug) 7371cc21f7bSLen Brown goto done; 7381cc21f7bSLen Brown 739562a2d37SLen Brown /* IRQ */ 740*812db3f7SLen Brown if (DO_BIC(BIC_IRQ)) 7413d109de2SLen Brown outp += sprintf(outp, "\t%d", t->irq_count); 742562a2d37SLen Brown 7431cc21f7bSLen Brown /* SMI */ 744*812db3f7SLen Brown if (DO_BIC(BIC_SMI)) 7453d109de2SLen Brown outp += sprintf(outp, "\t%d", t->smi_count); 7461cc21f7bSLen Brown 747678a3bd1SLen Brown /* C1 */ 748*812db3f7SLen Brown if (DO_BIC(BIC_CPU_c1)) 7493d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * t->c1/t->tsc); 750c98d5d94SLen Brown 751678a3bd1SLen Brown /* Added counters */ 752678a3bd1SLen Brown for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 753678a3bd1SLen Brown if (mp->format == FORMAT_RAW) { 754678a3bd1SLen Brown if (mp->width == 32) 755678a3bd1SLen Brown outp += sprintf(outp, "\t0x%08lx", (unsigned long) t->counter[i]); 756678a3bd1SLen Brown else 757678a3bd1SLen Brown outp += sprintf(outp, "\t0x%016llx", t->counter[i]); 758678a3bd1SLen Brown } else if (mp->format == FORMAT_DELTA) { 759678a3bd1SLen Brown outp += sprintf(outp, "\t%lld", t->counter[i]); 760678a3bd1SLen Brown } else if (mp->format == FORMAT_PERCENT) { 761678a3bd1SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * t->counter[i]/t->tsc); 762678a3bd1SLen Brown } 763678a3bd1SLen Brown } 764678a3bd1SLen Brown 765c98d5d94SLen Brown /* print per-core data only for 1st thread in core */ 766c98d5d94SLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 767c98d5d94SLen Brown goto done; 768c98d5d94SLen Brown 769*812db3f7SLen Brown if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates) 7703d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * c->c3/t->tsc); 771*812db3f7SLen Brown if (DO_BIC(BIC_CPU_c6)) 7723d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * c->c6/t->tsc); 773*812db3f7SLen Brown if (DO_BIC(BIC_CPU_c7)) 7743d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * c->c7/t->tsc); 775c98d5d94SLen Brown 776*812db3f7SLen Brown if (DO_BIC(BIC_CoreTmp)) 7773d109de2SLen Brown outp += sprintf(outp, "\t%d", c->core_temp_c); 778889facbeSLen Brown 779388e9c81SLen Brown for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 780388e9c81SLen Brown if (mp->format == FORMAT_RAW) { 781388e9c81SLen Brown if (mp->width == 32) 782388e9c81SLen Brown outp += sprintf(outp, "\t0x%08lx", (unsigned long) c->counter[i]); 783388e9c81SLen Brown else 784388e9c81SLen Brown outp += sprintf(outp, "\t0x%016llx", c->counter[i]); 785388e9c81SLen Brown } else if (mp->format == FORMAT_DELTA) { 786678a3bd1SLen Brown outp += sprintf(outp, "\t%lld", c->counter[i]); 787388e9c81SLen Brown } else if (mp->format == FORMAT_PERCENT) { 788388e9c81SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * c->counter[i]/t->tsc); 789388e9c81SLen Brown } 790388e9c81SLen Brown } 791388e9c81SLen Brown 792c98d5d94SLen Brown /* print per-package data only for 1st core in package */ 793c98d5d94SLen Brown if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 794c98d5d94SLen Brown goto done; 795c98d5d94SLen Brown 7960b2bb692SLen Brown /* PkgTmp */ 797*812db3f7SLen Brown if (DO_BIC(BIC_PkgTmp)) 7983d109de2SLen Brown outp += sprintf(outp, "\t%d", p->pkg_temp_c); 799889facbeSLen Brown 800fdf676e5SLen Brown /* GFXrc6 */ 801*812db3f7SLen Brown if (DO_BIC(BIC_GFX_rc6)) { 802ba3dec99SLen Brown if (p->gfx_rc6_ms == -1) { /* detect GFX counter reset */ 8033d109de2SLen Brown outp += sprintf(outp, "\t**.**"); 8049185e988SLen Brown } else { 8053d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 8069185e988SLen Brown p->gfx_rc6_ms / 10.0 / interval_float); 8079185e988SLen Brown } 8089185e988SLen Brown } 809fdf676e5SLen Brown 81027d47356SLen Brown /* GFXMHz */ 811*812db3f7SLen Brown if (DO_BIC(BIC_GFXMHz)) 8123d109de2SLen Brown outp += sprintf(outp, "\t%d", p->gfx_mhz); 81327d47356SLen Brown 8140b2bb692SLen Brown /* Totl%C0, Any%C0 GFX%C0 CPUGFX% */ 8150b2bb692SLen Brown if (do_skl_residency) { 8163d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_wtd_core_c0/t->tsc); 8173d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_any_core_c0/t->tsc); 8183d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_any_gfxe_c0/t->tsc); 8193d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_both_core_gfxe_c0/t->tsc); 8200b2bb692SLen Brown } 8210b2bb692SLen Brown 822ee7e38e3SLen Brown if (do_pc2) 8233d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pc2/t->tsc); 824ee7e38e3SLen Brown if (do_pc3) 8253d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pc3/t->tsc); 826ee7e38e3SLen Brown if (do_pc6) 8273d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pc6/t->tsc); 828ee7e38e3SLen Brown if (do_pc7) 8293d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pc7/t->tsc); 830ca58710fSKristen Carlson Accardi if (do_c8_c9_c10) { 8313d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pc8/t->tsc); 8323d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pc9/t->tsc); 8333d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pc10/t->tsc); 834ca58710fSKristen Carlson Accardi } 835889facbeSLen Brown 836889facbeSLen Brown /* 837889facbeSLen Brown * If measurement interval exceeds minimum RAPL Joule Counter range, 838889facbeSLen Brown * indicate that results are suspect by printing "**" in fraction place. 839889facbeSLen Brown */ 840fc04cc67SLen Brown if (interval_float < rapl_joule_counter_range) 8413d109de2SLen Brown fmt8 = "\t%.2f"; 842fc04cc67SLen Brown else 843fc04cc67SLen Brown fmt8 = "%6.0f**"; 844889facbeSLen Brown 845*812db3f7SLen Brown if (DO_BIC(BIC_PkgWatt)) 846fc04cc67SLen Brown outp += sprintf(outp, fmt8, p->energy_pkg * rapl_energy_units / interval_float); 847*812db3f7SLen Brown if (DO_BIC(BIC_CorWatt)) 848fc04cc67SLen Brown outp += sprintf(outp, fmt8, p->energy_cores * rapl_energy_units / interval_float); 849*812db3f7SLen Brown if (DO_BIC(BIC_GFXWatt)) 850fc04cc67SLen Brown outp += sprintf(outp, fmt8, p->energy_gfx * rapl_energy_units / interval_float); 851*812db3f7SLen Brown if (DO_BIC(BIC_RAMWatt)) 85240ee8e3bSAndrey Semin outp += sprintf(outp, fmt8, p->energy_dram * rapl_dram_energy_units / interval_float); 853*812db3f7SLen Brown if (DO_BIC(BIC_Pkg_J)) 854*812db3f7SLen Brown outp += sprintf(outp, fmt8, p->energy_pkg * rapl_energy_units); 855*812db3f7SLen Brown if (DO_BIC(BIC_Cor_J)) 856*812db3f7SLen Brown outp += sprintf(outp, fmt8, p->energy_cores * rapl_energy_units); 857*812db3f7SLen Brown if (DO_BIC(BIC_GFX_J)) 858*812db3f7SLen Brown outp += sprintf(outp, fmt8, p->energy_gfx * rapl_energy_units); 859*812db3f7SLen Brown if (DO_BIC(BIC_RAM_J)) 860*812db3f7SLen Brown outp += sprintf(outp, fmt8, p->energy_dram * rapl_dram_energy_units); 861*812db3f7SLen Brown if (DO_BIC(BIC_PKG__)) 862fc04cc67SLen Brown outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); 863*812db3f7SLen Brown if (DO_BIC(BIC_RAM__)) 864fc04cc67SLen Brown outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); 865*812db3f7SLen Brown 866388e9c81SLen Brown for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 867388e9c81SLen Brown if (mp->format == FORMAT_RAW) { 868388e9c81SLen Brown if (mp->width == 32) 869388e9c81SLen Brown outp += sprintf(outp, "\t0x%08lx", (unsigned long) p->counter[i]); 870388e9c81SLen Brown else 871388e9c81SLen Brown outp += sprintf(outp, "\t0x%016llx", p->counter[i]); 872388e9c81SLen Brown } else if (mp->format == FORMAT_DELTA) { 873678a3bd1SLen Brown outp += sprintf(outp, "\t%lld", p->counter[i]); 874388e9c81SLen Brown } else if (mp->format == FORMAT_PERCENT) { 875388e9c81SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->counter[i]/t->tsc); 876388e9c81SLen Brown } 877388e9c81SLen Brown } 878388e9c81SLen Brown 879c98d5d94SLen Brown done: 880c98d5d94SLen Brown outp += sprintf(outp, "\n"); 881c98d5d94SLen Brown 882c98d5d94SLen Brown return 0; 883103a8feaSLen Brown } 884103a8feaSLen Brown 885b7d8c148SLen Brown void flush_output_stdout(void) 886103a8feaSLen Brown { 887b7d8c148SLen Brown FILE *filep; 888b7d8c148SLen Brown 889b7d8c148SLen Brown if (outf == stderr) 890b7d8c148SLen Brown filep = stdout; 891b7d8c148SLen Brown else 892b7d8c148SLen Brown filep = outf; 893b7d8c148SLen Brown 894b7d8c148SLen Brown fputs(output_buffer, filep); 895b7d8c148SLen Brown fflush(filep); 896b7d8c148SLen Brown 897c98d5d94SLen Brown outp = output_buffer; 898c98d5d94SLen Brown } 899b7d8c148SLen Brown void flush_output_stderr(void) 900c98d5d94SLen Brown { 901b7d8c148SLen Brown fputs(output_buffer, outf); 902b7d8c148SLen Brown fflush(outf); 903c98d5d94SLen Brown outp = output_buffer; 904c98d5d94SLen Brown } 905c98d5d94SLen Brown void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) 906c98d5d94SLen Brown { 907e23da037SLen Brown static int printed; 908103a8feaSLen Brown 909e23da037SLen Brown if (!printed || !summary_only) 910103a8feaSLen Brown print_header(); 911103a8feaSLen Brown 912c98d5d94SLen Brown if (topo.num_cpus > 1) 913c98d5d94SLen Brown format_counters(&average.threads, &average.cores, 914c98d5d94SLen Brown &average.packages); 915103a8feaSLen Brown 916e23da037SLen Brown printed = 1; 917e23da037SLen Brown 918e23da037SLen Brown if (summary_only) 919e23da037SLen Brown return; 920e23da037SLen Brown 921c98d5d94SLen Brown for_all_cpus(format_counters, t, c, p); 922103a8feaSLen Brown } 923103a8feaSLen Brown 924889facbeSLen Brown #define DELTA_WRAP32(new, old) \ 925889facbeSLen Brown if (new > old) { \ 926889facbeSLen Brown old = new - old; \ 927889facbeSLen Brown } else { \ 928889facbeSLen Brown old = 0x100000000 + new - old; \ 929889facbeSLen Brown } 930889facbeSLen Brown 931ba3dec99SLen Brown int 932c98d5d94SLen Brown delta_package(struct pkg_data *new, struct pkg_data *old) 933103a8feaSLen Brown { 934388e9c81SLen Brown int i; 935388e9c81SLen Brown struct msr_counter *mp; 9360b2bb692SLen Brown 9370b2bb692SLen Brown if (do_skl_residency) { 9380b2bb692SLen Brown old->pkg_wtd_core_c0 = new->pkg_wtd_core_c0 - old->pkg_wtd_core_c0; 9390b2bb692SLen Brown old->pkg_any_core_c0 = new->pkg_any_core_c0 - old->pkg_any_core_c0; 9400b2bb692SLen Brown old->pkg_any_gfxe_c0 = new->pkg_any_gfxe_c0 - old->pkg_any_gfxe_c0; 9410b2bb692SLen Brown old->pkg_both_core_gfxe_c0 = new->pkg_both_core_gfxe_c0 - old->pkg_both_core_gfxe_c0; 9420b2bb692SLen Brown } 943c98d5d94SLen Brown old->pc2 = new->pc2 - old->pc2; 944ee7e38e3SLen Brown if (do_pc3) 945c98d5d94SLen Brown old->pc3 = new->pc3 - old->pc3; 946ee7e38e3SLen Brown if (do_pc6) 947c98d5d94SLen Brown old->pc6 = new->pc6 - old->pc6; 948ee7e38e3SLen Brown if (do_pc7) 949c98d5d94SLen Brown old->pc7 = new->pc7 - old->pc7; 950ca58710fSKristen Carlson Accardi old->pc8 = new->pc8 - old->pc8; 951ca58710fSKristen Carlson Accardi old->pc9 = new->pc9 - old->pc9; 952ca58710fSKristen Carlson Accardi old->pc10 = new->pc10 - old->pc10; 953889facbeSLen Brown old->pkg_temp_c = new->pkg_temp_c; 954889facbeSLen Brown 9559185e988SLen Brown /* flag an error when rc6 counter resets/wraps */ 9569185e988SLen Brown if (old->gfx_rc6_ms > new->gfx_rc6_ms) 9579185e988SLen Brown old->gfx_rc6_ms = -1; 9589185e988SLen Brown else 959fdf676e5SLen Brown old->gfx_rc6_ms = new->gfx_rc6_ms - old->gfx_rc6_ms; 9609185e988SLen Brown 96127d47356SLen Brown old->gfx_mhz = new->gfx_mhz; 96227d47356SLen Brown 963889facbeSLen Brown DELTA_WRAP32(new->energy_pkg, old->energy_pkg); 964889facbeSLen Brown DELTA_WRAP32(new->energy_cores, old->energy_cores); 965889facbeSLen Brown DELTA_WRAP32(new->energy_gfx, old->energy_gfx); 966889facbeSLen Brown DELTA_WRAP32(new->energy_dram, old->energy_dram); 967889facbeSLen Brown DELTA_WRAP32(new->rapl_pkg_perf_status, old->rapl_pkg_perf_status); 968889facbeSLen Brown DELTA_WRAP32(new->rapl_dram_perf_status, old->rapl_dram_perf_status); 969ba3dec99SLen Brown 970388e9c81SLen Brown for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 971388e9c81SLen Brown if (mp->format == FORMAT_RAW) 972388e9c81SLen Brown old->counter[i] = new->counter[i]; 973388e9c81SLen Brown else 974388e9c81SLen Brown old->counter[i] = new->counter[i] - old->counter[i]; 975388e9c81SLen Brown } 976388e9c81SLen Brown 977ba3dec99SLen Brown return 0; 978103a8feaSLen Brown } 979103a8feaSLen Brown 980c98d5d94SLen Brown void 981c98d5d94SLen Brown delta_core(struct core_data *new, struct core_data *old) 982c98d5d94SLen Brown { 983388e9c81SLen Brown int i; 984388e9c81SLen Brown struct msr_counter *mp; 985388e9c81SLen Brown 986c98d5d94SLen Brown old->c3 = new->c3 - old->c3; 987c98d5d94SLen Brown old->c6 = new->c6 - old->c6; 988c98d5d94SLen Brown old->c7 = new->c7 - old->c7; 989889facbeSLen Brown old->core_temp_c = new->core_temp_c; 990388e9c81SLen Brown 991388e9c81SLen Brown for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 992388e9c81SLen Brown if (mp->format == FORMAT_RAW) 993388e9c81SLen Brown old->counter[i] = new->counter[i]; 994388e9c81SLen Brown else 995388e9c81SLen Brown old->counter[i] = new->counter[i] - old->counter[i]; 996388e9c81SLen Brown } 997103a8feaSLen Brown } 998c98d5d94SLen Brown 999c3ae331dSLen Brown /* 1000c3ae331dSLen Brown * old = new - old 1001c3ae331dSLen Brown */ 1002ba3dec99SLen Brown int 1003c98d5d94SLen Brown delta_thread(struct thread_data *new, struct thread_data *old, 1004c98d5d94SLen Brown struct core_data *core_delta) 1005c98d5d94SLen Brown { 1006388e9c81SLen Brown int i; 1007388e9c81SLen Brown struct msr_counter *mp; 1008388e9c81SLen Brown 1009c98d5d94SLen Brown old->tsc = new->tsc - old->tsc; 1010c98d5d94SLen Brown 1011103a8feaSLen Brown /* check for TSC < 1 Mcycles over interval */ 1012b2c95d90SJosh Triplett if (old->tsc < (1000 * 1000)) 1013b2c95d90SJosh Triplett errx(-3, "Insanely slow TSC rate, TSC stops in idle?\n" 1014b2c95d90SJosh Triplett "You can disable all c-states by booting with \"idle=poll\"\n" 1015b2c95d90SJosh Triplett "or just the deep ones with \"processor.max_cstate=1\""); 1016103a8feaSLen Brown 1017c98d5d94SLen Brown old->c1 = new->c1 - old->c1; 1018c98d5d94SLen Brown 1019*812db3f7SLen Brown if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz)) { 1020c98d5d94SLen Brown if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) { 1021c98d5d94SLen Brown old->aperf = new->aperf - old->aperf; 1022c98d5d94SLen Brown old->mperf = new->mperf - old->mperf; 1023c98d5d94SLen Brown } else { 1024ba3dec99SLen Brown return -1; 1025103a8feaSLen Brown } 1026a729617cSLen Brown } 1027103a8feaSLen Brown 1028c98d5d94SLen Brown 1029144b44b1SLen Brown if (use_c1_residency_msr) { 1030144b44b1SLen Brown /* 1031144b44b1SLen Brown * Some models have a dedicated C1 residency MSR, 1032144b44b1SLen Brown * which should be more accurate than the derivation below. 1033144b44b1SLen Brown */ 1034144b44b1SLen Brown } else { 1035103a8feaSLen Brown /* 1036c3ae331dSLen Brown * As counter collection is not atomic, 1037c3ae331dSLen Brown * it is possible for mperf's non-halted cycles + idle states 1038103a8feaSLen Brown * to exceed TSC's all cycles: show c1 = 0% in that case. 1039103a8feaSLen Brown */ 1040c3ae331dSLen Brown if ((old->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > old->tsc) 1041c98d5d94SLen Brown old->c1 = 0; 1042c98d5d94SLen Brown else { 1043c98d5d94SLen Brown /* normal case, derive c1 */ 1044c98d5d94SLen Brown old->c1 = old->tsc - old->mperf - core_delta->c3 1045c98d5d94SLen Brown - core_delta->c6 - core_delta->c7; 1046c98d5d94SLen Brown } 1047144b44b1SLen Brown } 1048c3ae331dSLen Brown 1049c98d5d94SLen Brown if (old->mperf == 0) { 1050b7d8c148SLen Brown if (debug > 1) 1051b7d8c148SLen Brown fprintf(outf, "cpu%d MPERF 0!\n", old->cpu_id); 1052c98d5d94SLen Brown old->mperf = 1; /* divide by 0 protection */ 1053c98d5d94SLen Brown } 1054103a8feaSLen Brown 1055*812db3f7SLen Brown if (DO_BIC(BIC_IRQ)) 1056562a2d37SLen Brown old->irq_count = new->irq_count - old->irq_count; 1057562a2d37SLen Brown 1058*812db3f7SLen Brown if (DO_BIC(BIC_SMI)) 10591ed51011SLen Brown old->smi_count = new->smi_count - old->smi_count; 1060ba3dec99SLen Brown 1061388e9c81SLen Brown for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 1062388e9c81SLen Brown if (mp->format == FORMAT_RAW) 1063388e9c81SLen Brown old->counter[i] = new->counter[i]; 1064388e9c81SLen Brown else 1065388e9c81SLen Brown old->counter[i] = new->counter[i] - old->counter[i]; 1066388e9c81SLen Brown } 1067ba3dec99SLen Brown return 0; 1068103a8feaSLen Brown } 1069c98d5d94SLen Brown 1070c98d5d94SLen Brown int delta_cpu(struct thread_data *t, struct core_data *c, 1071c98d5d94SLen Brown struct pkg_data *p, struct thread_data *t2, 1072c98d5d94SLen Brown struct core_data *c2, struct pkg_data *p2) 1073c98d5d94SLen Brown { 1074ba3dec99SLen Brown int retval = 0; 1075ba3dec99SLen Brown 1076c98d5d94SLen Brown /* calculate core delta only for 1st thread in core */ 1077c98d5d94SLen Brown if (t->flags & CPU_IS_FIRST_THREAD_IN_CORE) 1078c98d5d94SLen Brown delta_core(c, c2); 1079c98d5d94SLen Brown 1080c98d5d94SLen Brown /* always calculate thread delta */ 1081ba3dec99SLen Brown retval = delta_thread(t, t2, c2); /* c2 is core delta */ 1082ba3dec99SLen Brown if (retval) 1083ba3dec99SLen Brown return retval; 1084c98d5d94SLen Brown 1085c98d5d94SLen Brown /* calculate package delta only for 1st core in package */ 1086c98d5d94SLen Brown if (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE) 1087ba3dec99SLen Brown retval = delta_package(p, p2); 1088c98d5d94SLen Brown 1089ba3dec99SLen Brown return retval; 1090103a8feaSLen Brown } 1091103a8feaSLen Brown 1092c98d5d94SLen Brown void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) 1093103a8feaSLen Brown { 1094388e9c81SLen Brown int i; 1095388e9c81SLen Brown struct msr_counter *mp; 1096388e9c81SLen Brown 1097c98d5d94SLen Brown t->tsc = 0; 1098c98d5d94SLen Brown t->aperf = 0; 1099c98d5d94SLen Brown t->mperf = 0; 1100c98d5d94SLen Brown t->c1 = 0; 1101103a8feaSLen Brown 1102562a2d37SLen Brown t->irq_count = 0; 1103562a2d37SLen Brown t->smi_count = 0; 1104562a2d37SLen Brown 1105c98d5d94SLen Brown /* tells format_counters to dump all fields from this set */ 1106c98d5d94SLen Brown t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE; 1107c98d5d94SLen Brown 1108c98d5d94SLen Brown c->c3 = 0; 1109c98d5d94SLen Brown c->c6 = 0; 1110c98d5d94SLen Brown c->c7 = 0; 1111889facbeSLen Brown c->core_temp_c = 0; 1112c98d5d94SLen Brown 11130b2bb692SLen Brown p->pkg_wtd_core_c0 = 0; 11140b2bb692SLen Brown p->pkg_any_core_c0 = 0; 11150b2bb692SLen Brown p->pkg_any_gfxe_c0 = 0; 11160b2bb692SLen Brown p->pkg_both_core_gfxe_c0 = 0; 11170b2bb692SLen Brown 1118c98d5d94SLen Brown p->pc2 = 0; 1119ee7e38e3SLen Brown if (do_pc3) 1120c98d5d94SLen Brown p->pc3 = 0; 1121ee7e38e3SLen Brown if (do_pc6) 1122c98d5d94SLen Brown p->pc6 = 0; 1123ee7e38e3SLen Brown if (do_pc7) 1124c98d5d94SLen Brown p->pc7 = 0; 1125ca58710fSKristen Carlson Accardi p->pc8 = 0; 1126ca58710fSKristen Carlson Accardi p->pc9 = 0; 1127ca58710fSKristen Carlson Accardi p->pc10 = 0; 1128889facbeSLen Brown 1129889facbeSLen Brown p->energy_pkg = 0; 1130889facbeSLen Brown p->energy_dram = 0; 1131889facbeSLen Brown p->energy_cores = 0; 1132889facbeSLen Brown p->energy_gfx = 0; 1133889facbeSLen Brown p->rapl_pkg_perf_status = 0; 1134889facbeSLen Brown p->rapl_dram_perf_status = 0; 1135889facbeSLen Brown p->pkg_temp_c = 0; 113627d47356SLen Brown 1137fdf676e5SLen Brown p->gfx_rc6_ms = 0; 113827d47356SLen Brown p->gfx_mhz = 0; 1139388e9c81SLen Brown for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) 1140388e9c81SLen Brown t->counter[i] = 0; 1141388e9c81SLen Brown 1142388e9c81SLen Brown for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) 1143388e9c81SLen Brown c->counter[i] = 0; 1144388e9c81SLen Brown 1145388e9c81SLen Brown for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) 1146388e9c81SLen Brown p->counter[i] = 0; 1147103a8feaSLen Brown } 1148c98d5d94SLen Brown int sum_counters(struct thread_data *t, struct core_data *c, 1149c98d5d94SLen Brown struct pkg_data *p) 1150103a8feaSLen Brown { 1151388e9c81SLen Brown int i; 1152388e9c81SLen Brown struct msr_counter *mp; 1153388e9c81SLen Brown 1154c98d5d94SLen Brown average.threads.tsc += t->tsc; 1155c98d5d94SLen Brown average.threads.aperf += t->aperf; 1156c98d5d94SLen Brown average.threads.mperf += t->mperf; 1157c98d5d94SLen Brown average.threads.c1 += t->c1; 115815aaa346SLen Brown 1159562a2d37SLen Brown average.threads.irq_count += t->irq_count; 1160562a2d37SLen Brown average.threads.smi_count += t->smi_count; 1161562a2d37SLen Brown 1162388e9c81SLen Brown for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 1163388e9c81SLen Brown if (mp->format == FORMAT_RAW) 1164388e9c81SLen Brown continue; 1165388e9c81SLen Brown average.threads.counter[i] += t->counter[i]; 1166388e9c81SLen Brown } 1167388e9c81SLen Brown 1168c98d5d94SLen Brown /* sum per-core values only for 1st thread in core */ 1169c98d5d94SLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 1170c98d5d94SLen Brown return 0; 1171c98d5d94SLen Brown 1172c98d5d94SLen Brown average.cores.c3 += c->c3; 1173c98d5d94SLen Brown average.cores.c6 += c->c6; 1174c98d5d94SLen Brown average.cores.c7 += c->c7; 1175c98d5d94SLen Brown 1176889facbeSLen Brown average.cores.core_temp_c = MAX(average.cores.core_temp_c, c->core_temp_c); 1177889facbeSLen Brown 1178388e9c81SLen Brown for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 1179388e9c81SLen Brown if (mp->format == FORMAT_RAW) 1180388e9c81SLen Brown continue; 1181388e9c81SLen Brown average.cores.counter[i] += c->counter[i]; 1182388e9c81SLen Brown } 1183388e9c81SLen Brown 1184c98d5d94SLen Brown /* sum per-pkg values only for 1st core in pkg */ 1185c98d5d94SLen Brown if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 1186c98d5d94SLen Brown return 0; 1187c98d5d94SLen Brown 11880b2bb692SLen Brown if (do_skl_residency) { 11890b2bb692SLen Brown average.packages.pkg_wtd_core_c0 += p->pkg_wtd_core_c0; 11900b2bb692SLen Brown average.packages.pkg_any_core_c0 += p->pkg_any_core_c0; 11910b2bb692SLen Brown average.packages.pkg_any_gfxe_c0 += p->pkg_any_gfxe_c0; 11920b2bb692SLen Brown average.packages.pkg_both_core_gfxe_c0 += p->pkg_both_core_gfxe_c0; 11930b2bb692SLen Brown } 11940b2bb692SLen Brown 1195c98d5d94SLen Brown average.packages.pc2 += p->pc2; 1196ee7e38e3SLen Brown if (do_pc3) 1197c98d5d94SLen Brown average.packages.pc3 += p->pc3; 1198ee7e38e3SLen Brown if (do_pc6) 1199c98d5d94SLen Brown average.packages.pc6 += p->pc6; 1200ee7e38e3SLen Brown if (do_pc7) 1201c98d5d94SLen Brown average.packages.pc7 += p->pc7; 1202ca58710fSKristen Carlson Accardi average.packages.pc8 += p->pc8; 1203ca58710fSKristen Carlson Accardi average.packages.pc9 += p->pc9; 1204ca58710fSKristen Carlson Accardi average.packages.pc10 += p->pc10; 1205c98d5d94SLen Brown 1206889facbeSLen Brown average.packages.energy_pkg += p->energy_pkg; 1207889facbeSLen Brown average.packages.energy_dram += p->energy_dram; 1208889facbeSLen Brown average.packages.energy_cores += p->energy_cores; 1209889facbeSLen Brown average.packages.energy_gfx += p->energy_gfx; 1210889facbeSLen Brown 1211fdf676e5SLen Brown average.packages.gfx_rc6_ms = p->gfx_rc6_ms; 121227d47356SLen Brown average.packages.gfx_mhz = p->gfx_mhz; 121327d47356SLen Brown 1214889facbeSLen Brown average.packages.pkg_temp_c = MAX(average.packages.pkg_temp_c, p->pkg_temp_c); 1215889facbeSLen Brown 1216889facbeSLen Brown average.packages.rapl_pkg_perf_status += p->rapl_pkg_perf_status; 1217889facbeSLen Brown average.packages.rapl_dram_perf_status += p->rapl_dram_perf_status; 1218388e9c81SLen Brown 1219388e9c81SLen Brown for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 1220388e9c81SLen Brown if (mp->format == FORMAT_RAW) 1221388e9c81SLen Brown continue; 1222388e9c81SLen Brown average.packages.counter[i] += p->counter[i]; 1223388e9c81SLen Brown } 1224c98d5d94SLen Brown return 0; 1225c98d5d94SLen Brown } 1226c98d5d94SLen Brown /* 1227c98d5d94SLen Brown * sum the counters for all cpus in the system 1228c98d5d94SLen Brown * compute the weighted average 1229c98d5d94SLen Brown */ 1230c98d5d94SLen Brown void compute_average(struct thread_data *t, struct core_data *c, 1231c98d5d94SLen Brown struct pkg_data *p) 1232c98d5d94SLen Brown { 1233388e9c81SLen Brown int i; 1234388e9c81SLen Brown struct msr_counter *mp; 1235388e9c81SLen Brown 1236c98d5d94SLen Brown clear_counters(&average.threads, &average.cores, &average.packages); 1237c98d5d94SLen Brown 1238c98d5d94SLen Brown for_all_cpus(sum_counters, t, c, p); 1239c98d5d94SLen Brown 1240c98d5d94SLen Brown average.threads.tsc /= topo.num_cpus; 1241c98d5d94SLen Brown average.threads.aperf /= topo.num_cpus; 1242c98d5d94SLen Brown average.threads.mperf /= topo.num_cpus; 1243c98d5d94SLen Brown average.threads.c1 /= topo.num_cpus; 1244c98d5d94SLen Brown 1245c98d5d94SLen Brown average.cores.c3 /= topo.num_cores; 1246c98d5d94SLen Brown average.cores.c6 /= topo.num_cores; 1247c98d5d94SLen Brown average.cores.c7 /= topo.num_cores; 1248c98d5d94SLen Brown 12490b2bb692SLen Brown if (do_skl_residency) { 12500b2bb692SLen Brown average.packages.pkg_wtd_core_c0 /= topo.num_packages; 12510b2bb692SLen Brown average.packages.pkg_any_core_c0 /= topo.num_packages; 12520b2bb692SLen Brown average.packages.pkg_any_gfxe_c0 /= topo.num_packages; 12530b2bb692SLen Brown average.packages.pkg_both_core_gfxe_c0 /= topo.num_packages; 12540b2bb692SLen Brown } 12550b2bb692SLen Brown 1256c98d5d94SLen Brown average.packages.pc2 /= topo.num_packages; 1257ee7e38e3SLen Brown if (do_pc3) 1258c98d5d94SLen Brown average.packages.pc3 /= topo.num_packages; 1259ee7e38e3SLen Brown if (do_pc6) 1260c98d5d94SLen Brown average.packages.pc6 /= topo.num_packages; 1261ee7e38e3SLen Brown if (do_pc7) 1262c98d5d94SLen Brown average.packages.pc7 /= topo.num_packages; 1263ca58710fSKristen Carlson Accardi 1264ca58710fSKristen Carlson Accardi average.packages.pc8 /= topo.num_packages; 1265ca58710fSKristen Carlson Accardi average.packages.pc9 /= topo.num_packages; 1266ca58710fSKristen Carlson Accardi average.packages.pc10 /= topo.num_packages; 1267388e9c81SLen Brown 1268388e9c81SLen Brown for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 1269388e9c81SLen Brown if (mp->format == FORMAT_RAW) 1270388e9c81SLen Brown continue; 1271388e9c81SLen Brown average.threads.counter[i] /= topo.num_cpus; 1272388e9c81SLen Brown } 1273388e9c81SLen Brown for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 1274388e9c81SLen Brown if (mp->format == FORMAT_RAW) 1275388e9c81SLen Brown continue; 1276388e9c81SLen Brown average.cores.counter[i] /= topo.num_cores; 1277388e9c81SLen Brown } 1278388e9c81SLen Brown for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 1279388e9c81SLen Brown if (mp->format == FORMAT_RAW) 1280388e9c81SLen Brown continue; 1281388e9c81SLen Brown average.packages.counter[i] /= topo.num_packages; 1282388e9c81SLen Brown } 1283c98d5d94SLen Brown } 1284c98d5d94SLen Brown 1285c98d5d94SLen Brown static unsigned long long rdtsc(void) 1286c98d5d94SLen Brown { 1287c98d5d94SLen Brown unsigned int low, high; 1288c98d5d94SLen Brown 1289c98d5d94SLen Brown asm volatile("rdtsc" : "=a" (low), "=d" (high)); 1290c98d5d94SLen Brown 1291c98d5d94SLen Brown return low | ((unsigned long long)high) << 32; 1292c98d5d94SLen Brown } 1293c98d5d94SLen Brown 1294c98d5d94SLen Brown /* 1295c98d5d94SLen Brown * get_counters(...) 1296c98d5d94SLen Brown * migrate to cpu 1297c98d5d94SLen Brown * acquire and record local counters for that cpu 1298c98d5d94SLen Brown */ 1299c98d5d94SLen Brown int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) 1300c98d5d94SLen Brown { 1301c98d5d94SLen Brown int cpu = t->cpu_id; 1302889facbeSLen Brown unsigned long long msr; 13030102b067SLen Brown int aperf_mperf_retry_count = 0; 1304388e9c81SLen Brown struct msr_counter *mp; 1305388e9c81SLen Brown int i; 1306c98d5d94SLen Brown 1307e52966c0SLen Brown if (cpu_migrate(cpu)) { 1308b7d8c148SLen Brown fprintf(outf, "Could not migrate to CPU %d\n", cpu); 130915aaa346SLen Brown return -1; 1310e52966c0SLen Brown } 131115aaa346SLen Brown 13120102b067SLen Brown retry: 1313c98d5d94SLen Brown t->tsc = rdtsc(); /* we are running on local CPU of interest */ 131415aaa346SLen Brown 1315*812db3f7SLen Brown if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz)) { 13160102b067SLen Brown unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time; 13170102b067SLen Brown 13180102b067SLen Brown /* 13190102b067SLen Brown * The TSC, APERF and MPERF must be read together for 13200102b067SLen Brown * APERF/MPERF and MPERF/TSC to give accurate results. 13210102b067SLen Brown * 13220102b067SLen Brown * Unfortunately, APERF and MPERF are read by 13230102b067SLen Brown * individual system call, so delays may occur 13240102b067SLen Brown * between them. If the time to read them 13250102b067SLen Brown * varies by a large amount, we re-read them. 13260102b067SLen Brown */ 13270102b067SLen Brown 13280102b067SLen Brown /* 13290102b067SLen Brown * This initial dummy APERF read has been seen to 13300102b067SLen Brown * reduce jitter in the subsequent reads. 13310102b067SLen Brown */ 13320102b067SLen Brown 13339c63a650SLen Brown if (get_msr(cpu, MSR_IA32_APERF, &t->aperf)) 1334c98d5d94SLen Brown return -3; 13350102b067SLen Brown 13360102b067SLen Brown t->tsc = rdtsc(); /* re-read close to APERF */ 13370102b067SLen Brown 13380102b067SLen Brown tsc_before = t->tsc; 13390102b067SLen Brown 13400102b067SLen Brown if (get_msr(cpu, MSR_IA32_APERF, &t->aperf)) 13410102b067SLen Brown return -3; 13420102b067SLen Brown 13430102b067SLen Brown tsc_between = rdtsc(); 13440102b067SLen Brown 13459c63a650SLen Brown if (get_msr(cpu, MSR_IA32_MPERF, &t->mperf)) 1346c98d5d94SLen Brown return -4; 13470102b067SLen Brown 13480102b067SLen Brown tsc_after = rdtsc(); 13490102b067SLen Brown 13500102b067SLen Brown aperf_time = tsc_between - tsc_before; 13510102b067SLen Brown mperf_time = tsc_after - tsc_between; 13520102b067SLen Brown 13530102b067SLen Brown /* 13540102b067SLen Brown * If the system call latency to read APERF and MPERF 13550102b067SLen Brown * differ by more than 2x, then try again. 13560102b067SLen Brown */ 13570102b067SLen Brown if ((aperf_time > (2 * mperf_time)) || (mperf_time > (2 * aperf_time))) { 13580102b067SLen Brown aperf_mperf_retry_count++; 13590102b067SLen Brown if (aperf_mperf_retry_count < 5) 13600102b067SLen Brown goto retry; 13610102b067SLen Brown else 13620102b067SLen Brown warnx("cpu%d jitter %lld %lld", 13630102b067SLen Brown cpu, aperf_time, mperf_time); 13640102b067SLen Brown } 13650102b067SLen Brown aperf_mperf_retry_count = 0; 13660102b067SLen Brown 1367b2b34dfeSHubert Chrzaniuk t->aperf = t->aperf * aperf_mperf_multiplier; 1368b2b34dfeSHubert Chrzaniuk t->mperf = t->mperf * aperf_mperf_multiplier; 136988c3281fSLen Brown } 137088c3281fSLen Brown 1371*812db3f7SLen Brown if (DO_BIC(BIC_IRQ)) 1372562a2d37SLen Brown t->irq_count = irqs_per_cpu[cpu]; 1373*812db3f7SLen Brown if (DO_BIC(BIC_SMI)) { 13741ed51011SLen Brown if (get_msr(cpu, MSR_SMI_COUNT, &msr)) 13751ed51011SLen Brown return -5; 13761ed51011SLen Brown t->smi_count = msr & 0xFFFFFFFF; 13771ed51011SLen Brown } 1378c98d5d94SLen Brown 1379144b44b1SLen Brown if (use_c1_residency_msr) { 1380144b44b1SLen Brown if (get_msr(cpu, MSR_CORE_C1_RES, &t->c1)) 1381144b44b1SLen Brown return -6; 1382144b44b1SLen Brown } 1383144b44b1SLen Brown 1384388e9c81SLen Brown for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 1385388e9c81SLen Brown if (get_msr(cpu, mp->msr_num, &t->counter[i])) 1386388e9c81SLen Brown return -10; 1387388e9c81SLen Brown } 1388388e9c81SLen Brown 1389388e9c81SLen Brown 1390c98d5d94SLen Brown /* collect core counters only for 1st thread in core */ 1391c98d5d94SLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 1392c98d5d94SLen Brown return 0; 1393c98d5d94SLen Brown 1394*812db3f7SLen Brown if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates) { 1395c98d5d94SLen Brown if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3)) 1396c98d5d94SLen Brown return -6; 1397144b44b1SLen Brown } 1398144b44b1SLen Brown 1399*812db3f7SLen Brown if (DO_BIC(BIC_CPU_c6) && !do_knl_cstates) { 1400c98d5d94SLen Brown if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6)) 1401c98d5d94SLen Brown return -7; 1402fb5d4327SDasaratharaman Chandramouli } else if (do_knl_cstates) { 1403fb5d4327SDasaratharaman Chandramouli if (get_msr(cpu, MSR_KNL_CORE_C6_RESIDENCY, &c->c6)) 1404fb5d4327SDasaratharaman Chandramouli return -7; 1405103a8feaSLen Brown } 140615aaa346SLen Brown 1407*812db3f7SLen Brown if (DO_BIC(BIC_CPU_c7)) 1408c98d5d94SLen Brown if (get_msr(cpu, MSR_CORE_C7_RESIDENCY, &c->c7)) 1409c98d5d94SLen Brown return -8; 1410c98d5d94SLen Brown 1411*812db3f7SLen Brown if (DO_BIC(BIC_CoreTmp)) { 1412889facbeSLen Brown if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr)) 1413889facbeSLen Brown return -9; 1414889facbeSLen Brown c->core_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F); 1415889facbeSLen Brown } 1416889facbeSLen Brown 1417388e9c81SLen Brown for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 1418388e9c81SLen Brown if (get_msr(cpu, mp->msr_num, &c->counter[i])) 1419388e9c81SLen Brown return -10; 1420388e9c81SLen Brown } 1421889facbeSLen Brown 1422c98d5d94SLen Brown /* collect package counters only for 1st core in package */ 1423c98d5d94SLen Brown if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 1424c98d5d94SLen Brown return 0; 142515aaa346SLen Brown 14260b2bb692SLen Brown if (do_skl_residency) { 14270b2bb692SLen Brown if (get_msr(cpu, MSR_PKG_WEIGHTED_CORE_C0_RES, &p->pkg_wtd_core_c0)) 14280b2bb692SLen Brown return -10; 14290b2bb692SLen Brown if (get_msr(cpu, MSR_PKG_ANY_CORE_C0_RES, &p->pkg_any_core_c0)) 14300b2bb692SLen Brown return -11; 14310b2bb692SLen Brown if (get_msr(cpu, MSR_PKG_ANY_GFXE_C0_RES, &p->pkg_any_gfxe_c0)) 14320b2bb692SLen Brown return -12; 14330b2bb692SLen Brown if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0)) 14340b2bb692SLen Brown return -13; 14350b2bb692SLen Brown } 1436ee7e38e3SLen Brown if (do_pc3) 1437c98d5d94SLen Brown if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3)) 1438c98d5d94SLen Brown return -9; 1439ee7e38e3SLen Brown if (do_pc6) 1440c98d5d94SLen Brown if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6)) 1441c98d5d94SLen Brown return -10; 1442ee7e38e3SLen Brown if (do_pc2) 1443c98d5d94SLen Brown if (get_msr(cpu, MSR_PKG_C2_RESIDENCY, &p->pc2)) 1444c98d5d94SLen Brown return -11; 1445ee7e38e3SLen Brown if (do_pc7) 1446c98d5d94SLen Brown if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7)) 1447c98d5d94SLen Brown return -12; 1448ca58710fSKristen Carlson Accardi if (do_c8_c9_c10) { 1449ca58710fSKristen Carlson Accardi if (get_msr(cpu, MSR_PKG_C8_RESIDENCY, &p->pc8)) 1450ca58710fSKristen Carlson Accardi return -13; 1451ca58710fSKristen Carlson Accardi if (get_msr(cpu, MSR_PKG_C9_RESIDENCY, &p->pc9)) 1452ca58710fSKristen Carlson Accardi return -13; 1453ca58710fSKristen Carlson Accardi if (get_msr(cpu, MSR_PKG_C10_RESIDENCY, &p->pc10)) 1454ca58710fSKristen Carlson Accardi return -13; 1455ca58710fSKristen Carlson Accardi } 1456889facbeSLen Brown if (do_rapl & RAPL_PKG) { 1457889facbeSLen Brown if (get_msr(cpu, MSR_PKG_ENERGY_STATUS, &msr)) 1458889facbeSLen Brown return -13; 1459889facbeSLen Brown p->energy_pkg = msr & 0xFFFFFFFF; 1460889facbeSLen Brown } 14619148494cSJacob Pan if (do_rapl & RAPL_CORES_ENERGY_STATUS) { 1462889facbeSLen Brown if (get_msr(cpu, MSR_PP0_ENERGY_STATUS, &msr)) 1463889facbeSLen Brown return -14; 1464889facbeSLen Brown p->energy_cores = msr & 0xFFFFFFFF; 1465889facbeSLen Brown } 1466889facbeSLen Brown if (do_rapl & RAPL_DRAM) { 1467889facbeSLen Brown if (get_msr(cpu, MSR_DRAM_ENERGY_STATUS, &msr)) 1468889facbeSLen Brown return -15; 1469889facbeSLen Brown p->energy_dram = msr & 0xFFFFFFFF; 1470889facbeSLen Brown } 1471889facbeSLen Brown if (do_rapl & RAPL_GFX) { 1472889facbeSLen Brown if (get_msr(cpu, MSR_PP1_ENERGY_STATUS, &msr)) 1473889facbeSLen Brown return -16; 1474889facbeSLen Brown p->energy_gfx = msr & 0xFFFFFFFF; 1475889facbeSLen Brown } 1476889facbeSLen Brown if (do_rapl & RAPL_PKG_PERF_STATUS) { 1477889facbeSLen Brown if (get_msr(cpu, MSR_PKG_PERF_STATUS, &msr)) 1478889facbeSLen Brown return -16; 1479889facbeSLen Brown p->rapl_pkg_perf_status = msr & 0xFFFFFFFF; 1480889facbeSLen Brown } 1481889facbeSLen Brown if (do_rapl & RAPL_DRAM_PERF_STATUS) { 1482889facbeSLen Brown if (get_msr(cpu, MSR_DRAM_PERF_STATUS, &msr)) 1483889facbeSLen Brown return -16; 1484889facbeSLen Brown p->rapl_dram_perf_status = msr & 0xFFFFFFFF; 1485889facbeSLen Brown } 1486*812db3f7SLen Brown if (DO_BIC(BIC_PkgTmp)) { 1487889facbeSLen Brown if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr)) 1488889facbeSLen Brown return -17; 1489889facbeSLen Brown p->pkg_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F); 1490889facbeSLen Brown } 1491fdf676e5SLen Brown 1492*812db3f7SLen Brown if (DO_BIC(BIC_GFX_rc6)) 1493fdf676e5SLen Brown p->gfx_rc6_ms = gfx_cur_rc6_ms; 1494fdf676e5SLen Brown 1495*812db3f7SLen Brown if (DO_BIC(BIC_GFXMHz)) 149627d47356SLen Brown p->gfx_mhz = gfx_cur_mhz; 149727d47356SLen Brown 1498388e9c81SLen Brown for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 1499388e9c81SLen Brown if (get_msr(cpu, mp->msr_num, &p->counter[i])) 1500388e9c81SLen Brown return -10; 1501388e9c81SLen Brown } 1502388e9c81SLen Brown 150315aaa346SLen Brown return 0; 1504103a8feaSLen Brown } 1505103a8feaSLen Brown 1506ee7e38e3SLen Brown /* 1507ee7e38e3SLen Brown * MSR_PKG_CST_CONFIG_CONTROL decoding for pkg_cstate_limit: 1508ee7e38e3SLen Brown * If you change the values, note they are used both in comparisons 1509ee7e38e3SLen Brown * (>= PCL__7) and to index pkg_cstate_limit_strings[]. 1510ee7e38e3SLen Brown */ 1511ee7e38e3SLen Brown 1512ee7e38e3SLen Brown #define PCLUKN 0 /* Unknown */ 1513ee7e38e3SLen Brown #define PCLRSV 1 /* Reserved */ 1514ee7e38e3SLen Brown #define PCL__0 2 /* PC0 */ 1515ee7e38e3SLen Brown #define PCL__1 3 /* PC1 */ 1516ee7e38e3SLen Brown #define PCL__2 4 /* PC2 */ 1517ee7e38e3SLen Brown #define PCL__3 5 /* PC3 */ 1518ee7e38e3SLen Brown #define PCL__4 6 /* PC4 */ 1519ee7e38e3SLen Brown #define PCL__6 7 /* PC6 */ 1520ee7e38e3SLen Brown #define PCL_6N 8 /* PC6 No Retention */ 1521ee7e38e3SLen Brown #define PCL_6R 9 /* PC6 Retention */ 1522ee7e38e3SLen Brown #define PCL__7 10 /* PC7 */ 1523ee7e38e3SLen Brown #define PCL_7S 11 /* PC7 Shrink */ 15240b2bb692SLen Brown #define PCL__8 12 /* PC8 */ 15250b2bb692SLen Brown #define PCL__9 13 /* PC9 */ 15260b2bb692SLen Brown #define PCLUNL 14 /* Unlimited */ 1527ee7e38e3SLen Brown 1528ee7e38e3SLen Brown int pkg_cstate_limit = PCLUKN; 1529ee7e38e3SLen Brown char *pkg_cstate_limit_strings[] = { "reserved", "unknown", "pc0", "pc1", "pc2", 15300b2bb692SLen Brown "pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "pc8", "pc9", "unlimited"}; 1531ee7e38e3SLen Brown 1532e9257f5fSLen Brown int nhm_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1533e9257f5fSLen Brown int snb_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1534e9257f5fSLen Brown int hsw_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1535e9257f5fSLen Brown int slv_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1536e9257f5fSLen Brown int amt_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1537e9257f5fSLen Brown int phi_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1538e4085d54SLen Brown int bxt_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1539d8ebb442SLen Brown int skx_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1540ee7e38e3SLen Brown 1541a2b7b749SLen Brown 1542a2b7b749SLen Brown static void 1543a2b7b749SLen Brown calculate_tsc_tweak() 1544a2b7b749SLen Brown { 1545a2b7b749SLen Brown tsc_tweak = base_hz / tsc_hz; 1546a2b7b749SLen Brown } 1547a2b7b749SLen Brown 1548fcd17211SLen Brown static void 1549fcd17211SLen Brown dump_nhm_platform_info(void) 1550103a8feaSLen Brown { 1551103a8feaSLen Brown unsigned long long msr; 1552103a8feaSLen Brown unsigned int ratio; 1553103a8feaSLen Brown 1554ec0adc53SLen Brown get_msr(base_cpu, MSR_PLATFORM_INFO, &msr); 1555103a8feaSLen Brown 1556b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr); 15576574a5d5SLen Brown 1558103a8feaSLen Brown ratio = (msr >> 40) & 0xFF; 1559b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max efficiency frequency\n", 1560103a8feaSLen Brown ratio, bclk, ratio * bclk); 1561103a8feaSLen Brown 1562103a8feaSLen Brown ratio = (msr >> 8) & 0xFF; 1563b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz base frequency\n", 1564103a8feaSLen Brown ratio, bclk, ratio * bclk); 1565103a8feaSLen Brown 15667ce7d5deSPrarit Bhargava get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr); 1567b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n", 1568bfae2052SLen Brown base_cpu, msr, msr & 0x2 ? "EN" : "DIS"); 156967920418SLen Brown 1570fcd17211SLen Brown return; 1571fcd17211SLen Brown } 1572fcd17211SLen Brown 1573fcd17211SLen Brown static void 1574fcd17211SLen Brown dump_hsw_turbo_ratio_limits(void) 1575fcd17211SLen Brown { 1576fcd17211SLen Brown unsigned long long msr; 1577fcd17211SLen Brown unsigned int ratio; 1578fcd17211SLen Brown 15797ce7d5deSPrarit Bhargava get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT2, &msr); 1580fcd17211SLen Brown 1581b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT2: 0x%08llx\n", base_cpu, msr); 1582fcd17211SLen Brown 1583fcd17211SLen Brown ratio = (msr >> 8) & 0xFF; 1584fcd17211SLen Brown if (ratio) 1585b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 18 active cores\n", 1586fcd17211SLen Brown ratio, bclk, ratio * bclk); 1587fcd17211SLen Brown 1588fcd17211SLen Brown ratio = (msr >> 0) & 0xFF; 1589fcd17211SLen Brown if (ratio) 1590b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 17 active cores\n", 1591fcd17211SLen Brown ratio, bclk, ratio * bclk); 1592fcd17211SLen Brown return; 1593fcd17211SLen Brown } 1594fcd17211SLen Brown 1595fcd17211SLen Brown static void 1596fcd17211SLen Brown dump_ivt_turbo_ratio_limits(void) 1597fcd17211SLen Brown { 1598fcd17211SLen Brown unsigned long long msr; 1599fcd17211SLen Brown unsigned int ratio; 16006574a5d5SLen Brown 16017ce7d5deSPrarit Bhargava get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &msr); 16026574a5d5SLen Brown 1603b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, msr); 16046574a5d5SLen Brown 16056574a5d5SLen Brown ratio = (msr >> 56) & 0xFF; 16066574a5d5SLen Brown if (ratio) 1607b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 16 active cores\n", 16086574a5d5SLen Brown ratio, bclk, ratio * bclk); 16096574a5d5SLen Brown 16106574a5d5SLen Brown ratio = (msr >> 48) & 0xFF; 16116574a5d5SLen Brown if (ratio) 1612b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 15 active cores\n", 16136574a5d5SLen Brown ratio, bclk, ratio * bclk); 16146574a5d5SLen Brown 16156574a5d5SLen Brown ratio = (msr >> 40) & 0xFF; 16166574a5d5SLen Brown if (ratio) 1617b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 14 active cores\n", 16186574a5d5SLen Brown ratio, bclk, ratio * bclk); 16196574a5d5SLen Brown 16206574a5d5SLen Brown ratio = (msr >> 32) & 0xFF; 16216574a5d5SLen Brown if (ratio) 1622b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 13 active cores\n", 16236574a5d5SLen Brown ratio, bclk, ratio * bclk); 16246574a5d5SLen Brown 16256574a5d5SLen Brown ratio = (msr >> 24) & 0xFF; 16266574a5d5SLen Brown if (ratio) 1627b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 12 active cores\n", 16286574a5d5SLen Brown ratio, bclk, ratio * bclk); 16296574a5d5SLen Brown 16306574a5d5SLen Brown ratio = (msr >> 16) & 0xFF; 16316574a5d5SLen Brown if (ratio) 1632b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 11 active cores\n", 16336574a5d5SLen Brown ratio, bclk, ratio * bclk); 16346574a5d5SLen Brown 16356574a5d5SLen Brown ratio = (msr >> 8) & 0xFF; 16366574a5d5SLen Brown if (ratio) 1637b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 10 active cores\n", 16386574a5d5SLen Brown ratio, bclk, ratio * bclk); 16396574a5d5SLen Brown 16406574a5d5SLen Brown ratio = (msr >> 0) & 0xFF; 16416574a5d5SLen Brown if (ratio) 1642b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 9 active cores\n", 16436574a5d5SLen Brown ratio, bclk, ratio * bclk); 1644103a8feaSLen Brown return; 1645fcd17211SLen Brown } 1646fcd17211SLen Brown 1647fcd17211SLen Brown static void 1648fcd17211SLen Brown dump_nhm_turbo_ratio_limits(void) 1649fcd17211SLen Brown { 1650fcd17211SLen Brown unsigned long long msr; 1651fcd17211SLen Brown unsigned int ratio; 1652103a8feaSLen Brown 16537ce7d5deSPrarit Bhargava get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr); 1654103a8feaSLen Brown 1655b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr); 16566574a5d5SLen Brown 16576574a5d5SLen Brown ratio = (msr >> 56) & 0xFF; 16586574a5d5SLen Brown if (ratio) 1659b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 8 active cores\n", 16606574a5d5SLen Brown ratio, bclk, ratio * bclk); 16616574a5d5SLen Brown 16626574a5d5SLen Brown ratio = (msr >> 48) & 0xFF; 16636574a5d5SLen Brown if (ratio) 1664b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 7 active cores\n", 16656574a5d5SLen Brown ratio, bclk, ratio * bclk); 16666574a5d5SLen Brown 16676574a5d5SLen Brown ratio = (msr >> 40) & 0xFF; 16686574a5d5SLen Brown if (ratio) 1669b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 6 active cores\n", 16706574a5d5SLen Brown ratio, bclk, ratio * bclk); 16716574a5d5SLen Brown 16726574a5d5SLen Brown ratio = (msr >> 32) & 0xFF; 16736574a5d5SLen Brown if (ratio) 1674b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 5 active cores\n", 16756574a5d5SLen Brown ratio, bclk, ratio * bclk); 16766574a5d5SLen Brown 1677103a8feaSLen Brown ratio = (msr >> 24) & 0xFF; 1678103a8feaSLen Brown if (ratio) 1679b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 4 active cores\n", 1680103a8feaSLen Brown ratio, bclk, ratio * bclk); 1681103a8feaSLen Brown 1682103a8feaSLen Brown ratio = (msr >> 16) & 0xFF; 1683103a8feaSLen Brown if (ratio) 1684b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 3 active cores\n", 1685103a8feaSLen Brown ratio, bclk, ratio * bclk); 1686103a8feaSLen Brown 1687103a8feaSLen Brown ratio = (msr >> 8) & 0xFF; 1688103a8feaSLen Brown if (ratio) 1689b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 2 active cores\n", 1690103a8feaSLen Brown ratio, bclk, ratio * bclk); 1691103a8feaSLen Brown 1692103a8feaSLen Brown ratio = (msr >> 0) & 0xFF; 1693103a8feaSLen Brown if (ratio) 1694b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 1 active cores\n", 1695103a8feaSLen Brown ratio, bclk, ratio * bclk); 1696fcd17211SLen Brown return; 1697fcd17211SLen Brown } 16983a9a941dSLen Brown 1699fcd17211SLen Brown static void 1700fb5d4327SDasaratharaman Chandramouli dump_knl_turbo_ratio_limits(void) 1701fb5d4327SDasaratharaman Chandramouli { 1702cbf97abaSHubert Chrzaniuk const unsigned int buckets_no = 7; 1703cbf97abaSHubert Chrzaniuk 1704fb5d4327SDasaratharaman Chandramouli unsigned long long msr; 1705cbf97abaSHubert Chrzaniuk int delta_cores, delta_ratio; 1706cbf97abaSHubert Chrzaniuk int i, b_nr; 1707cbf97abaSHubert Chrzaniuk unsigned int cores[buckets_no]; 1708cbf97abaSHubert Chrzaniuk unsigned int ratio[buckets_no]; 1709fb5d4327SDasaratharaman Chandramouli 1710ebf5926aSSrinivas Pandruvada get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr); 1711fb5d4327SDasaratharaman Chandramouli 1712b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", 1713bfae2052SLen Brown base_cpu, msr); 1714fb5d4327SDasaratharaman Chandramouli 1715fb5d4327SDasaratharaman Chandramouli /** 1716fb5d4327SDasaratharaman Chandramouli * Turbo encoding in KNL is as follows: 1717cbf97abaSHubert Chrzaniuk * [0] -- Reserved 1718cbf97abaSHubert Chrzaniuk * [7:1] -- Base value of number of active cores of bucket 1. 1719fb5d4327SDasaratharaman Chandramouli * [15:8] -- Base value of freq ratio of bucket 1. 1720fb5d4327SDasaratharaman Chandramouli * [20:16] -- +ve delta of number of active cores of bucket 2. 1721fb5d4327SDasaratharaman Chandramouli * i.e. active cores of bucket 2 = 1722fb5d4327SDasaratharaman Chandramouli * active cores of bucket 1 + delta 1723fb5d4327SDasaratharaman Chandramouli * [23:21] -- Negative delta of freq ratio of bucket 2. 1724fb5d4327SDasaratharaman Chandramouli * i.e. freq ratio of bucket 2 = 1725fb5d4327SDasaratharaman Chandramouli * freq ratio of bucket 1 - delta 1726fb5d4327SDasaratharaman Chandramouli * [28:24]-- +ve delta of number of active cores of bucket 3. 1727fb5d4327SDasaratharaman Chandramouli * [31:29]-- -ve delta of freq ratio of bucket 3. 1728fb5d4327SDasaratharaman Chandramouli * [36:32]-- +ve delta of number of active cores of bucket 4. 1729fb5d4327SDasaratharaman Chandramouli * [39:37]-- -ve delta of freq ratio of bucket 4. 1730fb5d4327SDasaratharaman Chandramouli * [44:40]-- +ve delta of number of active cores of bucket 5. 1731fb5d4327SDasaratharaman Chandramouli * [47:45]-- -ve delta of freq ratio of bucket 5. 1732fb5d4327SDasaratharaman Chandramouli * [52:48]-- +ve delta of number of active cores of bucket 6. 1733fb5d4327SDasaratharaman Chandramouli * [55:53]-- -ve delta of freq ratio of bucket 6. 1734fb5d4327SDasaratharaman Chandramouli * [60:56]-- +ve delta of number of active cores of bucket 7. 1735fb5d4327SDasaratharaman Chandramouli * [63:61]-- -ve delta of freq ratio of bucket 7. 1736fb5d4327SDasaratharaman Chandramouli */ 1737fb5d4327SDasaratharaman Chandramouli 1738cbf97abaSHubert Chrzaniuk b_nr = 0; 1739cbf97abaSHubert Chrzaniuk cores[b_nr] = (msr & 0xFF) >> 1; 1740cbf97abaSHubert Chrzaniuk ratio[b_nr] = (msr >> 8) & 0xFF; 1741cbf97abaSHubert Chrzaniuk 1742cbf97abaSHubert Chrzaniuk for (i = 16; i < 64; i += 8) { 1743fb5d4327SDasaratharaman Chandramouli delta_cores = (msr >> i) & 0x1F; 1744cbf97abaSHubert Chrzaniuk delta_ratio = (msr >> (i + 5)) & 0x7; 1745fb5d4327SDasaratharaman Chandramouli 1746cbf97abaSHubert Chrzaniuk cores[b_nr + 1] = cores[b_nr] + delta_cores; 1747cbf97abaSHubert Chrzaniuk ratio[b_nr + 1] = ratio[b_nr] - delta_ratio; 1748cbf97abaSHubert Chrzaniuk b_nr++; 1749fb5d4327SDasaratharaman Chandramouli } 1750cbf97abaSHubert Chrzaniuk 1751cbf97abaSHubert Chrzaniuk for (i = buckets_no - 1; i >= 0; i--) 1752cbf97abaSHubert Chrzaniuk if (i > 0 ? ratio[i] != ratio[i - 1] : 1) 1753b7d8c148SLen Brown fprintf(outf, 1754fb5d4327SDasaratharaman Chandramouli "%d * %.0f = %.0f MHz max turbo %d active cores\n", 1755cbf97abaSHubert Chrzaniuk ratio[i], bclk, ratio[i] * bclk, cores[i]); 1756fb5d4327SDasaratharaman Chandramouli } 1757fb5d4327SDasaratharaman Chandramouli 1758fb5d4327SDasaratharaman Chandramouli static void 1759fcd17211SLen Brown dump_nhm_cst_cfg(void) 1760fcd17211SLen Brown { 1761fcd17211SLen Brown unsigned long long msr; 1762fcd17211SLen Brown 17637ce7d5deSPrarit Bhargava get_msr(base_cpu, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr); 1764fcd17211SLen Brown 1765fcd17211SLen Brown #define SNB_C1_AUTO_UNDEMOTE (1UL << 27) 1766fcd17211SLen Brown #define SNB_C3_AUTO_UNDEMOTE (1UL << 28) 1767fcd17211SLen Brown 1768b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x%08llx", base_cpu, msr); 1769fcd17211SLen Brown 1770b7d8c148SLen Brown fprintf(outf, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: %s)\n", 1771fcd17211SLen Brown (msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "", 1772fcd17211SLen Brown (msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "", 1773fcd17211SLen Brown (msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "", 1774fcd17211SLen Brown (msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "", 1775fcd17211SLen Brown (msr & (1 << 15)) ? "" : "UN", 17766c34f160SLen Brown (unsigned int)msr & 0xF, 1777fcd17211SLen Brown pkg_cstate_limit_strings[pkg_cstate_limit]); 1778fcd17211SLen Brown return; 1779103a8feaSLen Brown } 1780103a8feaSLen Brown 17816fb3143bSLen Brown static void 17826fb3143bSLen Brown dump_config_tdp(void) 17836fb3143bSLen Brown { 17846fb3143bSLen Brown unsigned long long msr; 17856fb3143bSLen Brown 17866fb3143bSLen Brown get_msr(base_cpu, MSR_CONFIG_TDP_NOMINAL, &msr); 1787b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_CONFIG_TDP_NOMINAL: 0x%08llx", base_cpu, msr); 1788685b535bSChen Yu fprintf(outf, " (base_ratio=%d)\n", (unsigned int)msr & 0xFF); 17896fb3143bSLen Brown 17906fb3143bSLen Brown get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_1, &msr); 1791b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_1: 0x%08llx (", base_cpu, msr); 17926fb3143bSLen Brown if (msr) { 1793685b535bSChen Yu fprintf(outf, "PKG_MIN_PWR_LVL1=%d ", (unsigned int)(msr >> 48) & 0x7FFF); 1794685b535bSChen Yu fprintf(outf, "PKG_MAX_PWR_LVL1=%d ", (unsigned int)(msr >> 32) & 0x7FFF); 1795685b535bSChen Yu fprintf(outf, "LVL1_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF); 1796685b535bSChen Yu fprintf(outf, "PKG_TDP_LVL1=%d", (unsigned int)(msr) & 0x7FFF); 17976fb3143bSLen Brown } 1798b7d8c148SLen Brown fprintf(outf, ")\n"); 17996fb3143bSLen Brown 18006fb3143bSLen Brown get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_2, &msr); 1801b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_2: 0x%08llx (", base_cpu, msr); 18026fb3143bSLen Brown if (msr) { 1803685b535bSChen Yu fprintf(outf, "PKG_MIN_PWR_LVL2=%d ", (unsigned int)(msr >> 48) & 0x7FFF); 1804685b535bSChen Yu fprintf(outf, "PKG_MAX_PWR_LVL2=%d ", (unsigned int)(msr >> 32) & 0x7FFF); 1805685b535bSChen Yu fprintf(outf, "LVL2_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF); 1806685b535bSChen Yu fprintf(outf, "PKG_TDP_LVL2=%d", (unsigned int)(msr) & 0x7FFF); 18076fb3143bSLen Brown } 1808b7d8c148SLen Brown fprintf(outf, ")\n"); 18096fb3143bSLen Brown 18106fb3143bSLen Brown get_msr(base_cpu, MSR_CONFIG_TDP_CONTROL, &msr); 1811b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_CONFIG_TDP_CONTROL: 0x%08llx (", base_cpu, msr); 18126fb3143bSLen Brown if ((msr) & 0x3) 1813b7d8c148SLen Brown fprintf(outf, "TDP_LEVEL=%d ", (unsigned int)(msr) & 0x3); 1814b7d8c148SLen Brown fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1); 1815b7d8c148SLen Brown fprintf(outf, ")\n"); 18166fb3143bSLen Brown 18176fb3143bSLen Brown get_msr(base_cpu, MSR_TURBO_ACTIVATION_RATIO, &msr); 1818b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_TURBO_ACTIVATION_RATIO: 0x%08llx (", base_cpu, msr); 1819685b535bSChen Yu fprintf(outf, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0xFF); 1820b7d8c148SLen Brown fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1); 1821b7d8c148SLen Brown fprintf(outf, ")\n"); 18226fb3143bSLen Brown } 18235a63426eSLen Brown 18245a63426eSLen Brown unsigned int irtl_time_units[] = {1, 32, 1024, 32768, 1048576, 33554432, 0, 0 }; 18255a63426eSLen Brown 18265a63426eSLen Brown void print_irtl(void) 18275a63426eSLen Brown { 18285a63426eSLen Brown unsigned long long msr; 18295a63426eSLen Brown 18305a63426eSLen Brown get_msr(base_cpu, MSR_PKGC3_IRTL, &msr); 18315a63426eSLen Brown fprintf(outf, "cpu%d: MSR_PKGC3_IRTL: 0x%08llx (", base_cpu, msr); 18325a63426eSLen Brown fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", 18335a63426eSLen Brown (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 18345a63426eSLen Brown 18355a63426eSLen Brown get_msr(base_cpu, MSR_PKGC6_IRTL, &msr); 18365a63426eSLen Brown fprintf(outf, "cpu%d: MSR_PKGC6_IRTL: 0x%08llx (", base_cpu, msr); 18375a63426eSLen Brown fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", 18385a63426eSLen Brown (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 18395a63426eSLen Brown 18405a63426eSLen Brown get_msr(base_cpu, MSR_PKGC7_IRTL, &msr); 18415a63426eSLen Brown fprintf(outf, "cpu%d: MSR_PKGC7_IRTL: 0x%08llx (", base_cpu, msr); 18425a63426eSLen Brown fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", 18435a63426eSLen Brown (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 18445a63426eSLen Brown 18455a63426eSLen Brown if (!do_irtl_hsw) 18465a63426eSLen Brown return; 18475a63426eSLen Brown 18485a63426eSLen Brown get_msr(base_cpu, MSR_PKGC8_IRTL, &msr); 18495a63426eSLen Brown fprintf(outf, "cpu%d: MSR_PKGC8_IRTL: 0x%08llx (", base_cpu, msr); 18505a63426eSLen Brown fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", 18515a63426eSLen Brown (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 18525a63426eSLen Brown 18535a63426eSLen Brown get_msr(base_cpu, MSR_PKGC9_IRTL, &msr); 18545a63426eSLen Brown fprintf(outf, "cpu%d: MSR_PKGC9_IRTL: 0x%08llx (", base_cpu, msr); 18555a63426eSLen Brown fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", 18565a63426eSLen Brown (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 18575a63426eSLen Brown 18585a63426eSLen Brown get_msr(base_cpu, MSR_PKGC10_IRTL, &msr); 18595a63426eSLen Brown fprintf(outf, "cpu%d: MSR_PKGC10_IRTL: 0x%08llx (", base_cpu, msr); 18605a63426eSLen Brown fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", 18615a63426eSLen Brown (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 18625a63426eSLen Brown 18635a63426eSLen Brown } 186436229897SLen Brown void free_fd_percpu(void) 186536229897SLen Brown { 186636229897SLen Brown int i; 186736229897SLen Brown 186801a67adfSMika Westerberg for (i = 0; i < topo.max_cpu_num + 1; ++i) { 186936229897SLen Brown if (fd_percpu[i] != 0) 187036229897SLen Brown close(fd_percpu[i]); 187136229897SLen Brown } 187236229897SLen Brown 187336229897SLen Brown free(fd_percpu); 18746fb3143bSLen Brown } 18756fb3143bSLen Brown 1876c98d5d94SLen Brown void free_all_buffers(void) 1877103a8feaSLen Brown { 1878c98d5d94SLen Brown CPU_FREE(cpu_present_set); 1879c98d5d94SLen Brown cpu_present_set = NULL; 188036229897SLen Brown cpu_present_setsize = 0; 1881103a8feaSLen Brown 1882c98d5d94SLen Brown CPU_FREE(cpu_affinity_set); 1883c98d5d94SLen Brown cpu_affinity_set = NULL; 1884c98d5d94SLen Brown cpu_affinity_setsize = 0; 1885103a8feaSLen Brown 1886c98d5d94SLen Brown free(thread_even); 1887c98d5d94SLen Brown free(core_even); 1888c98d5d94SLen Brown free(package_even); 1889103a8feaSLen Brown 1890c98d5d94SLen Brown thread_even = NULL; 1891c98d5d94SLen Brown core_even = NULL; 1892c98d5d94SLen Brown package_even = NULL; 1893103a8feaSLen Brown 1894c98d5d94SLen Brown free(thread_odd); 1895c98d5d94SLen Brown free(core_odd); 1896c98d5d94SLen Brown free(package_odd); 1897103a8feaSLen Brown 1898c98d5d94SLen Brown thread_odd = NULL; 1899c98d5d94SLen Brown core_odd = NULL; 1900c98d5d94SLen Brown package_odd = NULL; 1901103a8feaSLen Brown 1902c98d5d94SLen Brown free(output_buffer); 1903c98d5d94SLen Brown output_buffer = NULL; 1904c98d5d94SLen Brown outp = NULL; 190536229897SLen Brown 190636229897SLen Brown free_fd_percpu(); 1907562a2d37SLen Brown 1908562a2d37SLen Brown free(irq_column_2_cpu); 1909562a2d37SLen Brown free(irqs_per_cpu); 1910103a8feaSLen Brown } 1911103a8feaSLen Brown 1912103a8feaSLen Brown /* 191357a42a34SJosh Triplett * Open a file, and exit on failure 191457a42a34SJosh Triplett */ 191557a42a34SJosh Triplett FILE *fopen_or_die(const char *path, const char *mode) 191657a42a34SJosh Triplett { 1917b7d8c148SLen Brown FILE *filep = fopen(path, mode); 1918b2c95d90SJosh Triplett if (!filep) 1919b2c95d90SJosh Triplett err(1, "%s: open failed", path); 192057a42a34SJosh Triplett return filep; 192157a42a34SJosh Triplett } 192257a42a34SJosh Triplett 192357a42a34SJosh Triplett /* 192495aebc44SJosh Triplett * Parse a file containing a single int. 192595aebc44SJosh Triplett */ 192695aebc44SJosh Triplett int parse_int_file(const char *fmt, ...) 192795aebc44SJosh Triplett { 192895aebc44SJosh Triplett va_list args; 192995aebc44SJosh Triplett char path[PATH_MAX]; 193095aebc44SJosh Triplett FILE *filep; 193195aebc44SJosh Triplett int value; 193295aebc44SJosh Triplett 193395aebc44SJosh Triplett va_start(args, fmt); 193495aebc44SJosh Triplett vsnprintf(path, sizeof(path), fmt, args); 193595aebc44SJosh Triplett va_end(args); 193657a42a34SJosh Triplett filep = fopen_or_die(path, "r"); 1937b2c95d90SJosh Triplett if (fscanf(filep, "%d", &value) != 1) 1938b2c95d90SJosh Triplett err(1, "%s: failed to parse number from file", path); 193995aebc44SJosh Triplett fclose(filep); 194095aebc44SJosh Triplett return value; 194195aebc44SJosh Triplett } 194295aebc44SJosh Triplett 194395aebc44SJosh Triplett /* 1944e275b388SDasaratharaman Chandramouli * get_cpu_position_in_core(cpu) 1945e275b388SDasaratharaman Chandramouli * return the position of the CPU among its HT siblings in the core 1946e275b388SDasaratharaman Chandramouli * return -1 if the sibling is not in list 1947103a8feaSLen Brown */ 1948e275b388SDasaratharaman Chandramouli int get_cpu_position_in_core(int cpu) 1949103a8feaSLen Brown { 1950e275b388SDasaratharaman Chandramouli char path[64]; 1951e275b388SDasaratharaman Chandramouli FILE *filep; 1952e275b388SDasaratharaman Chandramouli int this_cpu; 1953e275b388SDasaratharaman Chandramouli char character; 1954e275b388SDasaratharaman Chandramouli int i; 1955e275b388SDasaratharaman Chandramouli 1956e275b388SDasaratharaman Chandramouli sprintf(path, 1957e275b388SDasaratharaman Chandramouli "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", 1958e275b388SDasaratharaman Chandramouli cpu); 1959e275b388SDasaratharaman Chandramouli filep = fopen(path, "r"); 1960e275b388SDasaratharaman Chandramouli if (filep == NULL) { 1961e275b388SDasaratharaman Chandramouli perror(path); 1962e275b388SDasaratharaman Chandramouli exit(1); 1963e275b388SDasaratharaman Chandramouli } 1964e275b388SDasaratharaman Chandramouli 1965e275b388SDasaratharaman Chandramouli for (i = 0; i < topo.num_threads_per_core; i++) { 1966e275b388SDasaratharaman Chandramouli fscanf(filep, "%d", &this_cpu); 1967e275b388SDasaratharaman Chandramouli if (this_cpu == cpu) { 1968e275b388SDasaratharaman Chandramouli fclose(filep); 1969e275b388SDasaratharaman Chandramouli return i; 1970e275b388SDasaratharaman Chandramouli } 1971e275b388SDasaratharaman Chandramouli 1972e275b388SDasaratharaman Chandramouli /* Account for no separator after last thread*/ 1973e275b388SDasaratharaman Chandramouli if (i != (topo.num_threads_per_core - 1)) 1974e275b388SDasaratharaman Chandramouli fscanf(filep, "%c", &character); 1975e275b388SDasaratharaman Chandramouli } 1976e275b388SDasaratharaman Chandramouli 1977e275b388SDasaratharaman Chandramouli fclose(filep); 1978e275b388SDasaratharaman Chandramouli return -1; 1979c98d5d94SLen Brown } 1980103a8feaSLen Brown 1981c98d5d94SLen Brown /* 1982c98d5d94SLen Brown * cpu_is_first_core_in_package(cpu) 1983c98d5d94SLen Brown * return 1 if given CPU is 1st core in package 1984c98d5d94SLen Brown */ 1985c98d5d94SLen Brown int cpu_is_first_core_in_package(int cpu) 1986c98d5d94SLen Brown { 198795aebc44SJosh Triplett return cpu == parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_siblings_list", cpu); 1988103a8feaSLen Brown } 1989103a8feaSLen Brown 1990103a8feaSLen Brown int get_physical_package_id(int cpu) 1991103a8feaSLen Brown { 199295aebc44SJosh Triplett return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu); 1993103a8feaSLen Brown } 1994103a8feaSLen Brown 1995103a8feaSLen Brown int get_core_id(int cpu) 1996103a8feaSLen Brown { 199795aebc44SJosh Triplett return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_id", cpu); 1998103a8feaSLen Brown } 1999103a8feaSLen Brown 2000c98d5d94SLen Brown int get_num_ht_siblings(int cpu) 2001c98d5d94SLen Brown { 2002c98d5d94SLen Brown char path[80]; 2003c98d5d94SLen Brown FILE *filep; 2004e275b388SDasaratharaman Chandramouli int sib1; 2005e275b388SDasaratharaman Chandramouli int matches = 0; 2006c98d5d94SLen Brown char character; 2007e275b388SDasaratharaman Chandramouli char str[100]; 2008e275b388SDasaratharaman Chandramouli char *ch; 2009c98d5d94SLen Brown 2010c98d5d94SLen Brown sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu); 201157a42a34SJosh Triplett filep = fopen_or_die(path, "r"); 2012e275b388SDasaratharaman Chandramouli 2013103a8feaSLen Brown /* 2014c98d5d94SLen Brown * file format: 2015e275b388SDasaratharaman Chandramouli * A ',' separated or '-' separated set of numbers 2016e275b388SDasaratharaman Chandramouli * (eg 1-2 or 1,3,4,5) 2017c98d5d94SLen Brown */ 2018e275b388SDasaratharaman Chandramouli fscanf(filep, "%d%c\n", &sib1, &character); 2019e275b388SDasaratharaman Chandramouli fseek(filep, 0, SEEK_SET); 2020e275b388SDasaratharaman Chandramouli fgets(str, 100, filep); 2021e275b388SDasaratharaman Chandramouli ch = strchr(str, character); 2022e275b388SDasaratharaman Chandramouli while (ch != NULL) { 2023e275b388SDasaratharaman Chandramouli matches++; 2024e275b388SDasaratharaman Chandramouli ch = strchr(ch+1, character); 2025e275b388SDasaratharaman Chandramouli } 2026c98d5d94SLen Brown 2027c98d5d94SLen Brown fclose(filep); 2028e275b388SDasaratharaman Chandramouli return matches+1; 2029c98d5d94SLen Brown } 2030c98d5d94SLen Brown 2031c98d5d94SLen Brown /* 2032c98d5d94SLen Brown * run func(thread, core, package) in topology order 2033c98d5d94SLen Brown * skip non-present cpus 2034103a8feaSLen Brown */ 2035103a8feaSLen Brown 2036c98d5d94SLen Brown int for_all_cpus_2(int (func)(struct thread_data *, struct core_data *, 2037c98d5d94SLen Brown struct pkg_data *, struct thread_data *, struct core_data *, 2038c98d5d94SLen Brown struct pkg_data *), struct thread_data *thread_base, 2039c98d5d94SLen Brown struct core_data *core_base, struct pkg_data *pkg_base, 2040c98d5d94SLen Brown struct thread_data *thread_base2, struct core_data *core_base2, 2041c98d5d94SLen Brown struct pkg_data *pkg_base2) 2042c98d5d94SLen Brown { 2043c98d5d94SLen Brown int retval, pkg_no, core_no, thread_no; 2044c98d5d94SLen Brown 2045c98d5d94SLen Brown for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) { 2046c98d5d94SLen Brown for (core_no = 0; core_no < topo.num_cores_per_pkg; ++core_no) { 2047c98d5d94SLen Brown for (thread_no = 0; thread_no < 2048c98d5d94SLen Brown topo.num_threads_per_core; ++thread_no) { 2049c98d5d94SLen Brown struct thread_data *t, *t2; 2050c98d5d94SLen Brown struct core_data *c, *c2; 2051c98d5d94SLen Brown struct pkg_data *p, *p2; 2052c98d5d94SLen Brown 2053c98d5d94SLen Brown t = GET_THREAD(thread_base, thread_no, core_no, pkg_no); 2054c98d5d94SLen Brown 2055c98d5d94SLen Brown if (cpu_is_not_present(t->cpu_id)) 2056c98d5d94SLen Brown continue; 2057c98d5d94SLen Brown 2058c98d5d94SLen Brown t2 = GET_THREAD(thread_base2, thread_no, core_no, pkg_no); 2059c98d5d94SLen Brown 2060c98d5d94SLen Brown c = GET_CORE(core_base, core_no, pkg_no); 2061c98d5d94SLen Brown c2 = GET_CORE(core_base2, core_no, pkg_no); 2062c98d5d94SLen Brown 2063c98d5d94SLen Brown p = GET_PKG(pkg_base, pkg_no); 2064c98d5d94SLen Brown p2 = GET_PKG(pkg_base2, pkg_no); 2065c98d5d94SLen Brown 2066c98d5d94SLen Brown retval = func(t, c, p, t2, c2, p2); 2067c98d5d94SLen Brown if (retval) 2068c98d5d94SLen Brown return retval; 2069c98d5d94SLen Brown } 2070c98d5d94SLen Brown } 2071c98d5d94SLen Brown } 2072c98d5d94SLen Brown return 0; 2073c98d5d94SLen Brown } 2074c98d5d94SLen Brown 2075c98d5d94SLen Brown /* 2076c98d5d94SLen Brown * run func(cpu) on every cpu in /proc/stat 2077c98d5d94SLen Brown * return max_cpu number 2078c98d5d94SLen Brown */ 2079c98d5d94SLen Brown int for_all_proc_cpus(int (func)(int)) 2080103a8feaSLen Brown { 2081103a8feaSLen Brown FILE *fp; 2082c98d5d94SLen Brown int cpu_num; 2083103a8feaSLen Brown int retval; 2084103a8feaSLen Brown 208557a42a34SJosh Triplett fp = fopen_or_die(proc_stat, "r"); 2086103a8feaSLen Brown 2087103a8feaSLen Brown retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n"); 2088b2c95d90SJosh Triplett if (retval != 0) 2089b2c95d90SJosh Triplett err(1, "%s: failed to parse format", proc_stat); 2090103a8feaSLen Brown 2091c98d5d94SLen Brown while (1) { 2092c98d5d94SLen Brown retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num); 2093103a8feaSLen Brown if (retval != 1) 2094103a8feaSLen Brown break; 2095103a8feaSLen Brown 2096c98d5d94SLen Brown retval = func(cpu_num); 2097c98d5d94SLen Brown if (retval) { 2098c98d5d94SLen Brown fclose(fp); 2099c98d5d94SLen Brown return(retval); 2100c98d5d94SLen Brown } 2101103a8feaSLen Brown } 2102103a8feaSLen Brown fclose(fp); 2103c98d5d94SLen Brown return 0; 2104103a8feaSLen Brown } 2105103a8feaSLen Brown 2106103a8feaSLen Brown void re_initialize(void) 2107103a8feaSLen Brown { 2108c98d5d94SLen Brown free_all_buffers(); 2109c98d5d94SLen Brown setup_all_buffers(); 2110c98d5d94SLen Brown printf("turbostat: re-initialized with num_cpus %d\n", topo.num_cpus); 2111103a8feaSLen Brown } 2112103a8feaSLen Brown 2113c98d5d94SLen Brown 2114103a8feaSLen Brown /* 2115c98d5d94SLen Brown * count_cpus() 2116c98d5d94SLen Brown * remember the last one seen, it will be the max 2117103a8feaSLen Brown */ 2118c98d5d94SLen Brown int count_cpus(int cpu) 2119103a8feaSLen Brown { 2120c98d5d94SLen Brown if (topo.max_cpu_num < cpu) 2121c98d5d94SLen Brown topo.max_cpu_num = cpu; 2122103a8feaSLen Brown 2123c98d5d94SLen Brown topo.num_cpus += 1; 2124c98d5d94SLen Brown return 0; 2125103a8feaSLen Brown } 2126c98d5d94SLen Brown int mark_cpu_present(int cpu) 2127c98d5d94SLen Brown { 2128c98d5d94SLen Brown CPU_SET_S(cpu, cpu_present_setsize, cpu_present_set); 212915aaa346SLen Brown return 0; 2130103a8feaSLen Brown } 2131103a8feaSLen Brown 2132562a2d37SLen Brown /* 2133562a2d37SLen Brown * snapshot_proc_interrupts() 2134562a2d37SLen Brown * 2135562a2d37SLen Brown * read and record summary of /proc/interrupts 2136562a2d37SLen Brown * 2137562a2d37SLen Brown * return 1 if config change requires a restart, else return 0 2138562a2d37SLen Brown */ 2139562a2d37SLen Brown int snapshot_proc_interrupts(void) 2140562a2d37SLen Brown { 2141562a2d37SLen Brown static FILE *fp; 2142562a2d37SLen Brown int column, retval; 2143562a2d37SLen Brown 2144562a2d37SLen Brown if (fp == NULL) 2145562a2d37SLen Brown fp = fopen_or_die("/proc/interrupts", "r"); 2146562a2d37SLen Brown else 2147562a2d37SLen Brown rewind(fp); 2148562a2d37SLen Brown 2149562a2d37SLen Brown /* read 1st line of /proc/interrupts to get cpu* name for each column */ 2150562a2d37SLen Brown for (column = 0; column < topo.num_cpus; ++column) { 2151562a2d37SLen Brown int cpu_number; 2152562a2d37SLen Brown 2153562a2d37SLen Brown retval = fscanf(fp, " CPU%d", &cpu_number); 2154562a2d37SLen Brown if (retval != 1) 2155562a2d37SLen Brown break; 2156562a2d37SLen Brown 2157562a2d37SLen Brown if (cpu_number > topo.max_cpu_num) { 2158562a2d37SLen Brown warn("/proc/interrupts: cpu%d: > %d", cpu_number, topo.max_cpu_num); 2159562a2d37SLen Brown return 1; 2160562a2d37SLen Brown } 2161562a2d37SLen Brown 2162562a2d37SLen Brown irq_column_2_cpu[column] = cpu_number; 2163562a2d37SLen Brown irqs_per_cpu[cpu_number] = 0; 2164562a2d37SLen Brown } 2165562a2d37SLen Brown 2166562a2d37SLen Brown /* read /proc/interrupt count lines and sum up irqs per cpu */ 2167562a2d37SLen Brown while (1) { 2168562a2d37SLen Brown int column; 2169562a2d37SLen Brown char buf[64]; 2170562a2d37SLen Brown 2171562a2d37SLen Brown retval = fscanf(fp, " %s:", buf); /* flush irq# "N:" */ 2172562a2d37SLen Brown if (retval != 1) 2173562a2d37SLen Brown break; 2174562a2d37SLen Brown 2175562a2d37SLen Brown /* read the count per cpu */ 2176562a2d37SLen Brown for (column = 0; column < topo.num_cpus; ++column) { 2177562a2d37SLen Brown 2178562a2d37SLen Brown int cpu_number, irq_count; 2179562a2d37SLen Brown 2180562a2d37SLen Brown retval = fscanf(fp, " %d", &irq_count); 2181562a2d37SLen Brown if (retval != 1) 2182562a2d37SLen Brown break; 2183562a2d37SLen Brown 2184562a2d37SLen Brown cpu_number = irq_column_2_cpu[column]; 2185562a2d37SLen Brown irqs_per_cpu[cpu_number] += irq_count; 2186562a2d37SLen Brown 2187562a2d37SLen Brown } 2188562a2d37SLen Brown 2189562a2d37SLen Brown while (getc(fp) != '\n') 2190562a2d37SLen Brown ; /* flush interrupt description */ 2191562a2d37SLen Brown 2192562a2d37SLen Brown } 2193562a2d37SLen Brown return 0; 2194562a2d37SLen Brown } 219527d47356SLen Brown /* 2196fdf676e5SLen Brown * snapshot_gfx_rc6_ms() 2197fdf676e5SLen Brown * 2198fdf676e5SLen Brown * record snapshot of 2199fdf676e5SLen Brown * /sys/class/drm/card0/power/rc6_residency_ms 2200fdf676e5SLen Brown * 2201fdf676e5SLen Brown * return 1 if config change requires a restart, else return 0 2202fdf676e5SLen Brown */ 2203fdf676e5SLen Brown int snapshot_gfx_rc6_ms(void) 2204fdf676e5SLen Brown { 2205fdf676e5SLen Brown FILE *fp; 2206fdf676e5SLen Brown int retval; 2207fdf676e5SLen Brown 2208fdf676e5SLen Brown fp = fopen_or_die("/sys/class/drm/card0/power/rc6_residency_ms", "r"); 2209fdf676e5SLen Brown 2210fdf676e5SLen Brown retval = fscanf(fp, "%lld", &gfx_cur_rc6_ms); 2211fdf676e5SLen Brown if (retval != 1) 2212fdf676e5SLen Brown err(1, "GFX rc6"); 2213fdf676e5SLen Brown 2214fdf676e5SLen Brown fclose(fp); 2215fdf676e5SLen Brown 2216fdf676e5SLen Brown return 0; 2217fdf676e5SLen Brown } 2218fdf676e5SLen Brown /* 221927d47356SLen Brown * snapshot_gfx_mhz() 222027d47356SLen Brown * 222127d47356SLen Brown * record snapshot of 222227d47356SLen Brown * /sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz 222327d47356SLen Brown * 222427d47356SLen Brown * return 1 if config change requires a restart, else return 0 222527d47356SLen Brown */ 222627d47356SLen Brown int snapshot_gfx_mhz(void) 222727d47356SLen Brown { 222827d47356SLen Brown static FILE *fp; 222927d47356SLen Brown int retval; 223027d47356SLen Brown 223127d47356SLen Brown if (fp == NULL) 223227d47356SLen Brown fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", "r"); 223327d47356SLen Brown else 223427d47356SLen Brown rewind(fp); 223527d47356SLen Brown 223627d47356SLen Brown retval = fscanf(fp, "%d", &gfx_cur_mhz); 223727d47356SLen Brown if (retval != 1) 223827d47356SLen Brown err(1, "GFX MHz"); 223927d47356SLen Brown 224027d47356SLen Brown return 0; 224127d47356SLen Brown } 2242562a2d37SLen Brown 2243562a2d37SLen Brown /* 2244562a2d37SLen Brown * snapshot /proc and /sys files 2245562a2d37SLen Brown * 2246562a2d37SLen Brown * return 1 if configuration restart needed, else return 0 2247562a2d37SLen Brown */ 2248562a2d37SLen Brown int snapshot_proc_sysfs_files(void) 2249562a2d37SLen Brown { 2250562a2d37SLen Brown if (snapshot_proc_interrupts()) 2251562a2d37SLen Brown return 1; 2252562a2d37SLen Brown 2253*812db3f7SLen Brown if (DO_BIC(BIC_GFX_rc6)) 2254fdf676e5SLen Brown snapshot_gfx_rc6_ms(); 2255fdf676e5SLen Brown 2256*812db3f7SLen Brown if (DO_BIC(BIC_GFXMHz)) 225727d47356SLen Brown snapshot_gfx_mhz(); 225827d47356SLen Brown 2259562a2d37SLen Brown return 0; 2260562a2d37SLen Brown } 2261562a2d37SLen Brown 2262103a8feaSLen Brown void turbostat_loop() 2263103a8feaSLen Brown { 2264c98d5d94SLen Brown int retval; 2265e52966c0SLen Brown int restarted = 0; 2266c98d5d94SLen Brown 2267103a8feaSLen Brown restart: 2268e52966c0SLen Brown restarted++; 2269e52966c0SLen Brown 2270562a2d37SLen Brown snapshot_proc_sysfs_files(); 2271c98d5d94SLen Brown retval = for_all_cpus(get_counters, EVEN_COUNTERS); 2272d91bb17cSLen Brown if (retval < -1) { 2273d91bb17cSLen Brown exit(retval); 2274d91bb17cSLen Brown } else if (retval == -1) { 2275e52966c0SLen Brown if (restarted > 1) { 2276e52966c0SLen Brown exit(retval); 2277e52966c0SLen Brown } 2278c98d5d94SLen Brown re_initialize(); 2279c98d5d94SLen Brown goto restart; 2280c98d5d94SLen Brown } 2281e52966c0SLen Brown restarted = 0; 2282103a8feaSLen Brown gettimeofday(&tv_even, (struct timezone *)NULL); 2283103a8feaSLen Brown 2284103a8feaSLen Brown while (1) { 2285c98d5d94SLen Brown if (for_all_proc_cpus(cpu_is_not_present)) { 2286103a8feaSLen Brown re_initialize(); 2287103a8feaSLen Brown goto restart; 2288103a8feaSLen Brown } 22892a0609c0SLen Brown nanosleep(&interval_ts, NULL); 2290562a2d37SLen Brown if (snapshot_proc_sysfs_files()) 2291562a2d37SLen Brown goto restart; 2292c98d5d94SLen Brown retval = for_all_cpus(get_counters, ODD_COUNTERS); 2293d91bb17cSLen Brown if (retval < -1) { 2294d91bb17cSLen Brown exit(retval); 2295d91bb17cSLen Brown } else if (retval == -1) { 229615aaa346SLen Brown re_initialize(); 229715aaa346SLen Brown goto restart; 229815aaa346SLen Brown } 2299103a8feaSLen Brown gettimeofday(&tv_odd, (struct timezone *)NULL); 2300103a8feaSLen Brown timersub(&tv_odd, &tv_even, &tv_delta); 2301ba3dec99SLen Brown if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS)) { 2302ba3dec99SLen Brown re_initialize(); 2303ba3dec99SLen Brown goto restart; 2304ba3dec99SLen Brown } 2305c98d5d94SLen Brown compute_average(EVEN_COUNTERS); 2306c98d5d94SLen Brown format_all_counters(EVEN_COUNTERS); 2307b7d8c148SLen Brown flush_output_stdout(); 23082a0609c0SLen Brown nanosleep(&interval_ts, NULL); 2309562a2d37SLen Brown if (snapshot_proc_sysfs_files()) 2310562a2d37SLen Brown goto restart; 2311c98d5d94SLen Brown retval = for_all_cpus(get_counters, EVEN_COUNTERS); 2312d91bb17cSLen Brown if (retval < -1) { 2313d91bb17cSLen Brown exit(retval); 2314d91bb17cSLen Brown } else if (retval == -1) { 2315103a8feaSLen Brown re_initialize(); 2316103a8feaSLen Brown goto restart; 2317103a8feaSLen Brown } 2318103a8feaSLen Brown gettimeofday(&tv_even, (struct timezone *)NULL); 2319103a8feaSLen Brown timersub(&tv_even, &tv_odd, &tv_delta); 2320ba3dec99SLen Brown if (for_all_cpus_2(delta_cpu, EVEN_COUNTERS, ODD_COUNTERS)) { 2321ba3dec99SLen Brown re_initialize(); 2322ba3dec99SLen Brown goto restart; 2323ba3dec99SLen Brown } 2324c98d5d94SLen Brown compute_average(ODD_COUNTERS); 2325c98d5d94SLen Brown format_all_counters(ODD_COUNTERS); 2326b7d8c148SLen Brown flush_output_stdout(); 2327103a8feaSLen Brown } 2328103a8feaSLen Brown } 2329103a8feaSLen Brown 2330103a8feaSLen Brown void check_dev_msr() 2331103a8feaSLen Brown { 2332103a8feaSLen Brown struct stat sb; 23337ce7d5deSPrarit Bhargava char pathname[32]; 2334103a8feaSLen Brown 23357ce7d5deSPrarit Bhargava sprintf(pathname, "/dev/cpu/%d/msr", base_cpu); 23367ce7d5deSPrarit Bhargava if (stat(pathname, &sb)) 2337a21d38c8SLen Brown if (system("/sbin/modprobe msr > /dev/null 2>&1")) 2338d7899447SLen Brown err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" "); 2339103a8feaSLen Brown } 2340103a8feaSLen Brown 234198481e79SLen Brown void check_permissions() 2342103a8feaSLen Brown { 234398481e79SLen Brown struct __user_cap_header_struct cap_header_data; 234498481e79SLen Brown cap_user_header_t cap_header = &cap_header_data; 234598481e79SLen Brown struct __user_cap_data_struct cap_data_data; 234698481e79SLen Brown cap_user_data_t cap_data = &cap_data_data; 234798481e79SLen Brown extern int capget(cap_user_header_t hdrp, cap_user_data_t datap); 234898481e79SLen Brown int do_exit = 0; 23497ce7d5deSPrarit Bhargava char pathname[32]; 235098481e79SLen Brown 235198481e79SLen Brown /* check for CAP_SYS_RAWIO */ 235298481e79SLen Brown cap_header->pid = getpid(); 235398481e79SLen Brown cap_header->version = _LINUX_CAPABILITY_VERSION; 235498481e79SLen Brown if (capget(cap_header, cap_data) < 0) 235598481e79SLen Brown err(-6, "capget(2) failed"); 235698481e79SLen Brown 235798481e79SLen Brown if ((cap_data->effective & (1 << CAP_SYS_RAWIO)) == 0) { 235898481e79SLen Brown do_exit++; 235998481e79SLen Brown warnx("capget(CAP_SYS_RAWIO) failed," 236098481e79SLen Brown " try \"# setcap cap_sys_rawio=ep %s\"", progname); 236198481e79SLen Brown } 236298481e79SLen Brown 236398481e79SLen Brown /* test file permissions */ 23647ce7d5deSPrarit Bhargava sprintf(pathname, "/dev/cpu/%d/msr", base_cpu); 23657ce7d5deSPrarit Bhargava if (euidaccess(pathname, R_OK)) { 236698481e79SLen Brown do_exit++; 236798481e79SLen Brown warn("/dev/cpu/0/msr open failed, try chown or chmod +r /dev/cpu/*/msr"); 236898481e79SLen Brown } 236998481e79SLen Brown 237098481e79SLen Brown /* if all else fails, thell them to be root */ 237198481e79SLen Brown if (do_exit) 2372b2c95d90SJosh Triplett if (getuid() != 0) 2373d7899447SLen Brown warnx("... or simply run as root"); 237498481e79SLen Brown 237598481e79SLen Brown if (do_exit) 237698481e79SLen Brown exit(-6); 2377103a8feaSLen Brown } 2378103a8feaSLen Brown 2379d7899447SLen Brown /* 2380d7899447SLen Brown * NHM adds support for additional MSRs: 2381d7899447SLen Brown * 2382d7899447SLen Brown * MSR_SMI_COUNT 0x00000034 2383d7899447SLen Brown * 2384ec0adc53SLen Brown * MSR_PLATFORM_INFO 0x000000ce 2385d7899447SLen Brown * MSR_NHM_SNB_PKG_CST_CFG_CTL 0x000000e2 2386d7899447SLen Brown * 2387d7899447SLen Brown * MSR_PKG_C3_RESIDENCY 0x000003f8 2388d7899447SLen Brown * MSR_PKG_C6_RESIDENCY 0x000003f9 2389d7899447SLen Brown * MSR_CORE_C3_RESIDENCY 0x000003fc 2390d7899447SLen Brown * MSR_CORE_C6_RESIDENCY 0x000003fd 2391d7899447SLen Brown * 2392ee7e38e3SLen Brown * Side effect: 2393ee7e38e3SLen Brown * sets global pkg_cstate_limit to decode MSR_NHM_SNB_PKG_CST_CFG_CTL 2394d7899447SLen Brown */ 2395ee7e38e3SLen Brown int probe_nhm_msrs(unsigned int family, unsigned int model) 2396103a8feaSLen Brown { 2397ee7e38e3SLen Brown unsigned long long msr; 239821ed5574SLen Brown unsigned int base_ratio; 2399ee7e38e3SLen Brown int *pkg_cstate_limits; 2400ee7e38e3SLen Brown 2401103a8feaSLen Brown if (!genuine_intel) 2402103a8feaSLen Brown return 0; 2403103a8feaSLen Brown 2404103a8feaSLen Brown if (family != 6) 2405103a8feaSLen Brown return 0; 2406103a8feaSLen Brown 240721ed5574SLen Brown bclk = discover_bclk(family, model); 240821ed5574SLen Brown 2409103a8feaSLen Brown switch (model) { 2410869ce69eSLen Brown case INTEL_FAM6_NEHALEM_EP: /* Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP */ 2411869ce69eSLen Brown case INTEL_FAM6_NEHALEM: /* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */ 2412103a8feaSLen Brown case 0x1F: /* Core i7 and i5 Processor - Nehalem */ 2413869ce69eSLen Brown case INTEL_FAM6_WESTMERE: /* Westmere Client - Clarkdale, Arrandale */ 2414869ce69eSLen Brown case INTEL_FAM6_WESTMERE_EP: /* Westmere EP - Gulftown */ 2415869ce69eSLen Brown case INTEL_FAM6_NEHALEM_EX: /* Nehalem-EX Xeon - Beckton */ 2416869ce69eSLen Brown case INTEL_FAM6_WESTMERE_EX: /* Westmere-EX Xeon - Eagleton */ 2417ee7e38e3SLen Brown pkg_cstate_limits = nhm_pkg_cstate_limits; 2418ee7e38e3SLen Brown break; 2419869ce69eSLen Brown case INTEL_FAM6_SANDYBRIDGE: /* SNB */ 2420869ce69eSLen Brown case INTEL_FAM6_SANDYBRIDGE_X: /* SNB Xeon */ 2421869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE: /* IVB */ 2422869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */ 2423ee7e38e3SLen Brown pkg_cstate_limits = snb_pkg_cstate_limits; 2424ee7e38e3SLen Brown break; 2425869ce69eSLen Brown case INTEL_FAM6_HASWELL_CORE: /* HSW */ 2426869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSX */ 2427869ce69eSLen Brown case INTEL_FAM6_HASWELL_ULT: /* HSW */ 2428869ce69eSLen Brown case INTEL_FAM6_HASWELL_GT3E: /* HSW */ 2429869ce69eSLen Brown case INTEL_FAM6_BROADWELL_CORE: /* BDW */ 2430869ce69eSLen Brown case INTEL_FAM6_BROADWELL_GT3E: /* BDW */ 2431869ce69eSLen Brown case INTEL_FAM6_BROADWELL_X: /* BDX */ 2432869ce69eSLen Brown case INTEL_FAM6_BROADWELL_XEON_D: /* BDX-DE */ 2433869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 2434869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 2435869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 2436869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 2437ee7e38e3SLen Brown pkg_cstate_limits = hsw_pkg_cstate_limits; 2438ee7e38e3SLen Brown break; 2439d8ebb442SLen Brown case INTEL_FAM6_SKYLAKE_X: /* SKX */ 2440d8ebb442SLen Brown pkg_cstate_limits = skx_pkg_cstate_limits; 2441d8ebb442SLen Brown break; 2442869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */ 2443869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */ 2444ee7e38e3SLen Brown pkg_cstate_limits = slv_pkg_cstate_limits; 2445ee7e38e3SLen Brown break; 2446869ce69eSLen Brown case INTEL_FAM6_ATOM_AIRMONT: /* AMT */ 2447ee7e38e3SLen Brown pkg_cstate_limits = amt_pkg_cstate_limits; 2448ee7e38e3SLen Brown break; 2449869ce69eSLen Brown case INTEL_FAM6_XEON_PHI_KNL: /* PHI */ 2450005c82d6SLen Brown case INTEL_FAM6_XEON_PHI_KNM: 2451ee7e38e3SLen Brown pkg_cstate_limits = phi_pkg_cstate_limits; 2452ee7e38e3SLen Brown break; 2453869ce69eSLen Brown case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 2454869ce69eSLen Brown case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ 2455e4085d54SLen Brown pkg_cstate_limits = bxt_pkg_cstate_limits; 2456e4085d54SLen Brown break; 2457103a8feaSLen Brown default: 2458103a8feaSLen Brown return 0; 2459103a8feaSLen Brown } 24607ce7d5deSPrarit Bhargava get_msr(base_cpu, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr); 2461e9257f5fSLen Brown pkg_cstate_limit = pkg_cstate_limits[msr & 0xF]; 2462ee7e38e3SLen Brown 2463ec0adc53SLen Brown get_msr(base_cpu, MSR_PLATFORM_INFO, &msr); 246421ed5574SLen Brown base_ratio = (msr >> 8) & 0xFF; 246521ed5574SLen Brown 246621ed5574SLen Brown base_hz = base_ratio * bclk * 1000000; 246721ed5574SLen Brown has_base_hz = 1; 2468ee7e38e3SLen Brown return 1; 2469103a8feaSLen Brown } 2470d7899447SLen Brown int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model) 2471d7899447SLen Brown { 2472d7899447SLen Brown switch (model) { 2473d7899447SLen Brown /* Nehalem compatible, but do not include turbo-ratio limit support */ 2474869ce69eSLen Brown case INTEL_FAM6_NEHALEM_EX: /* Nehalem-EX Xeon - Beckton */ 2475869ce69eSLen Brown case INTEL_FAM6_WESTMERE_EX: /* Westmere-EX Xeon - Eagleton */ 2476869ce69eSLen Brown case INTEL_FAM6_XEON_PHI_KNL: /* PHI - Knights Landing (different MSR definition) */ 2477005c82d6SLen Brown case INTEL_FAM6_XEON_PHI_KNM: 2478d7899447SLen Brown return 0; 2479d7899447SLen Brown default: 2480d7899447SLen Brown return 1; 2481d7899447SLen Brown } 2482d7899447SLen Brown } 24836574a5d5SLen Brown int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model) 24846574a5d5SLen Brown { 24856574a5d5SLen Brown if (!genuine_intel) 24866574a5d5SLen Brown return 0; 24876574a5d5SLen Brown 24886574a5d5SLen Brown if (family != 6) 24896574a5d5SLen Brown return 0; 24906574a5d5SLen Brown 24916574a5d5SLen Brown switch (model) { 2492869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */ 2493869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSW Xeon */ 24946574a5d5SLen Brown return 1; 24956574a5d5SLen Brown default: 24966574a5d5SLen Brown return 0; 24976574a5d5SLen Brown } 24986574a5d5SLen Brown } 2499fcd17211SLen Brown int has_hsw_turbo_ratio_limit(unsigned int family, unsigned int model) 2500fcd17211SLen Brown { 2501fcd17211SLen Brown if (!genuine_intel) 2502fcd17211SLen Brown return 0; 2503fcd17211SLen Brown 2504fcd17211SLen Brown if (family != 6) 2505fcd17211SLen Brown return 0; 2506fcd17211SLen Brown 2507fcd17211SLen Brown switch (model) { 2508869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSW Xeon */ 2509fcd17211SLen Brown return 1; 2510fcd17211SLen Brown default: 2511fcd17211SLen Brown return 0; 2512fcd17211SLen Brown } 2513fcd17211SLen Brown } 2514fcd17211SLen Brown 2515fb5d4327SDasaratharaman Chandramouli int has_knl_turbo_ratio_limit(unsigned int family, unsigned int model) 2516fb5d4327SDasaratharaman Chandramouli { 2517fb5d4327SDasaratharaman Chandramouli if (!genuine_intel) 2518fb5d4327SDasaratharaman Chandramouli return 0; 2519fb5d4327SDasaratharaman Chandramouli 2520fb5d4327SDasaratharaman Chandramouli if (family != 6) 2521fb5d4327SDasaratharaman Chandramouli return 0; 2522fb5d4327SDasaratharaman Chandramouli 2523fb5d4327SDasaratharaman Chandramouli switch (model) { 2524869ce69eSLen Brown case INTEL_FAM6_XEON_PHI_KNL: /* Knights Landing */ 2525005c82d6SLen Brown case INTEL_FAM6_XEON_PHI_KNM: 2526fb5d4327SDasaratharaman Chandramouli return 1; 2527fb5d4327SDasaratharaman Chandramouli default: 2528fb5d4327SDasaratharaman Chandramouli return 0; 2529fb5d4327SDasaratharaman Chandramouli } 2530fb5d4327SDasaratharaman Chandramouli } 25316fb3143bSLen Brown int has_config_tdp(unsigned int family, unsigned int model) 25326fb3143bSLen Brown { 25336fb3143bSLen Brown if (!genuine_intel) 25346fb3143bSLen Brown return 0; 25356fb3143bSLen Brown 25366fb3143bSLen Brown if (family != 6) 25376fb3143bSLen Brown return 0; 25386fb3143bSLen Brown 25396fb3143bSLen Brown switch (model) { 2540869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE: /* IVB */ 2541869ce69eSLen Brown case INTEL_FAM6_HASWELL_CORE: /* HSW */ 2542869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSX */ 2543869ce69eSLen Brown case INTEL_FAM6_HASWELL_ULT: /* HSW */ 2544869ce69eSLen Brown case INTEL_FAM6_HASWELL_GT3E: /* HSW */ 2545869ce69eSLen Brown case INTEL_FAM6_BROADWELL_CORE: /* BDW */ 2546869ce69eSLen Brown case INTEL_FAM6_BROADWELL_GT3E: /* BDW */ 2547869ce69eSLen Brown case INTEL_FAM6_BROADWELL_X: /* BDX */ 2548869ce69eSLen Brown case INTEL_FAM6_BROADWELL_XEON_D: /* BDX-DE */ 2549869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 2550869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 2551869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 2552869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 2553869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_X: /* SKX */ 25546fb3143bSLen Brown 2555869ce69eSLen Brown case INTEL_FAM6_XEON_PHI_KNL: /* Knights Landing */ 2556005c82d6SLen Brown case INTEL_FAM6_XEON_PHI_KNM: 25576fb3143bSLen Brown return 1; 25586fb3143bSLen Brown default: 25596fb3143bSLen Brown return 0; 25606fb3143bSLen Brown } 25616fb3143bSLen Brown } 25626fb3143bSLen Brown 2563fcd17211SLen Brown static void 25641b69317dSColin Ian King dump_cstate_pstate_config_info(unsigned int family, unsigned int model) 2565fcd17211SLen Brown { 2566fcd17211SLen Brown if (!do_nhm_platform_info) 2567fcd17211SLen Brown return; 2568fcd17211SLen Brown 2569fcd17211SLen Brown dump_nhm_platform_info(); 2570fcd17211SLen Brown 2571fcd17211SLen Brown if (has_hsw_turbo_ratio_limit(family, model)) 2572fcd17211SLen Brown dump_hsw_turbo_ratio_limits(); 2573fcd17211SLen Brown 2574fcd17211SLen Brown if (has_ivt_turbo_ratio_limit(family, model)) 2575fcd17211SLen Brown dump_ivt_turbo_ratio_limits(); 2576fcd17211SLen Brown 2577fcd17211SLen Brown if (has_nhm_turbo_ratio_limit(family, model)) 2578fcd17211SLen Brown dump_nhm_turbo_ratio_limits(); 2579fcd17211SLen Brown 2580fb5d4327SDasaratharaman Chandramouli if (has_knl_turbo_ratio_limit(family, model)) 2581fb5d4327SDasaratharaman Chandramouli dump_knl_turbo_ratio_limits(); 2582fb5d4327SDasaratharaman Chandramouli 25836fb3143bSLen Brown if (has_config_tdp(family, model)) 25846fb3143bSLen Brown dump_config_tdp(); 25856fb3143bSLen Brown 2586fcd17211SLen Brown dump_nhm_cst_cfg(); 2587fcd17211SLen Brown } 2588fcd17211SLen Brown 25896574a5d5SLen Brown 2590889facbeSLen Brown /* 2591889facbeSLen Brown * print_epb() 2592889facbeSLen Brown * Decode the ENERGY_PERF_BIAS MSR 2593889facbeSLen Brown */ 2594889facbeSLen Brown int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p) 2595889facbeSLen Brown { 2596889facbeSLen Brown unsigned long long msr; 2597889facbeSLen Brown char *epb_string; 2598889facbeSLen Brown int cpu; 2599889facbeSLen Brown 2600889facbeSLen Brown if (!has_epb) 2601889facbeSLen Brown return 0; 2602889facbeSLen Brown 2603889facbeSLen Brown cpu = t->cpu_id; 2604889facbeSLen Brown 2605889facbeSLen Brown /* EPB is per-package */ 2606889facbeSLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 2607889facbeSLen Brown return 0; 2608889facbeSLen Brown 2609889facbeSLen Brown if (cpu_migrate(cpu)) { 2610b7d8c148SLen Brown fprintf(outf, "Could not migrate to CPU %d\n", cpu); 2611889facbeSLen Brown return -1; 2612889facbeSLen Brown } 2613889facbeSLen Brown 2614889facbeSLen Brown if (get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr)) 2615889facbeSLen Brown return 0; 2616889facbeSLen Brown 2617e9be7dd6SLen Brown switch (msr & 0xF) { 2618889facbeSLen Brown case ENERGY_PERF_BIAS_PERFORMANCE: 2619889facbeSLen Brown epb_string = "performance"; 2620889facbeSLen Brown break; 2621889facbeSLen Brown case ENERGY_PERF_BIAS_NORMAL: 2622889facbeSLen Brown epb_string = "balanced"; 2623889facbeSLen Brown break; 2624889facbeSLen Brown case ENERGY_PERF_BIAS_POWERSAVE: 2625889facbeSLen Brown epb_string = "powersave"; 2626889facbeSLen Brown break; 2627889facbeSLen Brown default: 2628889facbeSLen Brown epb_string = "custom"; 2629889facbeSLen Brown break; 2630889facbeSLen Brown } 2631b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_ENERGY_PERF_BIAS: 0x%08llx (%s)\n", cpu, msr, epb_string); 2632889facbeSLen Brown 2633889facbeSLen Brown return 0; 2634889facbeSLen Brown } 26357f5c258eSLen Brown /* 26367f5c258eSLen Brown * print_hwp() 26377f5c258eSLen Brown * Decode the MSR_HWP_CAPABILITIES 26387f5c258eSLen Brown */ 26397f5c258eSLen Brown int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p) 26407f5c258eSLen Brown { 26417f5c258eSLen Brown unsigned long long msr; 26427f5c258eSLen Brown int cpu; 26437f5c258eSLen Brown 26447f5c258eSLen Brown if (!has_hwp) 26457f5c258eSLen Brown return 0; 26467f5c258eSLen Brown 26477f5c258eSLen Brown cpu = t->cpu_id; 26487f5c258eSLen Brown 26497f5c258eSLen Brown /* MSR_HWP_CAPABILITIES is per-package */ 26507f5c258eSLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 26517f5c258eSLen Brown return 0; 26527f5c258eSLen Brown 26537f5c258eSLen Brown if (cpu_migrate(cpu)) { 2654b7d8c148SLen Brown fprintf(outf, "Could not migrate to CPU %d\n", cpu); 26557f5c258eSLen Brown return -1; 26567f5c258eSLen Brown } 26577f5c258eSLen Brown 26587f5c258eSLen Brown if (get_msr(cpu, MSR_PM_ENABLE, &msr)) 26597f5c258eSLen Brown return 0; 26607f5c258eSLen Brown 2661b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PM_ENABLE: 0x%08llx (%sHWP)\n", 26627f5c258eSLen Brown cpu, msr, (msr & (1 << 0)) ? "" : "No-"); 26637f5c258eSLen Brown 26647f5c258eSLen Brown /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */ 26657f5c258eSLen Brown if ((msr & (1 << 0)) == 0) 26667f5c258eSLen Brown return 0; 26677f5c258eSLen Brown 26687f5c258eSLen Brown if (get_msr(cpu, MSR_HWP_CAPABILITIES, &msr)) 26697f5c258eSLen Brown return 0; 26707f5c258eSLen Brown 2671b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_HWP_CAPABILITIES: 0x%08llx " 26727f5c258eSLen Brown "(high 0x%x guar 0x%x eff 0x%x low 0x%x)\n", 26737f5c258eSLen Brown cpu, msr, 26747f5c258eSLen Brown (unsigned int)HWP_HIGHEST_PERF(msr), 26757f5c258eSLen Brown (unsigned int)HWP_GUARANTEED_PERF(msr), 26767f5c258eSLen Brown (unsigned int)HWP_MOSTEFFICIENT_PERF(msr), 26777f5c258eSLen Brown (unsigned int)HWP_LOWEST_PERF(msr)); 26787f5c258eSLen Brown 26797f5c258eSLen Brown if (get_msr(cpu, MSR_HWP_REQUEST, &msr)) 26807f5c258eSLen Brown return 0; 26817f5c258eSLen Brown 2682b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_HWP_REQUEST: 0x%08llx " 26837f5c258eSLen Brown "(min 0x%x max 0x%x des 0x%x epp 0x%x window 0x%x pkg 0x%x)\n", 26847f5c258eSLen Brown cpu, msr, 26857f5c258eSLen Brown (unsigned int)(((msr) >> 0) & 0xff), 26867f5c258eSLen Brown (unsigned int)(((msr) >> 8) & 0xff), 26877f5c258eSLen Brown (unsigned int)(((msr) >> 16) & 0xff), 26887f5c258eSLen Brown (unsigned int)(((msr) >> 24) & 0xff), 26897f5c258eSLen Brown (unsigned int)(((msr) >> 32) & 0xff3), 26907f5c258eSLen Brown (unsigned int)(((msr) >> 42) & 0x1)); 26917f5c258eSLen Brown 26927f5c258eSLen Brown if (has_hwp_pkg) { 26937f5c258eSLen Brown if (get_msr(cpu, MSR_HWP_REQUEST_PKG, &msr)) 26947f5c258eSLen Brown return 0; 26957f5c258eSLen Brown 2696b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_HWP_REQUEST_PKG: 0x%08llx " 26977f5c258eSLen Brown "(min 0x%x max 0x%x des 0x%x epp 0x%x window 0x%x)\n", 26987f5c258eSLen Brown cpu, msr, 26997f5c258eSLen Brown (unsigned int)(((msr) >> 0) & 0xff), 27007f5c258eSLen Brown (unsigned int)(((msr) >> 8) & 0xff), 27017f5c258eSLen Brown (unsigned int)(((msr) >> 16) & 0xff), 27027f5c258eSLen Brown (unsigned int)(((msr) >> 24) & 0xff), 27037f5c258eSLen Brown (unsigned int)(((msr) >> 32) & 0xff3)); 27047f5c258eSLen Brown } 27057f5c258eSLen Brown if (has_hwp_notify) { 27067f5c258eSLen Brown if (get_msr(cpu, MSR_HWP_INTERRUPT, &msr)) 27077f5c258eSLen Brown return 0; 27087f5c258eSLen Brown 2709b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_HWP_INTERRUPT: 0x%08llx " 27107f5c258eSLen Brown "(%s_Guaranteed_Perf_Change, %s_Excursion_Min)\n", 27117f5c258eSLen Brown cpu, msr, 27127f5c258eSLen Brown ((msr) & 0x1) ? "EN" : "Dis", 27137f5c258eSLen Brown ((msr) & 0x2) ? "EN" : "Dis"); 27147f5c258eSLen Brown } 27157f5c258eSLen Brown if (get_msr(cpu, MSR_HWP_STATUS, &msr)) 27167f5c258eSLen Brown return 0; 27177f5c258eSLen Brown 2718b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_HWP_STATUS: 0x%08llx " 27197f5c258eSLen Brown "(%sGuaranteed_Perf_Change, %sExcursion_Min)\n", 27207f5c258eSLen Brown cpu, msr, 27217f5c258eSLen Brown ((msr) & 0x1) ? "" : "No-", 27227f5c258eSLen Brown ((msr) & 0x2) ? "" : "No-"); 2723889facbeSLen Brown 2724889facbeSLen Brown return 0; 2725889facbeSLen Brown } 2726889facbeSLen Brown 27273a9a941dSLen Brown /* 27283a9a941dSLen Brown * print_perf_limit() 27293a9a941dSLen Brown */ 27303a9a941dSLen Brown int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data *p) 27313a9a941dSLen Brown { 27323a9a941dSLen Brown unsigned long long msr; 27333a9a941dSLen Brown int cpu; 27343a9a941dSLen Brown 27353a9a941dSLen Brown cpu = t->cpu_id; 27363a9a941dSLen Brown 27373a9a941dSLen Brown /* per-package */ 27383a9a941dSLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 27393a9a941dSLen Brown return 0; 27403a9a941dSLen Brown 27413a9a941dSLen Brown if (cpu_migrate(cpu)) { 2742b7d8c148SLen Brown fprintf(outf, "Could not migrate to CPU %d\n", cpu); 27433a9a941dSLen Brown return -1; 27443a9a941dSLen Brown } 27453a9a941dSLen Brown 27463a9a941dSLen Brown if (do_core_perf_limit_reasons) { 27473a9a941dSLen Brown get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr); 2748b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); 2749b7d8c148SLen Brown fprintf(outf, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)", 2750e33cbe85SLen Brown (msr & 1 << 15) ? "bit15, " : "", 27513a9a941dSLen Brown (msr & 1 << 14) ? "bit14, " : "", 2752e33cbe85SLen Brown (msr & 1 << 13) ? "Transitions, " : "", 2753e33cbe85SLen Brown (msr & 1 << 12) ? "MultiCoreTurbo, " : "", 2754e33cbe85SLen Brown (msr & 1 << 11) ? "PkgPwrL2, " : "", 2755e33cbe85SLen Brown (msr & 1 << 10) ? "PkgPwrL1, " : "", 2756e33cbe85SLen Brown (msr & 1 << 9) ? "CorePwr, " : "", 2757e33cbe85SLen Brown (msr & 1 << 8) ? "Amps, " : "", 2758e33cbe85SLen Brown (msr & 1 << 6) ? "VR-Therm, " : "", 2759e33cbe85SLen Brown (msr & 1 << 5) ? "Auto-HWP, " : "", 2760e33cbe85SLen Brown (msr & 1 << 4) ? "Graphics, " : "", 2761e33cbe85SLen Brown (msr & 1 << 2) ? "bit2, " : "", 2762e33cbe85SLen Brown (msr & 1 << 1) ? "ThermStatus, " : "", 2763e33cbe85SLen Brown (msr & 1 << 0) ? "PROCHOT, " : ""); 2764b7d8c148SLen Brown fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n", 2765e33cbe85SLen Brown (msr & 1 << 31) ? "bit31, " : "", 27663a9a941dSLen Brown (msr & 1 << 30) ? "bit30, " : "", 2767e33cbe85SLen Brown (msr & 1 << 29) ? "Transitions, " : "", 2768e33cbe85SLen Brown (msr & 1 << 28) ? "MultiCoreTurbo, " : "", 2769e33cbe85SLen Brown (msr & 1 << 27) ? "PkgPwrL2, " : "", 2770e33cbe85SLen Brown (msr & 1 << 26) ? "PkgPwrL1, " : "", 2771e33cbe85SLen Brown (msr & 1 << 25) ? "CorePwr, " : "", 2772e33cbe85SLen Brown (msr & 1 << 24) ? "Amps, " : "", 2773e33cbe85SLen Brown (msr & 1 << 22) ? "VR-Therm, " : "", 2774e33cbe85SLen Brown (msr & 1 << 21) ? "Auto-HWP, " : "", 2775e33cbe85SLen Brown (msr & 1 << 20) ? "Graphics, " : "", 2776e33cbe85SLen Brown (msr & 1 << 18) ? "bit18, " : "", 2777e33cbe85SLen Brown (msr & 1 << 17) ? "ThermStatus, " : "", 2778e33cbe85SLen Brown (msr & 1 << 16) ? "PROCHOT, " : ""); 27793a9a941dSLen Brown 27803a9a941dSLen Brown } 27813a9a941dSLen Brown if (do_gfx_perf_limit_reasons) { 27823a9a941dSLen Brown get_msr(cpu, MSR_GFX_PERF_LIMIT_REASONS, &msr); 2783b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_GFX_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); 2784b7d8c148SLen Brown fprintf(outf, " (Active: %s%s%s%s%s%s%s%s)", 27853a9a941dSLen Brown (msr & 1 << 0) ? "PROCHOT, " : "", 27863a9a941dSLen Brown (msr & 1 << 1) ? "ThermStatus, " : "", 27873a9a941dSLen Brown (msr & 1 << 4) ? "Graphics, " : "", 27883a9a941dSLen Brown (msr & 1 << 6) ? "VR-Therm, " : "", 27893a9a941dSLen Brown (msr & 1 << 8) ? "Amps, " : "", 27903a9a941dSLen Brown (msr & 1 << 9) ? "GFXPwr, " : "", 27913a9a941dSLen Brown (msr & 1 << 10) ? "PkgPwrL1, " : "", 27923a9a941dSLen Brown (msr & 1 << 11) ? "PkgPwrL2, " : ""); 2793b7d8c148SLen Brown fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s)\n", 27943a9a941dSLen Brown (msr & 1 << 16) ? "PROCHOT, " : "", 27953a9a941dSLen Brown (msr & 1 << 17) ? "ThermStatus, " : "", 27963a9a941dSLen Brown (msr & 1 << 20) ? "Graphics, " : "", 27973a9a941dSLen Brown (msr & 1 << 22) ? "VR-Therm, " : "", 27983a9a941dSLen Brown (msr & 1 << 24) ? "Amps, " : "", 27993a9a941dSLen Brown (msr & 1 << 25) ? "GFXPwr, " : "", 28003a9a941dSLen Brown (msr & 1 << 26) ? "PkgPwrL1, " : "", 28013a9a941dSLen Brown (msr & 1 << 27) ? "PkgPwrL2, " : ""); 28023a9a941dSLen Brown } 28033a9a941dSLen Brown if (do_ring_perf_limit_reasons) { 28043a9a941dSLen Brown get_msr(cpu, MSR_RING_PERF_LIMIT_REASONS, &msr); 2805b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_RING_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); 2806b7d8c148SLen Brown fprintf(outf, " (Active: %s%s%s%s%s%s)", 28073a9a941dSLen Brown (msr & 1 << 0) ? "PROCHOT, " : "", 28083a9a941dSLen Brown (msr & 1 << 1) ? "ThermStatus, " : "", 28093a9a941dSLen Brown (msr & 1 << 6) ? "VR-Therm, " : "", 28103a9a941dSLen Brown (msr & 1 << 8) ? "Amps, " : "", 28113a9a941dSLen Brown (msr & 1 << 10) ? "PkgPwrL1, " : "", 28123a9a941dSLen Brown (msr & 1 << 11) ? "PkgPwrL2, " : ""); 2813b7d8c148SLen Brown fprintf(outf, " (Logged: %s%s%s%s%s%s)\n", 28143a9a941dSLen Brown (msr & 1 << 16) ? "PROCHOT, " : "", 28153a9a941dSLen Brown (msr & 1 << 17) ? "ThermStatus, " : "", 28163a9a941dSLen Brown (msr & 1 << 22) ? "VR-Therm, " : "", 28173a9a941dSLen Brown (msr & 1 << 24) ? "Amps, " : "", 28183a9a941dSLen Brown (msr & 1 << 26) ? "PkgPwrL1, " : "", 28193a9a941dSLen Brown (msr & 1 << 27) ? "PkgPwrL2, " : ""); 28203a9a941dSLen Brown } 28213a9a941dSLen Brown return 0; 28223a9a941dSLen Brown } 28233a9a941dSLen Brown 2824889facbeSLen Brown #define RAPL_POWER_GRANULARITY 0x7FFF /* 15 bit power granularity */ 2825889facbeSLen Brown #define RAPL_TIME_GRANULARITY 0x3F /* 6 bit time granularity */ 2826889facbeSLen Brown 28271b69317dSColin Ian King double get_tdp(unsigned int model) 2828144b44b1SLen Brown { 2829144b44b1SLen Brown unsigned long long msr; 2830144b44b1SLen Brown 2831144b44b1SLen Brown if (do_rapl & RAPL_PKG_POWER_INFO) 28327ce7d5deSPrarit Bhargava if (!get_msr(base_cpu, MSR_PKG_POWER_INFO, &msr)) 2833144b44b1SLen Brown return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units; 2834144b44b1SLen Brown 2835144b44b1SLen Brown switch (model) { 2836869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT1: 2837869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT2: 2838144b44b1SLen Brown return 30.0; 2839144b44b1SLen Brown default: 2840144b44b1SLen Brown return 135.0; 2841144b44b1SLen Brown } 2842144b44b1SLen Brown } 2843144b44b1SLen Brown 284440ee8e3bSAndrey Semin /* 284540ee8e3bSAndrey Semin * rapl_dram_energy_units_probe() 284640ee8e3bSAndrey Semin * Energy units are either hard-coded, or come from RAPL Energy Unit MSR. 284740ee8e3bSAndrey Semin */ 284840ee8e3bSAndrey Semin static double 284940ee8e3bSAndrey Semin rapl_dram_energy_units_probe(int model, double rapl_energy_units) 285040ee8e3bSAndrey Semin { 285140ee8e3bSAndrey Semin /* only called for genuine_intel, family 6 */ 285240ee8e3bSAndrey Semin 285340ee8e3bSAndrey Semin switch (model) { 2854869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSX */ 2855869ce69eSLen Brown case INTEL_FAM6_BROADWELL_X: /* BDX */ 2856869ce69eSLen Brown case INTEL_FAM6_BROADWELL_XEON_D: /* BDX-DE */ 2857869ce69eSLen Brown case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ 2858005c82d6SLen Brown case INTEL_FAM6_XEON_PHI_KNM: 285940ee8e3bSAndrey Semin return (rapl_dram_energy_units = 15.3 / 1000000); 286040ee8e3bSAndrey Semin default: 286140ee8e3bSAndrey Semin return (rapl_energy_units); 286240ee8e3bSAndrey Semin } 286340ee8e3bSAndrey Semin } 286440ee8e3bSAndrey Semin 2865144b44b1SLen Brown 2866889facbeSLen Brown /* 2867889facbeSLen Brown * rapl_probe() 2868889facbeSLen Brown * 2869144b44b1SLen Brown * sets do_rapl, rapl_power_units, rapl_energy_units, rapl_time_units 2870889facbeSLen Brown */ 2871889facbeSLen Brown void rapl_probe(unsigned int family, unsigned int model) 2872889facbeSLen Brown { 2873889facbeSLen Brown unsigned long long msr; 2874144b44b1SLen Brown unsigned int time_unit; 2875889facbeSLen Brown double tdp; 2876889facbeSLen Brown 2877889facbeSLen Brown if (!genuine_intel) 2878889facbeSLen Brown return; 2879889facbeSLen Brown 2880889facbeSLen Brown if (family != 6) 2881889facbeSLen Brown return; 2882889facbeSLen Brown 2883889facbeSLen Brown switch (model) { 2884869ce69eSLen Brown case INTEL_FAM6_SANDYBRIDGE: 2885869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE: 2886869ce69eSLen Brown case INTEL_FAM6_HASWELL_CORE: /* HSW */ 2887869ce69eSLen Brown case INTEL_FAM6_HASWELL_ULT: /* HSW */ 2888869ce69eSLen Brown case INTEL_FAM6_HASWELL_GT3E: /* HSW */ 2889869ce69eSLen Brown case INTEL_FAM6_BROADWELL_CORE: /* BDW */ 2890869ce69eSLen Brown case INTEL_FAM6_BROADWELL_GT3E: /* BDW */ 2891144b44b1SLen Brown do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO; 2892*812db3f7SLen Brown if (rapl_joules) { 2893*812db3f7SLen Brown BIC_PRESENT(BIC_Pkg_J); 2894*812db3f7SLen Brown BIC_PRESENT(BIC_Cor_J); 2895*812db3f7SLen Brown BIC_PRESENT(BIC_GFX_J); 2896*812db3f7SLen Brown } else { 2897*812db3f7SLen Brown BIC_PRESENT(BIC_PkgWatt); 2898*812db3f7SLen Brown BIC_PRESENT(BIC_CorWatt); 2899*812db3f7SLen Brown BIC_PRESENT(BIC_GFXWatt); 2900*812db3f7SLen Brown } 2901889facbeSLen Brown break; 2902869ce69eSLen Brown case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 2903e4085d54SLen Brown do_rapl = RAPL_PKG | RAPL_PKG_POWER_INFO; 2904*812db3f7SLen Brown if (rapl_joules) 2905*812db3f7SLen Brown BIC_PRESENT(BIC_Pkg_J); 2906*812db3f7SLen Brown else 2907*812db3f7SLen Brown BIC_PRESENT(BIC_PkgWatt); 2908e4085d54SLen Brown break; 2909869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 2910869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 2911869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 2912869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 29130b2bb692SLen Brown do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO; 2914*812db3f7SLen Brown BIC_PRESENT(BIC_PKG__); 2915*812db3f7SLen Brown BIC_PRESENT(BIC_RAM__); 2916*812db3f7SLen Brown if (rapl_joules) { 2917*812db3f7SLen Brown BIC_PRESENT(BIC_Pkg_J); 2918*812db3f7SLen Brown BIC_PRESENT(BIC_Cor_J); 2919*812db3f7SLen Brown BIC_PRESENT(BIC_RAM_J); 2920*812db3f7SLen Brown } else { 2921*812db3f7SLen Brown BIC_PRESENT(BIC_PkgWatt); 2922*812db3f7SLen Brown BIC_PRESENT(BIC_CorWatt); 2923*812db3f7SLen Brown BIC_PRESENT(BIC_RAMWatt); 2924*812db3f7SLen Brown } 29250b2bb692SLen Brown break; 2926869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSX */ 2927869ce69eSLen Brown case INTEL_FAM6_BROADWELL_X: /* BDX */ 2928869ce69eSLen Brown case INTEL_FAM6_BROADWELL_XEON_D: /* BDX-DE */ 2929869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_X: /* SKX */ 2930869ce69eSLen Brown case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ 2931005c82d6SLen Brown case INTEL_FAM6_XEON_PHI_KNM: 29320b2bb692SLen Brown do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO; 2933*812db3f7SLen Brown BIC_PRESENT(BIC_PKG__); 2934*812db3f7SLen Brown BIC_PRESENT(BIC_RAM__); 2935*812db3f7SLen Brown if (rapl_joules) { 2936*812db3f7SLen Brown BIC_PRESENT(BIC_Pkg_J); 2937*812db3f7SLen Brown BIC_PRESENT(BIC_RAM_J); 2938*812db3f7SLen Brown } else { 2939*812db3f7SLen Brown BIC_PRESENT(BIC_PkgWatt); 2940*812db3f7SLen Brown BIC_PRESENT(BIC_RAMWatt); 2941*812db3f7SLen Brown } 2942e6f9bb3cSLen Brown break; 2943869ce69eSLen Brown case INTEL_FAM6_SANDYBRIDGE_X: 2944869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE_X: 29450b2bb692SLen Brown do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO; 2946*812db3f7SLen Brown BIC_PRESENT(BIC_PKG__); 2947*812db3f7SLen Brown BIC_PRESENT(BIC_RAM__); 2948*812db3f7SLen Brown if (rapl_joules) { 2949*812db3f7SLen Brown BIC_PRESENT(BIC_Pkg_J); 2950*812db3f7SLen Brown BIC_PRESENT(BIC_Cor_J); 2951*812db3f7SLen Brown BIC_PRESENT(BIC_RAM_J); 2952*812db3f7SLen Brown } else { 2953*812db3f7SLen Brown BIC_PRESENT(BIC_PkgWatt); 2954*812db3f7SLen Brown BIC_PRESENT(BIC_CorWatt); 2955*812db3f7SLen Brown BIC_PRESENT(BIC_RAMWatt); 2956*812db3f7SLen Brown } 2957144b44b1SLen Brown break; 2958869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */ 2959869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */ 2960144b44b1SLen Brown do_rapl = RAPL_PKG | RAPL_CORES; 2961*812db3f7SLen Brown if (rapl_joules) { 2962*812db3f7SLen Brown BIC_PRESENT(BIC_Pkg_J); 2963*812db3f7SLen Brown BIC_PRESENT(BIC_Cor_J); 2964*812db3f7SLen Brown } else { 2965*812db3f7SLen Brown BIC_PRESENT(BIC_PkgWatt); 2966*812db3f7SLen Brown BIC_PRESENT(BIC_CorWatt); 2967*812db3f7SLen Brown } 2968889facbeSLen Brown break; 2969869ce69eSLen Brown case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ 29700f644909SJacob Pan do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO | RAPL_CORES_ENERGY_STATUS; 2971*812db3f7SLen Brown BIC_PRESENT(BIC_PKG__); 2972*812db3f7SLen Brown BIC_PRESENT(BIC_RAM__); 2973*812db3f7SLen Brown if (rapl_joules) { 2974*812db3f7SLen Brown BIC_PRESENT(BIC_Pkg_J); 2975*812db3f7SLen Brown BIC_PRESENT(BIC_Cor_J); 2976*812db3f7SLen Brown BIC_PRESENT(BIC_RAM_J); 2977*812db3f7SLen Brown } else { 2978*812db3f7SLen Brown BIC_PRESENT(BIC_PkgWatt); 2979*812db3f7SLen Brown BIC_PRESENT(BIC_CorWatt); 2980*812db3f7SLen Brown BIC_PRESENT(BIC_RAMWatt); 2981*812db3f7SLen Brown } 29820f644909SJacob Pan break; 2983889facbeSLen Brown default: 2984889facbeSLen Brown return; 2985889facbeSLen Brown } 2986889facbeSLen Brown 2987889facbeSLen Brown /* units on package 0, verify later other packages match */ 29887ce7d5deSPrarit Bhargava if (get_msr(base_cpu, MSR_RAPL_POWER_UNIT, &msr)) 2989889facbeSLen Brown return; 2990889facbeSLen Brown 2991889facbeSLen Brown rapl_power_units = 1.0 / (1 << (msr & 0xF)); 2992869ce69eSLen Brown if (model == INTEL_FAM6_ATOM_SILVERMONT1) 2993144b44b1SLen Brown rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000; 2994144b44b1SLen Brown else 2995889facbeSLen Brown rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F)); 2996889facbeSLen Brown 299740ee8e3bSAndrey Semin rapl_dram_energy_units = rapl_dram_energy_units_probe(model, rapl_energy_units); 299840ee8e3bSAndrey Semin 2999144b44b1SLen Brown time_unit = msr >> 16 & 0xF; 3000144b44b1SLen Brown if (time_unit == 0) 3001144b44b1SLen Brown time_unit = 0xA; 3002889facbeSLen Brown 3003144b44b1SLen Brown rapl_time_units = 1.0 / (1 << (time_unit)); 3004144b44b1SLen Brown 3005144b44b1SLen Brown tdp = get_tdp(model); 3006889facbeSLen Brown 3007889facbeSLen Brown rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp; 3008d8af6f5fSLen Brown if (debug) 3009b7d8c148SLen Brown fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp); 3010889facbeSLen Brown 3011889facbeSLen Brown return; 3012889facbeSLen Brown } 3013889facbeSLen Brown 30141b69317dSColin Ian King void perf_limit_reasons_probe(unsigned int family, unsigned int model) 30153a9a941dSLen Brown { 30163a9a941dSLen Brown if (!genuine_intel) 30173a9a941dSLen Brown return; 30183a9a941dSLen Brown 30193a9a941dSLen Brown if (family != 6) 30203a9a941dSLen Brown return; 30213a9a941dSLen Brown 30223a9a941dSLen Brown switch (model) { 3023869ce69eSLen Brown case INTEL_FAM6_HASWELL_CORE: /* HSW */ 3024869ce69eSLen Brown case INTEL_FAM6_HASWELL_ULT: /* HSW */ 3025869ce69eSLen Brown case INTEL_FAM6_HASWELL_GT3E: /* HSW */ 30263a9a941dSLen Brown do_gfx_perf_limit_reasons = 1; 3027869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSX */ 30283a9a941dSLen Brown do_core_perf_limit_reasons = 1; 30293a9a941dSLen Brown do_ring_perf_limit_reasons = 1; 30303a9a941dSLen Brown default: 30313a9a941dSLen Brown return; 30323a9a941dSLen Brown } 30333a9a941dSLen Brown } 30343a9a941dSLen Brown 3035889facbeSLen Brown int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p) 3036889facbeSLen Brown { 3037889facbeSLen Brown unsigned long long msr; 3038889facbeSLen Brown unsigned int dts; 3039889facbeSLen Brown int cpu; 3040889facbeSLen Brown 3041889facbeSLen Brown if (!(do_dts || do_ptm)) 3042889facbeSLen Brown return 0; 3043889facbeSLen Brown 3044889facbeSLen Brown cpu = t->cpu_id; 3045889facbeSLen Brown 3046889facbeSLen Brown /* DTS is per-core, no need to print for each thread */ 3047889facbeSLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 3048889facbeSLen Brown return 0; 3049889facbeSLen Brown 3050889facbeSLen Brown if (cpu_migrate(cpu)) { 3051b7d8c148SLen Brown fprintf(outf, "Could not migrate to CPU %d\n", cpu); 3052889facbeSLen Brown return -1; 3053889facbeSLen Brown } 3054889facbeSLen Brown 3055889facbeSLen Brown if (do_ptm && (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) { 3056889facbeSLen Brown if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr)) 3057889facbeSLen Brown return 0; 3058889facbeSLen Brown 3059889facbeSLen Brown dts = (msr >> 16) & 0x7F; 3060b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n", 3061889facbeSLen Brown cpu, msr, tcc_activation_temp - dts); 3062889facbeSLen Brown 3063889facbeSLen Brown #ifdef THERM_DEBUG 3064889facbeSLen Brown if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &msr)) 3065889facbeSLen Brown return 0; 3066889facbeSLen Brown 3067889facbeSLen Brown dts = (msr >> 16) & 0x7F; 3068889facbeSLen Brown dts2 = (msr >> 8) & 0x7F; 3069b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", 3070889facbeSLen Brown cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2); 3071889facbeSLen Brown #endif 3072889facbeSLen Brown } 3073889facbeSLen Brown 3074889facbeSLen Brown 3075889facbeSLen Brown if (do_dts) { 3076889facbeSLen Brown unsigned int resolution; 3077889facbeSLen Brown 3078889facbeSLen Brown if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr)) 3079889facbeSLen Brown return 0; 3080889facbeSLen Brown 3081889facbeSLen Brown dts = (msr >> 16) & 0x7F; 3082889facbeSLen Brown resolution = (msr >> 27) & 0xF; 3083b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n", 3084889facbeSLen Brown cpu, msr, tcc_activation_temp - dts, resolution); 3085889facbeSLen Brown 3086889facbeSLen Brown #ifdef THERM_DEBUG 3087889facbeSLen Brown if (get_msr(cpu, MSR_IA32_THERM_INTERRUPT, &msr)) 3088889facbeSLen Brown return 0; 3089889facbeSLen Brown 3090889facbeSLen Brown dts = (msr >> 16) & 0x7F; 3091889facbeSLen Brown dts2 = (msr >> 8) & 0x7F; 3092b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", 3093889facbeSLen Brown cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2); 3094889facbeSLen Brown #endif 3095889facbeSLen Brown } 3096889facbeSLen Brown 3097889facbeSLen Brown return 0; 3098889facbeSLen Brown } 3099889facbeSLen Brown 3100889facbeSLen Brown void print_power_limit_msr(int cpu, unsigned long long msr, char *label) 3101889facbeSLen Brown { 3102b7d8c148SLen Brown fprintf(outf, "cpu%d: %s: %sabled (%f Watts, %f sec, clamp %sabled)\n", 3103889facbeSLen Brown cpu, label, 3104889facbeSLen Brown ((msr >> 15) & 1) ? "EN" : "DIS", 3105889facbeSLen Brown ((msr >> 0) & 0x7FFF) * rapl_power_units, 3106889facbeSLen Brown (1.0 + (((msr >> 22) & 0x3)/4.0)) * (1 << ((msr >> 17) & 0x1F)) * rapl_time_units, 3107889facbeSLen Brown (((msr >> 16) & 1) ? "EN" : "DIS")); 3108889facbeSLen Brown 3109889facbeSLen Brown return; 3110889facbeSLen Brown } 3111889facbeSLen Brown 3112889facbeSLen Brown int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) 3113889facbeSLen Brown { 3114889facbeSLen Brown unsigned long long msr; 3115889facbeSLen Brown int cpu; 3116889facbeSLen Brown 3117889facbeSLen Brown if (!do_rapl) 3118889facbeSLen Brown return 0; 3119889facbeSLen Brown 3120889facbeSLen Brown /* RAPL counters are per package, so print only for 1st thread/package */ 3121889facbeSLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 3122889facbeSLen Brown return 0; 3123889facbeSLen Brown 3124889facbeSLen Brown cpu = t->cpu_id; 3125889facbeSLen Brown if (cpu_migrate(cpu)) { 3126b7d8c148SLen Brown fprintf(outf, "Could not migrate to CPU %d\n", cpu); 3127889facbeSLen Brown return -1; 3128889facbeSLen Brown } 3129889facbeSLen Brown 3130889facbeSLen Brown if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr)) 3131889facbeSLen Brown return -1; 3132889facbeSLen Brown 3133d8af6f5fSLen Brown if (debug) { 3134b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_RAPL_POWER_UNIT: 0x%08llx " 3135889facbeSLen Brown "(%f Watts, %f Joules, %f sec.)\n", cpu, msr, 3136144b44b1SLen Brown rapl_power_units, rapl_energy_units, rapl_time_units); 3137889facbeSLen Brown } 3138144b44b1SLen Brown if (do_rapl & RAPL_PKG_POWER_INFO) { 3139144b44b1SLen Brown 3140889facbeSLen Brown if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr)) 3141889facbeSLen Brown return -5; 3142889facbeSLen Brown 3143889facbeSLen Brown 3144b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PKG_POWER_INFO: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n", 3145889facbeSLen Brown cpu, msr, 3146889facbeSLen Brown ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units, 3147889facbeSLen Brown ((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units, 3148889facbeSLen Brown ((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units, 3149889facbeSLen Brown ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units); 3150889facbeSLen Brown 3151144b44b1SLen Brown } 3152144b44b1SLen Brown if (do_rapl & RAPL_PKG) { 3153144b44b1SLen Brown 3154889facbeSLen Brown if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr)) 3155889facbeSLen Brown return -9; 3156889facbeSLen Brown 3157b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n", 3158889facbeSLen Brown cpu, msr, (msr >> 63) & 1 ? "": "UN"); 3159889facbeSLen Brown 3160889facbeSLen Brown print_power_limit_msr(cpu, msr, "PKG Limit #1"); 3161b7d8c148SLen Brown fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%f Watts, %f* sec, clamp %sabled)\n", 3162889facbeSLen Brown cpu, 3163889facbeSLen Brown ((msr >> 47) & 1) ? "EN" : "DIS", 3164889facbeSLen Brown ((msr >> 32) & 0x7FFF) * rapl_power_units, 3165889facbeSLen Brown (1.0 + (((msr >> 54) & 0x3)/4.0)) * (1 << ((msr >> 49) & 0x1F)) * rapl_time_units, 3166889facbeSLen Brown ((msr >> 48) & 1) ? "EN" : "DIS"); 3167889facbeSLen Brown } 3168889facbeSLen Brown 31690b2bb692SLen Brown if (do_rapl & RAPL_DRAM_POWER_INFO) { 3170889facbeSLen Brown if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr)) 3171889facbeSLen Brown return -6; 3172889facbeSLen Brown 3173b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n", 3174889facbeSLen Brown cpu, msr, 3175889facbeSLen Brown ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units, 3176889facbeSLen Brown ((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units, 3177889facbeSLen Brown ((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units, 3178889facbeSLen Brown ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units); 31790b2bb692SLen Brown } 31800b2bb692SLen Brown if (do_rapl & RAPL_DRAM) { 3181889facbeSLen Brown if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr)) 3182889facbeSLen Brown return -9; 3183b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n", 3184889facbeSLen Brown cpu, msr, (msr >> 31) & 1 ? "": "UN"); 3185889facbeSLen Brown 3186889facbeSLen Brown print_power_limit_msr(cpu, msr, "DRAM Limit"); 3187889facbeSLen Brown } 3188144b44b1SLen Brown if (do_rapl & RAPL_CORE_POLICY) { 3189d8af6f5fSLen Brown if (debug) { 3190889facbeSLen Brown if (get_msr(cpu, MSR_PP0_POLICY, &msr)) 3191889facbeSLen Brown return -7; 3192889facbeSLen Brown 3193b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF); 3194144b44b1SLen Brown } 3195144b44b1SLen Brown } 31969148494cSJacob Pan if (do_rapl & RAPL_CORES_POWER_LIMIT) { 3197d8af6f5fSLen Brown if (debug) { 3198889facbeSLen Brown if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr)) 3199889facbeSLen Brown return -9; 3200b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n", 3201889facbeSLen Brown cpu, msr, (msr >> 31) & 1 ? "": "UN"); 3202889facbeSLen Brown print_power_limit_msr(cpu, msr, "Cores Limit"); 3203889facbeSLen Brown } 3204889facbeSLen Brown } 3205889facbeSLen Brown if (do_rapl & RAPL_GFX) { 3206d8af6f5fSLen Brown if (debug) { 3207889facbeSLen Brown if (get_msr(cpu, MSR_PP1_POLICY, &msr)) 3208889facbeSLen Brown return -8; 3209889facbeSLen Brown 3210b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF); 3211889facbeSLen Brown 3212889facbeSLen Brown if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr)) 3213889facbeSLen Brown return -9; 3214b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n", 3215889facbeSLen Brown cpu, msr, (msr >> 31) & 1 ? "": "UN"); 3216889facbeSLen Brown print_power_limit_msr(cpu, msr, "GFX Limit"); 3217889facbeSLen Brown } 3218889facbeSLen Brown } 3219889facbeSLen Brown return 0; 3220889facbeSLen Brown } 3221889facbeSLen Brown 3222d7899447SLen Brown /* 3223d7899447SLen Brown * SNB adds support for additional MSRs: 3224d7899447SLen Brown * 3225d7899447SLen Brown * MSR_PKG_C7_RESIDENCY 0x000003fa 3226d7899447SLen Brown * MSR_CORE_C7_RESIDENCY 0x000003fe 3227d7899447SLen Brown * MSR_PKG_C2_RESIDENCY 0x0000060d 3228d7899447SLen Brown */ 3229103a8feaSLen Brown 3230d7899447SLen Brown int has_snb_msrs(unsigned int family, unsigned int model) 3231103a8feaSLen Brown { 3232103a8feaSLen Brown if (!genuine_intel) 3233103a8feaSLen Brown return 0; 3234103a8feaSLen Brown 3235103a8feaSLen Brown switch (model) { 3236869ce69eSLen Brown case INTEL_FAM6_SANDYBRIDGE: 3237869ce69eSLen Brown case INTEL_FAM6_SANDYBRIDGE_X: 3238869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE: /* IVB */ 3239869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */ 3240869ce69eSLen Brown case INTEL_FAM6_HASWELL_CORE: /* HSW */ 3241869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSW */ 3242869ce69eSLen Brown case INTEL_FAM6_HASWELL_ULT: /* HSW */ 3243869ce69eSLen Brown case INTEL_FAM6_HASWELL_GT3E: /* HSW */ 3244869ce69eSLen Brown case INTEL_FAM6_BROADWELL_CORE: /* BDW */ 3245869ce69eSLen Brown case INTEL_FAM6_BROADWELL_GT3E: /* BDW */ 3246869ce69eSLen Brown case INTEL_FAM6_BROADWELL_X: /* BDX */ 3247869ce69eSLen Brown case INTEL_FAM6_BROADWELL_XEON_D: /* BDX-DE */ 3248869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 3249869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 3250869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 3251869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 3252869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_X: /* SKX */ 3253869ce69eSLen Brown case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 32545bbac26eSXiaolong Wang case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ 3255103a8feaSLen Brown return 1; 3256103a8feaSLen Brown } 3257103a8feaSLen Brown return 0; 3258103a8feaSLen Brown } 3259103a8feaSLen Brown 3260d7899447SLen Brown /* 3261d7899447SLen Brown * HSW adds support for additional MSRs: 3262d7899447SLen Brown * 3263d7899447SLen Brown * MSR_PKG_C8_RESIDENCY 0x00000630 3264d7899447SLen Brown * MSR_PKG_C9_RESIDENCY 0x00000631 3265d7899447SLen Brown * MSR_PKG_C10_RESIDENCY 0x00000632 32665a63426eSLen Brown * 32675a63426eSLen Brown * MSR_PKGC8_IRTL 0x00000633 32685a63426eSLen Brown * MSR_PKGC9_IRTL 0x00000634 32695a63426eSLen Brown * MSR_PKGC10_IRTL 0x00000635 32705a63426eSLen Brown * 3271d7899447SLen Brown */ 3272d7899447SLen Brown int has_hsw_msrs(unsigned int family, unsigned int model) 3273ca58710fSKristen Carlson Accardi { 3274ca58710fSKristen Carlson Accardi if (!genuine_intel) 3275ca58710fSKristen Carlson Accardi return 0; 3276ca58710fSKristen Carlson Accardi 3277ca58710fSKristen Carlson Accardi switch (model) { 3278869ce69eSLen Brown case INTEL_FAM6_HASWELL_ULT: /* HSW */ 3279869ce69eSLen Brown case INTEL_FAM6_BROADWELL_CORE: /* BDW */ 3280869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 3281869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 3282869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 3283869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 3284869ce69eSLen Brown case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 3285ca58710fSKristen Carlson Accardi return 1; 3286ca58710fSKristen Carlson Accardi } 3287ca58710fSKristen Carlson Accardi return 0; 3288ca58710fSKristen Carlson Accardi } 3289ca58710fSKristen Carlson Accardi 32900b2bb692SLen Brown /* 32910b2bb692SLen Brown * SKL adds support for additional MSRS: 32920b2bb692SLen Brown * 32930b2bb692SLen Brown * MSR_PKG_WEIGHTED_CORE_C0_RES 0x00000658 32940b2bb692SLen Brown * MSR_PKG_ANY_CORE_C0_RES 0x00000659 32950b2bb692SLen Brown * MSR_PKG_ANY_GFXE_C0_RES 0x0000065A 32960b2bb692SLen Brown * MSR_PKG_BOTH_CORE_GFXE_C0_RES 0x0000065B 32970b2bb692SLen Brown */ 32980b2bb692SLen Brown int has_skl_msrs(unsigned int family, unsigned int model) 32990b2bb692SLen Brown { 33000b2bb692SLen Brown if (!genuine_intel) 33010b2bb692SLen Brown return 0; 33020b2bb692SLen Brown 33030b2bb692SLen Brown switch (model) { 3304869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 3305869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 3306869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 3307869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 33080b2bb692SLen Brown return 1; 33090b2bb692SLen Brown } 33100b2bb692SLen Brown return 0; 33110b2bb692SLen Brown } 33120b2bb692SLen Brown 33130b2bb692SLen Brown 3314ca58710fSKristen Carlson Accardi 3315144b44b1SLen Brown int is_slm(unsigned int family, unsigned int model) 3316144b44b1SLen Brown { 3317144b44b1SLen Brown if (!genuine_intel) 3318144b44b1SLen Brown return 0; 3319144b44b1SLen Brown switch (model) { 3320869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */ 3321869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */ 3322144b44b1SLen Brown return 1; 3323144b44b1SLen Brown } 3324144b44b1SLen Brown return 0; 3325144b44b1SLen Brown } 3326144b44b1SLen Brown 3327fb5d4327SDasaratharaman Chandramouli int is_knl(unsigned int family, unsigned int model) 3328fb5d4327SDasaratharaman Chandramouli { 3329fb5d4327SDasaratharaman Chandramouli if (!genuine_intel) 3330fb5d4327SDasaratharaman Chandramouli return 0; 3331fb5d4327SDasaratharaman Chandramouli switch (model) { 3332869ce69eSLen Brown case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ 3333005c82d6SLen Brown case INTEL_FAM6_XEON_PHI_KNM: 3334fb5d4327SDasaratharaman Chandramouli return 1; 3335fb5d4327SDasaratharaman Chandramouli } 3336fb5d4327SDasaratharaman Chandramouli return 0; 3337fb5d4327SDasaratharaman Chandramouli } 3338fb5d4327SDasaratharaman Chandramouli 3339b2b34dfeSHubert Chrzaniuk unsigned int get_aperf_mperf_multiplier(unsigned int family, unsigned int model) 3340b2b34dfeSHubert Chrzaniuk { 3341b2b34dfeSHubert Chrzaniuk if (is_knl(family, model)) 3342b2b34dfeSHubert Chrzaniuk return 1024; 3343b2b34dfeSHubert Chrzaniuk return 1; 3344b2b34dfeSHubert Chrzaniuk } 3345b2b34dfeSHubert Chrzaniuk 3346144b44b1SLen Brown #define SLM_BCLK_FREQS 5 3347144b44b1SLen Brown double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0}; 3348144b44b1SLen Brown 3349144b44b1SLen Brown double slm_bclk(void) 3350144b44b1SLen Brown { 3351144b44b1SLen Brown unsigned long long msr = 3; 3352144b44b1SLen Brown unsigned int i; 3353144b44b1SLen Brown double freq; 3354144b44b1SLen Brown 33557ce7d5deSPrarit Bhargava if (get_msr(base_cpu, MSR_FSB_FREQ, &msr)) 3356b7d8c148SLen Brown fprintf(outf, "SLM BCLK: unknown\n"); 3357144b44b1SLen Brown 3358144b44b1SLen Brown i = msr & 0xf; 3359144b44b1SLen Brown if (i >= SLM_BCLK_FREQS) { 3360b7d8c148SLen Brown fprintf(outf, "SLM BCLK[%d] invalid\n", i); 33610a91e551SColin Ian King i = 3; 3362144b44b1SLen Brown } 3363144b44b1SLen Brown freq = slm_freq_table[i]; 3364144b44b1SLen Brown 3365b7d8c148SLen Brown fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq); 3366144b44b1SLen Brown 3367144b44b1SLen Brown return freq; 3368144b44b1SLen Brown } 3369144b44b1SLen Brown 3370103a8feaSLen Brown double discover_bclk(unsigned int family, unsigned int model) 3371103a8feaSLen Brown { 3372121b48bbSChrzaniuk, Hubert if (has_snb_msrs(family, model) || is_knl(family, model)) 3373103a8feaSLen Brown return 100.00; 3374144b44b1SLen Brown else if (is_slm(family, model)) 3375144b44b1SLen Brown return slm_bclk(); 3376103a8feaSLen Brown else 3377103a8feaSLen Brown return 133.33; 3378103a8feaSLen Brown } 3379103a8feaSLen Brown 3380889facbeSLen Brown /* 3381889facbeSLen Brown * MSR_IA32_TEMPERATURE_TARGET indicates the temperature where 3382889facbeSLen Brown * the Thermal Control Circuit (TCC) activates. 3383889facbeSLen Brown * This is usually equal to tjMax. 3384889facbeSLen Brown * 3385889facbeSLen Brown * Older processors do not have this MSR, so there we guess, 3386889facbeSLen Brown * but also allow cmdline over-ride with -T. 3387889facbeSLen Brown * 3388889facbeSLen Brown * Several MSR temperature values are in units of degrees-C 3389889facbeSLen Brown * below this value, including the Digital Thermal Sensor (DTS), 3390889facbeSLen Brown * Package Thermal Management Sensor (PTM), and thermal event thresholds. 3391889facbeSLen Brown */ 3392889facbeSLen Brown int set_temperature_target(struct thread_data *t, struct core_data *c, struct pkg_data *p) 3393889facbeSLen Brown { 3394889facbeSLen Brown unsigned long long msr; 3395889facbeSLen Brown unsigned int target_c_local; 3396889facbeSLen Brown int cpu; 3397889facbeSLen Brown 3398889facbeSLen Brown /* tcc_activation_temp is used only for dts or ptm */ 3399889facbeSLen Brown if (!(do_dts || do_ptm)) 3400889facbeSLen Brown return 0; 3401889facbeSLen Brown 3402889facbeSLen Brown /* this is a per-package concept */ 3403889facbeSLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 3404889facbeSLen Brown return 0; 3405889facbeSLen Brown 3406889facbeSLen Brown cpu = t->cpu_id; 3407889facbeSLen Brown if (cpu_migrate(cpu)) { 3408b7d8c148SLen Brown fprintf(outf, "Could not migrate to CPU %d\n", cpu); 3409889facbeSLen Brown return -1; 3410889facbeSLen Brown } 3411889facbeSLen Brown 3412889facbeSLen Brown if (tcc_activation_temp_override != 0) { 3413889facbeSLen Brown tcc_activation_temp = tcc_activation_temp_override; 3414b7d8c148SLen Brown fprintf(outf, "cpu%d: Using cmdline TCC Target (%d C)\n", 3415889facbeSLen Brown cpu, tcc_activation_temp); 3416889facbeSLen Brown return 0; 3417889facbeSLen Brown } 3418889facbeSLen Brown 3419889facbeSLen Brown /* Temperature Target MSR is Nehalem and newer only */ 3420d7899447SLen Brown if (!do_nhm_platform_info) 3421889facbeSLen Brown goto guess; 3422889facbeSLen Brown 34237ce7d5deSPrarit Bhargava if (get_msr(base_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr)) 3424889facbeSLen Brown goto guess; 3425889facbeSLen Brown 34263482124aSJean Delvare target_c_local = (msr >> 16) & 0xFF; 3427889facbeSLen Brown 3428d8af6f5fSLen Brown if (debug) 3429b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n", 3430889facbeSLen Brown cpu, msr, target_c_local); 3431889facbeSLen Brown 34323482124aSJean Delvare if (!target_c_local) 3433889facbeSLen Brown goto guess; 3434889facbeSLen Brown 3435889facbeSLen Brown tcc_activation_temp = target_c_local; 3436889facbeSLen Brown 3437889facbeSLen Brown return 0; 3438889facbeSLen Brown 3439889facbeSLen Brown guess: 3440889facbeSLen Brown tcc_activation_temp = TJMAX_DEFAULT; 3441b7d8c148SLen Brown fprintf(outf, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n", 3442889facbeSLen Brown cpu, tcc_activation_temp); 3443889facbeSLen Brown 3444889facbeSLen Brown return 0; 3445889facbeSLen Brown } 344669807a63SLen Brown 3447aa8d8cc7SLen Brown void decode_feature_control_msr(void) 3448aa8d8cc7SLen Brown { 3449aa8d8cc7SLen Brown unsigned long long msr; 3450aa8d8cc7SLen Brown 3451aa8d8cc7SLen Brown if (!get_msr(base_cpu, MSR_IA32_FEATURE_CONTROL, &msr)) 3452aa8d8cc7SLen Brown fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n", 3453aa8d8cc7SLen Brown base_cpu, msr, 3454aa8d8cc7SLen Brown msr & FEATURE_CONTROL_LOCKED ? "" : "UN-", 3455aa8d8cc7SLen Brown msr & (1 << 18) ? "SGX" : ""); 3456aa8d8cc7SLen Brown } 3457aa8d8cc7SLen Brown 345869807a63SLen Brown void decode_misc_enable_msr(void) 345969807a63SLen Brown { 346069807a63SLen Brown unsigned long long msr; 346169807a63SLen Brown 346269807a63SLen Brown if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr)) 3463b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%s %s %s)\n", 346469807a63SLen Brown base_cpu, msr, 346569807a63SLen Brown msr & (1 << 3) ? "TCC" : "", 346669807a63SLen Brown msr & (1 << 16) ? "EIST" : "", 346769807a63SLen Brown msr & (1 << 18) ? "MONITOR" : ""); 346869807a63SLen Brown } 346969807a63SLen Brown 3470f0057310SLen Brown /* 3471f0057310SLen Brown * Decode MSR_MISC_PWR_MGMT 3472f0057310SLen Brown * 3473f0057310SLen Brown * Decode the bits according to the Nehalem documentation 3474f0057310SLen Brown * bit[0] seems to continue to have same meaning going forward 3475f0057310SLen Brown * bit[1] less so... 3476f0057310SLen Brown */ 3477f0057310SLen Brown void decode_misc_pwr_mgmt_msr(void) 3478f0057310SLen Brown { 3479f0057310SLen Brown unsigned long long msr; 3480f0057310SLen Brown 3481f0057310SLen Brown if (!do_nhm_platform_info) 3482f0057310SLen Brown return; 3483f0057310SLen Brown 3484f0057310SLen Brown if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr)) 3485ddadb8adSSrinivas Pandruvada fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB %sable-OOB)\n", 3486f0057310SLen Brown base_cpu, msr, 3487f0057310SLen Brown msr & (1 << 0) ? "DIS" : "EN", 3488ddadb8adSSrinivas Pandruvada msr & (1 << 1) ? "EN" : "DIS", 3489ddadb8adSSrinivas Pandruvada msr & (1 << 8) ? "EN" : "DIS"); 3490f0057310SLen Brown } 34917f5c258eSLen Brown 3492fcd17211SLen Brown void process_cpuid() 3493103a8feaSLen Brown { 349461a87ba7SLen Brown unsigned int eax, ebx, ecx, edx, max_level, max_extended_level; 3495103a8feaSLen Brown unsigned int fms, family, model, stepping; 3496103a8feaSLen Brown 3497103a8feaSLen Brown eax = ebx = ecx = edx = 0; 3498103a8feaSLen Brown 34995aea2f7fSLen Brown __cpuid(0, max_level, ebx, ecx, edx); 3500103a8feaSLen Brown 3501103a8feaSLen Brown if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e) 3502103a8feaSLen Brown genuine_intel = 1; 3503103a8feaSLen Brown 3504d8af6f5fSLen Brown if (debug) 3505b7d8c148SLen Brown fprintf(outf, "CPUID(0): %.4s%.4s%.4s ", 3506103a8feaSLen Brown (char *)&ebx, (char *)&edx, (char *)&ecx); 3507103a8feaSLen Brown 35085aea2f7fSLen Brown __cpuid(1, fms, ebx, ecx, edx); 3509103a8feaSLen Brown family = (fms >> 8) & 0xf; 3510103a8feaSLen Brown model = (fms >> 4) & 0xf; 3511103a8feaSLen Brown stepping = fms & 0xf; 3512103a8feaSLen Brown if (family == 6 || family == 0xf) 3513103a8feaSLen Brown model += ((fms >> 16) & 0xf) << 4; 3514103a8feaSLen Brown 351569807a63SLen Brown if (debug) { 3516b7d8c148SLen Brown fprintf(outf, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n", 3517103a8feaSLen Brown max_level, family, model, stepping, family, model, stepping); 3518aa8d8cc7SLen Brown fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s\n", 351969807a63SLen Brown ecx & (1 << 0) ? "SSE3" : "-", 352069807a63SLen Brown ecx & (1 << 3) ? "MONITOR" : "-", 3521aa8d8cc7SLen Brown ecx & (1 << 6) ? "SMX" : "-", 352269807a63SLen Brown ecx & (1 << 7) ? "EIST" : "-", 352369807a63SLen Brown ecx & (1 << 8) ? "TM2" : "-", 352469807a63SLen Brown edx & (1 << 4) ? "TSC" : "-", 352569807a63SLen Brown edx & (1 << 5) ? "MSR" : "-", 352669807a63SLen Brown edx & (1 << 22) ? "ACPI-TM" : "-", 352769807a63SLen Brown edx & (1 << 29) ? "TM" : "-"); 352869807a63SLen Brown } 3529103a8feaSLen Brown 3530b2c95d90SJosh Triplett if (!(edx & (1 << 5))) 3531b2c95d90SJosh Triplett errx(1, "CPUID: no MSR"); 3532103a8feaSLen Brown 3533103a8feaSLen Brown /* 3534103a8feaSLen Brown * check max extended function levels of CPUID. 3535103a8feaSLen Brown * This is needed to check for invariant TSC. 3536103a8feaSLen Brown * This check is valid for both Intel and AMD. 3537103a8feaSLen Brown */ 3538103a8feaSLen Brown ebx = ecx = edx = 0; 35395aea2f7fSLen Brown __cpuid(0x80000000, max_extended_level, ebx, ecx, edx); 3540103a8feaSLen Brown 354161a87ba7SLen Brown if (max_extended_level >= 0x80000007) { 3542103a8feaSLen Brown 3543103a8feaSLen Brown /* 3544103a8feaSLen Brown * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8 3545103a8feaSLen Brown * this check is valid for both Intel and AMD 3546103a8feaSLen Brown */ 35475aea2f7fSLen Brown __cpuid(0x80000007, eax, ebx, ecx, edx); 35488209e054SThomas Renninger has_invariant_tsc = edx & (1 << 8); 3549d7899447SLen Brown } 3550103a8feaSLen Brown 3551103a8feaSLen Brown /* 3552103a8feaSLen Brown * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0 3553103a8feaSLen Brown * this check is valid for both Intel and AMD 3554103a8feaSLen Brown */ 3555103a8feaSLen Brown 35565aea2f7fSLen Brown __cpuid(0x6, eax, ebx, ecx, edx); 35578209e054SThomas Renninger has_aperf = ecx & (1 << 0); 3558*812db3f7SLen Brown if (has_aperf) { 3559*812db3f7SLen Brown BIC_PRESENT(BIC_Avg_MHz); 3560*812db3f7SLen Brown BIC_PRESENT(BIC_Busy); 3561*812db3f7SLen Brown BIC_PRESENT(BIC_Bzy_MHz); 3562*812db3f7SLen Brown } 3563889facbeSLen Brown do_dts = eax & (1 << 0); 3564*812db3f7SLen Brown if (do_dts) 3565*812db3f7SLen Brown BIC_PRESENT(BIC_CoreTmp); 3566889facbeSLen Brown do_ptm = eax & (1 << 6); 3567*812db3f7SLen Brown if (do_ptm) 3568*812db3f7SLen Brown BIC_PRESENT(BIC_PkgTmp); 35697f5c258eSLen Brown has_hwp = eax & (1 << 7); 35707f5c258eSLen Brown has_hwp_notify = eax & (1 << 8); 35717f5c258eSLen Brown has_hwp_activity_window = eax & (1 << 9); 35727f5c258eSLen Brown has_hwp_epp = eax & (1 << 10); 35737f5c258eSLen Brown has_hwp_pkg = eax & (1 << 11); 3574889facbeSLen Brown has_epb = ecx & (1 << 3); 3575889facbeSLen Brown 3576d8af6f5fSLen Brown if (debug) 3577b7d8c148SLen Brown fprintf(outf, "CPUID(6): %sAPERF, %sDTS, %sPTM, %sHWP, " 35787f5c258eSLen Brown "%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n", 35797f5c258eSLen Brown has_aperf ? "" : "No-", 35807f5c258eSLen Brown do_dts ? "" : "No-", 35817f5c258eSLen Brown do_ptm ? "" : "No-", 35827f5c258eSLen Brown has_hwp ? "" : "No-", 35837f5c258eSLen Brown has_hwp_notify ? "" : "No-", 35847f5c258eSLen Brown has_hwp_activity_window ? "" : "No-", 35857f5c258eSLen Brown has_hwp_epp ? "" : "No-", 35867f5c258eSLen Brown has_hwp_pkg ? "" : "No-", 35877f5c258eSLen Brown has_epb ? "" : "No-"); 3588103a8feaSLen Brown 358969807a63SLen Brown if (debug) 359069807a63SLen Brown decode_misc_enable_msr(); 359169807a63SLen Brown 35928ae72255SLen Brown if (max_level >= 0x7 && debug) { 3593aa8d8cc7SLen Brown int has_sgx; 3594aa8d8cc7SLen Brown 3595aa8d8cc7SLen Brown ecx = 0; 3596aa8d8cc7SLen Brown 3597aa8d8cc7SLen Brown __cpuid_count(0x7, 0, eax, ebx, ecx, edx); 3598aa8d8cc7SLen Brown 3599aa8d8cc7SLen Brown has_sgx = ebx & (1 << 2); 3600aa8d8cc7SLen Brown fprintf(outf, "CPUID(7): %sSGX\n", has_sgx ? "" : "No-"); 3601aa8d8cc7SLen Brown 3602aa8d8cc7SLen Brown if (has_sgx) 3603aa8d8cc7SLen Brown decode_feature_control_msr(); 3604aa8d8cc7SLen Brown } 3605aa8d8cc7SLen Brown 360661a87ba7SLen Brown if (max_level >= 0x15) { 36078a5bdf41SLen Brown unsigned int eax_crystal; 36088a5bdf41SLen Brown unsigned int ebx_tsc; 36098a5bdf41SLen Brown 36108a5bdf41SLen Brown /* 36118a5bdf41SLen Brown * CPUID 15H TSC/Crystal ratio, possibly Crystal Hz 36128a5bdf41SLen Brown */ 36138a5bdf41SLen Brown eax_crystal = ebx_tsc = crystal_hz = edx = 0; 36145aea2f7fSLen Brown __cpuid(0x15, eax_crystal, ebx_tsc, crystal_hz, edx); 36158a5bdf41SLen Brown 36168a5bdf41SLen Brown if (ebx_tsc != 0) { 36178a5bdf41SLen Brown 36188a5bdf41SLen Brown if (debug && (ebx != 0)) 3619b7d8c148SLen Brown fprintf(outf, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n", 36208a5bdf41SLen Brown eax_crystal, ebx_tsc, crystal_hz); 36218a5bdf41SLen Brown 36228a5bdf41SLen Brown if (crystal_hz == 0) 36238a5bdf41SLen Brown switch(model) { 3624869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 3625869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 3626869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 3627869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 3628e8efbc80SLen Brown crystal_hz = 24000000; /* 24.0 MHz */ 3629e8efbc80SLen Brown break; 3630869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_X: /* SKX */ 36317268d407SLen Brown case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ 3632ec53e594SLen Brown crystal_hz = 25000000; /* 25.0 MHz */ 3633ec53e594SLen Brown break; 3634869ce69eSLen Brown case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 3635e8efbc80SLen Brown crystal_hz = 19200000; /* 19.2 MHz */ 36368a5bdf41SLen Brown break; 36378a5bdf41SLen Brown default: 36388a5bdf41SLen Brown crystal_hz = 0; 36398a5bdf41SLen Brown } 36408a5bdf41SLen Brown 36418a5bdf41SLen Brown if (crystal_hz) { 36428a5bdf41SLen Brown tsc_hz = (unsigned long long) crystal_hz * ebx_tsc / eax_crystal; 36438a5bdf41SLen Brown if (debug) 3644b7d8c148SLen Brown fprintf(outf, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n", 36458a5bdf41SLen Brown tsc_hz / 1000000, crystal_hz, ebx_tsc, eax_crystal); 36468a5bdf41SLen Brown } 36478a5bdf41SLen Brown } 36488a5bdf41SLen Brown } 364961a87ba7SLen Brown if (max_level >= 0x16) { 365061a87ba7SLen Brown unsigned int base_mhz, max_mhz, bus_mhz, edx; 365161a87ba7SLen Brown 365261a87ba7SLen Brown /* 365361a87ba7SLen Brown * CPUID 16H Base MHz, Max MHz, Bus MHz 365461a87ba7SLen Brown */ 365561a87ba7SLen Brown base_mhz = max_mhz = bus_mhz = edx = 0; 365661a87ba7SLen Brown 36575aea2f7fSLen Brown __cpuid(0x16, base_mhz, max_mhz, bus_mhz, edx); 365861a87ba7SLen Brown if (debug) 3659b7d8c148SLen Brown fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n", 366061a87ba7SLen Brown base_mhz, max_mhz, bus_mhz); 366161a87ba7SLen Brown } 36628a5bdf41SLen Brown 3663b2b34dfeSHubert Chrzaniuk if (has_aperf) 3664b2b34dfeSHubert Chrzaniuk aperf_mperf_multiplier = get_aperf_mperf_multiplier(family, model); 3665b2b34dfeSHubert Chrzaniuk 3666*812db3f7SLen Brown BIC_PRESENT(BIC_IRQ); 3667*812db3f7SLen Brown BIC_PRESENT(BIC_TSC_MHz); 3668*812db3f7SLen Brown 3669*812db3f7SLen Brown if (probe_nhm_msrs(family, model)) { 3670*812db3f7SLen Brown do_nhm_platform_info = 1; 3671*812db3f7SLen Brown BIC_PRESENT(BIC_CPU_c1); 3672*812db3f7SLen Brown BIC_PRESENT(BIC_CPU_c3); 3673*812db3f7SLen Brown BIC_PRESENT(BIC_CPU_c6); 3674*812db3f7SLen Brown BIC_PRESENT(BIC_SMI); 3675*812db3f7SLen Brown } 3676d7899447SLen Brown do_snb_cstates = has_snb_msrs(family, model); 3677*812db3f7SLen Brown 3678*812db3f7SLen Brown if (do_snb_cstates) 3679*812db3f7SLen Brown BIC_PRESENT(BIC_CPU_c7); 3680*812db3f7SLen Brown 36815a63426eSLen Brown do_irtl_snb = has_snb_msrs(family, model); 3682ee7e38e3SLen Brown do_pc2 = do_snb_cstates && (pkg_cstate_limit >= PCL__2); 3683ee7e38e3SLen Brown do_pc3 = (pkg_cstate_limit >= PCL__3); 3684ee7e38e3SLen Brown do_pc6 = (pkg_cstate_limit >= PCL__6); 3685ee7e38e3SLen Brown do_pc7 = do_snb_cstates && (pkg_cstate_limit >= PCL__7); 3686d7899447SLen Brown do_c8_c9_c10 = has_hsw_msrs(family, model); 36875a63426eSLen Brown do_irtl_hsw = has_hsw_msrs(family, model); 36880b2bb692SLen Brown do_skl_residency = has_skl_msrs(family, model); 3689144b44b1SLen Brown do_slm_cstates = is_slm(family, model); 3690fb5d4327SDasaratharaman Chandramouli do_knl_cstates = is_knl(family, model); 3691103a8feaSLen Brown 3692f0057310SLen Brown if (debug) 3693f0057310SLen Brown decode_misc_pwr_mgmt_msr(); 3694f0057310SLen Brown 3695889facbeSLen Brown rapl_probe(family, model); 36963a9a941dSLen Brown perf_limit_reasons_probe(family, model); 3697889facbeSLen Brown 3698fcd17211SLen Brown if (debug) 36991b69317dSColin Ian King dump_cstate_pstate_config_info(family, model); 3700fcd17211SLen Brown 3701a2b7b749SLen Brown if (has_skl_msrs(family, model)) 3702a2b7b749SLen Brown calculate_tsc_tweak(); 3703a2b7b749SLen Brown 3704*812db3f7SLen Brown if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK)) 3705*812db3f7SLen Brown BIC_PRESENT(BIC_GFX_rc6); 3706fdf676e5SLen Brown 3707*812db3f7SLen Brown if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK)) 3708*812db3f7SLen Brown BIC_PRESENT(BIC_GFXMHz); 370927d47356SLen Brown 3710889facbeSLen Brown return; 3711103a8feaSLen Brown } 3712103a8feaSLen Brown 3713d8af6f5fSLen Brown void help() 3714103a8feaSLen Brown { 3715b7d8c148SLen Brown fprintf(outf, 3716d8af6f5fSLen Brown "Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n" 3717d8af6f5fSLen Brown "\n" 3718d8af6f5fSLen Brown "Turbostat forks the specified COMMAND and prints statistics\n" 3719d8af6f5fSLen Brown "when COMMAND completes.\n" 3720d8af6f5fSLen Brown "If no COMMAND is specified, turbostat wakes every 5-seconds\n" 3721d8af6f5fSLen Brown "to print statistics, until interrupted.\n" 3722388e9c81SLen Brown "--add add a counter\n" 3723388e9c81SLen Brown " eg. --add msr0x10,u64,cpu,delta,MY_TSC\n" 3724d8af6f5fSLen Brown "--debug run in \"debug\" mode\n" 3725d8af6f5fSLen Brown "--interval sec Override default 5-second measurement interval\n" 3726d8af6f5fSLen Brown "--help print this help message\n" 3727b7d8c148SLen Brown "--out file create or truncate \"file\" for all output\n" 3728d8af6f5fSLen Brown "--version print version information\n" 3729d8af6f5fSLen Brown "\n" 3730d8af6f5fSLen Brown "For more help, run \"man turbostat\"\n"); 3731103a8feaSLen Brown } 3732103a8feaSLen Brown 3733103a8feaSLen Brown 3734103a8feaSLen Brown /* 3735103a8feaSLen Brown * in /dev/cpu/ return success for names that are numbers 3736103a8feaSLen Brown * ie. filter out ".", "..", "microcode". 3737103a8feaSLen Brown */ 3738103a8feaSLen Brown int dir_filter(const struct dirent *dirp) 3739103a8feaSLen Brown { 3740103a8feaSLen Brown if (isdigit(dirp->d_name[0])) 3741103a8feaSLen Brown return 1; 3742103a8feaSLen Brown else 3743103a8feaSLen Brown return 0; 3744103a8feaSLen Brown } 3745103a8feaSLen Brown 3746103a8feaSLen Brown int open_dev_cpu_msr(int dummy1) 3747103a8feaSLen Brown { 3748103a8feaSLen Brown return 0; 3749103a8feaSLen Brown } 3750103a8feaSLen Brown 3751c98d5d94SLen Brown void topology_probe() 3752c98d5d94SLen Brown { 3753c98d5d94SLen Brown int i; 3754c98d5d94SLen Brown int max_core_id = 0; 3755c98d5d94SLen Brown int max_package_id = 0; 3756c98d5d94SLen Brown int max_siblings = 0; 3757c98d5d94SLen Brown struct cpu_topology { 3758c98d5d94SLen Brown int core_id; 3759c98d5d94SLen Brown int physical_package_id; 3760c98d5d94SLen Brown } *cpus; 3761c98d5d94SLen Brown 3762c98d5d94SLen Brown /* Initialize num_cpus, max_cpu_num */ 3763c98d5d94SLen Brown topo.num_cpus = 0; 3764c98d5d94SLen Brown topo.max_cpu_num = 0; 3765c98d5d94SLen Brown for_all_proc_cpus(count_cpus); 3766c98d5d94SLen Brown if (!summary_only && topo.num_cpus > 1) 3767*812db3f7SLen Brown BIC_PRESENT(BIC_CPU); 3768c98d5d94SLen Brown 3769d8af6f5fSLen Brown if (debug > 1) 3770b7d8c148SLen Brown fprintf(outf, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num); 3771c98d5d94SLen Brown 3772c98d5d94SLen Brown cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology)); 3773b2c95d90SJosh Triplett if (cpus == NULL) 3774b2c95d90SJosh Triplett err(1, "calloc cpus"); 3775c98d5d94SLen Brown 3776c98d5d94SLen Brown /* 3777c98d5d94SLen Brown * Allocate and initialize cpu_present_set 3778c98d5d94SLen Brown */ 3779c98d5d94SLen Brown cpu_present_set = CPU_ALLOC((topo.max_cpu_num + 1)); 3780b2c95d90SJosh Triplett if (cpu_present_set == NULL) 3781b2c95d90SJosh Triplett err(3, "CPU_ALLOC"); 3782c98d5d94SLen Brown cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); 3783c98d5d94SLen Brown CPU_ZERO_S(cpu_present_setsize, cpu_present_set); 3784c98d5d94SLen Brown for_all_proc_cpus(mark_cpu_present); 3785c98d5d94SLen Brown 3786c98d5d94SLen Brown /* 3787c98d5d94SLen Brown * Allocate and initialize cpu_affinity_set 3788c98d5d94SLen Brown */ 3789c98d5d94SLen Brown cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1)); 3790b2c95d90SJosh Triplett if (cpu_affinity_set == NULL) 3791b2c95d90SJosh Triplett err(3, "CPU_ALLOC"); 3792c98d5d94SLen Brown cpu_affinity_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); 3793c98d5d94SLen Brown CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set); 3794c98d5d94SLen Brown 3795c98d5d94SLen Brown 3796c98d5d94SLen Brown /* 3797c98d5d94SLen Brown * For online cpus 3798c98d5d94SLen Brown * find max_core_id, max_package_id 3799c98d5d94SLen Brown */ 3800c98d5d94SLen Brown for (i = 0; i <= topo.max_cpu_num; ++i) { 3801c98d5d94SLen Brown int siblings; 3802c98d5d94SLen Brown 3803c98d5d94SLen Brown if (cpu_is_not_present(i)) { 3804d8af6f5fSLen Brown if (debug > 1) 3805b7d8c148SLen Brown fprintf(outf, "cpu%d NOT PRESENT\n", i); 3806c98d5d94SLen Brown continue; 3807c98d5d94SLen Brown } 3808c98d5d94SLen Brown cpus[i].core_id = get_core_id(i); 3809c98d5d94SLen Brown if (cpus[i].core_id > max_core_id) 3810c98d5d94SLen Brown max_core_id = cpus[i].core_id; 3811c98d5d94SLen Brown 3812c98d5d94SLen Brown cpus[i].physical_package_id = get_physical_package_id(i); 3813c98d5d94SLen Brown if (cpus[i].physical_package_id > max_package_id) 3814c98d5d94SLen Brown max_package_id = cpus[i].physical_package_id; 3815c98d5d94SLen Brown 3816c98d5d94SLen Brown siblings = get_num_ht_siblings(i); 3817c98d5d94SLen Brown if (siblings > max_siblings) 3818c98d5d94SLen Brown max_siblings = siblings; 3819d8af6f5fSLen Brown if (debug > 1) 3820b7d8c148SLen Brown fprintf(outf, "cpu %d pkg %d core %d\n", 3821c98d5d94SLen Brown i, cpus[i].physical_package_id, cpus[i].core_id); 3822c98d5d94SLen Brown } 3823c98d5d94SLen Brown topo.num_cores_per_pkg = max_core_id + 1; 3824d8af6f5fSLen Brown if (debug > 1) 3825b7d8c148SLen Brown fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", 3826c98d5d94SLen Brown max_core_id, topo.num_cores_per_pkg); 38271cc21f7bSLen Brown if (debug && !summary_only && topo.num_cores_per_pkg > 1) 3828*812db3f7SLen Brown BIC_PRESENT(BIC_Core); 3829c98d5d94SLen Brown 3830c98d5d94SLen Brown topo.num_packages = max_package_id + 1; 3831d8af6f5fSLen Brown if (debug > 1) 3832b7d8c148SLen Brown fprintf(outf, "max_package_id %d, sizing for %d packages\n", 3833c98d5d94SLen Brown max_package_id, topo.num_packages); 38341cc21f7bSLen Brown if (debug && !summary_only && topo.num_packages > 1) 3835*812db3f7SLen Brown BIC_PRESENT(BIC_Package); 3836c98d5d94SLen Brown 3837c98d5d94SLen Brown topo.num_threads_per_core = max_siblings; 3838d8af6f5fSLen Brown if (debug > 1) 3839b7d8c148SLen Brown fprintf(outf, "max_siblings %d\n", max_siblings); 3840c98d5d94SLen Brown 3841c98d5d94SLen Brown free(cpus); 3842c98d5d94SLen Brown } 3843c98d5d94SLen Brown 3844c98d5d94SLen Brown void 3845c98d5d94SLen Brown allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data **p) 3846c98d5d94SLen Brown { 3847c98d5d94SLen Brown int i; 3848c98d5d94SLen Brown 3849c98d5d94SLen Brown *t = calloc(topo.num_threads_per_core * topo.num_cores_per_pkg * 3850678a3bd1SLen Brown topo.num_packages, sizeof(struct thread_data)); 3851c98d5d94SLen Brown if (*t == NULL) 3852c98d5d94SLen Brown goto error; 3853c98d5d94SLen Brown 3854c98d5d94SLen Brown for (i = 0; i < topo.num_threads_per_core * 3855c98d5d94SLen Brown topo.num_cores_per_pkg * topo.num_packages; i++) 3856c98d5d94SLen Brown (*t)[i].cpu_id = -1; 3857c98d5d94SLen Brown 3858c98d5d94SLen Brown *c = calloc(topo.num_cores_per_pkg * topo.num_packages, 3859678a3bd1SLen Brown sizeof(struct core_data)); 3860c98d5d94SLen Brown if (*c == NULL) 3861c98d5d94SLen Brown goto error; 3862c98d5d94SLen Brown 3863c98d5d94SLen Brown for (i = 0; i < topo.num_cores_per_pkg * topo.num_packages; i++) 3864c98d5d94SLen Brown (*c)[i].core_id = -1; 3865c98d5d94SLen Brown 3866678a3bd1SLen Brown *p = calloc(topo.num_packages, sizeof(struct pkg_data)); 3867c98d5d94SLen Brown if (*p == NULL) 3868c98d5d94SLen Brown goto error; 3869c98d5d94SLen Brown 3870c98d5d94SLen Brown for (i = 0; i < topo.num_packages; i++) 3871c98d5d94SLen Brown (*p)[i].package_id = i; 3872c98d5d94SLen Brown 3873c98d5d94SLen Brown return; 3874c98d5d94SLen Brown error: 3875b2c95d90SJosh Triplett err(1, "calloc counters"); 3876c98d5d94SLen Brown } 3877c98d5d94SLen Brown /* 3878c98d5d94SLen Brown * init_counter() 3879c98d5d94SLen Brown * 3880c98d5d94SLen Brown * set cpu_id, core_num, pkg_num 3881c98d5d94SLen Brown * set FIRST_THREAD_IN_CORE and FIRST_CORE_IN_PACKAGE 3882c98d5d94SLen Brown * 3883c98d5d94SLen Brown * increment topo.num_cores when 1st core in pkg seen 3884c98d5d94SLen Brown */ 3885c98d5d94SLen Brown void init_counter(struct thread_data *thread_base, struct core_data *core_base, 3886c98d5d94SLen Brown struct pkg_data *pkg_base, int thread_num, int core_num, 3887c98d5d94SLen Brown int pkg_num, int cpu_id) 3888c98d5d94SLen Brown { 3889c98d5d94SLen Brown struct thread_data *t; 3890c98d5d94SLen Brown struct core_data *c; 3891c98d5d94SLen Brown struct pkg_data *p; 3892c98d5d94SLen Brown 3893c98d5d94SLen Brown t = GET_THREAD(thread_base, thread_num, core_num, pkg_num); 3894c98d5d94SLen Brown c = GET_CORE(core_base, core_num, pkg_num); 3895c98d5d94SLen Brown p = GET_PKG(pkg_base, pkg_num); 3896c98d5d94SLen Brown 3897c98d5d94SLen Brown t->cpu_id = cpu_id; 3898c98d5d94SLen Brown if (thread_num == 0) { 3899c98d5d94SLen Brown t->flags |= CPU_IS_FIRST_THREAD_IN_CORE; 3900c98d5d94SLen Brown if (cpu_is_first_core_in_package(cpu_id)) 3901c98d5d94SLen Brown t->flags |= CPU_IS_FIRST_CORE_IN_PACKAGE; 3902c98d5d94SLen Brown } 3903c98d5d94SLen Brown 3904c98d5d94SLen Brown c->core_id = core_num; 3905c98d5d94SLen Brown p->package_id = pkg_num; 3906c98d5d94SLen Brown } 3907c98d5d94SLen Brown 3908c98d5d94SLen Brown 3909c98d5d94SLen Brown int initialize_counters(int cpu_id) 3910c98d5d94SLen Brown { 3911c98d5d94SLen Brown int my_thread_id, my_core_id, my_package_id; 3912c98d5d94SLen Brown 3913c98d5d94SLen Brown my_package_id = get_physical_package_id(cpu_id); 3914c98d5d94SLen Brown my_core_id = get_core_id(cpu_id); 3915e275b388SDasaratharaman Chandramouli my_thread_id = get_cpu_position_in_core(cpu_id); 3916e275b388SDasaratharaman Chandramouli if (!my_thread_id) 3917c98d5d94SLen Brown topo.num_cores++; 3918c98d5d94SLen Brown 3919c98d5d94SLen Brown init_counter(EVEN_COUNTERS, my_thread_id, my_core_id, my_package_id, cpu_id); 3920c98d5d94SLen Brown init_counter(ODD_COUNTERS, my_thread_id, my_core_id, my_package_id, cpu_id); 3921c98d5d94SLen Brown return 0; 3922c98d5d94SLen Brown } 3923c98d5d94SLen Brown 3924c98d5d94SLen Brown void allocate_output_buffer() 3925c98d5d94SLen Brown { 39263b4d5c7fSAndy Shevchenko output_buffer = calloc(1, (1 + topo.num_cpus) * 1024); 3927c98d5d94SLen Brown outp = output_buffer; 3928b2c95d90SJosh Triplett if (outp == NULL) 3929b2c95d90SJosh Triplett err(-1, "calloc output buffer"); 3930c98d5d94SLen Brown } 393136229897SLen Brown void allocate_fd_percpu(void) 393236229897SLen Brown { 393301a67adfSMika Westerberg fd_percpu = calloc(topo.max_cpu_num + 1, sizeof(int)); 393436229897SLen Brown if (fd_percpu == NULL) 393536229897SLen Brown err(-1, "calloc fd_percpu"); 393636229897SLen Brown } 3937562a2d37SLen Brown void allocate_irq_buffers(void) 3938562a2d37SLen Brown { 3939562a2d37SLen Brown irq_column_2_cpu = calloc(topo.num_cpus, sizeof(int)); 3940562a2d37SLen Brown if (irq_column_2_cpu == NULL) 3941562a2d37SLen Brown err(-1, "calloc %d", topo.num_cpus); 3942c98d5d94SLen Brown 394301a67adfSMika Westerberg irqs_per_cpu = calloc(topo.max_cpu_num + 1, sizeof(int)); 3944562a2d37SLen Brown if (irqs_per_cpu == NULL) 394501a67adfSMika Westerberg err(-1, "calloc %d", topo.max_cpu_num + 1); 3946562a2d37SLen Brown } 3947c98d5d94SLen Brown void setup_all_buffers(void) 3948c98d5d94SLen Brown { 3949c98d5d94SLen Brown topology_probe(); 3950562a2d37SLen Brown allocate_irq_buffers(); 395136229897SLen Brown allocate_fd_percpu(); 3952c98d5d94SLen Brown allocate_counters(&thread_even, &core_even, &package_even); 3953c98d5d94SLen Brown allocate_counters(&thread_odd, &core_odd, &package_odd); 3954c98d5d94SLen Brown allocate_output_buffer(); 3955c98d5d94SLen Brown for_all_proc_cpus(initialize_counters); 3956c98d5d94SLen Brown } 39573b4d5c7fSAndy Shevchenko 39587ce7d5deSPrarit Bhargava void set_base_cpu(void) 39597ce7d5deSPrarit Bhargava { 39607ce7d5deSPrarit Bhargava base_cpu = sched_getcpu(); 39617ce7d5deSPrarit Bhargava if (base_cpu < 0) 39627ce7d5deSPrarit Bhargava err(-ENODEV, "No valid cpus found"); 39637ce7d5deSPrarit Bhargava 39647ce7d5deSPrarit Bhargava if (debug > 1) 3965b7d8c148SLen Brown fprintf(outf, "base_cpu = %d\n", base_cpu); 39667ce7d5deSPrarit Bhargava } 39677ce7d5deSPrarit Bhargava 3968103a8feaSLen Brown void turbostat_init() 3969103a8feaSLen Brown { 39707ce7d5deSPrarit Bhargava setup_all_buffers(); 39717ce7d5deSPrarit Bhargava set_base_cpu(); 3972103a8feaSLen Brown check_dev_msr(); 397398481e79SLen Brown check_permissions(); 3974fcd17211SLen Brown process_cpuid(); 3975103a8feaSLen Brown 3976103a8feaSLen Brown 3977d8af6f5fSLen Brown if (debug) 39787f5c258eSLen Brown for_all_cpus(print_hwp, ODD_COUNTERS); 39797f5c258eSLen Brown 39807f5c258eSLen Brown if (debug) 3981889facbeSLen Brown for_all_cpus(print_epb, ODD_COUNTERS); 3982889facbeSLen Brown 3983d8af6f5fSLen Brown if (debug) 39843a9a941dSLen Brown for_all_cpus(print_perf_limit, ODD_COUNTERS); 39853a9a941dSLen Brown 3986d8af6f5fSLen Brown if (debug) 3987889facbeSLen Brown for_all_cpus(print_rapl, ODD_COUNTERS); 3988889facbeSLen Brown 3989889facbeSLen Brown for_all_cpus(set_temperature_target, ODD_COUNTERS); 3990889facbeSLen Brown 3991d8af6f5fSLen Brown if (debug) 3992889facbeSLen Brown for_all_cpus(print_thermal, ODD_COUNTERS); 39935a63426eSLen Brown 39945a63426eSLen Brown if (debug && do_irtl_snb) 39955a63426eSLen Brown print_irtl(); 3996103a8feaSLen Brown } 3997103a8feaSLen Brown 3998103a8feaSLen Brown int fork_it(char **argv) 3999103a8feaSLen Brown { 4000103a8feaSLen Brown pid_t child_pid; 4001d91bb17cSLen Brown int status; 4002d15cf7c1SLen Brown 4003d91bb17cSLen Brown status = for_all_cpus(get_counters, EVEN_COUNTERS); 4004d91bb17cSLen Brown if (status) 4005d91bb17cSLen Brown exit(status); 4006d15cf7c1SLen Brown /* clear affinity side-effect of get_counters() */ 4007d15cf7c1SLen Brown sched_setaffinity(0, cpu_present_setsize, cpu_present_set); 4008103a8feaSLen Brown gettimeofday(&tv_even, (struct timezone *)NULL); 4009103a8feaSLen Brown 4010103a8feaSLen Brown child_pid = fork(); 4011103a8feaSLen Brown if (!child_pid) { 4012103a8feaSLen Brown /* child */ 4013103a8feaSLen Brown execvp(argv[0], argv); 4014103a8feaSLen Brown } else { 4015103a8feaSLen Brown 4016103a8feaSLen Brown /* parent */ 4017b2c95d90SJosh Triplett if (child_pid == -1) 4018b2c95d90SJosh Triplett err(1, "fork"); 4019103a8feaSLen Brown 4020103a8feaSLen Brown signal(SIGINT, SIG_IGN); 4021103a8feaSLen Brown signal(SIGQUIT, SIG_IGN); 4022b2c95d90SJosh Triplett if (waitpid(child_pid, &status, 0) == -1) 4023b2c95d90SJosh Triplett err(status, "waitpid"); 4024103a8feaSLen Brown } 4025c98d5d94SLen Brown /* 4026c98d5d94SLen Brown * n.b. fork_it() does not check for errors from for_all_cpus() 4027c98d5d94SLen Brown * because re-starting is problematic when forking 4028c98d5d94SLen Brown */ 4029c98d5d94SLen Brown for_all_cpus(get_counters, ODD_COUNTERS); 4030103a8feaSLen Brown gettimeofday(&tv_odd, (struct timezone *)NULL); 4031103a8feaSLen Brown timersub(&tv_odd, &tv_even, &tv_delta); 4032ba3dec99SLen Brown if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS)) 4033ba3dec99SLen Brown fprintf(outf, "%s: Counter reset detected\n", progname); 4034ba3dec99SLen Brown else { 4035c98d5d94SLen Brown compute_average(EVEN_COUNTERS); 4036c98d5d94SLen Brown format_all_counters(EVEN_COUNTERS); 4037ba3dec99SLen Brown } 4038103a8feaSLen Brown 4039b7d8c148SLen Brown fprintf(outf, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0); 4040b7d8c148SLen Brown 4041b7d8c148SLen Brown flush_output_stderr(); 4042103a8feaSLen Brown 4043d91bb17cSLen Brown return status; 4044103a8feaSLen Brown } 4045103a8feaSLen Brown 40463b4d5c7fSAndy Shevchenko int get_and_dump_counters(void) 40473b4d5c7fSAndy Shevchenko { 40483b4d5c7fSAndy Shevchenko int status; 40493b4d5c7fSAndy Shevchenko 40503b4d5c7fSAndy Shevchenko status = for_all_cpus(get_counters, ODD_COUNTERS); 40513b4d5c7fSAndy Shevchenko if (status) 40523b4d5c7fSAndy Shevchenko return status; 40533b4d5c7fSAndy Shevchenko 40543b4d5c7fSAndy Shevchenko status = for_all_cpus(dump_counters, ODD_COUNTERS); 40553b4d5c7fSAndy Shevchenko if (status) 40563b4d5c7fSAndy Shevchenko return status; 40573b4d5c7fSAndy Shevchenko 4058b7d8c148SLen Brown flush_output_stdout(); 40593b4d5c7fSAndy Shevchenko 40603b4d5c7fSAndy Shevchenko return status; 40613b4d5c7fSAndy Shevchenko } 40623b4d5c7fSAndy Shevchenko 4063d8af6f5fSLen Brown void print_version() { 40646886fee4SLen Brown fprintf(outf, "turbostat version 4.16 24 Dec 2016" 4065d8af6f5fSLen Brown " - Len Brown <lenb@kernel.org>\n"); 4066d8af6f5fSLen Brown } 4067d8af6f5fSLen Brown 4068388e9c81SLen Brown int add_counter(unsigned int msr_num, char *name, unsigned int width, 4069388e9c81SLen Brown enum counter_scope scope, enum counter_type type, 4070388e9c81SLen Brown enum counter_format format) 4071388e9c81SLen Brown { 4072388e9c81SLen Brown struct msr_counter *msrp; 4073388e9c81SLen Brown 4074388e9c81SLen Brown msrp = calloc(1, sizeof(struct msr_counter)); 4075388e9c81SLen Brown if (msrp == NULL) { 4076388e9c81SLen Brown perror("calloc"); 4077388e9c81SLen Brown exit(1); 4078388e9c81SLen Brown } 4079388e9c81SLen Brown 4080388e9c81SLen Brown msrp->msr_num = msr_num; 4081388e9c81SLen Brown strncpy(msrp->name, name, NAME_BYTES); 4082388e9c81SLen Brown msrp->width = width; 4083388e9c81SLen Brown msrp->type = type; 4084388e9c81SLen Brown msrp->format = format; 4085388e9c81SLen Brown 4086388e9c81SLen Brown switch (scope) { 4087388e9c81SLen Brown 4088388e9c81SLen Brown case SCOPE_CPU: 4089388e9c81SLen Brown msrp->next = sys.tp; 4090388e9c81SLen Brown sys.tp = msrp; 4091678a3bd1SLen Brown sys.added_thread_counters++; 4092678a3bd1SLen Brown if (sys.added_thread_counters > MAX_ADDED_COUNTERS) { 4093678a3bd1SLen Brown fprintf(stderr, "exceeded max %d added thread counters\n", 4094678a3bd1SLen Brown MAX_ADDED_COUNTERS); 4095678a3bd1SLen Brown exit(-1); 4096678a3bd1SLen Brown } 4097388e9c81SLen Brown break; 4098388e9c81SLen Brown 4099388e9c81SLen Brown case SCOPE_CORE: 4100388e9c81SLen Brown msrp->next = sys.cp; 4101388e9c81SLen Brown sys.cp = msrp; 4102678a3bd1SLen Brown sys.added_core_counters++; 4103678a3bd1SLen Brown if (sys.added_core_counters > MAX_ADDED_COUNTERS) { 4104678a3bd1SLen Brown fprintf(stderr, "exceeded max %d added core counters\n", 4105678a3bd1SLen Brown MAX_ADDED_COUNTERS); 4106678a3bd1SLen Brown exit(-1); 4107678a3bd1SLen Brown } 4108388e9c81SLen Brown break; 4109388e9c81SLen Brown 4110388e9c81SLen Brown case SCOPE_PACKAGE: 4111388e9c81SLen Brown msrp->next = sys.pp; 4112388e9c81SLen Brown sys.pp = msrp; 4113678a3bd1SLen Brown sys.added_package_counters++; 4114678a3bd1SLen Brown if (sys.added_package_counters > MAX_ADDED_COUNTERS) { 4115678a3bd1SLen Brown fprintf(stderr, "exceeded max %d added package counters\n", 4116678a3bd1SLen Brown MAX_ADDED_COUNTERS); 4117678a3bd1SLen Brown exit(-1); 4118678a3bd1SLen Brown } 4119388e9c81SLen Brown break; 4120388e9c81SLen Brown } 4121388e9c81SLen Brown 4122388e9c81SLen Brown return 0; 4123388e9c81SLen Brown } 4124388e9c81SLen Brown 4125388e9c81SLen Brown void parse_add_command(char *add_command) 4126388e9c81SLen Brown { 4127388e9c81SLen Brown int msr_num = 0; 4128388e9c81SLen Brown char name_buffer[NAME_BYTES]; 4129388e9c81SLen Brown int width = 64; 4130388e9c81SLen Brown int fail = 0; 4131388e9c81SLen Brown enum counter_scope scope = SCOPE_CPU; 4132388e9c81SLen Brown enum counter_type type = COUNTER_CYCLES; 4133388e9c81SLen Brown enum counter_format format = FORMAT_DELTA; 4134388e9c81SLen Brown 4135388e9c81SLen Brown while (add_command) { 4136388e9c81SLen Brown 4137388e9c81SLen Brown if (sscanf(add_command, "msr0x%x", &msr_num) == 1) 4138388e9c81SLen Brown goto next; 4139388e9c81SLen Brown 4140388e9c81SLen Brown if (sscanf(add_command, "msr%d", &msr_num) == 1) 4141388e9c81SLen Brown goto next; 4142388e9c81SLen Brown 4143388e9c81SLen Brown if (sscanf(add_command, "u%d", &width) == 1) { 4144388e9c81SLen Brown if ((width == 32) || (width == 64)) 4145388e9c81SLen Brown goto next; 4146388e9c81SLen Brown width = 64; 4147388e9c81SLen Brown } 4148388e9c81SLen Brown if (!strncmp(add_command, "cpu", strlen("cpu"))) { 4149388e9c81SLen Brown scope = SCOPE_CPU; 4150388e9c81SLen Brown goto next; 4151388e9c81SLen Brown } 4152388e9c81SLen Brown if (!strncmp(add_command, "core", strlen("core"))) { 4153388e9c81SLen Brown scope = SCOPE_CORE; 4154388e9c81SLen Brown goto next; 4155388e9c81SLen Brown } 4156388e9c81SLen Brown if (!strncmp(add_command, "package", strlen("package"))) { 4157388e9c81SLen Brown scope = SCOPE_PACKAGE; 4158388e9c81SLen Brown goto next; 4159388e9c81SLen Brown } 4160388e9c81SLen Brown if (!strncmp(add_command, "cycles", strlen("cycles"))) { 4161388e9c81SLen Brown type = COUNTER_CYCLES; 4162388e9c81SLen Brown goto next; 4163388e9c81SLen Brown } 4164388e9c81SLen Brown if (!strncmp(add_command, "seconds", strlen("seconds"))) { 4165388e9c81SLen Brown type = COUNTER_SECONDS; 4166388e9c81SLen Brown goto next; 4167388e9c81SLen Brown } 4168388e9c81SLen Brown if (!strncmp(add_command, "raw", strlen("raw"))) { 4169388e9c81SLen Brown format = FORMAT_RAW; 4170388e9c81SLen Brown goto next; 4171388e9c81SLen Brown } 4172388e9c81SLen Brown if (!strncmp(add_command, "delta", strlen("delta"))) { 4173388e9c81SLen Brown format = FORMAT_DELTA; 4174388e9c81SLen Brown goto next; 4175388e9c81SLen Brown } 4176388e9c81SLen Brown if (!strncmp(add_command, "percent", strlen("percent"))) { 4177388e9c81SLen Brown format = FORMAT_PERCENT; 4178388e9c81SLen Brown goto next; 4179388e9c81SLen Brown } 4180388e9c81SLen Brown 4181388e9c81SLen Brown if (sscanf(add_command, "%18s,%*s", name_buffer) == 1) { /* 18 < NAME_BYTES */ 4182388e9c81SLen Brown char *eos; 4183388e9c81SLen Brown 4184388e9c81SLen Brown eos = strchr(name_buffer, ','); 4185388e9c81SLen Brown if (eos) 4186388e9c81SLen Brown *eos = '\0'; 4187388e9c81SLen Brown goto next; 4188388e9c81SLen Brown } 4189388e9c81SLen Brown 4190388e9c81SLen Brown next: 4191388e9c81SLen Brown add_command = strchr(add_command, ','); 4192388e9c81SLen Brown if (add_command) 4193388e9c81SLen Brown add_command++; 4194388e9c81SLen Brown 4195388e9c81SLen Brown } 4196388e9c81SLen Brown if (msr_num == 0) { 4197388e9c81SLen Brown fprintf(stderr, "--add: (msrDDD | msr0xXXX) required\n"); 4198388e9c81SLen Brown fail++; 4199388e9c81SLen Brown } 4200388e9c81SLen Brown 4201388e9c81SLen Brown /* generate default column header */ 4202388e9c81SLen Brown if (*name_buffer == '\0') { 4203388e9c81SLen Brown if (format == FORMAT_RAW) { 4204388e9c81SLen Brown if (width == 32) 4205388e9c81SLen Brown sprintf(name_buffer, "msr%d", msr_num); 4206388e9c81SLen Brown else 4207388e9c81SLen Brown sprintf(name_buffer, "MSR%d", msr_num); 4208388e9c81SLen Brown } else if (format == FORMAT_DELTA) { 4209388e9c81SLen Brown if (width == 32) 4210388e9c81SLen Brown sprintf(name_buffer, "cnt%d", msr_num); 4211388e9c81SLen Brown else 4212388e9c81SLen Brown sprintf(name_buffer, "CNT%d", msr_num); 4213388e9c81SLen Brown } else if (format == FORMAT_PERCENT) { 4214388e9c81SLen Brown if (width == 32) 4215388e9c81SLen Brown sprintf(name_buffer, "msr%d%%", msr_num); 4216388e9c81SLen Brown else 4217388e9c81SLen Brown sprintf(name_buffer, "MSR%d%%", msr_num); 4218388e9c81SLen Brown } 4219388e9c81SLen Brown } 4220388e9c81SLen Brown 4221388e9c81SLen Brown if (add_counter(msr_num, name_buffer, width, scope, type, format)) 4222388e9c81SLen Brown fail++; 4223388e9c81SLen Brown 4224388e9c81SLen Brown if (fail) { 4225388e9c81SLen Brown help(); 4226388e9c81SLen Brown exit(1); 4227388e9c81SLen Brown } 4228388e9c81SLen Brown } 4229*812db3f7SLen Brown /* 4230*812db3f7SLen Brown * HIDE_LIST - hide this list of counters, show the rest [default] 4231*812db3f7SLen Brown * SHOW_LIST - show this list of counters, hide the rest 4232*812db3f7SLen Brown */ 4233*812db3f7SLen Brown enum show_hide_mode { SHOW_LIST, HIDE_LIST } global_show_hide_mode = HIDE_LIST; 4234*812db3f7SLen Brown 4235*812db3f7SLen Brown int shown; 4236*812db3f7SLen Brown /* 4237*812db3f7SLen Brown * parse_show_hide() - process cmdline to set default counter action 4238*812db3f7SLen Brown */ 4239*812db3f7SLen Brown void parse_show_hide(char *optarg, enum show_hide_mode new_mode) 4240*812db3f7SLen Brown { 4241*812db3f7SLen Brown /* 4242*812db3f7SLen Brown * --show: show only those specified 4243*812db3f7SLen Brown * The 1st invocation will clear and replace the enabled mask 4244*812db3f7SLen Brown * subsequent invocations can add to it. 4245*812db3f7SLen Brown */ 4246*812db3f7SLen Brown if (new_mode == SHOW_LIST) { 4247*812db3f7SLen Brown if (shown == 0) 4248*812db3f7SLen Brown bic_enabled = bic_lookup(optarg); 4249*812db3f7SLen Brown else 4250*812db3f7SLen Brown bic_enabled |= bic_lookup(optarg); 4251*812db3f7SLen Brown shown = 1; 4252*812db3f7SLen Brown 4253*812db3f7SLen Brown return; 4254*812db3f7SLen Brown } 4255*812db3f7SLen Brown 4256*812db3f7SLen Brown /* 4257*812db3f7SLen Brown * --hide: do not show those specified 4258*812db3f7SLen Brown * multiple invocations simply clear more bits in enabled mask 4259*812db3f7SLen Brown */ 4260*812db3f7SLen Brown bic_enabled &= ~bic_lookup(optarg); 4261*812db3f7SLen Brown } 4262*812db3f7SLen Brown 4263103a8feaSLen Brown void cmdline(int argc, char **argv) 4264103a8feaSLen Brown { 4265103a8feaSLen Brown int opt; 4266d8af6f5fSLen Brown int option_index = 0; 4267d8af6f5fSLen Brown static struct option long_options[] = { 4268388e9c81SLen Brown {"add", required_argument, 0, 'a'}, 4269d8af6f5fSLen Brown {"Dump", no_argument, 0, 'D'}, 4270d8af6f5fSLen Brown {"debug", no_argument, 0, 'd'}, 4271d8af6f5fSLen Brown {"interval", required_argument, 0, 'i'}, 4272d8af6f5fSLen Brown {"help", no_argument, 0, 'h'}, 4273*812db3f7SLen Brown {"hide", required_argument, 0, 'H'}, // meh, -h taken by --help 4274d8af6f5fSLen Brown {"Joules", no_argument, 0, 'J'}, 4275b7d8c148SLen Brown {"out", required_argument, 0, 'o'}, 4276d8af6f5fSLen Brown {"Package", no_argument, 0, 'p'}, 4277d8af6f5fSLen Brown {"processor", no_argument, 0, 'p'}, 4278*812db3f7SLen Brown {"show", required_argument, 0, 's'}, 4279d8af6f5fSLen Brown {"Summary", no_argument, 0, 'S'}, 4280d8af6f5fSLen Brown {"TCC", required_argument, 0, 'T'}, 4281d8af6f5fSLen Brown {"version", no_argument, 0, 'v' }, 4282d8af6f5fSLen Brown {0, 0, 0, 0 } 4283d8af6f5fSLen Brown }; 4284103a8feaSLen Brown 4285103a8feaSLen Brown progname = argv[0]; 4286103a8feaSLen Brown 4287b7d8c148SLen Brown while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:JM:m:o:PpST:v", 4288d8af6f5fSLen Brown long_options, &option_index)) != -1) { 4289103a8feaSLen Brown switch (opt) { 4290388e9c81SLen Brown case 'a': 4291388e9c81SLen Brown parse_add_command(optarg); 4292388e9c81SLen Brown break; 4293d8af6f5fSLen Brown case 'D': 4294d8af6f5fSLen Brown dump_only++; 42958e180f3cSLen Brown break; 4296d8af6f5fSLen Brown case 'd': 4297d8af6f5fSLen Brown debug++; 42982f32edf1SLen Brown break; 4299*812db3f7SLen Brown case 'H': 4300*812db3f7SLen Brown parse_show_hide(optarg, HIDE_LIST); 4301*812db3f7SLen Brown break; 4302d8af6f5fSLen Brown case 'h': 4303d8af6f5fSLen Brown default: 4304d8af6f5fSLen Brown help(); 4305d8af6f5fSLen Brown exit(1); 4306d8af6f5fSLen Brown case 'i': 43072a0609c0SLen Brown { 43082a0609c0SLen Brown double interval = strtod(optarg, NULL); 43092a0609c0SLen Brown 43102a0609c0SLen Brown if (interval < 0.001) { 4311b7d8c148SLen Brown fprintf(outf, "interval %f seconds is too small\n", 43122a0609c0SLen Brown interval); 43132a0609c0SLen Brown exit(2); 43142a0609c0SLen Brown } 43152a0609c0SLen Brown 43162a0609c0SLen Brown interval_ts.tv_sec = interval; 43172a0609c0SLen Brown interval_ts.tv_nsec = (interval - interval_ts.tv_sec) * 1000000000; 43182a0609c0SLen Brown } 4319889facbeSLen Brown break; 43205c56be9aSDirk Brandewie case 'J': 43215c56be9aSDirk Brandewie rapl_joules++; 43225c56be9aSDirk Brandewie break; 4323b7d8c148SLen Brown case 'o': 4324b7d8c148SLen Brown outf = fopen_or_die(optarg, "w"); 4325b7d8c148SLen Brown break; 4326d8af6f5fSLen Brown case 'P': 4327d8af6f5fSLen Brown show_pkg_only++; 4328d8af6f5fSLen Brown break; 4329d8af6f5fSLen Brown case 'p': 4330d8af6f5fSLen Brown show_core_only++; 4331d8af6f5fSLen Brown break; 4332*812db3f7SLen Brown case 's': 4333*812db3f7SLen Brown parse_show_hide(optarg, SHOW_LIST); 4334*812db3f7SLen Brown break; 4335d8af6f5fSLen Brown case 'S': 4336d8af6f5fSLen Brown summary_only++; 4337d8af6f5fSLen Brown break; 4338d8af6f5fSLen Brown case 'T': 4339d8af6f5fSLen Brown tcc_activation_temp_override = atoi(optarg); 4340d8af6f5fSLen Brown break; 4341d8af6f5fSLen Brown case 'v': 4342d8af6f5fSLen Brown print_version(); 4343d8af6f5fSLen Brown exit(0); 4344d8af6f5fSLen Brown break; 4345103a8feaSLen Brown } 4346103a8feaSLen Brown } 4347103a8feaSLen Brown } 4348103a8feaSLen Brown 4349103a8feaSLen Brown int main(int argc, char **argv) 4350103a8feaSLen Brown { 4351b7d8c148SLen Brown outf = stderr; 4352b7d8c148SLen Brown 4353103a8feaSLen Brown cmdline(argc, argv); 4354103a8feaSLen Brown 4355d8af6f5fSLen Brown if (debug) 4356d8af6f5fSLen Brown print_version(); 4357103a8feaSLen Brown 4358103a8feaSLen Brown turbostat_init(); 4359103a8feaSLen Brown 43603b4d5c7fSAndy Shevchenko /* dump counters and exit */ 43613b4d5c7fSAndy Shevchenko if (dump_only) 43623b4d5c7fSAndy Shevchenko return get_and_dump_counters(); 43633b4d5c7fSAndy Shevchenko 4364103a8feaSLen Brown /* 4365103a8feaSLen Brown * if any params left, it must be a command to fork 4366103a8feaSLen Brown */ 4367103a8feaSLen Brown if (argc - optind) 4368103a8feaSLen Brown return fork_it(argv + optind); 4369103a8feaSLen Brown else 4370103a8feaSLen Brown turbostat_loop(); 4371103a8feaSLen Brown 4372103a8feaSLen Brown return 0; 4373103a8feaSLen Brown } 4374