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_nhm_cstates; 56103a8feaSLen Brown unsigned int do_snb_cstates; 57fb5d4327SDasaratharaman Chandramouli unsigned int do_knl_cstates; 58ee7e38e3SLen Brown unsigned int do_pc2; 59ee7e38e3SLen Brown unsigned int do_pc3; 60ee7e38e3SLen Brown unsigned int do_pc6; 61ee7e38e3SLen Brown unsigned int do_pc7; 62ca58710fSKristen Carlson Accardi unsigned int do_c8_c9_c10; 630b2bb692SLen Brown unsigned int do_skl_residency; 64144b44b1SLen Brown unsigned int do_slm_cstates; 65144b44b1SLen Brown unsigned int use_c1_residency_msr; 66103a8feaSLen Brown unsigned int has_aperf; 67889facbeSLen Brown unsigned int has_epb; 685a63426eSLen Brown unsigned int do_irtl_snb; 695a63426eSLen Brown unsigned int do_irtl_hsw; 70fc04cc67SLen Brown unsigned int units = 1000000; /* MHz etc */ 71103a8feaSLen Brown unsigned int genuine_intel; 72103a8feaSLen Brown unsigned int has_invariant_tsc; 73d7899447SLen Brown unsigned int do_nhm_platform_info; 74b2b34dfeSHubert Chrzaniuk unsigned int aperf_mperf_multiplier = 1; 75562a2d37SLen Brown int do_irq = 1; 761ed51011SLen Brown int do_smi; 77103a8feaSLen Brown double bclk; 78a2b7b749SLen Brown double base_hz; 7921ed5574SLen Brown unsigned int has_base_hz; 80a2b7b749SLen Brown double tsc_tweak = 1.0; 81103a8feaSLen Brown unsigned int show_pkg; 82103a8feaSLen Brown unsigned int show_core; 83103a8feaSLen Brown unsigned int show_cpu; 84c98d5d94SLen Brown unsigned int show_pkg_only; 85c98d5d94SLen Brown unsigned int show_core_only; 86c98d5d94SLen Brown char *output_buffer, *outp; 87889facbeSLen Brown unsigned int do_rapl; 88889facbeSLen Brown unsigned int do_dts; 89889facbeSLen Brown unsigned int do_ptm; 90fdf676e5SLen Brown unsigned int do_gfx_rc6_ms; 91fdf676e5SLen Brown unsigned long long gfx_cur_rc6_ms; 9227d47356SLen Brown unsigned int do_gfx_mhz; 9327d47356SLen Brown unsigned int gfx_cur_mhz; 94889facbeSLen Brown unsigned int tcc_activation_temp; 95889facbeSLen Brown unsigned int tcc_activation_temp_override; 9640ee8e3bSAndrey Semin double rapl_power_units, rapl_time_units; 9740ee8e3bSAndrey Semin double rapl_dram_energy_units, rapl_energy_units; 98889facbeSLen Brown double rapl_joule_counter_range; 993a9a941dSLen Brown unsigned int do_core_perf_limit_reasons; 1003a9a941dSLen Brown unsigned int do_gfx_perf_limit_reasons; 1013a9a941dSLen Brown unsigned int do_ring_perf_limit_reasons; 1028a5bdf41SLen Brown unsigned int crystal_hz; 1038a5bdf41SLen Brown unsigned long long tsc_hz; 1047ce7d5deSPrarit Bhargava int base_cpu; 10521ed5574SLen Brown double discover_bclk(unsigned int family, unsigned int model); 1067f5c258eSLen Brown unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */ 1077f5c258eSLen Brown /* IA32_HWP_REQUEST, IA32_HWP_STATUS */ 1087f5c258eSLen Brown unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */ 1097f5c258eSLen Brown unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */ 1107f5c258eSLen Brown unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */ 1117f5c258eSLen Brown unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */ 112889facbeSLen Brown 113889facbeSLen Brown #define RAPL_PKG (1 << 0) 114e6f9bb3cSLen Brown /* 0x610 MSR_PKG_POWER_LIMIT */ 115e6f9bb3cSLen Brown /* 0x611 MSR_PKG_ENERGY_STATUS */ 116e6f9bb3cSLen Brown #define RAPL_PKG_PERF_STATUS (1 << 1) 117e6f9bb3cSLen Brown /* 0x613 MSR_PKG_PERF_STATUS */ 118e6f9bb3cSLen Brown #define RAPL_PKG_POWER_INFO (1 << 2) 119e6f9bb3cSLen Brown /* 0x614 MSR_PKG_POWER_INFO */ 120e6f9bb3cSLen Brown 121889facbeSLen Brown #define RAPL_DRAM (1 << 3) 122e6f9bb3cSLen Brown /* 0x618 MSR_DRAM_POWER_LIMIT */ 123e6f9bb3cSLen Brown /* 0x619 MSR_DRAM_ENERGY_STATUS */ 124e6f9bb3cSLen Brown #define RAPL_DRAM_PERF_STATUS (1 << 4) 125e6f9bb3cSLen Brown /* 0x61b MSR_DRAM_PERF_STATUS */ 1260b2bb692SLen Brown #define RAPL_DRAM_POWER_INFO (1 << 5) 1270b2bb692SLen Brown /* 0x61c MSR_DRAM_POWER_INFO */ 128e6f9bb3cSLen Brown 1299148494cSJacob Pan #define RAPL_CORES_POWER_LIMIT (1 << 6) 130e6f9bb3cSLen Brown /* 0x638 MSR_PP0_POWER_LIMIT */ 1310b2bb692SLen Brown #define RAPL_CORE_POLICY (1 << 7) 132e6f9bb3cSLen Brown /* 0x63a MSR_PP0_POLICY */ 133e6f9bb3cSLen Brown 1340b2bb692SLen Brown #define RAPL_GFX (1 << 8) 135e6f9bb3cSLen Brown /* 0x640 MSR_PP1_POWER_LIMIT */ 136e6f9bb3cSLen Brown /* 0x641 MSR_PP1_ENERGY_STATUS */ 137e6f9bb3cSLen Brown /* 0x642 MSR_PP1_POLICY */ 1389148494cSJacob Pan 1399148494cSJacob Pan #define RAPL_CORES_ENERGY_STATUS (1 << 9) 1409148494cSJacob Pan /* 0x639 MSR_PP0_ENERGY_STATUS */ 1419148494cSJacob Pan #define RAPL_CORES (RAPL_CORES_ENERGY_STATUS | RAPL_CORES_POWER_LIMIT) 142889facbeSLen Brown #define TJMAX_DEFAULT 100 143889facbeSLen Brown 144889facbeSLen Brown #define MAX(a, b) ((a) > (b) ? (a) : (b)) 145103a8feaSLen Brown 146388e9c81SLen Brown /* 147388e9c81SLen Brown * buffer size used by sscanf() for added column names 148388e9c81SLen Brown * Usually truncated to 7 characters, but also handles 18 columns for raw 64-bit counters 149388e9c81SLen Brown */ 150388e9c81SLen Brown #define NAME_BYTES 20 151388e9c81SLen Brown 152103a8feaSLen Brown int backwards_count; 153103a8feaSLen Brown char *progname; 154103a8feaSLen Brown 155c98d5d94SLen Brown cpu_set_t *cpu_present_set, *cpu_affinity_set; 156c98d5d94SLen Brown size_t cpu_present_setsize, cpu_affinity_setsize; 157c98d5d94SLen Brown 158c98d5d94SLen Brown struct thread_data { 159c98d5d94SLen Brown unsigned long long tsc; 160c98d5d94SLen Brown unsigned long long aperf; 161c98d5d94SLen Brown unsigned long long mperf; 162144b44b1SLen Brown unsigned long long c1; 163562a2d37SLen Brown unsigned int irq_count; 1641ed51011SLen Brown unsigned int smi_count; 165c98d5d94SLen Brown unsigned int cpu_id; 166c98d5d94SLen Brown unsigned int flags; 167c98d5d94SLen Brown #define CPU_IS_FIRST_THREAD_IN_CORE 0x2 168c98d5d94SLen Brown #define CPU_IS_FIRST_CORE_IN_PACKAGE 0x4 169388e9c81SLen Brown unsigned long long counter[1]; 170c98d5d94SLen Brown } *thread_even, *thread_odd; 171c98d5d94SLen Brown 172c98d5d94SLen Brown struct core_data { 173c98d5d94SLen Brown unsigned long long c3; 174c98d5d94SLen Brown unsigned long long c6; 175c98d5d94SLen Brown unsigned long long c7; 176889facbeSLen Brown unsigned int core_temp_c; 177c98d5d94SLen Brown unsigned int core_id; 178388e9c81SLen Brown unsigned long long counter[1]; 179c98d5d94SLen Brown } *core_even, *core_odd; 180c98d5d94SLen Brown 181c98d5d94SLen Brown struct pkg_data { 182c98d5d94SLen Brown unsigned long long pc2; 183c98d5d94SLen Brown unsigned long long pc3; 184c98d5d94SLen Brown unsigned long long pc6; 185c98d5d94SLen Brown unsigned long long pc7; 186ca58710fSKristen Carlson Accardi unsigned long long pc8; 187ca58710fSKristen Carlson Accardi unsigned long long pc9; 188ca58710fSKristen Carlson Accardi unsigned long long pc10; 1890b2bb692SLen Brown unsigned long long pkg_wtd_core_c0; 1900b2bb692SLen Brown unsigned long long pkg_any_core_c0; 1910b2bb692SLen Brown unsigned long long pkg_any_gfxe_c0; 1920b2bb692SLen Brown unsigned long long pkg_both_core_gfxe_c0; 1939185e988SLen Brown long long gfx_rc6_ms; 19427d47356SLen Brown unsigned int gfx_mhz; 195c98d5d94SLen Brown unsigned int package_id; 196889facbeSLen Brown unsigned int energy_pkg; /* MSR_PKG_ENERGY_STATUS */ 197889facbeSLen Brown unsigned int energy_dram; /* MSR_DRAM_ENERGY_STATUS */ 198889facbeSLen Brown unsigned int energy_cores; /* MSR_PP0_ENERGY_STATUS */ 199889facbeSLen Brown unsigned int energy_gfx; /* MSR_PP1_ENERGY_STATUS */ 200889facbeSLen Brown unsigned int rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */ 201889facbeSLen Brown unsigned int rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */ 202889facbeSLen Brown unsigned int pkg_temp_c; 203388e9c81SLen Brown unsigned long long counter[1]; 204c98d5d94SLen Brown } *package_even, *package_odd; 205c98d5d94SLen Brown 206c98d5d94SLen Brown #define ODD_COUNTERS thread_odd, core_odd, package_odd 207c98d5d94SLen Brown #define EVEN_COUNTERS thread_even, core_even, package_even 208c98d5d94SLen Brown 209c98d5d94SLen Brown #define GET_THREAD(thread_base, thread_no, core_no, pkg_no) \ 210c98d5d94SLen Brown (thread_base + (pkg_no) * topo.num_cores_per_pkg * \ 211c98d5d94SLen Brown topo.num_threads_per_core + \ 212c98d5d94SLen Brown (core_no) * topo.num_threads_per_core + (thread_no)) 213c98d5d94SLen Brown #define GET_CORE(core_base, core_no, pkg_no) \ 214c98d5d94SLen Brown (core_base + (pkg_no) * topo.num_cores_per_pkg + (core_no)) 215c98d5d94SLen Brown #define GET_PKG(pkg_base, pkg_no) (pkg_base + pkg_no) 216c98d5d94SLen Brown 217388e9c81SLen Brown enum counter_scope {SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE}; 218388e9c81SLen Brown enum counter_type {COUNTER_CYCLES, COUNTER_SECONDS}; 219388e9c81SLen Brown enum counter_format {FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT}; 220388e9c81SLen Brown 221388e9c81SLen Brown struct msr_counter { 222388e9c81SLen Brown unsigned int msr_num; 223388e9c81SLen Brown char name[NAME_BYTES]; 224388e9c81SLen Brown unsigned int width; 225388e9c81SLen Brown enum counter_type type; 226388e9c81SLen Brown enum counter_format format; 227388e9c81SLen Brown struct msr_counter *next; 228388e9c81SLen Brown }; 229388e9c81SLen Brown 230388e9c81SLen Brown struct sys_counters { 231388e9c81SLen Brown unsigned int thread_counter_bytes; 232388e9c81SLen Brown unsigned int core_counter_bytes; 233388e9c81SLen Brown unsigned int package_counter_bytes; 234388e9c81SLen Brown struct msr_counter *tp; 235388e9c81SLen Brown struct msr_counter *cp; 236388e9c81SLen Brown struct msr_counter *pp; 237388e9c81SLen Brown } sys; 238388e9c81SLen Brown 239c98d5d94SLen Brown struct system_summary { 240c98d5d94SLen Brown struct thread_data threads; 241c98d5d94SLen Brown struct core_data cores; 242c98d5d94SLen Brown struct pkg_data packages; 243388e9c81SLen Brown } average; 244c98d5d94SLen Brown 245c98d5d94SLen Brown 246c98d5d94SLen Brown struct topo_params { 247c98d5d94SLen Brown int num_packages; 248103a8feaSLen Brown int num_cpus; 249c98d5d94SLen Brown int num_cores; 250c98d5d94SLen Brown int max_cpu_num; 251c98d5d94SLen Brown int num_cores_per_pkg; 252c98d5d94SLen Brown int num_threads_per_core; 253c98d5d94SLen Brown } topo; 254103a8feaSLen Brown 255c98d5d94SLen Brown struct timeval tv_even, tv_odd, tv_delta; 256103a8feaSLen Brown 257562a2d37SLen Brown int *irq_column_2_cpu; /* /proc/interrupts column numbers */ 258562a2d37SLen Brown int *irqs_per_cpu; /* indexed by cpu_num */ 259562a2d37SLen Brown 260c98d5d94SLen Brown void setup_all_buffers(void); 261103a8feaSLen Brown 262c98d5d94SLen Brown int cpu_is_not_present(int cpu) 263d15cf7c1SLen Brown { 264c98d5d94SLen Brown return !CPU_ISSET_S(cpu, cpu_present_setsize, cpu_present_set); 265c98d5d94SLen Brown } 266c98d5d94SLen Brown /* 267c98d5d94SLen Brown * run func(thread, core, package) in topology order 268c98d5d94SLen Brown * skip non-present cpus 269c98d5d94SLen Brown */ 270c98d5d94SLen Brown 271c98d5d94SLen Brown int for_all_cpus(int (func)(struct thread_data *, struct core_data *, struct pkg_data *), 272c98d5d94SLen Brown struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base) 273c98d5d94SLen Brown { 274c98d5d94SLen Brown int retval, pkg_no, core_no, thread_no; 275c98d5d94SLen Brown 276c98d5d94SLen Brown for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) { 277c98d5d94SLen Brown for (core_no = 0; core_no < topo.num_cores_per_pkg; ++core_no) { 278c98d5d94SLen Brown for (thread_no = 0; thread_no < 279c98d5d94SLen Brown topo.num_threads_per_core; ++thread_no) { 280c98d5d94SLen Brown struct thread_data *t; 281c98d5d94SLen Brown struct core_data *c; 282c98d5d94SLen Brown struct pkg_data *p; 283c98d5d94SLen Brown 284c98d5d94SLen Brown t = GET_THREAD(thread_base, thread_no, core_no, pkg_no); 285c98d5d94SLen Brown 286c98d5d94SLen Brown if (cpu_is_not_present(t->cpu_id)) 287c98d5d94SLen Brown continue; 288c98d5d94SLen Brown 289c98d5d94SLen Brown c = GET_CORE(core_base, core_no, pkg_no); 290c98d5d94SLen Brown p = GET_PKG(pkg_base, pkg_no); 291c98d5d94SLen Brown 292c98d5d94SLen Brown retval = func(t, c, p); 293c98d5d94SLen Brown if (retval) 294c98d5d94SLen Brown return retval; 295c98d5d94SLen Brown } 296c98d5d94SLen Brown } 297c98d5d94SLen Brown } 298d15cf7c1SLen Brown return 0; 299d15cf7c1SLen Brown } 300d15cf7c1SLen Brown 30188c3281fSLen Brown int cpu_migrate(int cpu) 30288c3281fSLen Brown { 303c98d5d94SLen Brown CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set); 304c98d5d94SLen Brown CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set); 305c98d5d94SLen Brown if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1) 30688c3281fSLen Brown return -1; 30788c3281fSLen Brown else 30888c3281fSLen Brown return 0; 30988c3281fSLen Brown } 31036229897SLen Brown int get_msr_fd(int cpu) 311103a8feaSLen Brown { 312103a8feaSLen Brown char pathname[32]; 313103a8feaSLen Brown int fd; 314103a8feaSLen Brown 31536229897SLen Brown fd = fd_percpu[cpu]; 31636229897SLen Brown 31736229897SLen Brown if (fd) 31836229897SLen Brown return fd; 31936229897SLen Brown 320103a8feaSLen Brown sprintf(pathname, "/dev/cpu/%d/msr", cpu); 321103a8feaSLen Brown fd = open(pathname, O_RDONLY); 32215aaa346SLen Brown if (fd < 0) 32398481e79SLen Brown err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname); 324103a8feaSLen Brown 32536229897SLen Brown fd_percpu[cpu] = fd; 32636229897SLen Brown 32736229897SLen Brown return fd; 32836229897SLen Brown } 32936229897SLen Brown 33036229897SLen Brown int get_msr(int cpu, off_t offset, unsigned long long *msr) 33136229897SLen Brown { 33236229897SLen Brown ssize_t retval; 33336229897SLen Brown 33436229897SLen Brown retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset); 33515aaa346SLen Brown 33698481e79SLen Brown if (retval != sizeof *msr) 33736229897SLen Brown err(-1, "msr %d offset 0x%llx read failed", cpu, (unsigned long long)offset); 33815aaa346SLen Brown 33915aaa346SLen Brown return 0; 340103a8feaSLen Brown } 341103a8feaSLen Brown 342fc04cc67SLen Brown /* 343fc04cc67SLen Brown * Example Format w/ field column widths: 344fc04cc67SLen Brown * 345388e9c81SLen Brown * Package Core CPU Avg_MHz Bzy_MHz TSC_MHz IRQ SMI Busy% CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 ThreadC CoreTmp CoreCnt PkgTmp GFXMHz Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt PkgCnt 346562a2d37SLen Brown * 12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678 347fc04cc67SLen Brown */ 348fc04cc67SLen Brown 349a829eb4dSLen Brown void print_header(void) 350103a8feaSLen Brown { 351388e9c81SLen Brown struct msr_counter *mp; 352388e9c81SLen Brown 353103a8feaSLen Brown if (show_pkg) 3543d109de2SLen Brown outp += sprintf(outp, "\tPackage"); 355103a8feaSLen Brown if (show_core) 3563d109de2SLen Brown outp += sprintf(outp, "\tCore"); 357103a8feaSLen Brown if (show_cpu) 3583d109de2SLen Brown outp += sprintf(outp, "\tCPU"); 359103a8feaSLen Brown if (has_aperf) 3603d109de2SLen Brown outp += sprintf(outp, "\tAvg_MHz"); 361d7899447SLen Brown if (has_aperf) 3623d109de2SLen Brown outp += sprintf(outp, "\tBusy%%"); 363fc04cc67SLen Brown if (has_aperf) 3643d109de2SLen Brown outp += sprintf(outp, "\tBzy_MHz"); 3653d109de2SLen Brown outp += sprintf(outp, "\tTSC_MHz"); 3661cc21f7bSLen Brown 3671cc21f7bSLen Brown if (!debug) 3681cc21f7bSLen Brown goto done; 3691cc21f7bSLen Brown 370562a2d37SLen Brown if (do_irq) 3713d109de2SLen Brown outp += sprintf(outp, "\tIRQ"); 3721cc21f7bSLen Brown if (do_smi) 3733d109de2SLen Brown outp += sprintf(outp, "\tSMI"); 3741cc21f7bSLen Brown 375103a8feaSLen Brown if (do_nhm_cstates) 3763d109de2SLen Brown outp += sprintf(outp, "\tCPU%%c1"); 377fb5d4327SDasaratharaman Chandramouli if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates) 3783d109de2SLen Brown outp += sprintf(outp, "\tCPU%%c3"); 379103a8feaSLen Brown if (do_nhm_cstates) 3803d109de2SLen Brown outp += sprintf(outp, "\tCPU%%c6"); 381103a8feaSLen Brown if (do_snb_cstates) 3823d109de2SLen Brown outp += sprintf(outp, "\tCPU%%c7"); 383889facbeSLen Brown 384388e9c81SLen Brown for (mp = sys.tp; mp; mp = mp->next) { 385388e9c81SLen Brown if (mp->format == FORMAT_RAW) { 386388e9c81SLen Brown if (mp->width == 64) 387388e9c81SLen Brown outp += sprintf(outp, "\t%18.18s", mp->name); 388388e9c81SLen Brown else 389388e9c81SLen Brown outp += sprintf(outp, "\t%10.10s", mp->name); 390388e9c81SLen Brown } else { 391388e9c81SLen Brown outp += sprintf(outp, "\t%-7.7s", mp->name); 392388e9c81SLen Brown } 393388e9c81SLen Brown } 394388e9c81SLen Brown 395889facbeSLen Brown if (do_dts) 3963d109de2SLen Brown outp += sprintf(outp, "\tCoreTmp"); 397388e9c81SLen Brown 398388e9c81SLen Brown for (mp = sys.cp; mp; mp = mp->next) { 399388e9c81SLen Brown if (mp->format == FORMAT_RAW) { 400388e9c81SLen Brown if (mp->width == 64) 401388e9c81SLen Brown outp += sprintf(outp, "\t%18.18s", mp->name); 402388e9c81SLen Brown else 403388e9c81SLen Brown outp += sprintf(outp, "\t%10.10s", mp->name); 404388e9c81SLen Brown } else { 405388e9c81SLen Brown outp += sprintf(outp, "\t%-7.7s", mp->name); 406388e9c81SLen Brown } 407388e9c81SLen Brown } 408388e9c81SLen Brown 409889facbeSLen Brown if (do_ptm) 4103d109de2SLen Brown outp += sprintf(outp, "\tPkgTmp"); 411889facbeSLen Brown 412fdf676e5SLen Brown if (do_gfx_rc6_ms) 4133d109de2SLen Brown outp += sprintf(outp, "\tGFX%%rc6"); 414fdf676e5SLen Brown 41527d47356SLen Brown if (do_gfx_mhz) 4163d109de2SLen Brown outp += sprintf(outp, "\tGFXMHz"); 41727d47356SLen Brown 4180b2bb692SLen Brown if (do_skl_residency) { 4193d109de2SLen Brown outp += sprintf(outp, "\tTotl%%C0"); 4203d109de2SLen Brown outp += sprintf(outp, "\tAny%%C0"); 4213d109de2SLen Brown outp += sprintf(outp, "\tGFX%%C0"); 4223d109de2SLen Brown outp += sprintf(outp, "\tCPUGFX%%"); 4230b2bb692SLen Brown } 4240b2bb692SLen Brown 425ee7e38e3SLen Brown if (do_pc2) 4263d109de2SLen Brown outp += sprintf(outp, "\tPkg%%pc2"); 427ee7e38e3SLen Brown if (do_pc3) 4283d109de2SLen Brown outp += sprintf(outp, "\tPkg%%pc3"); 429ee7e38e3SLen Brown if (do_pc6) 4303d109de2SLen Brown outp += sprintf(outp, "\tPkg%%pc6"); 431ee7e38e3SLen Brown if (do_pc7) 4323d109de2SLen Brown outp += sprintf(outp, "\tPkg%%pc7"); 433ca58710fSKristen Carlson Accardi if (do_c8_c9_c10) { 4343d109de2SLen Brown outp += sprintf(outp, "\tPkg%%pc8"); 4353d109de2SLen Brown outp += sprintf(outp, "\tPkg%%pc9"); 4363d109de2SLen Brown outp += sprintf(outp, "\tPk%%pc10"); 437ca58710fSKristen Carlson Accardi } 438103a8feaSLen Brown 4395c56be9aSDirk Brandewie if (do_rapl && !rapl_joules) { 440889facbeSLen Brown if (do_rapl & RAPL_PKG) 4413d109de2SLen Brown outp += sprintf(outp, "\tPkgWatt"); 4429148494cSJacob Pan if (do_rapl & RAPL_CORES_ENERGY_STATUS) 4433d109de2SLen Brown outp += sprintf(outp, "\tCorWatt"); 444889facbeSLen Brown if (do_rapl & RAPL_GFX) 4453d109de2SLen Brown outp += sprintf(outp, "\tGFXWatt"); 446889facbeSLen Brown if (do_rapl & RAPL_DRAM) 4473d109de2SLen Brown outp += sprintf(outp, "\tRAMWatt"); 448889facbeSLen Brown if (do_rapl & RAPL_PKG_PERF_STATUS) 4493d109de2SLen Brown outp += sprintf(outp, "\tPKG_%%"); 450889facbeSLen Brown if (do_rapl & RAPL_DRAM_PERF_STATUS) 4513d109de2SLen Brown outp += sprintf(outp, "\tRAM_%%"); 452d7899447SLen Brown } else if (do_rapl && rapl_joules) { 4535c56be9aSDirk Brandewie if (do_rapl & RAPL_PKG) 4543d109de2SLen Brown outp += sprintf(outp, "\tPkg_J"); 4559148494cSJacob Pan if (do_rapl & RAPL_CORES_ENERGY_STATUS) 4563d109de2SLen Brown outp += sprintf(outp, "\tCor_J"); 4575c56be9aSDirk Brandewie if (do_rapl & RAPL_GFX) 4583d109de2SLen Brown outp += sprintf(outp, "\tGFX_J"); 4595c56be9aSDirk Brandewie if (do_rapl & RAPL_DRAM) 4603d109de2SLen Brown outp += sprintf(outp, "\tRAM_J"); 4615c56be9aSDirk Brandewie if (do_rapl & RAPL_PKG_PERF_STATUS) 4623d109de2SLen Brown outp += sprintf(outp, "\tPKG_%%"); 4635c56be9aSDirk Brandewie if (do_rapl & RAPL_DRAM_PERF_STATUS) 4643d109de2SLen Brown outp += sprintf(outp, "\tRAM_%%"); 4655c56be9aSDirk Brandewie } 466388e9c81SLen Brown for (mp = sys.pp; mp; mp = mp->next) { 467388e9c81SLen Brown if (mp->format == FORMAT_RAW) { 468388e9c81SLen Brown if (mp->width == 64) 469388e9c81SLen Brown outp += sprintf(outp, "\t%18.18s", mp->name); 470388e9c81SLen Brown else 471388e9c81SLen Brown outp += sprintf(outp, "\t%10.10s", mp->name); 472388e9c81SLen Brown } else { 473388e9c81SLen Brown outp += sprintf(outp, "\t%-7.7s", mp->name); 474388e9c81SLen Brown } 475388e9c81SLen Brown } 476388e9c81SLen Brown 4771cc21f7bSLen Brown done: 478c98d5d94SLen Brown outp += sprintf(outp, "\n"); 479103a8feaSLen Brown } 480103a8feaSLen Brown 481c98d5d94SLen Brown int dump_counters(struct thread_data *t, struct core_data *c, 482c98d5d94SLen Brown struct pkg_data *p) 483103a8feaSLen Brown { 484388e9c81SLen Brown int i; 485388e9c81SLen Brown struct msr_counter *mp; 486388e9c81SLen Brown 4873b4d5c7fSAndy Shevchenko outp += sprintf(outp, "t %p, c %p, p %p\n", t, c, p); 488c98d5d94SLen Brown 489c98d5d94SLen Brown if (t) { 4903b4d5c7fSAndy Shevchenko outp += sprintf(outp, "CPU: %d flags 0x%x\n", 4913b4d5c7fSAndy Shevchenko t->cpu_id, t->flags); 4923b4d5c7fSAndy Shevchenko outp += sprintf(outp, "TSC: %016llX\n", t->tsc); 4933b4d5c7fSAndy Shevchenko outp += sprintf(outp, "aperf: %016llX\n", t->aperf); 4943b4d5c7fSAndy Shevchenko outp += sprintf(outp, "mperf: %016llX\n", t->mperf); 4953b4d5c7fSAndy Shevchenko outp += sprintf(outp, "c1: %016llX\n", t->c1); 496*6886fee4SLen Brown 497562a2d37SLen Brown if (do_irq) 498562a2d37SLen Brown outp += sprintf(outp, "IRQ: %08X\n", t->irq_count); 4991ed51011SLen Brown if (do_smi) 5003b4d5c7fSAndy Shevchenko outp += sprintf(outp, "SMI: %08X\n", t->smi_count); 501388e9c81SLen Brown 502388e9c81SLen Brown for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 503388e9c81SLen Brown outp += sprintf(outp, "tADDED [%d] msr0x%x: %08llX\n", 504388e9c81SLen Brown i, mp->msr_num, t->counter[i]); 505388e9c81SLen Brown } 506103a8feaSLen Brown } 507103a8feaSLen Brown 508c98d5d94SLen Brown if (c) { 5093b4d5c7fSAndy Shevchenko outp += sprintf(outp, "core: %d\n", c->core_id); 5103b4d5c7fSAndy Shevchenko outp += sprintf(outp, "c3: %016llX\n", c->c3); 5113b4d5c7fSAndy Shevchenko outp += sprintf(outp, "c6: %016llX\n", c->c6); 5123b4d5c7fSAndy Shevchenko outp += sprintf(outp, "c7: %016llX\n", c->c7); 5133b4d5c7fSAndy Shevchenko outp += sprintf(outp, "DTS: %dC\n", c->core_temp_c); 514388e9c81SLen Brown 515388e9c81SLen Brown for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 516388e9c81SLen Brown outp += sprintf(outp, "cADDED [%d] msr0x%x: %08llX\n", 517388e9c81SLen Brown i, mp->msr_num, c->counter[i]); 518388e9c81SLen Brown } 519c98d5d94SLen Brown } 520103a8feaSLen Brown 521c98d5d94SLen Brown if (p) { 5223b4d5c7fSAndy Shevchenko outp += sprintf(outp, "package: %d\n", p->package_id); 5230b2bb692SLen Brown 5240b2bb692SLen Brown outp += sprintf(outp, "Weighted cores: %016llX\n", p->pkg_wtd_core_c0); 5250b2bb692SLen Brown outp += sprintf(outp, "Any cores: %016llX\n", p->pkg_any_core_c0); 5260b2bb692SLen Brown outp += sprintf(outp, "Any GFX: %016llX\n", p->pkg_any_gfxe_c0); 5270b2bb692SLen Brown outp += sprintf(outp, "CPU + GFX: %016llX\n", p->pkg_both_core_gfxe_c0); 5280b2bb692SLen Brown 5293b4d5c7fSAndy Shevchenko outp += sprintf(outp, "pc2: %016llX\n", p->pc2); 530ee7e38e3SLen Brown if (do_pc3) 5313b4d5c7fSAndy Shevchenko outp += sprintf(outp, "pc3: %016llX\n", p->pc3); 532ee7e38e3SLen Brown if (do_pc6) 5333b4d5c7fSAndy Shevchenko outp += sprintf(outp, "pc6: %016llX\n", p->pc6); 534ee7e38e3SLen Brown if (do_pc7) 5353b4d5c7fSAndy Shevchenko outp += sprintf(outp, "pc7: %016llX\n", p->pc7); 5363b4d5c7fSAndy Shevchenko outp += sprintf(outp, "pc8: %016llX\n", p->pc8); 5373b4d5c7fSAndy Shevchenko outp += sprintf(outp, "pc9: %016llX\n", p->pc9); 5383b4d5c7fSAndy Shevchenko outp += sprintf(outp, "pc10: %016llX\n", p->pc10); 5393b4d5c7fSAndy Shevchenko outp += sprintf(outp, "Joules PKG: %0X\n", p->energy_pkg); 5403b4d5c7fSAndy Shevchenko outp += sprintf(outp, "Joules COR: %0X\n", p->energy_cores); 5413b4d5c7fSAndy Shevchenko outp += sprintf(outp, "Joules GFX: %0X\n", p->energy_gfx); 5423b4d5c7fSAndy Shevchenko outp += sprintf(outp, "Joules RAM: %0X\n", p->energy_dram); 5433b4d5c7fSAndy Shevchenko outp += sprintf(outp, "Throttle PKG: %0X\n", 5443b4d5c7fSAndy Shevchenko p->rapl_pkg_perf_status); 5453b4d5c7fSAndy Shevchenko outp += sprintf(outp, "Throttle RAM: %0X\n", 5463b4d5c7fSAndy Shevchenko p->rapl_dram_perf_status); 5473b4d5c7fSAndy Shevchenko outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c); 548388e9c81SLen Brown 549388e9c81SLen Brown for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 550388e9c81SLen Brown outp += sprintf(outp, "pADDED [%d] msr0x%x: %08llX\n", 551388e9c81SLen Brown i, mp->msr_num, p->counter[i]); 552388e9c81SLen Brown } 553c98d5d94SLen Brown } 5543b4d5c7fSAndy Shevchenko 5553b4d5c7fSAndy Shevchenko outp += sprintf(outp, "\n"); 5563b4d5c7fSAndy Shevchenko 557c98d5d94SLen Brown return 0; 558103a8feaSLen Brown } 559103a8feaSLen Brown 560e23da037SLen Brown /* 561e23da037SLen Brown * column formatting convention & formats 562e23da037SLen Brown */ 563c98d5d94SLen Brown int format_counters(struct thread_data *t, struct core_data *c, 564c98d5d94SLen Brown struct pkg_data *p) 565103a8feaSLen Brown { 566103a8feaSLen Brown double interval_float; 567fc04cc67SLen Brown char *fmt8; 568388e9c81SLen Brown int i; 569388e9c81SLen Brown struct msr_counter *mp; 570103a8feaSLen Brown 571c98d5d94SLen Brown /* if showing only 1st thread in core and this isn't one, bail out */ 572c98d5d94SLen Brown if (show_core_only && !(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 573c98d5d94SLen Brown return 0; 574c98d5d94SLen Brown 575c98d5d94SLen Brown /* if showing only 1st thread in pkg and this isn't one, bail out */ 576c98d5d94SLen Brown if (show_pkg_only && !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 577c98d5d94SLen Brown return 0; 578c98d5d94SLen Brown 579103a8feaSLen Brown interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0; 580103a8feaSLen Brown 581c98d5d94SLen Brown /* topo columns, print blanks on 1st (average) line */ 582c98d5d94SLen Brown if (t == &average.threads) { 583103a8feaSLen Brown if (show_pkg) 5843d109de2SLen Brown outp += sprintf(outp, "\t-"); 585103a8feaSLen Brown if (show_core) 5863d109de2SLen Brown outp += sprintf(outp, "\t-"); 587103a8feaSLen Brown if (show_cpu) 5883d109de2SLen Brown outp += sprintf(outp, "\t-"); 589103a8feaSLen Brown } else { 590c98d5d94SLen Brown if (show_pkg) { 591c98d5d94SLen Brown if (p) 5923d109de2SLen Brown outp += sprintf(outp, "\t%d", p->package_id); 593c98d5d94SLen Brown else 5943d109de2SLen Brown outp += sprintf(outp, "\t-"); 595c98d5d94SLen Brown } 596c98d5d94SLen Brown if (show_core) { 597c98d5d94SLen Brown if (c) 5983d109de2SLen Brown outp += sprintf(outp, "\t%d", c->core_id); 599c98d5d94SLen Brown else 6003d109de2SLen Brown outp += sprintf(outp, "\t-"); 601c98d5d94SLen Brown } 602103a8feaSLen Brown if (show_cpu) 6033d109de2SLen Brown outp += sprintf(outp, "\t%d", t->cpu_id); 604103a8feaSLen Brown } 605fc04cc67SLen Brown 606d7899447SLen Brown /* Avg_MHz */ 607fc04cc67SLen Brown if (has_aperf) 6083d109de2SLen Brown outp += sprintf(outp, "\t%.0f", 609fc04cc67SLen Brown 1.0 / units * t->aperf / interval_float); 610fc04cc67SLen Brown 61175d2e44eSLen Brown /* Busy% */ 612ba3dec99SLen Brown if (has_aperf) 6133d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * t->mperf/t->tsc/tsc_tweak); 614103a8feaSLen Brown 615d7899447SLen Brown /* Bzy_MHz */ 61621ed5574SLen Brown if (has_aperf) { 61721ed5574SLen Brown if (has_base_hz) 6183d109de2SLen Brown outp += sprintf(outp, "\t%.0f", base_hz / units * t->aperf / t->mperf); 61921ed5574SLen Brown else 6203d109de2SLen Brown outp += sprintf(outp, "\t%.0f", 62121ed5574SLen Brown 1.0 * t->tsc / units * t->aperf / t->mperf / interval_float); 62221ed5574SLen Brown } 623103a8feaSLen Brown 624d7899447SLen Brown /* TSC_MHz */ 6253d109de2SLen Brown outp += sprintf(outp, "\t%.0f", 1.0 * t->tsc/units/interval_float); 626103a8feaSLen Brown 6271cc21f7bSLen Brown if (!debug) 6281cc21f7bSLen Brown goto done; 6291cc21f7bSLen Brown 630562a2d37SLen Brown /* IRQ */ 631562a2d37SLen Brown if (do_irq) 6323d109de2SLen Brown outp += sprintf(outp, "\t%d", t->irq_count); 633562a2d37SLen Brown 6341cc21f7bSLen Brown /* SMI */ 6351cc21f7bSLen Brown if (do_smi) 6363d109de2SLen Brown outp += sprintf(outp, "\t%d", t->smi_count); 6371cc21f7bSLen Brown 638ba3dec99SLen Brown if (do_nhm_cstates) 6393d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * t->c1/t->tsc); 640c98d5d94SLen Brown 641c98d5d94SLen Brown /* print per-core data only for 1st thread in core */ 642c98d5d94SLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 643c98d5d94SLen Brown goto done; 644c98d5d94SLen Brown 645fb5d4327SDasaratharaman Chandramouli if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates) 6463d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * c->c3/t->tsc); 647103a8feaSLen Brown if (do_nhm_cstates) 6483d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * c->c6/t->tsc); 649103a8feaSLen Brown if (do_snb_cstates) 6503d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * c->c7/t->tsc); 651c98d5d94SLen Brown 652388e9c81SLen Brown for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 653388e9c81SLen Brown if (mp->format == FORMAT_RAW) { 654388e9c81SLen Brown if (mp->width == 32) 655388e9c81SLen Brown outp += sprintf(outp, "\t0x%08lx", (unsigned long) t->counter[i]); 656388e9c81SLen Brown else 657388e9c81SLen Brown outp += sprintf(outp, "\t0x%016llx", t->counter[i]); 658388e9c81SLen Brown } else if (mp->format == FORMAT_DELTA) { 659388e9c81SLen Brown outp += sprintf(outp, "\t%8lld", t->counter[i]); 660388e9c81SLen Brown } else if (mp->format == FORMAT_PERCENT) { 661388e9c81SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * t->counter[i]/t->tsc); 662388e9c81SLen Brown } 663388e9c81SLen Brown } 664388e9c81SLen Brown 665388e9c81SLen Brown 666889facbeSLen Brown if (do_dts) 6673d109de2SLen Brown outp += sprintf(outp, "\t%d", c->core_temp_c); 668889facbeSLen Brown 669388e9c81SLen Brown for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 670388e9c81SLen Brown if (mp->format == FORMAT_RAW) { 671388e9c81SLen Brown if (mp->width == 32) 672388e9c81SLen Brown outp += sprintf(outp, "\t0x%08lx", (unsigned long) c->counter[i]); 673388e9c81SLen Brown else 674388e9c81SLen Brown outp += sprintf(outp, "\t0x%016llx", c->counter[i]); 675388e9c81SLen Brown } else if (mp->format == FORMAT_DELTA) { 676388e9c81SLen Brown outp += sprintf(outp, "\t%8lld", c->counter[i]); 677388e9c81SLen Brown } else if (mp->format == FORMAT_PERCENT) { 678388e9c81SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * c->counter[i]/t->tsc); 679388e9c81SLen Brown } 680388e9c81SLen Brown } 681388e9c81SLen Brown 682c98d5d94SLen Brown /* print per-package data only for 1st core in package */ 683c98d5d94SLen Brown if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 684c98d5d94SLen Brown goto done; 685c98d5d94SLen Brown 6860b2bb692SLen Brown /* PkgTmp */ 687889facbeSLen Brown if (do_ptm) 6883d109de2SLen Brown outp += sprintf(outp, "\t%d", p->pkg_temp_c); 689889facbeSLen Brown 690fdf676e5SLen Brown /* GFXrc6 */ 6919185e988SLen Brown if (do_gfx_rc6_ms) { 692ba3dec99SLen Brown if (p->gfx_rc6_ms == -1) { /* detect GFX counter reset */ 6933d109de2SLen Brown outp += sprintf(outp, "\t**.**"); 6949185e988SLen Brown } else { 6953d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 6969185e988SLen Brown p->gfx_rc6_ms / 10.0 / interval_float); 6979185e988SLen Brown } 6989185e988SLen Brown } 699fdf676e5SLen Brown 70027d47356SLen Brown /* GFXMHz */ 70127d47356SLen Brown if (do_gfx_mhz) 7023d109de2SLen Brown outp += sprintf(outp, "\t%d", p->gfx_mhz); 70327d47356SLen Brown 7040b2bb692SLen Brown /* Totl%C0, Any%C0 GFX%C0 CPUGFX% */ 7050b2bb692SLen Brown if (do_skl_residency) { 7063d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_wtd_core_c0/t->tsc); 7073d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_any_core_c0/t->tsc); 7083d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_any_gfxe_c0/t->tsc); 7093d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_both_core_gfxe_c0/t->tsc); 7100b2bb692SLen Brown } 7110b2bb692SLen Brown 712ee7e38e3SLen Brown if (do_pc2) 7133d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pc2/t->tsc); 714ee7e38e3SLen Brown if (do_pc3) 7153d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pc3/t->tsc); 716ee7e38e3SLen Brown if (do_pc6) 7173d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pc6/t->tsc); 718ee7e38e3SLen Brown if (do_pc7) 7193d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pc7/t->tsc); 720ca58710fSKristen Carlson Accardi if (do_c8_c9_c10) { 7213d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pc8/t->tsc); 7223d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pc9/t->tsc); 7233d109de2SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->pc10/t->tsc); 724ca58710fSKristen Carlson Accardi } 725889facbeSLen Brown 726889facbeSLen Brown /* 727889facbeSLen Brown * If measurement interval exceeds minimum RAPL Joule Counter range, 728889facbeSLen Brown * indicate that results are suspect by printing "**" in fraction place. 729889facbeSLen Brown */ 730fc04cc67SLen Brown if (interval_float < rapl_joule_counter_range) 7313d109de2SLen Brown fmt8 = "\t%.2f"; 732fc04cc67SLen Brown else 733fc04cc67SLen Brown fmt8 = "%6.0f**"; 734889facbeSLen Brown 7355c56be9aSDirk Brandewie if (do_rapl && !rapl_joules) { 736889facbeSLen Brown if (do_rapl & RAPL_PKG) 737fc04cc67SLen Brown outp += sprintf(outp, fmt8, p->energy_pkg * rapl_energy_units / interval_float); 7389148494cSJacob Pan if (do_rapl & RAPL_CORES_ENERGY_STATUS) 739fc04cc67SLen Brown outp += sprintf(outp, fmt8, p->energy_cores * rapl_energy_units / interval_float); 740889facbeSLen Brown if (do_rapl & RAPL_GFX) 741fc04cc67SLen Brown outp += sprintf(outp, fmt8, p->energy_gfx * rapl_energy_units / interval_float); 742889facbeSLen Brown if (do_rapl & RAPL_DRAM) 74340ee8e3bSAndrey Semin outp += sprintf(outp, fmt8, p->energy_dram * rapl_dram_energy_units / interval_float); 744889facbeSLen Brown if (do_rapl & RAPL_PKG_PERF_STATUS) 745fc04cc67SLen Brown outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); 746889facbeSLen Brown if (do_rapl & RAPL_DRAM_PERF_STATUS) 747fc04cc67SLen Brown outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); 748d7899447SLen Brown } else if (do_rapl && rapl_joules) { 7495c56be9aSDirk Brandewie if (do_rapl & RAPL_PKG) 750fc04cc67SLen Brown outp += sprintf(outp, fmt8, 7515c56be9aSDirk Brandewie p->energy_pkg * rapl_energy_units); 7525c56be9aSDirk Brandewie if (do_rapl & RAPL_CORES) 753fc04cc67SLen Brown outp += sprintf(outp, fmt8, 7545c56be9aSDirk Brandewie p->energy_cores * rapl_energy_units); 7555c56be9aSDirk Brandewie if (do_rapl & RAPL_GFX) 756fc04cc67SLen Brown outp += sprintf(outp, fmt8, 7575c56be9aSDirk Brandewie p->energy_gfx * rapl_energy_units); 7585c56be9aSDirk Brandewie if (do_rapl & RAPL_DRAM) 759fc04cc67SLen Brown outp += sprintf(outp, fmt8, 76040ee8e3bSAndrey Semin p->energy_dram * rapl_dram_energy_units); 7615c56be9aSDirk Brandewie if (do_rapl & RAPL_PKG_PERF_STATUS) 762fc04cc67SLen Brown outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); 7635c56be9aSDirk Brandewie if (do_rapl & RAPL_DRAM_PERF_STATUS) 764fc04cc67SLen Brown outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); 7655c56be9aSDirk Brandewie } 766388e9c81SLen Brown for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 767388e9c81SLen Brown if (mp->format == FORMAT_RAW) { 768388e9c81SLen Brown if (mp->width == 32) 769388e9c81SLen Brown outp += sprintf(outp, "\t0x%08lx", (unsigned long) p->counter[i]); 770388e9c81SLen Brown else 771388e9c81SLen Brown outp += sprintf(outp, "\t0x%016llx", p->counter[i]); 772388e9c81SLen Brown } else if (mp->format == FORMAT_DELTA) { 773388e9c81SLen Brown outp += sprintf(outp, "\t%8lld", p->counter[i]); 774388e9c81SLen Brown } else if (mp->format == FORMAT_PERCENT) { 775388e9c81SLen Brown outp += sprintf(outp, "\t%.2f", 100.0 * p->counter[i]/t->tsc); 776388e9c81SLen Brown } 777388e9c81SLen Brown } 778388e9c81SLen Brown 779c98d5d94SLen Brown done: 780c98d5d94SLen Brown outp += sprintf(outp, "\n"); 781c98d5d94SLen Brown 782c98d5d94SLen Brown return 0; 783103a8feaSLen Brown } 784103a8feaSLen Brown 785b7d8c148SLen Brown void flush_output_stdout(void) 786103a8feaSLen Brown { 787b7d8c148SLen Brown FILE *filep; 788b7d8c148SLen Brown 789b7d8c148SLen Brown if (outf == stderr) 790b7d8c148SLen Brown filep = stdout; 791b7d8c148SLen Brown else 792b7d8c148SLen Brown filep = outf; 793b7d8c148SLen Brown 794b7d8c148SLen Brown fputs(output_buffer, filep); 795b7d8c148SLen Brown fflush(filep); 796b7d8c148SLen Brown 797c98d5d94SLen Brown outp = output_buffer; 798c98d5d94SLen Brown } 799b7d8c148SLen Brown void flush_output_stderr(void) 800c98d5d94SLen Brown { 801b7d8c148SLen Brown fputs(output_buffer, outf); 802b7d8c148SLen Brown fflush(outf); 803c98d5d94SLen Brown outp = output_buffer; 804c98d5d94SLen Brown } 805c98d5d94SLen Brown void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) 806c98d5d94SLen Brown { 807e23da037SLen Brown static int printed; 808103a8feaSLen Brown 809e23da037SLen Brown if (!printed || !summary_only) 810103a8feaSLen Brown print_header(); 811103a8feaSLen Brown 812c98d5d94SLen Brown if (topo.num_cpus > 1) 813c98d5d94SLen Brown format_counters(&average.threads, &average.cores, 814c98d5d94SLen Brown &average.packages); 815103a8feaSLen Brown 816e23da037SLen Brown printed = 1; 817e23da037SLen Brown 818e23da037SLen Brown if (summary_only) 819e23da037SLen Brown return; 820e23da037SLen Brown 821c98d5d94SLen Brown for_all_cpus(format_counters, t, c, p); 822103a8feaSLen Brown } 823103a8feaSLen Brown 824889facbeSLen Brown #define DELTA_WRAP32(new, old) \ 825889facbeSLen Brown if (new > old) { \ 826889facbeSLen Brown old = new - old; \ 827889facbeSLen Brown } else { \ 828889facbeSLen Brown old = 0x100000000 + new - old; \ 829889facbeSLen Brown } 830889facbeSLen Brown 831ba3dec99SLen Brown int 832c98d5d94SLen Brown delta_package(struct pkg_data *new, struct pkg_data *old) 833103a8feaSLen Brown { 834388e9c81SLen Brown int i; 835388e9c81SLen Brown struct msr_counter *mp; 8360b2bb692SLen Brown 8370b2bb692SLen Brown if (do_skl_residency) { 8380b2bb692SLen Brown old->pkg_wtd_core_c0 = new->pkg_wtd_core_c0 - old->pkg_wtd_core_c0; 8390b2bb692SLen Brown old->pkg_any_core_c0 = new->pkg_any_core_c0 - old->pkg_any_core_c0; 8400b2bb692SLen Brown old->pkg_any_gfxe_c0 = new->pkg_any_gfxe_c0 - old->pkg_any_gfxe_c0; 8410b2bb692SLen Brown old->pkg_both_core_gfxe_c0 = new->pkg_both_core_gfxe_c0 - old->pkg_both_core_gfxe_c0; 8420b2bb692SLen Brown } 843c98d5d94SLen Brown old->pc2 = new->pc2 - old->pc2; 844ee7e38e3SLen Brown if (do_pc3) 845c98d5d94SLen Brown old->pc3 = new->pc3 - old->pc3; 846ee7e38e3SLen Brown if (do_pc6) 847c98d5d94SLen Brown old->pc6 = new->pc6 - old->pc6; 848ee7e38e3SLen Brown if (do_pc7) 849c98d5d94SLen Brown old->pc7 = new->pc7 - old->pc7; 850ca58710fSKristen Carlson Accardi old->pc8 = new->pc8 - old->pc8; 851ca58710fSKristen Carlson Accardi old->pc9 = new->pc9 - old->pc9; 852ca58710fSKristen Carlson Accardi old->pc10 = new->pc10 - old->pc10; 853889facbeSLen Brown old->pkg_temp_c = new->pkg_temp_c; 854889facbeSLen Brown 8559185e988SLen Brown /* flag an error when rc6 counter resets/wraps */ 8569185e988SLen Brown if (old->gfx_rc6_ms > new->gfx_rc6_ms) 8579185e988SLen Brown old->gfx_rc6_ms = -1; 8589185e988SLen Brown else 859fdf676e5SLen Brown old->gfx_rc6_ms = new->gfx_rc6_ms - old->gfx_rc6_ms; 8609185e988SLen Brown 86127d47356SLen Brown old->gfx_mhz = new->gfx_mhz; 86227d47356SLen Brown 863889facbeSLen Brown DELTA_WRAP32(new->energy_pkg, old->energy_pkg); 864889facbeSLen Brown DELTA_WRAP32(new->energy_cores, old->energy_cores); 865889facbeSLen Brown DELTA_WRAP32(new->energy_gfx, old->energy_gfx); 866889facbeSLen Brown DELTA_WRAP32(new->energy_dram, old->energy_dram); 867889facbeSLen Brown DELTA_WRAP32(new->rapl_pkg_perf_status, old->rapl_pkg_perf_status); 868889facbeSLen Brown DELTA_WRAP32(new->rapl_dram_perf_status, old->rapl_dram_perf_status); 869ba3dec99SLen Brown 870388e9c81SLen Brown for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 871388e9c81SLen Brown if (mp->format == FORMAT_RAW) 872388e9c81SLen Brown old->counter[i] = new->counter[i]; 873388e9c81SLen Brown else 874388e9c81SLen Brown old->counter[i] = new->counter[i] - old->counter[i]; 875388e9c81SLen Brown } 876388e9c81SLen Brown 877ba3dec99SLen Brown return 0; 878103a8feaSLen Brown } 879103a8feaSLen Brown 880c98d5d94SLen Brown void 881c98d5d94SLen Brown delta_core(struct core_data *new, struct core_data *old) 882c98d5d94SLen Brown { 883388e9c81SLen Brown int i; 884388e9c81SLen Brown struct msr_counter *mp; 885388e9c81SLen Brown 886c98d5d94SLen Brown old->c3 = new->c3 - old->c3; 887c98d5d94SLen Brown old->c6 = new->c6 - old->c6; 888c98d5d94SLen Brown old->c7 = new->c7 - old->c7; 889889facbeSLen Brown old->core_temp_c = new->core_temp_c; 890388e9c81SLen Brown 891388e9c81SLen Brown for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 892388e9c81SLen Brown if (mp->format == FORMAT_RAW) 893388e9c81SLen Brown old->counter[i] = new->counter[i]; 894388e9c81SLen Brown else 895388e9c81SLen Brown old->counter[i] = new->counter[i] - old->counter[i]; 896388e9c81SLen Brown } 897103a8feaSLen Brown } 898c98d5d94SLen Brown 899c3ae331dSLen Brown /* 900c3ae331dSLen Brown * old = new - old 901c3ae331dSLen Brown */ 902ba3dec99SLen Brown int 903c98d5d94SLen Brown delta_thread(struct thread_data *new, struct thread_data *old, 904c98d5d94SLen Brown struct core_data *core_delta) 905c98d5d94SLen Brown { 906388e9c81SLen Brown int i; 907388e9c81SLen Brown struct msr_counter *mp; 908388e9c81SLen Brown 909c98d5d94SLen Brown old->tsc = new->tsc - old->tsc; 910c98d5d94SLen Brown 911103a8feaSLen Brown /* check for TSC < 1 Mcycles over interval */ 912b2c95d90SJosh Triplett if (old->tsc < (1000 * 1000)) 913b2c95d90SJosh Triplett errx(-3, "Insanely slow TSC rate, TSC stops in idle?\n" 914b2c95d90SJosh Triplett "You can disable all c-states by booting with \"idle=poll\"\n" 915b2c95d90SJosh Triplett "or just the deep ones with \"processor.max_cstate=1\""); 916103a8feaSLen Brown 917c98d5d94SLen Brown old->c1 = new->c1 - old->c1; 918c98d5d94SLen Brown 919a729617cSLen Brown if (has_aperf) { 920c98d5d94SLen Brown if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) { 921c98d5d94SLen Brown old->aperf = new->aperf - old->aperf; 922c98d5d94SLen Brown old->mperf = new->mperf - old->mperf; 923c98d5d94SLen Brown } else { 924ba3dec99SLen Brown return -1; 925103a8feaSLen Brown } 926a729617cSLen Brown } 927103a8feaSLen Brown 928c98d5d94SLen Brown 929144b44b1SLen Brown if (use_c1_residency_msr) { 930144b44b1SLen Brown /* 931144b44b1SLen Brown * Some models have a dedicated C1 residency MSR, 932144b44b1SLen Brown * which should be more accurate than the derivation below. 933144b44b1SLen Brown */ 934144b44b1SLen Brown } else { 935103a8feaSLen Brown /* 936c3ae331dSLen Brown * As counter collection is not atomic, 937c3ae331dSLen Brown * it is possible for mperf's non-halted cycles + idle states 938103a8feaSLen Brown * to exceed TSC's all cycles: show c1 = 0% in that case. 939103a8feaSLen Brown */ 940c3ae331dSLen Brown if ((old->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > old->tsc) 941c98d5d94SLen Brown old->c1 = 0; 942c98d5d94SLen Brown else { 943c98d5d94SLen Brown /* normal case, derive c1 */ 944c98d5d94SLen Brown old->c1 = old->tsc - old->mperf - core_delta->c3 945c98d5d94SLen Brown - core_delta->c6 - core_delta->c7; 946c98d5d94SLen Brown } 947144b44b1SLen Brown } 948c3ae331dSLen Brown 949c98d5d94SLen Brown if (old->mperf == 0) { 950b7d8c148SLen Brown if (debug > 1) 951b7d8c148SLen Brown fprintf(outf, "cpu%d MPERF 0!\n", old->cpu_id); 952c98d5d94SLen Brown old->mperf = 1; /* divide by 0 protection */ 953c98d5d94SLen Brown } 954103a8feaSLen Brown 955562a2d37SLen Brown if (do_irq) 956562a2d37SLen Brown old->irq_count = new->irq_count - old->irq_count; 957562a2d37SLen Brown 9581ed51011SLen Brown if (do_smi) 9591ed51011SLen Brown old->smi_count = new->smi_count - old->smi_count; 960ba3dec99SLen Brown 961388e9c81SLen Brown for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 962388e9c81SLen Brown if (mp->format == FORMAT_RAW) 963388e9c81SLen Brown old->counter[i] = new->counter[i]; 964388e9c81SLen Brown else 965388e9c81SLen Brown old->counter[i] = new->counter[i] - old->counter[i]; 966388e9c81SLen Brown } 967ba3dec99SLen Brown return 0; 968103a8feaSLen Brown } 969c98d5d94SLen Brown 970c98d5d94SLen Brown int delta_cpu(struct thread_data *t, struct core_data *c, 971c98d5d94SLen Brown struct pkg_data *p, struct thread_data *t2, 972c98d5d94SLen Brown struct core_data *c2, struct pkg_data *p2) 973c98d5d94SLen Brown { 974ba3dec99SLen Brown int retval = 0; 975ba3dec99SLen Brown 976c98d5d94SLen Brown /* calculate core delta only for 1st thread in core */ 977c98d5d94SLen Brown if (t->flags & CPU_IS_FIRST_THREAD_IN_CORE) 978c98d5d94SLen Brown delta_core(c, c2); 979c98d5d94SLen Brown 980c98d5d94SLen Brown /* always calculate thread delta */ 981ba3dec99SLen Brown retval = delta_thread(t, t2, c2); /* c2 is core delta */ 982ba3dec99SLen Brown if (retval) 983ba3dec99SLen Brown return retval; 984c98d5d94SLen Brown 985c98d5d94SLen Brown /* calculate package delta only for 1st core in package */ 986c98d5d94SLen Brown if (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE) 987ba3dec99SLen Brown retval = delta_package(p, p2); 988c98d5d94SLen Brown 989ba3dec99SLen Brown return retval; 990103a8feaSLen Brown } 991103a8feaSLen Brown 992c98d5d94SLen Brown void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) 993103a8feaSLen Brown { 994388e9c81SLen Brown int i; 995388e9c81SLen Brown struct msr_counter *mp; 996388e9c81SLen Brown 997c98d5d94SLen Brown t->tsc = 0; 998c98d5d94SLen Brown t->aperf = 0; 999c98d5d94SLen Brown t->mperf = 0; 1000c98d5d94SLen Brown t->c1 = 0; 1001103a8feaSLen Brown 1002562a2d37SLen Brown t->irq_count = 0; 1003562a2d37SLen Brown t->smi_count = 0; 1004562a2d37SLen Brown 1005c98d5d94SLen Brown /* tells format_counters to dump all fields from this set */ 1006c98d5d94SLen Brown t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE; 1007c98d5d94SLen Brown 1008c98d5d94SLen Brown c->c3 = 0; 1009c98d5d94SLen Brown c->c6 = 0; 1010c98d5d94SLen Brown c->c7 = 0; 1011889facbeSLen Brown c->core_temp_c = 0; 1012c98d5d94SLen Brown 10130b2bb692SLen Brown p->pkg_wtd_core_c0 = 0; 10140b2bb692SLen Brown p->pkg_any_core_c0 = 0; 10150b2bb692SLen Brown p->pkg_any_gfxe_c0 = 0; 10160b2bb692SLen Brown p->pkg_both_core_gfxe_c0 = 0; 10170b2bb692SLen Brown 1018c98d5d94SLen Brown p->pc2 = 0; 1019ee7e38e3SLen Brown if (do_pc3) 1020c98d5d94SLen Brown p->pc3 = 0; 1021ee7e38e3SLen Brown if (do_pc6) 1022c98d5d94SLen Brown p->pc6 = 0; 1023ee7e38e3SLen Brown if (do_pc7) 1024c98d5d94SLen Brown p->pc7 = 0; 1025ca58710fSKristen Carlson Accardi p->pc8 = 0; 1026ca58710fSKristen Carlson Accardi p->pc9 = 0; 1027ca58710fSKristen Carlson Accardi p->pc10 = 0; 1028889facbeSLen Brown 1029889facbeSLen Brown p->energy_pkg = 0; 1030889facbeSLen Brown p->energy_dram = 0; 1031889facbeSLen Brown p->energy_cores = 0; 1032889facbeSLen Brown p->energy_gfx = 0; 1033889facbeSLen Brown p->rapl_pkg_perf_status = 0; 1034889facbeSLen Brown p->rapl_dram_perf_status = 0; 1035889facbeSLen Brown p->pkg_temp_c = 0; 103627d47356SLen Brown 1037fdf676e5SLen Brown p->gfx_rc6_ms = 0; 103827d47356SLen Brown p->gfx_mhz = 0; 1039388e9c81SLen Brown 1040388e9c81SLen Brown for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) 1041388e9c81SLen Brown t->counter[i] = 0; 1042388e9c81SLen Brown 1043388e9c81SLen Brown for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) 1044388e9c81SLen Brown c->counter[i] = 0; 1045388e9c81SLen Brown 1046388e9c81SLen Brown for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) 1047388e9c81SLen Brown p->counter[i] = 0; 1048103a8feaSLen Brown } 1049c98d5d94SLen Brown int sum_counters(struct thread_data *t, struct core_data *c, 1050c98d5d94SLen Brown struct pkg_data *p) 1051103a8feaSLen Brown { 1052388e9c81SLen Brown int i; 1053388e9c81SLen Brown struct msr_counter *mp; 1054388e9c81SLen Brown 1055c98d5d94SLen Brown average.threads.tsc += t->tsc; 1056c98d5d94SLen Brown average.threads.aperf += t->aperf; 1057c98d5d94SLen Brown average.threads.mperf += t->mperf; 1058c98d5d94SLen Brown average.threads.c1 += t->c1; 105915aaa346SLen Brown 1060562a2d37SLen Brown average.threads.irq_count += t->irq_count; 1061562a2d37SLen Brown average.threads.smi_count += t->smi_count; 1062562a2d37SLen Brown 1063388e9c81SLen Brown for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 1064388e9c81SLen Brown if (mp->format == FORMAT_RAW) 1065388e9c81SLen Brown continue; 1066388e9c81SLen Brown average.threads.counter[i] += t->counter[i]; 1067388e9c81SLen Brown } 1068388e9c81SLen Brown 1069c98d5d94SLen Brown /* sum per-core values only for 1st thread in core */ 1070c98d5d94SLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 1071c98d5d94SLen Brown return 0; 1072c98d5d94SLen Brown 1073c98d5d94SLen Brown average.cores.c3 += c->c3; 1074c98d5d94SLen Brown average.cores.c6 += c->c6; 1075c98d5d94SLen Brown average.cores.c7 += c->c7; 1076c98d5d94SLen Brown 1077889facbeSLen Brown average.cores.core_temp_c = MAX(average.cores.core_temp_c, c->core_temp_c); 1078889facbeSLen Brown 1079388e9c81SLen Brown for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 1080388e9c81SLen Brown if (mp->format == FORMAT_RAW) 1081388e9c81SLen Brown continue; 1082388e9c81SLen Brown average.cores.counter[i] += c->counter[i]; 1083388e9c81SLen Brown } 1084388e9c81SLen Brown 1085c98d5d94SLen Brown /* sum per-pkg values only for 1st core in pkg */ 1086c98d5d94SLen Brown if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 1087c98d5d94SLen Brown return 0; 1088c98d5d94SLen Brown 10890b2bb692SLen Brown if (do_skl_residency) { 10900b2bb692SLen Brown average.packages.pkg_wtd_core_c0 += p->pkg_wtd_core_c0; 10910b2bb692SLen Brown average.packages.pkg_any_core_c0 += p->pkg_any_core_c0; 10920b2bb692SLen Brown average.packages.pkg_any_gfxe_c0 += p->pkg_any_gfxe_c0; 10930b2bb692SLen Brown average.packages.pkg_both_core_gfxe_c0 += p->pkg_both_core_gfxe_c0; 10940b2bb692SLen Brown } 10950b2bb692SLen Brown 1096c98d5d94SLen Brown average.packages.pc2 += p->pc2; 1097ee7e38e3SLen Brown if (do_pc3) 1098c98d5d94SLen Brown average.packages.pc3 += p->pc3; 1099ee7e38e3SLen Brown if (do_pc6) 1100c98d5d94SLen Brown average.packages.pc6 += p->pc6; 1101ee7e38e3SLen Brown if (do_pc7) 1102c98d5d94SLen Brown average.packages.pc7 += p->pc7; 1103ca58710fSKristen Carlson Accardi average.packages.pc8 += p->pc8; 1104ca58710fSKristen Carlson Accardi average.packages.pc9 += p->pc9; 1105ca58710fSKristen Carlson Accardi average.packages.pc10 += p->pc10; 1106c98d5d94SLen Brown 1107889facbeSLen Brown average.packages.energy_pkg += p->energy_pkg; 1108889facbeSLen Brown average.packages.energy_dram += p->energy_dram; 1109889facbeSLen Brown average.packages.energy_cores += p->energy_cores; 1110889facbeSLen Brown average.packages.energy_gfx += p->energy_gfx; 1111889facbeSLen Brown 1112fdf676e5SLen Brown average.packages.gfx_rc6_ms = p->gfx_rc6_ms; 111327d47356SLen Brown average.packages.gfx_mhz = p->gfx_mhz; 111427d47356SLen Brown 1115889facbeSLen Brown average.packages.pkg_temp_c = MAX(average.packages.pkg_temp_c, p->pkg_temp_c); 1116889facbeSLen Brown 1117889facbeSLen Brown average.packages.rapl_pkg_perf_status += p->rapl_pkg_perf_status; 1118889facbeSLen Brown average.packages.rapl_dram_perf_status += p->rapl_dram_perf_status; 1119388e9c81SLen Brown 1120388e9c81SLen Brown for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 1121388e9c81SLen Brown if (mp->format == FORMAT_RAW) 1122388e9c81SLen Brown continue; 1123388e9c81SLen Brown average.packages.counter[i] += p->counter[i]; 1124388e9c81SLen Brown } 1125c98d5d94SLen Brown return 0; 1126c98d5d94SLen Brown } 1127c98d5d94SLen Brown /* 1128c98d5d94SLen Brown * sum the counters for all cpus in the system 1129c98d5d94SLen Brown * compute the weighted average 1130c98d5d94SLen Brown */ 1131c98d5d94SLen Brown void compute_average(struct thread_data *t, struct core_data *c, 1132c98d5d94SLen Brown struct pkg_data *p) 1133c98d5d94SLen Brown { 1134388e9c81SLen Brown int i; 1135388e9c81SLen Brown struct msr_counter *mp; 1136388e9c81SLen Brown 1137c98d5d94SLen Brown clear_counters(&average.threads, &average.cores, &average.packages); 1138c98d5d94SLen Brown 1139c98d5d94SLen Brown for_all_cpus(sum_counters, t, c, p); 1140c98d5d94SLen Brown 1141c98d5d94SLen Brown average.threads.tsc /= topo.num_cpus; 1142c98d5d94SLen Brown average.threads.aperf /= topo.num_cpus; 1143c98d5d94SLen Brown average.threads.mperf /= topo.num_cpus; 1144c98d5d94SLen Brown average.threads.c1 /= topo.num_cpus; 1145c98d5d94SLen Brown 1146c98d5d94SLen Brown average.cores.c3 /= topo.num_cores; 1147c98d5d94SLen Brown average.cores.c6 /= topo.num_cores; 1148c98d5d94SLen Brown average.cores.c7 /= topo.num_cores; 1149c98d5d94SLen Brown 11500b2bb692SLen Brown if (do_skl_residency) { 11510b2bb692SLen Brown average.packages.pkg_wtd_core_c0 /= topo.num_packages; 11520b2bb692SLen Brown average.packages.pkg_any_core_c0 /= topo.num_packages; 11530b2bb692SLen Brown average.packages.pkg_any_gfxe_c0 /= topo.num_packages; 11540b2bb692SLen Brown average.packages.pkg_both_core_gfxe_c0 /= topo.num_packages; 11550b2bb692SLen Brown } 11560b2bb692SLen Brown 1157c98d5d94SLen Brown average.packages.pc2 /= topo.num_packages; 1158ee7e38e3SLen Brown if (do_pc3) 1159c98d5d94SLen Brown average.packages.pc3 /= topo.num_packages; 1160ee7e38e3SLen Brown if (do_pc6) 1161c98d5d94SLen Brown average.packages.pc6 /= topo.num_packages; 1162ee7e38e3SLen Brown if (do_pc7) 1163c98d5d94SLen Brown average.packages.pc7 /= topo.num_packages; 1164ca58710fSKristen Carlson Accardi 1165ca58710fSKristen Carlson Accardi average.packages.pc8 /= topo.num_packages; 1166ca58710fSKristen Carlson Accardi average.packages.pc9 /= topo.num_packages; 1167ca58710fSKristen Carlson Accardi average.packages.pc10 /= topo.num_packages; 1168388e9c81SLen Brown 1169388e9c81SLen Brown for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 1170388e9c81SLen Brown if (mp->format == FORMAT_RAW) 1171388e9c81SLen Brown continue; 1172388e9c81SLen Brown average.threads.counter[i] /= topo.num_cpus; 1173388e9c81SLen Brown } 1174388e9c81SLen Brown for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 1175388e9c81SLen Brown if (mp->format == FORMAT_RAW) 1176388e9c81SLen Brown continue; 1177388e9c81SLen Brown average.cores.counter[i] /= topo.num_cores; 1178388e9c81SLen Brown } 1179388e9c81SLen Brown for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 1180388e9c81SLen Brown if (mp->format == FORMAT_RAW) 1181388e9c81SLen Brown continue; 1182388e9c81SLen Brown average.packages.counter[i] /= topo.num_packages; 1183388e9c81SLen Brown } 1184c98d5d94SLen Brown } 1185c98d5d94SLen Brown 1186c98d5d94SLen Brown static unsigned long long rdtsc(void) 1187c98d5d94SLen Brown { 1188c98d5d94SLen Brown unsigned int low, high; 1189c98d5d94SLen Brown 1190c98d5d94SLen Brown asm volatile("rdtsc" : "=a" (low), "=d" (high)); 1191c98d5d94SLen Brown 1192c98d5d94SLen Brown return low | ((unsigned long long)high) << 32; 1193c98d5d94SLen Brown } 1194c98d5d94SLen Brown 1195c98d5d94SLen Brown /* 1196c98d5d94SLen Brown * get_counters(...) 1197c98d5d94SLen Brown * migrate to cpu 1198c98d5d94SLen Brown * acquire and record local counters for that cpu 1199c98d5d94SLen Brown */ 1200c98d5d94SLen Brown int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) 1201c98d5d94SLen Brown { 1202c98d5d94SLen Brown int cpu = t->cpu_id; 1203889facbeSLen Brown unsigned long long msr; 12040102b067SLen Brown int aperf_mperf_retry_count = 0; 1205388e9c81SLen Brown struct msr_counter *mp; 1206388e9c81SLen Brown int i; 1207c98d5d94SLen Brown 1208e52966c0SLen Brown if (cpu_migrate(cpu)) { 1209b7d8c148SLen Brown fprintf(outf, "Could not migrate to CPU %d\n", cpu); 121015aaa346SLen Brown return -1; 1211e52966c0SLen Brown } 121215aaa346SLen Brown 12130102b067SLen Brown retry: 1214c98d5d94SLen Brown t->tsc = rdtsc(); /* we are running on local CPU of interest */ 121515aaa346SLen Brown 121615aaa346SLen Brown if (has_aperf) { 12170102b067SLen Brown unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time; 12180102b067SLen Brown 12190102b067SLen Brown /* 12200102b067SLen Brown * The TSC, APERF and MPERF must be read together for 12210102b067SLen Brown * APERF/MPERF and MPERF/TSC to give accurate results. 12220102b067SLen Brown * 12230102b067SLen Brown * Unfortunately, APERF and MPERF are read by 12240102b067SLen Brown * individual system call, so delays may occur 12250102b067SLen Brown * between them. If the time to read them 12260102b067SLen Brown * varies by a large amount, we re-read them. 12270102b067SLen Brown */ 12280102b067SLen Brown 12290102b067SLen Brown /* 12300102b067SLen Brown * This initial dummy APERF read has been seen to 12310102b067SLen Brown * reduce jitter in the subsequent reads. 12320102b067SLen Brown */ 12330102b067SLen Brown 12349c63a650SLen Brown if (get_msr(cpu, MSR_IA32_APERF, &t->aperf)) 1235c98d5d94SLen Brown return -3; 12360102b067SLen Brown 12370102b067SLen Brown t->tsc = rdtsc(); /* re-read close to APERF */ 12380102b067SLen Brown 12390102b067SLen Brown tsc_before = t->tsc; 12400102b067SLen Brown 12410102b067SLen Brown if (get_msr(cpu, MSR_IA32_APERF, &t->aperf)) 12420102b067SLen Brown return -3; 12430102b067SLen Brown 12440102b067SLen Brown tsc_between = rdtsc(); 12450102b067SLen Brown 12469c63a650SLen Brown if (get_msr(cpu, MSR_IA32_MPERF, &t->mperf)) 1247c98d5d94SLen Brown return -4; 12480102b067SLen Brown 12490102b067SLen Brown tsc_after = rdtsc(); 12500102b067SLen Brown 12510102b067SLen Brown aperf_time = tsc_between - tsc_before; 12520102b067SLen Brown mperf_time = tsc_after - tsc_between; 12530102b067SLen Brown 12540102b067SLen Brown /* 12550102b067SLen Brown * If the system call latency to read APERF and MPERF 12560102b067SLen Brown * differ by more than 2x, then try again. 12570102b067SLen Brown */ 12580102b067SLen Brown if ((aperf_time > (2 * mperf_time)) || (mperf_time > (2 * aperf_time))) { 12590102b067SLen Brown aperf_mperf_retry_count++; 12600102b067SLen Brown if (aperf_mperf_retry_count < 5) 12610102b067SLen Brown goto retry; 12620102b067SLen Brown else 12630102b067SLen Brown warnx("cpu%d jitter %lld %lld", 12640102b067SLen Brown cpu, aperf_time, mperf_time); 12650102b067SLen Brown } 12660102b067SLen Brown aperf_mperf_retry_count = 0; 12670102b067SLen Brown 1268b2b34dfeSHubert Chrzaniuk t->aperf = t->aperf * aperf_mperf_multiplier; 1269b2b34dfeSHubert Chrzaniuk t->mperf = t->mperf * aperf_mperf_multiplier; 127088c3281fSLen Brown } 127188c3281fSLen Brown 1272562a2d37SLen Brown if (do_irq) 1273562a2d37SLen Brown t->irq_count = irqs_per_cpu[cpu]; 12741ed51011SLen Brown if (do_smi) { 12751ed51011SLen Brown if (get_msr(cpu, MSR_SMI_COUNT, &msr)) 12761ed51011SLen Brown return -5; 12771ed51011SLen Brown t->smi_count = msr & 0xFFFFFFFF; 12781ed51011SLen Brown } 1279c98d5d94SLen Brown 1280144b44b1SLen Brown if (use_c1_residency_msr) { 1281144b44b1SLen Brown if (get_msr(cpu, MSR_CORE_C1_RES, &t->c1)) 1282144b44b1SLen Brown return -6; 1283144b44b1SLen Brown } 1284144b44b1SLen Brown 1285388e9c81SLen Brown for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 1286388e9c81SLen Brown if (get_msr(cpu, mp->msr_num, &t->counter[i])) 1287388e9c81SLen Brown return -10; 1288388e9c81SLen Brown } 1289388e9c81SLen Brown 1290388e9c81SLen Brown 1291c98d5d94SLen Brown /* collect core counters only for 1st thread in core */ 1292c98d5d94SLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 1293c98d5d94SLen Brown return 0; 1294c98d5d94SLen Brown 1295fb5d4327SDasaratharaman Chandramouli if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates) { 1296c98d5d94SLen Brown if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3)) 1297c98d5d94SLen Brown return -6; 1298144b44b1SLen Brown } 1299144b44b1SLen Brown 1300fb5d4327SDasaratharaman Chandramouli if (do_nhm_cstates && !do_knl_cstates) { 1301c98d5d94SLen Brown if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6)) 1302c98d5d94SLen Brown return -7; 1303fb5d4327SDasaratharaman Chandramouli } else if (do_knl_cstates) { 1304fb5d4327SDasaratharaman Chandramouli if (get_msr(cpu, MSR_KNL_CORE_C6_RESIDENCY, &c->c6)) 1305fb5d4327SDasaratharaman Chandramouli return -7; 1306103a8feaSLen Brown } 130715aaa346SLen Brown 130815aaa346SLen Brown if (do_snb_cstates) 1309c98d5d94SLen Brown if (get_msr(cpu, MSR_CORE_C7_RESIDENCY, &c->c7)) 1310c98d5d94SLen Brown return -8; 1311c98d5d94SLen Brown 1312889facbeSLen Brown if (do_dts) { 1313889facbeSLen Brown if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr)) 1314889facbeSLen Brown return -9; 1315889facbeSLen Brown c->core_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F); 1316889facbeSLen Brown } 1317889facbeSLen Brown 1318388e9c81SLen Brown for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 1319388e9c81SLen Brown if (get_msr(cpu, mp->msr_num, &c->counter[i])) 1320388e9c81SLen Brown return -10; 1321388e9c81SLen Brown } 1322889facbeSLen Brown 1323c98d5d94SLen Brown /* collect package counters only for 1st core in package */ 1324c98d5d94SLen Brown if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 1325c98d5d94SLen Brown return 0; 132615aaa346SLen Brown 13270b2bb692SLen Brown if (do_skl_residency) { 13280b2bb692SLen Brown if (get_msr(cpu, MSR_PKG_WEIGHTED_CORE_C0_RES, &p->pkg_wtd_core_c0)) 13290b2bb692SLen Brown return -10; 13300b2bb692SLen Brown if (get_msr(cpu, MSR_PKG_ANY_CORE_C0_RES, &p->pkg_any_core_c0)) 13310b2bb692SLen Brown return -11; 13320b2bb692SLen Brown if (get_msr(cpu, MSR_PKG_ANY_GFXE_C0_RES, &p->pkg_any_gfxe_c0)) 13330b2bb692SLen Brown return -12; 13340b2bb692SLen Brown if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0)) 13350b2bb692SLen Brown return -13; 13360b2bb692SLen Brown } 1337ee7e38e3SLen Brown if (do_pc3) 1338c98d5d94SLen Brown if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3)) 1339c98d5d94SLen Brown return -9; 1340ee7e38e3SLen Brown if (do_pc6) 1341c98d5d94SLen Brown if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6)) 1342c98d5d94SLen Brown return -10; 1343ee7e38e3SLen Brown if (do_pc2) 1344c98d5d94SLen Brown if (get_msr(cpu, MSR_PKG_C2_RESIDENCY, &p->pc2)) 1345c98d5d94SLen Brown return -11; 1346ee7e38e3SLen Brown if (do_pc7) 1347c98d5d94SLen Brown if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7)) 1348c98d5d94SLen Brown return -12; 1349ca58710fSKristen Carlson Accardi if (do_c8_c9_c10) { 1350ca58710fSKristen Carlson Accardi if (get_msr(cpu, MSR_PKG_C8_RESIDENCY, &p->pc8)) 1351ca58710fSKristen Carlson Accardi return -13; 1352ca58710fSKristen Carlson Accardi if (get_msr(cpu, MSR_PKG_C9_RESIDENCY, &p->pc9)) 1353ca58710fSKristen Carlson Accardi return -13; 1354ca58710fSKristen Carlson Accardi if (get_msr(cpu, MSR_PKG_C10_RESIDENCY, &p->pc10)) 1355ca58710fSKristen Carlson Accardi return -13; 1356ca58710fSKristen Carlson Accardi } 1357889facbeSLen Brown if (do_rapl & RAPL_PKG) { 1358889facbeSLen Brown if (get_msr(cpu, MSR_PKG_ENERGY_STATUS, &msr)) 1359889facbeSLen Brown return -13; 1360889facbeSLen Brown p->energy_pkg = msr & 0xFFFFFFFF; 1361889facbeSLen Brown } 13629148494cSJacob Pan if (do_rapl & RAPL_CORES_ENERGY_STATUS) { 1363889facbeSLen Brown if (get_msr(cpu, MSR_PP0_ENERGY_STATUS, &msr)) 1364889facbeSLen Brown return -14; 1365889facbeSLen Brown p->energy_cores = msr & 0xFFFFFFFF; 1366889facbeSLen Brown } 1367889facbeSLen Brown if (do_rapl & RAPL_DRAM) { 1368889facbeSLen Brown if (get_msr(cpu, MSR_DRAM_ENERGY_STATUS, &msr)) 1369889facbeSLen Brown return -15; 1370889facbeSLen Brown p->energy_dram = msr & 0xFFFFFFFF; 1371889facbeSLen Brown } 1372889facbeSLen Brown if (do_rapl & RAPL_GFX) { 1373889facbeSLen Brown if (get_msr(cpu, MSR_PP1_ENERGY_STATUS, &msr)) 1374889facbeSLen Brown return -16; 1375889facbeSLen Brown p->energy_gfx = msr & 0xFFFFFFFF; 1376889facbeSLen Brown } 1377889facbeSLen Brown if (do_rapl & RAPL_PKG_PERF_STATUS) { 1378889facbeSLen Brown if (get_msr(cpu, MSR_PKG_PERF_STATUS, &msr)) 1379889facbeSLen Brown return -16; 1380889facbeSLen Brown p->rapl_pkg_perf_status = msr & 0xFFFFFFFF; 1381889facbeSLen Brown } 1382889facbeSLen Brown if (do_rapl & RAPL_DRAM_PERF_STATUS) { 1383889facbeSLen Brown if (get_msr(cpu, MSR_DRAM_PERF_STATUS, &msr)) 1384889facbeSLen Brown return -16; 1385889facbeSLen Brown p->rapl_dram_perf_status = msr & 0xFFFFFFFF; 1386889facbeSLen Brown } 1387889facbeSLen Brown if (do_ptm) { 1388889facbeSLen Brown if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr)) 1389889facbeSLen Brown return -17; 1390889facbeSLen Brown p->pkg_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F); 1391889facbeSLen Brown } 1392fdf676e5SLen Brown 1393fdf676e5SLen Brown if (do_gfx_rc6_ms) 1394fdf676e5SLen Brown p->gfx_rc6_ms = gfx_cur_rc6_ms; 1395fdf676e5SLen Brown 139627d47356SLen Brown if (do_gfx_mhz) 139727d47356SLen Brown p->gfx_mhz = gfx_cur_mhz; 139827d47356SLen Brown 1399388e9c81SLen Brown for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 1400388e9c81SLen Brown if (get_msr(cpu, mp->msr_num, &p->counter[i])) 1401388e9c81SLen Brown return -10; 1402388e9c81SLen Brown } 1403388e9c81SLen Brown 140415aaa346SLen Brown return 0; 1405103a8feaSLen Brown } 1406103a8feaSLen Brown 1407ee7e38e3SLen Brown /* 1408ee7e38e3SLen Brown * MSR_PKG_CST_CONFIG_CONTROL decoding for pkg_cstate_limit: 1409ee7e38e3SLen Brown * If you change the values, note they are used both in comparisons 1410ee7e38e3SLen Brown * (>= PCL__7) and to index pkg_cstate_limit_strings[]. 1411ee7e38e3SLen Brown */ 1412ee7e38e3SLen Brown 1413ee7e38e3SLen Brown #define PCLUKN 0 /* Unknown */ 1414ee7e38e3SLen Brown #define PCLRSV 1 /* Reserved */ 1415ee7e38e3SLen Brown #define PCL__0 2 /* PC0 */ 1416ee7e38e3SLen Brown #define PCL__1 3 /* PC1 */ 1417ee7e38e3SLen Brown #define PCL__2 4 /* PC2 */ 1418ee7e38e3SLen Brown #define PCL__3 5 /* PC3 */ 1419ee7e38e3SLen Brown #define PCL__4 6 /* PC4 */ 1420ee7e38e3SLen Brown #define PCL__6 7 /* PC6 */ 1421ee7e38e3SLen Brown #define PCL_6N 8 /* PC6 No Retention */ 1422ee7e38e3SLen Brown #define PCL_6R 9 /* PC6 Retention */ 1423ee7e38e3SLen Brown #define PCL__7 10 /* PC7 */ 1424ee7e38e3SLen Brown #define PCL_7S 11 /* PC7 Shrink */ 14250b2bb692SLen Brown #define PCL__8 12 /* PC8 */ 14260b2bb692SLen Brown #define PCL__9 13 /* PC9 */ 14270b2bb692SLen Brown #define PCLUNL 14 /* Unlimited */ 1428ee7e38e3SLen Brown 1429ee7e38e3SLen Brown int pkg_cstate_limit = PCLUKN; 1430ee7e38e3SLen Brown char *pkg_cstate_limit_strings[] = { "reserved", "unknown", "pc0", "pc1", "pc2", 14310b2bb692SLen Brown "pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "pc8", "pc9", "unlimited"}; 1432ee7e38e3SLen Brown 1433e9257f5fSLen 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}; 1434e9257f5fSLen 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}; 1435e9257f5fSLen 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}; 1436e9257f5fSLen 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}; 1437e9257f5fSLen 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}; 1438e9257f5fSLen 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}; 1439e4085d54SLen 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}; 1440d8ebb442SLen 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}; 1441ee7e38e3SLen Brown 1442a2b7b749SLen Brown 1443a2b7b749SLen Brown static void 1444a2b7b749SLen Brown calculate_tsc_tweak() 1445a2b7b749SLen Brown { 1446a2b7b749SLen Brown tsc_tweak = base_hz / tsc_hz; 1447a2b7b749SLen Brown } 1448a2b7b749SLen Brown 1449fcd17211SLen Brown static void 1450fcd17211SLen Brown dump_nhm_platform_info(void) 1451103a8feaSLen Brown { 1452103a8feaSLen Brown unsigned long long msr; 1453103a8feaSLen Brown unsigned int ratio; 1454103a8feaSLen Brown 1455ec0adc53SLen Brown get_msr(base_cpu, MSR_PLATFORM_INFO, &msr); 1456103a8feaSLen Brown 1457b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr); 14586574a5d5SLen Brown 1459103a8feaSLen Brown ratio = (msr >> 40) & 0xFF; 1460b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max efficiency frequency\n", 1461103a8feaSLen Brown ratio, bclk, ratio * bclk); 1462103a8feaSLen Brown 1463103a8feaSLen Brown ratio = (msr >> 8) & 0xFF; 1464b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz base frequency\n", 1465103a8feaSLen Brown ratio, bclk, ratio * bclk); 1466103a8feaSLen Brown 14677ce7d5deSPrarit Bhargava get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr); 1468b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n", 1469bfae2052SLen Brown base_cpu, msr, msr & 0x2 ? "EN" : "DIS"); 147067920418SLen Brown 1471fcd17211SLen Brown return; 1472fcd17211SLen Brown } 1473fcd17211SLen Brown 1474fcd17211SLen Brown static void 1475fcd17211SLen Brown dump_hsw_turbo_ratio_limits(void) 1476fcd17211SLen Brown { 1477fcd17211SLen Brown unsigned long long msr; 1478fcd17211SLen Brown unsigned int ratio; 1479fcd17211SLen Brown 14807ce7d5deSPrarit Bhargava get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT2, &msr); 1481fcd17211SLen Brown 1482b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT2: 0x%08llx\n", base_cpu, msr); 1483fcd17211SLen Brown 1484fcd17211SLen Brown ratio = (msr >> 8) & 0xFF; 1485fcd17211SLen Brown if (ratio) 1486b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 18 active cores\n", 1487fcd17211SLen Brown ratio, bclk, ratio * bclk); 1488fcd17211SLen Brown 1489fcd17211SLen Brown ratio = (msr >> 0) & 0xFF; 1490fcd17211SLen Brown if (ratio) 1491b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 17 active cores\n", 1492fcd17211SLen Brown ratio, bclk, ratio * bclk); 1493fcd17211SLen Brown return; 1494fcd17211SLen Brown } 1495fcd17211SLen Brown 1496fcd17211SLen Brown static void 1497fcd17211SLen Brown dump_ivt_turbo_ratio_limits(void) 1498fcd17211SLen Brown { 1499fcd17211SLen Brown unsigned long long msr; 1500fcd17211SLen Brown unsigned int ratio; 15016574a5d5SLen Brown 15027ce7d5deSPrarit Bhargava get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &msr); 15036574a5d5SLen Brown 1504b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, msr); 15056574a5d5SLen Brown 15066574a5d5SLen Brown ratio = (msr >> 56) & 0xFF; 15076574a5d5SLen Brown if (ratio) 1508b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 16 active cores\n", 15096574a5d5SLen Brown ratio, bclk, ratio * bclk); 15106574a5d5SLen Brown 15116574a5d5SLen Brown ratio = (msr >> 48) & 0xFF; 15126574a5d5SLen Brown if (ratio) 1513b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 15 active cores\n", 15146574a5d5SLen Brown ratio, bclk, ratio * bclk); 15156574a5d5SLen Brown 15166574a5d5SLen Brown ratio = (msr >> 40) & 0xFF; 15176574a5d5SLen Brown if (ratio) 1518b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 14 active cores\n", 15196574a5d5SLen Brown ratio, bclk, ratio * bclk); 15206574a5d5SLen Brown 15216574a5d5SLen Brown ratio = (msr >> 32) & 0xFF; 15226574a5d5SLen Brown if (ratio) 1523b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 13 active cores\n", 15246574a5d5SLen Brown ratio, bclk, ratio * bclk); 15256574a5d5SLen Brown 15266574a5d5SLen Brown ratio = (msr >> 24) & 0xFF; 15276574a5d5SLen Brown if (ratio) 1528b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 12 active cores\n", 15296574a5d5SLen Brown ratio, bclk, ratio * bclk); 15306574a5d5SLen Brown 15316574a5d5SLen Brown ratio = (msr >> 16) & 0xFF; 15326574a5d5SLen Brown if (ratio) 1533b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 11 active cores\n", 15346574a5d5SLen Brown ratio, bclk, ratio * bclk); 15356574a5d5SLen Brown 15366574a5d5SLen Brown ratio = (msr >> 8) & 0xFF; 15376574a5d5SLen Brown if (ratio) 1538b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 10 active cores\n", 15396574a5d5SLen Brown ratio, bclk, ratio * bclk); 15406574a5d5SLen Brown 15416574a5d5SLen Brown ratio = (msr >> 0) & 0xFF; 15426574a5d5SLen Brown if (ratio) 1543b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 9 active cores\n", 15446574a5d5SLen Brown ratio, bclk, ratio * bclk); 1545103a8feaSLen Brown return; 1546fcd17211SLen Brown } 1547fcd17211SLen Brown 1548fcd17211SLen Brown static void 1549fcd17211SLen Brown dump_nhm_turbo_ratio_limits(void) 1550fcd17211SLen Brown { 1551fcd17211SLen Brown unsigned long long msr; 1552fcd17211SLen Brown unsigned int ratio; 1553103a8feaSLen Brown 15547ce7d5deSPrarit Bhargava get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr); 1555103a8feaSLen Brown 1556b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr); 15576574a5d5SLen Brown 15586574a5d5SLen Brown ratio = (msr >> 56) & 0xFF; 15596574a5d5SLen Brown if (ratio) 1560b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 8 active cores\n", 15616574a5d5SLen Brown ratio, bclk, ratio * bclk); 15626574a5d5SLen Brown 15636574a5d5SLen Brown ratio = (msr >> 48) & 0xFF; 15646574a5d5SLen Brown if (ratio) 1565b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 7 active cores\n", 15666574a5d5SLen Brown ratio, bclk, ratio * bclk); 15676574a5d5SLen Brown 15686574a5d5SLen Brown ratio = (msr >> 40) & 0xFF; 15696574a5d5SLen Brown if (ratio) 1570b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 6 active cores\n", 15716574a5d5SLen Brown ratio, bclk, ratio * bclk); 15726574a5d5SLen Brown 15736574a5d5SLen Brown ratio = (msr >> 32) & 0xFF; 15746574a5d5SLen Brown if (ratio) 1575b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 5 active cores\n", 15766574a5d5SLen Brown ratio, bclk, ratio * bclk); 15776574a5d5SLen Brown 1578103a8feaSLen Brown ratio = (msr >> 24) & 0xFF; 1579103a8feaSLen Brown if (ratio) 1580b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 4 active cores\n", 1581103a8feaSLen Brown ratio, bclk, ratio * bclk); 1582103a8feaSLen Brown 1583103a8feaSLen Brown ratio = (msr >> 16) & 0xFF; 1584103a8feaSLen Brown if (ratio) 1585b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 3 active cores\n", 1586103a8feaSLen Brown ratio, bclk, ratio * bclk); 1587103a8feaSLen Brown 1588103a8feaSLen Brown ratio = (msr >> 8) & 0xFF; 1589103a8feaSLen Brown if (ratio) 1590b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 2 active cores\n", 1591103a8feaSLen Brown ratio, bclk, ratio * bclk); 1592103a8feaSLen Brown 1593103a8feaSLen Brown ratio = (msr >> 0) & 0xFF; 1594103a8feaSLen Brown if (ratio) 1595b7d8c148SLen Brown fprintf(outf, "%d * %.0f = %.0f MHz max turbo 1 active cores\n", 1596103a8feaSLen Brown ratio, bclk, ratio * bclk); 1597fcd17211SLen Brown return; 1598fcd17211SLen Brown } 15993a9a941dSLen Brown 1600fcd17211SLen Brown static void 1601fb5d4327SDasaratharaman Chandramouli dump_knl_turbo_ratio_limits(void) 1602fb5d4327SDasaratharaman Chandramouli { 1603cbf97abaSHubert Chrzaniuk const unsigned int buckets_no = 7; 1604cbf97abaSHubert Chrzaniuk 1605fb5d4327SDasaratharaman Chandramouli unsigned long long msr; 1606cbf97abaSHubert Chrzaniuk int delta_cores, delta_ratio; 1607cbf97abaSHubert Chrzaniuk int i, b_nr; 1608cbf97abaSHubert Chrzaniuk unsigned int cores[buckets_no]; 1609cbf97abaSHubert Chrzaniuk unsigned int ratio[buckets_no]; 1610fb5d4327SDasaratharaman Chandramouli 1611ebf5926aSSrinivas Pandruvada get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr); 1612fb5d4327SDasaratharaman Chandramouli 1613b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", 1614bfae2052SLen Brown base_cpu, msr); 1615fb5d4327SDasaratharaman Chandramouli 1616fb5d4327SDasaratharaman Chandramouli /** 1617fb5d4327SDasaratharaman Chandramouli * Turbo encoding in KNL is as follows: 1618cbf97abaSHubert Chrzaniuk * [0] -- Reserved 1619cbf97abaSHubert Chrzaniuk * [7:1] -- Base value of number of active cores of bucket 1. 1620fb5d4327SDasaratharaman Chandramouli * [15:8] -- Base value of freq ratio of bucket 1. 1621fb5d4327SDasaratharaman Chandramouli * [20:16] -- +ve delta of number of active cores of bucket 2. 1622fb5d4327SDasaratharaman Chandramouli * i.e. active cores of bucket 2 = 1623fb5d4327SDasaratharaman Chandramouli * active cores of bucket 1 + delta 1624fb5d4327SDasaratharaman Chandramouli * [23:21] -- Negative delta of freq ratio of bucket 2. 1625fb5d4327SDasaratharaman Chandramouli * i.e. freq ratio of bucket 2 = 1626fb5d4327SDasaratharaman Chandramouli * freq ratio of bucket 1 - delta 1627fb5d4327SDasaratharaman Chandramouli * [28:24]-- +ve delta of number of active cores of bucket 3. 1628fb5d4327SDasaratharaman Chandramouli * [31:29]-- -ve delta of freq ratio of bucket 3. 1629fb5d4327SDasaratharaman Chandramouli * [36:32]-- +ve delta of number of active cores of bucket 4. 1630fb5d4327SDasaratharaman Chandramouli * [39:37]-- -ve delta of freq ratio of bucket 4. 1631fb5d4327SDasaratharaman Chandramouli * [44:40]-- +ve delta of number of active cores of bucket 5. 1632fb5d4327SDasaratharaman Chandramouli * [47:45]-- -ve delta of freq ratio of bucket 5. 1633fb5d4327SDasaratharaman Chandramouli * [52:48]-- +ve delta of number of active cores of bucket 6. 1634fb5d4327SDasaratharaman Chandramouli * [55:53]-- -ve delta of freq ratio of bucket 6. 1635fb5d4327SDasaratharaman Chandramouli * [60:56]-- +ve delta of number of active cores of bucket 7. 1636fb5d4327SDasaratharaman Chandramouli * [63:61]-- -ve delta of freq ratio of bucket 7. 1637fb5d4327SDasaratharaman Chandramouli */ 1638fb5d4327SDasaratharaman Chandramouli 1639cbf97abaSHubert Chrzaniuk b_nr = 0; 1640cbf97abaSHubert Chrzaniuk cores[b_nr] = (msr & 0xFF) >> 1; 1641cbf97abaSHubert Chrzaniuk ratio[b_nr] = (msr >> 8) & 0xFF; 1642cbf97abaSHubert Chrzaniuk 1643cbf97abaSHubert Chrzaniuk for (i = 16; i < 64; i += 8) { 1644fb5d4327SDasaratharaman Chandramouli delta_cores = (msr >> i) & 0x1F; 1645cbf97abaSHubert Chrzaniuk delta_ratio = (msr >> (i + 5)) & 0x7; 1646fb5d4327SDasaratharaman Chandramouli 1647cbf97abaSHubert Chrzaniuk cores[b_nr + 1] = cores[b_nr] + delta_cores; 1648cbf97abaSHubert Chrzaniuk ratio[b_nr + 1] = ratio[b_nr] - delta_ratio; 1649cbf97abaSHubert Chrzaniuk b_nr++; 1650fb5d4327SDasaratharaman Chandramouli } 1651cbf97abaSHubert Chrzaniuk 1652cbf97abaSHubert Chrzaniuk for (i = buckets_no - 1; i >= 0; i--) 1653cbf97abaSHubert Chrzaniuk if (i > 0 ? ratio[i] != ratio[i - 1] : 1) 1654b7d8c148SLen Brown fprintf(outf, 1655fb5d4327SDasaratharaman Chandramouli "%d * %.0f = %.0f MHz max turbo %d active cores\n", 1656cbf97abaSHubert Chrzaniuk ratio[i], bclk, ratio[i] * bclk, cores[i]); 1657fb5d4327SDasaratharaman Chandramouli } 1658fb5d4327SDasaratharaman Chandramouli 1659fb5d4327SDasaratharaman Chandramouli static void 1660fcd17211SLen Brown dump_nhm_cst_cfg(void) 1661fcd17211SLen Brown { 1662fcd17211SLen Brown unsigned long long msr; 1663fcd17211SLen Brown 16647ce7d5deSPrarit Bhargava get_msr(base_cpu, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr); 1665fcd17211SLen Brown 1666fcd17211SLen Brown #define SNB_C1_AUTO_UNDEMOTE (1UL << 27) 1667fcd17211SLen Brown #define SNB_C3_AUTO_UNDEMOTE (1UL << 28) 1668fcd17211SLen Brown 1669b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x%08llx", base_cpu, msr); 1670fcd17211SLen Brown 1671b7d8c148SLen Brown fprintf(outf, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: %s)\n", 1672fcd17211SLen Brown (msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "", 1673fcd17211SLen Brown (msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "", 1674fcd17211SLen Brown (msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "", 1675fcd17211SLen Brown (msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "", 1676fcd17211SLen Brown (msr & (1 << 15)) ? "" : "UN", 16776c34f160SLen Brown (unsigned int)msr & 0xF, 1678fcd17211SLen Brown pkg_cstate_limit_strings[pkg_cstate_limit]); 1679fcd17211SLen Brown return; 1680103a8feaSLen Brown } 1681103a8feaSLen Brown 16826fb3143bSLen Brown static void 16836fb3143bSLen Brown dump_config_tdp(void) 16846fb3143bSLen Brown { 16856fb3143bSLen Brown unsigned long long msr; 16866fb3143bSLen Brown 16876fb3143bSLen Brown get_msr(base_cpu, MSR_CONFIG_TDP_NOMINAL, &msr); 1688b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_CONFIG_TDP_NOMINAL: 0x%08llx", base_cpu, msr); 1689685b535bSChen Yu fprintf(outf, " (base_ratio=%d)\n", (unsigned int)msr & 0xFF); 16906fb3143bSLen Brown 16916fb3143bSLen Brown get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_1, &msr); 1692b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_1: 0x%08llx (", base_cpu, msr); 16936fb3143bSLen Brown if (msr) { 1694685b535bSChen Yu fprintf(outf, "PKG_MIN_PWR_LVL1=%d ", (unsigned int)(msr >> 48) & 0x7FFF); 1695685b535bSChen Yu fprintf(outf, "PKG_MAX_PWR_LVL1=%d ", (unsigned int)(msr >> 32) & 0x7FFF); 1696685b535bSChen Yu fprintf(outf, "LVL1_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF); 1697685b535bSChen Yu fprintf(outf, "PKG_TDP_LVL1=%d", (unsigned int)(msr) & 0x7FFF); 16986fb3143bSLen Brown } 1699b7d8c148SLen Brown fprintf(outf, ")\n"); 17006fb3143bSLen Brown 17016fb3143bSLen Brown get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_2, &msr); 1702b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_2: 0x%08llx (", base_cpu, msr); 17036fb3143bSLen Brown if (msr) { 1704685b535bSChen Yu fprintf(outf, "PKG_MIN_PWR_LVL2=%d ", (unsigned int)(msr >> 48) & 0x7FFF); 1705685b535bSChen Yu fprintf(outf, "PKG_MAX_PWR_LVL2=%d ", (unsigned int)(msr >> 32) & 0x7FFF); 1706685b535bSChen Yu fprintf(outf, "LVL2_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF); 1707685b535bSChen Yu fprintf(outf, "PKG_TDP_LVL2=%d", (unsigned int)(msr) & 0x7FFF); 17086fb3143bSLen Brown } 1709b7d8c148SLen Brown fprintf(outf, ")\n"); 17106fb3143bSLen Brown 17116fb3143bSLen Brown get_msr(base_cpu, MSR_CONFIG_TDP_CONTROL, &msr); 1712b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_CONFIG_TDP_CONTROL: 0x%08llx (", base_cpu, msr); 17136fb3143bSLen Brown if ((msr) & 0x3) 1714b7d8c148SLen Brown fprintf(outf, "TDP_LEVEL=%d ", (unsigned int)(msr) & 0x3); 1715b7d8c148SLen Brown fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1); 1716b7d8c148SLen Brown fprintf(outf, ")\n"); 17176fb3143bSLen Brown 17186fb3143bSLen Brown get_msr(base_cpu, MSR_TURBO_ACTIVATION_RATIO, &msr); 1719b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_TURBO_ACTIVATION_RATIO: 0x%08llx (", base_cpu, msr); 1720685b535bSChen Yu fprintf(outf, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0xFF); 1721b7d8c148SLen Brown fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1); 1722b7d8c148SLen Brown fprintf(outf, ")\n"); 17236fb3143bSLen Brown } 17245a63426eSLen Brown 17255a63426eSLen Brown unsigned int irtl_time_units[] = {1, 32, 1024, 32768, 1048576, 33554432, 0, 0 }; 17265a63426eSLen Brown 17275a63426eSLen Brown void print_irtl(void) 17285a63426eSLen Brown { 17295a63426eSLen Brown unsigned long long msr; 17305a63426eSLen Brown 17315a63426eSLen Brown get_msr(base_cpu, MSR_PKGC3_IRTL, &msr); 17325a63426eSLen Brown fprintf(outf, "cpu%d: MSR_PKGC3_IRTL: 0x%08llx (", base_cpu, msr); 17335a63426eSLen Brown fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", 17345a63426eSLen Brown (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 17355a63426eSLen Brown 17365a63426eSLen Brown get_msr(base_cpu, MSR_PKGC6_IRTL, &msr); 17375a63426eSLen Brown fprintf(outf, "cpu%d: MSR_PKGC6_IRTL: 0x%08llx (", base_cpu, msr); 17385a63426eSLen Brown fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", 17395a63426eSLen Brown (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 17405a63426eSLen Brown 17415a63426eSLen Brown get_msr(base_cpu, MSR_PKGC7_IRTL, &msr); 17425a63426eSLen Brown fprintf(outf, "cpu%d: MSR_PKGC7_IRTL: 0x%08llx (", base_cpu, msr); 17435a63426eSLen Brown fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", 17445a63426eSLen Brown (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 17455a63426eSLen Brown 17465a63426eSLen Brown if (!do_irtl_hsw) 17475a63426eSLen Brown return; 17485a63426eSLen Brown 17495a63426eSLen Brown get_msr(base_cpu, MSR_PKGC8_IRTL, &msr); 17505a63426eSLen Brown fprintf(outf, "cpu%d: MSR_PKGC8_IRTL: 0x%08llx (", base_cpu, msr); 17515a63426eSLen Brown fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", 17525a63426eSLen Brown (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 17535a63426eSLen Brown 17545a63426eSLen Brown get_msr(base_cpu, MSR_PKGC9_IRTL, &msr); 17555a63426eSLen Brown fprintf(outf, "cpu%d: MSR_PKGC9_IRTL: 0x%08llx (", base_cpu, msr); 17565a63426eSLen Brown fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", 17575a63426eSLen Brown (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 17585a63426eSLen Brown 17595a63426eSLen Brown get_msr(base_cpu, MSR_PKGC10_IRTL, &msr); 17605a63426eSLen Brown fprintf(outf, "cpu%d: MSR_PKGC10_IRTL: 0x%08llx (", base_cpu, msr); 17615a63426eSLen Brown fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", 17625a63426eSLen Brown (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 17635a63426eSLen Brown 17645a63426eSLen Brown } 176536229897SLen Brown void free_fd_percpu(void) 176636229897SLen Brown { 176736229897SLen Brown int i; 176836229897SLen Brown 176901a67adfSMika Westerberg for (i = 0; i < topo.max_cpu_num + 1; ++i) { 177036229897SLen Brown if (fd_percpu[i] != 0) 177136229897SLen Brown close(fd_percpu[i]); 177236229897SLen Brown } 177336229897SLen Brown 177436229897SLen Brown free(fd_percpu); 17756fb3143bSLen Brown } 17766fb3143bSLen Brown 1777c98d5d94SLen Brown void free_all_buffers(void) 1778103a8feaSLen Brown { 1779c98d5d94SLen Brown CPU_FREE(cpu_present_set); 1780c98d5d94SLen Brown cpu_present_set = NULL; 178136229897SLen Brown cpu_present_setsize = 0; 1782103a8feaSLen Brown 1783c98d5d94SLen Brown CPU_FREE(cpu_affinity_set); 1784c98d5d94SLen Brown cpu_affinity_set = NULL; 1785c98d5d94SLen Brown cpu_affinity_setsize = 0; 1786103a8feaSLen Brown 1787c98d5d94SLen Brown free(thread_even); 1788c98d5d94SLen Brown free(core_even); 1789c98d5d94SLen Brown free(package_even); 1790103a8feaSLen Brown 1791c98d5d94SLen Brown thread_even = NULL; 1792c98d5d94SLen Brown core_even = NULL; 1793c98d5d94SLen Brown package_even = NULL; 1794103a8feaSLen Brown 1795c98d5d94SLen Brown free(thread_odd); 1796c98d5d94SLen Brown free(core_odd); 1797c98d5d94SLen Brown free(package_odd); 1798103a8feaSLen Brown 1799c98d5d94SLen Brown thread_odd = NULL; 1800c98d5d94SLen Brown core_odd = NULL; 1801c98d5d94SLen Brown package_odd = NULL; 1802103a8feaSLen Brown 1803c98d5d94SLen Brown free(output_buffer); 1804c98d5d94SLen Brown output_buffer = NULL; 1805c98d5d94SLen Brown outp = NULL; 180636229897SLen Brown 180736229897SLen Brown free_fd_percpu(); 1808562a2d37SLen Brown 1809562a2d37SLen Brown free(irq_column_2_cpu); 1810562a2d37SLen Brown free(irqs_per_cpu); 1811103a8feaSLen Brown } 1812103a8feaSLen Brown 1813103a8feaSLen Brown /* 181457a42a34SJosh Triplett * Open a file, and exit on failure 181557a42a34SJosh Triplett */ 181657a42a34SJosh Triplett FILE *fopen_or_die(const char *path, const char *mode) 181757a42a34SJosh Triplett { 1818b7d8c148SLen Brown FILE *filep = fopen(path, mode); 1819b2c95d90SJosh Triplett if (!filep) 1820b2c95d90SJosh Triplett err(1, "%s: open failed", path); 182157a42a34SJosh Triplett return filep; 182257a42a34SJosh Triplett } 182357a42a34SJosh Triplett 182457a42a34SJosh Triplett /* 182595aebc44SJosh Triplett * Parse a file containing a single int. 182695aebc44SJosh Triplett */ 182795aebc44SJosh Triplett int parse_int_file(const char *fmt, ...) 182895aebc44SJosh Triplett { 182995aebc44SJosh Triplett va_list args; 183095aebc44SJosh Triplett char path[PATH_MAX]; 183195aebc44SJosh Triplett FILE *filep; 183295aebc44SJosh Triplett int value; 183395aebc44SJosh Triplett 183495aebc44SJosh Triplett va_start(args, fmt); 183595aebc44SJosh Triplett vsnprintf(path, sizeof(path), fmt, args); 183695aebc44SJosh Triplett va_end(args); 183757a42a34SJosh Triplett filep = fopen_or_die(path, "r"); 1838b2c95d90SJosh Triplett if (fscanf(filep, "%d", &value) != 1) 1839b2c95d90SJosh Triplett err(1, "%s: failed to parse number from file", path); 184095aebc44SJosh Triplett fclose(filep); 184195aebc44SJosh Triplett return value; 184295aebc44SJosh Triplett } 184395aebc44SJosh Triplett 184495aebc44SJosh Triplett /* 1845e275b388SDasaratharaman Chandramouli * get_cpu_position_in_core(cpu) 1846e275b388SDasaratharaman Chandramouli * return the position of the CPU among its HT siblings in the core 1847e275b388SDasaratharaman Chandramouli * return -1 if the sibling is not in list 1848103a8feaSLen Brown */ 1849e275b388SDasaratharaman Chandramouli int get_cpu_position_in_core(int cpu) 1850103a8feaSLen Brown { 1851e275b388SDasaratharaman Chandramouli char path[64]; 1852e275b388SDasaratharaman Chandramouli FILE *filep; 1853e275b388SDasaratharaman Chandramouli int this_cpu; 1854e275b388SDasaratharaman Chandramouli char character; 1855e275b388SDasaratharaman Chandramouli int i; 1856e275b388SDasaratharaman Chandramouli 1857e275b388SDasaratharaman Chandramouli sprintf(path, 1858e275b388SDasaratharaman Chandramouli "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", 1859e275b388SDasaratharaman Chandramouli cpu); 1860e275b388SDasaratharaman Chandramouli filep = fopen(path, "r"); 1861e275b388SDasaratharaman Chandramouli if (filep == NULL) { 1862e275b388SDasaratharaman Chandramouli perror(path); 1863e275b388SDasaratharaman Chandramouli exit(1); 1864e275b388SDasaratharaman Chandramouli } 1865e275b388SDasaratharaman Chandramouli 1866e275b388SDasaratharaman Chandramouli for (i = 0; i < topo.num_threads_per_core; i++) { 1867e275b388SDasaratharaman Chandramouli fscanf(filep, "%d", &this_cpu); 1868e275b388SDasaratharaman Chandramouli if (this_cpu == cpu) { 1869e275b388SDasaratharaman Chandramouli fclose(filep); 1870e275b388SDasaratharaman Chandramouli return i; 1871e275b388SDasaratharaman Chandramouli } 1872e275b388SDasaratharaman Chandramouli 1873e275b388SDasaratharaman Chandramouli /* Account for no separator after last thread*/ 1874e275b388SDasaratharaman Chandramouli if (i != (topo.num_threads_per_core - 1)) 1875e275b388SDasaratharaman Chandramouli fscanf(filep, "%c", &character); 1876e275b388SDasaratharaman Chandramouli } 1877e275b388SDasaratharaman Chandramouli 1878e275b388SDasaratharaman Chandramouli fclose(filep); 1879e275b388SDasaratharaman Chandramouli return -1; 1880c98d5d94SLen Brown } 1881103a8feaSLen Brown 1882c98d5d94SLen Brown /* 1883c98d5d94SLen Brown * cpu_is_first_core_in_package(cpu) 1884c98d5d94SLen Brown * return 1 if given CPU is 1st core in package 1885c98d5d94SLen Brown */ 1886c98d5d94SLen Brown int cpu_is_first_core_in_package(int cpu) 1887c98d5d94SLen Brown { 188895aebc44SJosh Triplett return cpu == parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_siblings_list", cpu); 1889103a8feaSLen Brown } 1890103a8feaSLen Brown 1891103a8feaSLen Brown int get_physical_package_id(int cpu) 1892103a8feaSLen Brown { 189395aebc44SJosh Triplett return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu); 1894103a8feaSLen Brown } 1895103a8feaSLen Brown 1896103a8feaSLen Brown int get_core_id(int cpu) 1897103a8feaSLen Brown { 189895aebc44SJosh Triplett return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_id", cpu); 1899103a8feaSLen Brown } 1900103a8feaSLen Brown 1901c98d5d94SLen Brown int get_num_ht_siblings(int cpu) 1902c98d5d94SLen Brown { 1903c98d5d94SLen Brown char path[80]; 1904c98d5d94SLen Brown FILE *filep; 1905e275b388SDasaratharaman Chandramouli int sib1; 1906e275b388SDasaratharaman Chandramouli int matches = 0; 1907c98d5d94SLen Brown char character; 1908e275b388SDasaratharaman Chandramouli char str[100]; 1909e275b388SDasaratharaman Chandramouli char *ch; 1910c98d5d94SLen Brown 1911c98d5d94SLen Brown sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu); 191257a42a34SJosh Triplett filep = fopen_or_die(path, "r"); 1913e275b388SDasaratharaman Chandramouli 1914103a8feaSLen Brown /* 1915c98d5d94SLen Brown * file format: 1916e275b388SDasaratharaman Chandramouli * A ',' separated or '-' separated set of numbers 1917e275b388SDasaratharaman Chandramouli * (eg 1-2 or 1,3,4,5) 1918c98d5d94SLen Brown */ 1919e275b388SDasaratharaman Chandramouli fscanf(filep, "%d%c\n", &sib1, &character); 1920e275b388SDasaratharaman Chandramouli fseek(filep, 0, SEEK_SET); 1921e275b388SDasaratharaman Chandramouli fgets(str, 100, filep); 1922e275b388SDasaratharaman Chandramouli ch = strchr(str, character); 1923e275b388SDasaratharaman Chandramouli while (ch != NULL) { 1924e275b388SDasaratharaman Chandramouli matches++; 1925e275b388SDasaratharaman Chandramouli ch = strchr(ch+1, character); 1926e275b388SDasaratharaman Chandramouli } 1927c98d5d94SLen Brown 1928c98d5d94SLen Brown fclose(filep); 1929e275b388SDasaratharaman Chandramouli return matches+1; 1930c98d5d94SLen Brown } 1931c98d5d94SLen Brown 1932c98d5d94SLen Brown /* 1933c98d5d94SLen Brown * run func(thread, core, package) in topology order 1934c98d5d94SLen Brown * skip non-present cpus 1935103a8feaSLen Brown */ 1936103a8feaSLen Brown 1937c98d5d94SLen Brown int for_all_cpus_2(int (func)(struct thread_data *, struct core_data *, 1938c98d5d94SLen Brown struct pkg_data *, struct thread_data *, struct core_data *, 1939c98d5d94SLen Brown struct pkg_data *), struct thread_data *thread_base, 1940c98d5d94SLen Brown struct core_data *core_base, struct pkg_data *pkg_base, 1941c98d5d94SLen Brown struct thread_data *thread_base2, struct core_data *core_base2, 1942c98d5d94SLen Brown struct pkg_data *pkg_base2) 1943c98d5d94SLen Brown { 1944c98d5d94SLen Brown int retval, pkg_no, core_no, thread_no; 1945c98d5d94SLen Brown 1946c98d5d94SLen Brown for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) { 1947c98d5d94SLen Brown for (core_no = 0; core_no < topo.num_cores_per_pkg; ++core_no) { 1948c98d5d94SLen Brown for (thread_no = 0; thread_no < 1949c98d5d94SLen Brown topo.num_threads_per_core; ++thread_no) { 1950c98d5d94SLen Brown struct thread_data *t, *t2; 1951c98d5d94SLen Brown struct core_data *c, *c2; 1952c98d5d94SLen Brown struct pkg_data *p, *p2; 1953c98d5d94SLen Brown 1954c98d5d94SLen Brown t = GET_THREAD(thread_base, thread_no, core_no, pkg_no); 1955c98d5d94SLen Brown 1956c98d5d94SLen Brown if (cpu_is_not_present(t->cpu_id)) 1957c98d5d94SLen Brown continue; 1958c98d5d94SLen Brown 1959c98d5d94SLen Brown t2 = GET_THREAD(thread_base2, thread_no, core_no, pkg_no); 1960c98d5d94SLen Brown 1961c98d5d94SLen Brown c = GET_CORE(core_base, core_no, pkg_no); 1962c98d5d94SLen Brown c2 = GET_CORE(core_base2, core_no, pkg_no); 1963c98d5d94SLen Brown 1964c98d5d94SLen Brown p = GET_PKG(pkg_base, pkg_no); 1965c98d5d94SLen Brown p2 = GET_PKG(pkg_base2, pkg_no); 1966c98d5d94SLen Brown 1967c98d5d94SLen Brown retval = func(t, c, p, t2, c2, p2); 1968c98d5d94SLen Brown if (retval) 1969c98d5d94SLen Brown return retval; 1970c98d5d94SLen Brown } 1971c98d5d94SLen Brown } 1972c98d5d94SLen Brown } 1973c98d5d94SLen Brown return 0; 1974c98d5d94SLen Brown } 1975c98d5d94SLen Brown 1976c98d5d94SLen Brown /* 1977c98d5d94SLen Brown * run func(cpu) on every cpu in /proc/stat 1978c98d5d94SLen Brown * return max_cpu number 1979c98d5d94SLen Brown */ 1980c98d5d94SLen Brown int for_all_proc_cpus(int (func)(int)) 1981103a8feaSLen Brown { 1982103a8feaSLen Brown FILE *fp; 1983c98d5d94SLen Brown int cpu_num; 1984103a8feaSLen Brown int retval; 1985103a8feaSLen Brown 198657a42a34SJosh Triplett fp = fopen_or_die(proc_stat, "r"); 1987103a8feaSLen Brown 1988103a8feaSLen Brown retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n"); 1989b2c95d90SJosh Triplett if (retval != 0) 1990b2c95d90SJosh Triplett err(1, "%s: failed to parse format", proc_stat); 1991103a8feaSLen Brown 1992c98d5d94SLen Brown while (1) { 1993c98d5d94SLen Brown retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num); 1994103a8feaSLen Brown if (retval != 1) 1995103a8feaSLen Brown break; 1996103a8feaSLen Brown 1997c98d5d94SLen Brown retval = func(cpu_num); 1998c98d5d94SLen Brown if (retval) { 1999c98d5d94SLen Brown fclose(fp); 2000c98d5d94SLen Brown return(retval); 2001c98d5d94SLen Brown } 2002103a8feaSLen Brown } 2003103a8feaSLen Brown fclose(fp); 2004c98d5d94SLen Brown return 0; 2005103a8feaSLen Brown } 2006103a8feaSLen Brown 2007103a8feaSLen Brown void re_initialize(void) 2008103a8feaSLen Brown { 2009c98d5d94SLen Brown free_all_buffers(); 2010c98d5d94SLen Brown setup_all_buffers(); 2011c98d5d94SLen Brown printf("turbostat: re-initialized with num_cpus %d\n", topo.num_cpus); 2012103a8feaSLen Brown } 2013103a8feaSLen Brown 2014c98d5d94SLen Brown 2015103a8feaSLen Brown /* 2016c98d5d94SLen Brown * count_cpus() 2017c98d5d94SLen Brown * remember the last one seen, it will be the max 2018103a8feaSLen Brown */ 2019c98d5d94SLen Brown int count_cpus(int cpu) 2020103a8feaSLen Brown { 2021c98d5d94SLen Brown if (topo.max_cpu_num < cpu) 2022c98d5d94SLen Brown topo.max_cpu_num = cpu; 2023103a8feaSLen Brown 2024c98d5d94SLen Brown topo.num_cpus += 1; 2025c98d5d94SLen Brown return 0; 2026103a8feaSLen Brown } 2027c98d5d94SLen Brown int mark_cpu_present(int cpu) 2028c98d5d94SLen Brown { 2029c98d5d94SLen Brown CPU_SET_S(cpu, cpu_present_setsize, cpu_present_set); 203015aaa346SLen Brown return 0; 2031103a8feaSLen Brown } 2032103a8feaSLen Brown 2033562a2d37SLen Brown /* 2034562a2d37SLen Brown * snapshot_proc_interrupts() 2035562a2d37SLen Brown * 2036562a2d37SLen Brown * read and record summary of /proc/interrupts 2037562a2d37SLen Brown * 2038562a2d37SLen Brown * return 1 if config change requires a restart, else return 0 2039562a2d37SLen Brown */ 2040562a2d37SLen Brown int snapshot_proc_interrupts(void) 2041562a2d37SLen Brown { 2042562a2d37SLen Brown static FILE *fp; 2043562a2d37SLen Brown int column, retval; 2044562a2d37SLen Brown 2045562a2d37SLen Brown if (fp == NULL) 2046562a2d37SLen Brown fp = fopen_or_die("/proc/interrupts", "r"); 2047562a2d37SLen Brown else 2048562a2d37SLen Brown rewind(fp); 2049562a2d37SLen Brown 2050562a2d37SLen Brown /* read 1st line of /proc/interrupts to get cpu* name for each column */ 2051562a2d37SLen Brown for (column = 0; column < topo.num_cpus; ++column) { 2052562a2d37SLen Brown int cpu_number; 2053562a2d37SLen Brown 2054562a2d37SLen Brown retval = fscanf(fp, " CPU%d", &cpu_number); 2055562a2d37SLen Brown if (retval != 1) 2056562a2d37SLen Brown break; 2057562a2d37SLen Brown 2058562a2d37SLen Brown if (cpu_number > topo.max_cpu_num) { 2059562a2d37SLen Brown warn("/proc/interrupts: cpu%d: > %d", cpu_number, topo.max_cpu_num); 2060562a2d37SLen Brown return 1; 2061562a2d37SLen Brown } 2062562a2d37SLen Brown 2063562a2d37SLen Brown irq_column_2_cpu[column] = cpu_number; 2064562a2d37SLen Brown irqs_per_cpu[cpu_number] = 0; 2065562a2d37SLen Brown } 2066562a2d37SLen Brown 2067562a2d37SLen Brown /* read /proc/interrupt count lines and sum up irqs per cpu */ 2068562a2d37SLen Brown while (1) { 2069562a2d37SLen Brown int column; 2070562a2d37SLen Brown char buf[64]; 2071562a2d37SLen Brown 2072562a2d37SLen Brown retval = fscanf(fp, " %s:", buf); /* flush irq# "N:" */ 2073562a2d37SLen Brown if (retval != 1) 2074562a2d37SLen Brown break; 2075562a2d37SLen Brown 2076562a2d37SLen Brown /* read the count per cpu */ 2077562a2d37SLen Brown for (column = 0; column < topo.num_cpus; ++column) { 2078562a2d37SLen Brown 2079562a2d37SLen Brown int cpu_number, irq_count; 2080562a2d37SLen Brown 2081562a2d37SLen Brown retval = fscanf(fp, " %d", &irq_count); 2082562a2d37SLen Brown if (retval != 1) 2083562a2d37SLen Brown break; 2084562a2d37SLen Brown 2085562a2d37SLen Brown cpu_number = irq_column_2_cpu[column]; 2086562a2d37SLen Brown irqs_per_cpu[cpu_number] += irq_count; 2087562a2d37SLen Brown 2088562a2d37SLen Brown } 2089562a2d37SLen Brown 2090562a2d37SLen Brown while (getc(fp) != '\n') 2091562a2d37SLen Brown ; /* flush interrupt description */ 2092562a2d37SLen Brown 2093562a2d37SLen Brown } 2094562a2d37SLen Brown return 0; 2095562a2d37SLen Brown } 209627d47356SLen Brown /* 2097fdf676e5SLen Brown * snapshot_gfx_rc6_ms() 2098fdf676e5SLen Brown * 2099fdf676e5SLen Brown * record snapshot of 2100fdf676e5SLen Brown * /sys/class/drm/card0/power/rc6_residency_ms 2101fdf676e5SLen Brown * 2102fdf676e5SLen Brown * return 1 if config change requires a restart, else return 0 2103fdf676e5SLen Brown */ 2104fdf676e5SLen Brown int snapshot_gfx_rc6_ms(void) 2105fdf676e5SLen Brown { 2106fdf676e5SLen Brown FILE *fp; 2107fdf676e5SLen Brown int retval; 2108fdf676e5SLen Brown 2109fdf676e5SLen Brown fp = fopen_or_die("/sys/class/drm/card0/power/rc6_residency_ms", "r"); 2110fdf676e5SLen Brown 2111fdf676e5SLen Brown retval = fscanf(fp, "%lld", &gfx_cur_rc6_ms); 2112fdf676e5SLen Brown if (retval != 1) 2113fdf676e5SLen Brown err(1, "GFX rc6"); 2114fdf676e5SLen Brown 2115fdf676e5SLen Brown fclose(fp); 2116fdf676e5SLen Brown 2117fdf676e5SLen Brown return 0; 2118fdf676e5SLen Brown } 2119fdf676e5SLen Brown /* 212027d47356SLen Brown * snapshot_gfx_mhz() 212127d47356SLen Brown * 212227d47356SLen Brown * record snapshot of 212327d47356SLen Brown * /sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz 212427d47356SLen Brown * 212527d47356SLen Brown * return 1 if config change requires a restart, else return 0 212627d47356SLen Brown */ 212727d47356SLen Brown int snapshot_gfx_mhz(void) 212827d47356SLen Brown { 212927d47356SLen Brown static FILE *fp; 213027d47356SLen Brown int retval; 213127d47356SLen Brown 213227d47356SLen Brown if (fp == NULL) 213327d47356SLen Brown fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", "r"); 213427d47356SLen Brown else 213527d47356SLen Brown rewind(fp); 213627d47356SLen Brown 213727d47356SLen Brown retval = fscanf(fp, "%d", &gfx_cur_mhz); 213827d47356SLen Brown if (retval != 1) 213927d47356SLen Brown err(1, "GFX MHz"); 214027d47356SLen Brown 214127d47356SLen Brown return 0; 214227d47356SLen Brown } 2143562a2d37SLen Brown 2144562a2d37SLen Brown /* 2145562a2d37SLen Brown * snapshot /proc and /sys files 2146562a2d37SLen Brown * 2147562a2d37SLen Brown * return 1 if configuration restart needed, else return 0 2148562a2d37SLen Brown */ 2149562a2d37SLen Brown int snapshot_proc_sysfs_files(void) 2150562a2d37SLen Brown { 2151562a2d37SLen Brown if (snapshot_proc_interrupts()) 2152562a2d37SLen Brown return 1; 2153562a2d37SLen Brown 2154fdf676e5SLen Brown if (do_gfx_rc6_ms) 2155fdf676e5SLen Brown snapshot_gfx_rc6_ms(); 2156fdf676e5SLen Brown 215727d47356SLen Brown if (do_gfx_mhz) 215827d47356SLen Brown snapshot_gfx_mhz(); 215927d47356SLen Brown 2160562a2d37SLen Brown return 0; 2161562a2d37SLen Brown } 2162562a2d37SLen Brown 2163103a8feaSLen Brown void turbostat_loop() 2164103a8feaSLen Brown { 2165c98d5d94SLen Brown int retval; 2166e52966c0SLen Brown int restarted = 0; 2167c98d5d94SLen Brown 2168103a8feaSLen Brown restart: 2169e52966c0SLen Brown restarted++; 2170e52966c0SLen Brown 2171562a2d37SLen Brown snapshot_proc_sysfs_files(); 2172c98d5d94SLen Brown retval = for_all_cpus(get_counters, EVEN_COUNTERS); 2173d91bb17cSLen Brown if (retval < -1) { 2174d91bb17cSLen Brown exit(retval); 2175d91bb17cSLen Brown } else if (retval == -1) { 2176e52966c0SLen Brown if (restarted > 1) { 2177e52966c0SLen Brown exit(retval); 2178e52966c0SLen Brown } 2179c98d5d94SLen Brown re_initialize(); 2180c98d5d94SLen Brown goto restart; 2181c98d5d94SLen Brown } 2182e52966c0SLen Brown restarted = 0; 2183103a8feaSLen Brown gettimeofday(&tv_even, (struct timezone *)NULL); 2184103a8feaSLen Brown 2185103a8feaSLen Brown while (1) { 2186c98d5d94SLen Brown if (for_all_proc_cpus(cpu_is_not_present)) { 2187103a8feaSLen Brown re_initialize(); 2188103a8feaSLen Brown goto restart; 2189103a8feaSLen Brown } 21902a0609c0SLen Brown nanosleep(&interval_ts, NULL); 2191562a2d37SLen Brown if (snapshot_proc_sysfs_files()) 2192562a2d37SLen Brown goto restart; 2193c98d5d94SLen Brown retval = for_all_cpus(get_counters, ODD_COUNTERS); 2194d91bb17cSLen Brown if (retval < -1) { 2195d91bb17cSLen Brown exit(retval); 2196d91bb17cSLen Brown } else if (retval == -1) { 219715aaa346SLen Brown re_initialize(); 219815aaa346SLen Brown goto restart; 219915aaa346SLen Brown } 2200103a8feaSLen Brown gettimeofday(&tv_odd, (struct timezone *)NULL); 2201103a8feaSLen Brown timersub(&tv_odd, &tv_even, &tv_delta); 2202ba3dec99SLen Brown if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS)) { 2203ba3dec99SLen Brown re_initialize(); 2204ba3dec99SLen Brown goto restart; 2205ba3dec99SLen Brown } 2206c98d5d94SLen Brown compute_average(EVEN_COUNTERS); 2207c98d5d94SLen Brown format_all_counters(EVEN_COUNTERS); 2208b7d8c148SLen Brown flush_output_stdout(); 22092a0609c0SLen Brown nanosleep(&interval_ts, NULL); 2210562a2d37SLen Brown if (snapshot_proc_sysfs_files()) 2211562a2d37SLen Brown goto restart; 2212c98d5d94SLen Brown retval = for_all_cpus(get_counters, EVEN_COUNTERS); 2213d91bb17cSLen Brown if (retval < -1) { 2214d91bb17cSLen Brown exit(retval); 2215d91bb17cSLen Brown } else if (retval == -1) { 2216103a8feaSLen Brown re_initialize(); 2217103a8feaSLen Brown goto restart; 2218103a8feaSLen Brown } 2219103a8feaSLen Brown gettimeofday(&tv_even, (struct timezone *)NULL); 2220103a8feaSLen Brown timersub(&tv_even, &tv_odd, &tv_delta); 2221ba3dec99SLen Brown if (for_all_cpus_2(delta_cpu, EVEN_COUNTERS, ODD_COUNTERS)) { 2222ba3dec99SLen Brown re_initialize(); 2223ba3dec99SLen Brown goto restart; 2224ba3dec99SLen Brown } 2225c98d5d94SLen Brown compute_average(ODD_COUNTERS); 2226c98d5d94SLen Brown format_all_counters(ODD_COUNTERS); 2227b7d8c148SLen Brown flush_output_stdout(); 2228103a8feaSLen Brown } 2229103a8feaSLen Brown } 2230103a8feaSLen Brown 2231103a8feaSLen Brown void check_dev_msr() 2232103a8feaSLen Brown { 2233103a8feaSLen Brown struct stat sb; 22347ce7d5deSPrarit Bhargava char pathname[32]; 2235103a8feaSLen Brown 22367ce7d5deSPrarit Bhargava sprintf(pathname, "/dev/cpu/%d/msr", base_cpu); 22377ce7d5deSPrarit Bhargava if (stat(pathname, &sb)) 2238a21d38c8SLen Brown if (system("/sbin/modprobe msr > /dev/null 2>&1")) 2239d7899447SLen Brown err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" "); 2240103a8feaSLen Brown } 2241103a8feaSLen Brown 224298481e79SLen Brown void check_permissions() 2243103a8feaSLen Brown { 224498481e79SLen Brown struct __user_cap_header_struct cap_header_data; 224598481e79SLen Brown cap_user_header_t cap_header = &cap_header_data; 224698481e79SLen Brown struct __user_cap_data_struct cap_data_data; 224798481e79SLen Brown cap_user_data_t cap_data = &cap_data_data; 224898481e79SLen Brown extern int capget(cap_user_header_t hdrp, cap_user_data_t datap); 224998481e79SLen Brown int do_exit = 0; 22507ce7d5deSPrarit Bhargava char pathname[32]; 225198481e79SLen Brown 225298481e79SLen Brown /* check for CAP_SYS_RAWIO */ 225398481e79SLen Brown cap_header->pid = getpid(); 225498481e79SLen Brown cap_header->version = _LINUX_CAPABILITY_VERSION; 225598481e79SLen Brown if (capget(cap_header, cap_data) < 0) 225698481e79SLen Brown err(-6, "capget(2) failed"); 225798481e79SLen Brown 225898481e79SLen Brown if ((cap_data->effective & (1 << CAP_SYS_RAWIO)) == 0) { 225998481e79SLen Brown do_exit++; 226098481e79SLen Brown warnx("capget(CAP_SYS_RAWIO) failed," 226198481e79SLen Brown " try \"# setcap cap_sys_rawio=ep %s\"", progname); 226298481e79SLen Brown } 226398481e79SLen Brown 226498481e79SLen Brown /* test file permissions */ 22657ce7d5deSPrarit Bhargava sprintf(pathname, "/dev/cpu/%d/msr", base_cpu); 22667ce7d5deSPrarit Bhargava if (euidaccess(pathname, R_OK)) { 226798481e79SLen Brown do_exit++; 226898481e79SLen Brown warn("/dev/cpu/0/msr open failed, try chown or chmod +r /dev/cpu/*/msr"); 226998481e79SLen Brown } 227098481e79SLen Brown 227198481e79SLen Brown /* if all else fails, thell them to be root */ 227298481e79SLen Brown if (do_exit) 2273b2c95d90SJosh Triplett if (getuid() != 0) 2274d7899447SLen Brown warnx("... or simply run as root"); 227598481e79SLen Brown 227698481e79SLen Brown if (do_exit) 227798481e79SLen Brown exit(-6); 2278103a8feaSLen Brown } 2279103a8feaSLen Brown 2280d7899447SLen Brown /* 2281d7899447SLen Brown * NHM adds support for additional MSRs: 2282d7899447SLen Brown * 2283d7899447SLen Brown * MSR_SMI_COUNT 0x00000034 2284d7899447SLen Brown * 2285ec0adc53SLen Brown * MSR_PLATFORM_INFO 0x000000ce 2286d7899447SLen Brown * MSR_NHM_SNB_PKG_CST_CFG_CTL 0x000000e2 2287d7899447SLen Brown * 2288d7899447SLen Brown * MSR_PKG_C3_RESIDENCY 0x000003f8 2289d7899447SLen Brown * MSR_PKG_C6_RESIDENCY 0x000003f9 2290d7899447SLen Brown * MSR_CORE_C3_RESIDENCY 0x000003fc 2291d7899447SLen Brown * MSR_CORE_C6_RESIDENCY 0x000003fd 2292d7899447SLen Brown * 2293ee7e38e3SLen Brown * Side effect: 2294ee7e38e3SLen Brown * sets global pkg_cstate_limit to decode MSR_NHM_SNB_PKG_CST_CFG_CTL 2295d7899447SLen Brown */ 2296ee7e38e3SLen Brown int probe_nhm_msrs(unsigned int family, unsigned int model) 2297103a8feaSLen Brown { 2298ee7e38e3SLen Brown unsigned long long msr; 229921ed5574SLen Brown unsigned int base_ratio; 2300ee7e38e3SLen Brown int *pkg_cstate_limits; 2301ee7e38e3SLen Brown 2302103a8feaSLen Brown if (!genuine_intel) 2303103a8feaSLen Brown return 0; 2304103a8feaSLen Brown 2305103a8feaSLen Brown if (family != 6) 2306103a8feaSLen Brown return 0; 2307103a8feaSLen Brown 230821ed5574SLen Brown bclk = discover_bclk(family, model); 230921ed5574SLen Brown 2310103a8feaSLen Brown switch (model) { 2311869ce69eSLen Brown case INTEL_FAM6_NEHALEM_EP: /* Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP */ 2312869ce69eSLen Brown case INTEL_FAM6_NEHALEM: /* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */ 2313103a8feaSLen Brown case 0x1F: /* Core i7 and i5 Processor - Nehalem */ 2314869ce69eSLen Brown case INTEL_FAM6_WESTMERE: /* Westmere Client - Clarkdale, Arrandale */ 2315869ce69eSLen Brown case INTEL_FAM6_WESTMERE_EP: /* Westmere EP - Gulftown */ 2316869ce69eSLen Brown case INTEL_FAM6_NEHALEM_EX: /* Nehalem-EX Xeon - Beckton */ 2317869ce69eSLen Brown case INTEL_FAM6_WESTMERE_EX: /* Westmere-EX Xeon - Eagleton */ 2318ee7e38e3SLen Brown pkg_cstate_limits = nhm_pkg_cstate_limits; 2319ee7e38e3SLen Brown break; 2320869ce69eSLen Brown case INTEL_FAM6_SANDYBRIDGE: /* SNB */ 2321869ce69eSLen Brown case INTEL_FAM6_SANDYBRIDGE_X: /* SNB Xeon */ 2322869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE: /* IVB */ 2323869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */ 2324ee7e38e3SLen Brown pkg_cstate_limits = snb_pkg_cstate_limits; 2325ee7e38e3SLen Brown break; 2326869ce69eSLen Brown case INTEL_FAM6_HASWELL_CORE: /* HSW */ 2327869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSX */ 2328869ce69eSLen Brown case INTEL_FAM6_HASWELL_ULT: /* HSW */ 2329869ce69eSLen Brown case INTEL_FAM6_HASWELL_GT3E: /* HSW */ 2330869ce69eSLen Brown case INTEL_FAM6_BROADWELL_CORE: /* BDW */ 2331869ce69eSLen Brown case INTEL_FAM6_BROADWELL_GT3E: /* BDW */ 2332869ce69eSLen Brown case INTEL_FAM6_BROADWELL_X: /* BDX */ 2333869ce69eSLen Brown case INTEL_FAM6_BROADWELL_XEON_D: /* BDX-DE */ 2334869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 2335869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 2336869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 2337869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 2338ee7e38e3SLen Brown pkg_cstate_limits = hsw_pkg_cstate_limits; 2339ee7e38e3SLen Brown break; 2340d8ebb442SLen Brown case INTEL_FAM6_SKYLAKE_X: /* SKX */ 2341d8ebb442SLen Brown pkg_cstate_limits = skx_pkg_cstate_limits; 2342d8ebb442SLen Brown break; 2343869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */ 2344869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */ 2345ee7e38e3SLen Brown pkg_cstate_limits = slv_pkg_cstate_limits; 2346ee7e38e3SLen Brown break; 2347869ce69eSLen Brown case INTEL_FAM6_ATOM_AIRMONT: /* AMT */ 2348ee7e38e3SLen Brown pkg_cstate_limits = amt_pkg_cstate_limits; 2349ee7e38e3SLen Brown break; 2350869ce69eSLen Brown case INTEL_FAM6_XEON_PHI_KNL: /* PHI */ 2351005c82d6SLen Brown case INTEL_FAM6_XEON_PHI_KNM: 2352ee7e38e3SLen Brown pkg_cstate_limits = phi_pkg_cstate_limits; 2353ee7e38e3SLen Brown break; 2354869ce69eSLen Brown case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 2355869ce69eSLen Brown case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ 2356e4085d54SLen Brown pkg_cstate_limits = bxt_pkg_cstate_limits; 2357e4085d54SLen Brown break; 2358103a8feaSLen Brown default: 2359103a8feaSLen Brown return 0; 2360103a8feaSLen Brown } 23617ce7d5deSPrarit Bhargava get_msr(base_cpu, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr); 2362e9257f5fSLen Brown pkg_cstate_limit = pkg_cstate_limits[msr & 0xF]; 2363ee7e38e3SLen Brown 2364ec0adc53SLen Brown get_msr(base_cpu, MSR_PLATFORM_INFO, &msr); 236521ed5574SLen Brown base_ratio = (msr >> 8) & 0xFF; 236621ed5574SLen Brown 236721ed5574SLen Brown base_hz = base_ratio * bclk * 1000000; 236821ed5574SLen Brown has_base_hz = 1; 2369ee7e38e3SLen Brown return 1; 2370103a8feaSLen Brown } 2371d7899447SLen Brown int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model) 2372d7899447SLen Brown { 2373d7899447SLen Brown switch (model) { 2374d7899447SLen Brown /* Nehalem compatible, but do not include turbo-ratio limit support */ 2375869ce69eSLen Brown case INTEL_FAM6_NEHALEM_EX: /* Nehalem-EX Xeon - Beckton */ 2376869ce69eSLen Brown case INTEL_FAM6_WESTMERE_EX: /* Westmere-EX Xeon - Eagleton */ 2377869ce69eSLen Brown case INTEL_FAM6_XEON_PHI_KNL: /* PHI - Knights Landing (different MSR definition) */ 2378005c82d6SLen Brown case INTEL_FAM6_XEON_PHI_KNM: 2379d7899447SLen Brown return 0; 2380d7899447SLen Brown default: 2381d7899447SLen Brown return 1; 2382d7899447SLen Brown } 2383d7899447SLen Brown } 23846574a5d5SLen Brown int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model) 23856574a5d5SLen Brown { 23866574a5d5SLen Brown if (!genuine_intel) 23876574a5d5SLen Brown return 0; 23886574a5d5SLen Brown 23896574a5d5SLen Brown if (family != 6) 23906574a5d5SLen Brown return 0; 23916574a5d5SLen Brown 23926574a5d5SLen Brown switch (model) { 2393869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */ 2394869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSW Xeon */ 23956574a5d5SLen Brown return 1; 23966574a5d5SLen Brown default: 23976574a5d5SLen Brown return 0; 23986574a5d5SLen Brown } 23996574a5d5SLen Brown } 2400fcd17211SLen Brown int has_hsw_turbo_ratio_limit(unsigned int family, unsigned int model) 2401fcd17211SLen Brown { 2402fcd17211SLen Brown if (!genuine_intel) 2403fcd17211SLen Brown return 0; 2404fcd17211SLen Brown 2405fcd17211SLen Brown if (family != 6) 2406fcd17211SLen Brown return 0; 2407fcd17211SLen Brown 2408fcd17211SLen Brown switch (model) { 2409869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSW Xeon */ 2410fcd17211SLen Brown return 1; 2411fcd17211SLen Brown default: 2412fcd17211SLen Brown return 0; 2413fcd17211SLen Brown } 2414fcd17211SLen Brown } 2415fcd17211SLen Brown 2416fb5d4327SDasaratharaman Chandramouli int has_knl_turbo_ratio_limit(unsigned int family, unsigned int model) 2417fb5d4327SDasaratharaman Chandramouli { 2418fb5d4327SDasaratharaman Chandramouli if (!genuine_intel) 2419fb5d4327SDasaratharaman Chandramouli return 0; 2420fb5d4327SDasaratharaman Chandramouli 2421fb5d4327SDasaratharaman Chandramouli if (family != 6) 2422fb5d4327SDasaratharaman Chandramouli return 0; 2423fb5d4327SDasaratharaman Chandramouli 2424fb5d4327SDasaratharaman Chandramouli switch (model) { 2425869ce69eSLen Brown case INTEL_FAM6_XEON_PHI_KNL: /* Knights Landing */ 2426005c82d6SLen Brown case INTEL_FAM6_XEON_PHI_KNM: 2427fb5d4327SDasaratharaman Chandramouli return 1; 2428fb5d4327SDasaratharaman Chandramouli default: 2429fb5d4327SDasaratharaman Chandramouli return 0; 2430fb5d4327SDasaratharaman Chandramouli } 2431fb5d4327SDasaratharaman Chandramouli } 24326fb3143bSLen Brown int has_config_tdp(unsigned int family, unsigned int model) 24336fb3143bSLen Brown { 24346fb3143bSLen Brown if (!genuine_intel) 24356fb3143bSLen Brown return 0; 24366fb3143bSLen Brown 24376fb3143bSLen Brown if (family != 6) 24386fb3143bSLen Brown return 0; 24396fb3143bSLen Brown 24406fb3143bSLen Brown switch (model) { 2441869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE: /* IVB */ 2442869ce69eSLen Brown case INTEL_FAM6_HASWELL_CORE: /* HSW */ 2443869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSX */ 2444869ce69eSLen Brown case INTEL_FAM6_HASWELL_ULT: /* HSW */ 2445869ce69eSLen Brown case INTEL_FAM6_HASWELL_GT3E: /* HSW */ 2446869ce69eSLen Brown case INTEL_FAM6_BROADWELL_CORE: /* BDW */ 2447869ce69eSLen Brown case INTEL_FAM6_BROADWELL_GT3E: /* BDW */ 2448869ce69eSLen Brown case INTEL_FAM6_BROADWELL_X: /* BDX */ 2449869ce69eSLen Brown case INTEL_FAM6_BROADWELL_XEON_D: /* BDX-DE */ 2450869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 2451869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 2452869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 2453869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 2454869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_X: /* SKX */ 24556fb3143bSLen Brown 2456869ce69eSLen Brown case INTEL_FAM6_XEON_PHI_KNL: /* Knights Landing */ 2457005c82d6SLen Brown case INTEL_FAM6_XEON_PHI_KNM: 24586fb3143bSLen Brown return 1; 24596fb3143bSLen Brown default: 24606fb3143bSLen Brown return 0; 24616fb3143bSLen Brown } 24626fb3143bSLen Brown } 24636fb3143bSLen Brown 2464fcd17211SLen Brown static void 24651b69317dSColin Ian King dump_cstate_pstate_config_info(unsigned int family, unsigned int model) 2466fcd17211SLen Brown { 2467fcd17211SLen Brown if (!do_nhm_platform_info) 2468fcd17211SLen Brown return; 2469fcd17211SLen Brown 2470fcd17211SLen Brown dump_nhm_platform_info(); 2471fcd17211SLen Brown 2472fcd17211SLen Brown if (has_hsw_turbo_ratio_limit(family, model)) 2473fcd17211SLen Brown dump_hsw_turbo_ratio_limits(); 2474fcd17211SLen Brown 2475fcd17211SLen Brown if (has_ivt_turbo_ratio_limit(family, model)) 2476fcd17211SLen Brown dump_ivt_turbo_ratio_limits(); 2477fcd17211SLen Brown 2478fcd17211SLen Brown if (has_nhm_turbo_ratio_limit(family, model)) 2479fcd17211SLen Brown dump_nhm_turbo_ratio_limits(); 2480fcd17211SLen Brown 2481fb5d4327SDasaratharaman Chandramouli if (has_knl_turbo_ratio_limit(family, model)) 2482fb5d4327SDasaratharaman Chandramouli dump_knl_turbo_ratio_limits(); 2483fb5d4327SDasaratharaman Chandramouli 24846fb3143bSLen Brown if (has_config_tdp(family, model)) 24856fb3143bSLen Brown dump_config_tdp(); 24866fb3143bSLen Brown 2487fcd17211SLen Brown dump_nhm_cst_cfg(); 2488fcd17211SLen Brown } 2489fcd17211SLen Brown 24906574a5d5SLen Brown 2491889facbeSLen Brown /* 2492889facbeSLen Brown * print_epb() 2493889facbeSLen Brown * Decode the ENERGY_PERF_BIAS MSR 2494889facbeSLen Brown */ 2495889facbeSLen Brown int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p) 2496889facbeSLen Brown { 2497889facbeSLen Brown unsigned long long msr; 2498889facbeSLen Brown char *epb_string; 2499889facbeSLen Brown int cpu; 2500889facbeSLen Brown 2501889facbeSLen Brown if (!has_epb) 2502889facbeSLen Brown return 0; 2503889facbeSLen Brown 2504889facbeSLen Brown cpu = t->cpu_id; 2505889facbeSLen Brown 2506889facbeSLen Brown /* EPB is per-package */ 2507889facbeSLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 2508889facbeSLen Brown return 0; 2509889facbeSLen Brown 2510889facbeSLen Brown if (cpu_migrate(cpu)) { 2511b7d8c148SLen Brown fprintf(outf, "Could not migrate to CPU %d\n", cpu); 2512889facbeSLen Brown return -1; 2513889facbeSLen Brown } 2514889facbeSLen Brown 2515889facbeSLen Brown if (get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr)) 2516889facbeSLen Brown return 0; 2517889facbeSLen Brown 2518e9be7dd6SLen Brown switch (msr & 0xF) { 2519889facbeSLen Brown case ENERGY_PERF_BIAS_PERFORMANCE: 2520889facbeSLen Brown epb_string = "performance"; 2521889facbeSLen Brown break; 2522889facbeSLen Brown case ENERGY_PERF_BIAS_NORMAL: 2523889facbeSLen Brown epb_string = "balanced"; 2524889facbeSLen Brown break; 2525889facbeSLen Brown case ENERGY_PERF_BIAS_POWERSAVE: 2526889facbeSLen Brown epb_string = "powersave"; 2527889facbeSLen Brown break; 2528889facbeSLen Brown default: 2529889facbeSLen Brown epb_string = "custom"; 2530889facbeSLen Brown break; 2531889facbeSLen Brown } 2532b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_ENERGY_PERF_BIAS: 0x%08llx (%s)\n", cpu, msr, epb_string); 2533889facbeSLen Brown 2534889facbeSLen Brown return 0; 2535889facbeSLen Brown } 25367f5c258eSLen Brown /* 25377f5c258eSLen Brown * print_hwp() 25387f5c258eSLen Brown * Decode the MSR_HWP_CAPABILITIES 25397f5c258eSLen Brown */ 25407f5c258eSLen Brown int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p) 25417f5c258eSLen Brown { 25427f5c258eSLen Brown unsigned long long msr; 25437f5c258eSLen Brown int cpu; 25447f5c258eSLen Brown 25457f5c258eSLen Brown if (!has_hwp) 25467f5c258eSLen Brown return 0; 25477f5c258eSLen Brown 25487f5c258eSLen Brown cpu = t->cpu_id; 25497f5c258eSLen Brown 25507f5c258eSLen Brown /* MSR_HWP_CAPABILITIES is per-package */ 25517f5c258eSLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 25527f5c258eSLen Brown return 0; 25537f5c258eSLen Brown 25547f5c258eSLen Brown if (cpu_migrate(cpu)) { 2555b7d8c148SLen Brown fprintf(outf, "Could not migrate to CPU %d\n", cpu); 25567f5c258eSLen Brown return -1; 25577f5c258eSLen Brown } 25587f5c258eSLen Brown 25597f5c258eSLen Brown if (get_msr(cpu, MSR_PM_ENABLE, &msr)) 25607f5c258eSLen Brown return 0; 25617f5c258eSLen Brown 2562b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PM_ENABLE: 0x%08llx (%sHWP)\n", 25637f5c258eSLen Brown cpu, msr, (msr & (1 << 0)) ? "" : "No-"); 25647f5c258eSLen Brown 25657f5c258eSLen Brown /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */ 25667f5c258eSLen Brown if ((msr & (1 << 0)) == 0) 25677f5c258eSLen Brown return 0; 25687f5c258eSLen Brown 25697f5c258eSLen Brown if (get_msr(cpu, MSR_HWP_CAPABILITIES, &msr)) 25707f5c258eSLen Brown return 0; 25717f5c258eSLen Brown 2572b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_HWP_CAPABILITIES: 0x%08llx " 25737f5c258eSLen Brown "(high 0x%x guar 0x%x eff 0x%x low 0x%x)\n", 25747f5c258eSLen Brown cpu, msr, 25757f5c258eSLen Brown (unsigned int)HWP_HIGHEST_PERF(msr), 25767f5c258eSLen Brown (unsigned int)HWP_GUARANTEED_PERF(msr), 25777f5c258eSLen Brown (unsigned int)HWP_MOSTEFFICIENT_PERF(msr), 25787f5c258eSLen Brown (unsigned int)HWP_LOWEST_PERF(msr)); 25797f5c258eSLen Brown 25807f5c258eSLen Brown if (get_msr(cpu, MSR_HWP_REQUEST, &msr)) 25817f5c258eSLen Brown return 0; 25827f5c258eSLen Brown 2583b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_HWP_REQUEST: 0x%08llx " 25847f5c258eSLen Brown "(min 0x%x max 0x%x des 0x%x epp 0x%x window 0x%x pkg 0x%x)\n", 25857f5c258eSLen Brown cpu, msr, 25867f5c258eSLen Brown (unsigned int)(((msr) >> 0) & 0xff), 25877f5c258eSLen Brown (unsigned int)(((msr) >> 8) & 0xff), 25887f5c258eSLen Brown (unsigned int)(((msr) >> 16) & 0xff), 25897f5c258eSLen Brown (unsigned int)(((msr) >> 24) & 0xff), 25907f5c258eSLen Brown (unsigned int)(((msr) >> 32) & 0xff3), 25917f5c258eSLen Brown (unsigned int)(((msr) >> 42) & 0x1)); 25927f5c258eSLen Brown 25937f5c258eSLen Brown if (has_hwp_pkg) { 25947f5c258eSLen Brown if (get_msr(cpu, MSR_HWP_REQUEST_PKG, &msr)) 25957f5c258eSLen Brown return 0; 25967f5c258eSLen Brown 2597b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_HWP_REQUEST_PKG: 0x%08llx " 25987f5c258eSLen Brown "(min 0x%x max 0x%x des 0x%x epp 0x%x window 0x%x)\n", 25997f5c258eSLen Brown cpu, msr, 26007f5c258eSLen Brown (unsigned int)(((msr) >> 0) & 0xff), 26017f5c258eSLen Brown (unsigned int)(((msr) >> 8) & 0xff), 26027f5c258eSLen Brown (unsigned int)(((msr) >> 16) & 0xff), 26037f5c258eSLen Brown (unsigned int)(((msr) >> 24) & 0xff), 26047f5c258eSLen Brown (unsigned int)(((msr) >> 32) & 0xff3)); 26057f5c258eSLen Brown } 26067f5c258eSLen Brown if (has_hwp_notify) { 26077f5c258eSLen Brown if (get_msr(cpu, MSR_HWP_INTERRUPT, &msr)) 26087f5c258eSLen Brown return 0; 26097f5c258eSLen Brown 2610b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_HWP_INTERRUPT: 0x%08llx " 26117f5c258eSLen Brown "(%s_Guaranteed_Perf_Change, %s_Excursion_Min)\n", 26127f5c258eSLen Brown cpu, msr, 26137f5c258eSLen Brown ((msr) & 0x1) ? "EN" : "Dis", 26147f5c258eSLen Brown ((msr) & 0x2) ? "EN" : "Dis"); 26157f5c258eSLen Brown } 26167f5c258eSLen Brown if (get_msr(cpu, MSR_HWP_STATUS, &msr)) 26177f5c258eSLen Brown return 0; 26187f5c258eSLen Brown 2619b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_HWP_STATUS: 0x%08llx " 26207f5c258eSLen Brown "(%sGuaranteed_Perf_Change, %sExcursion_Min)\n", 26217f5c258eSLen Brown cpu, msr, 26227f5c258eSLen Brown ((msr) & 0x1) ? "" : "No-", 26237f5c258eSLen Brown ((msr) & 0x2) ? "" : "No-"); 2624889facbeSLen Brown 2625889facbeSLen Brown return 0; 2626889facbeSLen Brown } 2627889facbeSLen Brown 26283a9a941dSLen Brown /* 26293a9a941dSLen Brown * print_perf_limit() 26303a9a941dSLen Brown */ 26313a9a941dSLen Brown int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data *p) 26323a9a941dSLen Brown { 26333a9a941dSLen Brown unsigned long long msr; 26343a9a941dSLen Brown int cpu; 26353a9a941dSLen Brown 26363a9a941dSLen Brown cpu = t->cpu_id; 26373a9a941dSLen Brown 26383a9a941dSLen Brown /* per-package */ 26393a9a941dSLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 26403a9a941dSLen Brown return 0; 26413a9a941dSLen Brown 26423a9a941dSLen Brown if (cpu_migrate(cpu)) { 2643b7d8c148SLen Brown fprintf(outf, "Could not migrate to CPU %d\n", cpu); 26443a9a941dSLen Brown return -1; 26453a9a941dSLen Brown } 26463a9a941dSLen Brown 26473a9a941dSLen Brown if (do_core_perf_limit_reasons) { 26483a9a941dSLen Brown get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr); 2649b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); 2650b7d8c148SLen Brown fprintf(outf, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)", 2651e33cbe85SLen Brown (msr & 1 << 15) ? "bit15, " : "", 26523a9a941dSLen Brown (msr & 1 << 14) ? "bit14, " : "", 2653e33cbe85SLen Brown (msr & 1 << 13) ? "Transitions, " : "", 2654e33cbe85SLen Brown (msr & 1 << 12) ? "MultiCoreTurbo, " : "", 2655e33cbe85SLen Brown (msr & 1 << 11) ? "PkgPwrL2, " : "", 2656e33cbe85SLen Brown (msr & 1 << 10) ? "PkgPwrL1, " : "", 2657e33cbe85SLen Brown (msr & 1 << 9) ? "CorePwr, " : "", 2658e33cbe85SLen Brown (msr & 1 << 8) ? "Amps, " : "", 2659e33cbe85SLen Brown (msr & 1 << 6) ? "VR-Therm, " : "", 2660e33cbe85SLen Brown (msr & 1 << 5) ? "Auto-HWP, " : "", 2661e33cbe85SLen Brown (msr & 1 << 4) ? "Graphics, " : "", 2662e33cbe85SLen Brown (msr & 1 << 2) ? "bit2, " : "", 2663e33cbe85SLen Brown (msr & 1 << 1) ? "ThermStatus, " : "", 2664e33cbe85SLen Brown (msr & 1 << 0) ? "PROCHOT, " : ""); 2665b7d8c148SLen Brown fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n", 2666e33cbe85SLen Brown (msr & 1 << 31) ? "bit31, " : "", 26673a9a941dSLen Brown (msr & 1 << 30) ? "bit30, " : "", 2668e33cbe85SLen Brown (msr & 1 << 29) ? "Transitions, " : "", 2669e33cbe85SLen Brown (msr & 1 << 28) ? "MultiCoreTurbo, " : "", 2670e33cbe85SLen Brown (msr & 1 << 27) ? "PkgPwrL2, " : "", 2671e33cbe85SLen Brown (msr & 1 << 26) ? "PkgPwrL1, " : "", 2672e33cbe85SLen Brown (msr & 1 << 25) ? "CorePwr, " : "", 2673e33cbe85SLen Brown (msr & 1 << 24) ? "Amps, " : "", 2674e33cbe85SLen Brown (msr & 1 << 22) ? "VR-Therm, " : "", 2675e33cbe85SLen Brown (msr & 1 << 21) ? "Auto-HWP, " : "", 2676e33cbe85SLen Brown (msr & 1 << 20) ? "Graphics, " : "", 2677e33cbe85SLen Brown (msr & 1 << 18) ? "bit18, " : "", 2678e33cbe85SLen Brown (msr & 1 << 17) ? "ThermStatus, " : "", 2679e33cbe85SLen Brown (msr & 1 << 16) ? "PROCHOT, " : ""); 26803a9a941dSLen Brown 26813a9a941dSLen Brown } 26823a9a941dSLen Brown if (do_gfx_perf_limit_reasons) { 26833a9a941dSLen Brown get_msr(cpu, MSR_GFX_PERF_LIMIT_REASONS, &msr); 2684b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_GFX_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); 2685b7d8c148SLen Brown fprintf(outf, " (Active: %s%s%s%s%s%s%s%s)", 26863a9a941dSLen Brown (msr & 1 << 0) ? "PROCHOT, " : "", 26873a9a941dSLen Brown (msr & 1 << 1) ? "ThermStatus, " : "", 26883a9a941dSLen Brown (msr & 1 << 4) ? "Graphics, " : "", 26893a9a941dSLen Brown (msr & 1 << 6) ? "VR-Therm, " : "", 26903a9a941dSLen Brown (msr & 1 << 8) ? "Amps, " : "", 26913a9a941dSLen Brown (msr & 1 << 9) ? "GFXPwr, " : "", 26923a9a941dSLen Brown (msr & 1 << 10) ? "PkgPwrL1, " : "", 26933a9a941dSLen Brown (msr & 1 << 11) ? "PkgPwrL2, " : ""); 2694b7d8c148SLen Brown fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s)\n", 26953a9a941dSLen Brown (msr & 1 << 16) ? "PROCHOT, " : "", 26963a9a941dSLen Brown (msr & 1 << 17) ? "ThermStatus, " : "", 26973a9a941dSLen Brown (msr & 1 << 20) ? "Graphics, " : "", 26983a9a941dSLen Brown (msr & 1 << 22) ? "VR-Therm, " : "", 26993a9a941dSLen Brown (msr & 1 << 24) ? "Amps, " : "", 27003a9a941dSLen Brown (msr & 1 << 25) ? "GFXPwr, " : "", 27013a9a941dSLen Brown (msr & 1 << 26) ? "PkgPwrL1, " : "", 27023a9a941dSLen Brown (msr & 1 << 27) ? "PkgPwrL2, " : ""); 27033a9a941dSLen Brown } 27043a9a941dSLen Brown if (do_ring_perf_limit_reasons) { 27053a9a941dSLen Brown get_msr(cpu, MSR_RING_PERF_LIMIT_REASONS, &msr); 2706b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_RING_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); 2707b7d8c148SLen Brown fprintf(outf, " (Active: %s%s%s%s%s%s)", 27083a9a941dSLen Brown (msr & 1 << 0) ? "PROCHOT, " : "", 27093a9a941dSLen Brown (msr & 1 << 1) ? "ThermStatus, " : "", 27103a9a941dSLen Brown (msr & 1 << 6) ? "VR-Therm, " : "", 27113a9a941dSLen Brown (msr & 1 << 8) ? "Amps, " : "", 27123a9a941dSLen Brown (msr & 1 << 10) ? "PkgPwrL1, " : "", 27133a9a941dSLen Brown (msr & 1 << 11) ? "PkgPwrL2, " : ""); 2714b7d8c148SLen Brown fprintf(outf, " (Logged: %s%s%s%s%s%s)\n", 27153a9a941dSLen Brown (msr & 1 << 16) ? "PROCHOT, " : "", 27163a9a941dSLen Brown (msr & 1 << 17) ? "ThermStatus, " : "", 27173a9a941dSLen Brown (msr & 1 << 22) ? "VR-Therm, " : "", 27183a9a941dSLen Brown (msr & 1 << 24) ? "Amps, " : "", 27193a9a941dSLen Brown (msr & 1 << 26) ? "PkgPwrL1, " : "", 27203a9a941dSLen Brown (msr & 1 << 27) ? "PkgPwrL2, " : ""); 27213a9a941dSLen Brown } 27223a9a941dSLen Brown return 0; 27233a9a941dSLen Brown } 27243a9a941dSLen Brown 2725889facbeSLen Brown #define RAPL_POWER_GRANULARITY 0x7FFF /* 15 bit power granularity */ 2726889facbeSLen Brown #define RAPL_TIME_GRANULARITY 0x3F /* 6 bit time granularity */ 2727889facbeSLen Brown 27281b69317dSColin Ian King double get_tdp(unsigned int model) 2729144b44b1SLen Brown { 2730144b44b1SLen Brown unsigned long long msr; 2731144b44b1SLen Brown 2732144b44b1SLen Brown if (do_rapl & RAPL_PKG_POWER_INFO) 27337ce7d5deSPrarit Bhargava if (!get_msr(base_cpu, MSR_PKG_POWER_INFO, &msr)) 2734144b44b1SLen Brown return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units; 2735144b44b1SLen Brown 2736144b44b1SLen Brown switch (model) { 2737869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT1: 2738869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT2: 2739144b44b1SLen Brown return 30.0; 2740144b44b1SLen Brown default: 2741144b44b1SLen Brown return 135.0; 2742144b44b1SLen Brown } 2743144b44b1SLen Brown } 2744144b44b1SLen Brown 274540ee8e3bSAndrey Semin /* 274640ee8e3bSAndrey Semin * rapl_dram_energy_units_probe() 274740ee8e3bSAndrey Semin * Energy units are either hard-coded, or come from RAPL Energy Unit MSR. 274840ee8e3bSAndrey Semin */ 274940ee8e3bSAndrey Semin static double 275040ee8e3bSAndrey Semin rapl_dram_energy_units_probe(int model, double rapl_energy_units) 275140ee8e3bSAndrey Semin { 275240ee8e3bSAndrey Semin /* only called for genuine_intel, family 6 */ 275340ee8e3bSAndrey Semin 275440ee8e3bSAndrey Semin switch (model) { 2755869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSX */ 2756869ce69eSLen Brown case INTEL_FAM6_BROADWELL_X: /* BDX */ 2757869ce69eSLen Brown case INTEL_FAM6_BROADWELL_XEON_D: /* BDX-DE */ 2758869ce69eSLen Brown case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ 2759005c82d6SLen Brown case INTEL_FAM6_XEON_PHI_KNM: 276040ee8e3bSAndrey Semin return (rapl_dram_energy_units = 15.3 / 1000000); 276140ee8e3bSAndrey Semin default: 276240ee8e3bSAndrey Semin return (rapl_energy_units); 276340ee8e3bSAndrey Semin } 276440ee8e3bSAndrey Semin } 276540ee8e3bSAndrey Semin 2766144b44b1SLen Brown 2767889facbeSLen Brown /* 2768889facbeSLen Brown * rapl_probe() 2769889facbeSLen Brown * 2770144b44b1SLen Brown * sets do_rapl, rapl_power_units, rapl_energy_units, rapl_time_units 2771889facbeSLen Brown */ 2772889facbeSLen Brown void rapl_probe(unsigned int family, unsigned int model) 2773889facbeSLen Brown { 2774889facbeSLen Brown unsigned long long msr; 2775144b44b1SLen Brown unsigned int time_unit; 2776889facbeSLen Brown double tdp; 2777889facbeSLen Brown 2778889facbeSLen Brown if (!genuine_intel) 2779889facbeSLen Brown return; 2780889facbeSLen Brown 2781889facbeSLen Brown if (family != 6) 2782889facbeSLen Brown return; 2783889facbeSLen Brown 2784889facbeSLen Brown switch (model) { 2785869ce69eSLen Brown case INTEL_FAM6_SANDYBRIDGE: 2786869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE: 2787869ce69eSLen Brown case INTEL_FAM6_HASWELL_CORE: /* HSW */ 2788869ce69eSLen Brown case INTEL_FAM6_HASWELL_ULT: /* HSW */ 2789869ce69eSLen Brown case INTEL_FAM6_HASWELL_GT3E: /* HSW */ 2790869ce69eSLen Brown case INTEL_FAM6_BROADWELL_CORE: /* BDW */ 2791869ce69eSLen Brown case INTEL_FAM6_BROADWELL_GT3E: /* BDW */ 2792144b44b1SLen Brown do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO; 2793889facbeSLen Brown break; 2794869ce69eSLen Brown case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 2795e4085d54SLen Brown do_rapl = RAPL_PKG | RAPL_PKG_POWER_INFO; 2796e4085d54SLen Brown break; 2797869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 2798869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 2799869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 2800869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 28010b2bb692SLen Brown do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO; 28020b2bb692SLen Brown break; 2803869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSX */ 2804869ce69eSLen Brown case INTEL_FAM6_BROADWELL_X: /* BDX */ 2805869ce69eSLen Brown case INTEL_FAM6_BROADWELL_XEON_D: /* BDX-DE */ 2806869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_X: /* SKX */ 2807869ce69eSLen Brown case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ 2808005c82d6SLen Brown case INTEL_FAM6_XEON_PHI_KNM: 28090b2bb692SLen Brown do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO; 2810e6f9bb3cSLen Brown break; 2811869ce69eSLen Brown case INTEL_FAM6_SANDYBRIDGE_X: 2812869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE_X: 28130b2bb692SLen 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; 2814144b44b1SLen Brown break; 2815869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */ 2816869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */ 2817144b44b1SLen Brown do_rapl = RAPL_PKG | RAPL_CORES; 2818889facbeSLen Brown break; 2819869ce69eSLen Brown case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ 28200f644909SJacob 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; 28210f644909SJacob Pan break; 2822889facbeSLen Brown default: 2823889facbeSLen Brown return; 2824889facbeSLen Brown } 2825889facbeSLen Brown 2826889facbeSLen Brown /* units on package 0, verify later other packages match */ 28277ce7d5deSPrarit Bhargava if (get_msr(base_cpu, MSR_RAPL_POWER_UNIT, &msr)) 2828889facbeSLen Brown return; 2829889facbeSLen Brown 2830889facbeSLen Brown rapl_power_units = 1.0 / (1 << (msr & 0xF)); 2831869ce69eSLen Brown if (model == INTEL_FAM6_ATOM_SILVERMONT1) 2832144b44b1SLen Brown rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000; 2833144b44b1SLen Brown else 2834889facbeSLen Brown rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F)); 2835889facbeSLen Brown 283640ee8e3bSAndrey Semin rapl_dram_energy_units = rapl_dram_energy_units_probe(model, rapl_energy_units); 283740ee8e3bSAndrey Semin 2838144b44b1SLen Brown time_unit = msr >> 16 & 0xF; 2839144b44b1SLen Brown if (time_unit == 0) 2840144b44b1SLen Brown time_unit = 0xA; 2841889facbeSLen Brown 2842144b44b1SLen Brown rapl_time_units = 1.0 / (1 << (time_unit)); 2843144b44b1SLen Brown 2844144b44b1SLen Brown tdp = get_tdp(model); 2845889facbeSLen Brown 2846889facbeSLen Brown rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp; 2847d8af6f5fSLen Brown if (debug) 2848b7d8c148SLen Brown fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp); 2849889facbeSLen Brown 2850889facbeSLen Brown return; 2851889facbeSLen Brown } 2852889facbeSLen Brown 28531b69317dSColin Ian King void perf_limit_reasons_probe(unsigned int family, unsigned int model) 28543a9a941dSLen Brown { 28553a9a941dSLen Brown if (!genuine_intel) 28563a9a941dSLen Brown return; 28573a9a941dSLen Brown 28583a9a941dSLen Brown if (family != 6) 28593a9a941dSLen Brown return; 28603a9a941dSLen Brown 28613a9a941dSLen Brown switch (model) { 2862869ce69eSLen Brown case INTEL_FAM6_HASWELL_CORE: /* HSW */ 2863869ce69eSLen Brown case INTEL_FAM6_HASWELL_ULT: /* HSW */ 2864869ce69eSLen Brown case INTEL_FAM6_HASWELL_GT3E: /* HSW */ 28653a9a941dSLen Brown do_gfx_perf_limit_reasons = 1; 2866869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSX */ 28673a9a941dSLen Brown do_core_perf_limit_reasons = 1; 28683a9a941dSLen Brown do_ring_perf_limit_reasons = 1; 28693a9a941dSLen Brown default: 28703a9a941dSLen Brown return; 28713a9a941dSLen Brown } 28723a9a941dSLen Brown } 28733a9a941dSLen Brown 2874889facbeSLen Brown int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p) 2875889facbeSLen Brown { 2876889facbeSLen Brown unsigned long long msr; 2877889facbeSLen Brown unsigned int dts; 2878889facbeSLen Brown int cpu; 2879889facbeSLen Brown 2880889facbeSLen Brown if (!(do_dts || do_ptm)) 2881889facbeSLen Brown return 0; 2882889facbeSLen Brown 2883889facbeSLen Brown cpu = t->cpu_id; 2884889facbeSLen Brown 2885889facbeSLen Brown /* DTS is per-core, no need to print for each thread */ 2886889facbeSLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 2887889facbeSLen Brown return 0; 2888889facbeSLen Brown 2889889facbeSLen Brown if (cpu_migrate(cpu)) { 2890b7d8c148SLen Brown fprintf(outf, "Could not migrate to CPU %d\n", cpu); 2891889facbeSLen Brown return -1; 2892889facbeSLen Brown } 2893889facbeSLen Brown 2894889facbeSLen Brown if (do_ptm && (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) { 2895889facbeSLen Brown if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr)) 2896889facbeSLen Brown return 0; 2897889facbeSLen Brown 2898889facbeSLen Brown dts = (msr >> 16) & 0x7F; 2899b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n", 2900889facbeSLen Brown cpu, msr, tcc_activation_temp - dts); 2901889facbeSLen Brown 2902889facbeSLen Brown #ifdef THERM_DEBUG 2903889facbeSLen Brown if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &msr)) 2904889facbeSLen Brown return 0; 2905889facbeSLen Brown 2906889facbeSLen Brown dts = (msr >> 16) & 0x7F; 2907889facbeSLen Brown dts2 = (msr >> 8) & 0x7F; 2908b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", 2909889facbeSLen Brown cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2); 2910889facbeSLen Brown #endif 2911889facbeSLen Brown } 2912889facbeSLen Brown 2913889facbeSLen Brown 2914889facbeSLen Brown if (do_dts) { 2915889facbeSLen Brown unsigned int resolution; 2916889facbeSLen Brown 2917889facbeSLen Brown if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr)) 2918889facbeSLen Brown return 0; 2919889facbeSLen Brown 2920889facbeSLen Brown dts = (msr >> 16) & 0x7F; 2921889facbeSLen Brown resolution = (msr >> 27) & 0xF; 2922b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n", 2923889facbeSLen Brown cpu, msr, tcc_activation_temp - dts, resolution); 2924889facbeSLen Brown 2925889facbeSLen Brown #ifdef THERM_DEBUG 2926889facbeSLen Brown if (get_msr(cpu, MSR_IA32_THERM_INTERRUPT, &msr)) 2927889facbeSLen Brown return 0; 2928889facbeSLen Brown 2929889facbeSLen Brown dts = (msr >> 16) & 0x7F; 2930889facbeSLen Brown dts2 = (msr >> 8) & 0x7F; 2931b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", 2932889facbeSLen Brown cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2); 2933889facbeSLen Brown #endif 2934889facbeSLen Brown } 2935889facbeSLen Brown 2936889facbeSLen Brown return 0; 2937889facbeSLen Brown } 2938889facbeSLen Brown 2939889facbeSLen Brown void print_power_limit_msr(int cpu, unsigned long long msr, char *label) 2940889facbeSLen Brown { 2941b7d8c148SLen Brown fprintf(outf, "cpu%d: %s: %sabled (%f Watts, %f sec, clamp %sabled)\n", 2942889facbeSLen Brown cpu, label, 2943889facbeSLen Brown ((msr >> 15) & 1) ? "EN" : "DIS", 2944889facbeSLen Brown ((msr >> 0) & 0x7FFF) * rapl_power_units, 2945889facbeSLen Brown (1.0 + (((msr >> 22) & 0x3)/4.0)) * (1 << ((msr >> 17) & 0x1F)) * rapl_time_units, 2946889facbeSLen Brown (((msr >> 16) & 1) ? "EN" : "DIS")); 2947889facbeSLen Brown 2948889facbeSLen Brown return; 2949889facbeSLen Brown } 2950889facbeSLen Brown 2951889facbeSLen Brown int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) 2952889facbeSLen Brown { 2953889facbeSLen Brown unsigned long long msr; 2954889facbeSLen Brown int cpu; 2955889facbeSLen Brown 2956889facbeSLen Brown if (!do_rapl) 2957889facbeSLen Brown return 0; 2958889facbeSLen Brown 2959889facbeSLen Brown /* RAPL counters are per package, so print only for 1st thread/package */ 2960889facbeSLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 2961889facbeSLen Brown return 0; 2962889facbeSLen Brown 2963889facbeSLen Brown cpu = t->cpu_id; 2964889facbeSLen Brown if (cpu_migrate(cpu)) { 2965b7d8c148SLen Brown fprintf(outf, "Could not migrate to CPU %d\n", cpu); 2966889facbeSLen Brown return -1; 2967889facbeSLen Brown } 2968889facbeSLen Brown 2969889facbeSLen Brown if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr)) 2970889facbeSLen Brown return -1; 2971889facbeSLen Brown 2972d8af6f5fSLen Brown if (debug) { 2973b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_RAPL_POWER_UNIT: 0x%08llx " 2974889facbeSLen Brown "(%f Watts, %f Joules, %f sec.)\n", cpu, msr, 2975144b44b1SLen Brown rapl_power_units, rapl_energy_units, rapl_time_units); 2976889facbeSLen Brown } 2977144b44b1SLen Brown if (do_rapl & RAPL_PKG_POWER_INFO) { 2978144b44b1SLen Brown 2979889facbeSLen Brown if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr)) 2980889facbeSLen Brown return -5; 2981889facbeSLen Brown 2982889facbeSLen Brown 2983b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PKG_POWER_INFO: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n", 2984889facbeSLen Brown cpu, msr, 2985889facbeSLen Brown ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units, 2986889facbeSLen Brown ((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units, 2987889facbeSLen Brown ((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units, 2988889facbeSLen Brown ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units); 2989889facbeSLen Brown 2990144b44b1SLen Brown } 2991144b44b1SLen Brown if (do_rapl & RAPL_PKG) { 2992144b44b1SLen Brown 2993889facbeSLen Brown if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr)) 2994889facbeSLen Brown return -9; 2995889facbeSLen Brown 2996b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n", 2997889facbeSLen Brown cpu, msr, (msr >> 63) & 1 ? "": "UN"); 2998889facbeSLen Brown 2999889facbeSLen Brown print_power_limit_msr(cpu, msr, "PKG Limit #1"); 3000b7d8c148SLen Brown fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%f Watts, %f* sec, clamp %sabled)\n", 3001889facbeSLen Brown cpu, 3002889facbeSLen Brown ((msr >> 47) & 1) ? "EN" : "DIS", 3003889facbeSLen Brown ((msr >> 32) & 0x7FFF) * rapl_power_units, 3004889facbeSLen Brown (1.0 + (((msr >> 54) & 0x3)/4.0)) * (1 << ((msr >> 49) & 0x1F)) * rapl_time_units, 3005889facbeSLen Brown ((msr >> 48) & 1) ? "EN" : "DIS"); 3006889facbeSLen Brown } 3007889facbeSLen Brown 30080b2bb692SLen Brown if (do_rapl & RAPL_DRAM_POWER_INFO) { 3009889facbeSLen Brown if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr)) 3010889facbeSLen Brown return -6; 3011889facbeSLen Brown 3012b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n", 3013889facbeSLen Brown cpu, msr, 3014889facbeSLen Brown ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units, 3015889facbeSLen Brown ((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units, 3016889facbeSLen Brown ((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units, 3017889facbeSLen Brown ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units); 30180b2bb692SLen Brown } 30190b2bb692SLen Brown if (do_rapl & RAPL_DRAM) { 3020889facbeSLen Brown if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr)) 3021889facbeSLen Brown return -9; 3022b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n", 3023889facbeSLen Brown cpu, msr, (msr >> 31) & 1 ? "": "UN"); 3024889facbeSLen Brown 3025889facbeSLen Brown print_power_limit_msr(cpu, msr, "DRAM Limit"); 3026889facbeSLen Brown } 3027144b44b1SLen Brown if (do_rapl & RAPL_CORE_POLICY) { 3028d8af6f5fSLen Brown if (debug) { 3029889facbeSLen Brown if (get_msr(cpu, MSR_PP0_POLICY, &msr)) 3030889facbeSLen Brown return -7; 3031889facbeSLen Brown 3032b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF); 3033144b44b1SLen Brown } 3034144b44b1SLen Brown } 30359148494cSJacob Pan if (do_rapl & RAPL_CORES_POWER_LIMIT) { 3036d8af6f5fSLen Brown if (debug) { 3037889facbeSLen Brown if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr)) 3038889facbeSLen Brown return -9; 3039b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n", 3040889facbeSLen Brown cpu, msr, (msr >> 31) & 1 ? "": "UN"); 3041889facbeSLen Brown print_power_limit_msr(cpu, msr, "Cores Limit"); 3042889facbeSLen Brown } 3043889facbeSLen Brown } 3044889facbeSLen Brown if (do_rapl & RAPL_GFX) { 3045d8af6f5fSLen Brown if (debug) { 3046889facbeSLen Brown if (get_msr(cpu, MSR_PP1_POLICY, &msr)) 3047889facbeSLen Brown return -8; 3048889facbeSLen Brown 3049b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF); 3050889facbeSLen Brown 3051889facbeSLen Brown if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr)) 3052889facbeSLen Brown return -9; 3053b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n", 3054889facbeSLen Brown cpu, msr, (msr >> 31) & 1 ? "": "UN"); 3055889facbeSLen Brown print_power_limit_msr(cpu, msr, "GFX Limit"); 3056889facbeSLen Brown } 3057889facbeSLen Brown } 3058889facbeSLen Brown return 0; 3059889facbeSLen Brown } 3060889facbeSLen Brown 3061d7899447SLen Brown /* 3062d7899447SLen Brown * SNB adds support for additional MSRs: 3063d7899447SLen Brown * 3064d7899447SLen Brown * MSR_PKG_C7_RESIDENCY 0x000003fa 3065d7899447SLen Brown * MSR_CORE_C7_RESIDENCY 0x000003fe 3066d7899447SLen Brown * MSR_PKG_C2_RESIDENCY 0x0000060d 3067d7899447SLen Brown */ 3068103a8feaSLen Brown 3069d7899447SLen Brown int has_snb_msrs(unsigned int family, unsigned int model) 3070103a8feaSLen Brown { 3071103a8feaSLen Brown if (!genuine_intel) 3072103a8feaSLen Brown return 0; 3073103a8feaSLen Brown 3074103a8feaSLen Brown switch (model) { 3075869ce69eSLen Brown case INTEL_FAM6_SANDYBRIDGE: 3076869ce69eSLen Brown case INTEL_FAM6_SANDYBRIDGE_X: 3077869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE: /* IVB */ 3078869ce69eSLen Brown case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */ 3079869ce69eSLen Brown case INTEL_FAM6_HASWELL_CORE: /* HSW */ 3080869ce69eSLen Brown case INTEL_FAM6_HASWELL_X: /* HSW */ 3081869ce69eSLen Brown case INTEL_FAM6_HASWELL_ULT: /* HSW */ 3082869ce69eSLen Brown case INTEL_FAM6_HASWELL_GT3E: /* HSW */ 3083869ce69eSLen Brown case INTEL_FAM6_BROADWELL_CORE: /* BDW */ 3084869ce69eSLen Brown case INTEL_FAM6_BROADWELL_GT3E: /* BDW */ 3085869ce69eSLen Brown case INTEL_FAM6_BROADWELL_X: /* BDX */ 3086869ce69eSLen Brown case INTEL_FAM6_BROADWELL_XEON_D: /* BDX-DE */ 3087869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 3088869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 3089869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 3090869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 3091869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_X: /* SKX */ 3092869ce69eSLen Brown case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 30935bbac26eSXiaolong Wang case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ 3094103a8feaSLen Brown return 1; 3095103a8feaSLen Brown } 3096103a8feaSLen Brown return 0; 3097103a8feaSLen Brown } 3098103a8feaSLen Brown 3099d7899447SLen Brown /* 3100d7899447SLen Brown * HSW adds support for additional MSRs: 3101d7899447SLen Brown * 3102d7899447SLen Brown * MSR_PKG_C8_RESIDENCY 0x00000630 3103d7899447SLen Brown * MSR_PKG_C9_RESIDENCY 0x00000631 3104d7899447SLen Brown * MSR_PKG_C10_RESIDENCY 0x00000632 31055a63426eSLen Brown * 31065a63426eSLen Brown * MSR_PKGC8_IRTL 0x00000633 31075a63426eSLen Brown * MSR_PKGC9_IRTL 0x00000634 31085a63426eSLen Brown * MSR_PKGC10_IRTL 0x00000635 31095a63426eSLen Brown * 3110d7899447SLen Brown */ 3111d7899447SLen Brown int has_hsw_msrs(unsigned int family, unsigned int model) 3112ca58710fSKristen Carlson Accardi { 3113ca58710fSKristen Carlson Accardi if (!genuine_intel) 3114ca58710fSKristen Carlson Accardi return 0; 3115ca58710fSKristen Carlson Accardi 3116ca58710fSKristen Carlson Accardi switch (model) { 3117869ce69eSLen Brown case INTEL_FAM6_HASWELL_ULT: /* HSW */ 3118869ce69eSLen Brown case INTEL_FAM6_BROADWELL_CORE: /* BDW */ 3119869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 3120869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 3121869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 3122869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 3123869ce69eSLen Brown case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 3124ca58710fSKristen Carlson Accardi return 1; 3125ca58710fSKristen Carlson Accardi } 3126ca58710fSKristen Carlson Accardi return 0; 3127ca58710fSKristen Carlson Accardi } 3128ca58710fSKristen Carlson Accardi 31290b2bb692SLen Brown /* 31300b2bb692SLen Brown * SKL adds support for additional MSRS: 31310b2bb692SLen Brown * 31320b2bb692SLen Brown * MSR_PKG_WEIGHTED_CORE_C0_RES 0x00000658 31330b2bb692SLen Brown * MSR_PKG_ANY_CORE_C0_RES 0x00000659 31340b2bb692SLen Brown * MSR_PKG_ANY_GFXE_C0_RES 0x0000065A 31350b2bb692SLen Brown * MSR_PKG_BOTH_CORE_GFXE_C0_RES 0x0000065B 31360b2bb692SLen Brown */ 31370b2bb692SLen Brown int has_skl_msrs(unsigned int family, unsigned int model) 31380b2bb692SLen Brown { 31390b2bb692SLen Brown if (!genuine_intel) 31400b2bb692SLen Brown return 0; 31410b2bb692SLen Brown 31420b2bb692SLen Brown switch (model) { 3143869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 3144869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 3145869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 3146869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 31470b2bb692SLen Brown return 1; 31480b2bb692SLen Brown } 31490b2bb692SLen Brown return 0; 31500b2bb692SLen Brown } 31510b2bb692SLen Brown 31520b2bb692SLen Brown 3153ca58710fSKristen Carlson Accardi 3154144b44b1SLen Brown int is_slm(unsigned int family, unsigned int model) 3155144b44b1SLen Brown { 3156144b44b1SLen Brown if (!genuine_intel) 3157144b44b1SLen Brown return 0; 3158144b44b1SLen Brown switch (model) { 3159869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */ 3160869ce69eSLen Brown case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */ 3161144b44b1SLen Brown return 1; 3162144b44b1SLen Brown } 3163144b44b1SLen Brown return 0; 3164144b44b1SLen Brown } 3165144b44b1SLen Brown 3166fb5d4327SDasaratharaman Chandramouli int is_knl(unsigned int family, unsigned int model) 3167fb5d4327SDasaratharaman Chandramouli { 3168fb5d4327SDasaratharaman Chandramouli if (!genuine_intel) 3169fb5d4327SDasaratharaman Chandramouli return 0; 3170fb5d4327SDasaratharaman Chandramouli switch (model) { 3171869ce69eSLen Brown case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ 3172005c82d6SLen Brown case INTEL_FAM6_XEON_PHI_KNM: 3173fb5d4327SDasaratharaman Chandramouli return 1; 3174fb5d4327SDasaratharaman Chandramouli } 3175fb5d4327SDasaratharaman Chandramouli return 0; 3176fb5d4327SDasaratharaman Chandramouli } 3177fb5d4327SDasaratharaman Chandramouli 3178b2b34dfeSHubert Chrzaniuk unsigned int get_aperf_mperf_multiplier(unsigned int family, unsigned int model) 3179b2b34dfeSHubert Chrzaniuk { 3180b2b34dfeSHubert Chrzaniuk if (is_knl(family, model)) 3181b2b34dfeSHubert Chrzaniuk return 1024; 3182b2b34dfeSHubert Chrzaniuk return 1; 3183b2b34dfeSHubert Chrzaniuk } 3184b2b34dfeSHubert Chrzaniuk 3185144b44b1SLen Brown #define SLM_BCLK_FREQS 5 3186144b44b1SLen Brown double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0}; 3187144b44b1SLen Brown 3188144b44b1SLen Brown double slm_bclk(void) 3189144b44b1SLen Brown { 3190144b44b1SLen Brown unsigned long long msr = 3; 3191144b44b1SLen Brown unsigned int i; 3192144b44b1SLen Brown double freq; 3193144b44b1SLen Brown 31947ce7d5deSPrarit Bhargava if (get_msr(base_cpu, MSR_FSB_FREQ, &msr)) 3195b7d8c148SLen Brown fprintf(outf, "SLM BCLK: unknown\n"); 3196144b44b1SLen Brown 3197144b44b1SLen Brown i = msr & 0xf; 3198144b44b1SLen Brown if (i >= SLM_BCLK_FREQS) { 3199b7d8c148SLen Brown fprintf(outf, "SLM BCLK[%d] invalid\n", i); 32000a91e551SColin Ian King i = 3; 3201144b44b1SLen Brown } 3202144b44b1SLen Brown freq = slm_freq_table[i]; 3203144b44b1SLen Brown 3204b7d8c148SLen Brown fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq); 3205144b44b1SLen Brown 3206144b44b1SLen Brown return freq; 3207144b44b1SLen Brown } 3208144b44b1SLen Brown 3209103a8feaSLen Brown double discover_bclk(unsigned int family, unsigned int model) 3210103a8feaSLen Brown { 3211121b48bbSChrzaniuk, Hubert if (has_snb_msrs(family, model) || is_knl(family, model)) 3212103a8feaSLen Brown return 100.00; 3213144b44b1SLen Brown else if (is_slm(family, model)) 3214144b44b1SLen Brown return slm_bclk(); 3215103a8feaSLen Brown else 3216103a8feaSLen Brown return 133.33; 3217103a8feaSLen Brown } 3218103a8feaSLen Brown 3219889facbeSLen Brown /* 3220889facbeSLen Brown * MSR_IA32_TEMPERATURE_TARGET indicates the temperature where 3221889facbeSLen Brown * the Thermal Control Circuit (TCC) activates. 3222889facbeSLen Brown * This is usually equal to tjMax. 3223889facbeSLen Brown * 3224889facbeSLen Brown * Older processors do not have this MSR, so there we guess, 3225889facbeSLen Brown * but also allow cmdline over-ride with -T. 3226889facbeSLen Brown * 3227889facbeSLen Brown * Several MSR temperature values are in units of degrees-C 3228889facbeSLen Brown * below this value, including the Digital Thermal Sensor (DTS), 3229889facbeSLen Brown * Package Thermal Management Sensor (PTM), and thermal event thresholds. 3230889facbeSLen Brown */ 3231889facbeSLen Brown int set_temperature_target(struct thread_data *t, struct core_data *c, struct pkg_data *p) 3232889facbeSLen Brown { 3233889facbeSLen Brown unsigned long long msr; 3234889facbeSLen Brown unsigned int target_c_local; 3235889facbeSLen Brown int cpu; 3236889facbeSLen Brown 3237889facbeSLen Brown /* tcc_activation_temp is used only for dts or ptm */ 3238889facbeSLen Brown if (!(do_dts || do_ptm)) 3239889facbeSLen Brown return 0; 3240889facbeSLen Brown 3241889facbeSLen Brown /* this is a per-package concept */ 3242889facbeSLen Brown if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 3243889facbeSLen Brown return 0; 3244889facbeSLen Brown 3245889facbeSLen Brown cpu = t->cpu_id; 3246889facbeSLen Brown if (cpu_migrate(cpu)) { 3247b7d8c148SLen Brown fprintf(outf, "Could not migrate to CPU %d\n", cpu); 3248889facbeSLen Brown return -1; 3249889facbeSLen Brown } 3250889facbeSLen Brown 3251889facbeSLen Brown if (tcc_activation_temp_override != 0) { 3252889facbeSLen Brown tcc_activation_temp = tcc_activation_temp_override; 3253b7d8c148SLen Brown fprintf(outf, "cpu%d: Using cmdline TCC Target (%d C)\n", 3254889facbeSLen Brown cpu, tcc_activation_temp); 3255889facbeSLen Brown return 0; 3256889facbeSLen Brown } 3257889facbeSLen Brown 3258889facbeSLen Brown /* Temperature Target MSR is Nehalem and newer only */ 3259d7899447SLen Brown if (!do_nhm_platform_info) 3260889facbeSLen Brown goto guess; 3261889facbeSLen Brown 32627ce7d5deSPrarit Bhargava if (get_msr(base_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr)) 3263889facbeSLen Brown goto guess; 3264889facbeSLen Brown 32653482124aSJean Delvare target_c_local = (msr >> 16) & 0xFF; 3266889facbeSLen Brown 3267d8af6f5fSLen Brown if (debug) 3268b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n", 3269889facbeSLen Brown cpu, msr, target_c_local); 3270889facbeSLen Brown 32713482124aSJean Delvare if (!target_c_local) 3272889facbeSLen Brown goto guess; 3273889facbeSLen Brown 3274889facbeSLen Brown tcc_activation_temp = target_c_local; 3275889facbeSLen Brown 3276889facbeSLen Brown return 0; 3277889facbeSLen Brown 3278889facbeSLen Brown guess: 3279889facbeSLen Brown tcc_activation_temp = TJMAX_DEFAULT; 3280b7d8c148SLen Brown fprintf(outf, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n", 3281889facbeSLen Brown cpu, tcc_activation_temp); 3282889facbeSLen Brown 3283889facbeSLen Brown return 0; 3284889facbeSLen Brown } 328569807a63SLen Brown 3286aa8d8cc7SLen Brown void decode_feature_control_msr(void) 3287aa8d8cc7SLen Brown { 3288aa8d8cc7SLen Brown unsigned long long msr; 3289aa8d8cc7SLen Brown 3290aa8d8cc7SLen Brown if (!get_msr(base_cpu, MSR_IA32_FEATURE_CONTROL, &msr)) 3291aa8d8cc7SLen Brown fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n", 3292aa8d8cc7SLen Brown base_cpu, msr, 3293aa8d8cc7SLen Brown msr & FEATURE_CONTROL_LOCKED ? "" : "UN-", 3294aa8d8cc7SLen Brown msr & (1 << 18) ? "SGX" : ""); 3295aa8d8cc7SLen Brown } 3296aa8d8cc7SLen Brown 329769807a63SLen Brown void decode_misc_enable_msr(void) 329869807a63SLen Brown { 329969807a63SLen Brown unsigned long long msr; 330069807a63SLen Brown 330169807a63SLen Brown if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr)) 3302b7d8c148SLen Brown fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%s %s %s)\n", 330369807a63SLen Brown base_cpu, msr, 330469807a63SLen Brown msr & (1 << 3) ? "TCC" : "", 330569807a63SLen Brown msr & (1 << 16) ? "EIST" : "", 330669807a63SLen Brown msr & (1 << 18) ? "MONITOR" : ""); 330769807a63SLen Brown } 330869807a63SLen Brown 3309f0057310SLen Brown /* 3310f0057310SLen Brown * Decode MSR_MISC_PWR_MGMT 3311f0057310SLen Brown * 3312f0057310SLen Brown * Decode the bits according to the Nehalem documentation 3313f0057310SLen Brown * bit[0] seems to continue to have same meaning going forward 3314f0057310SLen Brown * bit[1] less so... 3315f0057310SLen Brown */ 3316f0057310SLen Brown void decode_misc_pwr_mgmt_msr(void) 3317f0057310SLen Brown { 3318f0057310SLen Brown unsigned long long msr; 3319f0057310SLen Brown 3320f0057310SLen Brown if (!do_nhm_platform_info) 3321f0057310SLen Brown return; 3322f0057310SLen Brown 3323f0057310SLen Brown if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr)) 3324ddadb8adSSrinivas Pandruvada fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB %sable-OOB)\n", 3325f0057310SLen Brown base_cpu, msr, 3326f0057310SLen Brown msr & (1 << 0) ? "DIS" : "EN", 3327ddadb8adSSrinivas Pandruvada msr & (1 << 1) ? "EN" : "DIS", 3328ddadb8adSSrinivas Pandruvada msr & (1 << 8) ? "EN" : "DIS"); 3329f0057310SLen Brown } 33307f5c258eSLen Brown 3331fcd17211SLen Brown void process_cpuid() 3332103a8feaSLen Brown { 333361a87ba7SLen Brown unsigned int eax, ebx, ecx, edx, max_level, max_extended_level; 3334103a8feaSLen Brown unsigned int fms, family, model, stepping; 3335103a8feaSLen Brown 3336103a8feaSLen Brown eax = ebx = ecx = edx = 0; 3337103a8feaSLen Brown 33385aea2f7fSLen Brown __cpuid(0, max_level, ebx, ecx, edx); 3339103a8feaSLen Brown 3340103a8feaSLen Brown if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e) 3341103a8feaSLen Brown genuine_intel = 1; 3342103a8feaSLen Brown 3343d8af6f5fSLen Brown if (debug) 3344b7d8c148SLen Brown fprintf(outf, "CPUID(0): %.4s%.4s%.4s ", 3345103a8feaSLen Brown (char *)&ebx, (char *)&edx, (char *)&ecx); 3346103a8feaSLen Brown 33475aea2f7fSLen Brown __cpuid(1, fms, ebx, ecx, edx); 3348103a8feaSLen Brown family = (fms >> 8) & 0xf; 3349103a8feaSLen Brown model = (fms >> 4) & 0xf; 3350103a8feaSLen Brown stepping = fms & 0xf; 3351103a8feaSLen Brown if (family == 6 || family == 0xf) 3352103a8feaSLen Brown model += ((fms >> 16) & 0xf) << 4; 3353103a8feaSLen Brown 335469807a63SLen Brown if (debug) { 3355b7d8c148SLen Brown fprintf(outf, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n", 3356103a8feaSLen Brown max_level, family, model, stepping, family, model, stepping); 3357aa8d8cc7SLen Brown fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s\n", 335869807a63SLen Brown ecx & (1 << 0) ? "SSE3" : "-", 335969807a63SLen Brown ecx & (1 << 3) ? "MONITOR" : "-", 3360aa8d8cc7SLen Brown ecx & (1 << 6) ? "SMX" : "-", 336169807a63SLen Brown ecx & (1 << 7) ? "EIST" : "-", 336269807a63SLen Brown ecx & (1 << 8) ? "TM2" : "-", 336369807a63SLen Brown edx & (1 << 4) ? "TSC" : "-", 336469807a63SLen Brown edx & (1 << 5) ? "MSR" : "-", 336569807a63SLen Brown edx & (1 << 22) ? "ACPI-TM" : "-", 336669807a63SLen Brown edx & (1 << 29) ? "TM" : "-"); 336769807a63SLen Brown } 3368103a8feaSLen Brown 3369b2c95d90SJosh Triplett if (!(edx & (1 << 5))) 3370b2c95d90SJosh Triplett errx(1, "CPUID: no MSR"); 3371103a8feaSLen Brown 3372103a8feaSLen Brown /* 3373103a8feaSLen Brown * check max extended function levels of CPUID. 3374103a8feaSLen Brown * This is needed to check for invariant TSC. 3375103a8feaSLen Brown * This check is valid for both Intel and AMD. 3376103a8feaSLen Brown */ 3377103a8feaSLen Brown ebx = ecx = edx = 0; 33785aea2f7fSLen Brown __cpuid(0x80000000, max_extended_level, ebx, ecx, edx); 3379103a8feaSLen Brown 338061a87ba7SLen Brown if (max_extended_level >= 0x80000007) { 3381103a8feaSLen Brown 3382103a8feaSLen Brown /* 3383103a8feaSLen Brown * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8 3384103a8feaSLen Brown * this check is valid for both Intel and AMD 3385103a8feaSLen Brown */ 33865aea2f7fSLen Brown __cpuid(0x80000007, eax, ebx, ecx, edx); 33878209e054SThomas Renninger has_invariant_tsc = edx & (1 << 8); 3388d7899447SLen Brown } 3389103a8feaSLen Brown 3390103a8feaSLen Brown /* 3391103a8feaSLen Brown * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0 3392103a8feaSLen Brown * this check is valid for both Intel and AMD 3393103a8feaSLen Brown */ 3394103a8feaSLen Brown 33955aea2f7fSLen Brown __cpuid(0x6, eax, ebx, ecx, edx); 33968209e054SThomas Renninger has_aperf = ecx & (1 << 0); 3397889facbeSLen Brown do_dts = eax & (1 << 0); 3398889facbeSLen Brown do_ptm = eax & (1 << 6); 33997f5c258eSLen Brown has_hwp = eax & (1 << 7); 34007f5c258eSLen Brown has_hwp_notify = eax & (1 << 8); 34017f5c258eSLen Brown has_hwp_activity_window = eax & (1 << 9); 34027f5c258eSLen Brown has_hwp_epp = eax & (1 << 10); 34037f5c258eSLen Brown has_hwp_pkg = eax & (1 << 11); 3404889facbeSLen Brown has_epb = ecx & (1 << 3); 3405889facbeSLen Brown 3406d8af6f5fSLen Brown if (debug) 3407b7d8c148SLen Brown fprintf(outf, "CPUID(6): %sAPERF, %sDTS, %sPTM, %sHWP, " 34087f5c258eSLen Brown "%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n", 34097f5c258eSLen Brown has_aperf ? "" : "No-", 34107f5c258eSLen Brown do_dts ? "" : "No-", 34117f5c258eSLen Brown do_ptm ? "" : "No-", 34127f5c258eSLen Brown has_hwp ? "" : "No-", 34137f5c258eSLen Brown has_hwp_notify ? "" : "No-", 34147f5c258eSLen Brown has_hwp_activity_window ? "" : "No-", 34157f5c258eSLen Brown has_hwp_epp ? "" : "No-", 34167f5c258eSLen Brown has_hwp_pkg ? "" : "No-", 34177f5c258eSLen Brown has_epb ? "" : "No-"); 3418103a8feaSLen Brown 341969807a63SLen Brown if (debug) 342069807a63SLen Brown decode_misc_enable_msr(); 342169807a63SLen Brown 34228ae72255SLen Brown if (max_level >= 0x7 && debug) { 3423aa8d8cc7SLen Brown int has_sgx; 3424aa8d8cc7SLen Brown 3425aa8d8cc7SLen Brown ecx = 0; 3426aa8d8cc7SLen Brown 3427aa8d8cc7SLen Brown __cpuid_count(0x7, 0, eax, ebx, ecx, edx); 3428aa8d8cc7SLen Brown 3429aa8d8cc7SLen Brown has_sgx = ebx & (1 << 2); 3430aa8d8cc7SLen Brown fprintf(outf, "CPUID(7): %sSGX\n", has_sgx ? "" : "No-"); 3431aa8d8cc7SLen Brown 3432aa8d8cc7SLen Brown if (has_sgx) 3433aa8d8cc7SLen Brown decode_feature_control_msr(); 3434aa8d8cc7SLen Brown } 3435aa8d8cc7SLen Brown 343661a87ba7SLen Brown if (max_level >= 0x15) { 34378a5bdf41SLen Brown unsigned int eax_crystal; 34388a5bdf41SLen Brown unsigned int ebx_tsc; 34398a5bdf41SLen Brown 34408a5bdf41SLen Brown /* 34418a5bdf41SLen Brown * CPUID 15H TSC/Crystal ratio, possibly Crystal Hz 34428a5bdf41SLen Brown */ 34438a5bdf41SLen Brown eax_crystal = ebx_tsc = crystal_hz = edx = 0; 34445aea2f7fSLen Brown __cpuid(0x15, eax_crystal, ebx_tsc, crystal_hz, edx); 34458a5bdf41SLen Brown 34468a5bdf41SLen Brown if (ebx_tsc != 0) { 34478a5bdf41SLen Brown 34488a5bdf41SLen Brown if (debug && (ebx != 0)) 3449b7d8c148SLen Brown fprintf(outf, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n", 34508a5bdf41SLen Brown eax_crystal, ebx_tsc, crystal_hz); 34518a5bdf41SLen Brown 34528a5bdf41SLen Brown if (crystal_hz == 0) 34538a5bdf41SLen Brown switch(model) { 3454869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 3455869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 3456869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 3457869ce69eSLen Brown case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 3458e8efbc80SLen Brown crystal_hz = 24000000; /* 24.0 MHz */ 3459e8efbc80SLen Brown break; 3460869ce69eSLen Brown case INTEL_FAM6_SKYLAKE_X: /* SKX */ 34617268d407SLen Brown case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ 3462ec53e594SLen Brown crystal_hz = 25000000; /* 25.0 MHz */ 3463ec53e594SLen Brown break; 3464869ce69eSLen Brown case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 3465e8efbc80SLen Brown crystal_hz = 19200000; /* 19.2 MHz */ 34668a5bdf41SLen Brown break; 34678a5bdf41SLen Brown default: 34688a5bdf41SLen Brown crystal_hz = 0; 34698a5bdf41SLen Brown } 34708a5bdf41SLen Brown 34718a5bdf41SLen Brown if (crystal_hz) { 34728a5bdf41SLen Brown tsc_hz = (unsigned long long) crystal_hz * ebx_tsc / eax_crystal; 34738a5bdf41SLen Brown if (debug) 3474b7d8c148SLen Brown fprintf(outf, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n", 34758a5bdf41SLen Brown tsc_hz / 1000000, crystal_hz, ebx_tsc, eax_crystal); 34768a5bdf41SLen Brown } 34778a5bdf41SLen Brown } 34788a5bdf41SLen Brown } 347961a87ba7SLen Brown if (max_level >= 0x16) { 348061a87ba7SLen Brown unsigned int base_mhz, max_mhz, bus_mhz, edx; 348161a87ba7SLen Brown 348261a87ba7SLen Brown /* 348361a87ba7SLen Brown * CPUID 16H Base MHz, Max MHz, Bus MHz 348461a87ba7SLen Brown */ 348561a87ba7SLen Brown base_mhz = max_mhz = bus_mhz = edx = 0; 348661a87ba7SLen Brown 34875aea2f7fSLen Brown __cpuid(0x16, base_mhz, max_mhz, bus_mhz, edx); 348861a87ba7SLen Brown if (debug) 3489b7d8c148SLen Brown fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n", 349061a87ba7SLen Brown base_mhz, max_mhz, bus_mhz); 349161a87ba7SLen Brown } 34928a5bdf41SLen Brown 3493b2b34dfeSHubert Chrzaniuk if (has_aperf) 3494b2b34dfeSHubert Chrzaniuk aperf_mperf_multiplier = get_aperf_mperf_multiplier(family, model); 3495b2b34dfeSHubert Chrzaniuk 3496ee7e38e3SLen Brown do_nhm_platform_info = do_nhm_cstates = do_smi = probe_nhm_msrs(family, model); 3497d7899447SLen Brown do_snb_cstates = has_snb_msrs(family, model); 34985a63426eSLen Brown do_irtl_snb = has_snb_msrs(family, model); 3499ee7e38e3SLen Brown do_pc2 = do_snb_cstates && (pkg_cstate_limit >= PCL__2); 3500ee7e38e3SLen Brown do_pc3 = (pkg_cstate_limit >= PCL__3); 3501ee7e38e3SLen Brown do_pc6 = (pkg_cstate_limit >= PCL__6); 3502ee7e38e3SLen Brown do_pc7 = do_snb_cstates && (pkg_cstate_limit >= PCL__7); 3503d7899447SLen Brown do_c8_c9_c10 = has_hsw_msrs(family, model); 35045a63426eSLen Brown do_irtl_hsw = has_hsw_msrs(family, model); 35050b2bb692SLen Brown do_skl_residency = has_skl_msrs(family, model); 3506144b44b1SLen Brown do_slm_cstates = is_slm(family, model); 3507fb5d4327SDasaratharaman Chandramouli do_knl_cstates = is_knl(family, model); 3508103a8feaSLen Brown 3509f0057310SLen Brown if (debug) 3510f0057310SLen Brown decode_misc_pwr_mgmt_msr(); 3511f0057310SLen Brown 3512889facbeSLen Brown rapl_probe(family, model); 35133a9a941dSLen Brown perf_limit_reasons_probe(family, model); 3514889facbeSLen Brown 3515fcd17211SLen Brown if (debug) 35161b69317dSColin Ian King dump_cstate_pstate_config_info(family, model); 3517fcd17211SLen Brown 3518a2b7b749SLen Brown if (has_skl_msrs(family, model)) 3519a2b7b749SLen Brown calculate_tsc_tweak(); 3520a2b7b749SLen Brown 3521fdf676e5SLen Brown do_gfx_rc6_ms = !access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK); 3522fdf676e5SLen Brown 352327d47356SLen Brown do_gfx_mhz = !access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK); 352427d47356SLen Brown 3525889facbeSLen Brown return; 3526103a8feaSLen Brown } 3527103a8feaSLen Brown 3528d8af6f5fSLen Brown void help() 3529103a8feaSLen Brown { 3530b7d8c148SLen Brown fprintf(outf, 3531d8af6f5fSLen Brown "Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n" 3532d8af6f5fSLen Brown "\n" 3533d8af6f5fSLen Brown "Turbostat forks the specified COMMAND and prints statistics\n" 3534d8af6f5fSLen Brown "when COMMAND completes.\n" 3535d8af6f5fSLen Brown "If no COMMAND is specified, turbostat wakes every 5-seconds\n" 3536d8af6f5fSLen Brown "to print statistics, until interrupted.\n" 3537388e9c81SLen Brown "--add add a counter\n" 3538388e9c81SLen Brown " eg. --add msr0x10,u64,cpu,delta,MY_TSC\n" 3539d8af6f5fSLen Brown "--debug run in \"debug\" mode\n" 3540d8af6f5fSLen Brown "--interval sec Override default 5-second measurement interval\n" 3541d8af6f5fSLen Brown "--help print this help message\n" 3542b7d8c148SLen Brown "--out file create or truncate \"file\" for all output\n" 3543d8af6f5fSLen Brown "--version print version information\n" 3544d8af6f5fSLen Brown "\n" 3545d8af6f5fSLen Brown "For more help, run \"man turbostat\"\n"); 3546103a8feaSLen Brown } 3547103a8feaSLen Brown 3548103a8feaSLen Brown 3549103a8feaSLen Brown /* 3550103a8feaSLen Brown * in /dev/cpu/ return success for names that are numbers 3551103a8feaSLen Brown * ie. filter out ".", "..", "microcode". 3552103a8feaSLen Brown */ 3553103a8feaSLen Brown int dir_filter(const struct dirent *dirp) 3554103a8feaSLen Brown { 3555103a8feaSLen Brown if (isdigit(dirp->d_name[0])) 3556103a8feaSLen Brown return 1; 3557103a8feaSLen Brown else 3558103a8feaSLen Brown return 0; 3559103a8feaSLen Brown } 3560103a8feaSLen Brown 3561103a8feaSLen Brown int open_dev_cpu_msr(int dummy1) 3562103a8feaSLen Brown { 3563103a8feaSLen Brown return 0; 3564103a8feaSLen Brown } 3565103a8feaSLen Brown 3566c98d5d94SLen Brown void topology_probe() 3567c98d5d94SLen Brown { 3568c98d5d94SLen Brown int i; 3569c98d5d94SLen Brown int max_core_id = 0; 3570c98d5d94SLen Brown int max_package_id = 0; 3571c98d5d94SLen Brown int max_siblings = 0; 3572c98d5d94SLen Brown struct cpu_topology { 3573c98d5d94SLen Brown int core_id; 3574c98d5d94SLen Brown int physical_package_id; 3575c98d5d94SLen Brown } *cpus; 3576c98d5d94SLen Brown 3577c98d5d94SLen Brown /* Initialize num_cpus, max_cpu_num */ 3578c98d5d94SLen Brown topo.num_cpus = 0; 3579c98d5d94SLen Brown topo.max_cpu_num = 0; 3580c98d5d94SLen Brown for_all_proc_cpus(count_cpus); 3581c98d5d94SLen Brown if (!summary_only && topo.num_cpus > 1) 3582c98d5d94SLen Brown show_cpu = 1; 3583c98d5d94SLen Brown 3584d8af6f5fSLen Brown if (debug > 1) 3585b7d8c148SLen Brown fprintf(outf, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num); 3586c98d5d94SLen Brown 3587c98d5d94SLen Brown cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology)); 3588b2c95d90SJosh Triplett if (cpus == NULL) 3589b2c95d90SJosh Triplett err(1, "calloc cpus"); 3590c98d5d94SLen Brown 3591c98d5d94SLen Brown /* 3592c98d5d94SLen Brown * Allocate and initialize cpu_present_set 3593c98d5d94SLen Brown */ 3594c98d5d94SLen Brown cpu_present_set = CPU_ALLOC((topo.max_cpu_num + 1)); 3595b2c95d90SJosh Triplett if (cpu_present_set == NULL) 3596b2c95d90SJosh Triplett err(3, "CPU_ALLOC"); 3597c98d5d94SLen Brown cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); 3598c98d5d94SLen Brown CPU_ZERO_S(cpu_present_setsize, cpu_present_set); 3599c98d5d94SLen Brown for_all_proc_cpus(mark_cpu_present); 3600c98d5d94SLen Brown 3601c98d5d94SLen Brown /* 3602c98d5d94SLen Brown * Allocate and initialize cpu_affinity_set 3603c98d5d94SLen Brown */ 3604c98d5d94SLen Brown cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1)); 3605b2c95d90SJosh Triplett if (cpu_affinity_set == NULL) 3606b2c95d90SJosh Triplett err(3, "CPU_ALLOC"); 3607c98d5d94SLen Brown cpu_affinity_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); 3608c98d5d94SLen Brown CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set); 3609c98d5d94SLen Brown 3610c98d5d94SLen Brown 3611c98d5d94SLen Brown /* 3612c98d5d94SLen Brown * For online cpus 3613c98d5d94SLen Brown * find max_core_id, max_package_id 3614c98d5d94SLen Brown */ 3615c98d5d94SLen Brown for (i = 0; i <= topo.max_cpu_num; ++i) { 3616c98d5d94SLen Brown int siblings; 3617c98d5d94SLen Brown 3618c98d5d94SLen Brown if (cpu_is_not_present(i)) { 3619d8af6f5fSLen Brown if (debug > 1) 3620b7d8c148SLen Brown fprintf(outf, "cpu%d NOT PRESENT\n", i); 3621c98d5d94SLen Brown continue; 3622c98d5d94SLen Brown } 3623c98d5d94SLen Brown cpus[i].core_id = get_core_id(i); 3624c98d5d94SLen Brown if (cpus[i].core_id > max_core_id) 3625c98d5d94SLen Brown max_core_id = cpus[i].core_id; 3626c98d5d94SLen Brown 3627c98d5d94SLen Brown cpus[i].physical_package_id = get_physical_package_id(i); 3628c98d5d94SLen Brown if (cpus[i].physical_package_id > max_package_id) 3629c98d5d94SLen Brown max_package_id = cpus[i].physical_package_id; 3630c98d5d94SLen Brown 3631c98d5d94SLen Brown siblings = get_num_ht_siblings(i); 3632c98d5d94SLen Brown if (siblings > max_siblings) 3633c98d5d94SLen Brown max_siblings = siblings; 3634d8af6f5fSLen Brown if (debug > 1) 3635b7d8c148SLen Brown fprintf(outf, "cpu %d pkg %d core %d\n", 3636c98d5d94SLen Brown i, cpus[i].physical_package_id, cpus[i].core_id); 3637c98d5d94SLen Brown } 3638c98d5d94SLen Brown topo.num_cores_per_pkg = max_core_id + 1; 3639d8af6f5fSLen Brown if (debug > 1) 3640b7d8c148SLen Brown fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", 3641c98d5d94SLen Brown max_core_id, topo.num_cores_per_pkg); 36421cc21f7bSLen Brown if (debug && !summary_only && topo.num_cores_per_pkg > 1) 3643c98d5d94SLen Brown show_core = 1; 3644c98d5d94SLen Brown 3645c98d5d94SLen Brown topo.num_packages = max_package_id + 1; 3646d8af6f5fSLen Brown if (debug > 1) 3647b7d8c148SLen Brown fprintf(outf, "max_package_id %d, sizing for %d packages\n", 3648c98d5d94SLen Brown max_package_id, topo.num_packages); 36491cc21f7bSLen Brown if (debug && !summary_only && topo.num_packages > 1) 3650c98d5d94SLen Brown show_pkg = 1; 3651c98d5d94SLen Brown 3652c98d5d94SLen Brown topo.num_threads_per_core = max_siblings; 3653d8af6f5fSLen Brown if (debug > 1) 3654b7d8c148SLen Brown fprintf(outf, "max_siblings %d\n", max_siblings); 3655c98d5d94SLen Brown 3656c98d5d94SLen Brown free(cpus); 3657c98d5d94SLen Brown } 3658c98d5d94SLen Brown 3659c98d5d94SLen Brown void 3660c98d5d94SLen Brown allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data **p) 3661c98d5d94SLen Brown { 3662c98d5d94SLen Brown int i; 3663c98d5d94SLen Brown 3664c98d5d94SLen Brown *t = calloc(topo.num_threads_per_core * topo.num_cores_per_pkg * 3665388e9c81SLen Brown topo.num_packages, sizeof(struct thread_data) + sys.thread_counter_bytes); 3666c98d5d94SLen Brown if (*t == NULL) 3667c98d5d94SLen Brown goto error; 3668c98d5d94SLen Brown 3669c98d5d94SLen Brown for (i = 0; i < topo.num_threads_per_core * 3670c98d5d94SLen Brown topo.num_cores_per_pkg * topo.num_packages; i++) 3671c98d5d94SLen Brown (*t)[i].cpu_id = -1; 3672c98d5d94SLen Brown 3673c98d5d94SLen Brown *c = calloc(topo.num_cores_per_pkg * topo.num_packages, 3674388e9c81SLen Brown sizeof(struct core_data) + sys.core_counter_bytes); 3675c98d5d94SLen Brown if (*c == NULL) 3676c98d5d94SLen Brown goto error; 3677c98d5d94SLen Brown 3678c98d5d94SLen Brown for (i = 0; i < topo.num_cores_per_pkg * topo.num_packages; i++) 3679c98d5d94SLen Brown (*c)[i].core_id = -1; 3680c98d5d94SLen Brown 3681388e9c81SLen Brown *p = calloc(topo.num_packages, sizeof(struct pkg_data) + sys.package_counter_bytes); 3682c98d5d94SLen Brown if (*p == NULL) 3683c98d5d94SLen Brown goto error; 3684c98d5d94SLen Brown 3685c98d5d94SLen Brown for (i = 0; i < topo.num_packages; i++) 3686c98d5d94SLen Brown (*p)[i].package_id = i; 3687c98d5d94SLen Brown 3688c98d5d94SLen Brown return; 3689c98d5d94SLen Brown error: 3690b2c95d90SJosh Triplett err(1, "calloc counters"); 3691c98d5d94SLen Brown } 3692c98d5d94SLen Brown /* 3693c98d5d94SLen Brown * init_counter() 3694c98d5d94SLen Brown * 3695c98d5d94SLen Brown * set cpu_id, core_num, pkg_num 3696c98d5d94SLen Brown * set FIRST_THREAD_IN_CORE and FIRST_CORE_IN_PACKAGE 3697c98d5d94SLen Brown * 3698c98d5d94SLen Brown * increment topo.num_cores when 1st core in pkg seen 3699c98d5d94SLen Brown */ 3700c98d5d94SLen Brown void init_counter(struct thread_data *thread_base, struct core_data *core_base, 3701c98d5d94SLen Brown struct pkg_data *pkg_base, int thread_num, int core_num, 3702c98d5d94SLen Brown int pkg_num, int cpu_id) 3703c98d5d94SLen Brown { 3704c98d5d94SLen Brown struct thread_data *t; 3705c98d5d94SLen Brown struct core_data *c; 3706c98d5d94SLen Brown struct pkg_data *p; 3707c98d5d94SLen Brown 3708c98d5d94SLen Brown t = GET_THREAD(thread_base, thread_num, core_num, pkg_num); 3709c98d5d94SLen Brown c = GET_CORE(core_base, core_num, pkg_num); 3710c98d5d94SLen Brown p = GET_PKG(pkg_base, pkg_num); 3711c98d5d94SLen Brown 3712c98d5d94SLen Brown t->cpu_id = cpu_id; 3713c98d5d94SLen Brown if (thread_num == 0) { 3714c98d5d94SLen Brown t->flags |= CPU_IS_FIRST_THREAD_IN_CORE; 3715c98d5d94SLen Brown if (cpu_is_first_core_in_package(cpu_id)) 3716c98d5d94SLen Brown t->flags |= CPU_IS_FIRST_CORE_IN_PACKAGE; 3717c98d5d94SLen Brown } 3718c98d5d94SLen Brown 3719c98d5d94SLen Brown c->core_id = core_num; 3720c98d5d94SLen Brown p->package_id = pkg_num; 3721c98d5d94SLen Brown } 3722c98d5d94SLen Brown 3723c98d5d94SLen Brown 3724c98d5d94SLen Brown int initialize_counters(int cpu_id) 3725c98d5d94SLen Brown { 3726c98d5d94SLen Brown int my_thread_id, my_core_id, my_package_id; 3727c98d5d94SLen Brown 3728c98d5d94SLen Brown my_package_id = get_physical_package_id(cpu_id); 3729c98d5d94SLen Brown my_core_id = get_core_id(cpu_id); 3730e275b388SDasaratharaman Chandramouli my_thread_id = get_cpu_position_in_core(cpu_id); 3731e275b388SDasaratharaman Chandramouli if (!my_thread_id) 3732c98d5d94SLen Brown topo.num_cores++; 3733c98d5d94SLen Brown 3734c98d5d94SLen Brown init_counter(EVEN_COUNTERS, my_thread_id, my_core_id, my_package_id, cpu_id); 3735c98d5d94SLen Brown init_counter(ODD_COUNTERS, my_thread_id, my_core_id, my_package_id, cpu_id); 3736c98d5d94SLen Brown return 0; 3737c98d5d94SLen Brown } 3738c98d5d94SLen Brown 3739c98d5d94SLen Brown void allocate_output_buffer() 3740c98d5d94SLen Brown { 37413b4d5c7fSAndy Shevchenko output_buffer = calloc(1, (1 + topo.num_cpus) * 1024); 3742c98d5d94SLen Brown outp = output_buffer; 3743b2c95d90SJosh Triplett if (outp == NULL) 3744b2c95d90SJosh Triplett err(-1, "calloc output buffer"); 3745c98d5d94SLen Brown } 374636229897SLen Brown void allocate_fd_percpu(void) 374736229897SLen Brown { 374801a67adfSMika Westerberg fd_percpu = calloc(topo.max_cpu_num + 1, sizeof(int)); 374936229897SLen Brown if (fd_percpu == NULL) 375036229897SLen Brown err(-1, "calloc fd_percpu"); 375136229897SLen Brown } 3752562a2d37SLen Brown void allocate_irq_buffers(void) 3753562a2d37SLen Brown { 3754562a2d37SLen Brown irq_column_2_cpu = calloc(topo.num_cpus, sizeof(int)); 3755562a2d37SLen Brown if (irq_column_2_cpu == NULL) 3756562a2d37SLen Brown err(-1, "calloc %d", topo.num_cpus); 3757c98d5d94SLen Brown 375801a67adfSMika Westerberg irqs_per_cpu = calloc(topo.max_cpu_num + 1, sizeof(int)); 3759562a2d37SLen Brown if (irqs_per_cpu == NULL) 376001a67adfSMika Westerberg err(-1, "calloc %d", topo.max_cpu_num + 1); 3761562a2d37SLen Brown } 3762c98d5d94SLen Brown void setup_all_buffers(void) 3763c98d5d94SLen Brown { 3764c98d5d94SLen Brown topology_probe(); 3765562a2d37SLen Brown allocate_irq_buffers(); 376636229897SLen Brown allocate_fd_percpu(); 3767c98d5d94SLen Brown allocate_counters(&thread_even, &core_even, &package_even); 3768c98d5d94SLen Brown allocate_counters(&thread_odd, &core_odd, &package_odd); 3769c98d5d94SLen Brown allocate_output_buffer(); 3770c98d5d94SLen Brown for_all_proc_cpus(initialize_counters); 3771c98d5d94SLen Brown } 37723b4d5c7fSAndy Shevchenko 37737ce7d5deSPrarit Bhargava void set_base_cpu(void) 37747ce7d5deSPrarit Bhargava { 37757ce7d5deSPrarit Bhargava base_cpu = sched_getcpu(); 37767ce7d5deSPrarit Bhargava if (base_cpu < 0) 37777ce7d5deSPrarit Bhargava err(-ENODEV, "No valid cpus found"); 37787ce7d5deSPrarit Bhargava 37797ce7d5deSPrarit Bhargava if (debug > 1) 3780b7d8c148SLen Brown fprintf(outf, "base_cpu = %d\n", base_cpu); 37817ce7d5deSPrarit Bhargava } 37827ce7d5deSPrarit Bhargava 3783103a8feaSLen Brown void turbostat_init() 3784103a8feaSLen Brown { 37857ce7d5deSPrarit Bhargava setup_all_buffers(); 37867ce7d5deSPrarit Bhargava set_base_cpu(); 3787103a8feaSLen Brown check_dev_msr(); 378898481e79SLen Brown check_permissions(); 3789fcd17211SLen Brown process_cpuid(); 3790103a8feaSLen Brown 3791103a8feaSLen Brown 3792d8af6f5fSLen Brown if (debug) 37937f5c258eSLen Brown for_all_cpus(print_hwp, ODD_COUNTERS); 37947f5c258eSLen Brown 37957f5c258eSLen Brown if (debug) 3796889facbeSLen Brown for_all_cpus(print_epb, ODD_COUNTERS); 3797889facbeSLen Brown 3798d8af6f5fSLen Brown if (debug) 37993a9a941dSLen Brown for_all_cpus(print_perf_limit, ODD_COUNTERS); 38003a9a941dSLen Brown 3801d8af6f5fSLen Brown if (debug) 3802889facbeSLen Brown for_all_cpus(print_rapl, ODD_COUNTERS); 3803889facbeSLen Brown 3804889facbeSLen Brown for_all_cpus(set_temperature_target, ODD_COUNTERS); 3805889facbeSLen Brown 3806d8af6f5fSLen Brown if (debug) 3807889facbeSLen Brown for_all_cpus(print_thermal, ODD_COUNTERS); 38085a63426eSLen Brown 38095a63426eSLen Brown if (debug && do_irtl_snb) 38105a63426eSLen Brown print_irtl(); 3811103a8feaSLen Brown } 3812103a8feaSLen Brown 3813103a8feaSLen Brown int fork_it(char **argv) 3814103a8feaSLen Brown { 3815103a8feaSLen Brown pid_t child_pid; 3816d91bb17cSLen Brown int status; 3817d15cf7c1SLen Brown 3818d91bb17cSLen Brown status = for_all_cpus(get_counters, EVEN_COUNTERS); 3819d91bb17cSLen Brown if (status) 3820d91bb17cSLen Brown exit(status); 3821d15cf7c1SLen Brown /* clear affinity side-effect of get_counters() */ 3822d15cf7c1SLen Brown sched_setaffinity(0, cpu_present_setsize, cpu_present_set); 3823103a8feaSLen Brown gettimeofday(&tv_even, (struct timezone *)NULL); 3824103a8feaSLen Brown 3825103a8feaSLen Brown child_pid = fork(); 3826103a8feaSLen Brown if (!child_pid) { 3827103a8feaSLen Brown /* child */ 3828103a8feaSLen Brown execvp(argv[0], argv); 3829103a8feaSLen Brown } else { 3830103a8feaSLen Brown 3831103a8feaSLen Brown /* parent */ 3832b2c95d90SJosh Triplett if (child_pid == -1) 3833b2c95d90SJosh Triplett err(1, "fork"); 3834103a8feaSLen Brown 3835103a8feaSLen Brown signal(SIGINT, SIG_IGN); 3836103a8feaSLen Brown signal(SIGQUIT, SIG_IGN); 3837b2c95d90SJosh Triplett if (waitpid(child_pid, &status, 0) == -1) 3838b2c95d90SJosh Triplett err(status, "waitpid"); 3839103a8feaSLen Brown } 3840c98d5d94SLen Brown /* 3841c98d5d94SLen Brown * n.b. fork_it() does not check for errors from for_all_cpus() 3842c98d5d94SLen Brown * because re-starting is problematic when forking 3843c98d5d94SLen Brown */ 3844c98d5d94SLen Brown for_all_cpus(get_counters, ODD_COUNTERS); 3845103a8feaSLen Brown gettimeofday(&tv_odd, (struct timezone *)NULL); 3846103a8feaSLen Brown timersub(&tv_odd, &tv_even, &tv_delta); 3847ba3dec99SLen Brown if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS)) 3848ba3dec99SLen Brown fprintf(outf, "%s: Counter reset detected\n", progname); 3849ba3dec99SLen Brown else { 3850c98d5d94SLen Brown compute_average(EVEN_COUNTERS); 3851c98d5d94SLen Brown format_all_counters(EVEN_COUNTERS); 3852ba3dec99SLen Brown } 3853103a8feaSLen Brown 3854b7d8c148SLen Brown fprintf(outf, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0); 3855b7d8c148SLen Brown 3856b7d8c148SLen Brown flush_output_stderr(); 3857103a8feaSLen Brown 3858d91bb17cSLen Brown return status; 3859103a8feaSLen Brown } 3860103a8feaSLen Brown 38613b4d5c7fSAndy Shevchenko int get_and_dump_counters(void) 38623b4d5c7fSAndy Shevchenko { 38633b4d5c7fSAndy Shevchenko int status; 38643b4d5c7fSAndy Shevchenko 38653b4d5c7fSAndy Shevchenko status = for_all_cpus(get_counters, ODD_COUNTERS); 38663b4d5c7fSAndy Shevchenko if (status) 38673b4d5c7fSAndy Shevchenko return status; 38683b4d5c7fSAndy Shevchenko 38693b4d5c7fSAndy Shevchenko status = for_all_cpus(dump_counters, ODD_COUNTERS); 38703b4d5c7fSAndy Shevchenko if (status) 38713b4d5c7fSAndy Shevchenko return status; 38723b4d5c7fSAndy Shevchenko 3873b7d8c148SLen Brown flush_output_stdout(); 38743b4d5c7fSAndy Shevchenko 38753b4d5c7fSAndy Shevchenko return status; 38763b4d5c7fSAndy Shevchenko } 38773b4d5c7fSAndy Shevchenko 3878d8af6f5fSLen Brown void print_version() { 3879*6886fee4SLen Brown fprintf(outf, "turbostat version 4.16 24 Dec 2016" 3880d8af6f5fSLen Brown " - Len Brown <lenb@kernel.org>\n"); 3881d8af6f5fSLen Brown } 3882d8af6f5fSLen Brown 3883388e9c81SLen Brown int add_counter(unsigned int msr_num, char *name, unsigned int width, 3884388e9c81SLen Brown enum counter_scope scope, enum counter_type type, 3885388e9c81SLen Brown enum counter_format format) 3886388e9c81SLen Brown { 3887388e9c81SLen Brown struct msr_counter *msrp; 3888388e9c81SLen Brown 3889388e9c81SLen Brown msrp = calloc(1, sizeof(struct msr_counter)); 3890388e9c81SLen Brown if (msrp == NULL) { 3891388e9c81SLen Brown perror("calloc"); 3892388e9c81SLen Brown exit(1); 3893388e9c81SLen Brown } 3894388e9c81SLen Brown 3895388e9c81SLen Brown msrp->msr_num = msr_num; 3896388e9c81SLen Brown strncpy(msrp->name, name, NAME_BYTES); 3897388e9c81SLen Brown msrp->width = width; 3898388e9c81SLen Brown msrp->type = type; 3899388e9c81SLen Brown msrp->format = format; 3900388e9c81SLen Brown 3901388e9c81SLen Brown switch (scope) { 3902388e9c81SLen Brown 3903388e9c81SLen Brown case SCOPE_CPU: 3904388e9c81SLen Brown sys.thread_counter_bytes += 64; 3905388e9c81SLen Brown msrp->next = sys.tp; 3906388e9c81SLen Brown sys.tp = msrp; 3907388e9c81SLen Brown sys.thread_counter_bytes += sizeof(unsigned long long); 3908388e9c81SLen Brown break; 3909388e9c81SLen Brown 3910388e9c81SLen Brown case SCOPE_CORE: 3911388e9c81SLen Brown sys.core_counter_bytes += 64; 3912388e9c81SLen Brown msrp->next = sys.cp; 3913388e9c81SLen Brown sys.cp = msrp; 3914388e9c81SLen Brown sys.core_counter_bytes += sizeof(unsigned long long); 3915388e9c81SLen Brown break; 3916388e9c81SLen Brown 3917388e9c81SLen Brown case SCOPE_PACKAGE: 3918388e9c81SLen Brown sys.package_counter_bytes += 64; 3919388e9c81SLen Brown msrp->next = sys.pp; 3920388e9c81SLen Brown sys.pp = msrp; 3921388e9c81SLen Brown sys.package_counter_bytes += sizeof(unsigned long long); 3922388e9c81SLen Brown break; 3923388e9c81SLen Brown } 3924388e9c81SLen Brown 3925388e9c81SLen Brown return 0; 3926388e9c81SLen Brown } 3927388e9c81SLen Brown 3928388e9c81SLen Brown void parse_add_command(char *add_command) 3929388e9c81SLen Brown { 3930388e9c81SLen Brown int msr_num = 0; 3931388e9c81SLen Brown char name_buffer[NAME_BYTES]; 3932388e9c81SLen Brown int width = 64; 3933388e9c81SLen Brown int fail = 0; 3934388e9c81SLen Brown enum counter_scope scope = SCOPE_CPU; 3935388e9c81SLen Brown enum counter_type type = COUNTER_CYCLES; 3936388e9c81SLen Brown enum counter_format format = FORMAT_DELTA; 3937388e9c81SLen Brown 3938388e9c81SLen Brown while (add_command) { 3939388e9c81SLen Brown 3940388e9c81SLen Brown if (sscanf(add_command, "msr0x%x", &msr_num) == 1) 3941388e9c81SLen Brown goto next; 3942388e9c81SLen Brown 3943388e9c81SLen Brown if (sscanf(add_command, "msr%d", &msr_num) == 1) 3944388e9c81SLen Brown goto next; 3945388e9c81SLen Brown 3946388e9c81SLen Brown if (sscanf(add_command, "u%d", &width) == 1) { 3947388e9c81SLen Brown if ((width == 32) || (width == 64)) 3948388e9c81SLen Brown goto next; 3949388e9c81SLen Brown width = 64; 3950388e9c81SLen Brown } 3951388e9c81SLen Brown if (!strncmp(add_command, "cpu", strlen("cpu"))) { 3952388e9c81SLen Brown scope = SCOPE_CPU; 3953388e9c81SLen Brown goto next; 3954388e9c81SLen Brown } 3955388e9c81SLen Brown if (!strncmp(add_command, "core", strlen("core"))) { 3956388e9c81SLen Brown scope = SCOPE_CORE; 3957388e9c81SLen Brown goto next; 3958388e9c81SLen Brown } 3959388e9c81SLen Brown if (!strncmp(add_command, "package", strlen("package"))) { 3960388e9c81SLen Brown scope = SCOPE_PACKAGE; 3961388e9c81SLen Brown goto next; 3962388e9c81SLen Brown } 3963388e9c81SLen Brown if (!strncmp(add_command, "cycles", strlen("cycles"))) { 3964388e9c81SLen Brown type = COUNTER_CYCLES; 3965388e9c81SLen Brown goto next; 3966388e9c81SLen Brown } 3967388e9c81SLen Brown if (!strncmp(add_command, "seconds", strlen("seconds"))) { 3968388e9c81SLen Brown type = COUNTER_SECONDS; 3969388e9c81SLen Brown goto next; 3970388e9c81SLen Brown } 3971388e9c81SLen Brown if (!strncmp(add_command, "raw", strlen("raw"))) { 3972388e9c81SLen Brown format = FORMAT_RAW; 3973388e9c81SLen Brown goto next; 3974388e9c81SLen Brown } 3975388e9c81SLen Brown if (!strncmp(add_command, "delta", strlen("delta"))) { 3976388e9c81SLen Brown format = FORMAT_DELTA; 3977388e9c81SLen Brown goto next; 3978388e9c81SLen Brown } 3979388e9c81SLen Brown if (!strncmp(add_command, "percent", strlen("percent"))) { 3980388e9c81SLen Brown format = FORMAT_PERCENT; 3981388e9c81SLen Brown goto next; 3982388e9c81SLen Brown } 3983388e9c81SLen Brown 3984388e9c81SLen Brown if (sscanf(add_command, "%18s,%*s", name_buffer) == 1) { /* 18 < NAME_BYTES */ 3985388e9c81SLen Brown char *eos; 3986388e9c81SLen Brown 3987388e9c81SLen Brown eos = strchr(name_buffer, ','); 3988388e9c81SLen Brown if (eos) 3989388e9c81SLen Brown *eos = '\0'; 3990388e9c81SLen Brown goto next; 3991388e9c81SLen Brown } 3992388e9c81SLen Brown 3993388e9c81SLen Brown next: 3994388e9c81SLen Brown add_command = strchr(add_command, ','); 3995388e9c81SLen Brown if (add_command) 3996388e9c81SLen Brown add_command++; 3997388e9c81SLen Brown 3998388e9c81SLen Brown } 3999388e9c81SLen Brown if (msr_num == 0) { 4000388e9c81SLen Brown fprintf(stderr, "--add: (msrDDD | msr0xXXX) required\n"); 4001388e9c81SLen Brown fail++; 4002388e9c81SLen Brown } 4003388e9c81SLen Brown 4004388e9c81SLen Brown /* generate default column header */ 4005388e9c81SLen Brown if (*name_buffer == '\0') { 4006388e9c81SLen Brown if (format == FORMAT_RAW) { 4007388e9c81SLen Brown if (width == 32) 4008388e9c81SLen Brown sprintf(name_buffer, "msr%d", msr_num); 4009388e9c81SLen Brown else 4010388e9c81SLen Brown sprintf(name_buffer, "MSR%d", msr_num); 4011388e9c81SLen Brown } else if (format == FORMAT_DELTA) { 4012388e9c81SLen Brown if (width == 32) 4013388e9c81SLen Brown sprintf(name_buffer, "cnt%d", msr_num); 4014388e9c81SLen Brown else 4015388e9c81SLen Brown sprintf(name_buffer, "CNT%d", msr_num); 4016388e9c81SLen Brown } else if (format == FORMAT_PERCENT) { 4017388e9c81SLen Brown if (width == 32) 4018388e9c81SLen Brown sprintf(name_buffer, "msr%d%%", msr_num); 4019388e9c81SLen Brown else 4020388e9c81SLen Brown sprintf(name_buffer, "MSR%d%%", msr_num); 4021388e9c81SLen Brown } 4022388e9c81SLen Brown } 4023388e9c81SLen Brown 4024388e9c81SLen Brown if (add_counter(msr_num, name_buffer, width, scope, type, format)) 4025388e9c81SLen Brown fail++; 4026388e9c81SLen Brown 4027388e9c81SLen Brown if (fail) { 4028388e9c81SLen Brown help(); 4029388e9c81SLen Brown exit(1); 4030388e9c81SLen Brown } 4031388e9c81SLen Brown } 4032103a8feaSLen Brown void cmdline(int argc, char **argv) 4033103a8feaSLen Brown { 4034103a8feaSLen Brown int opt; 4035d8af6f5fSLen Brown int option_index = 0; 4036d8af6f5fSLen Brown static struct option long_options[] = { 4037388e9c81SLen Brown {"add", required_argument, 0, 'a'}, 4038d8af6f5fSLen Brown {"Dump", no_argument, 0, 'D'}, 4039d8af6f5fSLen Brown {"debug", no_argument, 0, 'd'}, 4040d8af6f5fSLen Brown {"interval", required_argument, 0, 'i'}, 4041d8af6f5fSLen Brown {"help", no_argument, 0, 'h'}, 4042d8af6f5fSLen Brown {"Joules", no_argument, 0, 'J'}, 4043b7d8c148SLen Brown {"out", required_argument, 0, 'o'}, 4044d8af6f5fSLen Brown {"Package", no_argument, 0, 'p'}, 4045d8af6f5fSLen Brown {"processor", no_argument, 0, 'p'}, 4046d8af6f5fSLen Brown {"Summary", no_argument, 0, 'S'}, 4047d8af6f5fSLen Brown {"TCC", required_argument, 0, 'T'}, 4048d8af6f5fSLen Brown {"version", no_argument, 0, 'v' }, 4049d8af6f5fSLen Brown {0, 0, 0, 0 } 4050d8af6f5fSLen Brown }; 4051103a8feaSLen Brown 4052103a8feaSLen Brown progname = argv[0]; 4053103a8feaSLen Brown 4054b7d8c148SLen Brown while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:JM:m:o:PpST:v", 4055d8af6f5fSLen Brown long_options, &option_index)) != -1) { 4056103a8feaSLen Brown switch (opt) { 4057388e9c81SLen Brown case 'a': 4058388e9c81SLen Brown parse_add_command(optarg); 4059388e9c81SLen Brown break; 4060d8af6f5fSLen Brown case 'D': 4061d8af6f5fSLen Brown dump_only++; 40628e180f3cSLen Brown break; 4063d8af6f5fSLen Brown case 'd': 4064d8af6f5fSLen Brown debug++; 40652f32edf1SLen Brown break; 4066d8af6f5fSLen Brown case 'h': 4067d8af6f5fSLen Brown default: 4068d8af6f5fSLen Brown help(); 4069d8af6f5fSLen Brown exit(1); 4070d8af6f5fSLen Brown case 'i': 40712a0609c0SLen Brown { 40722a0609c0SLen Brown double interval = strtod(optarg, NULL); 40732a0609c0SLen Brown 40742a0609c0SLen Brown if (interval < 0.001) { 4075b7d8c148SLen Brown fprintf(outf, "interval %f seconds is too small\n", 40762a0609c0SLen Brown interval); 40772a0609c0SLen Brown exit(2); 40782a0609c0SLen Brown } 40792a0609c0SLen Brown 40802a0609c0SLen Brown interval_ts.tv_sec = interval; 40812a0609c0SLen Brown interval_ts.tv_nsec = (interval - interval_ts.tv_sec) * 1000000000; 40822a0609c0SLen Brown } 4083889facbeSLen Brown break; 40845c56be9aSDirk Brandewie case 'J': 40855c56be9aSDirk Brandewie rapl_joules++; 40865c56be9aSDirk Brandewie break; 4087b7d8c148SLen Brown case 'o': 4088b7d8c148SLen Brown outf = fopen_or_die(optarg, "w"); 4089b7d8c148SLen Brown break; 4090d8af6f5fSLen Brown case 'P': 4091d8af6f5fSLen Brown show_pkg_only++; 4092d8af6f5fSLen Brown break; 4093d8af6f5fSLen Brown case 'p': 4094d8af6f5fSLen Brown show_core_only++; 4095d8af6f5fSLen Brown break; 4096d8af6f5fSLen Brown case 'S': 4097d8af6f5fSLen Brown summary_only++; 4098d8af6f5fSLen Brown break; 4099d8af6f5fSLen Brown case 'T': 4100d8af6f5fSLen Brown tcc_activation_temp_override = atoi(optarg); 4101d8af6f5fSLen Brown break; 4102d8af6f5fSLen Brown case 'v': 4103d8af6f5fSLen Brown print_version(); 4104d8af6f5fSLen Brown exit(0); 4105d8af6f5fSLen Brown break; 4106103a8feaSLen Brown } 4107103a8feaSLen Brown } 4108103a8feaSLen Brown } 4109103a8feaSLen Brown 4110103a8feaSLen Brown int main(int argc, char **argv) 4111103a8feaSLen Brown { 4112b7d8c148SLen Brown outf = stderr; 4113b7d8c148SLen Brown 4114103a8feaSLen Brown cmdline(argc, argv); 4115103a8feaSLen Brown 4116d8af6f5fSLen Brown if (debug) 4117d8af6f5fSLen Brown print_version(); 4118103a8feaSLen Brown 4119103a8feaSLen Brown turbostat_init(); 4120103a8feaSLen Brown 41213b4d5c7fSAndy Shevchenko /* dump counters and exit */ 41223b4d5c7fSAndy Shevchenko if (dump_only) 41233b4d5c7fSAndy Shevchenko return get_and_dump_counters(); 41243b4d5c7fSAndy Shevchenko 4125103a8feaSLen Brown /* 4126103a8feaSLen Brown * if any params left, it must be a command to fork 4127103a8feaSLen Brown */ 4128103a8feaSLen Brown if (argc - optind) 4129103a8feaSLen Brown return fork_it(argv + optind); 4130103a8feaSLen Brown else 4131103a8feaSLen Brown turbostat_loop(); 4132103a8feaSLen Brown 4133103a8feaSLen Brown return 0; 4134103a8feaSLen Brown } 4135