diff options
| -rw-r--r-- | tools/power/x86/turbostat/.gitignore | 1 | ||||
| -rw-r--r-- | tools/power/x86/turbostat/Makefile | 2 | ||||
| -rw-r--r-- | tools/power/x86/turbostat/turbostat.c | 441 |
3 files changed, 244 insertions, 200 deletions
diff --git a/tools/power/x86/turbostat/.gitignore b/tools/power/x86/turbostat/.gitignore new file mode 100644 index 000000000000..7521370d3568 --- /dev/null +++ b/tools/power/x86/turbostat/.gitignore | |||
| @@ -0,0 +1 @@ | |||
| turbostat | |||
diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile index f09641da40d4..d1b3a361e526 100644 --- a/tools/power/x86/turbostat/Makefile +++ b/tools/power/x86/turbostat/Makefile | |||
| @@ -5,7 +5,7 @@ DESTDIR := | |||
| 5 | 5 | ||
| 6 | turbostat : turbostat.c | 6 | turbostat : turbostat.c |
| 7 | CFLAGS += -Wall | 7 | CFLAGS += -Wall |
| 8 | CFLAGS += -I../../../../arch/x86/include/uapi/ | 8 | CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/uapi/asm/msr-index.h"' |
| 9 | 9 | ||
| 10 | %: %.c | 10 | %: %.c |
| 11 | @mkdir -p $(BUILD_OUTPUT) | 11 | @mkdir -p $(BUILD_OUTPUT) |
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 9d77f13c2d25..77eb130168da 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c | |||
| @@ -20,8 +20,10 @@ | |||
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #define _GNU_SOURCE | 22 | #define _GNU_SOURCE |
| 23 | #include <asm/msr.h> | 23 | #include MSRHEADER |
| 24 | #include <stdarg.h> | ||
| 24 | #include <stdio.h> | 25 | #include <stdio.h> |
| 26 | #include <err.h> | ||
| 25 | #include <unistd.h> | 27 | #include <unistd.h> |
| 26 | #include <sys/types.h> | 28 | #include <sys/types.h> |
| 27 | #include <sys/wait.h> | 29 | #include <sys/wait.h> |
| @@ -35,13 +37,16 @@ | |||
| 35 | #include <string.h> | 37 | #include <string.h> |
| 36 | #include <ctype.h> | 38 | #include <ctype.h> |
| 37 | #include <sched.h> | 39 | #include <sched.h> |
| 40 | #include <cpuid.h> | ||
| 38 | 41 | ||
| 39 | char *proc_stat = "/proc/stat"; | 42 | char *proc_stat = "/proc/stat"; |
| 40 | unsigned int interval_sec = 5; /* set with -i interval_sec */ | 43 | unsigned int interval_sec = 5; /* set with -i interval_sec */ |
| 41 | unsigned int verbose; /* set with -v */ | 44 | unsigned int verbose; /* set with -v */ |
| 42 | unsigned int rapl_verbose; /* set with -R */ | 45 | unsigned int rapl_verbose; /* set with -R */ |
| 46 | unsigned int rapl_joules; /* set with -J */ | ||
| 43 | unsigned int thermal_verbose; /* set with -T */ | 47 | unsigned int thermal_verbose; /* set with -T */ |
| 44 | unsigned int summary_only; /* set with -s */ | 48 | unsigned int summary_only; /* set with -S */ |
| 49 | unsigned int dump_only; /* set with -s */ | ||
| 45 | unsigned int skip_c0; | 50 | unsigned int skip_c0; |
| 46 | unsigned int skip_c1; | 51 | unsigned int skip_c1; |
| 47 | unsigned int do_nhm_cstates; | 52 | unsigned int do_nhm_cstates; |
| @@ -77,14 +82,32 @@ unsigned int tcc_activation_temp_override; | |||
| 77 | double rapl_power_units, rapl_energy_units, rapl_time_units; | 82 | double rapl_power_units, rapl_energy_units, rapl_time_units; |
| 78 | double rapl_joule_counter_range; | 83 | double rapl_joule_counter_range; |
| 79 | 84 | ||
| 80 | #define RAPL_PKG (1 << 0) | 85 | #define RAPL_PKG (1 << 0) |
| 81 | #define RAPL_CORES (1 << 1) | 86 | /* 0x610 MSR_PKG_POWER_LIMIT */ |
| 82 | #define RAPL_GFX (1 << 2) | 87 | /* 0x611 MSR_PKG_ENERGY_STATUS */ |
| 83 | #define RAPL_DRAM (1 << 3) | 88 | #define RAPL_PKG_PERF_STATUS (1 << 1) |
| 84 | #define RAPL_PKG_PERF_STATUS (1 << 4) | 89 | /* 0x613 MSR_PKG_PERF_STATUS */ |
| 85 | #define RAPL_DRAM_PERF_STATUS (1 << 5) | 90 | #define RAPL_PKG_POWER_INFO (1 << 2) |
| 86 | #define RAPL_PKG_POWER_INFO (1 << 6) | 91 | /* 0x614 MSR_PKG_POWER_INFO */ |
| 87 | #define RAPL_CORE_POLICY (1 << 7) | 92 | |
| 93 | #define RAPL_DRAM (1 << 3) | ||
| 94 | /* 0x618 MSR_DRAM_POWER_LIMIT */ | ||
| 95 | /* 0x619 MSR_DRAM_ENERGY_STATUS */ | ||
| 96 | /* 0x61c MSR_DRAM_POWER_INFO */ | ||
| 97 | #define RAPL_DRAM_PERF_STATUS (1 << 4) | ||
| 98 | /* 0x61b MSR_DRAM_PERF_STATUS */ | ||
| 99 | |||
| 100 | #define RAPL_CORES (1 << 5) | ||
| 101 | /* 0x638 MSR_PP0_POWER_LIMIT */ | ||
| 102 | /* 0x639 MSR_PP0_ENERGY_STATUS */ | ||
| 103 | #define RAPL_CORE_POLICY (1 << 6) | ||
| 104 | /* 0x63a MSR_PP0_POLICY */ | ||
| 105 | |||
| 106 | |||
| 107 | #define RAPL_GFX (1 << 7) | ||
| 108 | /* 0x640 MSR_PP1_POWER_LIMIT */ | ||
| 109 | /* 0x641 MSR_PP1_ENERGY_STATUS */ | ||
| 110 | /* 0x642 MSR_PP1_POLICY */ | ||
| 88 | #define TJMAX_DEFAULT 100 | 111 | #define TJMAX_DEFAULT 100 |
| 89 | 112 | ||
| 90 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) | 113 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) |
| @@ -234,7 +257,7 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr) | |||
| 234 | close(fd); | 257 | close(fd); |
| 235 | 258 | ||
| 236 | if (retval != sizeof *msr) { | 259 | if (retval != sizeof *msr) { |
| 237 | fprintf(stderr, "%s offset 0x%zx read failed\n", pathname, offset); | 260 | fprintf(stderr, "%s offset 0x%llx read failed\n", pathname, (unsigned long long)offset); |
| 238 | return -1; | 261 | return -1; |
| 239 | } | 262 | } |
| 240 | 263 | ||
| @@ -296,70 +319,92 @@ void print_header(void) | |||
| 296 | outp += sprintf(outp, " %%pc10"); | 319 | outp += sprintf(outp, " %%pc10"); |
| 297 | } | 320 | } |
| 298 | 321 | ||
| 299 | if (do_rapl & RAPL_PKG) | 322 | if (do_rapl && !rapl_joules) { |
| 300 | outp += sprintf(outp, " Pkg_W"); | 323 | if (do_rapl & RAPL_PKG) |
| 301 | if (do_rapl & RAPL_CORES) | 324 | outp += sprintf(outp, " Pkg_W"); |
| 302 | outp += sprintf(outp, " Cor_W"); | 325 | if (do_rapl & RAPL_CORES) |
| 303 | if (do_rapl & RAPL_GFX) | 326 | outp += sprintf(outp, " Cor_W"); |
| 304 | outp += sprintf(outp, " GFX_W"); | 327 | if (do_rapl & RAPL_GFX) |
| 305 | if (do_rapl & RAPL_DRAM) | 328 | outp += sprintf(outp, " GFX_W"); |
| 306 | outp += sprintf(outp, " RAM_W"); | 329 | if (do_rapl & RAPL_DRAM) |
| 307 | if (do_rapl & RAPL_PKG_PERF_STATUS) | 330 | outp += sprintf(outp, " RAM_W"); |
| 308 | outp += sprintf(outp, " PKG_%%"); | 331 | if (do_rapl & RAPL_PKG_PERF_STATUS) |
| 309 | if (do_rapl & RAPL_DRAM_PERF_STATUS) | 332 | outp += sprintf(outp, " PKG_%%"); |
| 310 | outp += sprintf(outp, " RAM_%%"); | 333 | if (do_rapl & RAPL_DRAM_PERF_STATUS) |
| 334 | outp += sprintf(outp, " RAM_%%"); | ||
| 335 | } else { | ||
| 336 | if (do_rapl & RAPL_PKG) | ||
| 337 | outp += sprintf(outp, " Pkg_J"); | ||
| 338 | if (do_rapl & RAPL_CORES) | ||
| 339 | outp += sprintf(outp, " Cor_J"); | ||
| 340 | if (do_rapl & RAPL_GFX) | ||
| 341 | outp += sprintf(outp, " GFX_J"); | ||
| 342 | if (do_rapl & RAPL_DRAM) | ||
| 343 | outp += sprintf(outp, " RAM_W"); | ||
| 344 | if (do_rapl & RAPL_PKG_PERF_STATUS) | ||
| 345 | outp += sprintf(outp, " PKG_%%"); | ||
| 346 | if (do_rapl & RAPL_DRAM_PERF_STATUS) | ||
| 347 | outp += sprintf(outp, " RAM_%%"); | ||
| 348 | outp += sprintf(outp, " time"); | ||
| 311 | 349 | ||
| 350 | } | ||
| 312 | outp += sprintf(outp, "\n"); | 351 | outp += sprintf(outp, "\n"); |
| 313 | } | 352 | } |
| 314 | 353 | ||
| 315 | int dump_counters(struct thread_data *t, struct core_data *c, | 354 | int dump_counters(struct thread_data *t, struct core_data *c, |
| 316 | struct pkg_data *p) | 355 | struct pkg_data *p) |
| 317 | { | 356 | { |
| 318 | fprintf(stderr, "t %p, c %p, p %p\n", t, c, p); | 357 | outp += sprintf(outp, "t %p, c %p, p %p\n", t, c, p); |
| 319 | 358 | ||
| 320 | if (t) { | 359 | if (t) { |
| 321 | fprintf(stderr, "CPU: %d flags 0x%x\n", t->cpu_id, t->flags); | 360 | outp += sprintf(outp, "CPU: %d flags 0x%x\n", |
| 322 | fprintf(stderr, "TSC: %016llX\n", t->tsc); | 361 | t->cpu_id, t->flags); |
| 323 | fprintf(stderr, "aperf: %016llX\n", t->aperf); | 362 | outp += sprintf(outp, "TSC: %016llX\n", t->tsc); |
| 324 | fprintf(stderr, "mperf: %016llX\n", t->mperf); | 363 | outp += sprintf(outp, "aperf: %016llX\n", t->aperf); |
| 325 | fprintf(stderr, "c1: %016llX\n", t->c1); | 364 | outp += sprintf(outp, "mperf: %016llX\n", t->mperf); |
| 326 | fprintf(stderr, "msr0x%x: %08llX\n", | 365 | outp += sprintf(outp, "c1: %016llX\n", t->c1); |
| 366 | outp += sprintf(outp, "msr0x%x: %08llX\n", | ||
| 327 | extra_delta_offset32, t->extra_delta32); | 367 | extra_delta_offset32, t->extra_delta32); |
| 328 | fprintf(stderr, "msr0x%x: %016llX\n", | 368 | outp += sprintf(outp, "msr0x%x: %016llX\n", |
| 329 | extra_delta_offset64, t->extra_delta64); | 369 | extra_delta_offset64, t->extra_delta64); |
| 330 | fprintf(stderr, "msr0x%x: %08llX\n", | 370 | outp += sprintf(outp, "msr0x%x: %08llX\n", |
| 331 | extra_msr_offset32, t->extra_msr32); | 371 | extra_msr_offset32, t->extra_msr32); |
| 332 | fprintf(stderr, "msr0x%x: %016llX\n", | 372 | outp += sprintf(outp, "msr0x%x: %016llX\n", |
| 333 | extra_msr_offset64, t->extra_msr64); | 373 | extra_msr_offset64, t->extra_msr64); |
| 334 | if (do_smi) | 374 | if (do_smi) |
| 335 | fprintf(stderr, "SMI: %08X\n", t->smi_count); | 375 | outp += sprintf(outp, "SMI: %08X\n", t->smi_count); |
| 336 | } | 376 | } |
| 337 | 377 | ||
| 338 | if (c) { | 378 | if (c) { |
| 339 | fprintf(stderr, "core: %d\n", c->core_id); | 379 | outp += sprintf(outp, "core: %d\n", c->core_id); |
| 340 | fprintf(stderr, "c3: %016llX\n", c->c3); | 380 | outp += sprintf(outp, "c3: %016llX\n", c->c3); |
| 341 | fprintf(stderr, "c6: %016llX\n", c->c6); | 381 | outp += sprintf(outp, "c6: %016llX\n", c->c6); |
| 342 | fprintf(stderr, "c7: %016llX\n", c->c7); | 382 | outp += sprintf(outp, "c7: %016llX\n", c->c7); |
| 343 | fprintf(stderr, "DTS: %dC\n", c->core_temp_c); | 383 | outp += sprintf(outp, "DTS: %dC\n", c->core_temp_c); |
| 344 | } | 384 | } |
| 345 | 385 | ||
| 346 | if (p) { | 386 | if (p) { |
| 347 | fprintf(stderr, "package: %d\n", p->package_id); | 387 | outp += sprintf(outp, "package: %d\n", p->package_id); |
| 348 | fprintf(stderr, "pc2: %016llX\n", p->pc2); | 388 | outp += sprintf(outp, "pc2: %016llX\n", p->pc2); |
| 349 | fprintf(stderr, "pc3: %016llX\n", p->pc3); | 389 | outp += sprintf(outp, "pc3: %016llX\n", p->pc3); |
| 350 | fprintf(stderr, "pc6: %016llX\n", p->pc6); | 390 | outp += sprintf(outp, "pc6: %016llX\n", p->pc6); |
| 351 | fprintf(stderr, "pc7: %016llX\n", p->pc7); | 391 | outp += sprintf(outp, "pc7: %016llX\n", p->pc7); |
| 352 | fprintf(stderr, "pc8: %016llX\n", p->pc8); | 392 | outp += sprintf(outp, "pc8: %016llX\n", p->pc8); |
| 353 | fprintf(stderr, "pc9: %016llX\n", p->pc9); | 393 | outp += sprintf(outp, "pc9: %016llX\n", p->pc9); |
| 354 | fprintf(stderr, "pc10: %016llX\n", p->pc10); | 394 | outp += sprintf(outp, "pc10: %016llX\n", p->pc10); |
| 355 | fprintf(stderr, "Joules PKG: %0X\n", p->energy_pkg); | 395 | outp += sprintf(outp, "Joules PKG: %0X\n", p->energy_pkg); |
| 356 | fprintf(stderr, "Joules COR: %0X\n", p->energy_cores); | 396 | outp += sprintf(outp, "Joules COR: %0X\n", p->energy_cores); |
| 357 | fprintf(stderr, "Joules GFX: %0X\n", p->energy_gfx); | 397 | outp += sprintf(outp, "Joules GFX: %0X\n", p->energy_gfx); |
| 358 | fprintf(stderr, "Joules RAM: %0X\n", p->energy_dram); | 398 | outp += sprintf(outp, "Joules RAM: %0X\n", p->energy_dram); |
| 359 | fprintf(stderr, "Throttle PKG: %0X\n", p->rapl_pkg_perf_status); | 399 | outp += sprintf(outp, "Throttle PKG: %0X\n", |
| 360 | fprintf(stderr, "Throttle RAM: %0X\n", p->rapl_dram_perf_status); | 400 | p->rapl_pkg_perf_status); |
| 361 | fprintf(stderr, "PTM: %dC\n", p->pkg_temp_c); | 401 | outp += sprintf(outp, "Throttle RAM: %0X\n", |
| 402 | p->rapl_dram_perf_status); | ||
| 403 | outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c); | ||
| 362 | } | 404 | } |
| 405 | |||
| 406 | outp += sprintf(outp, "\n"); | ||
| 407 | |||
| 363 | return 0; | 408 | return 0; |
| 364 | } | 409 | } |
| 365 | 410 | ||
| @@ -527,19 +572,39 @@ int format_counters(struct thread_data *t, struct core_data *c, | |||
| 527 | fmt6 = " %4.0f**"; | 572 | fmt6 = " %4.0f**"; |
| 528 | } | 573 | } |
| 529 | 574 | ||
| 530 | if (do_rapl & RAPL_PKG) | 575 | if (do_rapl && !rapl_joules) { |
| 531 | outp += sprintf(outp, fmt6, p->energy_pkg * rapl_energy_units / interval_float); | 576 | if (do_rapl & RAPL_PKG) |
| 532 | if (do_rapl & RAPL_CORES) | 577 | outp += sprintf(outp, fmt6, p->energy_pkg * rapl_energy_units / interval_float); |
| 533 | outp += sprintf(outp, fmt6, p->energy_cores * rapl_energy_units / interval_float); | 578 | if (do_rapl & RAPL_CORES) |
| 534 | if (do_rapl & RAPL_GFX) | 579 | outp += sprintf(outp, fmt6, p->energy_cores * rapl_energy_units / interval_float); |
| 535 | outp += sprintf(outp, fmt5, p->energy_gfx * rapl_energy_units / interval_float); | 580 | if (do_rapl & RAPL_GFX) |
| 536 | if (do_rapl & RAPL_DRAM) | 581 | outp += sprintf(outp, fmt5, p->energy_gfx * rapl_energy_units / interval_float); |
| 537 | outp += sprintf(outp, fmt5, p->energy_dram * rapl_energy_units / interval_float); | 582 | if (do_rapl & RAPL_DRAM) |
| 538 | if (do_rapl & RAPL_PKG_PERF_STATUS ) | 583 | outp += sprintf(outp, fmt5, p->energy_dram * rapl_energy_units / interval_float); |
| 539 | outp += sprintf(outp, fmt5, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); | 584 | if (do_rapl & RAPL_PKG_PERF_STATUS) |
| 540 | if (do_rapl & RAPL_DRAM_PERF_STATUS ) | 585 | outp += sprintf(outp, fmt5, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); |
| 541 | outp += sprintf(outp, fmt5, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); | 586 | if (do_rapl & RAPL_DRAM_PERF_STATUS) |
| 587 | outp += sprintf(outp, fmt5, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); | ||
| 588 | } else { | ||
| 589 | if (do_rapl & RAPL_PKG) | ||
| 590 | outp += sprintf(outp, fmt6, | ||
| 591 | p->energy_pkg * rapl_energy_units); | ||
| 592 | if (do_rapl & RAPL_CORES) | ||
| 593 | outp += sprintf(outp, fmt6, | ||
| 594 | p->energy_cores * rapl_energy_units); | ||
| 595 | if (do_rapl & RAPL_GFX) | ||
| 596 | outp += sprintf(outp, fmt5, | ||
| 597 | p->energy_gfx * rapl_energy_units); | ||
| 598 | if (do_rapl & RAPL_DRAM) | ||
| 599 | outp += sprintf(outp, fmt5, | ||
| 600 | p->energy_dram * rapl_energy_units); | ||
| 601 | if (do_rapl & RAPL_PKG_PERF_STATUS) | ||
| 602 | outp += sprintf(outp, fmt5, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); | ||
| 603 | if (do_rapl & RAPL_DRAM_PERF_STATUS) | ||
| 604 | outp += sprintf(outp, fmt5, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); | ||
| 605 | outp += sprintf(outp, fmt5, interval_float); | ||
| 542 | 606 | ||
| 607 | } | ||
| 543 | done: | 608 | done: |
| 544 | outp += sprintf(outp, "\n"); | 609 | outp += sprintf(outp, "\n"); |
| 545 | 610 | ||
| @@ -622,12 +687,10 @@ delta_thread(struct thread_data *new, struct thread_data *old, | |||
| 622 | old->tsc = new->tsc - old->tsc; | 687 | old->tsc = new->tsc - old->tsc; |
| 623 | 688 | ||
| 624 | /* check for TSC < 1 Mcycles over interval */ | 689 | /* check for TSC < 1 Mcycles over interval */ |
| 625 | if (old->tsc < (1000 * 1000)) { | 690 | if (old->tsc < (1000 * 1000)) |
| 626 | fprintf(stderr, "Insanely slow TSC rate, TSC stops in idle?\n"); | 691 | errx(-3, "Insanely slow TSC rate, TSC stops in idle?\n" |
| 627 | fprintf(stderr, "You can disable all c-states by booting with \"idle=poll\"\n"); | 692 | "You can disable all c-states by booting with \"idle=poll\"\n" |
| 628 | fprintf(stderr, "or just the deep ones with \"processor.max_cstate=1\"\n"); | 693 | "or just the deep ones with \"processor.max_cstate=1\""); |
| 629 | exit(-3); | ||
| 630 | } | ||
| 631 | 694 | ||
| 632 | old->c1 = new->c1 - old->c1; | 695 | old->c1 = new->c1 - old->c1; |
| 633 | 696 | ||
| @@ -1173,24 +1236,43 @@ void free_all_buffers(void) | |||
| 1173 | } | 1236 | } |
| 1174 | 1237 | ||
| 1175 | /* | 1238 | /* |
| 1239 | * Open a file, and exit on failure | ||
| 1240 | */ | ||
| 1241 | FILE *fopen_or_die(const char *path, const char *mode) | ||
| 1242 | { | ||
| 1243 | FILE *filep = fopen(path, "r"); | ||
| 1244 | if (!filep) | ||
| 1245 | err(1, "%s: open failed", path); | ||
| 1246 | return filep; | ||
| 1247 | } | ||
| 1248 | |||
| 1249 | /* | ||
| 1250 | * Parse a file containing a single int. | ||
| 1251 | */ | ||
| 1252 | int parse_int_file(const char *fmt, ...) | ||
| 1253 | { | ||
| 1254 | va_list args; | ||
| 1255 | char path[PATH_MAX]; | ||
| 1256 | FILE *filep; | ||
| 1257 | int value; | ||
| 1258 | |||
| 1259 | va_start(args, fmt); | ||
| 1260 | vsnprintf(path, sizeof(path), fmt, args); | ||
| 1261 | va_end(args); | ||
| 1262 | filep = fopen_or_die(path, "r"); | ||
| 1263 | if (fscanf(filep, "%d", &value) != 1) | ||
| 1264 | err(1, "%s: failed to parse number from file", path); | ||
| 1265 | fclose(filep); | ||
| 1266 | return value; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | /* | ||
| 1176 | * cpu_is_first_sibling_in_core(cpu) | 1270 | * cpu_is_first_sibling_in_core(cpu) |
| 1177 | * return 1 if given CPU is 1st HT sibling in the core | 1271 | * return 1 if given CPU is 1st HT sibling in the core |
| 1178 | */ | 1272 | */ |
| 1179 | int cpu_is_first_sibling_in_core(int cpu) | 1273 | int cpu_is_first_sibling_in_core(int cpu) |
| 1180 | { | 1274 | { |
| 1181 | char path[64]; | 1275 | return cpu == parse_int_file("/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu); |
| 1182 | FILE *filep; | ||
| 1183 | int first_cpu; | ||
| 1184 | |||
| 1185 | sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu); | ||
| 1186 | filep = fopen(path, "r"); | ||
| 1187 | if (filep == NULL) { | ||
| 1188 | perror(path); | ||
| 1189 | exit(1); | ||
| 1190 | } | ||
| 1191 | fscanf(filep, "%d", &first_cpu); | ||
| 1192 | fclose(filep); | ||
| 1193 | return (cpu == first_cpu); | ||
| 1194 | } | 1276 | } |
| 1195 | 1277 | ||
| 1196 | /* | 1278 | /* |
| @@ -1199,53 +1281,17 @@ int cpu_is_first_sibling_in_core(int cpu) | |||
| 1199 | */ | 1281 | */ |
| 1200 | int cpu_is_first_core_in_package(int cpu) | 1282 | int cpu_is_first_core_in_package(int cpu) |
| 1201 | { | 1283 | { |
| 1202 | char path[64]; | 1284 | return cpu == parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_siblings_list", cpu); |
| 1203 | FILE *filep; | ||
| 1204 | int first_cpu; | ||
| 1205 | |||
| 1206 | sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/core_siblings_list", cpu); | ||
| 1207 | filep = fopen(path, "r"); | ||
| 1208 | if (filep == NULL) { | ||
| 1209 | perror(path); | ||
| 1210 | exit(1); | ||
| 1211 | } | ||
| 1212 | fscanf(filep, "%d", &first_cpu); | ||
| 1213 | fclose(filep); | ||
| 1214 | return (cpu == first_cpu); | ||
| 1215 | } | 1285 | } |
| 1216 | 1286 | ||
| 1217 | int get_physical_package_id(int cpu) | 1287 | int get_physical_package_id(int cpu) |
| 1218 | { | 1288 | { |
| 1219 | char path[80]; | 1289 | return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu); |
| 1220 | FILE *filep; | ||
| 1221 | int pkg; | ||
| 1222 | |||
| 1223 | sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu); | ||
| 1224 | filep = fopen(path, "r"); | ||
| 1225 | if (filep == NULL) { | ||
| 1226 | perror(path); | ||
| 1227 | exit(1); | ||
| 1228 | } | ||
| 1229 | fscanf(filep, "%d", &pkg); | ||
| 1230 | fclose(filep); | ||
| 1231 | return pkg; | ||
| 1232 | } | 1290 | } |
| 1233 | 1291 | ||
| 1234 | int get_core_id(int cpu) | 1292 | int get_core_id(int cpu) |
| 1235 | { | 1293 | { |
| 1236 | char path[80]; | 1294 | return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_id", cpu); |
| 1237 | FILE *filep; | ||
| 1238 | int core; | ||
| 1239 | |||
| 1240 | sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/core_id", cpu); | ||
| 1241 | filep = fopen(path, "r"); | ||
| 1242 | if (filep == NULL) { | ||
| 1243 | perror(path); | ||
| 1244 | exit(1); | ||
| 1245 | } | ||
| 1246 | fscanf(filep, "%d", &core); | ||
| 1247 | fclose(filep); | ||
| 1248 | return core; | ||
| 1249 | } | 1295 | } |
| 1250 | 1296 | ||
| 1251 | int get_num_ht_siblings(int cpu) | 1297 | int get_num_ht_siblings(int cpu) |
| @@ -1257,11 +1303,7 @@ int get_num_ht_siblings(int cpu) | |||
| 1257 | char character; | 1303 | char character; |
| 1258 | 1304 | ||
| 1259 | sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu); | 1305 | sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu); |
| 1260 | filep = fopen(path, "r"); | 1306 | filep = fopen_or_die(path, "r"); |
| 1261 | if (filep == NULL) { | ||
| 1262 | perror(path); | ||
| 1263 | exit(1); | ||
| 1264 | } | ||
| 1265 | /* | 1307 | /* |
| 1266 | * file format: | 1308 | * file format: |
| 1267 | * if a pair of number with a character between: 2 siblings (eg. 1-2, or 1,4) | 1309 | * if a pair of number with a character between: 2 siblings (eg. 1-2, or 1,4) |
| @@ -1331,17 +1373,11 @@ int for_all_proc_cpus(int (func)(int)) | |||
| 1331 | int cpu_num; | 1373 | int cpu_num; |
| 1332 | int retval; | 1374 | int retval; |
| 1333 | 1375 | ||
| 1334 | fp = fopen(proc_stat, "r"); | 1376 | fp = fopen_or_die(proc_stat, "r"); |
| 1335 | if (fp == NULL) { | ||
| 1336 | perror(proc_stat); | ||
| 1337 | exit(1); | ||
| 1338 | } | ||
| 1339 | 1377 | ||
| 1340 | retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n"); | 1378 | retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n"); |
| 1341 | if (retval != 0) { | 1379 | if (retval != 0) |
| 1342 | perror("/proc/stat format"); | 1380 | err(1, "%s: failed to parse format", proc_stat); |
| 1343 | exit(1); | ||
| 1344 | } | ||
| 1345 | 1381 | ||
| 1346 | while (1) { | 1382 | while (1) { |
| 1347 | retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num); | 1383 | retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num); |
| @@ -1445,19 +1481,15 @@ void check_dev_msr() | |||
| 1445 | { | 1481 | { |
| 1446 | struct stat sb; | 1482 | struct stat sb; |
| 1447 | 1483 | ||
| 1448 | if (stat("/dev/cpu/0/msr", &sb)) { | 1484 | if (stat("/dev/cpu/0/msr", &sb)) |
| 1449 | fprintf(stderr, "no /dev/cpu/0/msr\n"); | 1485 | err(-5, "no /dev/cpu/0/msr\n" |
| 1450 | fprintf(stderr, "Try \"# modprobe msr\"\n"); | 1486 | "Try \"# modprobe msr\""); |
| 1451 | exit(-5); | ||
| 1452 | } | ||
| 1453 | } | 1487 | } |
| 1454 | 1488 | ||
| 1455 | void check_super_user() | 1489 | void check_super_user() |
| 1456 | { | 1490 | { |
| 1457 | if (getuid() != 0) { | 1491 | if (getuid() != 0) |
| 1458 | fprintf(stderr, "must be root\n"); | 1492 | errx(-6, "must be root"); |
| 1459 | exit(-6); | ||
| 1460 | } | ||
| 1461 | } | 1493 | } |
| 1462 | 1494 | ||
| 1463 | int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model) | 1495 | int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model) |
| @@ -1479,7 +1511,7 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model) | |||
| 1479 | case 0x3A: /* IVB */ | 1511 | case 0x3A: /* IVB */ |
| 1480 | case 0x3E: /* IVB Xeon */ | 1512 | case 0x3E: /* IVB Xeon */ |
| 1481 | case 0x3C: /* HSW */ | 1513 | case 0x3C: /* HSW */ |
| 1482 | case 0x3F: /* HSW */ | 1514 | case 0x3F: /* HSX */ |
| 1483 | case 0x45: /* HSW */ | 1515 | case 0x45: /* HSW */ |
| 1484 | case 0x46: /* HSW */ | 1516 | case 0x46: /* HSW */ |
| 1485 | case 0x37: /* BYT */ | 1517 | case 0x37: /* BYT */ |
| @@ -1595,11 +1627,13 @@ void rapl_probe(unsigned int family, unsigned int model) | |||
| 1595 | case 0x2A: | 1627 | case 0x2A: |
| 1596 | case 0x3A: | 1628 | case 0x3A: |
| 1597 | case 0x3C: /* HSW */ | 1629 | case 0x3C: /* HSW */ |
| 1598 | case 0x3F: /* HSW */ | ||
| 1599 | case 0x45: /* HSW */ | 1630 | case 0x45: /* HSW */ |
| 1600 | case 0x46: /* HSW */ | 1631 | case 0x46: /* HSW */ |
| 1601 | do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO; | 1632 | do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO; |
| 1602 | break; | 1633 | break; |
| 1634 | case 0x3F: /* HSX */ | ||
| 1635 | do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO; | ||
| 1636 | break; | ||
| 1603 | case 0x2D: | 1637 | case 0x2D: |
| 1604 | case 0x3E: | 1638 | case 0x3E: |
| 1605 | do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO; | 1639 | do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO; |
| @@ -1978,7 +2012,7 @@ void check_cpuid() | |||
| 1978 | 2012 | ||
| 1979 | eax = ebx = ecx = edx = 0; | 2013 | eax = ebx = ecx = edx = 0; |
| 1980 | 2014 | ||
| 1981 | asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0)); | 2015 | __get_cpuid(0, &max_level, &ebx, &ecx, &edx); |
| 1982 | 2016 | ||
| 1983 | if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e) | 2017 | if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e) |
| 1984 | genuine_intel = 1; | 2018 | genuine_intel = 1; |
| @@ -1987,7 +2021,7 @@ void check_cpuid() | |||
| 1987 | fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ", | 2021 | fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ", |
| 1988 | (char *)&ebx, (char *)&edx, (char *)&ecx); | 2022 | (char *)&ebx, (char *)&edx, (char *)&ecx); |
| 1989 | 2023 | ||
| 1990 | asm("cpuid" : "=a" (fms), "=c" (ecx), "=d" (edx) : "a" (1) : "ebx"); | 2024 | __get_cpuid(1, &fms, &ebx, &ecx, &edx); |
| 1991 | family = (fms >> 8) & 0xf; | 2025 | family = (fms >> 8) & 0xf; |
| 1992 | model = (fms >> 4) & 0xf; | 2026 | model = (fms >> 4) & 0xf; |
| 1993 | stepping = fms & 0xf; | 2027 | stepping = fms & 0xf; |
| @@ -1998,10 +2032,8 @@ void check_cpuid() | |||
| 1998 | fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n", | 2032 | fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n", |
| 1999 | max_level, family, model, stepping, family, model, stepping); | 2033 | max_level, family, model, stepping, family, model, stepping); |
| 2000 | 2034 | ||
| 2001 | if (!(edx & (1 << 5))) { | 2035 | if (!(edx & (1 << 5))) |
| 2002 | fprintf(stderr, "CPUID: no MSR\n"); | 2036 | errx(1, "CPUID: no MSR"); |
| 2003 | exit(1); | ||
| 2004 | } | ||
| 2005 | 2037 | ||
| 2006 | /* | 2038 | /* |
| 2007 | * check max extended function levels of CPUID. | 2039 | * check max extended function levels of CPUID. |
| @@ -2009,31 +2041,27 @@ void check_cpuid() | |||
| 2009 | * This check is valid for both Intel and AMD. | 2041 | * This check is valid for both Intel and AMD. |
| 2010 | */ | 2042 | */ |
| 2011 | ebx = ecx = edx = 0; | 2043 | ebx = ecx = edx = 0; |
| 2012 | asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x80000000)); | 2044 | __get_cpuid(0x80000000, &max_level, &ebx, &ecx, &edx); |
| 2013 | 2045 | ||
| 2014 | if (max_level < 0x80000007) { | 2046 | if (max_level < 0x80000007) |
| 2015 | fprintf(stderr, "CPUID: no invariant TSC (max_level 0x%x)\n", max_level); | 2047 | errx(1, "CPUID: no invariant TSC (max_level 0x%x)", max_level); |
| 2016 | exit(1); | ||
| 2017 | } | ||
| 2018 | 2048 | ||
| 2019 | /* | 2049 | /* |
| 2020 | * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8 | 2050 | * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8 |
| 2021 | * this check is valid for both Intel and AMD | 2051 | * this check is valid for both Intel and AMD |
| 2022 | */ | 2052 | */ |
| 2023 | asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x80000007)); | 2053 | __get_cpuid(0x80000007, &eax, &ebx, &ecx, &edx); |
| 2024 | has_invariant_tsc = edx & (1 << 8); | 2054 | has_invariant_tsc = edx & (1 << 8); |
| 2025 | 2055 | ||
| 2026 | if (!has_invariant_tsc) { | 2056 | if (!has_invariant_tsc) |
| 2027 | fprintf(stderr, "No invariant TSC\n"); | 2057 | errx(1, "No invariant TSC"); |
| 2028 | exit(1); | ||
| 2029 | } | ||
| 2030 | 2058 | ||
| 2031 | /* | 2059 | /* |
| 2032 | * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0 | 2060 | * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0 |
| 2033 | * this check is valid for both Intel and AMD | 2061 | * this check is valid for both Intel and AMD |
| 2034 | */ | 2062 | */ |
| 2035 | 2063 | ||
| 2036 | asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x6)); | 2064 | __get_cpuid(0x6, &eax, &ebx, &ecx, &edx); |
| 2037 | has_aperf = ecx & (1 << 0); | 2065 | has_aperf = ecx & (1 << 0); |
| 2038 | do_dts = eax & (1 << 0); | 2066 | do_dts = eax & (1 << 0); |
| 2039 | do_ptm = eax & (1 << 6); | 2067 | do_ptm = eax & (1 << 6); |
| @@ -2047,7 +2075,7 @@ void check_cpuid() | |||
| 2047 | has_epb ? ", EPB": ""); | 2075 | has_epb ? ", EPB": ""); |
| 2048 | 2076 | ||
| 2049 | if (!has_aperf) | 2077 | if (!has_aperf) |
| 2050 | exit(-1); | 2078 | errx(-1, "No APERF"); |
| 2051 | 2079 | ||
| 2052 | do_nehalem_platform_info = genuine_intel && has_invariant_tsc; | 2080 | do_nehalem_platform_info = genuine_intel && has_invariant_tsc; |
| 2053 | do_nhm_cstates = genuine_intel; /* all Intel w/ non-stop TSC have NHM counters */ | 2081 | do_nhm_cstates = genuine_intel; /* all Intel w/ non-stop TSC have NHM counters */ |
| @@ -2067,9 +2095,8 @@ void check_cpuid() | |||
| 2067 | 2095 | ||
| 2068 | void usage() | 2096 | void usage() |
| 2069 | { | 2097 | { |
| 2070 | fprintf(stderr, "%s: [-v][-R][-T][-p|-P|-S][-c MSR# | -s]][-C MSR#][-m MSR#][-M MSR#][-i interval_sec | command ...]\n", | 2098 | errx(1, "%s: [-v][-R][-T][-p|-P|-S][-c MSR#][-C MSR#][-m MSR#][-M MSR#][-i interval_sec | command ...]\n", |
| 2071 | progname); | 2099 | progname); |
| 2072 | exit(1); | ||
| 2073 | } | 2100 | } |
| 2074 | 2101 | ||
| 2075 | 2102 | ||
| @@ -2112,19 +2139,15 @@ void topology_probe() | |||
| 2112 | fprintf(stderr, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num); | 2139 | fprintf(stderr, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num); |
| 2113 | 2140 | ||
| 2114 | cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology)); | 2141 | cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology)); |
| 2115 | if (cpus == NULL) { | 2142 | if (cpus == NULL) |
| 2116 | perror("calloc cpus"); | 2143 | err(1, "calloc cpus"); |
| 2117 | exit(1); | ||
| 2118 | } | ||
| 2119 | 2144 | ||
| 2120 | /* | 2145 | /* |
| 2121 | * Allocate and initialize cpu_present_set | 2146 | * Allocate and initialize cpu_present_set |
| 2122 | */ | 2147 | */ |
| 2123 | cpu_present_set = CPU_ALLOC((topo.max_cpu_num + 1)); | 2148 | cpu_present_set = CPU_ALLOC((topo.max_cpu_num + 1)); |
| 2124 | if (cpu_present_set == NULL) { | 2149 | if (cpu_present_set == NULL) |
| 2125 | perror("CPU_ALLOC"); | 2150 | err(3, "CPU_ALLOC"); |
| 2126 | exit(3); | ||
| 2127 | } | ||
| 2128 | cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); | 2151 | cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); |
| 2129 | CPU_ZERO_S(cpu_present_setsize, cpu_present_set); | 2152 | CPU_ZERO_S(cpu_present_setsize, cpu_present_set); |
| 2130 | for_all_proc_cpus(mark_cpu_present); | 2153 | for_all_proc_cpus(mark_cpu_present); |
| @@ -2133,10 +2156,8 @@ void topology_probe() | |||
| 2133 | * Allocate and initialize cpu_affinity_set | 2156 | * Allocate and initialize cpu_affinity_set |
| 2134 | */ | 2157 | */ |
| 2135 | cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1)); | 2158 | cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1)); |
| 2136 | if (cpu_affinity_set == NULL) { | 2159 | if (cpu_affinity_set == NULL) |
| 2137 | perror("CPU_ALLOC"); | 2160 | err(3, "CPU_ALLOC"); |
| 2138 | exit(3); | ||
| 2139 | } | ||
| 2140 | cpu_affinity_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); | 2161 | cpu_affinity_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); |
| 2141 | CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set); | 2162 | CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set); |
| 2142 | 2163 | ||
| @@ -2220,8 +2241,7 @@ allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data | |||
| 2220 | 2241 | ||
| 2221 | return; | 2242 | return; |
| 2222 | error: | 2243 | error: |
| 2223 | perror("calloc counters"); | 2244 | err(1, "calloc counters"); |
| 2224 | exit(1); | ||
| 2225 | } | 2245 | } |
| 2226 | /* | 2246 | /* |
| 2227 | * init_counter() | 2247 | * init_counter() |
| @@ -2276,12 +2296,10 @@ int initialize_counters(int cpu_id) | |||
| 2276 | 2296 | ||
| 2277 | void allocate_output_buffer() | 2297 | void allocate_output_buffer() |
| 2278 | { | 2298 | { |
| 2279 | output_buffer = calloc(1, (1 + topo.num_cpus) * 256); | 2299 | output_buffer = calloc(1, (1 + topo.num_cpus) * 1024); |
| 2280 | outp = output_buffer; | 2300 | outp = output_buffer; |
| 2281 | if (outp == NULL) { | 2301 | if (outp == NULL) |
| 2282 | perror("calloc"); | 2302 | err(-1, "calloc output buffer"); |
| 2283 | exit(-1); | ||
| 2284 | } | ||
| 2285 | } | 2303 | } |
| 2286 | 2304 | ||
| 2287 | void setup_all_buffers(void) | 2305 | void setup_all_buffers(void) |
| @@ -2292,6 +2310,7 @@ void setup_all_buffers(void) | |||
| 2292 | allocate_output_buffer(); | 2310 | allocate_output_buffer(); |
| 2293 | for_all_proc_cpus(initialize_counters); | 2311 | for_all_proc_cpus(initialize_counters); |
| 2294 | } | 2312 | } |
| 2313 | |||
| 2295 | void turbostat_init() | 2314 | void turbostat_init() |
| 2296 | { | 2315 | { |
| 2297 | check_cpuid(); | 2316 | check_cpuid(); |
| @@ -2335,17 +2354,13 @@ int fork_it(char **argv) | |||
| 2335 | } else { | 2354 | } else { |
| 2336 | 2355 | ||
| 2337 | /* parent */ | 2356 | /* parent */ |
| 2338 | if (child_pid == -1) { | 2357 | if (child_pid == -1) |
| 2339 | perror("fork"); | 2358 | err(1, "fork"); |
| 2340 | exit(1); | ||
| 2341 | } | ||
| 2342 | 2359 | ||
| 2343 | signal(SIGINT, SIG_IGN); | 2360 | signal(SIGINT, SIG_IGN); |
| 2344 | signal(SIGQUIT, SIG_IGN); | 2361 | signal(SIGQUIT, SIG_IGN); |
| 2345 | if (waitpid(child_pid, &status, 0) == -1) { | 2362 | if (waitpid(child_pid, &status, 0) == -1) |
| 2346 | perror("wait"); | 2363 | err(status, "waitpid"); |
| 2347 | exit(status); | ||
| 2348 | } | ||
| 2349 | } | 2364 | } |
| 2350 | /* | 2365 | /* |
| 2351 | * n.b. fork_it() does not check for errors from for_all_cpus() | 2366 | * n.b. fork_it() does not check for errors from for_all_cpus() |
| @@ -2364,13 +2379,30 @@ int fork_it(char **argv) | |||
| 2364 | return status; | 2379 | return status; |
| 2365 | } | 2380 | } |
| 2366 | 2381 | ||
| 2382 | int get_and_dump_counters(void) | ||
| 2383 | { | ||
| 2384 | int status; | ||
| 2385 | |||
| 2386 | status = for_all_cpus(get_counters, ODD_COUNTERS); | ||
| 2387 | if (status) | ||
| 2388 | return status; | ||
| 2389 | |||
| 2390 | status = for_all_cpus(dump_counters, ODD_COUNTERS); | ||
| 2391 | if (status) | ||
| 2392 | return status; | ||
| 2393 | |||
| 2394 | flush_stdout(); | ||
| 2395 | |||
| 2396 | return status; | ||
| 2397 | } | ||
| 2398 | |||
| 2367 | void cmdline(int argc, char **argv) | 2399 | void cmdline(int argc, char **argv) |
| 2368 | { | 2400 | { |
| 2369 | int opt; | 2401 | int opt; |
| 2370 | 2402 | ||
| 2371 | progname = argv[0]; | 2403 | progname = argv[0]; |
| 2372 | 2404 | ||
| 2373 | while ((opt = getopt(argc, argv, "+pPSvi:sc:sC:m:M:RT:")) != -1) { | 2405 | while ((opt = getopt(argc, argv, "+pPsSvi:c:C:m:M:RJT:")) != -1) { |
| 2374 | switch (opt) { | 2406 | switch (opt) { |
| 2375 | case 'p': | 2407 | case 'p': |
| 2376 | show_core_only++; | 2408 | show_core_only++; |
| @@ -2378,6 +2410,9 @@ void cmdline(int argc, char **argv) | |||
| 2378 | case 'P': | 2410 | case 'P': |
| 2379 | show_pkg_only++; | 2411 | show_pkg_only++; |
| 2380 | break; | 2412 | break; |
| 2413 | case 's': | ||
| 2414 | dump_only++; | ||
| 2415 | break; | ||
| 2381 | case 'S': | 2416 | case 'S': |
| 2382 | summary_only++; | 2417 | summary_only++; |
| 2383 | break; | 2418 | break; |
| @@ -2405,6 +2440,10 @@ void cmdline(int argc, char **argv) | |||
| 2405 | case 'T': | 2440 | case 'T': |
| 2406 | tcc_activation_temp_override = atoi(optarg); | 2441 | tcc_activation_temp_override = atoi(optarg); |
| 2407 | break; | 2442 | break; |
| 2443 | case 'J': | ||
| 2444 | rapl_joules++; | ||
| 2445 | break; | ||
| 2446 | |||
| 2408 | default: | 2447 | default: |
| 2409 | usage(); | 2448 | usage(); |
| 2410 | } | 2449 | } |
| @@ -2416,11 +2455,15 @@ int main(int argc, char **argv) | |||
| 2416 | cmdline(argc, argv); | 2455 | cmdline(argc, argv); |
| 2417 | 2456 | ||
| 2418 | if (verbose) | 2457 | if (verbose) |
| 2419 | fprintf(stderr, "turbostat v3.5 April 26, 2013" | 2458 | fprintf(stderr, "turbostat v3.6 Dec 2, 2013" |
| 2420 | " - Len Brown <lenb@kernel.org>\n"); | 2459 | " - Len Brown <lenb@kernel.org>\n"); |
| 2421 | 2460 | ||
| 2422 | turbostat_init(); | 2461 | turbostat_init(); |
| 2423 | 2462 | ||
| 2463 | /* dump counters and exit */ | ||
| 2464 | if (dump_only) | ||
| 2465 | return get_and_dump_counters(); | ||
| 2466 | |||
| 2424 | /* | 2467 | /* |
| 2425 | * if any params left, it must be a command to fork | 2468 | * if any params left, it must be a command to fork |
| 2426 | */ | 2469 | */ |
