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