diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-02 14:28:48 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-02 14:28:48 -0500 |
commit | 87af5e5c22568201dfbda5cac9c76e96982adc9c (patch) | |
tree | a47312617500e2042a252acc36e71d0a63a24abc /tools | |
parent | e4c0da21650185cb7df6685c5437dad0e9f77028 (diff) | |
parent | 3b4d5c7fec0a0b1bbf56d3b8337770fa30f4d1ad (diff) |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
Pull turbostat updates from Len Brown.
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux:
tools/power turbostat: introduce -s to dump counters
tools/power turbostat: remove unused command line option
turbostat: Add option to report joules consumed per sample
turbostat: run on HSX
turbostat: Add a .gitignore to ignore the compiled turbostat binary
turbostat: Clean up error handling; disambiguate error messages; use err and errx
turbostat: Factor out common function to open file and exit on failure
turbostat: Add a helper to parse a single int out of a file
turbostat: Check return value of fscanf
turbostat: Use GCC's CPUID functions to support PIC
turbostat: Don't attempt to printf an off_t with %zx
turbostat: Don't put unprocessed uapi headers in the include path
Diffstat (limited to 'tools')
-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 | */ |