FILE
turbostat.c
File preview with syntax highlighting.
linux-6.19.14/tools/power/x86/turbostat/turbostat.c
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * turbostat -- show CPU frequency and C-state residency 4 * on modern Intel and AMD processors. 5 * 6 * Copyright (c) 2025 Intel Corporation. 7 * Len Brown <len.brown@intel.com> 8 */ 9 10#define _GNU_SOURCE 11#include MSRHEADER 12 13// copied from arch/x86/include/asm/cpu_device_id.h 14#define VFM_MODEL_BIT 0 15#define VFM_FAMILY_BIT 8 16#define VFM_VENDOR_BIT 16 17#define VFM_RSVD_BIT 24 18 19#define VFM_MODEL_MASK GENMASK(VFM_FAMILY_BIT - 1, VFM_MODEL_BIT) 20#define VFM_FAMILY_MASK GENMASK(VFM_VENDOR_BIT - 1, VFM_FAMILY_BIT) 21#define VFM_VENDOR_MASK GENMASK(VFM_RSVD_BIT - 1, VFM_VENDOR_BIT) 22 23#define VFM_MODEL(vfm) (((vfm) & VFM_MODEL_MASK) >> VFM_MODEL_BIT) 24#define VFM_FAMILY(vfm) (((vfm) & VFM_FAMILY_MASK) >> VFM_FAMILY_BIT) 25#define VFM_VENDOR(vfm) (((vfm) & VFM_VENDOR_MASK) >> VFM_VENDOR_BIT) 26 27#define VFM_MAKE(_vendor, _family, _model) ( \ 28 ((_model) << VFM_MODEL_BIT) | \ 29 ((_family) << VFM_FAMILY_BIT) | \ 30 ((_vendor) << VFM_VENDOR_BIT) \ 31) 32// end copied section 33 34#define CPUID_LEAF_MODEL_ID 0x1A 35#define CPUID_LEAF_MODEL_ID_CORE_TYPE_SHIFT 24 36 37#define X86_VENDOR_INTEL 0 38 39#include INTEL_FAMILY_HEADER 40#include BUILD_BUG_HEADER 41#include <stdarg.h> 42#include <stdio.h> 43#include <err.h> 44#include <unistd.h> 45#include <sys/types.h> 46#include <sys/wait.h> 47#include <sys/stat.h> 48#include <sys/select.h> 49#include <sys/resource.h> 50#include <sys/mman.h> 51#include <fcntl.h> 52#include <signal.h> 53#include <sys/time.h> 54#include <stdlib.h> 55#include <getopt.h> 56#include <dirent.h> 57#include <string.h> 58#include <ctype.h> 59#include <sched.h> 60#include <time.h> 61#include <cpuid.h> 62#include <sys/capability.h> 63#include <errno.h> 64#include <math.h> 65#include <linux/perf_event.h> 66#include <asm/unistd.h> 67#include <stdbool.h> 68#include <assert.h> 69#include <linux/kernel.h> 70#include <limits.h> 71 72#define UNUSED(x) (void)(x) 73 74/* 75 * This list matches the column headers, except 76 * 1. built-in only, the sysfs counters are not here -- we learn of those at run-time 77 * 2. Core and CPU are moved to the end, we can't have strings that contain them 78 * matching on them for --show and --hide. 79 */ 80 81/* 82 * buffer size used by sscanf() for added column names 83 * Usually truncated to 7 characters, but also handles 18 columns for raw 64-bit counters 84 */ 85#define NAME_BYTES 20 86#define PATH_BYTES 128 87#define PERF_NAME_BYTES 128 88 89#define MAX_NOFILE 0x8000 90 91#define COUNTER_KIND_PERF_PREFIX "perf/" 92#define COUNTER_KIND_PERF_PREFIX_LEN strlen(COUNTER_KIND_PERF_PREFIX) 93#define PERF_DEV_NAME_BYTES 32 94#define PERF_EVT_NAME_BYTES 32 95 96#define INTEL_ECORE_TYPE 0x20 97#define INTEL_PCORE_TYPE 0x40 98 99#define ROUND_UP_TO_PAGE_SIZE(n) (((n) + 0x1000UL-1UL) & ~(0x1000UL-1UL)) 100 101enum counter_scope { SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE }; 102enum counter_type { COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC, COUNTER_K2M }; 103enum counter_format { FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT, FORMAT_AVERAGE }; 104enum counter_source { COUNTER_SOURCE_NONE, COUNTER_SOURCE_PERF, COUNTER_SOURCE_MSR }; 105 106struct perf_counter_info { 107 struct perf_counter_info *next; 108 109 /* How to open the counter / What counter it is. */ 110 char device[PERF_DEV_NAME_BYTES]; 111 char event[PERF_EVT_NAME_BYTES]; 112 113 /* How to show/format the counter. */ 114 char name[PERF_NAME_BYTES]; 115 unsigned int width; 116 enum counter_scope scope; 117 enum counter_type type; 118 enum counter_format format; 119 double scale; 120 121 /* For reading the counter. */ 122 int *fd_perf_per_domain; 123 size_t num_domains; 124}; 125 126struct sysfs_path { 127 char path[PATH_BYTES]; 128 int id; 129 struct sysfs_path *next; 130}; 131 132struct msr_counter { 133 unsigned int msr_num; 134 char name[NAME_BYTES]; 135 struct sysfs_path *sp; 136 unsigned int width; 137 enum counter_type type; 138 enum counter_format format; 139 struct msr_counter *next; 140 unsigned int flags; 141#define FLAGS_HIDE (1 << 0) 142#define FLAGS_SHOW (1 << 1) 143#define SYSFS_PERCPU (1 << 1) 144}; 145static int use_android_msr_path; 146 147struct msr_counter bic[] = { 148 { 0x0, "usec", NULL, 0, 0, 0, NULL, 0 }, 149 { 0x0, "Time_Of_Day_Seconds", NULL, 0, 0, 0, NULL, 0 }, 150 { 0x0, "Package", NULL, 0, 0, 0, NULL, 0 }, 151 { 0x0, "Node", NULL, 0, 0, 0, NULL, 0 }, 152 { 0x0, "Avg_MHz", NULL, 0, 0, 0, NULL, 0 }, 153 { 0x0, "Busy%", NULL, 0, 0, 0, NULL, 0 }, 154 { 0x0, "Bzy_MHz", NULL, 0, 0, 0, NULL, 0 }, 155 { 0x0, "TSC_MHz", NULL, 0, 0, 0, NULL, 0 }, 156 { 0x0, "IRQ", NULL, 0, 0, 0, NULL, 0 }, 157 { 0x0, "SMI", NULL, 32, 0, FORMAT_DELTA, NULL, 0 }, 158 { 0x0, "cpuidle", NULL, 0, 0, 0, NULL, 0 }, 159 { 0x0, "CPU%c1", NULL, 0, 0, 0, NULL, 0 }, 160 { 0x0, "CPU%c3", NULL, 0, 0, 0, NULL, 0 }, 161 { 0x0, "CPU%c6", NULL, 0, 0, 0, NULL, 0 }, 162 { 0x0, "CPU%c7", NULL, 0, 0, 0, NULL, 0 }, 163 { 0x0, "ThreadC", NULL, 0, 0, 0, NULL, 0 }, 164 { 0x0, "CoreTmp", NULL, 0, 0, 0, NULL, 0 }, 165 { 0x0, "CoreCnt", NULL, 0, 0, 0, NULL, 0 }, 166 { 0x0, "PkgTmp", NULL, 0, 0, 0, NULL, 0 }, 167 { 0x0, "GFX%rc6", NULL, 0, 0, 0, NULL, 0 }, 168 { 0x0, "GFXMHz", NULL, 0, 0, 0, NULL, 0 }, 169 { 0x0, "Pkg%pc2", NULL, 0, 0, 0, NULL, 0 }, 170 { 0x0, "Pkg%pc3", NULL, 0, 0, 0, NULL, 0 }, 171 { 0x0, "Pkg%pc6", NULL, 0, 0, 0, NULL, 0 }, 172 { 0x0, "Pkg%pc7", NULL, 0, 0, 0, NULL, 0 }, 173 { 0x0, "Pkg%pc8", NULL, 0, 0, 0, NULL, 0 }, 174 { 0x0, "Pkg%pc9", NULL, 0, 0, 0, NULL, 0 }, 175 { 0x0, "Pk%pc10", NULL, 0, 0, 0, NULL, 0 }, 176 { 0x0, "CPU%LPI", NULL, 0, 0, 0, NULL, 0 }, 177 { 0x0, "SYS%LPI", NULL, 0, 0, 0, NULL, 0 }, 178 { 0x0, "PkgWatt", NULL, 0, 0, 0, NULL, 0 }, 179 { 0x0, "CorWatt", NULL, 0, 0, 0, NULL, 0 }, 180 { 0x0, "GFXWatt", NULL, 0, 0, 0, NULL, 0 }, 181 { 0x0, "PkgCnt", NULL, 0, 0, 0, NULL, 0 }, 182 { 0x0, "RAMWatt", NULL, 0, 0, 0, NULL, 0 }, 183 { 0x0, "PKG_%", NULL, 0, 0, 0, NULL, 0 }, 184 { 0x0, "RAM_%", NULL, 0, 0, 0, NULL, 0 }, 185 { 0x0, "Pkg_J", NULL, 0, 0, 0, NULL, 0 }, 186 { 0x0, "Cor_J", NULL, 0, 0, 0, NULL, 0 }, 187 { 0x0, "GFX_J", NULL, 0, 0, 0, NULL, 0 }, 188 { 0x0, "RAM_J", NULL, 0, 0, 0, NULL, 0 }, 189 { 0x0, "Mod%c6", NULL, 0, 0, 0, NULL, 0 }, 190 { 0x0, "Totl%C0", NULL, 0, 0, 0, NULL, 0 }, 191 { 0x0, "Any%C0", NULL, 0, 0, 0, NULL, 0 }, 192 { 0x0, "GFX%C0", NULL, 0, 0, 0, NULL, 0 }, 193 { 0x0, "CPUGFX%", NULL, 0, 0, 0, NULL, 0 }, 194 { 0x0, "Core", NULL, 0, 0, 0, NULL, 0 }, 195 { 0x0, "CPU", NULL, 0, 0, 0, NULL, 0 }, 196 { 0x0, "APIC", NULL, 0, 0, 0, NULL, 0 }, 197 { 0x0, "X2APIC", NULL, 0, 0, 0, NULL, 0 }, 198 { 0x0, "Die", NULL, 0, 0, 0, NULL, 0 }, 199 { 0x0, "L3", NULL, 0, 0, 0, NULL, 0 }, 200 { 0x0, "GFXAMHz", NULL, 0, 0, 0, NULL, 0 }, 201 { 0x0, "IPC", NULL, 0, 0, 0, NULL, 0 }, 202 { 0x0, "CoreThr", NULL, 0, 0, 0, NULL, 0 }, 203 { 0x0, "UncMHz", NULL, 0, 0, 0, NULL, 0 }, 204 { 0x0, "SAM%mc6", NULL, 0, 0, 0, NULL, 0 }, 205 { 0x0, "SAMMHz", NULL, 0, 0, 0, NULL, 0 }, 206 { 0x0, "SAMAMHz", NULL, 0, 0, 0, NULL, 0 }, 207 { 0x0, "Die%c6", NULL, 0, 0, 0, NULL, 0 }, 208 { 0x0, "SysWatt", NULL, 0, 0, 0, NULL, 0 }, 209 { 0x0, "Sys_J", NULL, 0, 0, 0, NULL, 0 }, 210 { 0x0, "NMI", NULL, 0, 0, 0, NULL, 0 }, 211 { 0x0, "CPU%c1e", NULL, 0, 0, 0, NULL, 0 }, 212 { 0x0, "pct_idle", NULL, 0, 0, 0, NULL, 0 }, 213 { 0x0, "LLCkRPS", NULL, 0, 0, 0, NULL, 0 }, 214 { 0x0, "LLC%hit", NULL, 0, 0, 0, NULL, 0 }, 215}; 216 217/* n.b. bic_names must match the order in bic[], above */ 218enum bic_names { 219 BIC_USEC, 220 BIC_TOD, 221 BIC_Package, 222 BIC_Node, 223 BIC_Avg_MHz, 224 BIC_Busy, 225 BIC_Bzy_MHz, 226 BIC_TSC_MHz, 227 BIC_IRQ, 228 BIC_SMI, 229 BIC_cpuidle, 230 BIC_CPU_c1, 231 BIC_CPU_c3, 232 BIC_CPU_c6, 233 BIC_CPU_c7, 234 BIC_ThreadC, 235 BIC_CoreTmp, 236 BIC_CoreCnt, 237 BIC_PkgTmp, 238 BIC_GFX_rc6, 239 BIC_GFXMHz, 240 BIC_Pkgpc2, 241 BIC_Pkgpc3, 242 BIC_Pkgpc6, 243 BIC_Pkgpc7, 244 BIC_Pkgpc8, 245 BIC_Pkgpc9, 246 BIC_Pkgpc10, 247 BIC_CPU_LPI, 248 BIC_SYS_LPI, 249 BIC_PkgWatt, 250 BIC_CorWatt, 251 BIC_GFXWatt, 252 BIC_PkgCnt, 253 BIC_RAMWatt, 254 BIC_PKG__, 255 BIC_RAM__, 256 BIC_Pkg_J, 257 BIC_Cor_J, 258 BIC_GFX_J, 259 BIC_RAM_J, 260 BIC_Mod_c6, 261 BIC_Totl_c0, 262 BIC_Any_c0, 263 BIC_GFX_c0, 264 BIC_CPUGFX, 265 BIC_Core, 266 BIC_CPU, 267 BIC_APIC, 268 BIC_X2APIC, 269 BIC_Die, 270 BIC_L3, 271 BIC_GFXACTMHz, 272 BIC_IPC, 273 BIC_CORE_THROT_CNT, 274 BIC_UNCORE_MHZ, 275 BIC_SAM_mc6, 276 BIC_SAMMHz, 277 BIC_SAMACTMHz, 278 BIC_Diec6, 279 BIC_SysWatt, 280 BIC_Sys_J, 281 BIC_NMI, 282 BIC_CPU_c1e, 283 BIC_pct_idle, 284 BIC_LLC_RPS, 285 BIC_LLC_HIT, 286 MAX_BIC 287}; 288 289void print_bic_set(char *s, cpu_set_t *set) 290{ 291 int i; 292 293 assert(MAX_BIC < CPU_SETSIZE); 294 295 printf("%s:", s); 296 297 for (i = 0; i <= MAX_BIC; ++i) { 298 299 if (CPU_ISSET(i, set)) { 300 assert(i < MAX_BIC); 301 printf(" %s", bic[i].name); 302 } 303 } 304 putchar('\n'); 305} 306 307static cpu_set_t bic_group_topology; 308static cpu_set_t bic_group_thermal_pwr; 309static cpu_set_t bic_group_frequency; 310static cpu_set_t bic_group_hw_idle; 311static cpu_set_t bic_group_sw_idle; 312static cpu_set_t bic_group_idle; 313static cpu_set_t bic_group_cache; 314static cpu_set_t bic_group_other; 315static cpu_set_t bic_group_disabled_by_default; 316static cpu_set_t bic_enabled; 317static cpu_set_t bic_present; 318 319/* modify */ 320#define BIC_INIT(set) CPU_ZERO(set) 321 322#define SET_BIC(COUNTER_NUMBER, set) CPU_SET(COUNTER_NUMBER, set) 323#define CLR_BIC(COUNTER_NUMBER, set) CPU_CLR(COUNTER_NUMBER, set) 324 325#define BIC_PRESENT(COUNTER_NUMBER) SET_BIC(COUNTER_NUMBER, &bic_present) 326#define BIC_NOT_PRESENT(COUNTER_NUMBER) CPU_CLR(COUNTER_NUMBER, &bic_present) 327 328/* test */ 329#define BIC_IS_ENABLED(COUNTER_NUMBER) CPU_ISSET(COUNTER_NUMBER, &bic_enabled) 330#define DO_BIC_READ(COUNTER_NUMBER) CPU_ISSET(COUNTER_NUMBER, &bic_present) 331#define DO_BIC(COUNTER_NUMBER) (CPU_ISSET(COUNTER_NUMBER, &bic_enabled) && CPU_ISSET(COUNTER_NUMBER, &bic_present)) 332 333static void bic_set_all(cpu_set_t *set) 334{ 335 int i; 336 337 assert(MAX_BIC < CPU_SETSIZE); 338 339 for (i = 0; i < MAX_BIC; ++i) 340 SET_BIC(i, set); 341} 342 343/* 344 * bic_clear_bits() 345 * clear all the bits from "clr" in "dst" 346 */ 347static void bic_clear_bits(cpu_set_t *dst, cpu_set_t *clr) 348{ 349 int i; 350 351 assert(MAX_BIC < CPU_SETSIZE); 352 353 for (i = 0; i < MAX_BIC; ++i) 354 if (CPU_ISSET(i, clr)) 355 CLR_BIC(i, dst); 356} 357 358static void bic_groups_init(void) 359{ 360 BIC_INIT(&bic_group_topology); 361 SET_BIC(BIC_Package, &bic_group_topology); 362 SET_BIC(BIC_Node, &bic_group_topology); 363 SET_BIC(BIC_CoreCnt, &bic_group_topology); 364 SET_BIC(BIC_PkgCnt, &bic_group_topology); 365 SET_BIC(BIC_Core, &bic_group_topology); 366 SET_BIC(BIC_CPU, &bic_group_topology); 367 SET_BIC(BIC_Die, &bic_group_topology); 368 SET_BIC(BIC_L3, &bic_group_topology); 369 370 BIC_INIT(&bic_group_thermal_pwr); 371 SET_BIC(BIC_CoreTmp, &bic_group_thermal_pwr); 372 SET_BIC(BIC_PkgTmp, &bic_group_thermal_pwr); 373 SET_BIC(BIC_PkgWatt, &bic_group_thermal_pwr); 374 SET_BIC(BIC_CorWatt, &bic_group_thermal_pwr); 375 SET_BIC(BIC_GFXWatt, &bic_group_thermal_pwr); 376 SET_BIC(BIC_RAMWatt, &bic_group_thermal_pwr); 377 SET_BIC(BIC_PKG__, &bic_group_thermal_pwr); 378 SET_BIC(BIC_RAM__, &bic_group_thermal_pwr); 379 SET_BIC(BIC_SysWatt, &bic_group_thermal_pwr); 380 381 BIC_INIT(&bic_group_frequency); 382 SET_BIC(BIC_Avg_MHz, &bic_group_frequency); 383 SET_BIC(BIC_Busy, &bic_group_frequency); 384 SET_BIC(BIC_Bzy_MHz, &bic_group_frequency); 385 SET_BIC(BIC_TSC_MHz, &bic_group_frequency); 386 SET_BIC(BIC_GFXMHz, &bic_group_frequency); 387 SET_BIC(BIC_GFXACTMHz, &bic_group_frequency); 388 SET_BIC(BIC_SAMMHz, &bic_group_frequency); 389 SET_BIC(BIC_SAMACTMHz, &bic_group_frequency); 390 SET_BIC(BIC_UNCORE_MHZ, &bic_group_frequency); 391 392 BIC_INIT(&bic_group_hw_idle); 393 SET_BIC(BIC_Busy, &bic_group_hw_idle); 394 SET_BIC(BIC_CPU_c1, &bic_group_hw_idle); 395 SET_BIC(BIC_CPU_c3, &bic_group_hw_idle); 396 SET_BIC(BIC_CPU_c6, &bic_group_hw_idle); 397 SET_BIC(BIC_CPU_c7, &bic_group_hw_idle); 398 SET_BIC(BIC_GFX_rc6, &bic_group_hw_idle); 399 SET_BIC(BIC_Pkgpc2, &bic_group_hw_idle); 400 SET_BIC(BIC_Pkgpc3, &bic_group_hw_idle); 401 SET_BIC(BIC_Pkgpc6, &bic_group_hw_idle); 402 SET_BIC(BIC_Pkgpc7, &bic_group_hw_idle); 403 SET_BIC(BIC_Pkgpc8, &bic_group_hw_idle); 404 SET_BIC(BIC_Pkgpc9, &bic_group_hw_idle); 405 SET_BIC(BIC_Pkgpc10, &bic_group_hw_idle); 406 SET_BIC(BIC_CPU_LPI, &bic_group_hw_idle); 407 SET_BIC(BIC_SYS_LPI, &bic_group_hw_idle); 408 SET_BIC(BIC_Mod_c6, &bic_group_hw_idle); 409 SET_BIC(BIC_Totl_c0, &bic_group_hw_idle); 410 SET_BIC(BIC_Any_c0, &bic_group_hw_idle); 411 SET_BIC(BIC_GFX_c0, &bic_group_hw_idle); 412 SET_BIC(BIC_CPUGFX, &bic_group_hw_idle); 413 SET_BIC(BIC_SAM_mc6, &bic_group_hw_idle); 414 SET_BIC(BIC_Diec6, &bic_group_hw_idle); 415 416 BIC_INIT(&bic_group_sw_idle); 417 SET_BIC(BIC_Busy, &bic_group_sw_idle); 418 SET_BIC(BIC_cpuidle, &bic_group_sw_idle); 419 SET_BIC(BIC_pct_idle, &bic_group_sw_idle); 420 421 BIC_INIT(&bic_group_idle); 422 423 CPU_OR(&bic_group_idle, &bic_group_idle, &bic_group_hw_idle); 424 SET_BIC(BIC_pct_idle, &bic_group_idle); 425 426 BIC_INIT(&bic_group_cache); 427 SET_BIC(BIC_LLC_RPS, &bic_group_cache); 428 SET_BIC(BIC_LLC_HIT, &bic_group_cache); 429 430 BIC_INIT(&bic_group_other); 431 SET_BIC(BIC_IRQ, &bic_group_other); 432 SET_BIC(BIC_NMI, &bic_group_other); 433 SET_BIC(BIC_SMI, &bic_group_other); 434 SET_BIC(BIC_ThreadC, &bic_group_other); 435 SET_BIC(BIC_CoreTmp, &bic_group_other); 436 SET_BIC(BIC_IPC, &bic_group_other); 437 438 BIC_INIT(&bic_group_disabled_by_default); 439 SET_BIC(BIC_USEC, &bic_group_disabled_by_default); 440 SET_BIC(BIC_TOD, &bic_group_disabled_by_default); 441 SET_BIC(BIC_cpuidle, &bic_group_disabled_by_default); 442 SET_BIC(BIC_APIC, &bic_group_disabled_by_default); 443 SET_BIC(BIC_X2APIC, &bic_group_disabled_by_default); 444 445 BIC_INIT(&bic_enabled); 446 bic_set_all(&bic_enabled); 447 bic_clear_bits(&bic_enabled, &bic_group_disabled_by_default); 448 449 BIC_INIT(&bic_present); 450 SET_BIC(BIC_USEC, &bic_present); 451 SET_BIC(BIC_TOD, &bic_present); 452 SET_BIC(BIC_cpuidle, &bic_present); 453 SET_BIC(BIC_APIC, &bic_present); 454 SET_BIC(BIC_X2APIC, &bic_present); 455 SET_BIC(BIC_pct_idle, &bic_present); 456} 457 458/* 459 * MSR_PKG_CST_CONFIG_CONTROL decoding for pkg_cstate_limit: 460 * If you change the values, note they are used both in comparisons 461 * (>= PCL__7) and to index pkg_cstate_limit_strings[]. 462 */ 463#define PCLUKN 0 /* Unknown */ 464#define PCLRSV 1 /* Reserved */ 465#define PCL__0 2 /* PC0 */ 466#define PCL__1 3 /* PC1 */ 467#define PCL__2 4 /* PC2 */ 468#define PCL__3 5 /* PC3 */ 469#define PCL__4 6 /* PC4 */ 470#define PCL__6 7 /* PC6 */ 471#define PCL_6N 8 /* PC6 No Retention */ 472#define PCL_6R 9 /* PC6 Retention */ 473#define PCL__7 10 /* PC7 */ 474#define PCL_7S 11 /* PC7 Shrink */ 475#define PCL__8 12 /* PC8 */ 476#define PCL__9 13 /* PC9 */ 477#define PCL_10 14 /* PC10 */ 478#define PCLUNL 15 /* Unlimited */ 479 480char *proc_stat = "/proc/stat"; 481FILE *outf; 482int *fd_percpu; 483int *fd_instr_count_percpu; 484int *fd_llc_percpu; 485struct timeval interval_tv = { 5, 0 }; 486struct timespec interval_ts = { 5, 0 }; 487 488unsigned int num_iterations; 489unsigned int header_iterations; 490unsigned int debug; 491unsigned int quiet; 492unsigned int shown; 493unsigned int sums_need_wide_columns; 494unsigned int rapl_joules; 495unsigned int valid_rapl_msrs; 496unsigned int summary_only; 497unsigned int list_header_only; 498unsigned int dump_only; 499unsigned int force_load; 500unsigned int cpuid_has_aperf_mperf; 501unsigned int has_aperf_access; 502unsigned int has_epb; 503unsigned int has_turbo; 504unsigned int is_hybrid; 505unsigned int units = 1000000; /* MHz etc */ 506unsigned int genuine_intel; 507unsigned int authentic_amd; 508unsigned int hygon_genuine; 509unsigned int max_level, max_extended_level; 510unsigned int has_invariant_tsc; 511unsigned int aperf_mperf_multiplier = 1; 512double bclk; 513double base_hz; 514unsigned int has_base_hz; 515double tsc_tweak = 1.0; 516unsigned int show_pkg_only; 517unsigned int show_core_only; 518char *output_buffer, *outp; 519unsigned int do_dts; 520unsigned int do_ptm; 521unsigned int do_ipc; 522unsigned long long cpuidle_cur_cpu_lpi_us; 523unsigned long long cpuidle_cur_sys_lpi_us; 524unsigned int tj_max; 525unsigned int tj_max_override; 526double rapl_power_units, rapl_time_units; 527double rapl_dram_energy_units, rapl_energy_units, rapl_psys_energy_units; 528double rapl_joule_counter_range; 529unsigned int crystal_hz; 530unsigned long long tsc_hz; 531int base_cpu; 532unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */ 533 /* IA32_HWP_REQUEST, IA32_HWP_STATUS */ 534unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */ 535unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */ 536unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */ 537unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */ 538unsigned int first_counter_read = 1; 539 540static struct timeval procsysfs_tv_begin; 541 542int ignore_stdin; 543bool no_msr; 544bool no_perf; 545 546enum gfx_sysfs_idx { 547 GFX_rc6, 548 GFX_MHz, 549 GFX_ACTMHz, 550 SAM_mc6, 551 SAM_MHz, 552 SAM_ACTMHz, 553 GFX_MAX 554}; 555 556struct gfx_sysfs_info { 557 FILE *fp; 558 unsigned int val; 559 unsigned long long val_ull; 560}; 561 562static struct gfx_sysfs_info gfx_info[GFX_MAX]; 563 564int get_msr(int cpu, off_t offset, unsigned long long *msr); 565int add_counter(unsigned int msr_num, char *path, char *name, 566 unsigned int width, enum counter_scope scope, enum counter_type type, enum counter_format format, int flags, int package_num); 567 568/* Model specific support Start */ 569 570/* List of features that may diverge among different platforms */ 571struct platform_features { 572 bool has_msr_misc_feature_control; /* MSR_MISC_FEATURE_CONTROL */ 573 bool has_msr_misc_pwr_mgmt; /* MSR_MISC_PWR_MGMT */ 574 bool has_nhm_msrs; /* MSR_PLATFORM_INFO, MSR_IA32_TEMPERATURE_TARGET, MSR_SMI_COUNT, MSR_PKG_CST_CONFIG_CONTROL, MSR_IA32_POWER_CTL, TRL MSRs */ 575 bool has_config_tdp; /* MSR_CONFIG_TDP_NOMINAL/LEVEL_1/LEVEL_2/CONTROL, MSR_TURBO_ACTIVATION_RATIO */ 576 int bclk_freq; /* CPU base clock */ 577 int crystal_freq; /* Crystal clock to use when not available from CPUID.15 */ 578 int supported_cstates; /* Core cstates and Package cstates supported */ 579 int cst_limit; /* MSR_PKG_CST_CONFIG_CONTROL */ 580 bool has_cst_auto_convension; /* AUTOMATIC_CSTATE_CONVERSION bit in MSR_PKG_CST_CONFIG_CONTROL */ 581 bool has_irtl_msrs; /* MSR_PKGC3/PKGC6/PKGC7/PKGC8/PKGC9/PKGC10_IRTL */ 582 bool has_msr_core_c1_res; /* MSR_CORE_C1_RES */ 583 bool has_msr_module_c6_res_ms; /* MSR_MODULE_C6_RES_MS */ 584 bool has_msr_c6_demotion_policy_config; /* MSR_CC6_DEMOTION_POLICY_CONFIG/MSR_MC6_DEMOTION_POLICY_CONFIG */ 585 bool has_msr_atom_pkg_c6_residency; /* MSR_ATOM_PKG_C6_RESIDENCY */ 586 bool has_msr_knl_core_c6_residency; /* MSR_KNL_CORE_C6_RESIDENCY */ 587 bool has_ext_cst_msrs; /* MSR_PKG_WEIGHTED_CORE_C0_RES/MSR_PKG_ANY_CORE_C0_RES/MSR_PKG_ANY_GFXE_C0_RES/MSR_PKG_BOTH_CORE_GFXE_C0_RES */ 588 bool has_cst_prewake_bit; /* Cstate prewake bit in MSR_IA32_POWER_CTL */ 589 int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ 590 int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */ 591 int plat_rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */ 592 bool has_per_core_rapl; /* Indicates cores energy collection is per-core, not per-package. AMD specific for now */ 593 bool has_rapl_divisor; /* Divisor for Energy unit raw value from MSR_RAPL_POWER_UNIT */ 594 bool has_fixed_rapl_unit; /* Fixed Energy Unit used for DRAM RAPL Domain */ 595 bool has_fixed_rapl_psys_unit; /* Fixed Energy Unit used for PSYS RAPL Domain */ 596 int rapl_quirk_tdp; /* Hardcoded TDP value when cannot be retrieved from hardware */ 597 int tcc_offset_bits; /* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */ 598 bool enable_tsc_tweak; /* Use CPU Base freq instead of TSC freq for aperf/mperf counter */ 599 bool need_perf_multiplier; /* mperf/aperf multiplier */ 600}; 601 602struct platform_data { 603 unsigned int vfm; 604 const struct platform_features *features; 605}; 606 607/* For BCLK */ 608enum bclk_freq { 609 BCLK_100MHZ = 1, 610 BCLK_133MHZ, 611 BCLK_SLV, 612}; 613 614#define SLM_BCLK_FREQS 5 615double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0 }; 616 617double slm_bclk(void) 618{ 619 unsigned long long msr = 3; 620 unsigned int i; 621 double freq; 622 623 if (get_msr(base_cpu, MSR_FSB_FREQ, &msr)) 624 fprintf(outf, "SLM BCLK: unknown\n"); 625 626 i = msr & 0xf; 627 if (i >= SLM_BCLK_FREQS) { 628 fprintf(outf, "SLM BCLK[%d] invalid\n", i); 629 i = 3; 630 } 631 freq = slm_freq_table[i]; 632 633 if (!quiet) 634 fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq); 635 636 return freq; 637} 638 639/* For Package cstate limit */ 640enum package_cstate_limit { 641 CST_LIMIT_NHM = 1, 642 CST_LIMIT_SNB, 643 CST_LIMIT_HSW, 644 CST_LIMIT_SKX, 645 CST_LIMIT_ICX, 646 CST_LIMIT_SLV, 647 CST_LIMIT_AMT, 648 CST_LIMIT_KNL, 649 CST_LIMIT_GMT, 650}; 651 652/* For Turbo Ratio Limit MSRs */ 653enum turbo_ratio_limit_msrs { 654 TRL_BASE = BIT(0), 655 TRL_LIMIT1 = BIT(1), 656 TRL_LIMIT2 = BIT(2), 657 TRL_ATOM = BIT(3), 658 TRL_KNL = BIT(4), 659 TRL_CORECOUNT = BIT(5), 660}; 661 662/* For Perf Limit Reason MSRs */ 663enum perf_limit_reason_msrs { 664 PLR_CORE = BIT(0), 665 PLR_GFX = BIT(1), 666 PLR_RING = BIT(2), 667}; 668 669/* For RAPL MSRs */ 670enum rapl_msrs { 671 RAPL_PKG_POWER_LIMIT = BIT(0), /* 0x610 MSR_PKG_POWER_LIMIT */ 672 RAPL_PKG_ENERGY_STATUS = BIT(1), /* 0x611 MSR_PKG_ENERGY_STATUS */ 673 RAPL_PKG_PERF_STATUS = BIT(2), /* 0x613 MSR_PKG_PERF_STATUS */ 674 RAPL_PKG_POWER_INFO = BIT(3), /* 0x614 MSR_PKG_POWER_INFO */ 675 RAPL_DRAM_POWER_LIMIT = BIT(4), /* 0x618 MSR_DRAM_POWER_LIMIT */ 676 RAPL_DRAM_ENERGY_STATUS = BIT(5), /* 0x619 MSR_DRAM_ENERGY_STATUS */ 677 RAPL_DRAM_PERF_STATUS = BIT(6), /* 0x61b MSR_DRAM_PERF_STATUS */ 678 RAPL_DRAM_POWER_INFO = BIT(7), /* 0x61c MSR_DRAM_POWER_INFO */ 679 RAPL_CORE_POWER_LIMIT = BIT(8), /* 0x638 MSR_PP0_POWER_LIMIT */ 680 RAPL_CORE_ENERGY_STATUS = BIT(9), /* 0x639 MSR_PP0_ENERGY_STATUS */ 681 RAPL_CORE_POLICY = BIT(10), /* 0x63a MSR_PP0_POLICY */ 682 RAPL_GFX_POWER_LIMIT = BIT(11), /* 0x640 MSR_PP1_POWER_LIMIT */ 683 RAPL_GFX_ENERGY_STATUS = BIT(12), /* 0x641 MSR_PP1_ENERGY_STATUS */ 684 RAPL_GFX_POLICY = BIT(13), /* 0x642 MSR_PP1_POLICY */ 685 RAPL_AMD_PWR_UNIT = BIT(14), /* 0xc0010299 MSR_AMD_RAPL_POWER_UNIT */ 686 RAPL_AMD_CORE_ENERGY_STAT = BIT(15), /* 0xc001029a MSR_AMD_CORE_ENERGY_STATUS */ 687 RAPL_AMD_PKG_ENERGY_STAT = BIT(16), /* 0xc001029b MSR_AMD_PKG_ENERGY_STATUS */ 688 RAPL_PLATFORM_ENERGY_LIMIT = BIT(17), /* 0x64c MSR_PLATFORM_ENERGY_LIMIT */ 689 RAPL_PLATFORM_ENERGY_STATUS = BIT(18), /* 0x64d MSR_PLATFORM_ENERGY_STATUS */ 690}; 691 692#define RAPL_PKG (RAPL_PKG_ENERGY_STATUS | RAPL_PKG_POWER_LIMIT) 693#define RAPL_DRAM (RAPL_DRAM_ENERGY_STATUS | RAPL_DRAM_POWER_LIMIT) 694#define RAPL_CORE (RAPL_CORE_ENERGY_STATUS | RAPL_CORE_POWER_LIMIT) 695#define RAPL_GFX (RAPL_GFX_POWER_LIMIT | RAPL_GFX_ENERGY_STATUS) 696#define RAPL_PSYS (RAPL_PLATFORM_ENERGY_STATUS | RAPL_PLATFORM_ENERGY_LIMIT) 697 698#define RAPL_PKG_ALL (RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO) 699#define RAPL_DRAM_ALL (RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_DRAM_POWER_INFO) 700#define RAPL_CORE_ALL (RAPL_CORE | RAPL_CORE_POLICY) 701#define RAPL_GFX_ALL (RAPL_GFX | RAPL_GFX_POLICY) 702 703#define RAPL_AMD_F17H (RAPL_AMD_PWR_UNIT | RAPL_AMD_CORE_ENERGY_STAT | RAPL_AMD_PKG_ENERGY_STAT) 704 705/* For Cstates */ 706enum cstates { 707 CC1 = BIT(0), 708 CC3 = BIT(1), 709 CC6 = BIT(2), 710 CC7 = BIT(3), 711 PC2 = BIT(4), 712 PC3 = BIT(5), 713 PC6 = BIT(6), 714 PC7 = BIT(7), 715 PC8 = BIT(8), 716 PC9 = BIT(9), 717 PC10 = BIT(10), 718}; 719 720static const struct platform_features nhm_features = { 721 .has_msr_misc_pwr_mgmt = 1, 722 .has_nhm_msrs = 1, 723 .bclk_freq = BCLK_133MHZ, 724 .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6, 725 .cst_limit = CST_LIMIT_NHM, 726 .trl_msrs = TRL_BASE, 727}; 728 729static const struct platform_features nhx_features = { 730 .has_msr_misc_pwr_mgmt = 1, 731 .has_nhm_msrs = 1, 732 .bclk_freq = BCLK_133MHZ, 733 .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6, 734 .cst_limit = CST_LIMIT_NHM, 735}; 736 737static const struct platform_features snb_features = { 738 .has_msr_misc_feature_control = 1, 739 .has_msr_misc_pwr_mgmt = 1, 740 .has_nhm_msrs = 1, 741 .bclk_freq = BCLK_100MHZ, 742 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, 743 .cst_limit = CST_LIMIT_SNB, 744 .has_irtl_msrs = 1, 745 .trl_msrs = TRL_BASE, 746 .plat_rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, 747}; 748 749static const struct platform_features snx_features = { 750 .has_msr_misc_feature_control = 1, 751 .has_msr_misc_pwr_mgmt = 1, 752 .has_nhm_msrs = 1, 753 .bclk_freq = BCLK_100MHZ, 754 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, 755 .cst_limit = CST_LIMIT_SNB, 756 .has_irtl_msrs = 1, 757 .trl_msrs = TRL_BASE, 758 .plat_rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL, 759}; 760 761static const struct platform_features ivb_features = { 762 .has_msr_misc_feature_control = 1, 763 .has_msr_misc_pwr_mgmt = 1, 764 .has_nhm_msrs = 1, 765 .has_config_tdp = 1, 766 .bclk_freq = BCLK_100MHZ, 767 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, 768 .cst_limit = CST_LIMIT_SNB, 769 .has_irtl_msrs = 1, 770 .trl_msrs = TRL_BASE, 771 .plat_rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, 772}; 773 774static const struct platform_features ivx_features = { 775 .has_msr_misc_feature_control = 1, 776 .has_msr_misc_pwr_mgmt = 1, 777 .has_nhm_msrs = 1, 778 .bclk_freq = BCLK_100MHZ, 779 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, 780 .cst_limit = CST_LIMIT_SNB, 781 .has_irtl_msrs = 1, 782 .trl_msrs = TRL_BASE | TRL_LIMIT1, 783 .plat_rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL, 784}; 785 786static const struct platform_features hsw_features = { 787 .has_msr_misc_feature_control = 1, 788 .has_msr_misc_pwr_mgmt = 1, 789 .has_nhm_msrs = 1, 790 .has_config_tdp = 1, 791 .bclk_freq = BCLK_100MHZ, 792 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, 793 .cst_limit = CST_LIMIT_HSW, 794 .has_irtl_msrs = 1, 795 .trl_msrs = TRL_BASE, 796 .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, 797 .plat_rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, 798}; 799 800static const struct platform_features hsx_features = { 801 .has_msr_misc_feature_control = 1, 802 .has_msr_misc_pwr_mgmt = 1, 803 .has_nhm_msrs = 1, 804 .has_config_tdp = 1, 805 .bclk_freq = BCLK_100MHZ, 806 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, 807 .cst_limit = CST_LIMIT_HSW, 808 .has_irtl_msrs = 1, 809 .trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2, 810 .plr_msrs = PLR_CORE | PLR_RING, 811 .plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, 812 .has_fixed_rapl_unit = 1, 813}; 814 815static const struct platform_features hswl_features = { 816 .has_msr_misc_feature_control = 1, 817 .has_msr_misc_pwr_mgmt = 1, 818 .has_nhm_msrs = 1, 819 .has_config_tdp = 1, 820 .bclk_freq = BCLK_100MHZ, 821 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, 822 .cst_limit = CST_LIMIT_HSW, 823 .has_irtl_msrs = 1, 824 .trl_msrs = TRL_BASE, 825 .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, 826 .plat_rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, 827}; 828 829static const struct platform_features hswg_features = { 830 .has_msr_misc_feature_control = 1, 831 .has_msr_misc_pwr_mgmt = 1, 832 .has_nhm_msrs = 1, 833 .has_config_tdp = 1, 834 .bclk_freq = BCLK_100MHZ, 835 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, 836 .cst_limit = CST_LIMIT_HSW, 837 .has_irtl_msrs = 1, 838 .trl_msrs = TRL_BASE, 839 .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, 840 .plat_rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, 841}; 842 843static const struct platform_features bdw_features = { 844 .has_msr_misc_feature_control = 1, 845 .has_msr_misc_pwr_mgmt = 1, 846 .has_nhm_msrs = 1, 847 .has_config_tdp = 1, 848 .bclk_freq = BCLK_100MHZ, 849 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, 850 .cst_limit = CST_LIMIT_HSW, 851 .has_irtl_msrs = 1, 852 .trl_msrs = TRL_BASE, 853 .plat_rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, 854}; 855 856static const struct platform_features bdwg_features = { 857 .has_msr_misc_feature_control = 1, 858 .has_msr_misc_pwr_mgmt = 1, 859 .has_nhm_msrs = 1, 860 .has_config_tdp = 1, 861 .bclk_freq = BCLK_100MHZ, 862 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, 863 .cst_limit = CST_LIMIT_HSW, 864 .has_irtl_msrs = 1, 865 .trl_msrs = TRL_BASE, 866 .plat_rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, 867}; 868 869static const struct platform_features bdx_features = { 870 .has_msr_misc_feature_control = 1, 871 .has_msr_misc_pwr_mgmt = 1, 872 .has_nhm_msrs = 1, 873 .has_config_tdp = 1, 874 .bclk_freq = BCLK_100MHZ, 875 .supported_cstates = CC1 | CC3 | CC6 | PC2 | PC3 | PC6, 876 .cst_limit = CST_LIMIT_HSW, 877 .has_irtl_msrs = 1, 878 .has_cst_auto_convension = 1, 879 .trl_msrs = TRL_BASE, 880 .plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, 881 .has_fixed_rapl_unit = 1, 882}; 883 884static const struct platform_features skl_features = { 885 .has_msr_misc_feature_control = 1, 886 .has_msr_misc_pwr_mgmt = 1, 887 .has_nhm_msrs = 1, 888 .has_config_tdp = 1, 889 .bclk_freq = BCLK_100MHZ, 890 .crystal_freq = 24000000, 891 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, 892 .cst_limit = CST_LIMIT_HSW, 893 .has_irtl_msrs = 1, 894 .has_ext_cst_msrs = 1, 895 .trl_msrs = TRL_BASE, 896 .tcc_offset_bits = 6, 897 .plat_rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX | RAPL_PSYS, 898 .enable_tsc_tweak = 1, 899}; 900 901static const struct platform_features cnl_features = { 902 .has_msr_misc_feature_control = 1, 903 .has_msr_misc_pwr_mgmt = 1, 904 .has_nhm_msrs = 1, 905 .has_config_tdp = 1, 906 .bclk_freq = BCLK_100MHZ, 907 .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, 908 .cst_limit = CST_LIMIT_HSW, 909 .has_irtl_msrs = 1, 910 .has_msr_core_c1_res = 1, 911 .has_ext_cst_msrs = 1, 912 .trl_msrs = TRL_BASE, 913 .tcc_offset_bits = 6, 914 .plat_rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX | RAPL_PSYS, 915 .enable_tsc_tweak = 1, 916}; 917 918/* Copied from cnl_features, with PC7/PC9 removed */ 919static const struct platform_features adl_features = { 920 .has_msr_misc_feature_control = cnl_features.has_msr_misc_feature_control, 921 .has_msr_misc_pwr_mgmt = cnl_features.has_msr_misc_pwr_mgmt, 922 .has_nhm_msrs = cnl_features.has_nhm_msrs, 923 .has_config_tdp = cnl_features.has_config_tdp, 924 .bclk_freq = cnl_features.bclk_freq, 925 .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC8 | PC10, 926 .cst_limit = cnl_features.cst_limit, 927 .has_irtl_msrs = cnl_features.has_irtl_msrs, 928 .has_msr_core_c1_res = cnl_features.has_msr_core_c1_res, 929 .has_ext_cst_msrs = cnl_features.has_ext_cst_msrs, 930 .trl_msrs = cnl_features.trl_msrs, 931 .tcc_offset_bits = cnl_features.tcc_offset_bits, 932 .plat_rapl_msrs = cnl_features.plat_rapl_msrs, 933 .enable_tsc_tweak = cnl_features.enable_tsc_tweak, 934}; 935 936/* Copied from adl_features, with PC3/PC8 removed */ 937static const struct platform_features lnl_features = { 938 .has_msr_misc_feature_control = adl_features.has_msr_misc_feature_control, 939 .has_msr_misc_pwr_mgmt = adl_features.has_msr_misc_pwr_mgmt, 940 .has_nhm_msrs = adl_features.has_nhm_msrs, 941 .has_config_tdp = adl_features.has_config_tdp, 942 .bclk_freq = adl_features.bclk_freq, 943 .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC6 | PC10, 944 .cst_limit = adl_features.cst_limit, 945 .has_irtl_msrs = adl_features.has_irtl_msrs, 946 .has_msr_core_c1_res = adl_features.has_msr_core_c1_res, 947 .has_ext_cst_msrs = adl_features.has_ext_cst_msrs, 948 .trl_msrs = adl_features.trl_msrs, 949 .tcc_offset_bits = adl_features.tcc_offset_bits, 950 .plat_rapl_msrs = adl_features.plat_rapl_msrs, 951 .enable_tsc_tweak = adl_features.enable_tsc_tweak, 952}; 953 954static const struct platform_features skx_features = { 955 .has_msr_misc_feature_control = 1, 956 .has_msr_misc_pwr_mgmt = 1, 957 .has_nhm_msrs = 1, 958 .has_config_tdp = 1, 959 .bclk_freq = BCLK_100MHZ, 960 .supported_cstates = CC1 | CC6 | PC2 | PC6, 961 .cst_limit = CST_LIMIT_SKX, 962 .has_irtl_msrs = 1, 963 .has_cst_auto_convension = 1, 964 .trl_msrs = TRL_BASE | TRL_CORECOUNT, 965 .plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, 966 .has_fixed_rapl_unit = 1, 967}; 968 969static const struct platform_features icx_features = { 970 .has_msr_misc_feature_control = 1, 971 .has_msr_misc_pwr_mgmt = 1, 972 .has_nhm_msrs = 1, 973 .has_config_tdp = 1, 974 .bclk_freq = BCLK_100MHZ, 975 .supported_cstates = CC1 | CC6 | PC2 | PC6, 976 .cst_limit = CST_LIMIT_ICX, 977 .has_msr_core_c1_res = 1, 978 .has_irtl_msrs = 1, 979 .has_cst_prewake_bit = 1, 980 .trl_msrs = TRL_BASE | TRL_CORECOUNT, 981 .plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS, 982 .has_fixed_rapl_unit = 1, 983}; 984 985static const struct platform_features spr_features = { 986 .has_msr_misc_feature_control = 1, 987 .has_msr_misc_pwr_mgmt = 1, 988 .has_nhm_msrs = 1, 989 .has_config_tdp = 1, 990 .bclk_freq = BCLK_100MHZ, 991 .supported_cstates = CC1 | CC6 | PC2 | PC6, 992 .cst_limit = CST_LIMIT_SKX, 993 .has_msr_core_c1_res = 1, 994 .has_irtl_msrs = 1, 995 .has_cst_prewake_bit = 1, 996 .has_fixed_rapl_psys_unit = 1, 997 .trl_msrs = TRL_BASE | TRL_CORECOUNT, 998 .plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS, 999}; 1000 1001static const struct platform_features dmr_features = { 1002 .has_msr_misc_feature_control = spr_features.has_msr_misc_feature_control, 1003 .has_msr_misc_pwr_mgmt = spr_features.has_msr_misc_pwr_mgmt, 1004 .has_nhm_msrs = spr_features.has_nhm_msrs, 1005 .bclk_freq = spr_features.bclk_freq, 1006 .supported_cstates = spr_features.supported_cstates, 1007 .cst_limit = spr_features.cst_limit, 1008 .has_msr_core_c1_res = spr_features.has_msr_core_c1_res, 1009 .has_cst_prewake_bit = spr_features.has_cst_prewake_bit, 1010 .has_fixed_rapl_psys_unit = spr_features.has_fixed_rapl_psys_unit, 1011 .trl_msrs = spr_features.trl_msrs, 1012 .has_msr_module_c6_res_ms = 1, /* DMR has Dual-Core-Module and MC6 MSR */ 1013 .plat_rapl_msrs = 0, /* DMR does not have RAPL MSRs */ 1014 .plr_msrs = 0, /* DMR does not have PLR MSRs */ 1015 .has_irtl_msrs = 0, /* DMR does not have IRTL MSRs */ 1016 .has_config_tdp = 0, /* DMR does not have CTDP MSRs */ 1017}; 1018 1019static const struct platform_features srf_features = { 1020 .has_msr_misc_feature_control = 1, 1021 .has_msr_misc_pwr_mgmt = 1, 1022 .has_nhm_msrs = 1, 1023 .has_config_tdp = 1, 1024 .bclk_freq = BCLK_100MHZ, 1025 .supported_cstates = CC1 | CC6 | PC2 | PC6, 1026 .cst_limit = CST_LIMIT_SKX, 1027 .has_msr_core_c1_res = 1, 1028 .has_msr_module_c6_res_ms = 1, 1029 .has_irtl_msrs = 1, 1030 .has_cst_prewake_bit = 1, 1031 .trl_msrs = TRL_BASE | TRL_CORECOUNT, 1032 .plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS, 1033}; 1034 1035static const struct platform_features grr_features = { 1036 .has_msr_misc_feature_control = 1, 1037 .has_msr_misc_pwr_mgmt = 1, 1038 .has_nhm_msrs = 1, 1039 .has_config_tdp = 1, 1040 .bclk_freq = BCLK_100MHZ, 1041 .supported_cstates = CC1 | CC6, 1042 .cst_limit = CST_LIMIT_SKX, 1043 .has_msr_core_c1_res = 1, 1044 .has_msr_module_c6_res_ms = 1, 1045 .has_irtl_msrs = 1, 1046 .has_cst_prewake_bit = 1, 1047 .trl_msrs = TRL_BASE | TRL_CORECOUNT, 1048 .plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS, 1049}; 1050 1051static const struct platform_features slv_features = { 1052 .has_nhm_msrs = 1, 1053 .bclk_freq = BCLK_SLV, 1054 .supported_cstates = CC1 | CC6 | PC6, 1055 .cst_limit = CST_LIMIT_SLV, 1056 .has_msr_core_c1_res = 1, 1057 .has_msr_module_c6_res_ms = 1, 1058 .has_msr_c6_demotion_policy_config = 1, 1059 .has_msr_atom_pkg_c6_residency = 1, 1060 .trl_msrs = TRL_ATOM, 1061 .plat_rapl_msrs = RAPL_PKG | RAPL_CORE, 1062 .has_rapl_divisor = 1, 1063 .rapl_quirk_tdp = 30, 1064}; 1065 1066static const struct platform_features slvd_features = { 1067 .has_msr_misc_pwr_mgmt = 1, 1068 .has_nhm_msrs = 1, 1069 .bclk_freq = BCLK_SLV, 1070 .supported_cstates = CC1 | CC6 | PC3 | PC6, 1071 .cst_limit = CST_LIMIT_SLV, 1072 .has_msr_atom_pkg_c6_residency = 1, 1073 .trl_msrs = TRL_BASE, 1074 .plat_rapl_msrs = RAPL_PKG | RAPL_CORE, 1075 .rapl_quirk_tdp = 30, 1076}; 1077 1078static const struct platform_features amt_features = { 1079 .has_nhm_msrs = 1, 1080 .bclk_freq = BCLK_133MHZ, 1081 .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6, 1082 .cst_limit = CST_LIMIT_AMT, 1083 .trl_msrs = TRL_BASE, 1084}; 1085 1086static const struct platform_features gmt_features = { 1087 .has_msr_misc_pwr_mgmt = 1, 1088 .has_nhm_msrs = 1, 1089 .bclk_freq = BCLK_100MHZ, 1090 .crystal_freq = 19200000, 1091 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, 1092 .cst_limit = CST_LIMIT_GMT, 1093 .has_irtl_msrs = 1, 1094 .trl_msrs = TRL_BASE | TRL_CORECOUNT, 1095 .plat_rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, 1096}; 1097 1098static const struct platform_features gmtd_features = { 1099 .has_msr_misc_pwr_mgmt = 1, 1100 .has_nhm_msrs = 1, 1101 .bclk_freq = BCLK_100MHZ, 1102 .crystal_freq = 25000000, 1103 .supported_cstates = CC1 | CC6 | PC2 | PC6, 1104 .cst_limit = CST_LIMIT_GMT, 1105 .has_irtl_msrs = 1, 1106 .has_msr_core_c1_res = 1, 1107 .trl_msrs = TRL_BASE | TRL_CORECOUNT, 1108 .plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS, 1109}; 1110 1111static const struct platform_features gmtp_features = { 1112 .has_msr_misc_pwr_mgmt = 1, 1113 .has_nhm_msrs = 1, 1114 .bclk_freq = BCLK_100MHZ, 1115 .crystal_freq = 19200000, 1116 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, 1117 .cst_limit = CST_LIMIT_GMT, 1118 .has_irtl_msrs = 1, 1119 .trl_msrs = TRL_BASE, 1120 .plat_rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, 1121}; 1122 1123static const struct platform_features tmt_features = { 1124 .has_msr_misc_pwr_mgmt = 1, 1125 .has_nhm_msrs = 1, 1126 .bclk_freq = BCLK_100MHZ, 1127 .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, 1128 .cst_limit = CST_LIMIT_GMT, 1129 .has_irtl_msrs = 1, 1130 .trl_msrs = TRL_BASE, 1131 .plat_rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, 1132 .enable_tsc_tweak = 1, 1133}; 1134 1135static const struct platform_features tmtd_features = { 1136 .has_msr_misc_pwr_mgmt = 1, 1137 .has_nhm_msrs = 1, 1138 .bclk_freq = BCLK_100MHZ, 1139 .supported_cstates = CC1 | CC6, 1140 .cst_limit = CST_LIMIT_GMT, 1141 .has_irtl_msrs = 1, 1142 .trl_msrs = TRL_BASE | TRL_CORECOUNT, 1143 .plat_rapl_msrs = RAPL_PKG_ALL, 1144}; 1145 1146static const struct platform_features knl_features = { 1147 .has_msr_misc_pwr_mgmt = 1, 1148 .has_nhm_msrs = 1, 1149 .has_config_tdp = 1, 1150 .bclk_freq = BCLK_100MHZ, 1151 .supported_cstates = CC1 | CC6 | PC3 | PC6, 1152 .cst_limit = CST_LIMIT_KNL, 1153 .has_msr_knl_core_c6_residency = 1, 1154 .trl_msrs = TRL_KNL, 1155 .plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, 1156 .has_fixed_rapl_unit = 1, 1157 .need_perf_multiplier = 1, 1158}; 1159 1160static const struct platform_features default_features = { 1161}; 1162 1163static const struct platform_features amd_features_with_rapl = { 1164 .plat_rapl_msrs = RAPL_AMD_F17H, 1165 .has_per_core_rapl = 1, 1166 .rapl_quirk_tdp = 280, /* This is the max stock TDP of HEDT/Server Fam17h+ chips */ 1167}; 1168 1169static const struct platform_data turbostat_pdata[] = { 1170 { INTEL_NEHALEM, &nhm_features }, 1171 { INTEL_NEHALEM_G, &nhm_features }, 1172 { INTEL_NEHALEM_EP, &nhm_features }, 1173 { INTEL_NEHALEM_EX, &nhx_features }, 1174 { INTEL_WESTMERE, &nhm_features }, 1175 { INTEL_WESTMERE_EP, &nhm_features }, 1176 { INTEL_WESTMERE_EX, &nhx_features }, 1177 { INTEL_SANDYBRIDGE, &snb_features }, 1178 { INTEL_SANDYBRIDGE_X, &snx_features }, 1179 { INTEL_IVYBRIDGE, &ivb_features }, 1180 { INTEL_IVYBRIDGE_X, &ivx_features }, 1181 { INTEL_HASWELL, &hsw_features }, 1182 { INTEL_HASWELL_X, &hsx_features }, 1183 { INTEL_HASWELL_L, &hswl_features }, 1184 { INTEL_HASWELL_G, &hswg_features }, 1185 { INTEL_BROADWELL, &bdw_features }, 1186 { INTEL_BROADWELL_G, &bdwg_features }, 1187 { INTEL_BROADWELL_X, &bdx_features }, 1188 { INTEL_BROADWELL_D, &bdx_features }, 1189 { INTEL_SKYLAKE_L, &skl_features }, 1190 { INTEL_SKYLAKE, &skl_features }, 1191 { INTEL_SKYLAKE_X, &skx_features }, 1192 { INTEL_KABYLAKE_L, &skl_features }, 1193 { INTEL_KABYLAKE, &skl_features }, 1194 { INTEL_COMETLAKE, &skl_features }, 1195 { INTEL_COMETLAKE_L, &skl_features }, 1196 { INTEL_CANNONLAKE_L, &cnl_features }, 1197 { INTEL_ICELAKE_X, &icx_features }, 1198 { INTEL_ICELAKE_D, &icx_features }, 1199 { INTEL_ICELAKE_L, &cnl_features }, 1200 { INTEL_ICELAKE_NNPI, &cnl_features }, 1201 { INTEL_ROCKETLAKE, &cnl_features }, 1202 { INTEL_TIGERLAKE_L, &cnl_features }, 1203 { INTEL_TIGERLAKE, &cnl_features }, 1204 { INTEL_SAPPHIRERAPIDS_X, &spr_features }, 1205 { INTEL_EMERALDRAPIDS_X, &spr_features }, 1206 { INTEL_GRANITERAPIDS_X, &spr_features }, 1207 { INTEL_GRANITERAPIDS_D, &spr_features }, 1208 { INTEL_DIAMONDRAPIDS_X, &dmr_features }, 1209 { INTEL_LAKEFIELD, &cnl_features }, 1210 { INTEL_ALDERLAKE, &adl_features }, 1211 { INTEL_ALDERLAKE_L, &adl_features }, 1212 { INTEL_RAPTORLAKE, &adl_features }, 1213 { INTEL_RAPTORLAKE_P, &adl_features }, 1214 { INTEL_RAPTORLAKE_S, &adl_features }, 1215 { INTEL_BARTLETTLAKE, &adl_features }, 1216 { INTEL_METEORLAKE, &adl_features }, 1217 { INTEL_METEORLAKE_L, &adl_features }, 1218 { INTEL_ARROWLAKE_H, &adl_features }, 1219 { INTEL_ARROWLAKE_U, &adl_features }, 1220 { INTEL_ARROWLAKE, &adl_features }, 1221 { INTEL_LUNARLAKE_M, &lnl_features }, 1222 { INTEL_PANTHERLAKE_L, &lnl_features }, 1223 { INTEL_NOVALAKE, &lnl_features }, 1224 { INTEL_NOVALAKE_L, &lnl_features }, 1225 { INTEL_WILDCATLAKE_L, &lnl_features }, 1226 { INTEL_ATOM_SILVERMONT, &slv_features }, 1227 { INTEL_ATOM_SILVERMONT_D, &slvd_features }, 1228 { INTEL_ATOM_AIRMONT, &amt_features }, 1229 { INTEL_ATOM_GOLDMONT, &gmt_features }, 1230 { INTEL_ATOM_GOLDMONT_D, &gmtd_features }, 1231 { INTEL_ATOM_GOLDMONT_PLUS, &gmtp_features }, 1232 { INTEL_ATOM_TREMONT_D, &tmtd_features }, 1233 { INTEL_ATOM_TREMONT, &tmt_features }, 1234 { INTEL_ATOM_TREMONT_L, &tmt_features }, 1235 { INTEL_ATOM_GRACEMONT, &adl_features }, 1236 { INTEL_ATOM_CRESTMONT_X, &srf_features }, 1237 { INTEL_ATOM_CRESTMONT, &grr_features }, 1238 { INTEL_ATOM_DARKMONT_X, &srf_features }, 1239 { INTEL_XEON_PHI_KNL, &knl_features }, 1240 { INTEL_XEON_PHI_KNM, &knl_features }, 1241 /* 1242 * Missing support for 1243 * INTEL_ICELAKE 1244 * INTEL_ATOM_SILVERMONT_MID 1245 * INTEL_ATOM_SILVERMONT_MID2 1246 * INTEL_ATOM_AIRMONT_NP 1247 */ 1248 { 0, NULL }, 1249}; 1250 1251static const struct platform_features *platform; 1252 1253void probe_platform_features(unsigned int family, unsigned int model) 1254{ 1255 int i; 1256 1257 if (authentic_amd || hygon_genuine) { 1258 /* fallback to default features on unsupported models */ 1259 force_load++; 1260 if (max_extended_level >= 0x80000007) { 1261 unsigned int eax, ebx, ecx, edx; 1262 1263 __cpuid(0x80000007, eax, ebx, ecx, edx); 1264 /* RAPL (Fam 17h+) */ 1265 if ((edx & (1 << 14)) && family >= 0x17) 1266 platform = &amd_features_with_rapl; 1267 } 1268 goto end; 1269 } 1270 1271 if (!genuine_intel) 1272 goto end; 1273 1274 for (i = 0; turbostat_pdata[i].features; i++) { 1275 if (VFM_FAMILY(turbostat_pdata[i].vfm) == family && VFM_MODEL(turbostat_pdata[i].vfm) == model) { 1276 platform = turbostat_pdata[i].features; 1277 return; 1278 } 1279 } 1280 1281end: 1282 if (force_load && !platform) { 1283 fprintf(outf, "Forced to run on unsupported platform!\n"); 1284 platform = &default_features; 1285 } 1286 1287 if (platform) 1288 return; 1289 1290 fprintf(stderr, "Unsupported platform detected.\n\tSee RUN THE LATEST VERSION on turbostat(8)\n"); 1291 exit(1); 1292} 1293 1294/* Model specific support End */ 1295 1296#define TJMAX_DEFAULT 100 1297 1298/* MSRs that are not yet in the kernel-provided header. */ 1299#define MSR_RAPL_PWR_UNIT 0xc0010299 1300#define MSR_CORE_ENERGY_STAT 0xc001029a 1301#define MSR_PKG_ENERGY_STAT 0xc001029b 1302 1303#define MAX(a, b) ((a) > (b) ? (a) : (b)) 1304 1305int backwards_count; 1306char *progname; 1307 1308#define CPU_SUBSET_MAXCPUS 8192 /* need to use before probe... */ 1309cpu_set_t *cpu_present_set, *cpu_possible_set, *cpu_effective_set, *cpu_allowed_set, *cpu_affinity_set, *cpu_subset; 1310size_t cpu_present_setsize, cpu_possible_setsize, cpu_effective_setsize, cpu_allowed_setsize, cpu_affinity_setsize, cpu_subset_size; 1311#define MAX_ADDED_THREAD_COUNTERS 24 1312#define MAX_ADDED_CORE_COUNTERS 8 1313#define MAX_ADDED_PACKAGE_COUNTERS 16 1314#define PMT_MAX_ADDED_THREAD_COUNTERS 24 1315#define PMT_MAX_ADDED_CORE_COUNTERS 8 1316#define PMT_MAX_ADDED_PACKAGE_COUNTERS 16 1317#define BITMASK_SIZE 32 1318 1319#define ZERO_ARRAY(arr) (memset(arr, 0, sizeof(arr)) + __must_be_array(arr)) 1320 1321/* Indexes used to map data read from perf and MSRs into global variables */ 1322enum rapl_rci_index { 1323 RAPL_RCI_INDEX_ENERGY_PKG = 0, 1324 RAPL_RCI_INDEX_ENERGY_CORES = 1, 1325 RAPL_RCI_INDEX_DRAM = 2, 1326 RAPL_RCI_INDEX_GFX = 3, 1327 RAPL_RCI_INDEX_PKG_PERF_STATUS = 4, 1328 RAPL_RCI_INDEX_DRAM_PERF_STATUS = 5, 1329 RAPL_RCI_INDEX_CORE_ENERGY = 6, 1330 RAPL_RCI_INDEX_ENERGY_PLATFORM = 7, 1331 NUM_RAPL_COUNTERS, 1332}; 1333 1334enum rapl_unit { 1335 RAPL_UNIT_INVALID, 1336 RAPL_UNIT_JOULES, 1337 RAPL_UNIT_WATTS, 1338}; 1339 1340struct rapl_counter_info_t { 1341 unsigned long long data[NUM_RAPL_COUNTERS]; 1342 enum counter_source source[NUM_RAPL_COUNTERS]; 1343 unsigned long long flags[NUM_RAPL_COUNTERS]; 1344 double scale[NUM_RAPL_COUNTERS]; 1345 enum rapl_unit unit[NUM_RAPL_COUNTERS]; 1346 unsigned long long msr[NUM_RAPL_COUNTERS]; 1347 unsigned long long msr_mask[NUM_RAPL_COUNTERS]; 1348 int msr_shift[NUM_RAPL_COUNTERS]; 1349 1350 int fd_perf; 1351}; 1352 1353/* struct rapl_counter_info_t for each RAPL domain */ 1354struct rapl_counter_info_t *rapl_counter_info_perdomain; 1355unsigned int rapl_counter_info_perdomain_size; 1356 1357#define RAPL_COUNTER_FLAG_PLATFORM_COUNTER (1u << 0) 1358#define RAPL_COUNTER_FLAG_USE_MSR_SUM (1u << 1) 1359 1360struct rapl_counter_arch_info { 1361 int feature_mask; /* Mask for testing if the counter is supported on host */ 1362 const char *perf_subsys; 1363 const char *perf_name; 1364 unsigned long long msr; 1365 unsigned long long msr_mask; 1366 int msr_shift; /* Positive mean shift right, negative mean shift left */ 1367 double *platform_rapl_msr_scale; /* Scale applied to values read by MSR (platform dependent, filled at runtime) */ 1368 unsigned int rci_index; /* Maps data from perf counters to global variables */ 1369 unsigned int bic_number; 1370 double compat_scale; /* Some counters require constant scaling to be in the same range as other, similar ones */ 1371 unsigned long long flags; 1372}; 1373 1374static const struct rapl_counter_arch_info rapl_counter_arch_infos[] = { 1375 { 1376 .feature_mask = RAPL_PKG, 1377 .perf_subsys = "power", 1378 .perf_name = "energy-pkg", 1379 .msr = MSR_PKG_ENERGY_STATUS, 1380 .msr_mask = 0xFFFFFFFFFFFFFFFF, 1381 .msr_shift = 0, 1382 .platform_rapl_msr_scale = &rapl_energy_units, 1383 .rci_index = RAPL_RCI_INDEX_ENERGY_PKG, 1384 .bic_number = BIC_PkgWatt, 1385 .compat_scale = 1.0, 1386 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, 1387 }, 1388 { 1389 .feature_mask = RAPL_PKG, 1390 .perf_subsys = "power", 1391 .perf_name = "energy-pkg", 1392 .msr = MSR_PKG_ENERGY_STATUS, 1393 .msr_mask = 0xFFFFFFFFFFFFFFFF, 1394 .msr_shift = 0, 1395 .platform_rapl_msr_scale = &rapl_energy_units, 1396 .rci_index = RAPL_RCI_INDEX_ENERGY_PKG, 1397 .bic_number = BIC_Pkg_J, 1398 .compat_scale = 1.0, 1399 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, 1400 }, 1401 { 1402 .feature_mask = RAPL_AMD_F17H, 1403 .perf_subsys = "power", 1404 .perf_name = "energy-pkg", 1405 .msr = MSR_PKG_ENERGY_STAT, 1406 .msr_mask = 0xFFFFFFFFFFFFFFFF, 1407 .msr_shift = 0, 1408 .platform_rapl_msr_scale = &rapl_energy_units, 1409 .rci_index = RAPL_RCI_INDEX_ENERGY_PKG, 1410 .bic_number = BIC_PkgWatt, 1411 .compat_scale = 1.0, 1412 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, 1413 }, 1414 { 1415 .feature_mask = RAPL_AMD_F17H, 1416 .perf_subsys = "power", 1417 .perf_name = "energy-pkg", 1418 .msr = MSR_PKG_ENERGY_STAT, 1419 .msr_mask = 0xFFFFFFFFFFFFFFFF, 1420 .msr_shift = 0, 1421 .platform_rapl_msr_scale = &rapl_energy_units, 1422 .rci_index = RAPL_RCI_INDEX_ENERGY_PKG, 1423 .bic_number = BIC_Pkg_J, 1424 .compat_scale = 1.0, 1425 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, 1426 }, 1427 { 1428 .feature_mask = RAPL_CORE_ENERGY_STATUS, 1429 .perf_subsys = "power", 1430 .perf_name = "energy-cores", 1431 .msr = MSR_PP0_ENERGY_STATUS, 1432 .msr_mask = 0xFFFFFFFFFFFFFFFF, 1433 .msr_shift = 0, 1434 .platform_rapl_msr_scale = &rapl_energy_units, 1435 .rci_index = RAPL_RCI_INDEX_ENERGY_CORES, 1436 .bic_number = BIC_CorWatt, 1437 .compat_scale = 1.0, 1438 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, 1439 }, 1440 { 1441 .feature_mask = RAPL_CORE_ENERGY_STATUS, 1442 .perf_subsys = "power", 1443 .perf_name = "energy-cores", 1444 .msr = MSR_PP0_ENERGY_STATUS, 1445 .msr_mask = 0xFFFFFFFFFFFFFFFF, 1446 .msr_shift = 0, 1447 .platform_rapl_msr_scale = &rapl_energy_units, 1448 .rci_index = RAPL_RCI_INDEX_ENERGY_CORES, 1449 .bic_number = BIC_Cor_J, 1450 .compat_scale = 1.0, 1451 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, 1452 }, 1453 { 1454 .feature_mask = RAPL_DRAM, 1455 .perf_subsys = "power", 1456 .perf_name = "energy-ram", 1457 .msr = MSR_DRAM_ENERGY_STATUS, 1458 .msr_mask = 0xFFFFFFFFFFFFFFFF, 1459 .msr_shift = 0, 1460 .platform_rapl_msr_scale = &rapl_dram_energy_units, 1461 .rci_index = RAPL_RCI_INDEX_DRAM, 1462 .bic_number = BIC_RAMWatt, 1463 .compat_scale = 1.0, 1464 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, 1465 }, 1466 { 1467 .feature_mask = RAPL_DRAM, 1468 .perf_subsys = "power", 1469 .perf_name = "energy-ram", 1470 .msr = MSR_DRAM_ENERGY_STATUS, 1471 .msr_mask = 0xFFFFFFFFFFFFFFFF, 1472 .msr_shift = 0, 1473 .platform_rapl_msr_scale = &rapl_dram_energy_units, 1474 .rci_index = RAPL_RCI_INDEX_DRAM, 1475 .bic_number = BIC_RAM_J, 1476 .compat_scale = 1.0, 1477 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, 1478 }, 1479 { 1480 .feature_mask = RAPL_GFX, 1481 .perf_subsys = "power", 1482 .perf_name = "energy-gpu", 1483 .msr = MSR_PP1_ENERGY_STATUS, 1484 .msr_mask = 0xFFFFFFFFFFFFFFFF, 1485 .msr_shift = 0, 1486 .platform_rapl_msr_scale = &rapl_energy_units, 1487 .rci_index = RAPL_RCI_INDEX_GFX, 1488 .bic_number = BIC_GFXWatt, 1489 .compat_scale = 1.0, 1490 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, 1491 }, 1492 { 1493 .feature_mask = RAPL_GFX, 1494 .perf_subsys = "power", 1495 .perf_name = "energy-gpu", 1496 .msr = MSR_PP1_ENERGY_STATUS, 1497 .msr_mask = 0xFFFFFFFFFFFFFFFF, 1498 .msr_shift = 0, 1499 .platform_rapl_msr_scale = &rapl_energy_units, 1500 .rci_index = RAPL_RCI_INDEX_GFX, 1501 .bic_number = BIC_GFX_J, 1502 .compat_scale = 1.0, 1503 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, 1504 }, 1505 { 1506 .feature_mask = RAPL_PKG_PERF_STATUS, 1507 .perf_subsys = NULL, 1508 .perf_name = NULL, 1509 .msr = MSR_PKG_PERF_STATUS, 1510 .msr_mask = 0xFFFFFFFFFFFFFFFF, 1511 .msr_shift = 0, 1512 .platform_rapl_msr_scale = &rapl_time_units, 1513 .rci_index = RAPL_RCI_INDEX_PKG_PERF_STATUS, 1514 .bic_number = BIC_PKG__, 1515 .compat_scale = 100.0, 1516 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, 1517 }, 1518 { 1519 .feature_mask = RAPL_DRAM_PERF_STATUS, 1520 .perf_subsys = NULL, 1521 .perf_name = NULL, 1522 .msr = MSR_DRAM_PERF_STATUS, 1523 .msr_mask = 0xFFFFFFFFFFFFFFFF, 1524 .msr_shift = 0, 1525 .platform_rapl_msr_scale = &rapl_time_units, 1526 .rci_index = RAPL_RCI_INDEX_DRAM_PERF_STATUS, 1527 .bic_number = BIC_RAM__, 1528 .compat_scale = 100.0, 1529 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, 1530 }, 1531 { 1532 .feature_mask = RAPL_AMD_F17H, 1533 .perf_subsys = NULL, 1534 .perf_name = NULL, 1535 .msr = MSR_CORE_ENERGY_STAT, 1536 .msr_mask = 0xFFFFFFFF, 1537 .msr_shift = 0, 1538 .platform_rapl_msr_scale = &rapl_energy_units, 1539 .rci_index = RAPL_RCI_INDEX_CORE_ENERGY, 1540 .bic_number = BIC_CorWatt, 1541 .compat_scale = 1.0, 1542 .flags = 0, 1543 }, 1544 { 1545 .feature_mask = RAPL_AMD_F17H, 1546 .perf_subsys = NULL, 1547 .perf_name = NULL, 1548 .msr = MSR_CORE_ENERGY_STAT, 1549 .msr_mask = 0xFFFFFFFF, 1550 .msr_shift = 0, 1551 .platform_rapl_msr_scale = &rapl_energy_units, 1552 .rci_index = RAPL_RCI_INDEX_CORE_ENERGY, 1553 .bic_number = BIC_Cor_J, 1554 .compat_scale = 1.0, 1555 .flags = 0, 1556 }, 1557 { 1558 .feature_mask = RAPL_PSYS, 1559 .perf_subsys = "power", 1560 .perf_name = "energy-psys", 1561 .msr = MSR_PLATFORM_ENERGY_STATUS, 1562 .msr_mask = 0x00000000FFFFFFFF, 1563 .msr_shift = 0, 1564 .platform_rapl_msr_scale = &rapl_psys_energy_units, 1565 .rci_index = RAPL_RCI_INDEX_ENERGY_PLATFORM, 1566 .bic_number = BIC_SysWatt, 1567 .compat_scale = 1.0, 1568 .flags = RAPL_COUNTER_FLAG_PLATFORM_COUNTER | RAPL_COUNTER_FLAG_USE_MSR_SUM, 1569 }, 1570 { 1571 .feature_mask = RAPL_PSYS, 1572 .perf_subsys = "power", 1573 .perf_name = "energy-psys", 1574 .msr = MSR_PLATFORM_ENERGY_STATUS, 1575 .msr_mask = 0x00000000FFFFFFFF, 1576 .msr_shift = 0, 1577 .platform_rapl_msr_scale = &rapl_psys_energy_units, 1578 .rci_index = RAPL_RCI_INDEX_ENERGY_PLATFORM, 1579 .bic_number = BIC_Sys_J, 1580 .compat_scale = 1.0, 1581 .flags = RAPL_COUNTER_FLAG_PLATFORM_COUNTER | RAPL_COUNTER_FLAG_USE_MSR_SUM, 1582 }, 1583}; 1584 1585struct rapl_counter { 1586 unsigned long long raw_value; 1587 enum rapl_unit unit; 1588 double scale; 1589}; 1590 1591/* Indexes used to map data read from perf and MSRs into global variables */ 1592enum ccstate_rci_index { 1593 CCSTATE_RCI_INDEX_C1_RESIDENCY = 0, 1594 CCSTATE_RCI_INDEX_C3_RESIDENCY = 1, 1595 CCSTATE_RCI_INDEX_C6_RESIDENCY = 2, 1596 CCSTATE_RCI_INDEX_C7_RESIDENCY = 3, 1597 PCSTATE_RCI_INDEX_C2_RESIDENCY = 4, 1598 PCSTATE_RCI_INDEX_C3_RESIDENCY = 5, 1599 PCSTATE_RCI_INDEX_C6_RESIDENCY = 6, 1600 PCSTATE_RCI_INDEX_C7_RESIDENCY = 7, 1601 PCSTATE_RCI_INDEX_C8_RESIDENCY = 8, 1602 PCSTATE_RCI_INDEX_C9_RESIDENCY = 9, 1603 PCSTATE_RCI_INDEX_C10_RESIDENCY = 10, 1604 NUM_CSTATE_COUNTERS, 1605}; 1606 1607struct cstate_counter_info_t { 1608 unsigned long long data[NUM_CSTATE_COUNTERS]; 1609 enum counter_source source[NUM_CSTATE_COUNTERS]; 1610 unsigned long long msr[NUM_CSTATE_COUNTERS]; 1611 int fd_perf_core; 1612 int fd_perf_pkg; 1613}; 1614 1615struct cstate_counter_info_t *ccstate_counter_info; 1616unsigned int ccstate_counter_info_size; 1617 1618#define CSTATE_COUNTER_FLAG_COLLECT_PER_CORE (1u << 0) 1619#define CSTATE_COUNTER_FLAG_COLLECT_PER_THREAD ((1u << 1) | CSTATE_COUNTER_FLAG_COLLECT_PER_CORE) 1620#define CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY (1u << 2) 1621 1622struct cstate_counter_arch_info { 1623 int feature_mask; /* Mask for testing if the counter is supported on host */ 1624 const char *perf_subsys; 1625 const char *perf_name; 1626 unsigned long long msr; 1627 unsigned int rci_index; /* Maps data from perf counters to global variables */ 1628 unsigned int bic_number; 1629 unsigned long long flags; 1630 int pkg_cstate_limit; 1631}; 1632 1633static struct cstate_counter_arch_info ccstate_counter_arch_infos[] = { 1634 { 1635 .feature_mask = CC1, 1636 .perf_subsys = "cstate_core", 1637 .perf_name = "c1-residency", 1638 .msr = MSR_CORE_C1_RES, 1639 .rci_index = CCSTATE_RCI_INDEX_C1_RESIDENCY, 1640 .bic_number = BIC_CPU_c1, 1641 .flags = CSTATE_COUNTER_FLAG_COLLECT_PER_THREAD, 1642 .pkg_cstate_limit = 0, 1643 }, 1644 { 1645 .feature_mask = CC3, 1646 .perf_subsys = "cstate_core", 1647 .perf_name = "c3-residency", 1648 .msr = MSR_CORE_C3_RESIDENCY, 1649 .rci_index = CCSTATE_RCI_INDEX_C3_RESIDENCY, 1650 .bic_number = BIC_CPU_c3, 1651 .flags = CSTATE_COUNTER_FLAG_COLLECT_PER_CORE | CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY, 1652 .pkg_cstate_limit = 0, 1653 }, 1654 { 1655 .feature_mask = CC6, 1656 .perf_subsys = "cstate_core", 1657 .perf_name = "c6-residency", 1658 .msr = MSR_CORE_C6_RESIDENCY, 1659 .rci_index = CCSTATE_RCI_INDEX_C6_RESIDENCY, 1660 .bic_number = BIC_CPU_c6, 1661 .flags = CSTATE_COUNTER_FLAG_COLLECT_PER_CORE | CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY, 1662 .pkg_cstate_limit = 0, 1663 }, 1664 { 1665 .feature_mask = CC7, 1666 .perf_subsys = "cstate_core", 1667 .perf_name = "c7-residency", 1668 .msr = MSR_CORE_C7_RESIDENCY, 1669 .rci_index = CCSTATE_RCI_INDEX_C7_RESIDENCY, 1670 .bic_number = BIC_CPU_c7, 1671 .flags = CSTATE_COUNTER_FLAG_COLLECT_PER_CORE | CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY, 1672 .pkg_cstate_limit = 0, 1673 }, 1674 { 1675 .feature_mask = PC2, 1676 .perf_subsys = "cstate_pkg", 1677 .perf_name = "c2-residency", 1678 .msr = MSR_PKG_C2_RESIDENCY, 1679 .rci_index = PCSTATE_RCI_INDEX_C2_RESIDENCY, 1680 .bic_number = BIC_Pkgpc2, 1681 .flags = 0, 1682 .pkg_cstate_limit = PCL__2, 1683 }, 1684 { 1685 .feature_mask = PC3, 1686 .perf_subsys = "cstate_pkg", 1687 .perf_name = "c3-residency", 1688 .msr = MSR_PKG_C3_RESIDENCY, 1689 .rci_index = PCSTATE_RCI_INDEX_C3_RESIDENCY, 1690 .bic_number = BIC_Pkgpc3, 1691 .flags = 0, 1692 .pkg_cstate_limit = PCL__3, 1693 }, 1694 { 1695 .feature_mask = PC6, 1696 .perf_subsys = "cstate_pkg", 1697 .perf_name = "c6-residency", 1698 .msr = MSR_PKG_C6_RESIDENCY, 1699 .rci_index = PCSTATE_RCI_INDEX_C6_RESIDENCY, 1700 .bic_number = BIC_Pkgpc6, 1701 .flags = 0, 1702 .pkg_cstate_limit = PCL__6, 1703 }, 1704 { 1705 .feature_mask = PC7, 1706 .perf_subsys = "cstate_pkg", 1707 .perf_name = "c7-residency", 1708 .msr = MSR_PKG_C7_RESIDENCY, 1709 .rci_index = PCSTATE_RCI_INDEX_C7_RESIDENCY, 1710 .bic_number = BIC_Pkgpc7, 1711 .flags = 0, 1712 .pkg_cstate_limit = PCL__7, 1713 }, 1714 { 1715 .feature_mask = PC8, 1716 .perf_subsys = "cstate_pkg", 1717 .perf_name = "c8-residency", 1718 .msr = MSR_PKG_C8_RESIDENCY, 1719 .rci_index = PCSTATE_RCI_INDEX_C8_RESIDENCY, 1720 .bic_number = BIC_Pkgpc8, 1721 .flags = 0, 1722 .pkg_cstate_limit = PCL__8, 1723 }, 1724 { 1725 .feature_mask = PC9, 1726 .perf_subsys = "cstate_pkg", 1727 .perf_name = "c9-residency", 1728 .msr = MSR_PKG_C9_RESIDENCY, 1729 .rci_index = PCSTATE_RCI_INDEX_C9_RESIDENCY, 1730 .bic_number = BIC_Pkgpc9, 1731 .flags = 0, 1732 .pkg_cstate_limit = PCL__9, 1733 }, 1734 { 1735 .feature_mask = PC10, 1736 .perf_subsys = "cstate_pkg", 1737 .perf_name = "c10-residency", 1738 .msr = MSR_PKG_C10_RESIDENCY, 1739 .rci_index = PCSTATE_RCI_INDEX_C10_RESIDENCY, 1740 .bic_number = BIC_Pkgpc10, 1741 .flags = 0, 1742 .pkg_cstate_limit = PCL_10, 1743 }, 1744}; 1745 1746/* Indexes used to map data read from perf and MSRs into global variables */ 1747enum msr_rci_index { 1748 MSR_RCI_INDEX_APERF = 0, 1749 MSR_RCI_INDEX_MPERF = 1, 1750 MSR_RCI_INDEX_SMI = 2, 1751 NUM_MSR_COUNTERS, 1752}; 1753 1754struct msr_counter_info_t { 1755 unsigned long long data[NUM_MSR_COUNTERS]; 1756 enum counter_source source[NUM_MSR_COUNTERS]; 1757 unsigned long long msr[NUM_MSR_COUNTERS]; 1758 unsigned long long msr_mask[NUM_MSR_COUNTERS]; 1759 int fd_perf; 1760}; 1761 1762struct msr_counter_info_t *msr_counter_info; 1763unsigned int msr_counter_info_size; 1764 1765struct msr_counter_arch_info { 1766 const char *perf_subsys; 1767 const char *perf_name; 1768 unsigned long long msr; 1769 unsigned long long msr_mask; 1770 unsigned int rci_index; /* Maps data from perf counters to global variables */ 1771 bool needed; 1772 bool present; 1773}; 1774 1775enum msr_arch_info_index { 1776 MSR_ARCH_INFO_APERF_INDEX = 0, 1777 MSR_ARCH_INFO_MPERF_INDEX = 1, 1778 MSR_ARCH_INFO_SMI_INDEX = 2, 1779}; 1780 1781static struct msr_counter_arch_info msr_counter_arch_infos[] = { 1782 [MSR_ARCH_INFO_APERF_INDEX] = { 1783 .perf_subsys = "msr", 1784 .perf_name = "aperf", 1785 .msr = MSR_IA32_APERF, 1786 .msr_mask = 0xFFFFFFFFFFFFFFFF, 1787 .rci_index = MSR_RCI_INDEX_APERF, 1788 }, 1789 1790 [MSR_ARCH_INFO_MPERF_INDEX] = { 1791 .perf_subsys = "msr", 1792 .perf_name = "mperf", 1793 .msr = MSR_IA32_MPERF, 1794 .msr_mask = 0xFFFFFFFFFFFFFFFF, 1795 .rci_index = MSR_RCI_INDEX_MPERF, 1796 }, 1797 1798 [MSR_ARCH_INFO_SMI_INDEX] = { 1799 .perf_subsys = "msr", 1800 .perf_name = "smi", 1801 .msr = MSR_SMI_COUNT, 1802 .msr_mask = 0xFFFFFFFF, 1803 .rci_index = MSR_RCI_INDEX_SMI, 1804 }, 1805}; 1806 1807/* Can be redefined when compiling, useful for testing. */ 1808#ifndef SYSFS_TELEM_PATH 1809#define SYSFS_TELEM_PATH "/sys/class/intel_pmt" 1810#endif 1811 1812#define PMT_COUNTER_MTL_DC6_OFFSET 120 1813#define PMT_COUNTER_MTL_DC6_LSB 0 1814#define PMT_COUNTER_MTL_DC6_MSB 63 1815#define PMT_MTL_DC6_GUID 0x1a067102 1816#define PMT_MTL_DC6_SEQ 0 1817 1818#define PMT_COUNTER_CWF_MC1E_OFFSET_BASE 20936 1819#define PMT_COUNTER_CWF_MC1E_OFFSET_INCREMENT 24 1820#define PMT_COUNTER_CWF_MC1E_NUM_MODULES_PER_FILE 12 1821#define PMT_COUNTER_CWF_CPUS_PER_MODULE 4 1822#define PMT_COUNTER_CWF_MC1E_LSB 0 1823#define PMT_COUNTER_CWF_MC1E_MSB 63 1824#define PMT_CWF_MC1E_GUID 0x14421519 1825 1826unsigned long long tcore_clock_freq_hz = 800000000; 1827 1828#define PMT_COUNTER_NAME_SIZE_BYTES 16 1829#define PMT_COUNTER_TYPE_NAME_SIZE_BYTES 32 1830 1831struct pmt_mmio { 1832 struct pmt_mmio *next; 1833 1834 unsigned int guid; 1835 unsigned int size; 1836 1837 /* Base pointer to the mmaped memory. */ 1838 void *mmio_base; 1839 1840 /* 1841 * Offset to be applied to the mmio_base 1842 * to get the beginning of the PMT counters for given GUID. 1843 */ 1844 unsigned long pmt_offset; 1845} *pmt_mmios; 1846 1847enum pmt_datatype { 1848 PMT_TYPE_RAW, 1849 PMT_TYPE_XTAL_TIME, 1850 PMT_TYPE_TCORE_CLOCK, 1851}; 1852 1853struct pmt_domain_info { 1854 /* 1855 * Pointer to the MMIO obtained by applying a counter offset 1856 * to the mmio_base of the mmaped region for the given GUID. 1857 * 1858 * This is where to read the raw value of the counter from. 1859 */ 1860 unsigned long *pcounter; 1861}; 1862 1863struct pmt_counter { 1864 struct pmt_counter *next; 1865 1866 /* PMT metadata */ 1867 char name[PMT_COUNTER_NAME_SIZE_BYTES]; 1868 enum pmt_datatype type; 1869 enum counter_scope scope; 1870 unsigned int lsb; 1871 unsigned int msb; 1872 1873 /* BIC-like metadata */ 1874 enum counter_format format; 1875 1876 unsigned int num_domains; 1877 struct pmt_domain_info *domains; 1878}; 1879 1880/* 1881 * PMT telemetry directory iterator. 1882 * Used to iterate telemetry files in sysfs in correct order. 1883 */ 1884struct pmt_diriter_t { 1885 DIR *dir; 1886 struct dirent **namelist; 1887 unsigned int num_names; 1888 unsigned int current_name_idx; 1889}; 1890 1891int pmt_telemdir_filter(const struct dirent *e) 1892{ 1893 unsigned int dummy; 1894 1895 return sscanf(e->d_name, "telem%u", &dummy); 1896} 1897 1898int pmt_telemdir_sort(const struct dirent **a, const struct dirent **b) 1899{ 1900 unsigned int aidx = 0, bidx = 0; 1901 1902 sscanf((*a)->d_name, "telem%u", &aidx); 1903 sscanf((*b)->d_name, "telem%u", &bidx); 1904 1905 return (aidx > bidx) ? 1 : (aidx < bidx) ? -1 : 0; 1906} 1907 1908const struct dirent *pmt_diriter_next(struct pmt_diriter_t *iter) 1909{ 1910 const struct dirent *ret = NULL; 1911 1912 if (!iter->dir) 1913 return NULL; 1914 1915 if (iter->current_name_idx >= iter->num_names) 1916 return NULL; 1917 1918 ret = iter->namelist[iter->current_name_idx]; 1919 ++iter->current_name_idx; 1920 1921 return ret; 1922} 1923 1924const struct dirent *pmt_diriter_begin(struct pmt_diriter_t *iter, const char *pmt_root_path) 1925{ 1926 int num_names = iter->num_names; 1927 1928 if (!iter->dir) { 1929 iter->dir = opendir(pmt_root_path); 1930 if (iter->dir == NULL) 1931 return NULL; 1932 1933 num_names = scandir(pmt_root_path, &iter->namelist, pmt_telemdir_filter, pmt_telemdir_sort); 1934 if (num_names == -1) 1935 return NULL; 1936 } 1937 1938 iter->current_name_idx = 0; 1939 iter->num_names = num_names; 1940 1941 return pmt_diriter_next(iter); 1942} 1943 1944void pmt_diriter_init(struct pmt_diriter_t *iter) 1945{ 1946 memset(iter, 0, sizeof(*iter)); 1947} 1948 1949void pmt_diriter_remove(struct pmt_diriter_t *iter) 1950{ 1951 if (iter->namelist) { 1952 for (unsigned int i = 0; i < iter->num_names; i++) { 1953 free(iter->namelist[i]); 1954 iter->namelist[i] = NULL; 1955 } 1956 } 1957 1958 free(iter->namelist); 1959 iter->namelist = NULL; 1960 iter->num_names = 0; 1961 iter->current_name_idx = 0; 1962 1963 closedir(iter->dir); 1964 iter->dir = NULL; 1965} 1966 1967unsigned int pmt_counter_get_width(const struct pmt_counter *p) 1968{ 1969 return (p->msb - p->lsb) + 1; 1970} 1971 1972void pmt_counter_resize_(struct pmt_counter *pcounter, unsigned int new_size) 1973{ 1974 struct pmt_domain_info *new_mem; 1975 1976 new_mem = (struct pmt_domain_info *)reallocarray(pcounter->domains, new_size, sizeof(*pcounter->domains)); 1977 if (!new_mem) { 1978 fprintf(stderr, "%s: failed to allocate memory for PMT counters\n", __func__); 1979 exit(1); 1980 } 1981 1982 /* Zero initialize just allocated memory. */ 1983 const size_t num_new_domains = new_size - pcounter->num_domains; 1984 1985 memset(&new_mem[pcounter->num_domains], 0, num_new_domains * sizeof(*pcounter->domains)); 1986 1987 pcounter->num_domains = new_size; 1988 pcounter->domains = new_mem; 1989} 1990 1991void pmt_counter_resize(struct pmt_counter *pcounter, unsigned int new_size) 1992{ 1993 /* 1994 * Allocate more memory ahead of time. 1995 * 1996 * Always allocate space for at least 8 elements 1997 * and double the size when growing. 1998 */ 1999 if (new_size < 8) 2000 new_size = 8; 2001 new_size = MAX(new_size, pcounter->num_domains * 2); 2002 2003 pmt_counter_resize_(pcounter, new_size); 2004} 2005 2006struct llc_stats { 2007 unsigned long long references; 2008 unsigned long long misses; 2009}; 2010struct thread_data { 2011 struct timeval tv_begin; 2012 struct timeval tv_end; 2013 struct timeval tv_delta; 2014 unsigned long long tsc; 2015 unsigned long long aperf; 2016 unsigned long long mperf; 2017 unsigned long long c1; 2018 unsigned long long instr_count; 2019 unsigned long long irq_count; 2020 unsigned long long nmi_count; 2021 unsigned int smi_count; 2022 struct llc_stats llc; 2023 unsigned int cpu_id; 2024 unsigned int apic_id; 2025 unsigned int x2apic_id; 2026 unsigned int flags; 2027 bool is_atom; 2028 unsigned long long counter[MAX_ADDED_THREAD_COUNTERS]; 2029 unsigned long long perf_counter[MAX_ADDED_THREAD_COUNTERS]; 2030 unsigned long long pmt_counter[PMT_MAX_ADDED_THREAD_COUNTERS]; 2031} *thread_even, *thread_odd; 2032 2033struct core_data { 2034 int base_cpu; 2035 unsigned long long c3; 2036 unsigned long long c6; 2037 unsigned long long c7; 2038 unsigned long long mc6_us; /* duplicate as per-core for now, even though per module */ 2039 unsigned int core_temp_c; 2040 struct rapl_counter core_energy; /* MSR_CORE_ENERGY_STAT */ 2041 unsigned int core_id; 2042 unsigned long long core_throt_cnt; 2043 unsigned long long counter[MAX_ADDED_CORE_COUNTERS]; 2044 unsigned long long perf_counter[MAX_ADDED_CORE_COUNTERS]; 2045 unsigned long long pmt_counter[PMT_MAX_ADDED_CORE_COUNTERS]; 2046} *core_even, *core_odd; 2047 2048struct pkg_data { 2049 int base_cpu; 2050 unsigned long long pc2; 2051 unsigned long long pc3; 2052 unsigned long long pc6; 2053 unsigned long long pc7; 2054 unsigned long long pc8; 2055 unsigned long long pc9; 2056 unsigned long long pc10; 2057 long long cpu_lpi; 2058 long long sys_lpi; 2059 unsigned long long pkg_wtd_core_c0; 2060 unsigned long long pkg_any_core_c0; 2061 unsigned long long pkg_any_gfxe_c0; 2062 unsigned long long pkg_both_core_gfxe_c0; 2063 long long gfx_rc6_ms; 2064 unsigned int gfx_mhz; 2065 unsigned int gfx_act_mhz; 2066 long long sam_mc6_ms; 2067 unsigned int sam_mhz; 2068 unsigned int sam_act_mhz; 2069 unsigned int package_id; 2070 struct rapl_counter energy_pkg; /* MSR_PKG_ENERGY_STATUS */ 2071 struct rapl_counter energy_dram; /* MSR_DRAM_ENERGY_STATUS */ 2072 struct rapl_counter energy_cores; /* MSR_PP0_ENERGY_STATUS */ 2073 struct rapl_counter energy_gfx; /* MSR_PP1_ENERGY_STATUS */ 2074 struct rapl_counter rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */ 2075 struct rapl_counter rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */ 2076 unsigned int pkg_temp_c; 2077 unsigned int uncore_mhz; 2078 unsigned long long die_c6; 2079 unsigned long long counter[MAX_ADDED_PACKAGE_COUNTERS]; 2080 unsigned long long perf_counter[MAX_ADDED_PACKAGE_COUNTERS]; 2081 unsigned long long pmt_counter[PMT_MAX_ADDED_PACKAGE_COUNTERS]; 2082} *package_even, *package_odd; 2083 2084#define ODD_COUNTERS thread_odd, core_odd, package_odd 2085#define EVEN_COUNTERS thread_even, core_even, package_even 2086 2087#define GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no) \ 2088 ((thread_base) + \ 2089 ((pkg_no) * \ 2090 topo.nodes_per_pkg * topo.cores_per_node * topo.threads_per_core) + \ 2091 ((node_no) * topo.cores_per_node * topo.threads_per_core) + \ 2092 ((core_no) * topo.threads_per_core) + \ 2093 (thread_no)) 2094 2095#define GET_CORE(core_base, core_no, node_no, pkg_no) \ 2096 ((core_base) + \ 2097 ((pkg_no) * topo.nodes_per_pkg * topo.cores_per_node) + \ 2098 ((node_no) * topo.cores_per_node) + \ 2099 (core_no)) 2100 2101/* 2102 * The accumulated sum of MSR is defined as a monotonic 2103 * increasing MSR, it will be accumulated periodically, 2104 * despite its register's bit width. 2105 */ 2106enum { 2107 IDX_PKG_ENERGY, 2108 IDX_DRAM_ENERGY, 2109 IDX_PP0_ENERGY, 2110 IDX_PP1_ENERGY, 2111 IDX_PKG_PERF, 2112 IDX_DRAM_PERF, 2113 IDX_PSYS_ENERGY, 2114 IDX_COUNT, 2115}; 2116 2117int get_msr_sum(int cpu, off_t offset, unsigned long long *msr); 2118 2119struct msr_sum_array { 2120 /* get_msr_sum() = sum + (get_msr() - last) */ 2121 struct { 2122 /*The accumulated MSR value is updated by the timer */ 2123 unsigned long long sum; 2124 /*The MSR footprint recorded in last timer */ 2125 unsigned long long last; 2126 } entries[IDX_COUNT]; 2127}; 2128 2129/* The percpu MSR sum array.*/ 2130struct msr_sum_array *per_cpu_msr_sum; 2131 2132off_t idx_to_offset(int idx) 2133{ 2134 off_t offset; 2135 2136 switch (idx) { 2137 case IDX_PKG_ENERGY: 2138 if (platform->plat_rapl_msrs & RAPL_AMD_F17H) 2139 offset = MSR_PKG_ENERGY_STAT; 2140 else 2141 offset = MSR_PKG_ENERGY_STATUS; 2142 break; 2143 case IDX_DRAM_ENERGY: 2144 offset = MSR_DRAM_ENERGY_STATUS; 2145 break; 2146 case IDX_PP0_ENERGY: 2147 offset = MSR_PP0_ENERGY_STATUS; 2148 break; 2149 case IDX_PP1_ENERGY: 2150 offset = MSR_PP1_ENERGY_STATUS; 2151 break; 2152 case IDX_PKG_PERF: 2153 offset = MSR_PKG_PERF_STATUS; 2154 break; 2155 case IDX_DRAM_PERF: 2156 offset = MSR_DRAM_PERF_STATUS; 2157 break; 2158 case IDX_PSYS_ENERGY: 2159 offset = MSR_PLATFORM_ENERGY_STATUS; 2160 break; 2161 default: 2162 offset = -1; 2163 } 2164 return offset; 2165} 2166 2167int offset_to_idx(off_t offset) 2168{ 2169 int idx; 2170 2171 switch (offset) { 2172 case MSR_PKG_ENERGY_STATUS: 2173 case MSR_PKG_ENERGY_STAT: 2174 idx = IDX_PKG_ENERGY; 2175 break; 2176 case MSR_DRAM_ENERGY_STATUS: 2177 idx = IDX_DRAM_ENERGY; 2178 break; 2179 case MSR_PP0_ENERGY_STATUS: 2180 idx = IDX_PP0_ENERGY; 2181 break; 2182 case MSR_PP1_ENERGY_STATUS: 2183 idx = IDX_PP1_ENERGY; 2184 break; 2185 case MSR_PKG_PERF_STATUS: 2186 idx = IDX_PKG_PERF; 2187 break; 2188 case MSR_DRAM_PERF_STATUS: 2189 idx = IDX_DRAM_PERF; 2190 break; 2191 case MSR_PLATFORM_ENERGY_STATUS: 2192 idx = IDX_PSYS_ENERGY; 2193 break; 2194 default: 2195 idx = -1; 2196 } 2197 return idx; 2198} 2199 2200int idx_valid(int idx) 2201{ 2202 switch (idx) { 2203 case IDX_PKG_ENERGY: 2204 return valid_rapl_msrs & (RAPL_PKG | RAPL_AMD_F17H); 2205 case IDX_DRAM_ENERGY: 2206 return valid_rapl_msrs & RAPL_DRAM; 2207 case IDX_PP0_ENERGY: 2208 return valid_rapl_msrs & RAPL_CORE_ENERGY_STATUS; 2209 case IDX_PP1_ENERGY: 2210 return valid_rapl_msrs & RAPL_GFX; 2211 case IDX_PKG_PERF: 2212 return valid_rapl_msrs & RAPL_PKG_PERF_STATUS; 2213 case IDX_DRAM_PERF: 2214 return valid_rapl_msrs & RAPL_DRAM_PERF_STATUS; 2215 case IDX_PSYS_ENERGY: 2216 return valid_rapl_msrs & RAPL_PSYS; 2217 default: 2218 return 0; 2219 } 2220} 2221 2222struct sys_counters { 2223 /* MSR added counters */ 2224 unsigned int added_thread_counters; 2225 unsigned int added_core_counters; 2226 unsigned int added_package_counters; 2227 struct msr_counter *tp; 2228 struct msr_counter *cp; 2229 struct msr_counter *pp; 2230 2231 /* perf added counters */ 2232 unsigned int added_thread_perf_counters; 2233 unsigned int added_core_perf_counters; 2234 unsigned int added_package_perf_counters; 2235 struct perf_counter_info *perf_tp; 2236 struct perf_counter_info *perf_cp; 2237 struct perf_counter_info *perf_pp; 2238 2239 struct pmt_counter *pmt_tp; 2240 struct pmt_counter *pmt_cp; 2241 struct pmt_counter *pmt_pp; 2242} sys; 2243 2244static size_t free_msr_counters_(struct msr_counter **pp) 2245{ 2246 struct msr_counter *p = NULL; 2247 size_t num_freed = 0; 2248 2249 while (*pp) { 2250 p = *pp; 2251 2252 if (p->msr_num != 0) { 2253 *pp = p->next; 2254 2255 free(p); 2256 ++num_freed; 2257 2258 continue; 2259 } 2260 2261 pp = &p->next; 2262 } 2263 2264 return num_freed; 2265} 2266 2267/* 2268 * Free all added counters accessed via msr. 2269 */ 2270static void free_sys_msr_counters(void) 2271{ 2272 /* Thread counters */ 2273 sys.added_thread_counters -= free_msr_counters_(&sys.tp); 2274 2275 /* Core counters */ 2276 sys.added_core_counters -= free_msr_counters_(&sys.cp); 2277 2278 /* Package counters */ 2279 sys.added_package_counters -= free_msr_counters_(&sys.pp); 2280} 2281 2282struct system_summary { 2283 struct thread_data threads; 2284 struct core_data cores; 2285 struct pkg_data packages; 2286} average; 2287 2288struct platform_counters { 2289 struct rapl_counter energy_psys; /* MSR_PLATFORM_ENERGY_STATUS */ 2290} platform_counters_odd, platform_counters_even; 2291 2292struct cpu_topology { 2293 int physical_package_id; 2294 int die_id; 2295 int l3_id; 2296 int logical_cpu_id; 2297 int physical_node_id; 2298 int logical_node_id; /* 0-based count within the package */ 2299 int physical_core_id; 2300 int thread_id; 2301 int type; 2302 cpu_set_t *put_ids; /* Processing Unit/Thread IDs */ 2303} *cpus; 2304 2305struct topo_params { 2306 int num_packages; 2307 int num_die; 2308 int num_cpus; 2309 int num_cores; 2310 int allowed_packages; 2311 int allowed_cpus; 2312 int allowed_cores; 2313 int max_cpu_num; 2314 int max_core_id; 2315 int max_package_id; 2316 int max_die_id; 2317 int max_l3_id; 2318 int max_node_num; 2319 int nodes_per_pkg; 2320 int cores_per_node; 2321 int threads_per_core; 2322} topo; 2323 2324struct timeval tv_even, tv_odd, tv_delta; 2325 2326int *irq_column_2_cpu; /* /proc/interrupts column numbers */ 2327int *irqs_per_cpu; /* indexed by cpu_num */ 2328int *nmi_per_cpu; /* indexed by cpu_num */ 2329 2330void setup_all_buffers(bool startup); 2331 2332char *sys_lpi_file; 2333char *sys_lpi_file_sysfs = "/sys/devices/system/cpu/cpuidle/low_power_idle_system_residency_us"; 2334char *sys_lpi_file_debugfs = "/sys/kernel/debug/pmc_core/slp_s0_residency_usec"; 2335 2336int cpu_is_not_present(int cpu) 2337{ 2338 return !CPU_ISSET_S(cpu, cpu_present_setsize, cpu_present_set); 2339} 2340 2341int cpu_is_not_allowed(int cpu) 2342{ 2343 return !CPU_ISSET_S(cpu, cpu_allowed_setsize, cpu_allowed_set); 2344} 2345 2346/* 2347 * run func(thread, core, package) in topology order 2348 * skip non-present cpus 2349 */ 2350 2351#define PER_THREAD_PARAMS struct thread_data *t, struct core_data *c, struct pkg_data *p 2352 2353int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pkg_data *), 2354 struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base) 2355{ 2356 int retval, pkg_no, core_no, thread_no, node_no; 2357 2358 retval = 0; 2359 2360 for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) { 2361 for (node_no = 0; node_no < topo.nodes_per_pkg; node_no++) { 2362 for (core_no = 0; core_no < topo.cores_per_node; ++core_no) { 2363 for (thread_no = 0; thread_no < topo.threads_per_core; ++thread_no) { 2364 struct thread_data *t; 2365 struct core_data *c; 2366 2367 t = GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no); 2368 2369 if (cpu_is_not_allowed(t->cpu_id)) 2370 continue; 2371 2372 c = GET_CORE(core_base, core_no, node_no, pkg_no); 2373 2374 retval |= func(t, c, &pkg_base[pkg_no]); 2375 } 2376 } 2377 } 2378 } 2379 return retval; 2380} 2381 2382int is_cpu_first_thread_in_core(struct thread_data *t, struct core_data *c) 2383{ 2384 return ((int)t->cpu_id == c->base_cpu || c->base_cpu < 0); 2385} 2386 2387int is_cpu_first_core_in_package(struct thread_data *t, struct pkg_data *p) 2388{ 2389 return ((int)t->cpu_id == p->base_cpu || p->base_cpu < 0); 2390} 2391 2392int is_cpu_first_thread_in_package(struct thread_data *t, struct core_data *c, struct pkg_data *p) 2393{ 2394 return is_cpu_first_thread_in_core(t, c) && is_cpu_first_core_in_package(t, p); 2395} 2396 2397int cpu_migrate(int cpu) 2398{ 2399 CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set); 2400 CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set); 2401 if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1) 2402 return -1; 2403 else 2404 return 0; 2405} 2406 2407int get_msr_fd(int cpu) 2408{ 2409 char pathname[32]; 2410 int fd; 2411 2412 fd = fd_percpu[cpu]; 2413 2414 if (fd) 2415 return fd; 2416 sprintf(pathname, use_android_msr_path ? "/dev/msr%d" : "/dev/cpu/%d/msr", cpu); 2417 fd = open(pathname, O_RDONLY); 2418 if (fd < 0) 2419 err(-1, "%s open failed, try chown or chmod +r %s, " 2420 "or run with --no-msr, or run as root", pathname, use_android_msr_path ? "/dev/msr*" : "/dev/cpu/*/msr"); 2421 fd_percpu[cpu] = fd; 2422 2423 return fd; 2424} 2425 2426static void bic_disable_msr_access(void) 2427{ 2428 CLR_BIC(BIC_Mod_c6, &bic_enabled); 2429 CLR_BIC(BIC_CoreTmp, &bic_enabled); 2430 CLR_BIC(BIC_Totl_c0, &bic_enabled); 2431 CLR_BIC(BIC_Any_c0, &bic_enabled); 2432 CLR_BIC(BIC_GFX_c0, &bic_enabled); 2433 CLR_BIC(BIC_CPUGFX, &bic_enabled); 2434 CLR_BIC(BIC_PkgTmp, &bic_enabled); 2435 2436 free_sys_msr_counters(); 2437} 2438 2439static void bic_disable_perf_access(void) 2440{ 2441 CLR_BIC(BIC_IPC, &bic_enabled); 2442 CLR_BIC(BIC_LLC_RPS, &bic_enabled); 2443 CLR_BIC(BIC_LLC_HIT, &bic_enabled); 2444} 2445 2446static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags) 2447{ 2448 assert(!no_perf); 2449 2450 return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); 2451} 2452 2453static long open_perf_counter(int cpu, unsigned int type, unsigned int config, int group_fd, __u64 read_format) 2454{ 2455 struct perf_event_attr attr; 2456 const pid_t pid = -1; 2457 const unsigned long flags = 0; 2458 2459 assert(!no_perf); 2460 2461 memset(&attr, 0, sizeof(struct perf_event_attr)); 2462 2463 attr.type = type; 2464 attr.size = sizeof(struct perf_event_attr); 2465 attr.config = config; 2466 attr.disabled = 0; 2467 attr.sample_type = PERF_SAMPLE_IDENTIFIER; 2468 attr.read_format = read_format; 2469 2470 const int fd = perf_event_open(&attr, pid, cpu, group_fd, flags); 2471 2472 return fd; 2473} 2474 2475int get_instr_count_fd(int cpu) 2476{ 2477 if (fd_instr_count_percpu[cpu]) 2478 return fd_instr_count_percpu[cpu]; 2479 2480 fd_instr_count_percpu[cpu] = open_perf_counter(cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, -1, 0); 2481 2482 return fd_instr_count_percpu[cpu]; 2483} 2484 2485int get_msr(int cpu, off_t offset, unsigned long long *msr) 2486{ 2487 ssize_t retval; 2488 2489 assert(!no_msr); 2490 2491 retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset); 2492 2493 if (retval != sizeof *msr) 2494 err(-1, "cpu%d: msr offset 0x%llx read failed", cpu, (unsigned long long)offset); 2495 2496 return 0; 2497} 2498 2499int add_msr_counter(int cpu, off_t offset) 2500{ 2501 ssize_t retval; 2502 unsigned long long value; 2503 2504 if (no_msr) 2505 return -1; 2506 2507 if (!offset) 2508 return -1; 2509 2510 retval = pread(get_msr_fd(cpu), &value, sizeof(value), offset); 2511 2512 /* if the read failed, the probe fails */ 2513 if (retval != sizeof(value)) 2514 return -1; 2515 2516 if (value == 0) 2517 return 0; 2518 2519 return 1; 2520} 2521 2522int add_rapl_msr_counter(int cpu, const struct rapl_counter_arch_info *cai) 2523{ 2524 int ret; 2525 2526 if (!(valid_rapl_msrs & cai->feature_mask)) 2527 return -1; 2528 2529 ret = add_msr_counter(cpu, cai->msr); 2530 if (ret < 0) 2531 return -1; 2532 2533 switch (cai->rci_index) { 2534 case RAPL_RCI_INDEX_ENERGY_PKG: 2535 case RAPL_RCI_INDEX_ENERGY_CORES: 2536 case RAPL_RCI_INDEX_DRAM: 2537 case RAPL_RCI_INDEX_GFX: 2538 case RAPL_RCI_INDEX_ENERGY_PLATFORM: 2539 if (ret == 0) 2540 return 1; 2541 } 2542 2543 /* PKG,DRAM_PERF_STATUS MSRs, can return any value */ 2544 return 1; 2545} 2546 2547/* Convert CPU ID to domain ID for given added perf counter. */ 2548unsigned int cpu_to_domain(const struct perf_counter_info *pc, int cpu) 2549{ 2550 switch (pc->scope) { 2551 case SCOPE_CPU: 2552 return cpu; 2553 2554 case SCOPE_CORE: 2555 return cpus[cpu].physical_core_id; 2556 2557 case SCOPE_PACKAGE: 2558 return cpus[cpu].physical_package_id; 2559 } 2560 2561 __builtin_unreachable(); 2562} 2563 2564#define MAX_DEFERRED 16 2565char *deferred_add_names[MAX_DEFERRED]; 2566char *deferred_skip_names[MAX_DEFERRED]; 2567int deferred_add_index; 2568int deferred_skip_index; 2569unsigned int deferred_add_consumed; 2570unsigned int deferred_skip_consumed; 2571 2572/* 2573 * HIDE_LIST - hide this list of counters, show the rest [default] 2574 * SHOW_LIST - show this list of counters, hide the rest 2575 */ 2576enum show_hide_mode { SHOW_LIST, HIDE_LIST } global_show_hide_mode = HIDE_LIST; 2577 2578void help(void) 2579{ 2580 fprintf(outf, 2581 "Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n" 2582 "\n" 2583 "Turbostat forks the specified COMMAND and prints statistics\n" 2584 "when COMMAND completes.\n" 2585 "If no COMMAND is specified, turbostat wakes every 5-seconds\n" 2586 "to print statistics, until interrupted.\n" 2587 " -a, --add counter\n" 2588 " add a counter\n" 2589 " eg. --add msr0x10,u64,cpu,delta,MY_TSC\n" 2590 " eg. --add perf/cstate_pkg/c2-residency,package,delta,percent,perfPC2\n" 2591 " eg. --add pmt,name=XTAL,type=raw,domain=package0,offset=0,lsb=0,msb=63,guid=0x1a067102\n" 2592 " -c, --cpu cpu-set\n" 2593 " limit output to summary plus cpu-set:\n" 2594 " {core | package | j,k,l..m,n-p }\n" 2595 " -d, --debug\n" 2596 " displays usec, Time_Of_Day_Seconds and more debugging\n" 2597 " debug messages are printed to stderr\n" 2598 " -D, --Dump\n" 2599 " displays the raw counter values\n" 2600 " -e, --enable [all | column]\n" 2601 " shows all or the specified disabled column\n" 2602 " -f, --force\n" 2603 " force load turbostat with minimum default features on unsupported platforms.\n" 2604 " -H, --hide [column | column,column,...]\n" 2605 " hide the specified column(s)\n" 2606 " -i, --interval sec.subsec\n" 2607 " override default 5-second measurement interval\n" 2608 " -J, --Joules\n" 2609 " displays energy in Joules instead of Watts\n" 2610 " -l, --list\n" 2611 " list column headers only\n" 2612 " -M, --no-msr\n" 2613 " disable all uses of the MSR driver\n" 2614 " -P, --no-perf\n" 2615 " disable all uses of the perf API\n" 2616 " -n, --num_iterations num\n" 2617 " number of the measurement iterations\n" 2618 " -N, --header_iterations num\n" 2619 " print header every num iterations\n" 2620 " -o, --out file\n" 2621 " create or truncate \"file\" for all output\n" 2622 " -q, --quiet\n" 2623 " skip decoding system configuration header\n" 2624 " -s, --show [column | column,column,...]\n" 2625 " show only the specified column(s)\n" 2626 " -S, --Summary\n" 2627 " limits output to 1-line system summary per interval\n" 2628 " -T, --TCC temperature\n" 2629 " sets the Thermal Control Circuit temperature in\n" 2630 " degrees Celsius\n" 2631 " -h, --help\n" 2632 " print this help message\n" 2633 " -v, --version\n\t\tprint version information\n\nFor more help, run \"man turbostat\"\n"); 2634} 2635 2636/* 2637 * bic_lookup 2638 * for all the strings in comma separate name_list, 2639 * set the approprate bit in return value. 2640 */ 2641void bic_lookup(cpu_set_t *ret_set, char *name_list, enum show_hide_mode mode) 2642{ 2643 unsigned int i; 2644 2645 while (name_list) { 2646 char *comma; 2647 2648 comma = strchr(name_list, ','); 2649 2650 if (comma) 2651 *comma = '\0'; 2652 2653 for (i = 0; i < MAX_BIC; ++i) { 2654 if (!strcmp(name_list, bic[i].name)) { 2655 SET_BIC(i, ret_set); 2656 break; 2657 } 2658 if (!strcmp(name_list, "all")) { 2659 bic_set_all(ret_set); 2660 break; 2661 } else if (!strcmp(name_list, "topology")) { 2662 CPU_OR(ret_set, ret_set, &bic_group_topology); 2663 break; 2664 } else if (!strcmp(name_list, "power")) { 2665 CPU_OR(ret_set, ret_set, &bic_group_thermal_pwr); 2666 break; 2667 } else if (!strcmp(name_list, "idle")) { 2668 CPU_OR(ret_set, ret_set, &bic_group_idle); 2669 break; 2670 } else if (!strcmp(name_list, "cache")) { 2671 CPU_OR(ret_set, ret_set, &bic_group_cache); 2672 break; 2673 } else if (!strcmp(name_list, "llc")) { 2674 CPU_OR(ret_set, ret_set, &bic_group_cache); 2675 break; 2676 } else if (!strcmp(name_list, "swidle")) { 2677 CPU_OR(ret_set, ret_set, &bic_group_sw_idle); 2678 break; 2679 } else if (!strcmp(name_list, "sysfs")) { /* legacy compatibility */ 2680 CPU_OR(ret_set, ret_set, &bic_group_sw_idle); 2681 break; 2682 } else if (!strcmp(name_list, "hwidle")) { 2683 CPU_OR(ret_set, ret_set, &bic_group_hw_idle); 2684 break; 2685 } else if (!strcmp(name_list, "frequency")) { 2686 CPU_OR(ret_set, ret_set, &bic_group_frequency); 2687 break; 2688 } else if (!strcmp(name_list, "other")) { 2689 CPU_OR(ret_set, ret_set, &bic_group_other); 2690 break; 2691 } 2692 } 2693 if (i == MAX_BIC) { 2694 if (mode == SHOW_LIST) { 2695 deferred_add_names[deferred_add_index++] = name_list; 2696 if (deferred_add_index >= MAX_DEFERRED) { 2697 fprintf(stderr, "More than max %d un-recognized --add options '%s'\n", MAX_DEFERRED, name_list); 2698 help(); 2699 exit(1); 2700 } 2701 } else { 2702 deferred_skip_names[deferred_skip_index++] = name_list; 2703 if (debug) 2704 fprintf(stderr, "deferred \"%s\"\n", name_list); 2705 if (deferred_skip_index >= MAX_DEFERRED) { 2706 fprintf(stderr, "More than max %d un-recognized --skip options '%s'\n", MAX_DEFERRED, name_list); 2707 help(); 2708 exit(1); 2709 } 2710 } 2711 } 2712 2713 name_list = comma; 2714 if (name_list) 2715 name_list++; 2716 2717 } 2718} 2719 2720/* 2721 * print_name() 2722 * Print column header name for raw 64-bit counter in 16 columns (at least 8-char plus a tab) 2723 * Otherwise, allow the name + tab to fit within 8-coumn tab-stop. 2724 * In both cases, left justififed, just like other turbostat columns, 2725 * to allow the column values to consume the tab. 2726 * 2727 * Yes, 32-bit counters can overflow 8-columns, and 2728 * 64-bit counters can overflow 16-columns, but that is uncommon. 2729 */ 2730static inline int print_name(int width, int *printed, char *delim, char *name, enum counter_type type, enum counter_format format) 2731{ 2732 UNUSED(type); 2733 2734 if (format == FORMAT_RAW && width >= 64) 2735 return (sprintf(outp, "%s%-8s", ((*printed)++ ? delim : ""), name)); 2736 else 2737 return (sprintf(outp, "%s%s", ((*printed)++ ? delim : ""), name)); 2738} 2739 2740static inline int print_hex_value(int width, int *printed, char *delim, unsigned long long value) 2741{ 2742 if (width <= 32) 2743 return (sprintf(outp, "%s%08x", ((*printed)++ ? delim : ""), (unsigned int)value)); 2744 else 2745 return (sprintf(outp, "%s%016llx", ((*printed)++ ? delim : ""), value)); 2746} 2747 2748static inline int print_decimal_value(int width, int *printed, char *delim, unsigned long long value) 2749{ 2750 UNUSED(width); 2751 2752 return (sprintf(outp, "%s%lld", ((*printed)++ ? delim : ""), value)); 2753} 2754 2755static inline int print_float_value(int *printed, char *delim, double value) 2756{ 2757 return (sprintf(outp, "%s%0.2f", ((*printed)++ ? delim : ""), value)); 2758} 2759 2760void print_header(char *delim) 2761{ 2762 struct msr_counter *mp; 2763 struct perf_counter_info *pp; 2764 struct pmt_counter *ppmt; 2765 int printed = 0; 2766 2767 if (DO_BIC(BIC_USEC)) 2768 outp += sprintf(outp, "%susec", (printed++ ? delim : "")); 2769 if (DO_BIC(BIC_TOD)) 2770 outp += sprintf(outp, "%sTime_Of_Day_Seconds", (printed++ ? delim : "")); 2771 if (DO_BIC(BIC_Package)) 2772 outp += sprintf(outp, "%sPackage", (printed++ ? delim : "")); 2773 if (DO_BIC(BIC_Die)) 2774 outp += sprintf(outp, "%sDie", (printed++ ? delim : "")); 2775 if (DO_BIC(BIC_L3)) 2776 outp += sprintf(outp, "%sL3", (printed++ ? delim : "")); 2777 if (DO_BIC(BIC_Node)) 2778 outp += sprintf(outp, "%sNode", (printed++ ? delim : "")); 2779 if (DO_BIC(BIC_Core)) 2780 outp += sprintf(outp, "%sCore", (printed++ ? delim : "")); 2781 if (DO_BIC(BIC_CPU)) 2782 outp += sprintf(outp, "%sCPU", (printed++ ? delim : "")); 2783 if (DO_BIC(BIC_APIC)) 2784 outp += sprintf(outp, "%sAPIC", (printed++ ? delim : "")); 2785 if (DO_BIC(BIC_X2APIC)) 2786 outp += sprintf(outp, "%sX2APIC", (printed++ ? delim : "")); 2787 if (DO_BIC(BIC_Avg_MHz)) 2788 outp += sprintf(outp, "%sAvg_MHz", (printed++ ? delim : "")); 2789 if (DO_BIC(BIC_Busy)) 2790 outp += sprintf(outp, "%sBusy%%", (printed++ ? delim : "")); 2791 if (DO_BIC(BIC_Bzy_MHz)) 2792 outp += sprintf(outp, "%sBzy_MHz", (printed++ ? delim : "")); 2793 if (DO_BIC(BIC_TSC_MHz)) 2794 outp += sprintf(outp, "%sTSC_MHz", (printed++ ? delim : "")); 2795 2796 if (DO_BIC(BIC_IPC)) 2797 outp += sprintf(outp, "%sIPC", (printed++ ? delim : "")); 2798 2799 if (DO_BIC(BIC_IRQ)) { 2800 if (sums_need_wide_columns) 2801 outp += sprintf(outp, "%s IRQ", (printed++ ? delim : "")); 2802 else 2803 outp += sprintf(outp, "%sIRQ", (printed++ ? delim : "")); 2804 } 2805 if (DO_BIC(BIC_NMI)) { 2806 if (sums_need_wide_columns) 2807 outp += sprintf(outp, "%s NMI", (printed++ ? delim : "")); 2808 else 2809 outp += sprintf(outp, "%sNMI", (printed++ ? delim : "")); 2810 } 2811 2812 if (DO_BIC(BIC_SMI)) 2813 outp += sprintf(outp, "%sSMI", (printed++ ? delim : "")); 2814 2815 if (DO_BIC(BIC_LLC_RPS)) 2816 outp += sprintf(outp, "%sLLCkRPS", (printed++ ? delim : "")); 2817 2818 if (DO_BIC(BIC_LLC_HIT)) 2819 outp += sprintf(outp, "%sLLC%%hit", (printed++ ? delim : "")); 2820 2821 for (mp = sys.tp; mp; mp = mp->next) 2822 outp += print_name(mp->width, &printed, delim, mp->name, mp->type, mp->format); 2823 2824 for (pp = sys.perf_tp; pp; pp = pp->next) 2825 outp += print_name(pp->width, &printed, delim, pp->name, pp->type, pp->format); 2826 2827 ppmt = sys.pmt_tp; 2828 while (ppmt) { 2829 switch (ppmt->type) { 2830 case PMT_TYPE_RAW: 2831 outp += print_name(pmt_counter_get_width(ppmt), &printed, delim, ppmt->name, COUNTER_ITEMS, ppmt->format); 2832 break; 2833 2834 case PMT_TYPE_XTAL_TIME: 2835 case PMT_TYPE_TCORE_CLOCK: 2836 outp += print_name(32, &printed, delim, ppmt->name, COUNTER_ITEMS, ppmt->format); 2837 break; 2838 } 2839 2840 ppmt = ppmt->next; 2841 } 2842 2843 if (DO_BIC(BIC_CPU_c1)) 2844 outp += sprintf(outp, "%sCPU%%c1", (printed++ ? delim : "")); 2845 if (DO_BIC(BIC_CPU_c3)) 2846 outp += sprintf(outp, "%sCPU%%c3", (printed++ ? delim : "")); 2847 if (DO_BIC(BIC_CPU_c6)) 2848 outp += sprintf(outp, "%sCPU%%c6", (printed++ ? delim : "")); 2849 if (DO_BIC(BIC_CPU_c7)) 2850 outp += sprintf(outp, "%sCPU%%c7", (printed++ ? delim : "")); 2851 2852 if (DO_BIC(BIC_Mod_c6)) 2853 outp += sprintf(outp, "%sMod%%c6", (printed++ ? delim : "")); 2854 2855 if (DO_BIC(BIC_CoreTmp)) 2856 outp += sprintf(outp, "%sCoreTmp", (printed++ ? delim : "")); 2857 2858 if (DO_BIC(BIC_CORE_THROT_CNT)) 2859 outp += sprintf(outp, "%sCoreThr", (printed++ ? delim : "")); 2860 2861 if (valid_rapl_msrs && !rapl_joules) { 2862 if (DO_BIC(BIC_CorWatt) && platform->has_per_core_rapl) 2863 outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : "")); 2864 } else if (valid_rapl_msrs && rapl_joules) { 2865 if (DO_BIC(BIC_Cor_J) && platform->has_per_core_rapl) 2866 outp += sprintf(outp, "%sCor_J", (printed++ ? delim : "")); 2867 } 2868 2869 for (mp = sys.cp; mp; mp = mp->next) 2870 outp += print_name(mp->width, &printed, delim, mp->name, mp->type, mp->format); 2871 2872 for (pp = sys.perf_cp; pp; pp = pp->next) 2873 outp += print_name(pp->width, &printed, delim, pp->name, pp->type, pp->format); 2874 2875 ppmt = sys.pmt_cp; 2876 while (ppmt) { 2877 switch (ppmt->type) { 2878 case PMT_TYPE_RAW: 2879 outp += print_name(pmt_counter_get_width(ppmt), &printed, delim, ppmt->name, COUNTER_ITEMS, ppmt->format); 2880 2881 break; 2882 2883 case PMT_TYPE_XTAL_TIME: 2884 case PMT_TYPE_TCORE_CLOCK: 2885 outp += print_name(32, &printed, delim, ppmt->name, COUNTER_ITEMS, ppmt->format); 2886 break; 2887 } 2888 2889 ppmt = ppmt->next; 2890 } 2891 if (DO_BIC(BIC_PkgTmp)) 2892 outp += sprintf(outp, "%sPkgTmp", (printed++ ? delim : "")); 2893 2894 if (DO_BIC(BIC_GFX_rc6)) 2895 outp += sprintf(outp, "%sGFX%%rc6", (printed++ ? delim : "")); 2896 2897 if (DO_BIC(BIC_GFXMHz)) 2898 outp += sprintf(outp, "%sGFXMHz", (printed++ ? delim : "")); 2899 2900 if (DO_BIC(BIC_GFXACTMHz)) 2901 outp += sprintf(outp, "%sGFXAMHz", (printed++ ? delim : "")); 2902 2903 if (DO_BIC(BIC_SAM_mc6)) 2904 outp += sprintf(outp, "%sSAM%%mc6", (printed++ ? delim : "")); 2905 2906 if (DO_BIC(BIC_SAMMHz)) 2907 outp += sprintf(outp, "%sSAMMHz", (printed++ ? delim : "")); 2908 2909 if (DO_BIC(BIC_SAMACTMHz)) 2910 outp += sprintf(outp, "%sSAMAMHz", (printed++ ? delim : "")); 2911 2912 if (DO_BIC(BIC_Totl_c0)) 2913 outp += sprintf(outp, "%sTotl%%C0", (printed++ ? delim : "")); 2914 if (DO_BIC(BIC_Any_c0)) 2915 outp += sprintf(outp, "%sAny%%C0", (printed++ ? delim : "")); 2916 if (DO_BIC(BIC_GFX_c0)) 2917 outp += sprintf(outp, "%sGFX%%C0", (printed++ ? delim : "")); 2918 if (DO_BIC(BIC_CPUGFX)) 2919 outp += sprintf(outp, "%sCPUGFX%%", (printed++ ? delim : "")); 2920 2921 if (DO_BIC(BIC_Pkgpc2)) 2922 outp += sprintf(outp, "%sPkg%%pc2", (printed++ ? delim : "")); 2923 if (DO_BIC(BIC_Pkgpc3)) 2924 outp += sprintf(outp, "%sPkg%%pc3", (printed++ ? delim : "")); 2925 if (DO_BIC(BIC_Pkgpc6)) 2926 outp += sprintf(outp, "%sPkg%%pc6", (printed++ ? delim : "")); 2927 if (DO_BIC(BIC_Pkgpc7)) 2928 outp += sprintf(outp, "%sPkg%%pc7", (printed++ ? delim : "")); 2929 if (DO_BIC(BIC_Pkgpc8)) 2930 outp += sprintf(outp, "%sPkg%%pc8", (printed++ ? delim : "")); 2931 if (DO_BIC(BIC_Pkgpc9)) 2932 outp += sprintf(outp, "%sPkg%%pc9", (printed++ ? delim : "")); 2933 if (DO_BIC(BIC_Pkgpc10)) 2934 outp += sprintf(outp, "%sPk%%pc10", (printed++ ? delim : "")); 2935 if (DO_BIC(BIC_Diec6)) 2936 outp += sprintf(outp, "%sDie%%c6", (printed++ ? delim : "")); 2937 if (DO_BIC(BIC_CPU_LPI)) 2938 outp += sprintf(outp, "%sCPU%%LPI", (printed++ ? delim : "")); 2939 if (DO_BIC(BIC_SYS_LPI)) 2940 outp += sprintf(outp, "%sSYS%%LPI", (printed++ ? delim : "")); 2941 2942 if (!rapl_joules) { 2943 if (DO_BIC(BIC_PkgWatt)) 2944 outp += sprintf(outp, "%sPkgWatt", (printed++ ? delim : "")); 2945 if (DO_BIC(BIC_CorWatt) && !platform->has_per_core_rapl) 2946 outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : "")); 2947 if (DO_BIC(BIC_GFXWatt)) 2948 outp += sprintf(outp, "%sGFXWatt", (printed++ ? delim : "")); 2949 if (DO_BIC(BIC_RAMWatt)) 2950 outp += sprintf(outp, "%sRAMWatt", (printed++ ? delim : "")); 2951 if (DO_BIC(BIC_PKG__)) 2952 outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : "")); 2953 if (DO_BIC(BIC_RAM__)) 2954 outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : "")); 2955 } else { 2956 if (DO_BIC(BIC_Pkg_J)) 2957 outp += sprintf(outp, "%sPkg_J", (printed++ ? delim : "")); 2958 if (DO_BIC(BIC_Cor_J) && !platform->has_per_core_rapl) 2959 outp += sprintf(outp, "%sCor_J", (printed++ ? delim : "")); 2960 if (DO_BIC(BIC_GFX_J)) 2961 outp += sprintf(outp, "%sGFX_J", (printed++ ? delim : "")); 2962 if (DO_BIC(BIC_RAM_J)) 2963 outp += sprintf(outp, "%sRAM_J", (printed++ ? delim : "")); 2964 if (DO_BIC(BIC_PKG__)) 2965 outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : "")); 2966 if (DO_BIC(BIC_RAM__)) 2967 outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : "")); 2968 } 2969 if (DO_BIC(BIC_UNCORE_MHZ)) 2970 outp += sprintf(outp, "%sUncMHz", (printed++ ? delim : "")); 2971 2972 for (mp = sys.pp; mp; mp = mp->next) 2973 outp += print_name(mp->width, &printed, delim, mp->name, mp->type, mp->format); 2974 2975 for (pp = sys.perf_pp; pp; pp = pp->next) 2976 outp += print_name(pp->width, &printed, delim, pp->name, pp->type, pp->format); 2977 2978 ppmt = sys.pmt_pp; 2979 while (ppmt) { 2980 switch (ppmt->type) { 2981 case PMT_TYPE_RAW: 2982 outp += print_name(pmt_counter_get_width(ppmt), &printed, delim, ppmt->name, COUNTER_ITEMS, ppmt->format); 2983 break; 2984 2985 case PMT_TYPE_XTAL_TIME: 2986 case PMT_TYPE_TCORE_CLOCK: 2987 outp += print_name(32, &printed, delim, ppmt->name, COUNTER_ITEMS, ppmt->format); 2988 break; 2989 } 2990 2991 ppmt = ppmt->next; 2992 } 2993 2994 if (DO_BIC(BIC_SysWatt)) 2995 outp += sprintf(outp, "%sSysWatt", (printed++ ? delim : "")); 2996 if (DO_BIC(BIC_Sys_J)) 2997 outp += sprintf(outp, "%sSys_J", (printed++ ? delim : "")); 2998 2999 outp += sprintf(outp, "\n"); 3000} 3001 3002/* 3003 * pct(numerator, denominator) 3004 * 3005 * Return sanity checked percentage (100.0 * numerator/denominotor) 3006 * 3007 * n < 0: nan 3008 * d <= 0: nan 3009 * n/d > 1.1: nan 3010 */ 3011double pct(double numerator, double denominator) 3012{ 3013 double retval; 3014 3015 if (numerator < 0) 3016 return nan(""); 3017 3018 if (denominator <= 0) 3019 return nan(""); 3020 3021 retval = 100.0 * numerator / denominator; 3022 3023 if (retval > 110.0) 3024 return nan(""); 3025 3026 return retval; 3027} 3028 3029int dump_counters(PER_THREAD_PARAMS) 3030{ 3031 int i; 3032 struct msr_counter *mp; 3033 struct platform_counters *pplat_cnt = p == package_odd ? &platform_counters_odd : &platform_counters_even; 3034 3035 outp += sprintf(outp, "t %p, c %p, p %p\n", t, c, p); 3036 3037 if (t) { 3038 outp += sprintf(outp, "CPU: %d flags 0x%x\n", t->cpu_id, t->flags); 3039 outp += sprintf(outp, "TSC: %016llX\n", t->tsc); 3040 outp += sprintf(outp, "aperf: %016llX\n", t->aperf); 3041 outp += sprintf(outp, "mperf: %016llX\n", t->mperf); 3042 outp += sprintf(outp, "c1: %016llX\n", t->c1); 3043 3044 if (DO_BIC(BIC_IPC)) 3045 outp += sprintf(outp, "IPC: %lld\n", t->instr_count); 3046 3047 if (DO_BIC(BIC_IRQ)) 3048 outp += sprintf(outp, "IRQ: %lld\n", t->irq_count); 3049 if (DO_BIC(BIC_NMI)) 3050 outp += sprintf(outp, "IRQ: %lld\n", t->nmi_count); 3051 if (DO_BIC(BIC_SMI)) 3052 outp += sprintf(outp, "SMI: %d\n", t->smi_count); 3053 3054 outp += sprintf(outp, "LLC refs: %lld", t->llc.references); 3055 outp += sprintf(outp, "LLC miss: %lld", t->llc.misses); 3056 outp += sprintf(outp, "LLC Hit%%: %.2f", pct((t->llc.references - t->llc.misses), t->llc.references)); 3057 3058 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 3059 outp += sprintf(outp, "tADDED [%d] %8s msr0x%x: %08llX %s\n", i, mp->name, mp->msr_num, t->counter[i], mp->sp->path); 3060 } 3061 } 3062 3063 if (c && is_cpu_first_thread_in_core(t, c)) { 3064 outp += sprintf(outp, "core: %d\n", c->core_id); 3065 outp += sprintf(outp, "c3: %016llX\n", c->c3); 3066 outp += sprintf(outp, "c6: %016llX\n", c->c6); 3067 outp += sprintf(outp, "c7: %016llX\n", c->c7); 3068 outp += sprintf(outp, "DTS: %dC\n", c->core_temp_c); 3069 outp += sprintf(outp, "cpu_throt_count: %016llX\n", c->core_throt_cnt); 3070 3071 const unsigned long long energy_value = c->core_energy.raw_value * c->core_energy.scale; 3072 const double energy_scale = c->core_energy.scale; 3073 3074 if (c->core_energy.unit == RAPL_UNIT_JOULES) 3075 outp += sprintf(outp, "Joules: %0llX (scale: %lf)\n", energy_value, energy_scale); 3076 3077 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 3078 outp += sprintf(outp, "cADDED [%d] %8s msr0x%x: %08llX %s\n", i, mp->name, mp->msr_num, c->counter[i], mp->sp->path); 3079 } 3080 outp += sprintf(outp, "mc6_us: %016llX\n", c->mc6_us); 3081 } 3082 3083 if (p && is_cpu_first_core_in_package(t, p)) { 3084 outp += sprintf(outp, "package: %d\n", p->package_id); 3085 3086 outp += sprintf(outp, "Weighted cores: %016llX\n", p->pkg_wtd_core_c0); 3087 outp += sprintf(outp, "Any cores: %016llX\n", p->pkg_any_core_c0); 3088 outp += sprintf(outp, "Any GFX: %016llX\n", p->pkg_any_gfxe_c0); 3089 outp += sprintf(outp, "CPU + GFX: %016llX\n", p->pkg_both_core_gfxe_c0); 3090 3091 outp += sprintf(outp, "pc2: %016llX\n", p->pc2); 3092 if (DO_BIC(BIC_Pkgpc3)) 3093 outp += sprintf(outp, "pc3: %016llX\n", p->pc3); 3094 if (DO_BIC(BIC_Pkgpc6)) 3095 outp += sprintf(outp, "pc6: %016llX\n", p->pc6); 3096 if (DO_BIC(BIC_Pkgpc7)) 3097 outp += sprintf(outp, "pc7: %016llX\n", p->pc7); 3098 outp += sprintf(outp, "pc8: %016llX\n", p->pc8); 3099 outp += sprintf(outp, "pc9: %016llX\n", p->pc9); 3100 outp += sprintf(outp, "pc10: %016llX\n", p->pc10); 3101 outp += sprintf(outp, "cpu_lpi: %016llX\n", p->cpu_lpi); 3102 outp += sprintf(outp, "sys_lpi: %016llX\n", p->sys_lpi); 3103 outp += sprintf(outp, "Joules PKG: %0llX\n", p->energy_pkg.raw_value); 3104 outp += sprintf(outp, "Joules COR: %0llX\n", p->energy_cores.raw_value); 3105 outp += sprintf(outp, "Joules GFX: %0llX\n", p->energy_gfx.raw_value); 3106 outp += sprintf(outp, "Joules RAM: %0llX\n", p->energy_dram.raw_value); 3107 outp += sprintf(outp, "Joules PSYS: %0llX\n", pplat_cnt->energy_psys.raw_value); 3108 outp += sprintf(outp, "Throttle PKG: %0llX\n", p->rapl_pkg_perf_status.raw_value); 3109 outp += sprintf(outp, "Throttle RAM: %0llX\n", p->rapl_dram_perf_status.raw_value); 3110 outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c); 3111 3112 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 3113 outp += sprintf(outp, "pADDED [%d] %8s msr0x%x: %08llX %s\n", i, mp->name, mp->msr_num, p->counter[i], mp->sp->path); 3114 } 3115 } 3116 3117 outp += sprintf(outp, "\n"); 3118 3119 return 0; 3120} 3121 3122double rapl_counter_get_value(const struct rapl_counter *c, enum rapl_unit desired_unit, double interval) 3123{ 3124 assert(desired_unit != RAPL_UNIT_INVALID); 3125 3126 /* 3127 * For now we don't expect anything other than joules, 3128 * so just simplify the logic. 3129 */ 3130 assert(c->unit == RAPL_UNIT_JOULES); 3131 3132 const double scaled = c->raw_value * c->scale; 3133 3134 if (desired_unit == RAPL_UNIT_WATTS) 3135 return scaled / interval; 3136 return scaled; 3137} 3138 3139void get_perf_llc_stats(int cpu, struct llc_stats *llc) 3140{ 3141 struct read_format { 3142 unsigned long long num_read; 3143 struct llc_stats llc; 3144 } r; 3145 const ssize_t expected_read_size = sizeof(r); 3146 ssize_t actual_read_size; 3147 3148 actual_read_size = read(fd_llc_percpu[cpu], &r, expected_read_size); 3149 3150 if (actual_read_size == -1) 3151 err(-1, "%s(cpu%d,) %d,,%ld\n", __func__, cpu, fd_llc_percpu[cpu], expected_read_size); 3152 3153 llc->references = r.llc.references; 3154 llc->misses = r.llc.misses; 3155 if (actual_read_size != expected_read_size) 3156 warn("%s: failed to read perf_data (req %zu act %zu)", __func__, expected_read_size, actual_read_size); 3157} 3158 3159/* 3160 * column formatting convention & formats 3161 */ 3162int format_counters(PER_THREAD_PARAMS) 3163{ 3164 static int count; 3165 3166 struct platform_counters *pplat_cnt = NULL; 3167 double interval_float, tsc; 3168 char *fmt8 = "%s%.2f"; 3169 3170 int i; 3171 struct msr_counter *mp; 3172 struct perf_counter_info *pp; 3173 struct pmt_counter *ppmt; 3174 char *delim = "\t"; 3175 int printed = 0; 3176 3177 if (t == &average.threads) { 3178 pplat_cnt = count & 1 ? &platform_counters_odd : &platform_counters_even; 3179 ++count; 3180 } 3181 3182 /* if showing only 1st thread in core and this isn't one, bail out */ 3183 if (show_core_only && !is_cpu_first_thread_in_core(t, c)) 3184 return 0; 3185 3186 /* if showing only 1st thread in pkg and this isn't one, bail out */ 3187 if (show_pkg_only && !is_cpu_first_core_in_package(t, p)) 3188 return 0; 3189 3190 /*if not summary line and --cpu is used */ 3191 if ((t != &average.threads) && (cpu_subset && !CPU_ISSET_S(t->cpu_id, cpu_subset_size, cpu_subset))) 3192 return 0; 3193 3194 if (DO_BIC(BIC_USEC)) { 3195 /* on each row, print how many usec each timestamp took to gather */ 3196 struct timeval tv; 3197 3198 timersub(&t->tv_end, &t->tv_begin, &tv); 3199 outp += sprintf(outp, "%5ld\t", tv.tv_sec * 1000000 + tv.tv_usec); 3200 } 3201 3202 /* Time_Of_Day_Seconds: on each row, print sec.usec last timestamp taken */ 3203 if (DO_BIC(BIC_TOD)) 3204 outp += sprintf(outp, "%10ld.%06ld\t", t->tv_end.tv_sec, t->tv_end.tv_usec); 3205 3206 interval_float = t->tv_delta.tv_sec + t->tv_delta.tv_usec / 1000000.0; 3207 3208 tsc = t->tsc * tsc_tweak; 3209 3210 /* topo columns, print blanks on 1st (average) line */ 3211 if (t == &average.threads) { 3212 if (DO_BIC(BIC_Package)) 3213 outp += sprintf(outp, "%s-", (printed++ ? delim : "")); 3214 if (DO_BIC(BIC_Die)) 3215 outp += sprintf(outp, "%s-", (printed++ ? delim : "")); 3216 if (DO_BIC(BIC_L3)) 3217 outp += sprintf(outp, "%s-", (printed++ ? delim : "")); 3218 if (DO_BIC(BIC_Node)) 3219 outp += sprintf(outp, "%s-", (printed++ ? delim : "")); 3220 if (DO_BIC(BIC_Core)) 3221 outp += sprintf(outp, "%s-", (printed++ ? delim : "")); 3222 if (DO_BIC(BIC_CPU)) 3223 outp += sprintf(outp, "%s-", (printed++ ? delim : "")); 3224 if (DO_BIC(BIC_APIC)) 3225 outp += sprintf(outp, "%s-", (printed++ ? delim : "")); 3226 if (DO_BIC(BIC_X2APIC)) 3227 outp += sprintf(outp, "%s-", (printed++ ? delim : "")); 3228 } else { 3229 if (DO_BIC(BIC_Package)) { 3230 if (p) 3231 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->package_id); 3232 else 3233 outp += sprintf(outp, "%s-", (printed++ ? delim : "")); 3234 } 3235 if (DO_BIC(BIC_Die)) { 3236 if (c) 3237 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), cpus[t->cpu_id].die_id); 3238 else 3239 outp += sprintf(outp, "%s-", (printed++ ? delim : "")); 3240 } 3241 if (DO_BIC(BIC_L3)) { 3242 if (c) 3243 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), cpus[t->cpu_id].l3_id); 3244 else 3245 outp += sprintf(outp, "%s-", (printed++ ? delim : "")); 3246 } 3247 if (DO_BIC(BIC_Node)) { 3248 if (t) 3249 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), cpus[t->cpu_id].physical_node_id); 3250 else 3251 outp += sprintf(outp, "%s-", (printed++ ? delim : "")); 3252 } 3253 if (DO_BIC(BIC_Core)) { 3254 if (c) 3255 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_id); 3256 else 3257 outp += sprintf(outp, "%s-", (printed++ ? delim : "")); 3258 } 3259 if (DO_BIC(BIC_CPU)) 3260 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->cpu_id); 3261 if (DO_BIC(BIC_APIC)) 3262 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->apic_id); 3263 if (DO_BIC(BIC_X2APIC)) 3264 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->x2apic_id); 3265 } 3266 3267 if (DO_BIC(BIC_Avg_MHz)) 3268 outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 / units * t->aperf / interval_float); 3269 3270 if (DO_BIC(BIC_Busy)) 3271 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(t->mperf, tsc)); 3272 3273 if (DO_BIC(BIC_Bzy_MHz)) { 3274 if (has_base_hz) 3275 outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), base_hz / units * t->aperf / t->mperf); 3276 else 3277 outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), tsc / units * t->aperf / t->mperf / interval_float); 3278 } 3279 3280 if (DO_BIC(BIC_TSC_MHz)) 3281 outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 * t->tsc / units / interval_float); 3282 3283 if (DO_BIC(BIC_IPC)) 3284 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 1.0 * t->instr_count / t->aperf); 3285 3286 /* IRQ */ 3287 if (DO_BIC(BIC_IRQ)) { 3288 if (sums_need_wide_columns) 3289 outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->irq_count); 3290 else 3291 outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->irq_count); 3292 } 3293 3294 /* NMI */ 3295 if (DO_BIC(BIC_NMI)) { 3296 if (sums_need_wide_columns) 3297 outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->nmi_count); 3298 else 3299 outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->nmi_count); 3300 } 3301 3302 /* SMI */ 3303 if (DO_BIC(BIC_SMI)) 3304 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->smi_count); 3305 3306 /* LLC Stats */ 3307 if (DO_BIC(BIC_LLC_RPS) || DO_BIC(BIC_LLC_HIT)) { 3308 if (DO_BIC(BIC_LLC_RPS)) 3309 outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), t->llc.references / interval_float / 1000); 3310 3311 if (DO_BIC(BIC_LLC_HIT)) 3312 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), pct((t->llc.references - t->llc.misses), t->llc.references)); 3313 } 3314 3315 /* Added Thread Counters */ 3316 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 3317 if (mp->format == FORMAT_RAW) 3318 outp += print_hex_value(mp->width, &printed, delim, t->counter[i]); 3319 else if (mp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE) 3320 outp += print_decimal_value(mp->width, &printed, delim, t->counter[i]); 3321 else if (mp->format == FORMAT_PERCENT) { 3322 if (mp->type == COUNTER_USEC) 3323 outp += print_float_value(&printed, delim, t->counter[i] / interval_float / 10000); 3324 else 3325 outp += print_float_value(&printed, delim, pct(t->counter[i], tsc)); 3326 } 3327 } 3328 3329 /* Added perf Thread Counters */ 3330 for (i = 0, pp = sys.perf_tp; pp; ++i, pp = pp->next) { 3331 if (pp->format == FORMAT_RAW) 3332 outp += print_hex_value(pp->width, &printed, delim, t->perf_counter[i]); 3333 else if (pp->format == FORMAT_DELTA || pp->format == FORMAT_AVERAGE) 3334 outp += print_decimal_value(pp->width, &printed, delim, t->perf_counter[i]); 3335 else if (pp->format == FORMAT_PERCENT) { 3336 if (pp->type == COUNTER_USEC) 3337 outp += print_float_value(&printed, delim, t->perf_counter[i] / interval_float / 10000); 3338 else 3339 outp += print_float_value(&printed, delim, pct(t->perf_counter[i], tsc)); 3340 } 3341 } 3342 3343 /* Added PMT Thread Counters */ 3344 for (i = 0, ppmt = sys.pmt_tp; ppmt; i++, ppmt = ppmt->next) { 3345 const unsigned long value_raw = t->pmt_counter[i]; 3346 double value_converted; 3347 switch (ppmt->type) { 3348 case PMT_TYPE_RAW: 3349 outp += print_hex_value(pmt_counter_get_width(ppmt), &printed, delim, t->pmt_counter[i]); 3350 break; 3351 3352 case PMT_TYPE_XTAL_TIME: 3353 value_converted = pct(value_raw / crystal_hz, interval_float); 3354 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted); 3355 break; 3356 3357 case PMT_TYPE_TCORE_CLOCK: 3358 value_converted = pct(value_raw / tcore_clock_freq_hz, interval_float); 3359 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted); 3360 } 3361 } 3362 3363 /* C1 */ 3364 if (DO_BIC(BIC_CPU_c1)) 3365 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(t->c1, tsc)); 3366 3367 /* print per-core data only for 1st thread in core */ 3368 if (!is_cpu_first_thread_in_core(t, c)) 3369 goto done; 3370 3371 if (DO_BIC(BIC_CPU_c3)) 3372 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->c3, tsc)); 3373 if (DO_BIC(BIC_CPU_c6)) 3374 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->c6, tsc)); 3375 if (DO_BIC(BIC_CPU_c7)) 3376 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->c7, tsc)); 3377 3378 /* Mod%c6 */ 3379 if (DO_BIC(BIC_Mod_c6)) 3380 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->mc6_us, tsc)); 3381 3382 if (DO_BIC(BIC_CoreTmp)) 3383 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_temp_c); 3384 3385 /* Core throttle count */ 3386 if (DO_BIC(BIC_CORE_THROT_CNT)) 3387 outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), c->core_throt_cnt); 3388 3389 /* Added Core Counters */ 3390 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 3391 if (mp->format == FORMAT_RAW) 3392 outp += print_hex_value(mp->width, &printed, delim, c->counter[i]); 3393 else if (mp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE) 3394 outp += print_decimal_value(mp->width, &printed, delim, c->counter[i]); 3395 else if (mp->format == FORMAT_PERCENT) 3396 outp += print_float_value(&printed, delim, pct(c->counter[i], tsc)); 3397 } 3398 3399 /* Added perf Core counters */ 3400 for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) { 3401 if (pp->format == FORMAT_RAW) 3402 outp += print_hex_value(pp->width, &printed, delim, c->perf_counter[i]); 3403 else if (pp->format == FORMAT_DELTA || pp->format == FORMAT_AVERAGE) 3404 outp += print_decimal_value(pp->width, &printed, delim, c->perf_counter[i]); 3405 else if (pp->format == FORMAT_PERCENT) 3406 outp += print_float_value(&printed, delim, pct(c->perf_counter[i], tsc)); 3407 } 3408 3409 /* Added PMT Core counters */ 3410 for (i = 0, ppmt = sys.pmt_cp; ppmt; i++, ppmt = ppmt->next) { 3411 const unsigned long value_raw = c->pmt_counter[i]; 3412 double value_converted; 3413 switch (ppmt->type) { 3414 case PMT_TYPE_RAW: 3415 outp += print_hex_value(pmt_counter_get_width(ppmt), &printed, delim, c->pmt_counter[i]); 3416 break; 3417 3418 case PMT_TYPE_XTAL_TIME: 3419 value_converted = pct(value_raw / crystal_hz, interval_float); 3420 outp += print_float_value(&printed, delim, value_converted); 3421 break; 3422 3423 case PMT_TYPE_TCORE_CLOCK: 3424 value_converted = pct(value_raw / tcore_clock_freq_hz, interval_float); 3425 outp += print_float_value(&printed, delim, value_converted); 3426 } 3427 } 3428 3429 if (DO_BIC(BIC_CorWatt) && platform->has_per_core_rapl) 3430 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&c->core_energy, RAPL_UNIT_WATTS, interval_float)); 3431 if (DO_BIC(BIC_Cor_J) && platform->has_per_core_rapl) 3432 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&c->core_energy, RAPL_UNIT_JOULES, interval_float)); 3433 3434 /* print per-package data only for 1st core in package */ 3435 if (!is_cpu_first_core_in_package(t, p)) 3436 goto done; 3437 3438 /* PkgTmp */ 3439 if (DO_BIC(BIC_PkgTmp)) 3440 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->pkg_temp_c); 3441 3442 /* GFXrc6 */ 3443 if (DO_BIC(BIC_GFX_rc6)) { 3444 if (p->gfx_rc6_ms == -1) { /* detect GFX counter reset */ 3445 outp += sprintf(outp, "%s**.**", (printed++ ? delim : "")); 3446 } else { 3447 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), p->gfx_rc6_ms / 10.0 / interval_float); 3448 } 3449 } 3450 3451 /* GFXMHz */ 3452 if (DO_BIC(BIC_GFXMHz)) 3453 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_mhz); 3454 3455 /* GFXACTMHz */ 3456 if (DO_BIC(BIC_GFXACTMHz)) 3457 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_act_mhz); 3458 3459 /* SAMmc6 */ 3460 if (DO_BIC(BIC_SAM_mc6)) { 3461 if (p->sam_mc6_ms == -1) { /* detect GFX counter reset */ 3462 outp += sprintf(outp, "%s**.**", (printed++ ? delim : "")); 3463 } else { 3464 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), p->sam_mc6_ms / 10.0 / interval_float); 3465 } 3466 } 3467 3468 /* SAMMHz */ 3469 if (DO_BIC(BIC_SAMMHz)) 3470 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->sam_mhz); 3471 3472 /* SAMACTMHz */ 3473 if (DO_BIC(BIC_SAMACTMHz)) 3474 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->sam_act_mhz); 3475 3476 /* Totl%C0, Any%C0 GFX%C0 CPUGFX% */ 3477 if (DO_BIC(BIC_Totl_c0)) 3478 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100 * p->pkg_wtd_core_c0 / tsc); /* can exceed 100% */ 3479 if (DO_BIC(BIC_Any_c0)) 3480 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pkg_any_core_c0, tsc)); 3481 if (DO_BIC(BIC_GFX_c0)) 3482 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pkg_any_gfxe_c0, tsc)); 3483 if (DO_BIC(BIC_CPUGFX)) 3484 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pkg_both_core_gfxe_c0, tsc)); 3485 3486 if (DO_BIC(BIC_Pkgpc2)) 3487 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc2, tsc)); 3488 if (DO_BIC(BIC_Pkgpc3)) 3489 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc3, tsc)); 3490 if (DO_BIC(BIC_Pkgpc6)) 3491 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc6, tsc)); 3492 if (DO_BIC(BIC_Pkgpc7)) 3493 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc7, tsc)); 3494 if (DO_BIC(BIC_Pkgpc8)) 3495 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc8, tsc)); 3496 if (DO_BIC(BIC_Pkgpc9)) 3497 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc9, tsc)); 3498 if (DO_BIC(BIC_Pkgpc10)) 3499 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc10, tsc)); 3500 3501 if (DO_BIC(BIC_Diec6)) 3502 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->die_c6 / crystal_hz, interval_float)); 3503 3504 if (DO_BIC(BIC_CPU_LPI)) { 3505 if (p->cpu_lpi >= 0) 3506 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->cpu_lpi / 1000000.0, interval_float)); 3507 else 3508 outp += sprintf(outp, "%s(neg)", (printed++ ? delim : "")); 3509 } 3510 if (DO_BIC(BIC_SYS_LPI)) { 3511 if (p->sys_lpi >= 0) 3512 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->sys_lpi / 1000000.0, interval_float)); 3513 else 3514 outp += sprintf(outp, "%s(neg)", (printed++ ? delim : "")); 3515 } 3516 3517 if (DO_BIC(BIC_PkgWatt)) 3518 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_pkg, RAPL_UNIT_WATTS, interval_float)); 3519 if (DO_BIC(BIC_CorWatt) && !platform->has_per_core_rapl) 3520 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_cores, RAPL_UNIT_WATTS, interval_float)); 3521 if (DO_BIC(BIC_GFXWatt)) 3522 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_gfx, RAPL_UNIT_WATTS, interval_float)); 3523 if (DO_BIC(BIC_RAMWatt)) 3524 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_dram, RAPL_UNIT_WATTS, interval_float)); 3525 if (DO_BIC(BIC_Pkg_J)) 3526 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_pkg, RAPL_UNIT_JOULES, interval_float)); 3527 if (DO_BIC(BIC_Cor_J) && !platform->has_per_core_rapl) 3528 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_cores, RAPL_UNIT_JOULES, interval_float)); 3529 if (DO_BIC(BIC_GFX_J)) 3530 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_gfx, RAPL_UNIT_JOULES, interval_float)); 3531 if (DO_BIC(BIC_RAM_J)) 3532 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_dram, RAPL_UNIT_JOULES, interval_float)); 3533 if (DO_BIC(BIC_PKG__)) 3534 outp += 3535 sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->rapl_pkg_perf_status, RAPL_UNIT_WATTS, interval_float)); 3536 if (DO_BIC(BIC_RAM__)) 3537 outp += 3538 sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->rapl_dram_perf_status, RAPL_UNIT_WATTS, interval_float)); 3539 /* UncMHz */ 3540 if (DO_BIC(BIC_UNCORE_MHZ)) 3541 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->uncore_mhz); 3542 3543 /* Added Package Counters */ 3544 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 3545 if (mp->format == FORMAT_RAW) 3546 outp += print_hex_value(mp->width, &printed, delim, p->counter[i]); 3547 else if (mp->type == COUNTER_K2M) 3548 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), (unsigned int)p->counter[i] / 1000); 3549 else if (mp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE) 3550 outp += print_decimal_value(mp->width, &printed, delim, p->counter[i]); 3551 else if (mp->format == FORMAT_PERCENT) 3552 outp += print_float_value(&printed, delim, pct(p->counter[i], tsc)); 3553 } 3554 3555 /* Added perf Package Counters */ 3556 for (i = 0, pp = sys.perf_pp; pp; i++, pp = pp->next) { 3557 if (pp->format == FORMAT_RAW) 3558 outp += print_hex_value(pp->width, &printed, delim, p->perf_counter[i]); 3559 else if (pp->type == COUNTER_K2M) 3560 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), (unsigned int)p->perf_counter[i] / 1000); 3561 else if (pp->format == FORMAT_DELTA || pp->format == FORMAT_AVERAGE) 3562 outp += print_decimal_value(pp->width, &printed, delim, p->perf_counter[i]); 3563 else if (pp->format == FORMAT_PERCENT) 3564 outp += print_float_value(&printed, delim, pct(p->perf_counter[i], tsc)); 3565 } 3566 3567 /* Added PMT Package Counters */ 3568 for (i = 0, ppmt = sys.pmt_pp; ppmt; i++, ppmt = ppmt->next) { 3569 const unsigned long value_raw = p->pmt_counter[i]; 3570 double value_converted; 3571 switch (ppmt->type) { 3572 case PMT_TYPE_RAW: 3573 outp += print_hex_value(pmt_counter_get_width(ppmt), &printed, delim, p->pmt_counter[i]); 3574 break; 3575 3576 case PMT_TYPE_XTAL_TIME: 3577 value_converted = pct(value_raw / crystal_hz, interval_float); 3578 outp += print_float_value(&printed, delim, value_converted); 3579 break; 3580 3581 case PMT_TYPE_TCORE_CLOCK: 3582 value_converted = pct(value_raw / tcore_clock_freq_hz, interval_float); 3583 outp += print_float_value(&printed, delim, value_converted); 3584 } 3585 } 3586 3587 if (DO_BIC(BIC_SysWatt) && (t == &average.threads)) 3588 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), 3589 rapl_counter_get_value(&pplat_cnt->energy_psys, RAPL_UNIT_WATTS, interval_float)); 3590 if (DO_BIC(BIC_Sys_J) && (t == &average.threads)) 3591 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), 3592 rapl_counter_get_value(&pplat_cnt->energy_psys, RAPL_UNIT_JOULES, interval_float)); 3593 3594done: 3595 if (*(outp - 1) != '\n') 3596 outp += sprintf(outp, "\n"); 3597 3598 return 0; 3599} 3600 3601void flush_output_stdout(void) 3602{ 3603 FILE *filep; 3604 3605 if (outf == stderr) 3606 filep = stdout; 3607 else 3608 filep = outf; 3609 3610 fputs(output_buffer, filep); 3611 fflush(filep); 3612 3613 outp = output_buffer; 3614} 3615 3616void flush_output_stderr(void) 3617{ 3618 fputs(output_buffer, outf); 3619 fflush(outf); 3620 outp = output_buffer; 3621} 3622 3623void format_all_counters(PER_THREAD_PARAMS) 3624{ 3625 static int count; 3626 3627 if ((!count || (header_iterations && !(count % header_iterations))) || !summary_only) 3628 print_header("\t"); 3629 3630 format_counters(&average.threads, &average.cores, &average.packages); 3631 3632 count++; 3633 3634 if (summary_only) 3635 return; 3636 3637 for_all_cpus(format_counters, t, c, p); 3638} 3639 3640#define DELTA_WRAP32(new, old) \ 3641 old = ((((unsigned long long)new << 32) - ((unsigned long long)old << 32)) >> 32); 3642 3643int delta_package(struct pkg_data *new, struct pkg_data *old) 3644{ 3645 int i; 3646 struct msr_counter *mp; 3647 struct perf_counter_info *pp; 3648 struct pmt_counter *ppmt; 3649 3650 if (DO_BIC(BIC_Totl_c0)) 3651 old->pkg_wtd_core_c0 = new->pkg_wtd_core_c0 - old->pkg_wtd_core_c0; 3652 if (DO_BIC(BIC_Any_c0)) 3653 old->pkg_any_core_c0 = new->pkg_any_core_c0 - old->pkg_any_core_c0; 3654 if (DO_BIC(BIC_GFX_c0)) 3655 old->pkg_any_gfxe_c0 = new->pkg_any_gfxe_c0 - old->pkg_any_gfxe_c0; 3656 if (DO_BIC(BIC_CPUGFX)) 3657 old->pkg_both_core_gfxe_c0 = new->pkg_both_core_gfxe_c0 - old->pkg_both_core_gfxe_c0; 3658 3659 old->pc2 = new->pc2 - old->pc2; 3660 if (DO_BIC(BIC_Pkgpc3)) 3661 old->pc3 = new->pc3 - old->pc3; 3662 if (DO_BIC(BIC_Pkgpc6)) 3663 old->pc6 = new->pc6 - old->pc6; 3664 if (DO_BIC(BIC_Pkgpc7)) 3665 old->pc7 = new->pc7 - old->pc7; 3666 old->pc8 = new->pc8 - old->pc8; 3667 old->pc9 = new->pc9 - old->pc9; 3668 old->pc10 = new->pc10 - old->pc10; 3669 old->die_c6 = new->die_c6 - old->die_c6; 3670 old->cpu_lpi = new->cpu_lpi - old->cpu_lpi; 3671 old->sys_lpi = new->sys_lpi - old->sys_lpi; 3672 old->pkg_temp_c = new->pkg_temp_c; 3673 3674 /* flag an error when rc6 counter resets/wraps */ 3675 if (old->gfx_rc6_ms > new->gfx_rc6_ms) 3676 old->gfx_rc6_ms = -1; 3677 else 3678 old->gfx_rc6_ms = new->gfx_rc6_ms - old->gfx_rc6_ms; 3679 3680 old->uncore_mhz = new->uncore_mhz; 3681 old->gfx_mhz = new->gfx_mhz; 3682 old->gfx_act_mhz = new->gfx_act_mhz; 3683 3684 /* flag an error when mc6 counter resets/wraps */ 3685 if (old->sam_mc6_ms > new->sam_mc6_ms) 3686 old->sam_mc6_ms = -1; 3687 else 3688 old->sam_mc6_ms = new->sam_mc6_ms - old->sam_mc6_ms; 3689 3690 old->sam_mhz = new->sam_mhz; 3691 old->sam_act_mhz = new->sam_act_mhz; 3692 3693 old->energy_pkg.raw_value = new->energy_pkg.raw_value - old->energy_pkg.raw_value; 3694 old->energy_cores.raw_value = new->energy_cores.raw_value - old->energy_cores.raw_value; 3695 old->energy_gfx.raw_value = new->energy_gfx.raw_value - old->energy_gfx.raw_value; 3696 old->energy_dram.raw_value = new->energy_dram.raw_value - old->energy_dram.raw_value; 3697 old->rapl_pkg_perf_status.raw_value = new->rapl_pkg_perf_status.raw_value - old->rapl_pkg_perf_status.raw_value; 3698 old->rapl_dram_perf_status.raw_value = new->rapl_dram_perf_status.raw_value - old->rapl_dram_perf_status.raw_value; 3699 3700 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 3701 if (mp->format == FORMAT_RAW) 3702 old->counter[i] = new->counter[i]; 3703 else if (mp->format == FORMAT_AVERAGE) 3704 old->counter[i] = new->counter[i]; 3705 else 3706 old->counter[i] = new->counter[i] - old->counter[i]; 3707 } 3708 3709 for (i = 0, pp = sys.perf_pp; pp; i++, pp = pp->next) { 3710 if (pp->format == FORMAT_RAW) 3711 old->perf_counter[i] = new->perf_counter[i]; 3712 else if (pp->format == FORMAT_AVERAGE) 3713 old->perf_counter[i] = new->perf_counter[i]; 3714 else 3715 old->perf_counter[i] = new->perf_counter[i] - old->perf_counter[i]; 3716 } 3717 3718 for (i = 0, ppmt = sys.pmt_pp; ppmt; i++, ppmt = ppmt->next) { 3719 if (ppmt->format == FORMAT_RAW) 3720 old->pmt_counter[i] = new->pmt_counter[i]; 3721 else 3722 old->pmt_counter[i] = new->pmt_counter[i] - old->pmt_counter[i]; 3723 } 3724 3725 return 0; 3726} 3727 3728void delta_core(struct core_data *new, struct core_data *old) 3729{ 3730 int i; 3731 struct msr_counter *mp; 3732 struct perf_counter_info *pp; 3733 struct pmt_counter *ppmt; 3734 3735 old->c3 = new->c3 - old->c3; 3736 old->c6 = new->c6 - old->c6; 3737 old->c7 = new->c7 - old->c7; 3738 old->core_temp_c = new->core_temp_c; 3739 old->core_throt_cnt = new->core_throt_cnt - old->core_throt_cnt; 3740 old->mc6_us = new->mc6_us - old->mc6_us; 3741 3742 DELTA_WRAP32(new->core_energy.raw_value, old->core_energy.raw_value); 3743 3744 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 3745 if (mp->format == FORMAT_RAW || mp->format == FORMAT_AVERAGE) 3746 old->counter[i] = new->counter[i]; 3747 else 3748 old->counter[i] = new->counter[i] - old->counter[i]; 3749 } 3750 3751 for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) { 3752 if (pp->format == FORMAT_RAW) 3753 old->perf_counter[i] = new->perf_counter[i]; 3754 else 3755 old->perf_counter[i] = new->perf_counter[i] - old->perf_counter[i]; 3756 } 3757 3758 for (i = 0, ppmt = sys.pmt_cp; ppmt; i++, ppmt = ppmt->next) { 3759 if (ppmt->format == FORMAT_RAW) 3760 old->pmt_counter[i] = new->pmt_counter[i]; 3761 else 3762 old->pmt_counter[i] = new->pmt_counter[i] - old->pmt_counter[i]; 3763 } 3764} 3765 3766int soft_c1_residency_display(int bic) 3767{ 3768 if (!DO_BIC(BIC_CPU_c1) || platform->has_msr_core_c1_res) 3769 return 0; 3770 3771 return DO_BIC_READ(bic); 3772} 3773 3774/* 3775 * old = new - old 3776 */ 3777int delta_thread(struct thread_data *new, struct thread_data *old, struct core_data *core_delta) 3778{ 3779 int i; 3780 struct msr_counter *mp; 3781 struct perf_counter_info *pp; 3782 struct pmt_counter *ppmt; 3783 3784 /* we run cpuid just the 1st time, copy the results */ 3785 if (DO_BIC(BIC_APIC)) 3786 new->apic_id = old->apic_id; 3787 if (DO_BIC(BIC_X2APIC)) 3788 new->x2apic_id = old->x2apic_id; 3789 3790 /* 3791 * the timestamps from start of measurement interval are in "old" 3792 * the timestamp from end of measurement interval are in "new" 3793 * over-write old w/ new so we can print end of interval values 3794 */ 3795 3796 timersub(&new->tv_begin, &old->tv_begin, &old->tv_delta); 3797 old->tv_begin = new->tv_begin; 3798 old->tv_end = new->tv_end; 3799 3800 old->tsc = new->tsc - old->tsc; 3801 3802 /* check for TSC < 1 Mcycles over interval */ 3803 if (old->tsc < (1000 * 1000)) 3804 errx(-3, "Insanely slow TSC rate, TSC stops in idle?\n" 3805 "You can disable all c-states by booting with \"idle=poll\"\n" "or just the deep ones with \"processor.max_cstate=1\""); 3806 3807 old->c1 = new->c1 - old->c1; 3808 3809 if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) || DO_BIC(BIC_IPC) 3810 || soft_c1_residency_display(BIC_Avg_MHz)) { 3811 if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) { 3812 old->aperf = new->aperf - old->aperf; 3813 old->mperf = new->mperf - old->mperf; 3814 } else { 3815 return -1; 3816 } 3817 } 3818 3819 if (platform->has_msr_core_c1_res) { 3820 /* 3821 * Some models have a dedicated C1 residency MSR, 3822 * which should be more accurate than the derivation below. 3823 */ 3824 } else { 3825 /* 3826 * As counter collection is not atomic, 3827 * it is possible for mperf's non-halted cycles + idle states 3828 * to exceed TSC's all cycles: show c1 = 0% in that case. 3829 */ 3830 if ((old->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > (old->tsc * tsc_tweak)) 3831 old->c1 = 0; 3832 else { 3833 /* normal case, derive c1 */ 3834 old->c1 = (old->tsc * tsc_tweak) - old->mperf - core_delta->c3 - core_delta->c6 - core_delta->c7; 3835 } 3836 } 3837 3838 if (old->mperf == 0) { 3839 if (debug > 1) 3840 fprintf(outf, "cpu%d MPERF 0!\n", old->cpu_id); 3841 old->mperf = 1; /* divide by 0 protection */ 3842 } 3843 3844 if (DO_BIC(BIC_IPC)) 3845 old->instr_count = new->instr_count - old->instr_count; 3846 3847 if (DO_BIC(BIC_IRQ)) 3848 old->irq_count = new->irq_count - old->irq_count; 3849 3850 if (DO_BIC(BIC_NMI)) 3851 old->nmi_count = new->nmi_count - old->nmi_count; 3852 3853 if (DO_BIC(BIC_SMI)) 3854 old->smi_count = new->smi_count - old->smi_count; 3855 3856 if (DO_BIC(BIC_LLC_RPS)) 3857 old->llc.references = new->llc.references - old->llc.references; 3858 3859 if (DO_BIC(BIC_LLC_HIT)) 3860 old->llc.misses = new->llc.misses - old->llc.misses; 3861 3862 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 3863 if (mp->format == FORMAT_RAW || mp->format == FORMAT_AVERAGE) 3864 old->counter[i] = new->counter[i]; 3865 else 3866 old->counter[i] = new->counter[i] - old->counter[i]; 3867 } 3868 3869 for (i = 0, pp = sys.perf_tp; pp; i++, pp = pp->next) { 3870 if (pp->format == FORMAT_RAW) 3871 old->perf_counter[i] = new->perf_counter[i]; 3872 else 3873 old->perf_counter[i] = new->perf_counter[i] - old->perf_counter[i]; 3874 } 3875 3876 for (i = 0, ppmt = sys.pmt_tp; ppmt; i++, ppmt = ppmt->next) { 3877 if (ppmt->format == FORMAT_RAW) 3878 old->pmt_counter[i] = new->pmt_counter[i]; 3879 else 3880 old->pmt_counter[i] = new->pmt_counter[i] - old->pmt_counter[i]; 3881 } 3882 3883 return 0; 3884} 3885 3886int delta_cpu(struct thread_data *t, struct core_data *c, struct pkg_data *p, struct thread_data *t2, struct core_data *c2, struct pkg_data *p2) 3887{ 3888 int retval = 0; 3889 3890 /* calculate core delta only for 1st thread in core */ 3891 if (is_cpu_first_thread_in_core(t, c)) 3892 delta_core(c, c2); 3893 3894 /* always calculate thread delta */ 3895 retval = delta_thread(t, t2, c2); /* c2 is core delta */ 3896 3897 /* calculate package delta only for 1st core in package */ 3898 if (is_cpu_first_core_in_package(t, p)) 3899 retval |= delta_package(p, p2); 3900 3901 return retval; 3902} 3903 3904void delta_platform(struct platform_counters *new, struct platform_counters *old) 3905{ 3906 old->energy_psys.raw_value = new->energy_psys.raw_value - old->energy_psys.raw_value; 3907} 3908 3909void rapl_counter_clear(struct rapl_counter *c) 3910{ 3911 c->raw_value = 0; 3912 c->scale = 0.0; 3913 c->unit = RAPL_UNIT_INVALID; 3914} 3915 3916void clear_counters(PER_THREAD_PARAMS) 3917{ 3918 int i; 3919 struct msr_counter *mp; 3920 3921 t->tv_begin.tv_sec = 0; 3922 t->tv_begin.tv_usec = 0; 3923 t->tv_end.tv_sec = 0; 3924 t->tv_end.tv_usec = 0; 3925 t->tv_delta.tv_sec = 0; 3926 t->tv_delta.tv_usec = 0; 3927 3928 t->tsc = 0; 3929 t->aperf = 0; 3930 t->mperf = 0; 3931 t->c1 = 0; 3932 3933 t->instr_count = 0; 3934 3935 t->irq_count = 0; 3936 t->nmi_count = 0; 3937 t->smi_count = 0; 3938 3939 t->llc.references = 0; 3940 t->llc.misses = 0; 3941 3942 c->c3 = 0; 3943 c->c6 = 0; 3944 c->c7 = 0; 3945 c->mc6_us = 0; 3946 c->core_temp_c = 0; 3947 rapl_counter_clear(&c->core_energy); 3948 c->core_throt_cnt = 0; 3949 3950 t->llc.references = 0; 3951 t->llc.misses = 0; 3952 3953 p->pkg_wtd_core_c0 = 0; 3954 p->pkg_any_core_c0 = 0; 3955 p->pkg_any_gfxe_c0 = 0; 3956 p->pkg_both_core_gfxe_c0 = 0; 3957 3958 p->pc2 = 0; 3959 if (DO_BIC(BIC_Pkgpc3)) 3960 p->pc3 = 0; 3961 if (DO_BIC(BIC_Pkgpc6)) 3962 p->pc6 = 0; 3963 if (DO_BIC(BIC_Pkgpc7)) 3964 p->pc7 = 0; 3965 p->pc8 = 0; 3966 p->pc9 = 0; 3967 p->pc10 = 0; 3968 p->die_c6 = 0; 3969 p->cpu_lpi = 0; 3970 p->sys_lpi = 0; 3971 3972 rapl_counter_clear(&p->energy_pkg); 3973 rapl_counter_clear(&p->energy_dram); 3974 rapl_counter_clear(&p->energy_cores); 3975 rapl_counter_clear(&p->energy_gfx); 3976 rapl_counter_clear(&p->rapl_pkg_perf_status); 3977 rapl_counter_clear(&p->rapl_dram_perf_status); 3978 p->pkg_temp_c = 0; 3979 3980 p->gfx_rc6_ms = 0; 3981 p->uncore_mhz = 0; 3982 p->gfx_mhz = 0; 3983 p->gfx_act_mhz = 0; 3984 p->sam_mc6_ms = 0; 3985 p->sam_mhz = 0; 3986 p->sam_act_mhz = 0; 3987 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) 3988 t->counter[i] = 0; 3989 3990 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) 3991 c->counter[i] = 0; 3992 3993 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) 3994 p->counter[i] = 0; 3995 3996 memset(&t->perf_counter[0], 0, sizeof(t->perf_counter)); 3997 memset(&c->perf_counter[0], 0, sizeof(c->perf_counter)); 3998 memset(&p->perf_counter[0], 0, sizeof(p->perf_counter)); 3999 4000 memset(&t->pmt_counter[0], 0, ARRAY_SIZE(t->pmt_counter)); 4001 memset(&c->pmt_counter[0], 0, ARRAY_SIZE(c->pmt_counter)); 4002 memset(&p->pmt_counter[0], 0, ARRAY_SIZE(p->pmt_counter)); 4003} 4004 4005void rapl_counter_accumulate(struct rapl_counter *dst, const struct rapl_counter *src) 4006{ 4007 /* Copy unit and scale from src if dst is not initialized */ 4008 if (dst->unit == RAPL_UNIT_INVALID) { 4009 dst->unit = src->unit; 4010 dst->scale = src->scale; 4011 } 4012 4013 assert(dst->unit == src->unit); 4014 assert(dst->scale == src->scale); 4015 4016 dst->raw_value += src->raw_value; 4017} 4018 4019int sum_counters(PER_THREAD_PARAMS) 4020{ 4021 int i; 4022 struct msr_counter *mp; 4023 struct perf_counter_info *pp; 4024 struct pmt_counter *ppmt; 4025 4026 /* copy un-changing apic_id's */ 4027 if (DO_BIC(BIC_APIC)) 4028 average.threads.apic_id = t->apic_id; 4029 if (DO_BIC(BIC_X2APIC)) 4030 average.threads.x2apic_id = t->x2apic_id; 4031 4032 /* remember first tv_begin */ 4033 if (average.threads.tv_begin.tv_sec == 0) 4034 average.threads.tv_begin = procsysfs_tv_begin; 4035 4036 /* remember last tv_end */ 4037 average.threads.tv_end = t->tv_end; 4038 4039 average.threads.tsc += t->tsc; 4040 average.threads.aperf += t->aperf; 4041 average.threads.mperf += t->mperf; 4042 average.threads.c1 += t->c1; 4043 4044 average.threads.instr_count += t->instr_count; 4045 4046 average.threads.irq_count += t->irq_count; 4047 average.threads.nmi_count += t->nmi_count; 4048 average.threads.smi_count += t->smi_count; 4049 4050 average.threads.llc.references += t->llc.references; 4051 average.threads.llc.misses += t->llc.misses; 4052 4053 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 4054 if (mp->format == FORMAT_RAW) 4055 continue; 4056 average.threads.counter[i] += t->counter[i]; 4057 } 4058 4059 for (i = 0, pp = sys.perf_tp; pp; i++, pp = pp->next) { 4060 if (pp->format == FORMAT_RAW) 4061 continue; 4062 average.threads.perf_counter[i] += t->perf_counter[i]; 4063 } 4064 4065 for (i = 0, ppmt = sys.pmt_tp; ppmt; i++, ppmt = ppmt->next) { 4066 average.threads.pmt_counter[i] += t->pmt_counter[i]; 4067 } 4068 4069 /* sum per-core values only for 1st thread in core */ 4070 if (!is_cpu_first_thread_in_core(t, c)) 4071 return 0; 4072 4073 average.cores.c3 += c->c3; 4074 average.cores.c6 += c->c6; 4075 average.cores.c7 += c->c7; 4076 average.cores.mc6_us += c->mc6_us; 4077 4078 average.cores.core_temp_c = MAX(average.cores.core_temp_c, c->core_temp_c); 4079 average.cores.core_throt_cnt = MAX(average.cores.core_throt_cnt, c->core_throt_cnt); 4080 4081 rapl_counter_accumulate(&average.cores.core_energy, &c->core_energy); 4082 4083 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 4084 if (mp->format == FORMAT_RAW) 4085 continue; 4086 average.cores.counter[i] += c->counter[i]; 4087 } 4088 4089 for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) { 4090 if (pp->format == FORMAT_RAW) 4091 continue; 4092 average.cores.perf_counter[i] += c->perf_counter[i]; 4093 } 4094 4095 for (i = 0, ppmt = sys.pmt_cp; ppmt; i++, ppmt = ppmt->next) { 4096 average.cores.pmt_counter[i] += c->pmt_counter[i]; 4097 } 4098 4099 /* sum per-pkg values only for 1st core in pkg */ 4100 if (!is_cpu_first_core_in_package(t, p)) 4101 return 0; 4102 4103 if (DO_BIC(BIC_Totl_c0)) 4104 average.packages.pkg_wtd_core_c0 += p->pkg_wtd_core_c0; 4105 if (DO_BIC(BIC_Any_c0)) 4106 average.packages.pkg_any_core_c0 += p->pkg_any_core_c0; 4107 if (DO_BIC(BIC_GFX_c0)) 4108 average.packages.pkg_any_gfxe_c0 += p->pkg_any_gfxe_c0; 4109 if (DO_BIC(BIC_CPUGFX)) 4110 average.packages.pkg_both_core_gfxe_c0 += p->pkg_both_core_gfxe_c0; 4111 4112 average.packages.pc2 += p->pc2; 4113 if (DO_BIC(BIC_Pkgpc3)) 4114 average.packages.pc3 += p->pc3; 4115 if (DO_BIC(BIC_Pkgpc6)) 4116 average.packages.pc6 += p->pc6; 4117 if (DO_BIC(BIC_Pkgpc7)) 4118 average.packages.pc7 += p->pc7; 4119 average.packages.pc8 += p->pc8; 4120 average.packages.pc9 += p->pc9; 4121 average.packages.pc10 += p->pc10; 4122 average.packages.die_c6 += p->die_c6; 4123 4124 average.packages.cpu_lpi = p->cpu_lpi; 4125 average.packages.sys_lpi = p->sys_lpi; 4126 4127 rapl_counter_accumulate(&average.packages.energy_pkg, &p->energy_pkg); 4128 rapl_counter_accumulate(&average.packages.energy_dram, &p->energy_dram); 4129 rapl_counter_accumulate(&average.packages.energy_cores, &p->energy_cores); 4130 rapl_counter_accumulate(&average.packages.energy_gfx, &p->energy_gfx); 4131 4132 average.packages.gfx_rc6_ms = p->gfx_rc6_ms; 4133 average.packages.uncore_mhz = p->uncore_mhz; 4134 average.packages.gfx_mhz = p->gfx_mhz; 4135 average.packages.gfx_act_mhz = p->gfx_act_mhz; 4136 average.packages.sam_mc6_ms = p->sam_mc6_ms; 4137 average.packages.sam_mhz = p->sam_mhz; 4138 average.packages.sam_act_mhz = p->sam_act_mhz; 4139 4140 average.packages.pkg_temp_c = MAX(average.packages.pkg_temp_c, p->pkg_temp_c); 4141 4142 rapl_counter_accumulate(&average.packages.rapl_pkg_perf_status, &p->rapl_pkg_perf_status); 4143 rapl_counter_accumulate(&average.packages.rapl_dram_perf_status, &p->rapl_dram_perf_status); 4144 4145 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 4146 if ((mp->format == FORMAT_RAW) && (topo.num_packages == 0)) 4147 average.packages.counter[i] = p->counter[i]; 4148 else 4149 average.packages.counter[i] += p->counter[i]; 4150 } 4151 4152 for (i = 0, pp = sys.perf_pp; pp; i++, pp = pp->next) { 4153 if ((pp->format == FORMAT_RAW) && (topo.num_packages == 0)) 4154 average.packages.perf_counter[i] = p->perf_counter[i]; 4155 else 4156 average.packages.perf_counter[i] += p->perf_counter[i]; 4157 } 4158 4159 for (i = 0, ppmt = sys.pmt_pp; ppmt; i++, ppmt = ppmt->next) { 4160 average.packages.pmt_counter[i] += p->pmt_counter[i]; 4161 } 4162 4163 return 0; 4164} 4165 4166/* 4167 * sum the counters for all cpus in the system 4168 * compute the weighted average 4169 */ 4170void compute_average(PER_THREAD_PARAMS) 4171{ 4172 int i; 4173 struct msr_counter *mp; 4174 struct perf_counter_info *pp; 4175 struct pmt_counter *ppmt; 4176 4177 clear_counters(&average.threads, &average.cores, &average.packages); 4178 4179 for_all_cpus(sum_counters, t, c, p); 4180 4181 /* Use the global time delta for the average. */ 4182 average.threads.tv_delta = tv_delta; 4183 4184 average.threads.tsc /= topo.allowed_cpus; 4185 average.threads.aperf /= topo.allowed_cpus; 4186 average.threads.mperf /= topo.allowed_cpus; 4187 average.threads.instr_count /= topo.allowed_cpus; 4188 average.threads.c1 /= topo.allowed_cpus; 4189 4190 if (average.threads.irq_count > 9999999) 4191 sums_need_wide_columns = 1; 4192 if (average.threads.nmi_count > 9999999) 4193 sums_need_wide_columns = 1; 4194 4195 average.cores.c3 /= topo.allowed_cores; 4196 average.cores.c6 /= topo.allowed_cores; 4197 average.cores.c7 /= topo.allowed_cores; 4198 average.cores.mc6_us /= topo.allowed_cores; 4199 4200 if (DO_BIC(BIC_Totl_c0)) 4201 average.packages.pkg_wtd_core_c0 /= topo.allowed_packages; 4202 if (DO_BIC(BIC_Any_c0)) 4203 average.packages.pkg_any_core_c0 /= topo.allowed_packages; 4204 if (DO_BIC(BIC_GFX_c0)) 4205 average.packages.pkg_any_gfxe_c0 /= topo.allowed_packages; 4206 if (DO_BIC(BIC_CPUGFX)) 4207 average.packages.pkg_both_core_gfxe_c0 /= topo.allowed_packages; 4208 4209 average.packages.pc2 /= topo.allowed_packages; 4210 if (DO_BIC(BIC_Pkgpc3)) 4211 average.packages.pc3 /= topo.allowed_packages; 4212 if (DO_BIC(BIC_Pkgpc6)) 4213 average.packages.pc6 /= topo.allowed_packages; 4214 if (DO_BIC(BIC_Pkgpc7)) 4215 average.packages.pc7 /= topo.allowed_packages; 4216 4217 average.packages.pc8 /= topo.allowed_packages; 4218 average.packages.pc9 /= topo.allowed_packages; 4219 average.packages.pc10 /= topo.allowed_packages; 4220 average.packages.die_c6 /= topo.allowed_packages; 4221 4222 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 4223 if (mp->format == FORMAT_RAW) 4224 continue; 4225 if (mp->type == COUNTER_ITEMS) { 4226 if (average.threads.counter[i] > 9999999) 4227 sums_need_wide_columns = 1; 4228 continue; 4229 } 4230 average.threads.counter[i] /= topo.allowed_cpus; 4231 } 4232 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 4233 if (mp->format == FORMAT_RAW) 4234 continue; 4235 if (mp->type == COUNTER_ITEMS) { 4236 if (average.cores.counter[i] > 9999999) 4237 sums_need_wide_columns = 1; 4238 } 4239 average.cores.counter[i] /= topo.allowed_cores; 4240 } 4241 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 4242 if (mp->format == FORMAT_RAW) 4243 continue; 4244 if (mp->type == COUNTER_ITEMS) { 4245 if (average.packages.counter[i] > 9999999) 4246 sums_need_wide_columns = 1; 4247 } 4248 average.packages.counter[i] /= topo.allowed_packages; 4249 } 4250 4251 for (i = 0, pp = sys.perf_tp; pp; i++, pp = pp->next) { 4252 if (pp->format == FORMAT_RAW) 4253 continue; 4254 if (pp->type == COUNTER_ITEMS) { 4255 if (average.threads.perf_counter[i] > 9999999) 4256 sums_need_wide_columns = 1; 4257 continue; 4258 } 4259 average.threads.perf_counter[i] /= topo.allowed_cpus; 4260 } 4261 for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) { 4262 if (pp->format == FORMAT_RAW) 4263 continue; 4264 if (pp->type == COUNTER_ITEMS) { 4265 if (average.cores.perf_counter[i] > 9999999) 4266 sums_need_wide_columns = 1; 4267 } 4268 average.cores.perf_counter[i] /= topo.allowed_cores; 4269 } 4270 for (i = 0, pp = sys.perf_pp; pp; i++, pp = pp->next) { 4271 if (pp->format == FORMAT_RAW) 4272 continue; 4273 if (pp->type == COUNTER_ITEMS) { 4274 if (average.packages.perf_counter[i] > 9999999) 4275 sums_need_wide_columns = 1; 4276 } 4277 average.packages.perf_counter[i] /= topo.allowed_packages; 4278 } 4279 4280 for (i = 0, ppmt = sys.pmt_tp; ppmt; i++, ppmt = ppmt->next) { 4281 average.threads.pmt_counter[i] /= topo.allowed_cpus; 4282 } 4283 for (i = 0, ppmt = sys.pmt_cp; ppmt; i++, ppmt = ppmt->next) { 4284 average.cores.pmt_counter[i] /= topo.allowed_cores; 4285 } 4286 for (i = 0, ppmt = sys.pmt_pp; ppmt; i++, ppmt = ppmt->next) { 4287 average.packages.pmt_counter[i] /= topo.allowed_packages; 4288 } 4289} 4290 4291static unsigned long long rdtsc(void) 4292{ 4293 unsigned int low, high; 4294 4295 asm volatile ("rdtsc":"=a" (low), "=d"(high)); 4296 4297 return low | ((unsigned long long)high) << 32; 4298} 4299 4300/* 4301 * Open a file, and exit on failure 4302 */ 4303FILE *fopen_or_die(const char *path, const char *mode) 4304{ 4305 FILE *filep = fopen(path, mode); 4306 4307 if (!filep) 4308 err(1, "%s: open failed", path); 4309 return filep; 4310} 4311 4312/* 4313 * snapshot_sysfs_counter() 4314 * 4315 * return snapshot of given counter 4316 */ 4317unsigned long long snapshot_sysfs_counter(char *path) 4318{ 4319 FILE *fp; 4320 int retval; 4321 unsigned long long counter; 4322 4323 fp = fopen_or_die(path, "r"); 4324 4325 retval = fscanf(fp, "%lld", &counter); 4326 if (retval != 1) 4327 err(1, "snapshot_sysfs_counter(%s)", path); 4328 4329 fclose(fp); 4330 4331 return counter; 4332} 4333 4334int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp, char *counter_path) 4335{ 4336 if (mp->msr_num != 0) { 4337 assert(!no_msr); 4338 if (get_msr(cpu, mp->msr_num, counterp)) 4339 return -1; 4340 } else { 4341 char path[128 + PATH_BYTES]; 4342 4343 if (mp->flags & SYSFS_PERCPU) { 4344 sprintf(path, "/sys/devices/system/cpu/cpu%d/%s", cpu, mp->sp->path); 4345 4346 *counterp = snapshot_sysfs_counter(path); 4347 } else { 4348 *counterp = snapshot_sysfs_counter(counter_path); 4349 } 4350 } 4351 4352 return 0; 4353} 4354 4355unsigned long long get_legacy_uncore_mhz(int package) 4356{ 4357 char path[128]; 4358 int die; 4359 static int warn_once; 4360 4361 /* 4362 * for this package, use the first die_id that exists 4363 */ 4364 for (die = 0; die <= topo.max_die_id; ++die) { 4365 4366 sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/current_freq_khz", package, die); 4367 4368 if (access(path, R_OK) == 0) 4369 return (snapshot_sysfs_counter(path) / 1000); 4370 } 4371 if (!warn_once) { 4372 warnx("BUG: %s: No %s", __func__, path); 4373 warn_once = 1; 4374 } 4375 4376 return 0; 4377} 4378 4379int get_epb(int cpu) 4380{ 4381 char path[128 + PATH_BYTES]; 4382 unsigned long long msr; 4383 int ret, epb = -1; 4384 FILE *fp; 4385 4386 sprintf(path, "/sys/devices/system/cpu/cpu%d/power/energy_perf_bias", cpu); 4387 4388 fp = fopen(path, "r"); 4389 if (!fp) 4390 goto msr_fallback; 4391 4392 ret = fscanf(fp, "%d", &epb); 4393 if (ret != 1) 4394 err(1, "%s(%s)", __func__, path); 4395 4396 fclose(fp); 4397 4398 return epb; 4399 4400msr_fallback: 4401 if (no_msr) 4402 return -1; 4403 4404 get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr); 4405 4406 return msr & 0xf; 4407} 4408 4409void get_apic_id(struct thread_data *t) 4410{ 4411 unsigned int eax, ebx, ecx, edx; 4412 4413 if (DO_BIC(BIC_APIC)) { 4414 eax = ebx = ecx = edx = 0; 4415 __cpuid(1, eax, ebx, ecx, edx); 4416 4417 t->apic_id = (ebx >> 24) & 0xff; 4418 } 4419 4420 if (!DO_BIC(BIC_X2APIC)) 4421 return; 4422 4423 if (authentic_amd || hygon_genuine) { 4424 unsigned int topology_extensions; 4425 4426 if (max_extended_level < 0x8000001e) 4427 return; 4428 4429 eax = ebx = ecx = edx = 0; 4430 __cpuid(0x80000001, eax, ebx, ecx, edx); 4431 topology_extensions = ecx & (1 << 22); 4432 4433 if (topology_extensions == 0) 4434 return; 4435 4436 eax = ebx = ecx = edx = 0; 4437 __cpuid(0x8000001e, eax, ebx, ecx, edx); 4438 4439 t->x2apic_id = eax; 4440 return; 4441 } 4442 4443 if (!genuine_intel) 4444 return; 4445 4446 if (max_level < 0xb) 4447 return; 4448 4449 ecx = 0; 4450 __cpuid(0xb, eax, ebx, ecx, edx); 4451 t->x2apic_id = edx; 4452 4453 if (debug && (t->apic_id != (t->x2apic_id & 0xff))) 4454 fprintf(outf, "cpu%d: BIOS BUG: apic 0x%x x2apic 0x%x\n", t->cpu_id, t->apic_id, t->x2apic_id); 4455} 4456 4457int get_core_throt_cnt(int cpu, unsigned long long *cnt) 4458{ 4459 char path[128 + PATH_BYTES]; 4460 unsigned long long tmp; 4461 FILE *fp; 4462 int ret; 4463 4464 sprintf(path, "/sys/devices/system/cpu/cpu%d/thermal_throttle/core_throttle_count", cpu); 4465 fp = fopen(path, "r"); 4466 if (!fp) 4467 return -1; 4468 ret = fscanf(fp, "%lld", &tmp); 4469 fclose(fp); 4470 if (ret != 1) 4471 return -1; 4472 *cnt = tmp; 4473 4474 return 0; 4475} 4476 4477static int read_perf_counter_info(const char *const path, const char *const parse_format, void *value_ptr) 4478{ 4479 int fdmt; 4480 int bytes_read; 4481 char buf[64]; 4482 int ret = -1; 4483 4484 fdmt = open(path, O_RDONLY, 0); 4485 if (fdmt == -1) { 4486 if (debug) 4487 fprintf(stderr, "Failed to parse perf counter info %s\n", path); 4488 ret = -1; 4489 goto cleanup_and_exit; 4490 } 4491 4492 bytes_read = read(fdmt, buf, sizeof(buf) - 1); 4493 if (bytes_read <= 0 || bytes_read >= (int)sizeof(buf)) { 4494 if (debug) 4495 fprintf(stderr, "Failed to parse perf counter info %s\n", path); 4496 ret = -1; 4497 goto cleanup_and_exit; 4498 } 4499 4500 buf[bytes_read] = '\0'; 4501 4502 if (sscanf(buf, parse_format, value_ptr) != 1) { 4503 if (debug) 4504 fprintf(stderr, "Failed to parse perf counter info %s\n", path); 4505 ret = -1; 4506 goto cleanup_and_exit; 4507 } 4508 4509 ret = 0; 4510 4511cleanup_and_exit: 4512 close(fdmt); 4513 return ret; 4514} 4515 4516static unsigned int read_perf_counter_info_n(const char *const path, const char *const parse_format) 4517{ 4518 unsigned int v; 4519 int status; 4520 4521 status = read_perf_counter_info(path, parse_format, &v); 4522 if (status) 4523 v = -1; 4524 4525 return v; 4526} 4527 4528static unsigned int read_perf_type(const char *subsys) 4529{ 4530 const char *const path_format = "/sys/bus/event_source/devices/%s/type"; 4531 const char *const format = "%u"; 4532 char path[128]; 4533 4534 snprintf(path, sizeof(path), path_format, subsys); 4535 4536 return read_perf_counter_info_n(path, format); 4537} 4538 4539static unsigned int read_perf_config(const char *subsys, const char *event_name) 4540{ 4541 const char *const path_format = "/sys/bus/event_source/devices/%s/events/%s"; 4542 FILE *fconfig = NULL; 4543 char path[128]; 4544 char config_str[64]; 4545 unsigned int config; 4546 unsigned int umask; 4547 bool has_config = false; 4548 bool has_umask = false; 4549 unsigned int ret = -1; 4550 4551 snprintf(path, sizeof(path), path_format, subsys, event_name); 4552 4553 fconfig = fopen(path, "r"); 4554 if (!fconfig) 4555 return -1; 4556 4557 if (fgets(config_str, ARRAY_SIZE(config_str), fconfig) != config_str) 4558 goto cleanup_and_exit; 4559 4560 for (char *pconfig_str = &config_str[0]; pconfig_str;) { 4561 if (sscanf(pconfig_str, "event=%x", &config) == 1) { 4562 has_config = true; 4563 goto next; 4564 } 4565 4566 if (sscanf(pconfig_str, "umask=%x", &umask) == 1) { 4567 has_umask = true; 4568 goto next; 4569 } 4570 4571next: 4572 pconfig_str = strchr(pconfig_str, ','); 4573 if (pconfig_str) { 4574 *pconfig_str = '\0'; 4575 ++pconfig_str; 4576 } 4577 } 4578 4579 if (!has_umask) 4580 umask = 0; 4581 4582 if (has_config) 4583 ret = (umask << 8) | config; 4584 4585cleanup_and_exit: 4586 fclose(fconfig); 4587 return ret; 4588} 4589 4590static unsigned int read_perf_rapl_unit(const char *subsys, const char *event_name) 4591{ 4592 const char *const path_format = "/sys/bus/event_source/devices/%s/events/%s.unit"; 4593 const char *const format = "%s"; 4594 char path[128]; 4595 char unit_buffer[16]; 4596 4597 snprintf(path, sizeof(path), path_format, subsys, event_name); 4598 4599 read_perf_counter_info(path, format, &unit_buffer); 4600 if (strcmp("Joules", unit_buffer) == 0) 4601 return RAPL_UNIT_JOULES; 4602 4603 return RAPL_UNIT_INVALID; 4604} 4605 4606static double read_perf_scale(const char *subsys, const char *event_name) 4607{ 4608 const char *const path_format = "/sys/bus/event_source/devices/%s/events/%s.scale"; 4609 const char *const format = "%lf"; 4610 char path[128]; 4611 double scale; 4612 4613 snprintf(path, sizeof(path), path_format, subsys, event_name); 4614 4615 if (read_perf_counter_info(path, format, &scale)) 4616 return 0.0; 4617 4618 return scale; 4619} 4620 4621size_t rapl_counter_info_count_perf(const struct rapl_counter_info_t *rci) 4622{ 4623 size_t ret = 0; 4624 4625 for (int i = 0; i < NUM_RAPL_COUNTERS; ++i) 4626 if (rci->source[i] == COUNTER_SOURCE_PERF) 4627 ++ret; 4628 4629 return ret; 4630} 4631 4632static size_t cstate_counter_info_count_perf(const struct cstate_counter_info_t *cci) 4633{ 4634 size_t ret = 0; 4635 4636 for (int i = 0; i < NUM_CSTATE_COUNTERS; ++i) 4637 if (cci->source[i] == COUNTER_SOURCE_PERF) 4638 ++ret; 4639 4640 return ret; 4641} 4642 4643void write_rapl_counter(struct rapl_counter *rc, struct rapl_counter_info_t *rci, unsigned int idx) 4644{ 4645 if (rci->source[idx] == COUNTER_SOURCE_NONE) 4646 return; 4647 4648 rc->raw_value = rci->data[idx]; 4649 rc->unit = rci->unit[idx]; 4650 rc->scale = rci->scale[idx]; 4651} 4652 4653int get_rapl_counters(int cpu, unsigned int domain, struct core_data *c, struct pkg_data *p) 4654{ 4655 struct platform_counters *pplat_cnt = p == package_odd ? &platform_counters_odd : &platform_counters_even; 4656 unsigned long long perf_data[NUM_RAPL_COUNTERS + 1]; 4657 struct rapl_counter_info_t *rci; 4658 4659 if (debug >= 2) 4660 fprintf(stderr, "%s: cpu%d domain%d\n", __func__, cpu, domain); 4661 4662 assert(rapl_counter_info_perdomain); 4663 assert(domain < rapl_counter_info_perdomain_size); 4664 4665 rci = &rapl_counter_info_perdomain[domain]; 4666 4667 /* 4668 * If we have any perf counters to read, read them all now, in bulk 4669 */ 4670 if (rci->fd_perf != -1) { 4671 size_t num_perf_counters = rapl_counter_info_count_perf(rci); 4672 const ssize_t expected_read_size = (num_perf_counters + 1) * sizeof(unsigned long long); 4673 const ssize_t actual_read_size = read(rci->fd_perf, &perf_data[0], sizeof(perf_data)); 4674 4675 if (actual_read_size != expected_read_size) 4676 err(-1, "%s: failed to read perf_data (%zu %zu)", __func__, expected_read_size, actual_read_size); 4677 } 4678 4679 for (unsigned int i = 0, pi = 1; i < NUM_RAPL_COUNTERS; ++i) { 4680 switch (rci->source[i]) { 4681 case COUNTER_SOURCE_NONE: 4682 rci->data[i] = 0; 4683 break; 4684 4685 case COUNTER_SOURCE_PERF: 4686 assert(pi < ARRAY_SIZE(perf_data)); 4687 assert(rci->fd_perf != -1); 4688 4689 if (debug >= 2) 4690 fprintf(stderr, "Reading rapl counter via perf at %u (%llu %e %lf)\n", 4691 i, perf_data[pi], rci->scale[i], perf_data[pi] * rci->scale[i]); 4692 4693 rci->data[i] = perf_data[pi]; 4694 4695 ++pi; 4696 break; 4697 4698 case COUNTER_SOURCE_MSR: 4699 if (debug >= 2) 4700 fprintf(stderr, "Reading rapl counter via msr at %u\n", i); 4701 4702 assert(!no_msr); 4703 if (rci->flags[i] & RAPL_COUNTER_FLAG_USE_MSR_SUM) { 4704 if (get_msr_sum(cpu, rci->msr[i], &rci->data[i])) 4705 return -13 - i; 4706 } else { 4707 if (get_msr(cpu, rci->msr[i], &rci->data[i])) 4708 return -13 - i; 4709 } 4710 4711 rci->data[i] &= rci->msr_mask[i]; 4712 if (rci->msr_shift[i] >= 0) 4713 rci->data[i] >>= abs(rci->msr_shift[i]); 4714 else 4715 rci->data[i] <<= abs(rci->msr_shift[i]); 4716 4717 break; 4718 } 4719 } 4720 4721 BUILD_BUG_ON(NUM_RAPL_COUNTERS != 8); 4722 write_rapl_counter(&p->energy_pkg, rci, RAPL_RCI_INDEX_ENERGY_PKG); 4723 write_rapl_counter(&p->energy_cores, rci, RAPL_RCI_INDEX_ENERGY_CORES); 4724 write_rapl_counter(&p->energy_dram, rci, RAPL_RCI_INDEX_DRAM); 4725 write_rapl_counter(&p->energy_gfx, rci, RAPL_RCI_INDEX_GFX); 4726 write_rapl_counter(&p->rapl_pkg_perf_status, rci, RAPL_RCI_INDEX_PKG_PERF_STATUS); 4727 write_rapl_counter(&p->rapl_dram_perf_status, rci, RAPL_RCI_INDEX_DRAM_PERF_STATUS); 4728 write_rapl_counter(&c->core_energy, rci, RAPL_RCI_INDEX_CORE_ENERGY); 4729 write_rapl_counter(&pplat_cnt->energy_psys, rci, RAPL_RCI_INDEX_ENERGY_PLATFORM); 4730 4731 return 0; 4732} 4733 4734char *find_sysfs_path_by_id(struct sysfs_path *sp, int id) 4735{ 4736 while (sp) { 4737 if (sp->id == id) 4738 return (sp->path); 4739 sp = sp->next; 4740 } 4741 if (debug) 4742 warnx("%s: id%d not found", __func__, id); 4743 return NULL; 4744} 4745 4746int get_cstate_counters(unsigned int cpu, PER_THREAD_PARAMS) 4747{ 4748 /* 4749 * Overcommit memory a little bit here, 4750 * but skip calculating exact sizes for the buffers. 4751 */ 4752 unsigned long long perf_data[NUM_CSTATE_COUNTERS]; 4753 unsigned long long perf_data_core[NUM_CSTATE_COUNTERS + 1]; 4754 unsigned long long perf_data_pkg[NUM_CSTATE_COUNTERS + 1]; 4755 4756 struct cstate_counter_info_t *cci; 4757 4758 if (debug >= 2) 4759 fprintf(stderr, "%s: cpu%d\n", __func__, cpu); 4760 4761 assert(ccstate_counter_info); 4762 assert(cpu <= ccstate_counter_info_size); 4763 4764 ZERO_ARRAY(perf_data); 4765 ZERO_ARRAY(perf_data_core); 4766 ZERO_ARRAY(perf_data_pkg); 4767 4768 cci = &ccstate_counter_info[cpu]; 4769 4770 /* 4771 * If we have any perf counters to read, read them all now, in bulk 4772 */ 4773 const size_t num_perf_counters = cstate_counter_info_count_perf(cci); 4774 ssize_t expected_read_size = num_perf_counters * sizeof(unsigned long long); 4775 ssize_t actual_read_size_core = 0, actual_read_size_pkg = 0; 4776 4777 if (cci->fd_perf_core != -1) { 4778 /* Each descriptor read begins with number of counters read. */ 4779 expected_read_size += sizeof(unsigned long long); 4780 4781 actual_read_size_core = read(cci->fd_perf_core, &perf_data_core[0], sizeof(perf_data_core)); 4782 4783 if (actual_read_size_core <= 0) 4784 err(-1, "%s: read perf %s: %ld", __func__, "core", actual_read_size_core); 4785 } 4786 4787 if (cci->fd_perf_pkg != -1) { 4788 /* Each descriptor read begins with number of counters read. */ 4789 expected_read_size += sizeof(unsigned long long); 4790 4791 actual_read_size_pkg = read(cci->fd_perf_pkg, &perf_data_pkg[0], sizeof(perf_data_pkg)); 4792 4793 if (actual_read_size_pkg <= 0) 4794 err(-1, "%s: read perf %s: %ld", __func__, "pkg", actual_read_size_pkg); 4795 } 4796 4797 const ssize_t actual_read_size_total = actual_read_size_core + actual_read_size_pkg; 4798 4799 if (actual_read_size_total != expected_read_size) 4800 err(-1, "%s: failed to read perf_data (%zu %zu)", __func__, expected_read_size, actual_read_size_total); 4801 4802 /* 4803 * Copy ccstate and pcstate data into unified buffer. 4804 * 4805 * Skip first element from core and pkg buffers. 4806 * Kernel puts there how many counters were read. 4807 */ 4808 const size_t num_core_counters = perf_data_core[0]; 4809 const size_t num_pkg_counters = perf_data_pkg[0]; 4810 4811 assert(num_perf_counters == num_core_counters + num_pkg_counters); 4812 4813 /* Copy ccstate perf data */ 4814 memcpy(&perf_data[0], &perf_data_core[1], num_core_counters * sizeof(unsigned long long)); 4815 4816 /* Copy pcstate perf data */ 4817 memcpy(&perf_data[num_core_counters], &perf_data_pkg[1], num_pkg_counters * sizeof(unsigned long long)); 4818 4819 for (unsigned int i = 0, pi = 0; i < NUM_CSTATE_COUNTERS; ++i) { 4820 switch (cci->source[i]) { 4821 case COUNTER_SOURCE_NONE: 4822 break; 4823 4824 case COUNTER_SOURCE_PERF: 4825 assert(pi < ARRAY_SIZE(perf_data)); 4826 assert(cci->fd_perf_core != -1 || cci->fd_perf_pkg != -1); 4827 4828 if (debug >= 2) 4829 fprintf(stderr, "cstate via %s %u: %llu\n", "perf", i, perf_data[pi]); 4830 4831 cci->data[i] = perf_data[pi]; 4832 4833 ++pi; 4834 break; 4835 4836 case COUNTER_SOURCE_MSR: 4837 assert(!no_msr); 4838 if (get_msr(cpu, cci->msr[i], &cci->data[i])) 4839 return -13 - i; 4840 4841 if (debug >= 2) 4842 fprintf(stderr, "cstate via %s0x%llx %u: %llu\n", "msr", cci->msr[i], i, cci->data[i]); 4843 4844 break; 4845 } 4846 } 4847 4848 /* 4849 * Helper to write the data only if the source of 4850 * the counter for the current cpu is not none. 4851 * 4852 * Otherwise we would overwrite core data with 0 (default value), 4853 * when invoked for the thread sibling. 4854 */ 4855#define PERF_COUNTER_WRITE_DATA(out_counter, index) do { \ 4856 if (cci->source[index] != COUNTER_SOURCE_NONE) \ 4857 out_counter = cci->data[index]; \ 4858} while (0) 4859 4860 BUILD_BUG_ON(NUM_CSTATE_COUNTERS != 11); 4861 4862 PERF_COUNTER_WRITE_DATA(t->c1, CCSTATE_RCI_INDEX_C1_RESIDENCY); 4863 PERF_COUNTER_WRITE_DATA(c->c3, CCSTATE_RCI_INDEX_C3_RESIDENCY); 4864 PERF_COUNTER_WRITE_DATA(c->c6, CCSTATE_RCI_INDEX_C6_RESIDENCY); 4865 PERF_COUNTER_WRITE_DATA(c->c7, CCSTATE_RCI_INDEX_C7_RESIDENCY); 4866 4867 PERF_COUNTER_WRITE_DATA(p->pc2, PCSTATE_RCI_INDEX_C2_RESIDENCY); 4868 PERF_COUNTER_WRITE_DATA(p->pc3, PCSTATE_RCI_INDEX_C3_RESIDENCY); 4869 PERF_COUNTER_WRITE_DATA(p->pc6, PCSTATE_RCI_INDEX_C6_RESIDENCY); 4870 PERF_COUNTER_WRITE_DATA(p->pc7, PCSTATE_RCI_INDEX_C7_RESIDENCY); 4871 PERF_COUNTER_WRITE_DATA(p->pc8, PCSTATE_RCI_INDEX_C8_RESIDENCY); 4872 PERF_COUNTER_WRITE_DATA(p->pc9, PCSTATE_RCI_INDEX_C9_RESIDENCY); 4873 PERF_COUNTER_WRITE_DATA(p->pc10, PCSTATE_RCI_INDEX_C10_RESIDENCY); 4874 4875#undef PERF_COUNTER_WRITE_DATA 4876 4877 return 0; 4878} 4879 4880size_t msr_counter_info_count_perf(const struct msr_counter_info_t *mci) 4881{ 4882 size_t ret = 0; 4883 4884 for (int i = 0; i < NUM_MSR_COUNTERS; ++i) 4885 if (mci->source[i] == COUNTER_SOURCE_PERF) 4886 ++ret; 4887 4888 return ret; 4889} 4890 4891int get_smi_aperf_mperf(unsigned int cpu, struct thread_data *t) 4892{ 4893 unsigned long long perf_data[NUM_MSR_COUNTERS + 1]; 4894 4895 struct msr_counter_info_t *mci; 4896 4897 if (debug >= 2) 4898 fprintf(stderr, "%s: cpu%d\n", __func__, cpu); 4899 4900 assert(msr_counter_info); 4901 assert(cpu <= msr_counter_info_size); 4902 4903 mci = &msr_counter_info[cpu]; 4904 4905 ZERO_ARRAY(perf_data); 4906 ZERO_ARRAY(mci->data); 4907 4908 if (mci->fd_perf != -1) { 4909 const size_t num_perf_counters = msr_counter_info_count_perf(mci); 4910 const ssize_t expected_read_size = (num_perf_counters + 1) * sizeof(unsigned long long); 4911 const ssize_t actual_read_size = read(mci->fd_perf, &perf_data[0], sizeof(perf_data)); 4912 4913 if (actual_read_size != expected_read_size) 4914 err(-1, "%s: failed to read perf_data (%zu %zu)", __func__, expected_read_size, actual_read_size); 4915 } 4916 4917 for (unsigned int i = 0, pi = 1; i < NUM_MSR_COUNTERS; ++i) { 4918 switch (mci->source[i]) { 4919 case COUNTER_SOURCE_NONE: 4920 break; 4921 4922 case COUNTER_SOURCE_PERF: 4923 assert(pi < ARRAY_SIZE(perf_data)); 4924 assert(mci->fd_perf != -1); 4925 4926 if (debug >= 2) 4927 fprintf(stderr, "Reading msr counter via perf at %u: %llu\n", i, perf_data[pi]); 4928 4929 mci->data[i] = perf_data[pi]; 4930 4931 ++pi; 4932 break; 4933 4934 case COUNTER_SOURCE_MSR: 4935 assert(!no_msr); 4936 4937 if (get_msr(cpu, mci->msr[i], &mci->data[i])) 4938 return -2 - i; 4939 4940 mci->data[i] &= mci->msr_mask[i]; 4941 4942 if (debug >= 2) 4943 fprintf(stderr, "Reading msr counter via msr at %u: %llu\n", i, mci->data[i]); 4944 4945 break; 4946 } 4947 } 4948 4949 BUILD_BUG_ON(NUM_MSR_COUNTERS != 3); 4950 t->aperf = mci->data[MSR_RCI_INDEX_APERF]; 4951 t->mperf = mci->data[MSR_RCI_INDEX_MPERF]; 4952 t->smi_count = mci->data[MSR_RCI_INDEX_SMI]; 4953 4954 return 0; 4955} 4956 4957int perf_counter_info_read_values(struct perf_counter_info *pp, int cpu, unsigned long long *out, size_t out_size) 4958{ 4959 unsigned int domain; 4960 unsigned long long value; 4961 int fd_counter; 4962 4963 for (size_t i = 0; pp; ++i, pp = pp->next) { 4964 domain = cpu_to_domain(pp, cpu); 4965 assert(domain < pp->num_domains); 4966 4967 fd_counter = pp->fd_perf_per_domain[domain]; 4968 4969 if (fd_counter == -1) 4970 continue; 4971 4972 if (read(fd_counter, &value, sizeof(value)) != sizeof(value)) 4973 return 1; 4974 4975 assert(i < out_size); 4976 out[i] = value * pp->scale; 4977 } 4978 4979 return 0; 4980} 4981 4982unsigned long pmt_gen_value_mask(unsigned int lsb, unsigned int msb) 4983{ 4984 unsigned long mask; 4985 4986 if (msb == 63) 4987 mask = 0xffffffffffffffff; 4988 else 4989 mask = ((1 << (msb + 1)) - 1); 4990 4991 mask -= (1 << lsb) - 1; 4992 4993 return mask; 4994} 4995 4996unsigned long pmt_read_counter(struct pmt_counter *ppmt, unsigned int domain_id) 4997{ 4998 if (domain_id >= ppmt->num_domains) 4999 return 0; 5000 5001 const unsigned long *pmmio = ppmt->domains[domain_id].pcounter; 5002 const unsigned long value = pmmio ? *pmmio : 0; 5003 const unsigned long value_mask = pmt_gen_value_mask(ppmt->lsb, ppmt->msb); 5004 const unsigned long value_shift = ppmt->lsb; 5005 5006 return (value & value_mask) >> value_shift; 5007} 5008 5009/* Rapl domain enumeration helpers */ 5010static inline int get_rapl_num_domains(void) 5011{ 5012 int num_packages = topo.max_package_id + 1; 5013 int num_cores_per_package; 5014 int num_cores; 5015 5016 if (!platform->has_per_core_rapl) 5017 return num_packages; 5018 5019 num_cores_per_package = topo.max_core_id + 1; 5020 num_cores = num_cores_per_package * num_packages; 5021 5022 return num_cores; 5023} 5024 5025static inline int get_rapl_domain_id(int cpu) 5026{ 5027 int nr_cores_per_package = topo.max_core_id + 1; 5028 int rapl_core_id; 5029 5030 if (!platform->has_per_core_rapl) 5031 return cpus[cpu].physical_package_id; 5032 5033 /* Compute the system-wide unique core-id for @cpu */ 5034 rapl_core_id = cpus[cpu].physical_core_id; 5035 rapl_core_id += cpus[cpu].physical_package_id * nr_cores_per_package; 5036 5037 return rapl_core_id; 5038} 5039 5040/* 5041 * get_counters(...) 5042 * migrate to cpu 5043 * acquire and record local counters for that cpu 5044 */ 5045int get_counters(PER_THREAD_PARAMS) 5046{ 5047 int cpu = t->cpu_id; 5048 unsigned long long msr; 5049 struct msr_counter *mp; 5050 struct pmt_counter *pp; 5051 int i; 5052 int status; 5053 5054 if (cpu_migrate(cpu)) { 5055 fprintf(outf, "%s: Could not migrate to CPU %d\n", __func__, cpu); 5056 return -1; 5057 } 5058 5059 gettimeofday(&t->tv_begin, (struct timezone *)NULL); 5060 5061 if (first_counter_read) 5062 get_apic_id(t); 5063 5064 t->tsc = rdtsc(); /* we are running on local CPU of interest */ 5065 5066 get_smi_aperf_mperf(cpu, t); 5067 5068 if (DO_BIC(BIC_LLC_RPS) || DO_BIC(BIC_LLC_HIT)) 5069 get_perf_llc_stats(cpu, &t->llc); 5070 5071 if (DO_BIC(BIC_IPC)) 5072 if (read(get_instr_count_fd(cpu), &t->instr_count, sizeof(long long)) != sizeof(long long)) 5073 return -4; 5074 5075 if (DO_BIC(BIC_IRQ)) 5076 t->irq_count = irqs_per_cpu[cpu]; 5077 if (DO_BIC(BIC_NMI)) 5078 t->nmi_count = nmi_per_cpu[cpu]; 5079 5080 get_cstate_counters(cpu, t, c, p); 5081 5082 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 5083 if (get_mp(cpu, mp, &t->counter[i], mp->sp->path)) 5084 return -10; 5085 } 5086 5087 if (perf_counter_info_read_values(sys.perf_tp, cpu, t->perf_counter, MAX_ADDED_THREAD_COUNTERS)) 5088 return -10; 5089 5090 for (i = 0, pp = sys.pmt_tp; pp; i++, pp = pp->next) 5091 t->pmt_counter[i] = pmt_read_counter(pp, t->cpu_id); 5092 5093 /* collect core counters only for 1st thread in core */ 5094 if (!is_cpu_first_thread_in_core(t, c)) 5095 goto done; 5096 5097 if (platform->has_per_core_rapl) { 5098 status = get_rapl_counters(cpu, get_rapl_domain_id(cpu), c, p); 5099 if (status != 0) 5100 return status; 5101 } 5102 5103 if (DO_BIC(BIC_CPU_c7) && t->is_atom) { 5104 /* 5105 * For Atom CPUs that has core cstate deeper than c6, 5106 * MSR_CORE_C6_RESIDENCY returns residency of cc6 and deeper. 5107 * Minus CC7 (and deeper cstates) residency to get 5108 * accturate cc6 residency. 5109 */ 5110 c->c6 -= c->c7; 5111 } 5112 5113 if (DO_BIC(BIC_Mod_c6)) 5114 if (get_msr(cpu, MSR_MODULE_C6_RES_MS, &c->mc6_us)) 5115 return -8; 5116 5117 if (DO_BIC(BIC_CoreTmp)) { 5118 if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr)) 5119 return -9; 5120 c->core_temp_c = tj_max - ((msr >> 16) & 0x7F); 5121 } 5122 5123 if (DO_BIC(BIC_CORE_THROT_CNT)) 5124 get_core_throt_cnt(cpu, &c->core_throt_cnt); 5125 5126 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 5127 if (get_mp(cpu, mp, &c->counter[i], mp->sp->path)) 5128 return -10; 5129 } 5130 5131 if (perf_counter_info_read_values(sys.perf_cp, cpu, c->perf_counter, MAX_ADDED_CORE_COUNTERS)) 5132 return -10; 5133 5134 for (i = 0, pp = sys.pmt_cp; pp; i++, pp = pp->next) 5135 c->pmt_counter[i] = pmt_read_counter(pp, c->core_id); 5136 5137 /* collect package counters only for 1st core in package */ 5138 if (!is_cpu_first_core_in_package(t, p)) 5139 goto done; 5140 5141 if (DO_BIC(BIC_Totl_c0)) { 5142 if (get_msr(cpu, MSR_PKG_WEIGHTED_CORE_C0_RES, &p->pkg_wtd_core_c0)) 5143 return -10; 5144 } 5145 if (DO_BIC(BIC_Any_c0)) { 5146 if (get_msr(cpu, MSR_PKG_ANY_CORE_C0_RES, &p->pkg_any_core_c0)) 5147 return -11; 5148 } 5149 if (DO_BIC(BIC_GFX_c0)) { 5150 if (get_msr(cpu, MSR_PKG_ANY_GFXE_C0_RES, &p->pkg_any_gfxe_c0)) 5151 return -12; 5152 } 5153 if (DO_BIC(BIC_CPUGFX)) { 5154 if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0)) 5155 return -13; 5156 } 5157 5158 if (DO_BIC(BIC_CPU_LPI)) 5159 p->cpu_lpi = cpuidle_cur_cpu_lpi_us; 5160 if (DO_BIC(BIC_SYS_LPI)) 5161 p->sys_lpi = cpuidle_cur_sys_lpi_us; 5162 5163 if (!platform->has_per_core_rapl) { 5164 status = get_rapl_counters(cpu, get_rapl_domain_id(cpu), c, p); 5165 if (status != 0) 5166 return status; 5167 } 5168 5169 if (DO_BIC(BIC_PkgTmp)) { 5170 if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr)) 5171 return -17; 5172 p->pkg_temp_c = tj_max - ((msr >> 16) & 0x7F); 5173 } 5174 5175 if (DO_BIC(BIC_UNCORE_MHZ)) 5176 p->uncore_mhz = get_legacy_uncore_mhz(p->package_id); 5177 5178 if (DO_BIC(BIC_GFX_rc6)) 5179 p->gfx_rc6_ms = gfx_info[GFX_rc6].val_ull; 5180 5181 if (DO_BIC(BIC_GFXMHz)) 5182 p->gfx_mhz = gfx_info[GFX_MHz].val; 5183 5184 if (DO_BIC(BIC_GFXACTMHz)) 5185 p->gfx_act_mhz = gfx_info[GFX_ACTMHz].val; 5186 5187 if (DO_BIC(BIC_SAM_mc6)) 5188 p->sam_mc6_ms = gfx_info[SAM_mc6].val_ull; 5189 5190 if (DO_BIC(BIC_SAMMHz)) 5191 p->sam_mhz = gfx_info[SAM_MHz].val; 5192 5193 if (DO_BIC(BIC_SAMACTMHz)) 5194 p->sam_act_mhz = gfx_info[SAM_ACTMHz].val; 5195 5196 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 5197 char *path = NULL; 5198 5199 if (mp->msr_num == 0) { 5200 path = find_sysfs_path_by_id(mp->sp, p->package_id); 5201 if (path == NULL) { 5202 warnx("%s: package_id %d not found", __func__, p->package_id); 5203 return -10; 5204 } 5205 } 5206 if (get_mp(cpu, mp, &p->counter[i], path)) 5207 return -10; 5208 } 5209 5210 if (perf_counter_info_read_values(sys.perf_pp, cpu, p->perf_counter, MAX_ADDED_PACKAGE_COUNTERS)) 5211 return -10; 5212 5213 for (i = 0, pp = sys.pmt_pp; pp; i++, pp = pp->next) 5214 p->pmt_counter[i] = pmt_read_counter(pp, p->package_id); 5215 5216done: 5217 gettimeofday(&t->tv_end, (struct timezone *)NULL); 5218 5219 return 0; 5220} 5221 5222int pkg_cstate_limit = PCLUKN; 5223char *pkg_cstate_limit_strings[] = { "unknown", "reserved", "pc0", "pc1", "pc2", 5224 "pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "pc8", "pc9", "pc10", "unlimited" 5225}; 5226 5227int nhm_pkg_cstate_limits[16] = { PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, 5228 PCLRSV, PCLRSV 5229}; 5230 5231int 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, 5232 PCLRSV, PCLRSV 5233}; 5234 5235int 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, 5236 PCLRSV, PCLRSV 5237}; 5238 5239int slv_pkg_cstate_limits[16] = { PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, 5240 PCL__6, PCL__7 5241}; 5242 5243int amt_pkg_cstate_limits[16] = { PCLUNL, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, 5244 PCLRSV, PCLRSV 5245}; 5246 5247int phi_pkg_cstate_limits[16] = { PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, 5248 PCLRSV, PCLRSV 5249}; 5250 5251int glm_pkg_cstate_limits[16] = { PCLUNL, PCL__1, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCL_10, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, 5252 PCLRSV, PCLRSV 5253}; 5254 5255int skx_pkg_cstate_limits[16] = { PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, 5256 PCLRSV, PCLRSV 5257}; 5258 5259int icx_pkg_cstate_limits[16] = { PCL__0, PCL__2, PCL__6, PCL__6, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, 5260 PCLRSV, PCLRSV 5261}; 5262 5263void probe_cst_limit(void) 5264{ 5265 unsigned long long msr; 5266 int *pkg_cstate_limits; 5267 5268 if (!platform->has_nhm_msrs || no_msr) 5269 return; 5270 5271 switch (platform->cst_limit) { 5272 case CST_LIMIT_NHM: 5273 pkg_cstate_limits = nhm_pkg_cstate_limits; 5274 break; 5275 case CST_LIMIT_SNB: 5276 pkg_cstate_limits = snb_pkg_cstate_limits; 5277 break; 5278 case CST_LIMIT_HSW: 5279 pkg_cstate_limits = hsw_pkg_cstate_limits; 5280 break; 5281 case CST_LIMIT_SKX: 5282 pkg_cstate_limits = skx_pkg_cstate_limits; 5283 break; 5284 case CST_LIMIT_ICX: 5285 pkg_cstate_limits = icx_pkg_cstate_limits; 5286 break; 5287 case CST_LIMIT_SLV: 5288 pkg_cstate_limits = slv_pkg_cstate_limits; 5289 break; 5290 case CST_LIMIT_AMT: 5291 pkg_cstate_limits = amt_pkg_cstate_limits; 5292 break; 5293 case CST_LIMIT_KNL: 5294 pkg_cstate_limits = phi_pkg_cstate_limits; 5295 break; 5296 case CST_LIMIT_GMT: 5297 pkg_cstate_limits = glm_pkg_cstate_limits; 5298 break; 5299 default: 5300 return; 5301 } 5302 5303 get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr); 5304 pkg_cstate_limit = pkg_cstate_limits[msr & 0xF]; 5305} 5306 5307static void dump_platform_info(void) 5308{ 5309 unsigned long long msr; 5310 unsigned int ratio; 5311 5312 if (!platform->has_nhm_msrs || no_msr) 5313 return; 5314 5315 get_msr(base_cpu, MSR_PLATFORM_INFO, &msr); 5316 5317 fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr); 5318 5319 ratio = (msr >> 40) & 0xFF; 5320 fprintf(outf, "%d * %.1f = %.1f MHz max efficiency frequency\n", ratio, bclk, ratio * bclk); 5321 5322 ratio = (msr >> 8) & 0xFF; 5323 fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n", ratio, bclk, ratio * bclk); 5324} 5325 5326static void dump_power_ctl(void) 5327{ 5328 unsigned long long msr; 5329 5330 if (!platform->has_nhm_msrs || no_msr) 5331 return; 5332 5333 get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr); 5334 fprintf(outf, "cpu%d: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n", base_cpu, msr, msr & 0x2 ? "EN" : "DIS"); 5335 5336 /* C-state Pre-wake Disable (CSTATE_PREWAKE_DISABLE) */ 5337 if (platform->has_cst_prewake_bit) 5338 fprintf(outf, "C-state Pre-wake: %sabled\n", msr & 0x40000000 ? "DIS" : "EN"); 5339 5340 return; 5341} 5342 5343static void dump_turbo_ratio_limit2(void) 5344{ 5345 unsigned long long msr; 5346 unsigned int ratio; 5347 5348 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT2, &msr); 5349 5350 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT2: 0x%08llx\n", base_cpu, msr); 5351 5352 ratio = (msr >> 8) & 0xFF; 5353 if (ratio) 5354 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 18 active cores\n", ratio, bclk, ratio * bclk); 5355 5356 ratio = (msr >> 0) & 0xFF; 5357 if (ratio) 5358 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 17 active cores\n", ratio, bclk, ratio * bclk); 5359 return; 5360} 5361 5362static void dump_turbo_ratio_limit1(void) 5363{ 5364 unsigned long long msr; 5365 unsigned int ratio; 5366 5367 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &msr); 5368 5369 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, msr); 5370 5371 ratio = (msr >> 56) & 0xFF; 5372 if (ratio) 5373 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 16 active cores\n", ratio, bclk, ratio * bclk); 5374 5375 ratio = (msr >> 48) & 0xFF; 5376 if (ratio) 5377 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 15 active cores\n", ratio, bclk, ratio * bclk); 5378 5379 ratio = (msr >> 40) & 0xFF; 5380 if (ratio) 5381 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 14 active cores\n", ratio, bclk, ratio * bclk); 5382 5383 ratio = (msr >> 32) & 0xFF; 5384 if (ratio) 5385 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 13 active cores\n", ratio, bclk, ratio * bclk); 5386 5387 ratio = (msr >> 24) & 0xFF; 5388 if (ratio) 5389 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 12 active cores\n", ratio, bclk, ratio * bclk); 5390 5391 ratio = (msr >> 16) & 0xFF; 5392 if (ratio) 5393 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 11 active cores\n", ratio, bclk, ratio * bclk); 5394 5395 ratio = (msr >> 8) & 0xFF; 5396 if (ratio) 5397 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 10 active cores\n", ratio, bclk, ratio * bclk); 5398 5399 ratio = (msr >> 0) & 0xFF; 5400 if (ratio) 5401 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 9 active cores\n", ratio, bclk, ratio * bclk); 5402 return; 5403} 5404 5405static void dump_turbo_ratio_limits(int trl_msr_offset) 5406{ 5407 unsigned long long msr, core_counts; 5408 int shift; 5409 5410 get_msr(base_cpu, trl_msr_offset, &msr); 5411 fprintf(outf, "cpu%d: MSR_%sTURBO_RATIO_LIMIT: 0x%08llx\n", 5412 base_cpu, trl_msr_offset == MSR_SECONDARY_TURBO_RATIO_LIMIT ? "SECONDARY_" : "", msr); 5413 5414 if (platform->trl_msrs & TRL_CORECOUNT) { 5415 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &core_counts); 5416 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, core_counts); 5417 } else { 5418 core_counts = 0x0807060504030201; 5419 } 5420 5421 for (shift = 56; shift >= 0; shift -= 8) { 5422 unsigned int ratio, group_size; 5423 5424 ratio = (msr >> shift) & 0xFF; 5425 group_size = (core_counts >> shift) & 0xFF; 5426 if (ratio) 5427 fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n", ratio, bclk, ratio * bclk, group_size); 5428 } 5429 5430 return; 5431} 5432 5433static void dump_atom_turbo_ratio_limits(void) 5434{ 5435 unsigned long long msr; 5436 unsigned int ratio; 5437 5438 get_msr(base_cpu, MSR_ATOM_CORE_RATIOS, &msr); 5439 fprintf(outf, "cpu%d: MSR_ATOM_CORE_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF); 5440 5441 ratio = (msr >> 0) & 0x3F; 5442 if (ratio) 5443 fprintf(outf, "%d * %.1f = %.1f MHz minimum operating frequency\n", ratio, bclk, ratio * bclk); 5444 5445 ratio = (msr >> 8) & 0x3F; 5446 if (ratio) 5447 fprintf(outf, "%d * %.1f = %.1f MHz low frequency mode (LFM)\n", ratio, bclk, ratio * bclk); 5448 5449 ratio = (msr >> 16) & 0x3F; 5450 if (ratio) 5451 fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n", ratio, bclk, ratio * bclk); 5452 5453 get_msr(base_cpu, MSR_ATOM_CORE_TURBO_RATIOS, &msr); 5454 fprintf(outf, "cpu%d: MSR_ATOM_CORE_TURBO_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF); 5455 5456 ratio = (msr >> 24) & 0x3F; 5457 if (ratio) 5458 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 4 active cores\n", ratio, bclk, ratio * bclk); 5459 5460 ratio = (msr >> 16) & 0x3F; 5461 if (ratio) 5462 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 3 active cores\n", ratio, bclk, ratio * bclk); 5463 5464 ratio = (msr >> 8) & 0x3F; 5465 if (ratio) 5466 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 2 active cores\n", ratio, bclk, ratio * bclk); 5467 5468 ratio = (msr >> 0) & 0x3F; 5469 if (ratio) 5470 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 1 active core\n", ratio, bclk, ratio * bclk); 5471} 5472 5473static void dump_knl_turbo_ratio_limits(void) 5474{ 5475 const unsigned int buckets_no = 7; 5476 5477 unsigned long long msr; 5478 int delta_cores, delta_ratio; 5479 int i, b_nr; 5480 unsigned int cores[buckets_no]; 5481 unsigned int ratio[buckets_no]; 5482 5483 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr); 5484 5485 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr); 5486 5487 /* 5488 * Turbo encoding in KNL is as follows: 5489 * [0] -- Reserved 5490 * [7:1] -- Base value of number of active cores of bucket 1. 5491 * [15:8] -- Base value of freq ratio of bucket 1. 5492 * [20:16] -- +ve delta of number of active cores of bucket 2. 5493 * i.e. active cores of bucket 2 = 5494 * active cores of bucket 1 + delta 5495 * [23:21] -- Negative delta of freq ratio of bucket 2. 5496 * i.e. freq ratio of bucket 2 = 5497 * freq ratio of bucket 1 - delta 5498 * [28:24]-- +ve delta of number of active cores of bucket 3. 5499 * [31:29]-- -ve delta of freq ratio of bucket 3. 5500 * [36:32]-- +ve delta of number of active cores of bucket 4. 5501 * [39:37]-- -ve delta of freq ratio of bucket 4. 5502 * [44:40]-- +ve delta of number of active cores of bucket 5. 5503 * [47:45]-- -ve delta of freq ratio of bucket 5. 5504 * [52:48]-- +ve delta of number of active cores of bucket 6. 5505 * [55:53]-- -ve delta of freq ratio of bucket 6. 5506 * [60:56]-- +ve delta of number of active cores of bucket 7. 5507 * [63:61]-- -ve delta of freq ratio of bucket 7. 5508 */ 5509 5510 b_nr = 0; 5511 cores[b_nr] = (msr & 0xFF) >> 1; 5512 ratio[b_nr] = (msr >> 8) & 0xFF; 5513 5514 for (i = 16; i < 64; i += 8) { 5515 delta_cores = (msr >> i) & 0x1F; 5516 delta_ratio = (msr >> (i + 5)) & 0x7; 5517 5518 cores[b_nr + 1] = cores[b_nr] + delta_cores; 5519 ratio[b_nr + 1] = ratio[b_nr] - delta_ratio; 5520 b_nr++; 5521 } 5522 5523 for (i = buckets_no - 1; i >= 0; i--) 5524 if (i > 0 ? ratio[i] != ratio[i - 1] : 1) 5525 fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n", ratio[i], bclk, ratio[i] * bclk, cores[i]); 5526} 5527 5528static void dump_cst_cfg(void) 5529{ 5530 unsigned long long msr; 5531 5532 if (!platform->has_nhm_msrs || no_msr) 5533 return; 5534 5535 get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr); 5536 5537 fprintf(outf, "cpu%d: MSR_PKG_CST_CONFIG_CONTROL: 0x%08llx", base_cpu, msr); 5538 5539 fprintf(outf, " (%s%s%s%s%slocked, pkg-cstate-limit=%d (%s)", 5540 (msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "", 5541 (msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "", 5542 (msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "", 5543 (msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "", 5544 (msr & (1 << 15)) ? "" : "UN", (unsigned int)msr & 0xF, pkg_cstate_limit_strings[pkg_cstate_limit]); 5545 5546#define AUTOMATIC_CSTATE_CONVERSION (1UL << 16) 5547 if (platform->has_cst_auto_convension) { 5548 fprintf(outf, ", automatic c-state conversion=%s", (msr & AUTOMATIC_CSTATE_CONVERSION) ? "on" : "off"); 5549 } 5550 5551 fprintf(outf, ")\n"); 5552 5553 return; 5554} 5555 5556static void dump_config_tdp(void) 5557{ 5558 unsigned long long msr; 5559 5560 get_msr(base_cpu, MSR_CONFIG_TDP_NOMINAL, &msr); 5561 fprintf(outf, "cpu%d: MSR_CONFIG_TDP_NOMINAL: 0x%08llx", base_cpu, msr); 5562 fprintf(outf, " (base_ratio=%d)\n", (unsigned int)msr & 0xFF); 5563 5564 get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_1, &msr); 5565 fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_1: 0x%08llx (", base_cpu, msr); 5566 if (msr) { 5567 fprintf(outf, "PKG_MIN_PWR_LVL1=%d ", (unsigned int)(msr >> 48) & 0x7FFF); 5568 fprintf(outf, "PKG_MAX_PWR_LVL1=%d ", (unsigned int)(msr >> 32) & 0x7FFF); 5569 fprintf(outf, "LVL1_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF); 5570 fprintf(outf, "PKG_TDP_LVL1=%d", (unsigned int)(msr) & 0x7FFF); 5571 } 5572 fprintf(outf, ")\n"); 5573 5574 get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_2, &msr); 5575 fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_2: 0x%08llx (", base_cpu, msr); 5576 if (msr) { 5577 fprintf(outf, "PKG_MIN_PWR_LVL2=%d ", (unsigned int)(msr >> 48) & 0x7FFF); 5578 fprintf(outf, "PKG_MAX_PWR_LVL2=%d ", (unsigned int)(msr >> 32) & 0x7FFF); 5579 fprintf(outf, "LVL2_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF); 5580 fprintf(outf, "PKG_TDP_LVL2=%d", (unsigned int)(msr) & 0x7FFF); 5581 } 5582 fprintf(outf, ")\n"); 5583 5584 get_msr(base_cpu, MSR_CONFIG_TDP_CONTROL, &msr); 5585 fprintf(outf, "cpu%d: MSR_CONFIG_TDP_CONTROL: 0x%08llx (", base_cpu, msr); 5586 if ((msr) & 0x3) 5587 fprintf(outf, "TDP_LEVEL=%d ", (unsigned int)(msr) & 0x3); 5588 fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1); 5589 fprintf(outf, ")\n"); 5590 5591 get_msr(base_cpu, MSR_TURBO_ACTIVATION_RATIO, &msr); 5592 fprintf(outf, "cpu%d: MSR_TURBO_ACTIVATION_RATIO: 0x%08llx (", base_cpu, msr); 5593 fprintf(outf, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0xFF); 5594 fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1); 5595 fprintf(outf, ")\n"); 5596} 5597 5598unsigned int irtl_time_units[] = { 1, 32, 1024, 32768, 1048576, 33554432, 0, 0 }; 5599 5600void print_irtl(void) 5601{ 5602 unsigned long long msr; 5603 5604 if (!platform->has_irtl_msrs || no_msr) 5605 return; 5606 5607 if (platform->supported_cstates & PC3) { 5608 get_msr(base_cpu, MSR_PKGC3_IRTL, &msr); 5609 fprintf(outf, "cpu%d: MSR_PKGC3_IRTL: 0x%08llx (", base_cpu, msr); 5610 fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 5611 } 5612 5613 if (platform->supported_cstates & PC6) { 5614 get_msr(base_cpu, MSR_PKGC6_IRTL, &msr); 5615 fprintf(outf, "cpu%d: MSR_PKGC6_IRTL: 0x%08llx (", base_cpu, msr); 5616 fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 5617 } 5618 5619 if (platform->supported_cstates & PC7) { 5620 get_msr(base_cpu, MSR_PKGC7_IRTL, &msr); 5621 fprintf(outf, "cpu%d: MSR_PKGC7_IRTL: 0x%08llx (", base_cpu, msr); 5622 fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 5623 } 5624 5625 if (platform->supported_cstates & PC8) { 5626 get_msr(base_cpu, MSR_PKGC8_IRTL, &msr); 5627 fprintf(outf, "cpu%d: MSR_PKGC8_IRTL: 0x%08llx (", base_cpu, msr); 5628 fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 5629 } 5630 5631 if (platform->supported_cstates & PC9) { 5632 get_msr(base_cpu, MSR_PKGC9_IRTL, &msr); 5633 fprintf(outf, "cpu%d: MSR_PKGC9_IRTL: 0x%08llx (", base_cpu, msr); 5634 fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 5635 } 5636 5637 if (platform->supported_cstates & PC10) { 5638 get_msr(base_cpu, MSR_PKGC10_IRTL, &msr); 5639 fprintf(outf, "cpu%d: MSR_PKGC10_IRTL: 0x%08llx (", base_cpu, msr); 5640 fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); 5641 } 5642} 5643 5644void free_fd_percpu(void) 5645{ 5646 int i; 5647 5648 if (!fd_percpu) 5649 return; 5650 5651 for (i = 0; i < topo.max_cpu_num + 1; ++i) { 5652 if (fd_percpu[i] != 0) 5653 close(fd_percpu[i]); 5654 } 5655 5656 free(fd_percpu); 5657 fd_percpu = NULL; 5658} 5659 5660void free_fd_instr_count_percpu(void) 5661{ 5662 if (!fd_instr_count_percpu) 5663 return; 5664 5665 for (int i = 0; i < topo.max_cpu_num + 1; ++i) { 5666 if (fd_instr_count_percpu[i] != 0) 5667 close(fd_instr_count_percpu[i]); 5668 } 5669 5670 free(fd_instr_count_percpu); 5671 fd_instr_count_percpu = NULL; 5672} 5673 5674void free_fd_llc_percpu(void) 5675{ 5676 if (!fd_llc_percpu) 5677 return; 5678 5679 for (int i = 0; i < topo.max_cpu_num + 1; ++i) { 5680 if (fd_llc_percpu[i] != 0) 5681 close(fd_llc_percpu[i]); 5682 } 5683 5684 free(fd_llc_percpu); 5685 fd_llc_percpu = NULL; 5686} 5687 5688void free_fd_cstate(void) 5689{ 5690 if (!ccstate_counter_info) 5691 return; 5692 5693 const int counter_info_num = ccstate_counter_info_size; 5694 5695 for (int counter_id = 0; counter_id < counter_info_num; ++counter_id) { 5696 if (ccstate_counter_info[counter_id].fd_perf_core != -1) 5697 close(ccstate_counter_info[counter_id].fd_perf_core); 5698 5699 if (ccstate_counter_info[counter_id].fd_perf_pkg != -1) 5700 close(ccstate_counter_info[counter_id].fd_perf_pkg); 5701 } 5702 5703 free(ccstate_counter_info); 5704 ccstate_counter_info = NULL; 5705 ccstate_counter_info_size = 0; 5706} 5707 5708void free_fd_msr(void) 5709{ 5710 if (!msr_counter_info) 5711 return; 5712 5713 for (int cpu = 0; cpu < topo.max_cpu_num; ++cpu) { 5714 if (msr_counter_info[cpu].fd_perf != -1) 5715 close(msr_counter_info[cpu].fd_perf); 5716 } 5717 5718 free(msr_counter_info); 5719 msr_counter_info = NULL; 5720 msr_counter_info_size = 0; 5721} 5722 5723void free_fd_rapl_percpu(void) 5724{ 5725 if (!rapl_counter_info_perdomain) 5726 return; 5727 5728 const int num_domains = rapl_counter_info_perdomain_size; 5729 5730 for (int domain_id = 0; domain_id < num_domains; ++domain_id) { 5731 if (rapl_counter_info_perdomain[domain_id].fd_perf != -1) 5732 close(rapl_counter_info_perdomain[domain_id].fd_perf); 5733 } 5734 5735 free(rapl_counter_info_perdomain); 5736 rapl_counter_info_perdomain = NULL; 5737 rapl_counter_info_perdomain_size = 0; 5738} 5739 5740void free_fd_added_perf_counters_(struct perf_counter_info *pp) 5741{ 5742 if (!pp) 5743 return; 5744 5745 if (!pp->fd_perf_per_domain) 5746 return; 5747 5748 while (pp) { 5749 for (size_t domain = 0; domain < pp->num_domains; ++domain) { 5750 if (pp->fd_perf_per_domain[domain] != -1) { 5751 close(pp->fd_perf_per_domain[domain]); 5752 pp->fd_perf_per_domain[domain] = -1; 5753 } 5754 } 5755 5756 free(pp->fd_perf_per_domain); 5757 pp->fd_perf_per_domain = NULL; 5758 5759 pp = pp->next; 5760 } 5761} 5762 5763void free_fd_added_perf_counters(void) 5764{ 5765 free_fd_added_perf_counters_(sys.perf_tp); 5766 free_fd_added_perf_counters_(sys.perf_cp); 5767 free_fd_added_perf_counters_(sys.perf_pp); 5768} 5769 5770void free_all_buffers(void) 5771{ 5772 int i; 5773 5774 CPU_FREE(cpu_present_set); 5775 cpu_present_set = NULL; 5776 cpu_present_setsize = 0; 5777 5778 CPU_FREE(cpu_effective_set); 5779 cpu_effective_set = NULL; 5780 cpu_effective_setsize = 0; 5781 5782 CPU_FREE(cpu_allowed_set); 5783 cpu_allowed_set = NULL; 5784 cpu_allowed_setsize = 0; 5785 5786 CPU_FREE(cpu_affinity_set); 5787 cpu_affinity_set = NULL; 5788 cpu_affinity_setsize = 0; 5789 5790 free(thread_even); 5791 free(core_even); 5792 free(package_even); 5793 5794 thread_even = NULL; 5795 core_even = NULL; 5796 package_even = NULL; 5797 5798 free(thread_odd); 5799 free(core_odd); 5800 free(package_odd); 5801 5802 thread_odd = NULL; 5803 core_odd = NULL; 5804 package_odd = NULL; 5805 5806 free(output_buffer); 5807 output_buffer = NULL; 5808 outp = NULL; 5809 5810 free_fd_percpu(); 5811 free_fd_instr_count_percpu(); 5812 free_fd_llc_percpu(); 5813 free_fd_msr(); 5814 free_fd_rapl_percpu(); 5815 free_fd_cstate(); 5816 free_fd_added_perf_counters(); 5817 5818 free(irq_column_2_cpu); 5819 free(irqs_per_cpu); 5820 free(nmi_per_cpu); 5821 5822 for (i = 0; i <= topo.max_cpu_num; ++i) { 5823 if (cpus[i].put_ids) 5824 CPU_FREE(cpus[i].put_ids); 5825 } 5826 free(cpus); 5827} 5828 5829/* 5830 * Parse a file containing a single int. 5831 * Return 0 if file can not be opened 5832 * Exit if file can be opened, but can not be parsed 5833 */ 5834int parse_int_file(const char *fmt, ...) 5835{ 5836 va_list args; 5837 char path[PATH_MAX]; 5838 FILE *filep; 5839 int value; 5840 5841 va_start(args, fmt); 5842 vsnprintf(path, sizeof(path), fmt, args); 5843 va_end(args); 5844 filep = fopen(path, "r"); 5845 if (!filep) 5846 return 0; 5847 if (fscanf(filep, "%d", &value) != 1) 5848 err(1, "%s: failed to parse number from file", path); 5849 fclose(filep); 5850 return value; 5851} 5852 5853/* 5854 * cpu_is_first_core_in_package(cpu) 5855 * return 1 if given CPU is 1st core in package 5856 */ 5857int cpu_is_first_core_in_package(int cpu) 5858{ 5859 return cpu == parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_siblings_list", cpu); 5860} 5861 5862int get_physical_package_id(int cpu) 5863{ 5864 return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu); 5865} 5866 5867int get_die_id(int cpu) 5868{ 5869 return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/die_id", cpu); 5870} 5871 5872int get_l3_id(int cpu) 5873{ 5874 return parse_int_file("/sys/devices/system/cpu/cpu%d/cache/index3/id", cpu); 5875} 5876 5877int get_core_id(int cpu) 5878{ 5879 return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_id", cpu); 5880} 5881 5882void set_node_data(void) 5883{ 5884 int pkg, node, lnode, cpu, cpux; 5885 int cpu_count; 5886 5887 /* initialize logical_node_id */ 5888 for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu) 5889 cpus[cpu].logical_node_id = -1; 5890 5891 cpu_count = 0; 5892 for (pkg = 0; pkg < topo.num_packages; pkg++) { 5893 lnode = 0; 5894 for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu) { 5895 if (cpus[cpu].physical_package_id != pkg) 5896 continue; 5897 /* find a cpu with an unset logical_node_id */ 5898 if (cpus[cpu].logical_node_id != -1) 5899 continue; 5900 cpus[cpu].logical_node_id = lnode; 5901 node = cpus[cpu].physical_node_id; 5902 cpu_count++; 5903 /* 5904 * find all matching cpus on this pkg and set 5905 * the logical_node_id 5906 */ 5907 for (cpux = cpu; cpux <= topo.max_cpu_num; cpux++) { 5908 if ((cpus[cpux].physical_package_id == pkg) && (cpus[cpux].physical_node_id == node)) { 5909 cpus[cpux].logical_node_id = lnode; 5910 cpu_count++; 5911 } 5912 } 5913 lnode++; 5914 if (lnode > topo.nodes_per_pkg) 5915 topo.nodes_per_pkg = lnode; 5916 } 5917 if (cpu_count >= topo.max_cpu_num) 5918 break; 5919 } 5920} 5921 5922int get_physical_node_id(struct cpu_topology *thiscpu) 5923{ 5924 char path[80]; 5925 FILE *filep; 5926 int i; 5927 int cpu = thiscpu->logical_cpu_id; 5928 5929 for (i = 0; i <= topo.max_cpu_num; i++) { 5930 sprintf(path, "/sys/devices/system/cpu/cpu%d/node%i/cpulist", cpu, i); 5931 filep = fopen(path, "r"); 5932 if (!filep) 5933 continue; 5934 fclose(filep); 5935 return i; 5936 } 5937 return -1; 5938} 5939 5940static int parse_cpu_str(char *cpu_str, cpu_set_t *cpu_set, int cpu_set_size) 5941{ 5942 unsigned int start, end; 5943 char *next = cpu_str; 5944 5945 while (next && *next) { 5946 5947 if (*next == '-') /* no negative cpu numbers */ 5948 return 1; 5949 5950 if (*next == '\0' || *next == '\n') 5951 break; 5952 5953 start = strtoul(next, &next, 10); 5954 5955 if (start >= CPU_SUBSET_MAXCPUS) 5956 return 1; 5957 CPU_SET_S(start, cpu_set_size, cpu_set); 5958 5959 if (*next == '\0' || *next == '\n') 5960 break; 5961 5962 if (*next == ',') { 5963 next += 1; 5964 continue; 5965 } 5966 5967 if (*next == '-') { 5968 next += 1; /* start range */ 5969 } else if (*next == '.') { 5970 next += 1; 5971 if (*next == '.') 5972 next += 1; /* start range */ 5973 else 5974 return 1; 5975 } 5976 5977 end = strtoul(next, &next, 10); 5978 if (end <= start) 5979 return 1; 5980 5981 while (++start <= end) { 5982 if (start >= CPU_SUBSET_MAXCPUS) 5983 return 1; 5984 CPU_SET_S(start, cpu_set_size, cpu_set); 5985 } 5986 5987 if (*next == ',') 5988 next += 1; 5989 else if (*next != '\0' && *next != '\n') 5990 return 1; 5991 } 5992 5993 return 0; 5994} 5995 5996int get_thread_siblings(struct cpu_topology *thiscpu) 5997{ 5998 char path[80], character; 5999 FILE *filep; 6000 unsigned long map; 6001 int so, shift, sib_core; 6002 int cpu = thiscpu->logical_cpu_id; 6003 int offset = topo.max_cpu_num + 1; 6004 size_t size; 6005 int thread_id = 0; 6006 6007 thiscpu->put_ids = CPU_ALLOC((topo.max_cpu_num + 1)); 6008 if (thiscpu->thread_id < 0) 6009 thiscpu->thread_id = thread_id++; 6010 if (!thiscpu->put_ids) 6011 return -1; 6012 6013 size = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); 6014 CPU_ZERO_S(size, thiscpu->put_ids); 6015 6016 sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", cpu); 6017 filep = fopen(path, "r"); 6018 6019 if (!filep) { 6020 warnx("%s: open failed", path); 6021 return -1; 6022 } 6023 do { 6024 offset -= BITMASK_SIZE; 6025 if (fscanf(filep, "%lx%c", &map, &character) != 2) 6026 err(1, "%s: failed to parse file", path); 6027 for (shift = 0; shift < BITMASK_SIZE; shift++) { 6028 if ((map >> shift) & 0x1) { 6029 so = shift + offset; 6030 sib_core = get_core_id(so); 6031 if (sib_core == thiscpu->physical_core_id) { 6032 CPU_SET_S(so, size, thiscpu->put_ids); 6033 if ((so != cpu) && (cpus[so].thread_id < 0)) 6034 cpus[so].thread_id = thread_id++; 6035 } 6036 } 6037 } 6038 } while (character == ','); 6039 fclose(filep); 6040 6041 return CPU_COUNT_S(size, thiscpu->put_ids); 6042} 6043 6044/* 6045 * run func(thread, core, package) in topology order 6046 * skip non-present cpus 6047 */ 6048 6049int for_all_cpus_2(int (func) (struct thread_data *, struct core_data *, 6050 struct pkg_data *, struct thread_data *, struct core_data *, 6051 struct pkg_data *), struct thread_data *thread_base, 6052 struct core_data *core_base, struct pkg_data *pkg_base, 6053 struct thread_data *thread_base2, struct core_data *core_base2, struct pkg_data *pkg_base2) 6054{ 6055 int retval, pkg_no, node_no, core_no, thread_no; 6056 6057 retval = 0; 6058 6059 for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) { 6060 for (node_no = 0; node_no < topo.nodes_per_pkg; ++node_no) { 6061 for (core_no = 0; core_no < topo.cores_per_node; ++core_no) { 6062 for (thread_no = 0; thread_no < topo.threads_per_core; ++thread_no) { 6063 struct thread_data *t, *t2; 6064 struct core_data *c, *c2; 6065 6066 t = GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no); 6067 6068 if (cpu_is_not_allowed(t->cpu_id)) 6069 continue; 6070 6071 t2 = GET_THREAD(thread_base2, thread_no, core_no, node_no, pkg_no); 6072 6073 c = GET_CORE(core_base, core_no, node_no, pkg_no); 6074 c2 = GET_CORE(core_base2, core_no, node_no, pkg_no); 6075 6076 retval |= func(t, c, &pkg_base[pkg_no], t2, c2, &pkg_base2[pkg_no]); 6077 } 6078 } 6079 } 6080 } 6081 return retval; 6082} 6083 6084/* 6085 * run func(cpu) on every cpu in /proc/stat 6086 * return max_cpu number 6087 */ 6088int for_all_proc_cpus(int (func) (int)) 6089{ 6090 FILE *fp; 6091 int cpu_num; 6092 int retval; 6093 6094 fp = fopen_or_die(proc_stat, "r"); 6095 6096 retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n"); 6097 if (retval != 0) 6098 err(1, "%s: failed to parse format", proc_stat); 6099 6100 while (1) { 6101 retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num); 6102 if (retval != 1) 6103 break; 6104 6105 retval = func(cpu_num); 6106 if (retval) { 6107 fclose(fp); 6108 return (retval); 6109 } 6110 } 6111 fclose(fp); 6112 return 0; 6113} 6114 6115#define PATH_EFFECTIVE_CPUS "/sys/fs/cgroup/cpuset.cpus.effective" 6116 6117static char cpu_effective_str[1024]; 6118 6119static int update_effective_str(bool startup) 6120{ 6121 FILE *fp; 6122 char *pos; 6123 char buf[1024]; 6124 int ret; 6125 6126 if (cpu_effective_str[0] == '\0' && !startup) 6127 return 0; 6128 6129 fp = fopen(PATH_EFFECTIVE_CPUS, "r"); 6130 if (!fp) 6131 return 0; 6132 6133 pos = fgets(buf, 1024, fp); 6134 if (!pos) 6135 err(1, "%s: file read failed\n", PATH_EFFECTIVE_CPUS); 6136 6137 fclose(fp); 6138 6139 ret = strncmp(cpu_effective_str, buf, 1024); 6140 if (!ret) 6141 return 0; 6142 6143 strncpy(cpu_effective_str, buf, 1024); 6144 return 1; 6145} 6146 6147static void update_effective_set(bool startup) 6148{ 6149 update_effective_str(startup); 6150 6151 if (parse_cpu_str(cpu_effective_str, cpu_effective_set, cpu_effective_setsize)) 6152 err(1, "%s: cpu str malformat %s\n", PATH_EFFECTIVE_CPUS, cpu_effective_str); 6153} 6154 6155void linux_perf_init(void); 6156void msr_perf_init(void); 6157void rapl_perf_init(void); 6158void cstate_perf_init(void); 6159void perf_llc_init(void); 6160void added_perf_counters_init(void); 6161void pmt_init(void); 6162 6163void re_initialize(void) 6164{ 6165 free_all_buffers(); 6166 setup_all_buffers(false); 6167 linux_perf_init(); 6168 msr_perf_init(); 6169 rapl_perf_init(); 6170 cstate_perf_init(); 6171 perf_llc_init(); 6172 added_perf_counters_init(); 6173 pmt_init(); 6174 fprintf(outf, "turbostat: re-initialized with num_cpus %d, allowed_cpus %d\n", topo.num_cpus, topo.allowed_cpus); 6175} 6176 6177void set_max_cpu_num(void) 6178{ 6179 FILE *filep; 6180 int base_cpu; 6181 unsigned long dummy; 6182 char pathname[64]; 6183 6184 base_cpu = sched_getcpu(); 6185 if (base_cpu < 0) 6186 err(1, "cannot find calling cpu ID"); 6187 sprintf(pathname, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", base_cpu); 6188 6189 filep = fopen_or_die(pathname, "r"); 6190 topo.max_cpu_num = 0; 6191 while (fscanf(filep, "%lx,", &dummy) == 1) 6192 topo.max_cpu_num += BITMASK_SIZE; 6193 fclose(filep); 6194 topo.max_cpu_num--; /* 0 based */ 6195} 6196 6197/* 6198 * count_cpus() 6199 * remember the last one seen, it will be the max 6200 */ 6201int count_cpus(int cpu) 6202{ 6203 UNUSED(cpu); 6204 6205 topo.num_cpus++; 6206 return 0; 6207} 6208 6209int mark_cpu_present(int cpu) 6210{ 6211 CPU_SET_S(cpu, cpu_present_setsize, cpu_present_set); 6212 return 0; 6213} 6214 6215int init_thread_id(int cpu) 6216{ 6217 cpus[cpu].thread_id = -1; 6218 return 0; 6219} 6220 6221int set_my_cpu_type(void) 6222{ 6223 unsigned int eax, ebx, ecx, edx; 6224 unsigned int max_level; 6225 6226 __cpuid(0, max_level, ebx, ecx, edx); 6227 6228 if (max_level < CPUID_LEAF_MODEL_ID) 6229 return 0; 6230 6231 __cpuid(CPUID_LEAF_MODEL_ID, eax, ebx, ecx, edx); 6232 6233 return (eax >> CPUID_LEAF_MODEL_ID_CORE_TYPE_SHIFT); 6234} 6235 6236int set_cpu_hybrid_type(int cpu) 6237{ 6238 if (cpu_migrate(cpu)) 6239 return -1; 6240 6241 int type = set_my_cpu_type(); 6242 6243 cpus[cpu].type = type; 6244 return 0; 6245} 6246 6247/* 6248 * snapshot_proc_interrupts() 6249 * 6250 * read and record summary of /proc/interrupts 6251 * 6252 * return 1 if config change requires a restart, else return 0 6253 */ 6254int snapshot_proc_interrupts(void) 6255{ 6256 static FILE *fp; 6257 int column, retval; 6258 6259 if (fp == NULL) 6260 fp = fopen_or_die("/proc/interrupts", "r"); 6261 else 6262 rewind(fp); 6263 6264 /* read 1st line of /proc/interrupts to get cpu* name for each column */ 6265 for (column = 0; column < topo.num_cpus; ++column) { 6266 int cpu_number; 6267 6268 retval = fscanf(fp, " CPU%d", &cpu_number); 6269 if (retval != 1) 6270 break; 6271 6272 if (cpu_number > topo.max_cpu_num) { 6273 warn("/proc/interrupts: cpu%d: > %d", cpu_number, topo.max_cpu_num); 6274 return 1; 6275 } 6276 6277 irq_column_2_cpu[column] = cpu_number; 6278 irqs_per_cpu[cpu_number] = 0; 6279 nmi_per_cpu[cpu_number] = 0; 6280 } 6281 6282 /* read /proc/interrupt count lines and sum up irqs per cpu */ 6283 while (1) { 6284 int column; 6285 char buf[64]; 6286 int this_row_is_nmi = 0; 6287 6288 retval = fscanf(fp, " %s:", buf); /* irq# "N:" */ 6289 if (retval != 1) 6290 break; 6291 6292 if (strncmp(buf, "NMI", strlen("NMI")) == 0) 6293 this_row_is_nmi = 1; 6294 6295 /* read the count per cpu */ 6296 for (column = 0; column < topo.num_cpus; ++column) { 6297 6298 int cpu_number, irq_count; 6299 6300 retval = fscanf(fp, " %d", &irq_count); 6301 6302 if (retval != 1) 6303 break; 6304 6305 cpu_number = irq_column_2_cpu[column]; 6306 irqs_per_cpu[cpu_number] += irq_count; 6307 if (this_row_is_nmi) 6308 nmi_per_cpu[cpu_number] += irq_count; 6309 } 6310 while (getc(fp) != '\n') ; /* flush interrupt description */ 6311 6312 } 6313 return 0; 6314} 6315 6316/* 6317 * snapshot_graphics() 6318 * 6319 * record snapshot of specified graphics sysfs knob 6320 * 6321 * return 1 if config change requires a restart, else return 0 6322 */ 6323int snapshot_graphics(int idx) 6324{ 6325 int retval; 6326 6327 rewind(gfx_info[idx].fp); 6328 fflush(gfx_info[idx].fp); 6329 6330 switch (idx) { 6331 case GFX_rc6: 6332 case SAM_mc6: 6333 retval = fscanf(gfx_info[idx].fp, "%lld", &gfx_info[idx].val_ull); 6334 if (retval != 1) 6335 err(1, "rc6"); 6336 return 0; 6337 case GFX_MHz: 6338 case GFX_ACTMHz: 6339 case SAM_MHz: 6340 case SAM_ACTMHz: 6341 retval = fscanf(gfx_info[idx].fp, "%d", &gfx_info[idx].val); 6342 if (retval != 1) 6343 err(1, "MHz"); 6344 return 0; 6345 default: 6346 return -EINVAL; 6347 } 6348} 6349 6350/* 6351 * snapshot_cpu_lpi() 6352 * 6353 * record snapshot of 6354 * /sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us 6355 */ 6356int snapshot_cpu_lpi_us(void) 6357{ 6358 FILE *fp; 6359 int retval; 6360 6361 fp = fopen_or_die("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", "r"); 6362 6363 retval = fscanf(fp, "%lld", &cpuidle_cur_cpu_lpi_us); 6364 if (retval != 1) { 6365 fprintf(stderr, "Disabling Low Power Idle CPU output\n"); 6366 BIC_NOT_PRESENT(BIC_CPU_LPI); 6367 fclose(fp); 6368 return -1; 6369 } 6370 6371 fclose(fp); 6372 6373 return 0; 6374} 6375 6376/* 6377 * snapshot_sys_lpi() 6378 * 6379 * record snapshot of sys_lpi_file 6380 */ 6381int snapshot_sys_lpi_us(void) 6382{ 6383 FILE *fp; 6384 int retval; 6385 6386 fp = fopen_or_die(sys_lpi_file, "r"); 6387 6388 retval = fscanf(fp, "%lld", &cpuidle_cur_sys_lpi_us); 6389 if (retval != 1) { 6390 fprintf(stderr, "Disabling Low Power Idle System output\n"); 6391 BIC_NOT_PRESENT(BIC_SYS_LPI); 6392 fclose(fp); 6393 return -1; 6394 } 6395 fclose(fp); 6396 6397 return 0; 6398} 6399 6400/* 6401 * snapshot /proc and /sys files 6402 * 6403 * return 1 if configuration restart needed, else return 0 6404 */ 6405int snapshot_proc_sysfs_files(void) 6406{ 6407 gettimeofday(&procsysfs_tv_begin, (struct timezone *)NULL); 6408 6409 if (DO_BIC(BIC_IRQ) || DO_BIC(BIC_NMI)) 6410 if (snapshot_proc_interrupts()) 6411 return 1; 6412 6413 if (DO_BIC(BIC_GFX_rc6)) 6414 snapshot_graphics(GFX_rc6); 6415 6416 if (DO_BIC(BIC_GFXMHz)) 6417 snapshot_graphics(GFX_MHz); 6418 6419 if (DO_BIC(BIC_GFXACTMHz)) 6420 snapshot_graphics(GFX_ACTMHz); 6421 6422 if (DO_BIC(BIC_SAM_mc6)) 6423 snapshot_graphics(SAM_mc6); 6424 6425 if (DO_BIC(BIC_SAMMHz)) 6426 snapshot_graphics(SAM_MHz); 6427 6428 if (DO_BIC(BIC_SAMACTMHz)) 6429 snapshot_graphics(SAM_ACTMHz); 6430 6431 if (DO_BIC(BIC_CPU_LPI)) 6432 snapshot_cpu_lpi_us(); 6433 6434 if (DO_BIC(BIC_SYS_LPI)) 6435 snapshot_sys_lpi_us(); 6436 6437 return 0; 6438} 6439 6440int exit_requested; 6441 6442static void signal_handler(int signal) 6443{ 6444 switch (signal) { 6445 case SIGINT: 6446 exit_requested = 1; 6447 if (debug) 6448 fprintf(stderr, " SIGINT\n"); 6449 break; 6450 case SIGUSR1: 6451 if (debug > 1) 6452 fprintf(stderr, "SIGUSR1\n"); 6453 break; 6454 } 6455} 6456 6457void setup_signal_handler(void) 6458{ 6459 struct sigaction sa; 6460 6461 memset(&sa, 0, sizeof(sa)); 6462 6463 sa.sa_handler = &signal_handler; 6464 6465 if (sigaction(SIGINT, &sa, NULL) < 0) 6466 err(1, "sigaction SIGINT"); 6467 if (sigaction(SIGUSR1, &sa, NULL) < 0) 6468 err(1, "sigaction SIGUSR1"); 6469} 6470 6471void do_sleep(void) 6472{ 6473 struct timeval tout; 6474 struct timespec rest; 6475 fd_set readfds; 6476 int retval; 6477 6478 FD_ZERO(&readfds); 6479 FD_SET(0, &readfds); 6480 6481 if (ignore_stdin) { 6482 nanosleep(&interval_ts, NULL); 6483 return; 6484 } 6485 6486 tout = interval_tv; 6487 retval = select(1, &readfds, NULL, NULL, &tout); 6488 6489 if (retval == 1) { 6490 switch (getc(stdin)) { 6491 case 'q': 6492 exit_requested = 1; 6493 break; 6494 case EOF: 6495 /* 6496 * 'stdin' is a pipe closed on the other end. There 6497 * won't be any further input. 6498 */ 6499 ignore_stdin = 1; 6500 /* Sleep the rest of the time */ 6501 rest.tv_sec = (tout.tv_sec + tout.tv_usec / 1000000); 6502 rest.tv_nsec = (tout.tv_usec % 1000000) * 1000; 6503 nanosleep(&rest, NULL); 6504 } 6505 } 6506} 6507 6508int get_msr_sum(int cpu, off_t offset, unsigned long long *msr) 6509{ 6510 int ret, idx; 6511 unsigned long long msr_cur, msr_last; 6512 6513 assert(!no_msr); 6514 6515 if (!per_cpu_msr_sum) 6516 return 1; 6517 6518 idx = offset_to_idx(offset); 6519 if (idx < 0) 6520 return idx; 6521 /* get_msr_sum() = sum + (get_msr() - last) */ 6522 ret = get_msr(cpu, offset, &msr_cur); 6523 if (ret) 6524 return ret; 6525 msr_last = per_cpu_msr_sum[cpu].entries[idx].last; 6526 DELTA_WRAP32(msr_cur, msr_last); 6527 *msr = msr_last + per_cpu_msr_sum[cpu].entries[idx].sum; 6528 6529 return 0; 6530} 6531 6532timer_t timerid; 6533 6534/* Timer callback, update the sum of MSRs periodically. */ 6535static int update_msr_sum(PER_THREAD_PARAMS) 6536{ 6537 int i, ret; 6538 int cpu = t->cpu_id; 6539 6540 UNUSED(c); 6541 UNUSED(p); 6542 6543 assert(!no_msr); 6544 6545 for (i = IDX_PKG_ENERGY; i < IDX_COUNT; i++) { 6546 unsigned long long msr_cur, msr_last; 6547 off_t offset; 6548 6549 if (!idx_valid(i)) 6550 continue; 6551 offset = idx_to_offset(i); 6552 if (offset < 0) 6553 continue; 6554 ret = get_msr(cpu, offset, &msr_cur); 6555 if (ret) { 6556 fprintf(outf, "Can not update msr(0x%llx)\n", (unsigned long long)offset); 6557 continue; 6558 } 6559 6560 msr_last = per_cpu_msr_sum[cpu].entries[i].last; 6561 per_cpu_msr_sum[cpu].entries[i].last = msr_cur & 0xffffffff; 6562 6563 DELTA_WRAP32(msr_cur, msr_last); 6564 per_cpu_msr_sum[cpu].entries[i].sum += msr_last; 6565 } 6566 return 0; 6567} 6568 6569static void msr_record_handler(union sigval v) 6570{ 6571 UNUSED(v); 6572 6573 for_all_cpus(update_msr_sum, EVEN_COUNTERS); 6574} 6575 6576void msr_sum_record(void) 6577{ 6578 struct itimerspec its; 6579 struct sigevent sev; 6580 6581 per_cpu_msr_sum = calloc(topo.max_cpu_num + 1, sizeof(struct msr_sum_array)); 6582 if (!per_cpu_msr_sum) { 6583 fprintf(outf, "Can not allocate memory for long time MSR.\n"); 6584 return; 6585 } 6586 /* 6587 * Signal handler might be restricted, so use thread notifier instead. 6588 */ 6589 memset(&sev, 0, sizeof(struct sigevent)); 6590 sev.sigev_notify = SIGEV_THREAD; 6591 sev.sigev_notify_function = msr_record_handler; 6592 6593 sev.sigev_value.sival_ptr = &timerid; 6594 if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) { 6595 fprintf(outf, "Can not create timer.\n"); 6596 goto release_msr; 6597 } 6598 6599 its.it_value.tv_sec = 0; 6600 its.it_value.tv_nsec = 1; 6601 /* 6602 * A wraparound time has been calculated early. 6603 * Some sources state that the peak power for a 6604 * microprocessor is usually 1.5 times the TDP rating, 6605 * use 2 * TDP for safety. 6606 */ 6607 its.it_interval.tv_sec = rapl_joule_counter_range / 2; 6608 its.it_interval.tv_nsec = 0; 6609 6610 if (timer_settime(timerid, 0, &its, NULL) == -1) { 6611 fprintf(outf, "Can not set timer.\n"); 6612 goto release_timer; 6613 } 6614 return; 6615 6616release_timer: 6617 timer_delete(timerid); 6618release_msr: 6619 free(per_cpu_msr_sum); 6620 per_cpu_msr_sum = NULL; 6621} 6622 6623/* 6624 * set_my_sched_priority(pri) 6625 * return previous priority on success 6626 * return value < -20 on failure 6627 */ 6628int set_my_sched_priority(int priority) 6629{ 6630 int retval; 6631 int original_priority; 6632 6633 errno = 0; 6634 original_priority = getpriority(PRIO_PROCESS, 0); 6635 if (errno && (original_priority == -1)) 6636 return -21; 6637 6638 retval = setpriority(PRIO_PROCESS, 0, priority); 6639 if (retval) 6640 return -21; 6641 6642 errno = 0; 6643 retval = getpriority(PRIO_PROCESS, 0); 6644 if (retval != priority) 6645 return -21; 6646 6647 return original_priority; 6648} 6649 6650void turbostat_loop() 6651{ 6652 int retval; 6653 int restarted = 0; 6654 unsigned int done_iters = 0; 6655 6656 setup_signal_handler(); 6657 6658 /* 6659 * elevate own priority for interval mode 6660 * 6661 * ignore on error - we probably don't have permission to set it, but 6662 * it's not a big deal 6663 */ 6664 set_my_sched_priority(-20); 6665 6666restart: 6667 restarted++; 6668 6669 snapshot_proc_sysfs_files(); 6670 retval = for_all_cpus(get_counters, EVEN_COUNTERS); 6671 first_counter_read = 0; 6672 if (retval < -1) { 6673 exit(retval); 6674 } else if (retval == -1) { 6675 if (restarted > 10) { 6676 exit(retval); 6677 } 6678 re_initialize(); 6679 goto restart; 6680 } 6681 restarted = 0; 6682 done_iters = 0; 6683 gettimeofday(&tv_even, (struct timezone *)NULL); 6684 6685 while (1) { 6686 if (for_all_proc_cpus(cpu_is_not_present)) { 6687 re_initialize(); 6688 goto restart; 6689 } 6690 if (update_effective_str(false)) { 6691 re_initialize(); 6692 goto restart; 6693 } 6694 do_sleep(); 6695 if (snapshot_proc_sysfs_files()) 6696 goto restart; 6697 retval = for_all_cpus(get_counters, ODD_COUNTERS); 6698 if (retval < -1) { 6699 exit(retval); 6700 } else if (retval == -1) { 6701 re_initialize(); 6702 goto restart; 6703 } 6704 gettimeofday(&tv_odd, (struct timezone *)NULL); 6705 timersub(&tv_odd, &tv_even, &tv_delta); 6706 if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS)) { 6707 re_initialize(); 6708 goto restart; 6709 } 6710 delta_platform(&platform_counters_odd, &platform_counters_even); 6711 compute_average(EVEN_COUNTERS); 6712 format_all_counters(EVEN_COUNTERS); 6713 flush_output_stdout(); 6714 if (exit_requested) 6715 break; 6716 if (num_iterations && ++done_iters >= num_iterations) 6717 break; 6718 do_sleep(); 6719 if (snapshot_proc_sysfs_files()) 6720 goto restart; 6721 retval = for_all_cpus(get_counters, EVEN_COUNTERS); 6722 if (retval < -1) { 6723 exit(retval); 6724 } else if (retval == -1) { 6725 re_initialize(); 6726 goto restart; 6727 } 6728 gettimeofday(&tv_even, (struct timezone *)NULL); 6729 timersub(&tv_even, &tv_odd, &tv_delta); 6730 if (for_all_cpus_2(delta_cpu, EVEN_COUNTERS, ODD_COUNTERS)) { 6731 re_initialize(); 6732 goto restart; 6733 } 6734 delta_platform(&platform_counters_even, &platform_counters_odd); 6735 compute_average(ODD_COUNTERS); 6736 format_all_counters(ODD_COUNTERS); 6737 flush_output_stdout(); 6738 if (exit_requested) 6739 break; 6740 if (num_iterations && ++done_iters >= num_iterations) 6741 break; 6742 } 6743} 6744 6745int probe_dev_msr(void) 6746{ 6747 struct stat sb; 6748 char pathname[32]; 6749 6750 sprintf(pathname, "/dev/msr%d", base_cpu); 6751 return !stat(pathname, &sb); 6752} 6753 6754int probe_dev_cpu_msr(void) 6755{ 6756 struct stat sb; 6757 char pathname[32]; 6758 6759 sprintf(pathname, "/dev/cpu/%d/msr", base_cpu); 6760 return !stat(pathname, &sb); 6761} 6762 6763int probe_msr_driver(void) 6764{ 6765 if (probe_dev_msr()) { 6766 use_android_msr_path = 1; 6767 return 1; 6768 } 6769 return probe_dev_cpu_msr(); 6770} 6771 6772void check_msr_driver(void) 6773{ 6774 if (probe_msr_driver()) 6775 return; 6776 6777 if (system("/sbin/modprobe msr > /dev/null 2>&1")) 6778 no_msr = 1; 6779 6780 if (!probe_msr_driver()) 6781 no_msr = 1; 6782} 6783 6784/* 6785 * check for CAP_SYS_RAWIO 6786 * return 0 on success 6787 * return 1 on fail 6788 */ 6789int check_for_cap_sys_rawio(void) 6790{ 6791 cap_t caps; 6792 cap_flag_value_t cap_flag_value; 6793 int ret = 0; 6794 6795 caps = cap_get_proc(); 6796 if (caps == NULL) { 6797 /* 6798 * CONFIG_MULTIUSER=n kernels have no cap_get_proc() 6799 * Allow them to continue and attempt to access MSRs 6800 */ 6801 if (errno == ENOSYS) 6802 return 0; 6803 6804 return 1; 6805 } 6806 6807 if (cap_get_flag(caps, CAP_SYS_RAWIO, CAP_EFFECTIVE, &cap_flag_value)) { 6808 ret = 1; 6809 goto free_and_exit; 6810 } 6811 6812 if (cap_flag_value != CAP_SET) { 6813 ret = 1; 6814 goto free_and_exit; 6815 } 6816 6817free_and_exit: 6818 if (cap_free(caps) == -1) 6819 err(-6, "cap_free\n"); 6820 6821 return ret; 6822} 6823 6824void check_msr_permission(void) 6825{ 6826 int failed = 0; 6827 char pathname[32]; 6828 6829 if (no_msr) 6830 return; 6831 6832 /* check for CAP_SYS_RAWIO */ 6833 failed += check_for_cap_sys_rawio(); 6834 6835 /* test file permissions */ 6836 sprintf(pathname, use_android_msr_path ? "/dev/msr%d" : "/dev/cpu/%d/msr", base_cpu); 6837 if (euidaccess(pathname, R_OK)) { 6838 failed++; 6839 } 6840 6841 if (failed) { 6842 warnx("Failed to access %s. Some of the counters may not be available\n" 6843 "\tRun as root to enable them or use %s to disable the access explicitly", pathname, "--no-msr"); 6844 no_msr = 1; 6845 } 6846} 6847 6848void probe_bclk(void) 6849{ 6850 unsigned long long msr; 6851 unsigned int base_ratio; 6852 6853 if (!platform->has_nhm_msrs || no_msr) 6854 return; 6855 6856 if (platform->bclk_freq == BCLK_100MHZ) 6857 bclk = 100.00; 6858 else if (platform->bclk_freq == BCLK_133MHZ) 6859 bclk = 133.33; 6860 else if (platform->bclk_freq == BCLK_SLV) 6861 bclk = slm_bclk(); 6862 else 6863 return; 6864 6865 get_msr(base_cpu, MSR_PLATFORM_INFO, &msr); 6866 base_ratio = (msr >> 8) & 0xFF; 6867 6868 base_hz = base_ratio * bclk * 1000000; 6869 has_base_hz = 1; 6870 6871 if (platform->enable_tsc_tweak) 6872 tsc_tweak = base_hz / tsc_hz; 6873} 6874 6875static void remove_underbar(char *s) 6876{ 6877 char *to = s; 6878 6879 while (*s) { 6880 if (*s != '_') 6881 *to++ = *s; 6882 s++; 6883 } 6884 6885 *to = 0; 6886} 6887 6888static void dump_turbo_ratio_info(void) 6889{ 6890 if (!has_turbo) 6891 return; 6892 6893 if (!platform->has_nhm_msrs || no_msr) 6894 return; 6895 6896 if (platform->trl_msrs & TRL_LIMIT2) 6897 dump_turbo_ratio_limit2(); 6898 6899 if (platform->trl_msrs & TRL_LIMIT1) 6900 dump_turbo_ratio_limit1(); 6901 6902 if (platform->trl_msrs & TRL_BASE) { 6903 dump_turbo_ratio_limits(MSR_TURBO_RATIO_LIMIT); 6904 6905 if (is_hybrid) 6906 dump_turbo_ratio_limits(MSR_SECONDARY_TURBO_RATIO_LIMIT); 6907 } 6908 6909 if (platform->trl_msrs & TRL_ATOM) 6910 dump_atom_turbo_ratio_limits(); 6911 6912 if (platform->trl_msrs & TRL_KNL) 6913 dump_knl_turbo_ratio_limits(); 6914 6915 if (platform->has_config_tdp) 6916 dump_config_tdp(); 6917} 6918 6919static int read_sysfs_int(char *path) 6920{ 6921 FILE *input; 6922 int retval = -1; 6923 6924 input = fopen(path, "r"); 6925 if (input == NULL) { 6926 if (debug) 6927 fprintf(outf, "NSFOD %s\n", path); 6928 return (-1); 6929 } 6930 if (fscanf(input, "%d", &retval) != 1) 6931 err(1, "%s: failed to read int from file", path); 6932 fclose(input); 6933 6934 return (retval); 6935} 6936 6937static void dump_sysfs_file(char *path) 6938{ 6939 FILE *input; 6940 char cpuidle_buf[64]; 6941 6942 input = fopen(path, "r"); 6943 if (input == NULL) { 6944 if (debug) 6945 fprintf(outf, "NSFOD %s\n", path); 6946 return; 6947 } 6948 if (!fgets(cpuidle_buf, sizeof(cpuidle_buf), input)) 6949 err(1, "%s: failed to read file", path); 6950 fclose(input); 6951 6952 fprintf(outf, "%s: %s", strrchr(path, '/') + 1, cpuidle_buf); 6953} 6954 6955static void probe_intel_uncore_frequency_legacy(void) 6956{ 6957 int i, j; 6958 char path[256]; 6959 6960 for (i = 0; i < topo.num_packages; ++i) { 6961 for (j = 0; j <= topo.max_die_id; ++j) { 6962 int k, l; 6963 char path_base[128]; 6964 6965 sprintf(path_base, "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d", i, j); 6966 6967 sprintf(path, "%s/current_freq_khz", path_base); 6968 if (access(path, R_OK)) 6969 continue; 6970 6971 BIC_PRESENT(BIC_UNCORE_MHZ); 6972 6973 if (quiet) 6974 return; 6975 6976 sprintf(path, "%s/min_freq_khz", path_base); 6977 k = read_sysfs_int(path); 6978 sprintf(path, "%s/max_freq_khz", path_base); 6979 l = read_sysfs_int(path); 6980 fprintf(outf, "Uncore Frequency package%d die%d: %d - %d MHz ", i, j, k / 1000, l / 1000); 6981 6982 sprintf(path, "%s/initial_min_freq_khz", path_base); 6983 k = read_sysfs_int(path); 6984 sprintf(path, "%s/initial_max_freq_khz", path_base); 6985 l = read_sysfs_int(path); 6986 fprintf(outf, "(%d - %d MHz)", k / 1000, l / 1000); 6987 6988 sprintf(path, "%s/current_freq_khz", path_base); 6989 k = read_sysfs_int(path); 6990 fprintf(outf, " %d MHz\n", k / 1000); 6991 } 6992 } 6993} 6994 6995static void probe_intel_uncore_frequency_cluster(void) 6996{ 6997 int i, uncore_max_id; 6998 char path[256]; 6999 char path_base[128]; 7000 7001 if (access("/sys/devices/system/cpu/intel_uncore_frequency/uncore00/current_freq_khz", R_OK)) 7002 return; 7003 7004 for (uncore_max_id = 0;; ++uncore_max_id) { 7005 7006 sprintf(path_base, "/sys/devices/system/cpu/intel_uncore_frequency/uncore%02d", uncore_max_id); 7007 7008 /* uncore## start at 00 and skips no numbers, so stop upon first missing */ 7009 if (access(path_base, R_OK)) { 7010 uncore_max_id -= 1; 7011 break; 7012 } 7013 } 7014 for (i = uncore_max_id; i >= 0; --i) { 7015 int k, l; 7016 int package_id, domain_id, cluster_id; 7017 char name_buf[16]; 7018 7019 sprintf(path_base, "/sys/devices/system/cpu/intel_uncore_frequency/uncore%02d", i); 7020 7021 if (access(path_base, R_OK)) 7022 err(1, "%s: %s\n", __func__, path_base); 7023 7024 sprintf(path, "%s/package_id", path_base); 7025 package_id = read_sysfs_int(path); 7026 7027 sprintf(path, "%s/domain_id", path_base); 7028 domain_id = read_sysfs_int(path); 7029 7030 sprintf(path, "%s/fabric_cluster_id", path_base); 7031 cluster_id = read_sysfs_int(path); 7032 7033 sprintf(path, "%s/current_freq_khz", path_base); 7034 sprintf(name_buf, "UMHz%d.%d", domain_id, cluster_id); 7035 7036 /* 7037 * Once add_couter() is called, that counter is always read 7038 * and reported -- So it is effectively (enabled & present). 7039 * Only call add_counter() here if legacy BIC_UNCORE_MHZ (UncMHz) 7040 * is (enabled). Since we are in this routine, we 7041 * know we will not probe and set (present) the legacy counter. 7042 * 7043 * This allows "--show/--hide UncMHz" to be effective for 7044 * the clustered MHz counters, as a group. 7045 */ 7046 if BIC_IS_ENABLED 7047 (BIC_UNCORE_MHZ) 7048 add_counter(0, path, name_buf, 0, SCOPE_PACKAGE, COUNTER_K2M, FORMAT_AVERAGE, 0, package_id); 7049 7050 if (quiet) 7051 continue; 7052 7053 sprintf(path, "%s/min_freq_khz", path_base); 7054 k = read_sysfs_int(path); 7055 sprintf(path, "%s/max_freq_khz", path_base); 7056 l = read_sysfs_int(path); 7057 fprintf(outf, "Uncore Frequency package%d domain%d cluster%d: %d - %d MHz ", package_id, domain_id, cluster_id, k / 1000, l / 1000); 7058 7059 sprintf(path, "%s/initial_min_freq_khz", path_base); 7060 k = read_sysfs_int(path); 7061 sprintf(path, "%s/initial_max_freq_khz", path_base); 7062 l = read_sysfs_int(path); 7063 fprintf(outf, "(%d - %d MHz)", k / 1000, l / 1000); 7064 7065 sprintf(path, "%s/current_freq_khz", path_base); 7066 k = read_sysfs_int(path); 7067 fprintf(outf, " %d MHz\n", k / 1000); 7068 } 7069} 7070 7071static void probe_intel_uncore_frequency(void) 7072{ 7073 if (!genuine_intel) 7074 return; 7075 7076 if (access("/sys/devices/system/cpu/intel_uncore_frequency/uncore00", R_OK) == 0) 7077 probe_intel_uncore_frequency_cluster(); 7078 else 7079 probe_intel_uncore_frequency_legacy(); 7080} 7081 7082static void set_graphics_fp(char *path, int idx) 7083{ 7084 if (!access(path, R_OK)) 7085 gfx_info[idx].fp = fopen_or_die(path, "r"); 7086} 7087 7088/* Enlarge this if there are /sys/class/drm/card2 ... */ 7089#define GFX_MAX_CARDS 2 7090 7091static void probe_graphics(void) 7092{ 7093 char path[PATH_MAX]; 7094 int i; 7095 7096 /* Xe graphics sysfs knobs */ 7097 if (!access("/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms", R_OK)) { 7098 FILE *fp; 7099 char buf[8]; 7100 bool gt0_is_gt; 7101 7102 fp = fopen("/sys/class/drm/card0/device/tile0/gt0/gtidle/name", "r"); 7103 if (!fp) 7104 goto next; 7105 7106 if (!fread(buf, sizeof(char), 7, fp)) { 7107 fclose(fp); 7108 goto next; 7109 } 7110 fclose(fp); 7111 7112 if (!strncmp(buf, "gt0-rc", strlen("gt0-rc"))) 7113 gt0_is_gt = true; 7114 else if (!strncmp(buf, "gt0-mc", strlen("gt0-mc"))) 7115 gt0_is_gt = false; 7116 else 7117 goto next; 7118 7119 set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms", gt0_is_gt ? GFX_rc6 : SAM_mc6); 7120 7121 set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq", gt0_is_gt ? GFX_MHz : SAM_MHz); 7122 7123 set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/freq0/act_freq", gt0_is_gt ? GFX_ACTMHz : SAM_ACTMHz); 7124 7125 set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms", gt0_is_gt ? SAM_mc6 : GFX_rc6); 7126 7127 set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq", gt0_is_gt ? SAM_MHz : GFX_MHz); 7128 7129 set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/freq0/act_freq", gt0_is_gt ? SAM_ACTMHz : GFX_ACTMHz); 7130 7131 goto end; 7132 } 7133 7134next: 7135 /* New i915 graphics sysfs knobs */ 7136 for (i = 0; i < GFX_MAX_CARDS; i++) { 7137 snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rc6_residency_ms", i); 7138 if (!access(path, R_OK)) 7139 break; 7140 } 7141 7142 if (i == GFX_MAX_CARDS) 7143 goto legacy_i915; 7144 7145 snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rc6_residency_ms", i); 7146 set_graphics_fp(path, GFX_rc6); 7147 7148 snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rps_cur_freq_mhz", i); 7149 set_graphics_fp(path, GFX_MHz); 7150 7151 snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rps_act_freq_mhz", i); 7152 set_graphics_fp(path, GFX_ACTMHz); 7153 7154 snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt1/rc6_residency_ms", i); 7155 set_graphics_fp(path, SAM_mc6); 7156 7157 snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt1/rps_cur_freq_mhz", i); 7158 set_graphics_fp(path, SAM_MHz); 7159 7160 snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt1/rps_act_freq_mhz", i); 7161 set_graphics_fp(path, SAM_ACTMHz); 7162 7163 goto end; 7164 7165legacy_i915: 7166 /* Fall back to traditional i915 graphics sysfs knobs */ 7167 set_graphics_fp("/sys/class/drm/card0/power/rc6_residency_ms", GFX_rc6); 7168 7169 set_graphics_fp("/sys/class/drm/card0/gt_cur_freq_mhz", GFX_MHz); 7170 if (!gfx_info[GFX_MHz].fp) 7171 set_graphics_fp("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", GFX_MHz); 7172 7173 set_graphics_fp("/sys/class/drm/card0/gt_act_freq_mhz", GFX_ACTMHz); 7174 if (!gfx_info[GFX_ACTMHz].fp) 7175 set_graphics_fp("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", GFX_ACTMHz); 7176 7177end: 7178 if (gfx_info[GFX_rc6].fp) 7179 BIC_PRESENT(BIC_GFX_rc6); 7180 if (gfx_info[GFX_MHz].fp) 7181 BIC_PRESENT(BIC_GFXMHz); 7182 if (gfx_info[GFX_ACTMHz].fp) 7183 BIC_PRESENT(BIC_GFXACTMHz); 7184 if (gfx_info[SAM_mc6].fp) 7185 BIC_PRESENT(BIC_SAM_mc6); 7186 if (gfx_info[SAM_MHz].fp) 7187 BIC_PRESENT(BIC_SAMMHz); 7188 if (gfx_info[SAM_ACTMHz].fp) 7189 BIC_PRESENT(BIC_SAMACTMHz); 7190} 7191 7192static void dump_sysfs_cstate_config(void) 7193{ 7194 char path[64]; 7195 char name_buf[16]; 7196 char desc[64]; 7197 FILE *input; 7198 int state; 7199 char *sp; 7200 7201 if (access("/sys/devices/system/cpu/cpuidle", R_OK)) { 7202 fprintf(outf, "cpuidle not loaded\n"); 7203 return; 7204 } 7205 7206 dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_driver"); 7207 dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_governor"); 7208 dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_governor_ro"); 7209 7210 for (state = 0; state < 10; ++state) { 7211 7212 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", base_cpu, state); 7213 input = fopen(path, "r"); 7214 if (input == NULL) 7215 continue; 7216 if (!fgets(name_buf, sizeof(name_buf), input)) 7217 err(1, "%s: failed to read file", path); 7218 7219 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */ 7220 sp = strchr(name_buf, '-'); 7221 if (!sp) 7222 sp = strchrnul(name_buf, '\n'); 7223 *sp = '\0'; 7224 fclose(input); 7225 7226 remove_underbar(name_buf); 7227 7228 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/desc", base_cpu, state); 7229 input = fopen(path, "r"); 7230 if (input == NULL) 7231 continue; 7232 if (!fgets(desc, sizeof(desc), input)) 7233 err(1, "%s: failed to read file", path); 7234 7235 fprintf(outf, "cpu%d: %s: %s", base_cpu, name_buf, desc); 7236 fclose(input); 7237 } 7238} 7239 7240static void dump_sysfs_pstate_config(void) 7241{ 7242 char path[64]; 7243 char driver_buf[64]; 7244 char governor_buf[64]; 7245 FILE *input; 7246 int turbo; 7247 7248 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_driver", base_cpu); 7249 input = fopen(path, "r"); 7250 if (input == NULL) { 7251 fprintf(outf, "NSFOD %s\n", path); 7252 return; 7253 } 7254 if (!fgets(driver_buf, sizeof(driver_buf), input)) 7255 err(1, "%s: failed to read file", path); 7256 fclose(input); 7257 7258 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor", base_cpu); 7259 input = fopen(path, "r"); 7260 if (input == NULL) { 7261 fprintf(outf, "NSFOD %s\n", path); 7262 return; 7263 } 7264 if (!fgets(governor_buf, sizeof(governor_buf), input)) 7265 err(1, "%s: failed to read file", path); 7266 fclose(input); 7267 7268 fprintf(outf, "cpu%d: cpufreq driver: %s", base_cpu, driver_buf); 7269 fprintf(outf, "cpu%d: cpufreq governor: %s", base_cpu, governor_buf); 7270 7271 sprintf(path, "/sys/devices/system/cpu/cpufreq/boost"); 7272 input = fopen(path, "r"); 7273 if (input != NULL) { 7274 if (fscanf(input, "%d", &turbo) != 1) 7275 err(1, "%s: failed to parse number from file", path); 7276 fprintf(outf, "cpufreq boost: %d\n", turbo); 7277 fclose(input); 7278 } 7279 7280 sprintf(path, "/sys/devices/system/cpu/intel_pstate/no_turbo"); 7281 input = fopen(path, "r"); 7282 if (input != NULL) { 7283 if (fscanf(input, "%d", &turbo) != 1) 7284 err(1, "%s: failed to parse number from file", path); 7285 fprintf(outf, "cpufreq intel_pstate no_turbo: %d\n", turbo); 7286 fclose(input); 7287 } 7288} 7289 7290/* 7291 * print_epb() 7292 * Decode the ENERGY_PERF_BIAS MSR 7293 */ 7294int print_epb(PER_THREAD_PARAMS) 7295{ 7296 char *epb_string; 7297 int cpu, epb; 7298 7299 UNUSED(c); 7300 UNUSED(p); 7301 7302 if (!has_epb) 7303 return 0; 7304 7305 cpu = t->cpu_id; 7306 7307 /* EPB is per-package */ 7308 if (!is_cpu_first_thread_in_package(t, c, p)) 7309 return 0; 7310 7311 if (cpu_migrate(cpu)) { 7312 fprintf(outf, "print_epb: Could not migrate to CPU %d\n", cpu); 7313 return -1; 7314 } 7315 7316 epb = get_epb(cpu); 7317 if (epb < 0) 7318 return 0; 7319 7320 switch (epb) { 7321 case ENERGY_PERF_BIAS_PERFORMANCE: 7322 epb_string = "performance"; 7323 break; 7324 case ENERGY_PERF_BIAS_NORMAL: 7325 epb_string = "balanced"; 7326 break; 7327 case ENERGY_PERF_BIAS_POWERSAVE: 7328 epb_string = "powersave"; 7329 break; 7330 default: 7331 epb_string = "custom"; 7332 break; 7333 } 7334 fprintf(outf, "cpu%d: EPB: %d (%s)\n", cpu, epb, epb_string); 7335 7336 return 0; 7337} 7338 7339/* 7340 * print_hwp() 7341 * Decode the MSR_HWP_CAPABILITIES 7342 */ 7343int print_hwp(PER_THREAD_PARAMS) 7344{ 7345 unsigned long long msr; 7346 int cpu; 7347 7348 UNUSED(c); 7349 UNUSED(p); 7350 7351 if (no_msr) 7352 return 0; 7353 7354 if (!has_hwp) 7355 return 0; 7356 7357 cpu = t->cpu_id; 7358 7359 /* MSR_HWP_CAPABILITIES is per-package */ 7360 if (!is_cpu_first_thread_in_package(t, c, p)) 7361 return 0; 7362 7363 if (cpu_migrate(cpu)) { 7364 fprintf(outf, "print_hwp: Could not migrate to CPU %d\n", cpu); 7365 return -1; 7366 } 7367 7368 if (get_msr(cpu, MSR_PM_ENABLE, &msr)) 7369 return 0; 7370 7371 fprintf(outf, "cpu%d: MSR_PM_ENABLE: 0x%08llx (%sHWP)\n", cpu, msr, (msr & (1 << 0)) ? "" : "No-"); 7372 7373 /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */ 7374 if ((msr & (1 << 0)) == 0) 7375 return 0; 7376 7377 if (get_msr(cpu, MSR_HWP_CAPABILITIES, &msr)) 7378 return 0; 7379 7380 fprintf(outf, "cpu%d: MSR_HWP_CAPABILITIES: 0x%08llx " 7381 "(high %d guar %d eff %d low %d)\n", 7382 cpu, msr, 7383 (unsigned int)HWP_HIGHEST_PERF(msr), 7384 (unsigned int)HWP_GUARANTEED_PERF(msr), (unsigned int)HWP_MOSTEFFICIENT_PERF(msr), (unsigned int)HWP_LOWEST_PERF(msr)); 7385 7386 if (get_msr(cpu, MSR_HWP_REQUEST, &msr)) 7387 return 0; 7388 7389 fprintf(outf, "cpu%d: MSR_HWP_REQUEST: 0x%08llx " 7390 "(min %d max %d des %d epp 0x%x window 0x%x pkg 0x%x)\n", 7391 cpu, msr, 7392 (unsigned int)(((msr) >> 0) & 0xff), 7393 (unsigned int)(((msr) >> 8) & 0xff), 7394 (unsigned int)(((msr) >> 16) & 0xff), 7395 (unsigned int)(((msr) >> 24) & 0xff), (unsigned int)(((msr) >> 32) & 0xff3), (unsigned int)(((msr) >> 42) & 0x1)); 7396 7397 if (has_hwp_pkg) { 7398 if (get_msr(cpu, MSR_HWP_REQUEST_PKG, &msr)) 7399 return 0; 7400 7401 fprintf(outf, "cpu%d: MSR_HWP_REQUEST_PKG: 0x%08llx " 7402 "(min %d max %d des %d epp 0x%x window 0x%x)\n", 7403 cpu, msr, 7404 (unsigned int)(((msr) >> 0) & 0xff), 7405 (unsigned int)(((msr) >> 8) & 0xff), 7406 (unsigned int)(((msr) >> 16) & 0xff), (unsigned int)(((msr) >> 24) & 0xff), (unsigned int)(((msr) >> 32) & 0xff3)); 7407 } 7408 if (has_hwp_notify) { 7409 if (get_msr(cpu, MSR_HWP_INTERRUPT, &msr)) 7410 return 0; 7411 7412 fprintf(outf, "cpu%d: MSR_HWP_INTERRUPT: 0x%08llx " 7413 "(%s_Guaranteed_Perf_Change, %s_Excursion_Min)\n", cpu, msr, ((msr) & 0x1) ? "EN" : "Dis", ((msr) & 0x2) ? "EN" : "Dis"); 7414 } 7415 if (get_msr(cpu, MSR_HWP_STATUS, &msr)) 7416 return 0; 7417 7418 fprintf(outf, "cpu%d: MSR_HWP_STATUS: 0x%08llx " 7419 "(%sGuaranteed_Perf_Change, %sExcursion_Min)\n", cpu, msr, ((msr) & 0x1) ? "" : "No-", ((msr) & 0x4) ? "" : "No-"); 7420 7421 return 0; 7422} 7423 7424/* 7425 * print_perf_limit() 7426 */ 7427int print_perf_limit(PER_THREAD_PARAMS) 7428{ 7429 unsigned long long msr; 7430 int cpu; 7431 7432 UNUSED(c); 7433 UNUSED(p); 7434 7435 if (no_msr) 7436 return 0; 7437 7438 cpu = t->cpu_id; 7439 7440 /* per-package */ 7441 if (!is_cpu_first_thread_in_package(t, c, p)) 7442 return 0; 7443 7444 if (cpu_migrate(cpu)) { 7445 fprintf(outf, "print_perf_limit: Could not migrate to CPU %d\n", cpu); 7446 return -1; 7447 } 7448 7449 if (platform->plr_msrs & PLR_CORE) { 7450 get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr); 7451 fprintf(outf, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); 7452 fprintf(outf, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)", 7453 (msr & 1 << 15) ? "bit15, " : "", 7454 (msr & 1 << 14) ? "bit14, " : "", 7455 (msr & 1 << 13) ? "Transitions, " : "", 7456 (msr & 1 << 12) ? "MultiCoreTurbo, " : "", 7457 (msr & 1 << 11) ? "PkgPwrL2, " : "", 7458 (msr & 1 << 10) ? "PkgPwrL1, " : "", 7459 (msr & 1 << 9) ? "CorePwr, " : "", 7460 (msr & 1 << 8) ? "Amps, " : "", 7461 (msr & 1 << 6) ? "VR-Therm, " : "", 7462 (msr & 1 << 5) ? "Auto-HWP, " : "", 7463 (msr & 1 << 4) ? "Graphics, " : "", 7464 (msr & 1 << 2) ? "bit2, " : "", (msr & 1 << 1) ? "ThermStatus, " : "", (msr & 1 << 0) ? "PROCHOT, " : ""); 7465 fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n", 7466 (msr & 1 << 31) ? "bit31, " : "", 7467 (msr & 1 << 30) ? "bit30, " : "", 7468 (msr & 1 << 29) ? "Transitions, " : "", 7469 (msr & 1 << 28) ? "MultiCoreTurbo, " : "", 7470 (msr & 1 << 27) ? "PkgPwrL2, " : "", 7471 (msr & 1 << 26) ? "PkgPwrL1, " : "", 7472 (msr & 1 << 25) ? "CorePwr, " : "", 7473 (msr & 1 << 24) ? "Amps, " : "", 7474 (msr & 1 << 22) ? "VR-Therm, " : "", 7475 (msr & 1 << 21) ? "Auto-HWP, " : "", 7476 (msr & 1 << 20) ? "Graphics, " : "", 7477 (msr & 1 << 18) ? "bit18, " : "", (msr & 1 << 17) ? "ThermStatus, " : "", (msr & 1 << 16) ? "PROCHOT, " : ""); 7478 7479 } 7480 if (platform->plr_msrs & PLR_GFX) { 7481 get_msr(cpu, MSR_GFX_PERF_LIMIT_REASONS, &msr); 7482 fprintf(outf, "cpu%d: MSR_GFX_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); 7483 fprintf(outf, " (Active: %s%s%s%s%s%s%s%s)", 7484 (msr & 1 << 0) ? "PROCHOT, " : "", 7485 (msr & 1 << 1) ? "ThermStatus, " : "", 7486 (msr & 1 << 4) ? "Graphics, " : "", 7487 (msr & 1 << 6) ? "VR-Therm, " : "", 7488 (msr & 1 << 8) ? "Amps, " : "", 7489 (msr & 1 << 9) ? "GFXPwr, " : "", (msr & 1 << 10) ? "PkgPwrL1, " : "", (msr & 1 << 11) ? "PkgPwrL2, " : ""); 7490 fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s)\n", 7491 (msr & 1 << 16) ? "PROCHOT, " : "", 7492 (msr & 1 << 17) ? "ThermStatus, " : "", 7493 (msr & 1 << 20) ? "Graphics, " : "", 7494 (msr & 1 << 22) ? "VR-Therm, " : "", 7495 (msr & 1 << 24) ? "Amps, " : "", 7496 (msr & 1 << 25) ? "GFXPwr, " : "", (msr & 1 << 26) ? "PkgPwrL1, " : "", (msr & 1 << 27) ? "PkgPwrL2, " : ""); 7497 } 7498 if (platform->plr_msrs & PLR_RING) { 7499 get_msr(cpu, MSR_RING_PERF_LIMIT_REASONS, &msr); 7500 fprintf(outf, "cpu%d: MSR_RING_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); 7501 fprintf(outf, " (Active: %s%s%s%s%s%s)", 7502 (msr & 1 << 0) ? "PROCHOT, " : "", 7503 (msr & 1 << 1) ? "ThermStatus, " : "", 7504 (msr & 1 << 6) ? "VR-Therm, " : "", 7505 (msr & 1 << 8) ? "Amps, " : "", (msr & 1 << 10) ? "PkgPwrL1, " : "", (msr & 1 << 11) ? "PkgPwrL2, " : ""); 7506 fprintf(outf, " (Logged: %s%s%s%s%s%s)\n", 7507 (msr & 1 << 16) ? "PROCHOT, " : "", 7508 (msr & 1 << 17) ? "ThermStatus, " : "", 7509 (msr & 1 << 22) ? "VR-Therm, " : "", 7510 (msr & 1 << 24) ? "Amps, " : "", (msr & 1 << 26) ? "PkgPwrL1, " : "", (msr & 1 << 27) ? "PkgPwrL2, " : ""); 7511 } 7512 return 0; 7513} 7514 7515#define RAPL_POWER_GRANULARITY 0x7FFF /* 15 bit power granularity */ 7516#define RAPL_TIME_GRANULARITY 0x3F /* 6 bit time granularity */ 7517 7518double get_quirk_tdp(void) 7519{ 7520 if (platform->rapl_quirk_tdp) 7521 return platform->rapl_quirk_tdp; 7522 7523 return 135.0; 7524} 7525 7526double get_tdp_intel(void) 7527{ 7528 unsigned long long msr; 7529 7530 if (valid_rapl_msrs & RAPL_PKG_POWER_INFO) 7531 if (!get_msr(base_cpu, MSR_PKG_POWER_INFO, &msr)) 7532 return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units; 7533 return get_quirk_tdp(); 7534} 7535 7536double get_tdp_amd(void) 7537{ 7538 return get_quirk_tdp(); 7539} 7540 7541void rapl_probe_intel(void) 7542{ 7543 unsigned long long msr; 7544 unsigned int time_unit; 7545 double tdp; 7546 7547 if (rapl_joules) { 7548 CLR_BIC(BIC_SysWatt, &bic_enabled); 7549 CLR_BIC(BIC_PkgWatt, &bic_enabled); 7550 CLR_BIC(BIC_CorWatt, &bic_enabled); 7551 CLR_BIC(BIC_RAMWatt, &bic_enabled); 7552 CLR_BIC(BIC_GFXWatt, &bic_enabled); 7553 } else { 7554 CLR_BIC(BIC_Sys_J, &bic_enabled); 7555 CLR_BIC(BIC_Pkg_J, &bic_enabled); 7556 CLR_BIC(BIC_Cor_J, &bic_enabled); 7557 CLR_BIC(BIC_RAM_J, &bic_enabled); 7558 CLR_BIC(BIC_GFX_J, &bic_enabled); 7559 } 7560 7561 if (!valid_rapl_msrs || no_msr) 7562 return; 7563 7564 if (!(valid_rapl_msrs & RAPL_PKG_PERF_STATUS)) 7565 CLR_BIC(BIC_PKG__, &bic_enabled); 7566 if (!(valid_rapl_msrs & RAPL_DRAM_PERF_STATUS)) 7567 CLR_BIC(BIC_RAM__, &bic_enabled); 7568 7569 /* units on package 0, verify later other packages match */ 7570 if (get_msr(base_cpu, MSR_RAPL_POWER_UNIT, &msr)) 7571 return; 7572 7573 rapl_power_units = 1.0 / (1 << (msr & 0xF)); 7574 if (platform->has_rapl_divisor) 7575 rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000; 7576 else 7577 rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F)); 7578 7579 if (platform->has_fixed_rapl_unit) 7580 rapl_dram_energy_units = (15.3 / 1000000); 7581 else 7582 rapl_dram_energy_units = rapl_energy_units; 7583 7584 if (platform->has_fixed_rapl_psys_unit) 7585 rapl_psys_energy_units = 1.0; 7586 else 7587 rapl_psys_energy_units = rapl_energy_units; 7588 7589 time_unit = msr >> 16 & 0xF; 7590 if (time_unit == 0) 7591 time_unit = 0xA; 7592 7593 rapl_time_units = 1.0 / (1 << (time_unit)); 7594 7595 tdp = get_tdp_intel(); 7596 7597 rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp; 7598 if (!quiet) 7599 fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp); 7600} 7601 7602void rapl_probe_amd(void) 7603{ 7604 unsigned long long msr; 7605 double tdp; 7606 7607 if (rapl_joules) { 7608 CLR_BIC(BIC_SysWatt, &bic_enabled); 7609 CLR_BIC(BIC_CorWatt, &bic_enabled); 7610 } else { 7611 CLR_BIC(BIC_Pkg_J, &bic_enabled); 7612 CLR_BIC(BIC_Cor_J, &bic_enabled); 7613 } 7614 7615 if (!valid_rapl_msrs || no_msr) 7616 return; 7617 7618 if (get_msr(base_cpu, MSR_RAPL_PWR_UNIT, &msr)) 7619 return; 7620 7621 rapl_time_units = ldexp(1.0, -(msr >> 16 & 0xf)); 7622 rapl_energy_units = ldexp(1.0, -(msr >> 8 & 0x1f)); 7623 rapl_power_units = ldexp(1.0, -(msr & 0xf)); 7624 7625 tdp = get_tdp_amd(); 7626 7627 rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp; 7628 if (!quiet) 7629 fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp); 7630} 7631 7632void print_power_limit_msr(int cpu, unsigned long long msr, char *label) 7633{ 7634 fprintf(outf, "cpu%d: %s: %sabled (%0.3f Watts, %f sec, clamp %sabled)\n", 7635 cpu, label, 7636 ((msr >> 15) & 1) ? "EN" : "DIS", 7637 ((msr >> 0) & 0x7FFF) * rapl_power_units, 7638 (1.0 + (((msr >> 22) & 0x3) / 4.0)) * (1 << ((msr >> 17) & 0x1F)) * rapl_time_units, (((msr >> 16) & 1) ? "EN" : "DIS")); 7639 7640 return; 7641} 7642 7643static int fread_int(char *path, int *val) 7644{ 7645 FILE *filep; 7646 int ret; 7647 7648 filep = fopen(path, "r"); 7649 if (!filep) 7650 return -1; 7651 7652 ret = fscanf(filep, "%d", val); 7653 fclose(filep); 7654 return ret; 7655} 7656 7657static int fread_ull(char *path, unsigned long long *val) 7658{ 7659 FILE *filep; 7660 int ret; 7661 7662 filep = fopen(path, "r"); 7663 if (!filep) 7664 return -1; 7665 7666 ret = fscanf(filep, "%llu", val); 7667 fclose(filep); 7668 return ret; 7669} 7670 7671static int fread_str(char *path, char *buf, int size) 7672{ 7673 FILE *filep; 7674 int ret; 7675 char *cp; 7676 7677 filep = fopen(path, "r"); 7678 if (!filep) 7679 return -1; 7680 7681 ret = fread(buf, 1, size, filep); 7682 fclose(filep); 7683 7684 /* replace '\n' with '\0' */ 7685 cp = strchr(buf, '\n'); 7686 if (cp != NULL) 7687 *cp = '\0'; 7688 7689 return ret; 7690} 7691 7692#define PATH_RAPL_SYSFS "/sys/class/powercap" 7693 7694static int dump_one_domain(char *domain_path) 7695{ 7696 char path[PATH_MAX]; 7697 char str[PATH_MAX]; 7698 unsigned long long val; 7699 int constraint; 7700 int enable; 7701 int ret; 7702 7703 snprintf(path, PATH_MAX, "%s/name", domain_path); 7704 ret = fread_str(path, str, PATH_MAX); 7705 if (ret <= 0) 7706 return -1; 7707 7708 fprintf(outf, "%s: %s", domain_path + strlen(PATH_RAPL_SYSFS) + 1, str); 7709 7710 snprintf(path, PATH_MAX, "%s/enabled", domain_path); 7711 ret = fread_int(path, &enable); 7712 if (ret <= 0) 7713 return -1; 7714 7715 if (!enable) { 7716 fputs(" disabled\n", outf); 7717 return 0; 7718 } 7719 7720 for (constraint = 0;; constraint++) { 7721 snprintf(path, PATH_MAX, "%s/constraint_%d_time_window_us", domain_path, constraint); 7722 ret = fread_ull(path, &val); 7723 if (ret <= 0) 7724 break; 7725 7726 if (val > 1000000) 7727 fprintf(outf, " %0.1fs", (double)val / 1000000); 7728 else if (val > 1000) 7729 fprintf(outf, " %0.1fms", (double)val / 1000); 7730 else 7731 fprintf(outf, " %0.1fus", (double)val); 7732 7733 snprintf(path, PATH_MAX, "%s/constraint_%d_power_limit_uw", domain_path, constraint); 7734 ret = fread_ull(path, &val); 7735 if (ret > 0 && val) 7736 fprintf(outf, ":%lluW", val / 1000000); 7737 7738 snprintf(path, PATH_MAX, "%s/constraint_%d_max_power_uw", domain_path, constraint); 7739 ret = fread_ull(path, &val); 7740 if (ret > 0 && val) 7741 fprintf(outf, ",max:%lluW", val / 1000000); 7742 } 7743 fputc('\n', outf); 7744 7745 return 0; 7746} 7747 7748static int print_rapl_sysfs(void) 7749{ 7750 DIR *dir, *cdir; 7751 struct dirent *entry, *centry; 7752 char path[PATH_MAX]; 7753 char str[PATH_MAX]; 7754 7755 if ((dir = opendir(PATH_RAPL_SYSFS)) == NULL) { 7756 warn("open %s failed", PATH_RAPL_SYSFS); 7757 return 1; 7758 } 7759 7760 while ((entry = readdir(dir)) != NULL) { 7761 if (strlen(entry->d_name) > 100) 7762 continue; 7763 7764 if (strncmp(entry->d_name, "intel-rapl", strlen("intel-rapl"))) 7765 continue; 7766 7767 snprintf(path, PATH_MAX, "%s/%s/name", PATH_RAPL_SYSFS, entry->d_name); 7768 7769 /* Parse top level domains first, including package and psys */ 7770 fread_str(path, str, PATH_MAX); 7771 if (strncmp(str, "package", strlen("package")) && strncmp(str, "psys", strlen("psys"))) 7772 continue; 7773 7774 snprintf(path, PATH_MAX, "%s/%s", PATH_RAPL_SYSFS, entry->d_name); 7775 if ((cdir = opendir(path)) == NULL) { 7776 perror("opendir() error"); 7777 return 1; 7778 } 7779 7780 dump_one_domain(path); 7781 7782 while ((centry = readdir(cdir)) != NULL) { 7783 if (strncmp(centry->d_name, "intel-rapl", strlen("intel-rapl"))) 7784 continue; 7785 snprintf(path, PATH_MAX, "%s/%s/%s", PATH_RAPL_SYSFS, entry->d_name, centry->d_name); 7786 dump_one_domain(path); 7787 } 7788 closedir(cdir); 7789 } 7790 7791 closedir(dir); 7792 return 0; 7793} 7794 7795int print_rapl(PER_THREAD_PARAMS) 7796{ 7797 unsigned long long msr; 7798 const char *msr_name; 7799 int cpu; 7800 7801 UNUSED(c); 7802 UNUSED(p); 7803 7804 if (!valid_rapl_msrs) 7805 return 0; 7806 7807 /* RAPL counters are per package, so print only for 1st thread/package */ 7808 if (!is_cpu_first_thread_in_package(t, c, p)) 7809 return 0; 7810 7811 cpu = t->cpu_id; 7812 if (cpu_migrate(cpu)) { 7813 fprintf(outf, "print_rapl: Could not migrate to CPU %d\n", cpu); 7814 return -1; 7815 } 7816 7817 if (valid_rapl_msrs & RAPL_AMD_F17H) { 7818 msr_name = "MSR_RAPL_PWR_UNIT"; 7819 if (get_msr(cpu, MSR_RAPL_PWR_UNIT, &msr)) 7820 return -1; 7821 } else { 7822 msr_name = "MSR_RAPL_POWER_UNIT"; 7823 if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr)) 7824 return -1; 7825 } 7826 7827 fprintf(outf, "cpu%d: %s: 0x%08llx (%f Watts, %f Joules, %f sec.)\n", cpu, msr_name, msr, 7828 rapl_power_units, rapl_energy_units, rapl_time_units); 7829 7830 if (valid_rapl_msrs & RAPL_PKG_POWER_INFO) { 7831 7832 if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr)) 7833 return -5; 7834 7835 fprintf(outf, "cpu%d: MSR_PKG_POWER_INFO: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n", 7836 cpu, msr, 7837 ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units, 7838 ((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units, 7839 ((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units, ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units); 7840 7841 } 7842 if (valid_rapl_msrs & RAPL_PKG) { 7843 7844 if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr)) 7845 return -9; 7846 7847 fprintf(outf, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n", cpu, msr, (msr >> 63) & 1 ? "" : "UN"); 7848 7849 print_power_limit_msr(cpu, msr, "PKG Limit #1"); 7850 fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%0.3f Watts, %f* sec, clamp %sabled)\n", 7851 cpu, 7852 ((msr >> 47) & 1) ? "EN" : "DIS", 7853 ((msr >> 32) & 0x7FFF) * rapl_power_units, 7854 (1.0 + (((msr >> 54) & 0x3) / 4.0)) * (1 << ((msr >> 49) & 0x1F)) * rapl_time_units, ((msr >> 48) & 1) ? "EN" : "DIS"); 7855 7856 if (get_msr(cpu, MSR_VR_CURRENT_CONFIG, &msr)) 7857 return -9; 7858 7859 fprintf(outf, "cpu%d: MSR_VR_CURRENT_CONFIG: 0x%08llx\n", cpu, msr); 7860 fprintf(outf, "cpu%d: PKG Limit #4: %f Watts (%slocked)\n", 7861 cpu, ((msr >> 0) & 0x1FFF) * rapl_power_units, (msr >> 31) & 1 ? "" : "UN"); 7862 } 7863 7864 if (valid_rapl_msrs & RAPL_DRAM_POWER_INFO) { 7865 if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr)) 7866 return -6; 7867 7868 fprintf(outf, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n", 7869 cpu, msr, 7870 ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units, 7871 ((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units, 7872 ((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units, ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units); 7873 } 7874 if (valid_rapl_msrs & RAPL_DRAM) { 7875 if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr)) 7876 return -9; 7877 fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n", cpu, msr, (msr >> 31) & 1 ? "" : "UN"); 7878 7879 print_power_limit_msr(cpu, msr, "DRAM Limit"); 7880 } 7881 if (valid_rapl_msrs & RAPL_CORE_POLICY) { 7882 if (get_msr(cpu, MSR_PP0_POLICY, &msr)) 7883 return -7; 7884 7885 fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF); 7886 } 7887 if (valid_rapl_msrs & RAPL_CORE_POWER_LIMIT) { 7888 if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr)) 7889 return -9; 7890 fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n", cpu, msr, (msr >> 31) & 1 ? "" : "UN"); 7891 print_power_limit_msr(cpu, msr, "Cores Limit"); 7892 } 7893 if (valid_rapl_msrs & RAPL_GFX) { 7894 if (get_msr(cpu, MSR_PP1_POLICY, &msr)) 7895 return -8; 7896 7897 fprintf(outf, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF); 7898 7899 if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr)) 7900 return -9; 7901 fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n", cpu, msr, (msr >> 31) & 1 ? "" : "UN"); 7902 print_power_limit_msr(cpu, msr, "GFX Limit"); 7903 } 7904 return 0; 7905} 7906 7907/* 7908 * probe_rapl_msrs 7909 * 7910 * initialize global valid_rapl_msrs to platform->plat_rapl_msrs 7911 * only if PKG_ENERGY counter is enumerated and reads non-zero 7912 */ 7913void probe_rapl_msrs(void) 7914{ 7915 int ret; 7916 off_t offset; 7917 unsigned long long msr_value; 7918 7919 if (no_msr) 7920 return; 7921 7922 if ((platform->plat_rapl_msrs & (RAPL_PKG | RAPL_AMD_F17H)) == 0) 7923 return; 7924 7925 offset = idx_to_offset(IDX_PKG_ENERGY); 7926 if (offset < 0) 7927 return; 7928 7929 ret = get_msr(base_cpu, offset, &msr_value); 7930 if (ret) { 7931 if (debug) 7932 fprintf(outf, "Can not read RAPL_PKG_ENERGY MSR(0x%llx)\n", (unsigned long long)offset); 7933 return; 7934 } 7935 if (msr_value == 0) { 7936 if (debug) 7937 fprintf(outf, "RAPL_PKG_ENERGY MSR(0x%llx) == ZERO: disabling all RAPL MSRs\n", (unsigned long long)offset); 7938 return; 7939 } 7940 7941 valid_rapl_msrs = platform->plat_rapl_msrs; /* success */ 7942} 7943 7944/* 7945 * probe_rapl() 7946 * 7947 * sets rapl_power_units, rapl_energy_units, rapl_time_units 7948 */ 7949void probe_rapl(void) 7950{ 7951 probe_rapl_msrs(); 7952 7953 if (genuine_intel) 7954 rapl_probe_intel(); 7955 if (authentic_amd || hygon_genuine) 7956 rapl_probe_amd(); 7957 7958 if (quiet) 7959 return; 7960 7961 print_rapl_sysfs(); 7962 7963 if (!valid_rapl_msrs || no_msr) 7964 return; 7965 7966 for_all_cpus(print_rapl, ODD_COUNTERS); 7967} 7968 7969/* 7970 * MSR_IA32_TEMPERATURE_TARGET indicates the temperature where 7971 * the Thermal Control Circuit (TCC) activates. 7972 * This is usually equal to tjMax. 7973 * 7974 * Older processors do not have this MSR, so there we guess, 7975 * but also allow cmdline over-ride with -T. 7976 * 7977 * Several MSR temperature values are in units of degrees-C 7978 * below this value, including the Digital Thermal Sensor (DTS), 7979 * Package Thermal Management Sensor (PTM), and thermal event thresholds. 7980 */ 7981int set_temperature_target(PER_THREAD_PARAMS) 7982{ 7983 unsigned long long msr; 7984 unsigned int tcc_default, tcc_offset; 7985 int cpu; 7986 7987 UNUSED(c); 7988 UNUSED(p); 7989 7990 /* tj_max is used only for dts or ptm */ 7991 if (!(do_dts || do_ptm)) 7992 return 0; 7993 7994 /* this is a per-package concept */ 7995 if (!is_cpu_first_thread_in_package(t, c, p)) 7996 return 0; 7997 7998 cpu = t->cpu_id; 7999 if (cpu_migrate(cpu)) { 8000 fprintf(outf, "Could not migrate to CPU %d\n", cpu); 8001 return -1; 8002 } 8003 8004 if (tj_max_override != 0) { 8005 tj_max = tj_max_override; 8006 fprintf(outf, "cpu%d: Using cmdline TCC Target (%d C)\n", cpu, tj_max); 8007 return 0; 8008 } 8009 8010 /* Temperature Target MSR is Nehalem and newer only */ 8011 if (!platform->has_nhm_msrs || no_msr) 8012 goto guess; 8013 8014 if (get_msr(base_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr)) 8015 goto guess; 8016 8017 tcc_default = (msr >> 16) & 0xFF; 8018 8019 if (!quiet) { 8020 int bits = platform->tcc_offset_bits; 8021 unsigned long long enabled = 0; 8022 8023 if (bits && !get_msr(base_cpu, MSR_PLATFORM_INFO, &enabled)) 8024 enabled = (enabled >> 30) & 1; 8025 8026 if (bits && enabled) { 8027 tcc_offset = (msr >> 24) & GENMASK(bits - 1, 0); 8028 fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C) (%d default - %d offset)\n", 8029 cpu, msr, tcc_default - tcc_offset, tcc_default, tcc_offset); 8030 } else { 8031 fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n", cpu, msr, tcc_default); 8032 } 8033 } 8034 8035 if (!tcc_default) 8036 goto guess; 8037 8038 tj_max = tcc_default; 8039 8040 return 0; 8041 8042guess: 8043 tj_max = TJMAX_DEFAULT; 8044 fprintf(outf, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n", cpu, tj_max); 8045 8046 return 0; 8047} 8048 8049int print_thermal(PER_THREAD_PARAMS) 8050{ 8051 unsigned long long msr; 8052 unsigned int dts, dts2; 8053 int cpu; 8054 8055 UNUSED(c); 8056 UNUSED(p); 8057 8058 if (no_msr) 8059 return 0; 8060 8061 if (!(do_dts || do_ptm)) 8062 return 0; 8063 8064 cpu = t->cpu_id; 8065 8066 /* DTS is per-core, no need to print for each thread */ 8067 if (!is_cpu_first_thread_in_core(t, c)) 8068 return 0; 8069 8070 if (cpu_migrate(cpu)) { 8071 fprintf(outf, "print_thermal: Could not migrate to CPU %d\n", cpu); 8072 return -1; 8073 } 8074 8075 if (do_ptm && is_cpu_first_core_in_package(t, p)) { 8076 if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr)) 8077 return 0; 8078 8079 dts = (msr >> 16) & 0x7F; 8080 fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n", cpu, msr, tj_max - dts); 8081 8082 if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &msr)) 8083 return 0; 8084 8085 dts = (msr >> 16) & 0x7F; 8086 dts2 = (msr >> 8) & 0x7F; 8087 fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", cpu, msr, tj_max - dts, tj_max - dts2); 8088 } 8089 8090 if (do_dts && debug) { 8091 unsigned int resolution; 8092 8093 if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr)) 8094 return 0; 8095 8096 dts = (msr >> 16) & 0x7F; 8097 resolution = (msr >> 27) & 0xF; 8098 fprintf(outf, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n", cpu, msr, tj_max - dts, resolution); 8099 8100 if (get_msr(cpu, MSR_IA32_THERM_INTERRUPT, &msr)) 8101 return 0; 8102 8103 dts = (msr >> 16) & 0x7F; 8104 dts2 = (msr >> 8) & 0x7F; 8105 fprintf(outf, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", cpu, msr, tj_max - dts, tj_max - dts2); 8106 } 8107 8108 return 0; 8109} 8110 8111void probe_thermal(void) 8112{ 8113 if (!access("/sys/devices/system/cpu/cpu0/thermal_throttle/core_throttle_count", R_OK)) 8114 BIC_PRESENT(BIC_CORE_THROT_CNT); 8115 else 8116 BIC_NOT_PRESENT(BIC_CORE_THROT_CNT); 8117 8118 for_all_cpus(set_temperature_target, ODD_COUNTERS); 8119 8120 if (quiet) 8121 return; 8122 8123 for_all_cpus(print_thermal, ODD_COUNTERS); 8124} 8125 8126int get_cpu_type(PER_THREAD_PARAMS) 8127{ 8128 unsigned int eax, ebx, ecx, edx; 8129 8130 UNUSED(c); 8131 UNUSED(p); 8132 8133 if (!genuine_intel) 8134 return 0; 8135 8136 if (cpu_migrate(t->cpu_id)) { 8137 fprintf(outf, "Could not migrate to CPU %d\n", t->cpu_id); 8138 return -1; 8139 } 8140 8141 if (max_level < 0x1a) 8142 return 0; 8143 8144 __cpuid(0x1a, eax, ebx, ecx, edx); 8145 eax = (eax >> 24) & 0xFF; 8146 if (eax == 0x20) 8147 t->is_atom = true; 8148 return 0; 8149} 8150 8151void decode_feature_control_msr(void) 8152{ 8153 unsigned long long msr; 8154 8155 if (no_msr) 8156 return; 8157 8158 if (!get_msr(base_cpu, MSR_IA32_FEAT_CTL, &msr)) 8159 fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n", 8160 base_cpu, msr, msr & FEAT_CTL_LOCKED ? "" : "UN-", msr & (1 << 18) ? "SGX" : ""); 8161} 8162 8163void decode_misc_enable_msr(void) 8164{ 8165 unsigned long long msr; 8166 8167 if (no_msr) 8168 return; 8169 8170 if (!genuine_intel) 8171 return; 8172 8173 if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr)) 8174 fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%sTCC %sEIST %sMWAIT %sPREFETCH %sTURBO)\n", 8175 base_cpu, msr, 8176 msr & MSR_IA32_MISC_ENABLE_TM1 ? "" : "No-", 8177 msr & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP ? "" : "No-", 8178 msr & MSR_IA32_MISC_ENABLE_MWAIT ? "" : "No-", 8179 msr & MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE ? "No-" : "", msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ? "No-" : ""); 8180} 8181 8182void decode_misc_feature_control(void) 8183{ 8184 unsigned long long msr; 8185 8186 if (no_msr) 8187 return; 8188 8189 if (!platform->has_msr_misc_feature_control) 8190 return; 8191 8192 if (!get_msr(base_cpu, MSR_MISC_FEATURE_CONTROL, &msr)) 8193 fprintf(outf, 8194 "cpu%d: MSR_MISC_FEATURE_CONTROL: 0x%08llx (%sL2-Prefetch %sL2-Prefetch-pair %sL1-Prefetch %sL1-IP-Prefetch)\n", 8195 base_cpu, msr, msr & (0 << 0) ? "No-" : "", msr & (1 << 0) ? "No-" : "", 8196 msr & (2 << 0) ? "No-" : "", msr & (3 << 0) ? "No-" : ""); 8197} 8198 8199/* 8200 * Decode MSR_MISC_PWR_MGMT 8201 * 8202 * Decode the bits according to the Nehalem documentation 8203 * bit[0] seems to continue to have same meaning going forward 8204 * bit[1] less so... 8205 */ 8206void decode_misc_pwr_mgmt_msr(void) 8207{ 8208 unsigned long long msr; 8209 8210 if (no_msr) 8211 return; 8212 8213 if (!platform->has_msr_misc_pwr_mgmt) 8214 return; 8215 8216 if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr)) 8217 fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB %sable-OOB)\n", 8218 base_cpu, msr, msr & (1 << 0) ? "DIS" : "EN", msr & (1 << 1) ? "EN" : "DIS", msr & (1 << 8) ? "EN" : "DIS"); 8219} 8220 8221/* 8222 * Decode MSR_CC6_DEMOTION_POLICY_CONFIG, MSR_MC6_DEMOTION_POLICY_CONFIG 8223 * 8224 * This MSRs are present on Silvermont processors, 8225 * Intel Atom processor E3000 series (Baytrail), and friends. 8226 */ 8227void decode_c6_demotion_policy_msr(void) 8228{ 8229 unsigned long long msr; 8230 8231 if (no_msr) 8232 return; 8233 8234 if (!platform->has_msr_c6_demotion_policy_config) 8235 return; 8236 8237 if (!get_msr(base_cpu, MSR_CC6_DEMOTION_POLICY_CONFIG, &msr)) 8238 fprintf(outf, "cpu%d: MSR_CC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-CC6-Demotion)\n", 8239 base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS"); 8240 8241 if (!get_msr(base_cpu, MSR_MC6_DEMOTION_POLICY_CONFIG, &msr)) 8242 fprintf(outf, "cpu%d: MSR_MC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-MC6-Demotion)\n", 8243 base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS"); 8244} 8245 8246void print_dev_latency(void) 8247{ 8248 char *path = "/dev/cpu_dma_latency"; 8249 int fd; 8250 int value; 8251 int retval; 8252 8253 fd = open(path, O_RDONLY); 8254 if (fd < 0) { 8255 if (debug) 8256 warnx("Read %s failed", path); 8257 return; 8258 } 8259 8260 retval = read(fd, (void *)&value, sizeof(int)); 8261 if (retval != sizeof(int)) { 8262 warn("read failed %s", path); 8263 close(fd); 8264 return; 8265 } 8266 fprintf(outf, "/dev/cpu_dma_latency: %d usec (%s)\n", value, value == 2000000000 ? "default" : "constrained"); 8267 8268 close(fd); 8269} 8270 8271static int has_perf_instr_count_access(void) 8272{ 8273 int fd; 8274 8275 if (no_perf) 8276 return 0; 8277 8278 fd = open_perf_counter(base_cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, -1, 0); 8279 if (fd != -1) 8280 close(fd); 8281 8282 if (fd == -1) 8283 warnx("Failed to access %s. Some of the counters may not be available\n" 8284 "\tRun as root to enable them or use %s to disable the access explicitly", "perf instructions retired counter", 8285 "'--hide IPC' or '--no-perf'"); 8286 8287 return (fd != -1); 8288} 8289 8290int add_rapl_perf_counter(int cpu, struct rapl_counter_info_t *rci, const struct rapl_counter_arch_info *cai, double *scale_, enum rapl_unit *unit_) 8291{ 8292 int ret = -1; 8293 8294 if (no_perf) 8295 return -1; 8296 8297 if (!cai->perf_name) 8298 return -1; 8299 8300 const double scale = read_perf_scale(cai->perf_subsys, cai->perf_name); 8301 8302 if (scale == 0.0) 8303 goto end; 8304 8305 const enum rapl_unit unit = read_perf_rapl_unit(cai->perf_subsys, cai->perf_name); 8306 8307 if (unit == RAPL_UNIT_INVALID) 8308 goto end; 8309 8310 const unsigned int rapl_type = read_perf_type(cai->perf_subsys); 8311 const unsigned int rapl_energy_pkg_config = read_perf_config(cai->perf_subsys, cai->perf_name); 8312 8313 ret = open_perf_counter(cpu, rapl_type, rapl_energy_pkg_config, rci->fd_perf, PERF_FORMAT_GROUP); 8314 if (ret == -1) 8315 goto end; 8316 8317 /* If it's the first counter opened, make it a group descriptor */ 8318 if (rci->fd_perf == -1) 8319 rci->fd_perf = ret; 8320 8321 *scale_ = scale; 8322 *unit_ = unit; 8323 8324end: 8325 if (debug >= 2) 8326 fprintf(stderr, "%s: %d (cpu: %d)\n", __func__, ret, cpu); 8327 8328 return ret; 8329} 8330 8331/* 8332 * Linux-perf manages the HW instructions-retired counter 8333 * by enabling when requested, and hiding rollover 8334 */ 8335void linux_perf_init(void) 8336{ 8337 if (access("/proc/sys/kernel/perf_event_paranoid", F_OK)) 8338 return; 8339 8340 if (BIC_IS_ENABLED(BIC_IPC) && cpuid_has_aperf_mperf) { 8341 fd_instr_count_percpu = calloc(topo.max_cpu_num + 1, sizeof(int)); 8342 if (fd_instr_count_percpu == NULL) 8343 err(-1, "calloc fd_instr_count_percpu"); 8344 } 8345 if (BIC_IS_ENABLED(BIC_LLC_RPS)) { 8346 fd_llc_percpu = calloc(topo.max_cpu_num + 1, sizeof(int)); 8347 if (fd_llc_percpu == NULL) 8348 err(-1, "calloc fd_llc_percpu"); 8349 } 8350} 8351 8352void rapl_perf_init(void) 8353{ 8354 const unsigned int num_domains = get_rapl_num_domains(); 8355 bool *domain_visited = calloc(num_domains, sizeof(bool)); 8356 8357 rapl_counter_info_perdomain = calloc(num_domains, sizeof(*rapl_counter_info_perdomain)); 8358 if (rapl_counter_info_perdomain == NULL) 8359 err(-1, "calloc rapl_counter_info_percpu"); 8360 rapl_counter_info_perdomain_size = num_domains; 8361 8362 /* 8363 * Initialize rapl_counter_info_percpu 8364 */ 8365 for (unsigned int domain_id = 0; domain_id < num_domains; ++domain_id) { 8366 struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[domain_id]; 8367 8368 rci->fd_perf = -1; 8369 for (size_t i = 0; i < NUM_RAPL_COUNTERS; ++i) { 8370 rci->data[i] = 0; 8371 rci->source[i] = COUNTER_SOURCE_NONE; 8372 } 8373 } 8374 8375 /* 8376 * Open/probe the counters 8377 * If can't get it via perf, fallback to MSR 8378 */ 8379 for (size_t i = 0; i < ARRAY_SIZE(rapl_counter_arch_infos); ++i) { 8380 8381 const struct rapl_counter_arch_info *const cai = &rapl_counter_arch_infos[i]; 8382 bool has_counter = 0; 8383 double scale; 8384 enum rapl_unit unit; 8385 unsigned int next_domain; 8386 8387 if (!BIC_IS_ENABLED(cai->bic_number)) 8388 continue; 8389 8390 memset(domain_visited, 0, num_domains * sizeof(*domain_visited)); 8391 8392 for (int cpu = 0; cpu < topo.max_cpu_num + 1; ++cpu) { 8393 8394 if (cpu_is_not_allowed(cpu)) 8395 continue; 8396 8397 /* Skip already seen and handled RAPL domains */ 8398 next_domain = get_rapl_domain_id(cpu); 8399 8400 assert(next_domain < num_domains); 8401 8402 if (domain_visited[next_domain]) 8403 continue; 8404 8405 domain_visited[next_domain] = 1; 8406 8407 if ((cai->flags & RAPL_COUNTER_FLAG_PLATFORM_COUNTER) && (cpu != base_cpu)) 8408 continue; 8409 8410 struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[next_domain]; 8411 8412 /* 8413 * rapl_counter_arch_infos[] can have multiple entries describing the same 8414 * counter, due to the difference from different platforms/Vendors. 8415 * E.g. rapl_counter_arch_infos[0] and rapl_counter_arch_infos[1] share the 8416 * same perf_subsys and perf_name, but with different MSR address. 8417 * rapl_counter_arch_infos[0] is for Intel and rapl_counter_arch_infos[1] 8418 * is for AMD. 8419 * In this case, it is possible that multiple rapl_counter_arch_infos[] 8420 * entries are probed just because their perf/msr is duplicate and valid. 8421 * 8422 * Thus need a check to avoid re-probe the same counters. 8423 */ 8424 if (rci->source[cai->rci_index] != COUNTER_SOURCE_NONE) 8425 break; 8426 8427 /* Use perf API for this counter */ 8428 if (add_rapl_perf_counter(cpu, rci, cai, &scale, &unit) != -1) { 8429 rci->source[cai->rci_index] = COUNTER_SOURCE_PERF; 8430 rci->scale[cai->rci_index] = scale * cai->compat_scale; 8431 rci->unit[cai->rci_index] = unit; 8432 rci->flags[cai->rci_index] = cai->flags; 8433 8434 /* Use MSR for this counter */ 8435 } else if (add_rapl_msr_counter(cpu, cai) >= 0) { 8436 rci->source[cai->rci_index] = COUNTER_SOURCE_MSR; 8437 rci->msr[cai->rci_index] = cai->msr; 8438 rci->msr_mask[cai->rci_index] = cai->msr_mask; 8439 rci->msr_shift[cai->rci_index] = cai->msr_shift; 8440 rci->unit[cai->rci_index] = RAPL_UNIT_JOULES; 8441 rci->scale[cai->rci_index] = *cai->platform_rapl_msr_scale * cai->compat_scale; 8442 rci->flags[cai->rci_index] = cai->flags; 8443 } 8444 8445 if (rci->source[cai->rci_index] != COUNTER_SOURCE_NONE) 8446 has_counter = 1; 8447 } 8448 8449 /* If any CPU has access to the counter, make it present */ 8450 if (has_counter) 8451 BIC_PRESENT(cai->bic_number); 8452 } 8453 8454 free(domain_visited); 8455} 8456 8457/* Assumes msr_counter_info is populated */ 8458static int has_amperf_access(void) 8459{ 8460 return cpuid_has_aperf_mperf && msr_counter_arch_infos[MSR_ARCH_INFO_APERF_INDEX].present && 8461 msr_counter_arch_infos[MSR_ARCH_INFO_MPERF_INDEX].present; 8462} 8463 8464int *get_cstate_perf_group_fd(struct cstate_counter_info_t *cci, const char *group_name) 8465{ 8466 if (strcmp(group_name, "cstate_core") == 0) 8467 return &cci->fd_perf_core; 8468 8469 if (strcmp(group_name, "cstate_pkg") == 0) 8470 return &cci->fd_perf_pkg; 8471 8472 return NULL; 8473} 8474 8475int add_cstate_perf_counter(int cpu, struct cstate_counter_info_t *cci, const struct cstate_counter_arch_info *cai) 8476{ 8477 int ret = -1; 8478 8479 if (no_perf) 8480 return -1; 8481 8482 if (!cai->perf_name) 8483 return -1; 8484 8485 int *pfd_group = get_cstate_perf_group_fd(cci, cai->perf_subsys); 8486 8487 if (pfd_group == NULL) 8488 goto end; 8489 8490 const unsigned int type = read_perf_type(cai->perf_subsys); 8491 const unsigned int config = read_perf_config(cai->perf_subsys, cai->perf_name); 8492 8493 ret = open_perf_counter(cpu, type, config, *pfd_group, PERF_FORMAT_GROUP); 8494 8495 if (ret == -1) 8496 goto end; 8497 8498 /* If it's the first counter opened, make it a group descriptor */ 8499 if (*pfd_group == -1) 8500 *pfd_group = ret; 8501 8502end: 8503 if (debug >= 2) 8504 fprintf(stderr, "%s: %d (cpu: %d)\n", __func__, ret, cpu); 8505 8506 return ret; 8507} 8508 8509int add_msr_perf_counter(int cpu, struct msr_counter_info_t *cci, const struct msr_counter_arch_info *cai) 8510{ 8511 int ret = -1; 8512 8513 if (no_perf) 8514 return -1; 8515 8516 if (!cai->perf_name) 8517 return -1; 8518 8519 const unsigned int type = read_perf_type(cai->perf_subsys); 8520 const unsigned int config = read_perf_config(cai->perf_subsys, cai->perf_name); 8521 8522 ret = open_perf_counter(cpu, type, config, cci->fd_perf, PERF_FORMAT_GROUP); 8523 8524 if (ret == -1) 8525 goto end; 8526 8527 /* If it's the first counter opened, make it a group descriptor */ 8528 if (cci->fd_perf == -1) 8529 cci->fd_perf = ret; 8530 8531end: 8532 if (debug) 8533 fprintf(stderr, "%s: %s/%s: %d (cpu: %d)\n", __func__, cai->perf_subsys, cai->perf_name, ret, cpu); 8534 8535 return ret; 8536} 8537 8538void msr_perf_init_(void) 8539{ 8540 const int mci_num = topo.max_cpu_num + 1; 8541 8542 msr_counter_info = calloc(mci_num, sizeof(*msr_counter_info)); 8543 if (!msr_counter_info) 8544 err(1, "calloc msr_counter_info"); 8545 msr_counter_info_size = mci_num; 8546 8547 for (int cpu = 0; cpu < mci_num; ++cpu) 8548 msr_counter_info[cpu].fd_perf = -1; 8549 8550 for (int cidx = 0; cidx < NUM_MSR_COUNTERS; ++cidx) { 8551 8552 struct msr_counter_arch_info *cai = &msr_counter_arch_infos[cidx]; 8553 8554 cai->present = false; 8555 8556 for (int cpu = 0; cpu < mci_num; ++cpu) { 8557 8558 struct msr_counter_info_t *const cci = &msr_counter_info[cpu]; 8559 8560 if (cpu_is_not_allowed(cpu)) 8561 continue; 8562 8563 if (cai->needed) { 8564 /* Use perf API for this counter */ 8565 if (add_msr_perf_counter(cpu, cci, cai) != -1) { 8566 cci->source[cai->rci_index] = COUNTER_SOURCE_PERF; 8567 cai->present = true; 8568 8569 /* User MSR for this counter */ 8570 } else if (add_msr_counter(cpu, cai->msr) >= 0) { 8571 cci->source[cai->rci_index] = COUNTER_SOURCE_MSR; 8572 cci->msr[cai->rci_index] = cai->msr; 8573 cci->msr_mask[cai->rci_index] = cai->msr_mask; 8574 cai->present = true; 8575 } 8576 } 8577 } 8578 } 8579} 8580 8581/* Initialize data for reading perf counters from the MSR group. */ 8582void msr_perf_init(void) 8583{ 8584 bool need_amperf = false, need_smi = false; 8585 const bool need_soft_c1 = (!platform->has_msr_core_c1_res) && (platform->supported_cstates & CC1); 8586 8587 need_amperf = BIC_IS_ENABLED(BIC_Avg_MHz) || BIC_IS_ENABLED(BIC_Busy) || BIC_IS_ENABLED(BIC_Bzy_MHz) 8588 || BIC_IS_ENABLED(BIC_IPC) || need_soft_c1; 8589 8590 if (BIC_IS_ENABLED(BIC_SMI)) 8591 need_smi = true; 8592 8593 /* Enable needed counters */ 8594 msr_counter_arch_infos[MSR_ARCH_INFO_APERF_INDEX].needed = need_amperf; 8595 msr_counter_arch_infos[MSR_ARCH_INFO_MPERF_INDEX].needed = need_amperf; 8596 msr_counter_arch_infos[MSR_ARCH_INFO_SMI_INDEX].needed = need_smi; 8597 8598 msr_perf_init_(); 8599 8600 const bool has_amperf = has_amperf_access(); 8601 const bool has_smi = msr_counter_arch_infos[MSR_ARCH_INFO_SMI_INDEX].present; 8602 8603 has_aperf_access = has_amperf; 8604 8605 if (has_amperf) { 8606 BIC_PRESENT(BIC_Avg_MHz); 8607 BIC_PRESENT(BIC_Busy); 8608 BIC_PRESENT(BIC_Bzy_MHz); 8609 BIC_PRESENT(BIC_SMI); 8610 } 8611 8612 if (has_smi) 8613 BIC_PRESENT(BIC_SMI); 8614} 8615 8616void cstate_perf_init_(bool soft_c1) 8617{ 8618 bool has_counter; 8619 bool *cores_visited = NULL, *pkg_visited = NULL; 8620 const int cores_visited_elems = topo.max_core_id + 1; 8621 const int pkg_visited_elems = topo.max_package_id + 1; 8622 const int cci_num = topo.max_cpu_num + 1; 8623 8624 ccstate_counter_info = calloc(cci_num, sizeof(*ccstate_counter_info)); 8625 if (!ccstate_counter_info) 8626 err(1, "calloc ccstate_counter_arch_info"); 8627 ccstate_counter_info_size = cci_num; 8628 8629 cores_visited = calloc(cores_visited_elems, sizeof(*cores_visited)); 8630 if (!cores_visited) 8631 err(1, "calloc cores_visited"); 8632 8633 pkg_visited = calloc(pkg_visited_elems, sizeof(*pkg_visited)); 8634 if (!pkg_visited) 8635 err(1, "calloc pkg_visited"); 8636 8637 /* Initialize cstate_counter_info_percpu */ 8638 for (int cpu = 0; cpu < cci_num; ++cpu) { 8639 ccstate_counter_info[cpu].fd_perf_core = -1; 8640 ccstate_counter_info[cpu].fd_perf_pkg = -1; 8641 } 8642 8643 for (int cidx = 0; cidx < NUM_CSTATE_COUNTERS; ++cidx) { 8644 has_counter = false; 8645 memset(cores_visited, 0, cores_visited_elems * sizeof(*cores_visited)); 8646 memset(pkg_visited, 0, pkg_visited_elems * sizeof(*pkg_visited)); 8647 8648 const struct cstate_counter_arch_info *cai = &ccstate_counter_arch_infos[cidx]; 8649 8650 for (int cpu = 0; cpu < cci_num; ++cpu) { 8651 8652 struct cstate_counter_info_t *const cci = &ccstate_counter_info[cpu]; 8653 8654 if (cpu_is_not_allowed(cpu)) 8655 continue; 8656 8657 const int core_id = cpus[cpu].physical_core_id; 8658 const int pkg_id = cpus[cpu].physical_package_id; 8659 8660 assert(core_id < cores_visited_elems); 8661 assert(pkg_id < pkg_visited_elems); 8662 8663 const bool per_thread = cai->flags & CSTATE_COUNTER_FLAG_COLLECT_PER_THREAD; 8664 const bool per_core = cai->flags & CSTATE_COUNTER_FLAG_COLLECT_PER_CORE; 8665 8666 if (!per_thread && cores_visited[core_id]) 8667 continue; 8668 8669 if (!per_core && pkg_visited[pkg_id]) 8670 continue; 8671 8672 const bool counter_needed = BIC_IS_ENABLED(cai->bic_number) || 8673 (soft_c1 && (cai->flags & CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY)); 8674 const bool counter_supported = (platform->supported_cstates & cai->feature_mask); 8675 8676 if (counter_needed && counter_supported) { 8677 /* Use perf API for this counter */ 8678 if (add_cstate_perf_counter(cpu, cci, cai) != -1) { 8679 8680 cci->source[cai->rci_index] = COUNTER_SOURCE_PERF; 8681 8682 /* User MSR for this counter */ 8683 } else if (pkg_cstate_limit >= cai->pkg_cstate_limit && add_msr_counter(cpu, cai->msr) >= 0) { 8684 cci->source[cai->rci_index] = COUNTER_SOURCE_MSR; 8685 cci->msr[cai->rci_index] = cai->msr; 8686 } 8687 } 8688 8689 if (cci->source[cai->rci_index] != COUNTER_SOURCE_NONE) { 8690 has_counter = true; 8691 cores_visited[core_id] = true; 8692 pkg_visited[pkg_id] = true; 8693 } 8694 } 8695 8696 /* If any CPU has access to the counter, make it present */ 8697 if (has_counter) 8698 BIC_PRESENT(cai->bic_number); 8699 } 8700 8701 free(cores_visited); 8702 free(pkg_visited); 8703} 8704 8705void cstate_perf_init(void) 8706{ 8707 /* 8708 * If we don't have a C1 residency MSR, we calculate it "in software", 8709 * but we need APERF, MPERF too. 8710 */ 8711 const bool soft_c1 = !platform->has_msr_core_c1_res && has_amperf_access() 8712 && platform->supported_cstates & CC1; 8713 8714 if (soft_c1) 8715 BIC_PRESENT(BIC_CPU_c1); 8716 8717 cstate_perf_init_(soft_c1); 8718} 8719 8720void probe_cstates(void) 8721{ 8722 probe_cst_limit(); 8723 8724 if (platform->has_msr_module_c6_res_ms) 8725 BIC_PRESENT(BIC_Mod_c6); 8726 8727 if (platform->has_ext_cst_msrs && !no_msr) { 8728 BIC_PRESENT(BIC_Totl_c0); 8729 BIC_PRESENT(BIC_Any_c0); 8730 BIC_PRESENT(BIC_GFX_c0); 8731 BIC_PRESENT(BIC_CPUGFX); 8732 } 8733 8734 if (quiet) 8735 return; 8736 8737 dump_power_ctl(); 8738 dump_cst_cfg(); 8739 decode_c6_demotion_policy_msr(); 8740 print_dev_latency(); 8741 dump_sysfs_cstate_config(); 8742 print_irtl(); 8743} 8744 8745void probe_lpi(void) 8746{ 8747 if (!access("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", R_OK)) 8748 BIC_PRESENT(BIC_CPU_LPI); 8749 else 8750 BIC_NOT_PRESENT(BIC_CPU_LPI); 8751 8752 if (!access(sys_lpi_file_sysfs, R_OK)) { 8753 sys_lpi_file = sys_lpi_file_sysfs; 8754 BIC_PRESENT(BIC_SYS_LPI); 8755 } else if (!access(sys_lpi_file_debugfs, R_OK)) { 8756 sys_lpi_file = sys_lpi_file_debugfs; 8757 BIC_PRESENT(BIC_SYS_LPI); 8758 } else { 8759 sys_lpi_file_sysfs = NULL; 8760 BIC_NOT_PRESENT(BIC_SYS_LPI); 8761 } 8762 8763} 8764 8765void probe_pstates(void) 8766{ 8767 probe_bclk(); 8768 8769 if (quiet) 8770 return; 8771 8772 dump_platform_info(); 8773 dump_turbo_ratio_info(); 8774 dump_sysfs_pstate_config(); 8775 decode_misc_pwr_mgmt_msr(); 8776 8777 for_all_cpus(print_hwp, ODD_COUNTERS); 8778 for_all_cpus(print_epb, ODD_COUNTERS); 8779 for_all_cpus(print_perf_limit, ODD_COUNTERS); 8780} 8781 8782void process_cpuid() 8783{ 8784 unsigned int eax, ebx, ecx, edx; 8785 unsigned int fms, family, model, stepping, ecx_flags, edx_flags; 8786 unsigned long long ucode_patch = 0; 8787 bool ucode_patch_valid = false; 8788 8789 eax = ebx = ecx = edx = 0; 8790 8791 __cpuid(0, max_level, ebx, ecx, edx); 8792 8793 if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69) 8794 genuine_intel = 1; 8795 else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65) 8796 authentic_amd = 1; 8797 else if (ebx == 0x6f677948 && ecx == 0x656e6975 && edx == 0x6e65476e) 8798 hygon_genuine = 1; 8799 8800 if (!quiet) 8801 fprintf(outf, "CPUID(0): %.4s%.4s%.4s 0x%x CPUID levels\n", (char *)&ebx, (char *)&edx, (char *)&ecx, max_level); 8802 8803 __cpuid(1, fms, ebx, ecx, edx); 8804 family = (fms >> 8) & 0xf; 8805 model = (fms >> 4) & 0xf; 8806 stepping = fms & 0xf; 8807 if (family == 0xf) 8808 family += (fms >> 20) & 0xff; 8809 if (family >= 6) 8810 model += ((fms >> 16) & 0xf) << 4; 8811 ecx_flags = ecx; 8812 edx_flags = edx; 8813 8814 if (!no_msr) { 8815 if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch)) { 8816 warnx("get_msr(UCODE)"); 8817 } else { 8818 ucode_patch_valid = true; 8819 if (!authentic_amd && !hygon_genuine) 8820 ucode_patch >>= 32; 8821 } 8822 } 8823 8824 /* 8825 * check max extended function levels of CPUID. 8826 * This is needed to check for invariant TSC. 8827 * This check is valid for both Intel and AMD. 8828 */ 8829 ebx = ecx = edx = 0; 8830 __cpuid(0x80000000, max_extended_level, ebx, ecx, edx); 8831 8832 if (!quiet) { 8833 fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d)", family, model, stepping, family, model, stepping); 8834 if (ucode_patch_valid) 8835 fprintf(outf, " microcode 0x%x", (unsigned int)ucode_patch); 8836 fputc('\n', outf); 8837 8838 fprintf(outf, "CPUID(0x80000000): max_extended_levels: 0x%x\n", max_extended_level); 8839 fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s %s\n", 8840 ecx_flags & (1 << 0) ? "SSE3" : "-", 8841 ecx_flags & (1 << 3) ? "MONITOR" : "-", 8842 ecx_flags & (1 << 6) ? "SMX" : "-", 8843 ecx_flags & (1 << 7) ? "EIST" : "-", 8844 ecx_flags & (1 << 8) ? "TM2" : "-", 8845 edx_flags & (1 << 4) ? "TSC" : "-", 8846 edx_flags & (1 << 5) ? "MSR" : "-", 8847 edx_flags & (1 << 22) ? "ACPI-TM" : "-", edx_flags & (1 << 28) ? "HT" : "-", edx_flags & (1 << 29) ? "TM" : "-"); 8848 } 8849 8850 probe_platform_features(family, model); 8851 8852 if (!(edx_flags & (1 << 5))) 8853 errx(1, "CPUID: no MSR"); 8854 8855 if (max_extended_level >= 0x80000007) { 8856 8857 /* 8858 * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8 8859 * this check is valid for both Intel and AMD 8860 */ 8861 __cpuid(0x80000007, eax, ebx, ecx, edx); 8862 has_invariant_tsc = edx & (1 << 8); 8863 } 8864 8865 /* 8866 * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0 8867 * this check is valid for both Intel and AMD 8868 */ 8869 8870 __cpuid(0x6, eax, ebx, ecx, edx); 8871 cpuid_has_aperf_mperf = ecx & (1 << 0); 8872 do_dts = eax & (1 << 0); 8873 if (do_dts) 8874 BIC_PRESENT(BIC_CoreTmp); 8875 has_turbo = eax & (1 << 1); 8876 do_ptm = eax & (1 << 6); 8877 if (do_ptm) 8878 BIC_PRESENT(BIC_PkgTmp); 8879 has_hwp = eax & (1 << 7); 8880 has_hwp_notify = eax & (1 << 8); 8881 has_hwp_activity_window = eax & (1 << 9); 8882 has_hwp_epp = eax & (1 << 10); 8883 has_hwp_pkg = eax & (1 << 11); 8884 has_epb = ecx & (1 << 3); 8885 8886 if (!quiet) 8887 fprintf(outf, "CPUID(6): %sAPERF, %sTURBO, %sDTS, %sPTM, %sHWP, " 8888 "%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n", 8889 cpuid_has_aperf_mperf ? "" : "No-", 8890 has_turbo ? "" : "No-", 8891 do_dts ? "" : "No-", 8892 do_ptm ? "" : "No-", 8893 has_hwp ? "" : "No-", 8894 has_hwp_notify ? "" : "No-", 8895 has_hwp_activity_window ? "" : "No-", has_hwp_epp ? "" : "No-", has_hwp_pkg ? "" : "No-", has_epb ? "" : "No-"); 8896 8897 if (!quiet) 8898 decode_misc_enable_msr(); 8899 8900 if (max_level >= 0x7 && !quiet) { 8901 int has_sgx; 8902 8903 ecx = 0; 8904 8905 __cpuid_count(0x7, 0, eax, ebx, ecx, edx); 8906 8907 has_sgx = ebx & (1 << 2); 8908 8909 is_hybrid = edx & (1 << 15); 8910 8911 fprintf(outf, "CPUID(7): %sSGX %sHybrid\n", has_sgx ? "" : "No-", is_hybrid ? "" : "No-"); 8912 8913 if (has_sgx) 8914 decode_feature_control_msr(); 8915 } 8916 8917 if (max_level >= 0x15) { 8918 unsigned int eax_crystal; 8919 unsigned int ebx_tsc; 8920 8921 /* 8922 * CPUID 15H TSC/Crystal ratio, possibly Crystal Hz 8923 */ 8924 eax_crystal = ebx_tsc = crystal_hz = edx = 0; 8925 __cpuid(0x15, eax_crystal, ebx_tsc, crystal_hz, edx); 8926 8927 if (ebx_tsc != 0) { 8928 if (!quiet && (ebx != 0)) 8929 fprintf(outf, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n", eax_crystal, ebx_tsc, crystal_hz); 8930 8931 if (crystal_hz == 0) 8932 crystal_hz = platform->crystal_freq; 8933 8934 if (crystal_hz) { 8935 tsc_hz = (unsigned long long)crystal_hz *ebx_tsc / eax_crystal; 8936 if (!quiet) 8937 fprintf(outf, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n", 8938 tsc_hz / 1000000, crystal_hz, ebx_tsc, eax_crystal); 8939 } 8940 } 8941 } 8942 if (max_level >= 0x16) { 8943 unsigned int base_mhz, max_mhz, bus_mhz, edx; 8944 8945 /* 8946 * CPUID 16H Base MHz, Max MHz, Bus MHz 8947 */ 8948 base_mhz = max_mhz = bus_mhz = edx = 0; 8949 8950 __cpuid(0x16, base_mhz, max_mhz, bus_mhz, edx); 8951 8952 bclk = bus_mhz; 8953 8954 base_hz = base_mhz * 1000000; 8955 has_base_hz = 1; 8956 8957 if (platform->enable_tsc_tweak) 8958 tsc_tweak = base_hz / tsc_hz; 8959 8960 if (!quiet) 8961 fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n", base_mhz, max_mhz, bus_mhz); 8962 } 8963 8964 if (cpuid_has_aperf_mperf) 8965 aperf_mperf_multiplier = platform->need_perf_multiplier ? 1024 : 1; 8966 8967 BIC_PRESENT(BIC_IRQ); 8968 BIC_PRESENT(BIC_NMI); 8969 BIC_PRESENT(BIC_TSC_MHz); 8970} 8971 8972static void counter_info_init(void) 8973{ 8974 for (int i = 0; i < NUM_CSTATE_COUNTERS; ++i) { 8975 struct cstate_counter_arch_info *const cai = &ccstate_counter_arch_infos[i]; 8976 8977 if (platform->has_msr_knl_core_c6_residency && cai->msr == MSR_CORE_C6_RESIDENCY) 8978 cai->msr = MSR_KNL_CORE_C6_RESIDENCY; 8979 8980 if (!platform->has_msr_core_c1_res && cai->msr == MSR_CORE_C1_RES) 8981 cai->msr = 0; 8982 8983 if (platform->has_msr_atom_pkg_c6_residency && cai->msr == MSR_PKG_C6_RESIDENCY) 8984 cai->msr = MSR_ATOM_PKG_C6_RESIDENCY; 8985 } 8986 8987 for (int i = 0; i < NUM_MSR_COUNTERS; ++i) { 8988 msr_counter_arch_infos[i].present = false; 8989 msr_counter_arch_infos[i].needed = false; 8990 } 8991} 8992 8993void probe_pm_features(void) 8994{ 8995 probe_pstates(); 8996 8997 probe_cstates(); 8998 8999 probe_lpi(); 9000 9001 probe_intel_uncore_frequency(); 9002 9003 probe_graphics(); 9004 9005 probe_rapl(); 9006 9007 probe_thermal(); 9008 9009 if (platform->has_nhm_msrs && !no_msr) 9010 BIC_PRESENT(BIC_SMI); 9011 9012 if (!quiet) 9013 decode_misc_feature_control(); 9014} 9015 9016/* perf_llc_probe 9017 * 9018 * return 1 on success, else 0 9019 */ 9020int has_perf_llc_access(void) 9021{ 9022 int fd; 9023 9024 if (no_perf) 9025 return 0; 9026 9027 fd = open_perf_counter(base_cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES, -1, PERF_FORMAT_GROUP); 9028 if (fd != -1) 9029 close(fd); 9030 9031 if (fd == -1) 9032 warnx("Failed to access %s. Some of the counters may not be available\n" 9033 "\tRun as root to enable them or use %s to disable the access explicitly", "perf LLC counters", "'--hide LLC' or '--no-perf'"); 9034 9035 return (fd != -1); 9036} 9037 9038void perf_llc_init(void) 9039{ 9040 int cpu; 9041 int retval; 9042 9043 if (no_perf) 9044 return; 9045 if (!(BIC_IS_ENABLED(BIC_LLC_RPS) && BIC_IS_ENABLED(BIC_LLC_HIT))) 9046 return; 9047 9048 for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu) { 9049 9050 if (cpu_is_not_allowed(cpu)) 9051 continue; 9052 9053 assert(fd_llc_percpu != 0); 9054 fd_llc_percpu[cpu] = open_perf_counter(cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES, -1, PERF_FORMAT_GROUP); 9055 if (fd_llc_percpu[cpu] == -1) { 9056 warnx("%s: perf REFS: failed to open counter on cpu%d", __func__, cpu); 9057 free_fd_llc_percpu(); 9058 return; 9059 } 9060 assert(fd_llc_percpu != 0); 9061 retval = open_perf_counter(cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES, fd_llc_percpu[cpu], PERF_FORMAT_GROUP); 9062 if (retval == -1) { 9063 warnx("%s: perf MISS: failed to open counter on cpu%d", __func__, cpu); 9064 free_fd_llc_percpu(); 9065 return; 9066 } 9067 } 9068 BIC_PRESENT(BIC_LLC_RPS); 9069 BIC_PRESENT(BIC_LLC_HIT); 9070} 9071 9072/* 9073 * in /dev/cpu/ return success for names that are numbers 9074 * ie. filter out ".", "..", "microcode". 9075 */ 9076int dir_filter(const struct dirent *dirp) 9077{ 9078 if (isdigit(dirp->d_name[0])) 9079 return 1; 9080 else 9081 return 0; 9082} 9083 9084char *possible_file = "/sys/devices/system/cpu/possible"; 9085char possible_buf[1024]; 9086 9087int initialize_cpu_possible_set(void) 9088{ 9089 FILE *fp; 9090 9091 fp = fopen(possible_file, "r"); 9092 if (!fp) { 9093 warn("open %s", possible_file); 9094 return -1; 9095 } 9096 if (fread(possible_buf, sizeof(char), 1024, fp) == 0) { 9097 warn("read %s", possible_file); 9098 goto err; 9099 } 9100 if (parse_cpu_str(possible_buf, cpu_possible_set, cpu_possible_setsize)) { 9101 warnx("%s: cpu str malformat %s\n", possible_file, cpu_effective_str); 9102 goto err; 9103 } 9104 return 0; 9105 9106err: 9107 fclose(fp); 9108 return -1; 9109} 9110 9111void topology_probe(bool startup) 9112{ 9113 int i; 9114 int max_core_id = 0; 9115 int max_package_id = 0; 9116 int max_siblings = 0; 9117 9118 /* Initialize num_cpus, max_cpu_num */ 9119 set_max_cpu_num(); 9120 topo.num_cpus = 0; 9121 for_all_proc_cpus(count_cpus); 9122 if (!summary_only) 9123 BIC_PRESENT(BIC_CPU); 9124 9125 if (debug > 1) 9126 fprintf(outf, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num); 9127 9128 cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology)); 9129 if (cpus == NULL) 9130 err(1, "calloc cpus"); 9131 9132 /* 9133 * Allocate and initialize cpu_present_set 9134 */ 9135 cpu_present_set = CPU_ALLOC((topo.max_cpu_num + 1)); 9136 if (cpu_present_set == NULL) 9137 err(3, "CPU_ALLOC"); 9138 cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); 9139 CPU_ZERO_S(cpu_present_setsize, cpu_present_set); 9140 for_all_proc_cpus(mark_cpu_present); 9141 9142 /* 9143 * Allocate and initialize cpu_possible_set 9144 */ 9145 cpu_possible_set = CPU_ALLOC((topo.max_cpu_num + 1)); 9146 if (cpu_possible_set == NULL) 9147 err(3, "CPU_ALLOC"); 9148 cpu_possible_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); 9149 CPU_ZERO_S(cpu_possible_setsize, cpu_possible_set); 9150 initialize_cpu_possible_set(); 9151 9152 /* 9153 * Allocate and initialize cpu_effective_set 9154 */ 9155 cpu_effective_set = CPU_ALLOC((topo.max_cpu_num + 1)); 9156 if (cpu_effective_set == NULL) 9157 err(3, "CPU_ALLOC"); 9158 cpu_effective_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); 9159 CPU_ZERO_S(cpu_effective_setsize, cpu_effective_set); 9160 update_effective_set(startup); 9161 9162 /* 9163 * Allocate and initialize cpu_allowed_set 9164 */ 9165 cpu_allowed_set = CPU_ALLOC((topo.max_cpu_num + 1)); 9166 if (cpu_allowed_set == NULL) 9167 err(3, "CPU_ALLOC"); 9168 cpu_allowed_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); 9169 CPU_ZERO_S(cpu_allowed_setsize, cpu_allowed_set); 9170 9171 /* 9172 * Validate and update cpu_allowed_set. 9173 * 9174 * Make sure all cpus in cpu_subset are also in cpu_present_set during startup. 9175 * Give a warning when cpus in cpu_subset become unavailable at runtime. 9176 * Give a warning when cpus are not effective because of cgroup setting. 9177 * 9178 * cpu_allowed_set is the intersection of cpu_present_set/cpu_effective_set/cpu_subset. 9179 */ 9180 for (i = 0; i < CPU_SUBSET_MAXCPUS; ++i) { 9181 if (cpu_subset && !CPU_ISSET_S(i, cpu_subset_size, cpu_subset)) 9182 continue; 9183 9184 if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set)) { 9185 if (cpu_subset) { 9186 /* cpus in cpu_subset must be in cpu_present_set during startup */ 9187 if (startup) 9188 err(1, "cpu%d not present", i); 9189 else 9190 fprintf(stderr, "cpu%d not present\n", i); 9191 } 9192 continue; 9193 } 9194 9195 if (CPU_COUNT_S(cpu_effective_setsize, cpu_effective_set)) { 9196 if (!CPU_ISSET_S(i, cpu_effective_setsize, cpu_effective_set)) { 9197 fprintf(stderr, "cpu%d not effective\n", i); 9198 continue; 9199 } 9200 } 9201 9202 CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set); 9203 } 9204 9205 if (!CPU_COUNT_S(cpu_allowed_setsize, cpu_allowed_set)) 9206 err(-ENODEV, "No valid cpus found"); 9207 sched_setaffinity(0, cpu_allowed_setsize, cpu_allowed_set); 9208 9209 /* 9210 * Allocate and initialize cpu_affinity_set 9211 */ 9212 cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1)); 9213 if (cpu_affinity_set == NULL) 9214 err(3, "CPU_ALLOC"); 9215 cpu_affinity_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); 9216 CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set); 9217 9218 for_all_proc_cpus(init_thread_id); 9219 9220 for_all_proc_cpus(set_cpu_hybrid_type); 9221 9222 /* 9223 * For online cpus 9224 * find max_core_id, max_package_id 9225 */ 9226 for (i = 0; i <= topo.max_cpu_num; ++i) { 9227 int siblings; 9228 9229 if (cpu_is_not_present(i)) { 9230 if (debug > 1) 9231 fprintf(outf, "cpu%d NOT PRESENT\n", i); 9232 continue; 9233 } 9234 9235 cpus[i].logical_cpu_id = i; 9236 9237 /* get package information */ 9238 cpus[i].physical_package_id = get_physical_package_id(i); 9239 if (cpus[i].physical_package_id > max_package_id) 9240 max_package_id = cpus[i].physical_package_id; 9241 9242 /* get die information */ 9243 cpus[i].die_id = get_die_id(i); 9244 if (cpus[i].die_id > topo.max_die_id) 9245 topo.max_die_id = cpus[i].die_id; 9246 9247 /* get l3 information */ 9248 cpus[i].l3_id = get_l3_id(i); 9249 if (cpus[i].l3_id > topo.max_l3_id) 9250 topo.max_l3_id = cpus[i].l3_id; 9251 9252 /* get numa node information */ 9253 cpus[i].physical_node_id = get_physical_node_id(&cpus[i]); 9254 if (cpus[i].physical_node_id > topo.max_node_num) 9255 topo.max_node_num = cpus[i].physical_node_id; 9256 9257 /* get core information */ 9258 cpus[i].physical_core_id = get_core_id(i); 9259 if (cpus[i].physical_core_id > max_core_id) 9260 max_core_id = cpus[i].physical_core_id; 9261 9262 /* get thread information */ 9263 siblings = get_thread_siblings(&cpus[i]); 9264 if (siblings > max_siblings) 9265 max_siblings = siblings; 9266 if (cpus[i].thread_id == 0) 9267 topo.num_cores++; 9268 } 9269 topo.max_core_id = max_core_id; 9270 topo.max_package_id = max_package_id; 9271 9272 topo.cores_per_node = max_core_id + 1; 9273 if (debug > 1) 9274 fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", max_core_id, topo.cores_per_node); 9275 if (!summary_only) 9276 BIC_PRESENT(BIC_Core); 9277 9278 topo.num_die = topo.max_die_id + 1; 9279 if (debug > 1) 9280 fprintf(outf, "max_die_id %d, sizing for %d die\n", topo.max_die_id, topo.num_die); 9281 if (!summary_only && topo.num_die > 1) 9282 BIC_PRESENT(BIC_Die); 9283 9284 if (!summary_only && topo.max_l3_id > 0) 9285 BIC_PRESENT(BIC_L3); 9286 9287 topo.num_packages = max_package_id + 1; 9288 if (debug > 1) 9289 fprintf(outf, "max_package_id %d, sizing for %d packages\n", max_package_id, topo.num_packages); 9290 if (!summary_only && topo.num_packages > 1) 9291 BIC_PRESENT(BIC_Package); 9292 9293 set_node_data(); 9294 if (debug > 1) 9295 fprintf(outf, "nodes_per_pkg %d\n", topo.nodes_per_pkg); 9296 if (!summary_only && topo.nodes_per_pkg > 1) 9297 BIC_PRESENT(BIC_Node); 9298 9299 topo.threads_per_core = max_siblings; 9300 if (debug > 1) 9301 fprintf(outf, "max_siblings %d\n", max_siblings); 9302 9303 if (debug < 1) 9304 return; 9305 9306 for (i = 0; i <= topo.max_cpu_num; ++i) { 9307 if (cpu_is_not_present(i)) 9308 continue; 9309 fprintf(outf, 9310 "cpu %d pkg %d die %d l3 %d node %d lnode %d core %d thread %d\n", 9311 i, cpus[i].physical_package_id, cpus[i].die_id, cpus[i].l3_id, 9312 cpus[i].physical_node_id, cpus[i].logical_node_id, cpus[i].physical_core_id, cpus[i].thread_id); 9313 } 9314 9315} 9316 9317void allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data **p) 9318{ 9319 int i; 9320 int num_cores = topo.cores_per_node * topo.nodes_per_pkg * topo.num_packages; 9321 int num_threads = topo.threads_per_core * num_cores; 9322 9323 *t = calloc(num_threads, sizeof(struct thread_data)); 9324 if (*t == NULL) 9325 goto error; 9326 9327 for (i = 0; i < num_threads; i++) 9328 (*t)[i].cpu_id = -1; 9329 9330 *c = calloc(num_cores, sizeof(struct core_data)); 9331 if (*c == NULL) 9332 goto error; 9333 9334 for (i = 0; i < num_cores; i++) { 9335 (*c)[i].core_id = -1; 9336 (*c)[i].base_cpu = -1; 9337 } 9338 9339 *p = calloc(topo.num_packages, sizeof(struct pkg_data)); 9340 if (*p == NULL) 9341 goto error; 9342 9343 for (i = 0; i < topo.num_packages; i++) { 9344 (*p)[i].package_id = i; 9345 (*p)[i].base_cpu = -1; 9346 } 9347 9348 return; 9349error: 9350 err(1, "calloc counters"); 9351} 9352 9353/* 9354 * init_counter() 9355 * 9356 * set FIRST_THREAD_IN_CORE and FIRST_CORE_IN_PACKAGE 9357 */ 9358void init_counter(struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base, int cpu_id) 9359{ 9360 int pkg_id = cpus[cpu_id].physical_package_id; 9361 int node_id = cpus[cpu_id].logical_node_id; 9362 int core_id = cpus[cpu_id].physical_core_id; 9363 int thread_id = cpus[cpu_id].thread_id; 9364 struct thread_data *t; 9365 struct core_data *c; 9366 9367 /* Workaround for systems where physical_node_id==-1 9368 * and logical_node_id==(-1 - topo.num_cpus) 9369 */ 9370 if (node_id < 0) 9371 node_id = 0; 9372 9373 t = GET_THREAD(thread_base, thread_id, core_id, node_id, pkg_id); 9374 c = GET_CORE(core_base, core_id, node_id, pkg_id); 9375 9376 t->cpu_id = cpu_id; 9377 if (!cpu_is_not_allowed(cpu_id)) { 9378 9379 if (c->base_cpu < 0) 9380 c->base_cpu = t->cpu_id; 9381 if (pkg_base[pkg_id].base_cpu < 0) 9382 pkg_base[pkg_id].base_cpu = t->cpu_id; 9383 } 9384 9385 c->core_id = core_id; 9386 pkg_base[pkg_id].package_id = pkg_id; 9387} 9388 9389int initialize_counters(int cpu_id) 9390{ 9391 init_counter(EVEN_COUNTERS, cpu_id); 9392 init_counter(ODD_COUNTERS, cpu_id); 9393 return 0; 9394} 9395 9396void allocate_output_buffer() 9397{ 9398 output_buffer = calloc(1, (1 + topo.num_cpus) * 2048); 9399 outp = output_buffer; 9400 if (outp == NULL) 9401 err(-1, "calloc output buffer"); 9402} 9403 9404void allocate_fd_percpu(void) 9405{ 9406 fd_percpu = calloc(topo.max_cpu_num + 1, sizeof(int)); 9407 if (fd_percpu == NULL) 9408 err(-1, "calloc fd_percpu"); 9409} 9410 9411void allocate_irq_buffers(void) 9412{ 9413 irq_column_2_cpu = calloc(topo.num_cpus, sizeof(int)); 9414 if (irq_column_2_cpu == NULL) 9415 err(-1, "calloc %d", topo.num_cpus); 9416 9417 irqs_per_cpu = calloc(topo.max_cpu_num + 1, sizeof(int)); 9418 if (irqs_per_cpu == NULL) 9419 err(-1, "calloc %d IRQ", topo.max_cpu_num + 1); 9420 9421 nmi_per_cpu = calloc(topo.max_cpu_num + 1, sizeof(int)); 9422 if (nmi_per_cpu == NULL) 9423 err(-1, "calloc %d NMI", topo.max_cpu_num + 1); 9424} 9425 9426int update_topo(PER_THREAD_PARAMS) 9427{ 9428 topo.allowed_cpus++; 9429 if ((int)t->cpu_id == c->base_cpu) 9430 topo.allowed_cores++; 9431 if ((int)t->cpu_id == p->base_cpu) 9432 topo.allowed_packages++; 9433 9434 return 0; 9435} 9436 9437void topology_update(void) 9438{ 9439 topo.allowed_cpus = 0; 9440 topo.allowed_cores = 0; 9441 topo.allowed_packages = 0; 9442 for_all_cpus(update_topo, ODD_COUNTERS); 9443} 9444 9445void setup_all_buffers(bool startup) 9446{ 9447 topology_probe(startup); 9448 allocate_irq_buffers(); 9449 allocate_fd_percpu(); 9450 allocate_counters(&thread_even, &core_even, &package_even); 9451 allocate_counters(&thread_odd, &core_odd, &package_odd); 9452 allocate_output_buffer(); 9453 for_all_proc_cpus(initialize_counters); 9454 topology_update(); 9455} 9456 9457void set_base_cpu(void) 9458{ 9459 int i; 9460 9461 for (i = 0; i < topo.max_cpu_num + 1; ++i) { 9462 if (cpu_is_not_allowed(i)) 9463 continue; 9464 base_cpu = i; 9465 if (debug > 1) 9466 fprintf(outf, "base_cpu = %d\n", base_cpu); 9467 return; 9468 } 9469 err(-ENODEV, "No valid cpus found"); 9470} 9471 9472bool has_added_counters(void) 9473{ 9474 /* 9475 * It only makes sense to call this after the command line is parsed, 9476 * otherwise sys structure is not populated. 9477 */ 9478 9479 return sys.added_core_counters | sys.added_thread_counters | sys.added_package_counters; 9480} 9481 9482void check_msr_access(void) 9483{ 9484 check_msr_driver(); 9485 check_msr_permission(); 9486 9487 if (no_msr) 9488 bic_disable_msr_access(); 9489} 9490 9491void check_perf_access(void) 9492{ 9493 if (BIC_IS_ENABLED(BIC_IPC)) 9494 if (!has_perf_instr_count_access()) 9495 no_perf = 1; 9496 9497 if (BIC_IS_ENABLED(BIC_LLC_RPS) || BIC_IS_ENABLED(BIC_LLC_HIT)) 9498 if (!has_perf_llc_access()) 9499 no_perf = 1; 9500 9501 if (no_perf) 9502 bic_disable_perf_access(); 9503} 9504 9505bool perf_has_hybrid_devices(void) 9506{ 9507 /* 9508 * 0: unknown 9509 * 1: has separate perf device for p and e core 9510 * -1: doesn't have separate perf device for p and e core 9511 */ 9512 static int cached; 9513 9514 if (cached > 0) 9515 return true; 9516 9517 if (cached < 0) 9518 return false; 9519 9520 if (access("/sys/bus/event_source/devices/cpu_core", F_OK)) { 9521 cached = -1; 9522 return false; 9523 } 9524 9525 if (access("/sys/bus/event_source/devices/cpu_atom", F_OK)) { 9526 cached = -1; 9527 return false; 9528 } 9529 9530 cached = 1; 9531 return true; 9532} 9533 9534int added_perf_counters_init_(struct perf_counter_info *pinfo) 9535{ 9536 size_t num_domains = 0; 9537 unsigned int next_domain; 9538 bool *domain_visited; 9539 unsigned int perf_type, perf_config; 9540 double perf_scale; 9541 int fd_perf; 9542 9543 if (!pinfo) 9544 return 0; 9545 9546 const size_t max_num_domains = MAX(topo.max_cpu_num + 1, MAX(topo.max_core_id + 1, topo.max_package_id + 1)); 9547 9548 domain_visited = calloc(max_num_domains, sizeof(*domain_visited)); 9549 9550 while (pinfo) { 9551 switch (pinfo->scope) { 9552 case SCOPE_CPU: 9553 num_domains = topo.max_cpu_num + 1; 9554 break; 9555 9556 case SCOPE_CORE: 9557 num_domains = topo.max_core_id + 1; 9558 break; 9559 9560 case SCOPE_PACKAGE: 9561 num_domains = topo.max_package_id + 1; 9562 break; 9563 } 9564 9565 /* Allocate buffer for file descriptor for each domain. */ 9566 pinfo->fd_perf_per_domain = calloc(num_domains, sizeof(*pinfo->fd_perf_per_domain)); 9567 if (!pinfo->fd_perf_per_domain) 9568 errx(1, "%s: alloc %s", __func__, "fd_perf_per_domain"); 9569 9570 for (size_t i = 0; i < num_domains; ++i) 9571 pinfo->fd_perf_per_domain[i] = -1; 9572 9573 pinfo->num_domains = num_domains; 9574 pinfo->scale = 1.0; 9575 9576 memset(domain_visited, 0, max_num_domains * sizeof(*domain_visited)); 9577 9578 for (int cpu = 0; cpu < topo.max_cpu_num + 1; ++cpu) { 9579 9580 next_domain = cpu_to_domain(pinfo, cpu); 9581 9582 assert(next_domain < num_domains); 9583 9584 if (cpu_is_not_allowed(cpu)) 9585 continue; 9586 9587 if (domain_visited[next_domain]) 9588 continue; 9589 9590 /* 9591 * Intel hybrid platforms expose different perf devices for P and E cores. 9592 * Instead of one, "/sys/bus/event_source/devices/cpu" device, there are 9593 * "/sys/bus/event_source/devices/{cpu_core,cpu_atom}". 9594 * 9595 * This makes it more complicated to the user, because most of the counters 9596 * are available on both and have to be handled manually, otherwise. 9597 * 9598 * Code below, allow user to use the old "cpu" name, which is translated accordingly. 9599 */ 9600 const char *perf_device = pinfo->device; 9601 9602 if (strcmp(perf_device, "cpu") == 0 && perf_has_hybrid_devices()) { 9603 switch (cpus[cpu].type) { 9604 case INTEL_PCORE_TYPE: 9605 perf_device = "cpu_core"; 9606 break; 9607 9608 case INTEL_ECORE_TYPE: 9609 perf_device = "cpu_atom"; 9610 break; 9611 9612 default: /* Don't change, we will probably fail and report a problem soon. */ 9613 break; 9614 } 9615 } 9616 9617 perf_type = read_perf_type(perf_device); 9618 if (perf_type == (unsigned int)-1) { 9619 warnx("%s: perf/%s/%s: failed to read %s", __func__, perf_device, pinfo->event, "type"); 9620 continue; 9621 } 9622 9623 perf_config = read_perf_config(perf_device, pinfo->event); 9624 if (perf_config == (unsigned int)-1) { 9625 warnx("%s: perf/%s/%s: failed to read %s", __func__, perf_device, pinfo->event, "config"); 9626 continue; 9627 } 9628 9629 /* Scale is not required, some counters just don't have it. */ 9630 perf_scale = read_perf_scale(perf_device, pinfo->event); 9631 if (perf_scale == 0.0) 9632 perf_scale = 1.0; 9633 9634 fd_perf = open_perf_counter(cpu, perf_type, perf_config, -1, 0); 9635 if (fd_perf == -1) { 9636 warnx("%s: perf/%s/%s: failed to open counter on cpu%d", __func__, perf_device, pinfo->event, cpu); 9637 continue; 9638 } 9639 9640 domain_visited[next_domain] = 1; 9641 pinfo->fd_perf_per_domain[next_domain] = fd_perf; 9642 pinfo->scale = perf_scale; 9643 9644 if (debug) 9645 fprintf(stderr, "Add perf/%s/%s cpu%d: %d\n", perf_device, pinfo->event, cpu, pinfo->fd_perf_per_domain[next_domain]); 9646 } 9647 9648 pinfo = pinfo->next; 9649 } 9650 9651 free(domain_visited); 9652 9653 return 0; 9654} 9655 9656void added_perf_counters_init(void) 9657{ 9658 if (added_perf_counters_init_(sys.perf_tp)) 9659 errx(1, "%s: %s", __func__, "thread"); 9660 9661 if (added_perf_counters_init_(sys.perf_cp)) 9662 errx(1, "%s: %s", __func__, "core"); 9663 9664 if (added_perf_counters_init_(sys.perf_pp)) 9665 errx(1, "%s: %s", __func__, "package"); 9666} 9667 9668int parse_telem_info_file(int fd_dir, const char *info_filename, const char *format, unsigned long *output) 9669{ 9670 int fd_telem_info; 9671 FILE *file_telem_info; 9672 unsigned long value; 9673 9674 fd_telem_info = openat(fd_dir, info_filename, O_RDONLY); 9675 if (fd_telem_info == -1) 9676 return -1; 9677 9678 file_telem_info = fdopen(fd_telem_info, "r"); 9679 if (file_telem_info == NULL) { 9680 close(fd_telem_info); 9681 return -1; 9682 } 9683 9684 if (fscanf(file_telem_info, format, &value) != 1) { 9685 fclose(file_telem_info); 9686 return -1; 9687 } 9688 9689 fclose(file_telem_info); 9690 9691 *output = value; 9692 9693 return 0; 9694} 9695 9696struct pmt_mmio *pmt_mmio_open(unsigned int target_guid) 9697{ 9698 struct pmt_diriter_t pmt_iter; 9699 const struct dirent *entry; 9700 struct stat st; 9701 int fd_telem_dir, fd_pmt; 9702 unsigned long guid, size, offset; 9703 size_t mmap_size; 9704 void *mmio; 9705 struct pmt_mmio *head = NULL, *last = NULL; 9706 struct pmt_mmio *new_pmt = NULL; 9707 9708 if (stat(SYSFS_TELEM_PATH, &st) == -1) 9709 return NULL; 9710 9711 pmt_diriter_init(&pmt_iter); 9712 entry = pmt_diriter_begin(&pmt_iter, SYSFS_TELEM_PATH); 9713 if (!entry) { 9714 pmt_diriter_remove(&pmt_iter); 9715 return NULL; 9716 } 9717 9718 for (; entry != NULL; entry = pmt_diriter_next(&pmt_iter)) { 9719 if (fstatat(dirfd(pmt_iter.dir), entry->d_name, &st, 0) == -1) 9720 break; 9721 9722 if (!S_ISDIR(st.st_mode)) 9723 continue; 9724 9725 fd_telem_dir = openat(dirfd(pmt_iter.dir), entry->d_name, O_RDONLY); 9726 if (fd_telem_dir == -1) 9727 break; 9728 9729 if (parse_telem_info_file(fd_telem_dir, "guid", "%lx", &guid)) { 9730 close(fd_telem_dir); 9731 break; 9732 } 9733 9734 if (parse_telem_info_file(fd_telem_dir, "size", "%lu", &size)) { 9735 close(fd_telem_dir); 9736 break; 9737 } 9738 9739 if (guid != target_guid) { 9740 close(fd_telem_dir); 9741 continue; 9742 } 9743 9744 if (parse_telem_info_file(fd_telem_dir, "offset", "%lu", &offset)) { 9745 close(fd_telem_dir); 9746 break; 9747 } 9748 9749 assert(offset == 0); 9750 9751 fd_pmt = openat(fd_telem_dir, "telem", O_RDONLY); 9752 if (fd_pmt == -1) 9753 goto loop_cleanup_and_break; 9754 9755 mmap_size = ROUND_UP_TO_PAGE_SIZE(size); 9756 mmio = mmap(0, mmap_size, PROT_READ, MAP_SHARED, fd_pmt, 0); 9757 if (mmio != MAP_FAILED) { 9758 if (debug) 9759 fprintf(stderr, "%s: 0x%lx mmaped at: %p\n", __func__, guid, mmio); 9760 9761 new_pmt = calloc(1, sizeof(*new_pmt)); 9762 9763 if (!new_pmt) { 9764 fprintf(stderr, "%s: Failed to allocate pmt_mmio\n", __func__); 9765 exit(1); 9766 } 9767 9768 /* 9769 * Create linked list of mmaped regions, 9770 * but preserve the ordering from sysfs. 9771 * Ordering is important for the user to 9772 * use the seq=%u parameter when adding a counter. 9773 */ 9774 new_pmt->guid = guid; 9775 new_pmt->mmio_base = mmio; 9776 new_pmt->pmt_offset = offset; 9777 new_pmt->size = size; 9778 new_pmt->next = pmt_mmios; 9779 9780 if (last) 9781 last->next = new_pmt; 9782 else 9783 head = new_pmt; 9784 9785 last = new_pmt; 9786 } 9787 9788loop_cleanup_and_break: 9789 close(fd_pmt); 9790 close(fd_telem_dir); 9791 } 9792 9793 pmt_diriter_remove(&pmt_iter); 9794 9795 /* 9796 * If we found something, stick just 9797 * created linked list to the front. 9798 */ 9799 if (head) 9800 pmt_mmios = head; 9801 9802 return head; 9803} 9804 9805struct pmt_mmio *pmt_mmio_find(unsigned int guid) 9806{ 9807 struct pmt_mmio *pmmio = pmt_mmios; 9808 9809 while (pmmio) { 9810 if (pmmio->guid == guid) 9811 return pmmio; 9812 9813 pmmio = pmmio->next; 9814 } 9815 9816 return NULL; 9817} 9818 9819void *pmt_get_counter_pointer(struct pmt_mmio *pmmio, unsigned long counter_offset) 9820{ 9821 char *ret; 9822 9823 /* Get base of mmaped PMT file. */ 9824 ret = (char *)pmmio->mmio_base; 9825 9826 /* 9827 * Apply PMT MMIO offset to obtain beginning of the mmaped telemetry data. 9828 * It's not guaranteed that the mmaped memory begins with the telemetry data 9829 * - we might have to apply the offset first. 9830 */ 9831 ret += pmmio->pmt_offset; 9832 9833 /* Apply the counter offset to get the address to the mmaped counter. */ 9834 ret += counter_offset; 9835 9836 return ret; 9837} 9838 9839struct pmt_mmio *pmt_add_guid(unsigned int guid, unsigned int seq) 9840{ 9841 struct pmt_mmio *ret; 9842 9843 ret = pmt_mmio_find(guid); 9844 if (!ret) 9845 ret = pmt_mmio_open(guid); 9846 9847 while (ret && seq) { 9848 ret = ret->next; 9849 --seq; 9850 } 9851 9852 return ret; 9853} 9854 9855enum pmt_open_mode { 9856 PMT_OPEN_TRY, /* Open failure is not an error. */ 9857 PMT_OPEN_REQUIRED, /* Open failure is a fatal error. */ 9858}; 9859 9860struct pmt_counter *pmt_find_counter(struct pmt_counter *pcounter, const char *name) 9861{ 9862 while (pcounter) { 9863 if (strcmp(pcounter->name, name) == 0) 9864 break; 9865 9866 pcounter = pcounter->next; 9867 } 9868 9869 return pcounter; 9870} 9871 9872struct pmt_counter **pmt_get_scope_root(enum counter_scope scope) 9873{ 9874 switch (scope) { 9875 case SCOPE_CPU: 9876 return &sys.pmt_tp; 9877 case SCOPE_CORE: 9878 return &sys.pmt_cp; 9879 case SCOPE_PACKAGE: 9880 return &sys.pmt_pp; 9881 } 9882 9883 __builtin_unreachable(); 9884} 9885 9886void pmt_counter_add_domain(struct pmt_counter *pcounter, unsigned long *pmmio, unsigned int domain_id) 9887{ 9888 /* Make sure the new domain fits. */ 9889 if (domain_id >= pcounter->num_domains) 9890 pmt_counter_resize(pcounter, domain_id + 1); 9891 9892 assert(pcounter->domains); 9893 assert(domain_id < pcounter->num_domains); 9894 9895 pcounter->domains[domain_id].pcounter = pmmio; 9896} 9897 9898int pmt_add_counter(unsigned int guid, unsigned int seq, const char *name, enum pmt_datatype type, 9899 unsigned int lsb, unsigned int msb, unsigned int offset, enum counter_scope scope, 9900 enum counter_format format, unsigned int domain_id, enum pmt_open_mode mode) 9901{ 9902 struct pmt_mmio *mmio; 9903 struct pmt_counter *pcounter; 9904 struct pmt_counter **const pmt_root = pmt_get_scope_root(scope); 9905 bool new_counter = false; 9906 int conflict = 0; 9907 9908 if (lsb > msb) { 9909 fprintf(stderr, "%s: %s: `%s` must be satisfied\n", __func__, "lsb <= msb", name); 9910 exit(1); 9911 } 9912 9913 if (msb >= 64) { 9914 fprintf(stderr, "%s: %s: `%s` must be satisfied\n", __func__, "msb < 64", name); 9915 exit(1); 9916 } 9917 9918 mmio = pmt_add_guid(guid, seq); 9919 if (!mmio) { 9920 if (mode != PMT_OPEN_TRY) { 9921 fprintf(stderr, "%s: failed to map PMT MMIO for guid %x, seq %u\n", __func__, guid, seq); 9922 exit(1); 9923 } 9924 9925 return 1; 9926 } 9927 9928 if (offset >= mmio->size) { 9929 if (mode != PMT_OPEN_TRY) { 9930 fprintf(stderr, "%s: offset %u outside of PMT MMIO size %u\n", __func__, offset, mmio->size); 9931 exit(1); 9932 } 9933 9934 return 1; 9935 } 9936 9937 pcounter = pmt_find_counter(*pmt_root, name); 9938 if (!pcounter) { 9939 pcounter = calloc(1, sizeof(*pcounter)); 9940 new_counter = true; 9941 } 9942 9943 if (new_counter) { 9944 strncpy(pcounter->name, name, ARRAY_SIZE(pcounter->name) - 1); 9945 pcounter->type = type; 9946 pcounter->scope = scope; 9947 pcounter->lsb = lsb; 9948 pcounter->msb = msb; 9949 pcounter->format = format; 9950 } else { 9951 conflict += pcounter->type != type; 9952 conflict += pcounter->scope != scope; 9953 conflict += pcounter->lsb != lsb; 9954 conflict += pcounter->msb != msb; 9955 conflict += pcounter->format != format; 9956 } 9957 9958 if (conflict) { 9959 fprintf(stderr, "%s: conflicting parameters for the PMT counter with the same name %s\n", __func__, name); 9960 exit(1); 9961 } 9962 9963 pmt_counter_add_domain(pcounter, pmt_get_counter_pointer(mmio, offset), domain_id); 9964 9965 if (new_counter) { 9966 pcounter->next = *pmt_root; 9967 *pmt_root = pcounter; 9968 } 9969 9970 return 0; 9971} 9972 9973void pmt_init(void) 9974{ 9975 int cpu_num; 9976 unsigned long seq, offset, mod_num; 9977 9978 if (BIC_IS_ENABLED(BIC_Diec6)) { 9979 pmt_add_counter(PMT_MTL_DC6_GUID, PMT_MTL_DC6_SEQ, "Die%c6", PMT_TYPE_XTAL_TIME, 9980 PMT_COUNTER_MTL_DC6_LSB, PMT_COUNTER_MTL_DC6_MSB, PMT_COUNTER_MTL_DC6_OFFSET, 9981 SCOPE_PACKAGE, FORMAT_DELTA, 0, PMT_OPEN_TRY); 9982 } 9983 9984 if (BIC_IS_ENABLED(BIC_CPU_c1e)) { 9985 seq = 0; 9986 offset = PMT_COUNTER_CWF_MC1E_OFFSET_BASE; 9987 mod_num = 0; /* Relative module number for current PMT file. */ 9988 9989 /* Open the counter for each CPU. */ 9990 for (cpu_num = 0; cpu_num < topo.max_cpu_num;) { 9991 9992 if (cpu_is_not_allowed(cpu_num)) 9993 goto next_loop_iter; 9994 9995 /* 9996 * Set the scope to CPU, even though CWF report the counter per module. 9997 * CPUs inside the same module will read from the same location, instead of reporting zeros. 9998 * 9999 * CWF with newer firmware might require a PMT_TYPE_XTAL_TIME intead of PMT_TYPE_TCORE_CLOCK. 10000 */ 10001 pmt_add_counter(PMT_CWF_MC1E_GUID, seq, "CPU%c1e", PMT_TYPE_TCORE_CLOCK, 10002 PMT_COUNTER_CWF_MC1E_LSB, PMT_COUNTER_CWF_MC1E_MSB, offset, SCOPE_CPU, FORMAT_DELTA, cpu_num, PMT_OPEN_TRY); 10003 10004 /* 10005 * Rather complex logic for each time we go to the next loop iteration, 10006 * so keep it as a label. 10007 */ 10008next_loop_iter: 10009 /* 10010 * Advance the cpu number and check if we should also advance offset to 10011 * the next counter inside the PMT file. 10012 * 10013 * On Clearwater Forest platform, the counter is reported per module, 10014 * so open the same counter for all of the CPUs inside the module. 10015 * That way, reported table show the correct value for all of the CPUs inside the module, 10016 * instead of zeros. 10017 */ 10018 ++cpu_num; 10019 if (cpu_num % PMT_COUNTER_CWF_CPUS_PER_MODULE == 0) { 10020 offset += PMT_COUNTER_CWF_MC1E_OFFSET_INCREMENT; 10021 ++mod_num; 10022 } 10023 10024 /* 10025 * There are PMT_COUNTER_CWF_MC1E_NUM_MODULES_PER_FILE in each PMT file. 10026 * 10027 * If that number is reached, seq must be incremented to advance to the next file in a sequence. 10028 * Offset inside that file and a module counter has to be reset. 10029 */ 10030 if (mod_num == PMT_COUNTER_CWF_MC1E_NUM_MODULES_PER_FILE) { 10031 ++seq; 10032 offset = PMT_COUNTER_CWF_MC1E_OFFSET_BASE; 10033 mod_num = 0; 10034 } 10035 } 10036 } 10037} 10038 10039void turbostat_init() 10040{ 10041 setup_all_buffers(true); 10042 set_base_cpu(); 10043 check_msr_access(); 10044 check_perf_access(); 10045 process_cpuid(); 10046 counter_info_init(); 10047 probe_pm_features(); 10048 msr_perf_init(); 10049 linux_perf_init(); 10050 rapl_perf_init(); 10051 cstate_perf_init(); 10052 perf_llc_init(); 10053 added_perf_counters_init(); 10054 pmt_init(); 10055 10056 for_all_cpus(get_cpu_type, ODD_COUNTERS); 10057 for_all_cpus(get_cpu_type, EVEN_COUNTERS); 10058 10059 if (BIC_IS_ENABLED(BIC_IPC) && has_aperf_access && get_instr_count_fd(base_cpu) != -1) 10060 BIC_PRESENT(BIC_IPC); 10061 10062 /* 10063 * If TSC tweak is needed, but couldn't get it, 10064 * disable more BICs, since it can't be reported accurately. 10065 */ 10066 if (platform->enable_tsc_tweak && !has_base_hz) { 10067 CLR_BIC(BIC_Busy, &bic_enabled); 10068 CLR_BIC(BIC_Bzy_MHz, &bic_enabled); 10069 } 10070} 10071 10072void affinitize_child(void) 10073{ 10074 /* Prefer cpu_possible_set, if available */ 10075 if (sched_setaffinity(0, cpu_possible_setsize, cpu_possible_set)) { 10076 warn("sched_setaffinity cpu_possible_set"); 10077 10078 /* Otherwise, allow child to run on same cpu set as turbostat */ 10079 if (sched_setaffinity(0, cpu_allowed_setsize, cpu_allowed_set)) 10080 warn("sched_setaffinity cpu_allowed_set"); 10081 } 10082} 10083 10084int fork_it(char **argv) 10085{ 10086 pid_t child_pid; 10087 int status; 10088 10089 snapshot_proc_sysfs_files(); 10090 status = for_all_cpus(get_counters, EVEN_COUNTERS); 10091 first_counter_read = 0; 10092 if (status) 10093 exit(status); 10094 gettimeofday(&tv_even, (struct timezone *)NULL); 10095 10096 child_pid = fork(); 10097 if (!child_pid) { 10098 /* child */ 10099 affinitize_child(); 10100 execvp(argv[0], argv); 10101 err(errno, "exec %s", argv[0]); 10102 } else { 10103 10104 /* parent */ 10105 if (child_pid == -1) 10106 err(1, "fork"); 10107 10108 signal(SIGINT, SIG_IGN); 10109 signal(SIGQUIT, SIG_IGN); 10110 if (waitpid(child_pid, &status, 0) == -1) 10111 err(status, "waitpid"); 10112 10113 if (WIFEXITED(status)) 10114 status = WEXITSTATUS(status); 10115 } 10116 /* 10117 * n.b. fork_it() does not check for errors from for_all_cpus() 10118 * because re-starting is problematic when forking 10119 */ 10120 snapshot_proc_sysfs_files(); 10121 for_all_cpus(get_counters, ODD_COUNTERS); 10122 gettimeofday(&tv_odd, (struct timezone *)NULL); 10123 timersub(&tv_odd, &tv_even, &tv_delta); 10124 if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS)) 10125 fprintf(outf, "%s: Counter reset detected\n", progname); 10126 delta_platform(&platform_counters_odd, &platform_counters_even); 10127 10128 compute_average(EVEN_COUNTERS); 10129 format_all_counters(EVEN_COUNTERS); 10130 10131 fprintf(outf, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec / 1000000.0); 10132 10133 flush_output_stderr(); 10134 10135 return status; 10136} 10137 10138int get_and_dump_counters(void) 10139{ 10140 int status; 10141 10142 snapshot_proc_sysfs_files(); 10143 status = for_all_cpus(get_counters, ODD_COUNTERS); 10144 if (status) 10145 return status; 10146 10147 status = for_all_cpus(dump_counters, ODD_COUNTERS); 10148 if (status) 10149 return status; 10150 10151 flush_output_stdout(); 10152 10153 return status; 10154} 10155 10156void print_version() 10157{ 10158 fprintf(outf, "turbostat version 2025.12.02 - Len Brown <lenb@kernel.org>\n"); 10159} 10160 10161#define COMMAND_LINE_SIZE 2048 10162 10163void print_bootcmd(void) 10164{ 10165 char bootcmd[COMMAND_LINE_SIZE]; 10166 FILE *fp; 10167 int ret; 10168 10169 memset(bootcmd, 0, COMMAND_LINE_SIZE); 10170 fp = fopen("/proc/cmdline", "r"); 10171 if (!fp) 10172 return; 10173 10174 ret = fread(bootcmd, sizeof(char), COMMAND_LINE_SIZE - 1, fp); 10175 if (ret) { 10176 bootcmd[ret] = '\0'; 10177 /* the last character is already '\n' */ 10178 fprintf(outf, "Kernel command line: %s", bootcmd); 10179 } 10180 10181 fclose(fp); 10182} 10183 10184struct msr_counter *find_msrp_by_name(struct msr_counter *head, char *name) 10185{ 10186 struct msr_counter *mp; 10187 10188 for (mp = head; mp; mp = mp->next) { 10189 if (debug) 10190 fprintf(stderr, "%s: %s %s\n", __func__, name, mp->name); 10191 if (!strcmp(name, mp->name)) 10192 return mp; 10193 } 10194 return NULL; 10195} 10196 10197int add_counter(unsigned int msr_num, char *path, char *name, 10198 unsigned int width, enum counter_scope scope, enum counter_type type, enum counter_format format, int flags, int id) 10199{ 10200 struct msr_counter *msrp; 10201 10202 if (no_msr && msr_num) 10203 errx(1, "Requested MSR counter 0x%x, but in --no-msr mode", msr_num); 10204 10205 if (debug) 10206 fprintf(stderr, "%s(msr%d, %s, %s, width%d, scope%d, type%d, format%d, flags%x, id%d)\n", 10207 __func__, msr_num, path, name, width, scope, type, format, flags, id); 10208 10209 switch (scope) { 10210 10211 case SCOPE_CPU: 10212 msrp = find_msrp_by_name(sys.tp, name); 10213 if (msrp) { 10214 if (debug) 10215 fprintf(stderr, "%s: %s FOUND\n", __func__, name); 10216 break; 10217 } 10218 if (sys.added_thread_counters++ >= MAX_ADDED_THREAD_COUNTERS) { 10219 warnx("ignoring thread counter %s", name); 10220 return -1; 10221 } 10222 break; 10223 case SCOPE_CORE: 10224 msrp = find_msrp_by_name(sys.cp, name); 10225 if (msrp) { 10226 if (debug) 10227 fprintf(stderr, "%s: %s FOUND\n", __func__, name); 10228 break; 10229 } 10230 if (sys.added_core_counters++ >= MAX_ADDED_CORE_COUNTERS) { 10231 warnx("ignoring core counter %s", name); 10232 return -1; 10233 } 10234 break; 10235 case SCOPE_PACKAGE: 10236 msrp = find_msrp_by_name(sys.pp, name); 10237 if (msrp) { 10238 if (debug) 10239 fprintf(stderr, "%s: %s FOUND\n", __func__, name); 10240 break; 10241 } 10242 if (sys.added_package_counters++ >= MAX_ADDED_PACKAGE_COUNTERS) { 10243 warnx("ignoring package counter %s", name); 10244 return -1; 10245 } 10246 break; 10247 default: 10248 warnx("ignoring counter %s with unknown scope", name); 10249 return -1; 10250 } 10251 10252 if (msrp == NULL) { 10253 msrp = calloc(1, sizeof(struct msr_counter)); 10254 if (msrp == NULL) 10255 err(-1, "calloc msr_counter"); 10256 10257 msrp->msr_num = msr_num; 10258 strncpy(msrp->name, name, NAME_BYTES - 1); 10259 msrp->width = width; 10260 msrp->type = type; 10261 msrp->format = format; 10262 msrp->flags = flags; 10263 10264 switch (scope) { 10265 case SCOPE_CPU: 10266 msrp->next = sys.tp; 10267 sys.tp = msrp; 10268 break; 10269 case SCOPE_CORE: 10270 msrp->next = sys.cp; 10271 sys.cp = msrp; 10272 break; 10273 case SCOPE_PACKAGE: 10274 msrp->next = sys.pp; 10275 sys.pp = msrp; 10276 break; 10277 } 10278 } 10279 10280 if (path) { 10281 struct sysfs_path *sp; 10282 10283 sp = calloc(1, sizeof(struct sysfs_path)); 10284 if (sp == NULL) { 10285 perror("calloc"); 10286 exit(1); 10287 } 10288 strncpy(sp->path, path, PATH_BYTES - 1); 10289 sp->id = id; 10290 sp->next = msrp->sp; 10291 msrp->sp = sp; 10292 } 10293 10294 return 0; 10295} 10296 10297/* 10298 * Initialize the fields used for identifying and opening the counter. 10299 * 10300 * Defer the initialization of any runtime buffers for actually reading 10301 * the counters for when we initialize all perf counters, so we can later 10302 * easily call re_initialize(). 10303 */ 10304struct perf_counter_info *make_perf_counter_info(const char *perf_device, 10305 const char *perf_event, 10306 const char *name, 10307 unsigned int width, enum counter_scope scope, enum counter_type type, enum counter_format format) 10308{ 10309 struct perf_counter_info *pinfo; 10310 10311 pinfo = calloc(1, sizeof(*pinfo)); 10312 if (!pinfo) 10313 errx(1, "%s: Failed to allocate %s/%s\n", __func__, perf_device, perf_event); 10314 10315 strncpy(pinfo->device, perf_device, ARRAY_SIZE(pinfo->device) - 1); 10316 strncpy(pinfo->event, perf_event, ARRAY_SIZE(pinfo->event) - 1); 10317 10318 strncpy(pinfo->name, name, ARRAY_SIZE(pinfo->name) - 1); 10319 pinfo->width = width; 10320 pinfo->scope = scope; 10321 pinfo->type = type; 10322 pinfo->format = format; 10323 10324 return pinfo; 10325} 10326 10327int add_perf_counter(const char *perf_device, const char *perf_event, const char *name_buffer, unsigned int width, 10328 enum counter_scope scope, enum counter_type type, enum counter_format format) 10329{ 10330 struct perf_counter_info *pinfo; 10331 10332 switch (scope) { 10333 case SCOPE_CPU: 10334 if (sys.added_thread_perf_counters >= MAX_ADDED_THREAD_COUNTERS) { 10335 warnx("ignoring thread counter perf/%s/%s", perf_device, perf_event); 10336 return -1; 10337 } 10338 break; 10339 10340 case SCOPE_CORE: 10341 if (sys.added_core_perf_counters >= MAX_ADDED_CORE_COUNTERS) { 10342 warnx("ignoring core counter perf/%s/%s", perf_device, perf_event); 10343 return -1; 10344 } 10345 break; 10346 10347 case SCOPE_PACKAGE: 10348 if (sys.added_package_perf_counters >= MAX_ADDED_PACKAGE_COUNTERS) { 10349 warnx("ignoring package counter perf/%s/%s", perf_device, perf_event); 10350 return -1; 10351 } 10352 break; 10353 } 10354 10355 pinfo = make_perf_counter_info(perf_device, perf_event, name_buffer, width, scope, type, format); 10356 10357 if (!pinfo) 10358 return -1; 10359 10360 switch (scope) { 10361 case SCOPE_CPU: 10362 pinfo->next = sys.perf_tp; 10363 sys.perf_tp = pinfo; 10364 ++sys.added_thread_perf_counters; 10365 break; 10366 10367 case SCOPE_CORE: 10368 pinfo->next = sys.perf_cp; 10369 sys.perf_cp = pinfo; 10370 ++sys.added_core_perf_counters; 10371 break; 10372 10373 case SCOPE_PACKAGE: 10374 pinfo->next = sys.perf_pp; 10375 sys.perf_pp = pinfo; 10376 ++sys.added_package_perf_counters; 10377 break; 10378 } 10379 10380 // FIXME: we might not have debug here yet 10381 if (debug) 10382 fprintf(stderr, "%s: %s/%s, name: %s, scope%d\n", __func__, pinfo->device, pinfo->event, pinfo->name, pinfo->scope); 10383 10384 return 0; 10385} 10386 10387void parse_add_command_msr(char *add_command) 10388{ 10389 int msr_num = 0; 10390 char *path = NULL; 10391 char perf_device[PERF_DEV_NAME_BYTES] = ""; 10392 char perf_event[PERF_EVT_NAME_BYTES] = ""; 10393 char name_buffer[PERF_NAME_BYTES] = ""; 10394 int width = 64; 10395 int fail = 0; 10396 enum counter_scope scope = SCOPE_CPU; 10397 enum counter_type type = COUNTER_CYCLES; 10398 enum counter_format format = FORMAT_DELTA; 10399 10400 while (add_command) { 10401 10402 if (sscanf(add_command, "msr0x%x", &msr_num) == 1) 10403 goto next; 10404 10405 if (sscanf(add_command, "msr%d", &msr_num) == 1) 10406 goto next; 10407 10408 BUILD_BUG_ON(ARRAY_SIZE(perf_device) <= 31); 10409 BUILD_BUG_ON(ARRAY_SIZE(perf_event) <= 31); 10410 if (sscanf(add_command, "perf/%31[^/]/%31[^,]", &perf_device[0], &perf_event[0]) == 2) 10411 goto next; 10412 10413 if (*add_command == '/') { 10414 path = add_command; 10415 goto next; 10416 } 10417 10418 if (sscanf(add_command, "u%d", &width) == 1) { 10419 if ((width == 32) || (width == 64)) 10420 goto next; 10421 width = 64; 10422 } 10423 if (!strncmp(add_command, "cpu", strlen("cpu"))) { 10424 scope = SCOPE_CPU; 10425 goto next; 10426 } 10427 if (!strncmp(add_command, "core", strlen("core"))) { 10428 scope = SCOPE_CORE; 10429 goto next; 10430 } 10431 if (!strncmp(add_command, "package", strlen("package"))) { 10432 scope = SCOPE_PACKAGE; 10433 goto next; 10434 } 10435 if (!strncmp(add_command, "cycles", strlen("cycles"))) { 10436 type = COUNTER_CYCLES; 10437 goto next; 10438 } 10439 if (!strncmp(add_command, "seconds", strlen("seconds"))) { 10440 type = COUNTER_SECONDS; 10441 goto next; 10442 } 10443 if (!strncmp(add_command, "usec", strlen("usec"))) { 10444 type = COUNTER_USEC; 10445 goto next; 10446 } 10447 if (!strncmp(add_command, "raw", strlen("raw"))) { 10448 format = FORMAT_RAW; 10449 goto next; 10450 } 10451 if (!strncmp(add_command, "average", strlen("average"))) { 10452 format = FORMAT_AVERAGE; 10453 goto next; 10454 } 10455 if (!strncmp(add_command, "delta", strlen("delta"))) { 10456 format = FORMAT_DELTA; 10457 goto next; 10458 } 10459 if (!strncmp(add_command, "percent", strlen("percent"))) { 10460 format = FORMAT_PERCENT; 10461 goto next; 10462 } 10463 10464 BUILD_BUG_ON(ARRAY_SIZE(name_buffer) <= 18); 10465 if (sscanf(add_command, "%18s,%*s", name_buffer) == 1) { 10466 char *eos; 10467 10468 eos = strchr(name_buffer, ','); 10469 if (eos) 10470 *eos = '\0'; 10471 goto next; 10472 } 10473 10474next: 10475 add_command = strchr(add_command, ','); 10476 if (add_command) { 10477 *add_command = '\0'; 10478 add_command++; 10479 } 10480 10481 } 10482 if ((msr_num == 0) && (path == NULL) && (perf_device[0] == '\0' || perf_event[0] == '\0')) { 10483 fprintf(stderr, "--add: (msrDDD | msr0xXXX | /path_to_counter | perf/device/event) required\n"); 10484 fail++; 10485 } 10486 10487 /* Test for non-empty perf_device and perf_event */ 10488 const bool is_perf_counter = perf_device[0] && perf_event[0]; 10489 10490 /* generate default column header */ 10491 if (*name_buffer == '\0') { 10492 if (is_perf_counter) { 10493 snprintf(name_buffer, ARRAY_SIZE(name_buffer), "perf/%s", perf_event); 10494 } else { 10495 if (width == 32) 10496 sprintf(name_buffer, "M0x%x%s", msr_num, format == FORMAT_PERCENT ? "%" : ""); 10497 else 10498 sprintf(name_buffer, "M0X%x%s", msr_num, format == FORMAT_PERCENT ? "%" : ""); 10499 } 10500 } 10501 10502 if (is_perf_counter) { 10503 if (add_perf_counter(perf_device, perf_event, name_buffer, width, scope, type, format)) 10504 fail++; 10505 } else { 10506 if (add_counter(msr_num, path, name_buffer, width, scope, type, format, 0, 0)) 10507 fail++; 10508 } 10509 10510 if (fail) { 10511 help(); 10512 exit(1); 10513 } 10514} 10515 10516bool starts_with(const char *str, const char *prefix) 10517{ 10518 return strncmp(prefix, str, strlen(prefix)) == 0; 10519} 10520 10521int pmt_parse_from_path(const char *target_path, unsigned int *out_guid, unsigned int *out_seq) 10522{ 10523 struct pmt_diriter_t pmt_iter; 10524 const struct dirent *dirname; 10525 struct stat stat, target_stat; 10526 int fd_telem_dir = -1; 10527 int fd_target_dir; 10528 unsigned int seq = 0; 10529 unsigned long guid, target_guid; 10530 int ret = -1; 10531 10532 fd_target_dir = open(target_path, O_RDONLY | O_DIRECTORY); 10533 if (fd_target_dir == -1) { 10534 return -1; 10535 } 10536 10537 if (fstat(fd_target_dir, &target_stat) == -1) { 10538 fprintf(stderr, "%s: Failed to stat the target: %s", __func__, strerror(errno)); 10539 exit(1); 10540 } 10541 10542 if (parse_telem_info_file(fd_target_dir, "guid", "%lx", &target_guid)) { 10543 fprintf(stderr, "%s: Failed to parse the target guid file: %s", __func__, strerror(errno)); 10544 exit(1); 10545 } 10546 10547 close(fd_target_dir); 10548 10549 pmt_diriter_init(&pmt_iter); 10550 10551 for (dirname = pmt_diriter_begin(&pmt_iter, SYSFS_TELEM_PATH); dirname != NULL; dirname = pmt_diriter_next(&pmt_iter)) { 10552 10553 fd_telem_dir = openat(dirfd(pmt_iter.dir), dirname->d_name, O_RDONLY | O_DIRECTORY); 10554 if (fd_telem_dir == -1) 10555 continue; 10556 10557 if (parse_telem_info_file(fd_telem_dir, "guid", "%lx", &guid)) { 10558 fprintf(stderr, "%s: Failed to parse the guid file: %s", __func__, strerror(errno)); 10559 continue; 10560 } 10561 10562 if (fstat(fd_telem_dir, &stat) == -1) { 10563 fprintf(stderr, "%s: Failed to stat %s directory: %s", __func__, dirname->d_name, strerror(errno)); 10564 continue; 10565 } 10566 10567 /* 10568 * If reached the same directory as target, exit the loop. 10569 * Seq has the correct value now. 10570 */ 10571 if (stat.st_dev == target_stat.st_dev && stat.st_ino == target_stat.st_ino) { 10572 ret = 0; 10573 break; 10574 } 10575 10576 /* 10577 * If reached directory with the same guid, 10578 * but it's not the target directory yet, 10579 * increment seq and continue the search. 10580 */ 10581 if (guid == target_guid) 10582 ++seq; 10583 10584 close(fd_telem_dir); 10585 fd_telem_dir = -1; 10586 } 10587 10588 pmt_diriter_remove(&pmt_iter); 10589 10590 if (fd_telem_dir != -1) 10591 close(fd_telem_dir); 10592 10593 if (!ret) { 10594 *out_guid = target_guid; 10595 *out_seq = seq; 10596 } 10597 10598 return ret; 10599} 10600 10601void parse_add_command_pmt(char *add_command) 10602{ 10603 char *name = NULL; 10604 char *type_name = NULL; 10605 char *format_name = NULL; 10606 char *direct_path = NULL; 10607 static const char direct_path_prefix[] = "path="; 10608 unsigned int offset; 10609 unsigned int lsb; 10610 unsigned int msb; 10611 unsigned int guid; 10612 unsigned int seq = 0; /* By default, pick first file in a sequence with a given GUID. */ 10613 unsigned int domain_id; 10614 enum counter_scope scope = 0; 10615 enum pmt_datatype type = PMT_TYPE_RAW; 10616 enum counter_format format = FORMAT_RAW; 10617 bool has_offset = false; 10618 bool has_lsb = false; 10619 bool has_msb = false; 10620 bool has_format = true; /* Format has a default value. */ 10621 bool has_guid = false; 10622 bool has_scope = false; 10623 bool has_type = true; /* Type has a default value. */ 10624 10625 /* Consume the "pmt," prefix. */ 10626 add_command = strchr(add_command, ','); 10627 if (!add_command) { 10628 help(); 10629 exit(1); 10630 } 10631 ++add_command; 10632 10633 while (add_command) { 10634 if (starts_with(add_command, "name=")) { 10635 name = add_command + strlen("name="); 10636 goto next; 10637 } 10638 10639 if (starts_with(add_command, "type=")) { 10640 type_name = add_command + strlen("type="); 10641 goto next; 10642 } 10643 10644 if (starts_with(add_command, "domain=")) { 10645 const size_t prefix_len = strlen("domain="); 10646 10647 if (sscanf(add_command + prefix_len, "cpu%u", &domain_id) == 1) { 10648 scope = SCOPE_CPU; 10649 has_scope = true; 10650 } else if (sscanf(add_command + prefix_len, "core%u", &domain_id) == 1) { 10651 scope = SCOPE_CORE; 10652 has_scope = true; 10653 } else if (sscanf(add_command + prefix_len, "package%u", &domain_id) == 1) { 10654 scope = SCOPE_PACKAGE; 10655 has_scope = true; 10656 } 10657 10658 if (!has_scope) { 10659 printf("%s: invalid value for scope. Expected cpu%%u, core%%u or package%%u.\n", __func__); 10660 exit(1); 10661 } 10662 10663 goto next; 10664 } 10665 10666 if (starts_with(add_command, "format=")) { 10667 format_name = add_command + strlen("format="); 10668 goto next; 10669 } 10670 10671 if (sscanf(add_command, "offset=%u", &offset) == 1) { 10672 has_offset = true; 10673 goto next; 10674 } 10675 10676 if (sscanf(add_command, "lsb=%u", &lsb) == 1) { 10677 has_lsb = true; 10678 goto next; 10679 } 10680 10681 if (sscanf(add_command, "msb=%u", &msb) == 1) { 10682 has_msb = true; 10683 goto next; 10684 } 10685 10686 if (sscanf(add_command, "guid=%x", &guid) == 1) { 10687 has_guid = true; 10688 goto next; 10689 } 10690 10691 if (sscanf(add_command, "seq=%x", &seq) == 1) 10692 goto next; 10693 10694 if (strncmp(add_command, direct_path_prefix, strlen(direct_path_prefix)) == 0) { 10695 direct_path = add_command + strlen(direct_path_prefix); 10696 goto next; 10697 } 10698next: 10699 add_command = strchr(add_command, ','); 10700 if (add_command) { 10701 *add_command = '\0'; 10702 add_command++; 10703 } 10704 } 10705 10706 if (!name) { 10707 printf("%s: missing %s\n", __func__, "name"); 10708 exit(1); 10709 } 10710 10711 if (strlen(name) >= PMT_COUNTER_NAME_SIZE_BYTES) { 10712 printf("%s: name has to be at most %d characters long\n", __func__, PMT_COUNTER_NAME_SIZE_BYTES); 10713 exit(1); 10714 } 10715 10716 if (format_name) { 10717 has_format = false; 10718 10719 if (strcmp("raw", format_name) == 0) { 10720 format = FORMAT_RAW; 10721 has_format = true; 10722 } 10723 10724 if (strcmp("average", format_name) == 0) { 10725 format = FORMAT_AVERAGE; 10726 has_format = true; 10727 } 10728 10729 if (strcmp("delta", format_name) == 0) { 10730 format = FORMAT_DELTA; 10731 has_format = true; 10732 } 10733 10734 if (!has_format) { 10735 fprintf(stderr, "%s: Invalid format %s. Expected raw, average or delta\n", __func__, format_name); 10736 exit(1); 10737 } 10738 } 10739 10740 if (type_name) { 10741 has_type = false; 10742 10743 if (strcmp("raw", type_name) == 0) { 10744 type = PMT_TYPE_RAW; 10745 has_type = true; 10746 } 10747 10748 if (strcmp("txtal_time", type_name) == 0) { 10749 type = PMT_TYPE_XTAL_TIME; 10750 has_type = true; 10751 } 10752 10753 if (strcmp("tcore_clock", type_name) == 0) { 10754 type = PMT_TYPE_TCORE_CLOCK; 10755 has_type = true; 10756 } 10757 10758 if (!has_type) { 10759 printf("%s: invalid %s: %s\n", __func__, "type", type_name); 10760 exit(1); 10761 } 10762 } 10763 10764 if (!has_offset) { 10765 printf("%s : missing %s\n", __func__, "offset"); 10766 exit(1); 10767 } 10768 10769 if (!has_lsb) { 10770 printf("%s: missing %s\n", __func__, "lsb"); 10771 exit(1); 10772 } 10773 10774 if (!has_msb) { 10775 printf("%s: missing %s\n", __func__, "msb"); 10776 exit(1); 10777 } 10778 10779 if (direct_path && has_guid) { 10780 printf("%s: path and guid+seq parameters are mutually exclusive\n" 10781 "notice: passed guid=0x%x and path=%s\n", __func__, guid, direct_path); 10782 exit(1); 10783 } 10784 10785 if (direct_path) { 10786 if (pmt_parse_from_path(direct_path, &guid, &seq)) { 10787 printf("%s: failed to parse PMT file from %s\n", __func__, direct_path); 10788 exit(1); 10789 } 10790 10791 /* GUID was just infered from the direct path. */ 10792 has_guid = true; 10793 } 10794 10795 if (!has_guid) { 10796 printf("%s: missing %s\n", __func__, "guid or path"); 10797 exit(1); 10798 } 10799 10800 if (!has_scope) { 10801 printf("%s: missing %s\n", __func__, "scope"); 10802 exit(1); 10803 } 10804 10805 if (lsb > msb) { 10806 printf("%s: lsb > msb doesn't make sense\n", __func__); 10807 exit(1); 10808 } 10809 10810 pmt_add_counter(guid, seq, name, type, lsb, msb, offset, scope, format, domain_id, PMT_OPEN_REQUIRED); 10811} 10812 10813void parse_add_command(char *add_command) 10814{ 10815 if (strncmp(add_command, "pmt", strlen("pmt")) == 0) 10816 return parse_add_command_pmt(add_command); 10817 return parse_add_command_msr(add_command); 10818} 10819 10820int is_deferred_add(char *name) 10821{ 10822 int i; 10823 10824 for (i = 0; i < deferred_add_index; ++i) 10825 if (!strcmp(name, deferred_add_names[i])) { 10826 deferred_add_consumed |= (1 << i); 10827 return 1; 10828 } 10829 return 0; 10830} 10831 10832int is_deferred_skip(char *name) 10833{ 10834 int i; 10835 10836 for (i = 0; i < deferred_skip_index; ++i) 10837 if (!strcmp(name, deferred_skip_names[i])) { 10838 deferred_skip_consumed |= (1 << i); 10839 return 1; 10840 } 10841 return 0; 10842} 10843 10844void verify_deferred_consumed(void) 10845{ 10846 int i; 10847 int fail = 0; 10848 10849 for (i = 0; i < deferred_add_index; ++i) { 10850 if (!(deferred_add_consumed & (1 << i))) { 10851 warnx("Counter '%s' can not be added.", deferred_add_names[i]); 10852 fail++; 10853 } 10854 } 10855 for (i = 0; i < deferred_skip_index; ++i) { 10856 if (!(deferred_skip_consumed & (1 << i))) { 10857 warnx("Counter '%s' can not be skipped.", deferred_skip_names[i]); 10858 fail++; 10859 } 10860 } 10861 if (fail) 10862 exit(-EINVAL); 10863} 10864 10865void probe_cpuidle_residency(void) 10866{ 10867 char path[64]; 10868 char name_buf[16]; 10869 FILE *input; 10870 int state; 10871 int min_state = 1024, max_state = 0; 10872 char *sp; 10873 10874 for (state = 10; state >= 0; --state) { 10875 10876 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", base_cpu, state); 10877 input = fopen(path, "r"); 10878 if (input == NULL) 10879 continue; 10880 if (!fgets(name_buf, sizeof(name_buf), input)) 10881 err(1, "%s: failed to read file", path); 10882 10883 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */ 10884 sp = strchr(name_buf, '-'); 10885 if (!sp) 10886 sp = strchrnul(name_buf, '\n'); 10887 *sp = '%'; 10888 *(sp + 1) = '\0'; 10889 10890 remove_underbar(name_buf); 10891 10892 fclose(input); 10893 10894 sprintf(path, "cpuidle/state%d/time", state); 10895 10896 if (!DO_BIC(BIC_pct_idle) && !is_deferred_add(name_buf)) 10897 continue; 10898 10899 if (is_deferred_skip(name_buf)) 10900 continue; 10901 10902 add_counter(0, path, name_buf, 32, SCOPE_CPU, COUNTER_USEC, FORMAT_PERCENT, SYSFS_PERCPU, 0); 10903 10904 if (state > max_state) 10905 max_state = state; 10906 if (state < min_state) 10907 min_state = state; 10908 } 10909} 10910 10911static bool cpuidle_counter_wanted(char *name) 10912{ 10913 if (is_deferred_skip(name)) 10914 return false; 10915 10916 return DO_BIC(BIC_cpuidle) || is_deferred_add(name); 10917} 10918 10919void probe_cpuidle_counts(void) 10920{ 10921 char path[64]; 10922 char name_buf[16]; 10923 FILE *input; 10924 int state; 10925 int min_state = 1024, max_state = 0; 10926 char *sp; 10927 10928 if (!DO_BIC(BIC_cpuidle) && !deferred_add_index) 10929 return; 10930 10931 for (state = 10; state >= 0; --state) { 10932 10933 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", base_cpu, state); 10934 input = fopen(path, "r"); 10935 if (input == NULL) 10936 continue; 10937 if (!fgets(name_buf, sizeof(name_buf), input)) 10938 err(1, "%s: failed to read file", path); 10939 fclose(input); 10940 10941 remove_underbar(name_buf); 10942 10943 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */ 10944 sp = strchr(name_buf, '-'); 10945 if (!sp) 10946 sp = strchrnul(name_buf, '\n'); 10947 10948 /* 10949 * The 'below' sysfs file always contains 0 for the deepest state (largest index), 10950 * do not add it. 10951 */ 10952 if (state != max_state) { 10953 /* 10954 * Add 'C1+' for C1, and so on. The 'below' sysfs file always contains 0 for 10955 * the last state, so do not add it. 10956 */ 10957 *sp = '+'; 10958 *(sp + 1) = '\0'; 10959 if (cpuidle_counter_wanted(name_buf)) { 10960 sprintf(path, "cpuidle/state%d/below", state); 10961 add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); 10962 } 10963 } 10964 10965 *sp = '\0'; 10966 if (cpuidle_counter_wanted(name_buf)) { 10967 sprintf(path, "cpuidle/state%d/usage", state); 10968 add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); 10969 } 10970 10971 /* 10972 * The 'above' sysfs file always contains 0 for the shallowest state (smallest 10973 * index), do not add it. 10974 */ 10975 if (state != min_state) { 10976 *sp = '-'; 10977 *(sp + 1) = '\0'; 10978 if (cpuidle_counter_wanted(name_buf)) { 10979 sprintf(path, "cpuidle/state%d/above", state); 10980 add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); 10981 } 10982 } 10983 } 10984} 10985 10986/* 10987 * parse cpuset with following syntax 10988 * 1,2,4..6,8-10 and set bits in cpu_subset 10989 */ 10990void parse_cpu_command(char *optarg) 10991{ 10992 if (!strcmp(optarg, "core")) { 10993 if (cpu_subset) 10994 goto error; 10995 show_core_only++; 10996 return; 10997 } 10998 if (!strcmp(optarg, "package")) { 10999 if (cpu_subset) 11000 goto error; 11001 show_pkg_only++; 11002 return; 11003 } 11004 if (show_core_only || show_pkg_only) 11005 goto error; 11006 11007 cpu_subset = CPU_ALLOC(CPU_SUBSET_MAXCPUS); 11008 if (cpu_subset == NULL) 11009 err(3, "CPU_ALLOC"); 11010 cpu_subset_size = CPU_ALLOC_SIZE(CPU_SUBSET_MAXCPUS); 11011 11012 CPU_ZERO_S(cpu_subset_size, cpu_subset); 11013 11014 if (parse_cpu_str(optarg, cpu_subset, cpu_subset_size)) 11015 goto error; 11016 11017 return; 11018 11019error: 11020 fprintf(stderr, "\"--cpu %s\" malformed\n", optarg); 11021 help(); 11022 exit(-1); 11023} 11024 11025void cmdline(int argc, char **argv) 11026{ 11027 int opt; 11028 int option_index = 0; 11029 static struct option long_options[] = { 11030 { "add", required_argument, 0, 'a' }, 11031 { "cpu", required_argument, 0, 'c' }, 11032 { "Dump", no_argument, 0, 'D' }, 11033 { "debug", no_argument, 0, 'd' }, /* internal, not documented */ 11034 { "enable", required_argument, 0, 'e' }, 11035 { "force", no_argument, 0, 'f' }, 11036 { "interval", required_argument, 0, 'i' }, 11037 { "IPC", no_argument, 0, 'I' }, 11038 { "num_iterations", required_argument, 0, 'n' }, 11039 { "header_iterations", required_argument, 0, 'N' }, 11040 { "help", no_argument, 0, 'h' }, 11041 { "hide", required_argument, 0, 'H' }, // meh, -h taken by --help 11042 { "Joules", no_argument, 0, 'J' }, 11043 { "list", no_argument, 0, 'l' }, 11044 { "out", required_argument, 0, 'o' }, 11045 { "quiet", no_argument, 0, 'q' }, 11046 { "no-msr", no_argument, 0, 'M' }, 11047 { "no-perf", no_argument, 0, 'P' }, 11048 { "show", required_argument, 0, 's' }, 11049 { "Summary", no_argument, 0, 'S' }, 11050 { "TCC", required_argument, 0, 'T' }, 11051 { "version", no_argument, 0, 'v' }, 11052 { 0, 0, 0, 0 } 11053 }; 11054 11055 progname = argv[0]; 11056 11057 /* 11058 * Parse some options early, because they may make other options invalid, 11059 * like adding the MSR counter with --add and at the same time using --no-msr. 11060 */ 11061 while ((opt = getopt_long_only(argc, argv, "+MPn:", long_options, &option_index)) != -1) { 11062 switch (opt) { 11063 case 'M': 11064 no_msr = 1; 11065 break; 11066 case 'P': 11067 no_perf = 1; 11068 break; 11069 default: 11070 break; 11071 } 11072 } 11073 optind = 0; 11074 11075 while ((opt = getopt_long_only(argc, argv, "+C:c:Dde:hi:Jn:o:qMST:v", long_options, &option_index)) != -1) { 11076 switch (opt) { 11077 case 'a': 11078 parse_add_command(optarg); 11079 break; 11080 case 'c': 11081 parse_cpu_command(optarg); 11082 break; 11083 case 'D': 11084 dump_only++; 11085 /* 11086 * Force the no_perf early to prevent using it as a source. 11087 * User asks for raw values, but perf returns them relative 11088 * to the opening of the file descriptor. 11089 */ 11090 no_perf = 1; 11091 break; 11092 case 'e': 11093 /* --enable specified counter, without clearning existing list */ 11094 bic_lookup(&bic_enabled, optarg, SHOW_LIST); 11095 break; 11096 case 'f': 11097 force_load++; 11098 break; 11099 case 'd': 11100 debug++; 11101 bic_set_all(&bic_enabled); 11102 break; 11103 case 'H': 11104 /* 11105 * --hide: do not show those specified 11106 * multiple invocations simply clear more bits in enabled mask 11107 */ 11108 { 11109 cpu_set_t bic_group_hide; 11110 11111 BIC_INIT(&bic_group_hide); 11112 11113 bic_lookup(&bic_group_hide, optarg, HIDE_LIST); 11114 bic_clear_bits(&bic_enabled, &bic_group_hide); 11115 } 11116 break; 11117 case 'h': 11118 default: 11119 help(); 11120 exit(1); 11121 case 'i': 11122 { 11123 double interval = strtod(optarg, NULL); 11124 11125 if (interval < 0.001) { 11126 fprintf(outf, "interval %f seconds is too small\n", interval); 11127 exit(2); 11128 } 11129 11130 interval_tv.tv_sec = interval_ts.tv_sec = interval; 11131 interval_tv.tv_usec = (interval - interval_tv.tv_sec) * 1000000; 11132 interval_ts.tv_nsec = (interval - interval_ts.tv_sec) * 1000000000; 11133 } 11134 break; 11135 case 'J': 11136 rapl_joules++; 11137 break; 11138 case 'l': 11139 bic_set_all(&bic_enabled); 11140 list_header_only++; 11141 quiet++; 11142 break; 11143 case 'o': 11144 outf = fopen_or_die(optarg, "w"); 11145 break; 11146 case 'q': 11147 quiet = 1; 11148 break; 11149 case 'M': 11150 case 'P': 11151 /* Parsed earlier */ 11152 break; 11153 case 'n': 11154 num_iterations = strtod(optarg, NULL); 11155 11156 if (num_iterations <= 0) { 11157 fprintf(outf, "iterations %d should be positive number\n", num_iterations); 11158 exit(2); 11159 } 11160 break; 11161 case 'N': 11162 header_iterations = strtod(optarg, NULL); 11163 11164 if (header_iterations <= 0) { 11165 fprintf(outf, "iterations %d should be positive number\n", header_iterations); 11166 exit(2); 11167 } 11168 break; 11169 case 's': 11170 /* 11171 * --show: show only those specified 11172 * The 1st invocation will clear and replace the enabled mask 11173 * subsequent invocations can add to it. 11174 */ 11175 if (shown == 0) 11176 BIC_INIT(&bic_enabled); 11177 bic_lookup(&bic_enabled, optarg, SHOW_LIST); 11178 shown = 1; 11179 break; 11180 case 'S': 11181 summary_only++; 11182 break; 11183 case 'T': 11184 tj_max_override = atoi(optarg); 11185 break; 11186 case 'v': 11187 print_version(); 11188 exit(0); 11189 break; 11190 } 11191 } 11192} 11193 11194void set_rlimit(void) 11195{ 11196 struct rlimit limit; 11197 11198 if (getrlimit(RLIMIT_NOFILE, &limit) < 0) 11199 err(1, "Failed to get rlimit"); 11200 11201 if (limit.rlim_max < MAX_NOFILE) 11202 limit.rlim_max = MAX_NOFILE; 11203 if (limit.rlim_cur < MAX_NOFILE) 11204 limit.rlim_cur = MAX_NOFILE; 11205 11206 if (setrlimit(RLIMIT_NOFILE, &limit) < 0) 11207 err(1, "Failed to set rlimit"); 11208} 11209 11210int main(int argc, char **argv) 11211{ 11212 int fd, ret; 11213 11214 bic_groups_init(); 11215 11216 fd = open("/sys/fs/cgroup/cgroup.procs", O_WRONLY); 11217 if (fd < 0) 11218 goto skip_cgroup_setting; 11219 11220 ret = write(fd, "0\n", 2); 11221 if (ret == -1) 11222 perror("Can't update cgroup\n"); 11223 11224 close(fd); 11225 11226skip_cgroup_setting: 11227 outf = stderr; 11228 cmdline(argc, argv); 11229 11230 if (!quiet) { 11231 print_version(); 11232 print_bootcmd(); 11233 } 11234 11235 probe_cpuidle_residency(); 11236 probe_cpuidle_counts(); 11237 11238 verify_deferred_consumed(); 11239 11240 if (!getuid()) 11241 set_rlimit(); 11242 11243 turbostat_init(); 11244 11245 if (!no_msr) 11246 msr_sum_record(); 11247 11248 /* dump counters and exit */ 11249 if (dump_only) 11250 return get_and_dump_counters(); 11251 11252 /* list header and exit */ 11253 if (list_header_only) { 11254 print_header(","); 11255 flush_output_stdout(); 11256 return 0; 11257 } 11258 11259 /* 11260 * if any params left, it must be a command to fork 11261 */ 11262 if (argc - optind) 11263 return fork_it(argv + optind); 11264 else 11265 turbostat_loop(); 11266 11267 return 0; 11268}
~/
Read-only file preview.