diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-02 20:28:48 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-02 20:28:48 +0100 |
commit | 87af5e5c22568201dfbda5cac9c76e96982adc9c (patch) | |
tree | a47312617500e2042a252acc36e71d0a63a24abc | |
parent | Merge tag 'fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/... (diff) | |
parent | tools/power turbostat: introduce -s to dump counters (diff) | |
download | linux-87af5e5c22568201dfbda5cac9c76e96982adc9c.tar.xz linux-87af5e5c22568201dfbda5cac9c76e96982adc9c.zip |
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
-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 := turbostat : turbostat.c CFLAGS += -Wall -CFLAGS += -I../../../../arch/x86/include/uapi/ +CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/uapi/asm/msr-index.h"' %: %.c @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 @@ */ #define _GNU_SOURCE -#include <asm/msr.h> +#include MSRHEADER +#include <stdarg.h> #include <stdio.h> +#include <err.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> @@ -35,13 +37,16 @@ #include <string.h> #include <ctype.h> #include <sched.h> +#include <cpuid.h> char *proc_stat = "/proc/stat"; unsigned int interval_sec = 5; /* set with -i interval_sec */ unsigned int verbose; /* set with -v */ unsigned int rapl_verbose; /* set with -R */ +unsigned int rapl_joules; /* set with -J */ unsigned int thermal_verbose; /* set with -T */ -unsigned int summary_only; /* set with -s */ +unsigned int summary_only; /* set with -S */ +unsigned int dump_only; /* set with -s */ unsigned int skip_c0; unsigned int skip_c1; unsigned int do_nhm_cstates; @@ -77,14 +82,32 @@ unsigned int tcc_activation_temp_override; double rapl_power_units, rapl_energy_units, rapl_time_units; double rapl_joule_counter_range; -#define RAPL_PKG (1 << 0) -#define RAPL_CORES (1 << 1) -#define RAPL_GFX (1 << 2) -#define RAPL_DRAM (1 << 3) -#define RAPL_PKG_PERF_STATUS (1 << 4) -#define RAPL_DRAM_PERF_STATUS (1 << 5) -#define RAPL_PKG_POWER_INFO (1 << 6) -#define RAPL_CORE_POLICY (1 << 7) +#define RAPL_PKG (1 << 0) + /* 0x610 MSR_PKG_POWER_LIMIT */ + /* 0x611 MSR_PKG_ENERGY_STATUS */ +#define RAPL_PKG_PERF_STATUS (1 << 1) + /* 0x613 MSR_PKG_PERF_STATUS */ +#define RAPL_PKG_POWER_INFO (1 << 2) + /* 0x614 MSR_PKG_POWER_INFO */ + +#define RAPL_DRAM (1 << 3) + /* 0x618 MSR_DRAM_POWER_LIMIT */ + /* 0x619 MSR_DRAM_ENERGY_STATUS */ + /* 0x61c MSR_DRAM_POWER_INFO */ +#define RAPL_DRAM_PERF_STATUS (1 << 4) + /* 0x61b MSR_DRAM_PERF_STATUS */ + +#define RAPL_CORES (1 << 5) + /* 0x638 MSR_PP0_POWER_LIMIT */ + /* 0x639 MSR_PP0_ENERGY_STATUS */ +#define RAPL_CORE_POLICY (1 << 6) + /* 0x63a MSR_PP0_POLICY */ + + +#define RAPL_GFX (1 << 7) + /* 0x640 MSR_PP1_POWER_LIMIT */ + /* 0x641 MSR_PP1_ENERGY_STATUS */ + /* 0x642 MSR_PP1_POLICY */ #define TJMAX_DEFAULT 100 #define MAX(a, b) ((a) > (b) ? (a) : (b)) @@ -234,7 +257,7 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr) close(fd); if (retval != sizeof *msr) { - fprintf(stderr, "%s offset 0x%zx read failed\n", pathname, offset); + fprintf(stderr, "%s offset 0x%llx read failed\n", pathname, (unsigned long long)offset); return -1; } @@ -296,70 +319,92 @@ void print_header(void) outp += sprintf(outp, " %%pc10"); } - if (do_rapl & RAPL_PKG) - outp += sprintf(outp, " Pkg_W"); - if (do_rapl & RAPL_CORES) - outp += sprintf(outp, " Cor_W"); - if (do_rapl & RAPL_GFX) - outp += sprintf(outp, " GFX_W"); - if (do_rapl & RAPL_DRAM) - outp += sprintf(outp, " RAM_W"); - if (do_rapl & RAPL_PKG_PERF_STATUS) - outp += sprintf(outp, " PKG_%%"); - if (do_rapl & RAPL_DRAM_PERF_STATUS) - outp += sprintf(outp, " RAM_%%"); + if (do_rapl && !rapl_joules) { + if (do_rapl & RAPL_PKG) + outp += sprintf(outp, " Pkg_W"); + if (do_rapl & RAPL_CORES) + outp += sprintf(outp, " Cor_W"); + if (do_rapl & RAPL_GFX) + outp += sprintf(outp, " GFX_W"); + if (do_rapl & RAPL_DRAM) + outp += sprintf(outp, " RAM_W"); + if (do_rapl & RAPL_PKG_PERF_STATUS) + outp += sprintf(outp, " PKG_%%"); + if (do_rapl & RAPL_DRAM_PERF_STATUS) + outp += sprintf(outp, " RAM_%%"); + } else { + if (do_rapl & RAPL_PKG) + outp += sprintf(outp, " Pkg_J"); + if (do_rapl & RAPL_CORES) + outp += sprintf(outp, " Cor_J"); + if (do_rapl & RAPL_GFX) + outp += sprintf(outp, " GFX_J"); + if (do_rapl & RAPL_DRAM) + outp += sprintf(outp, " RAM_W"); + if (do_rapl & RAPL_PKG_PERF_STATUS) + outp += sprintf(outp, " PKG_%%"); + if (do_rapl & RAPL_DRAM_PERF_STATUS) + outp += sprintf(outp, " RAM_%%"); + outp += sprintf(outp, " time"); + } outp += sprintf(outp, "\n"); } int dump_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) { - fprintf(stderr, "t %p, c %p, p %p\n", t, c, p); + outp += sprintf(outp, "t %p, c %p, p %p\n", t, c, p); if (t) { - fprintf(stderr, "CPU: %d flags 0x%x\n", t->cpu_id, t->flags); - fprintf(stderr, "TSC: %016llX\n", t->tsc); - fprintf(stderr, "aperf: %016llX\n", t->aperf); - fprintf(stderr, "mperf: %016llX\n", t->mperf); - fprintf(stderr, "c1: %016llX\n", t->c1); - fprintf(stderr, "msr0x%x: %08llX\n", + outp += sprintf(outp, "CPU: %d flags 0x%x\n", + t->cpu_id, t->flags); + outp += sprintf(outp, "TSC: %016llX\n", t->tsc); + outp += sprintf(outp, "aperf: %016llX\n", t->aperf); + outp += sprintf(outp, "mperf: %016llX\n", t->mperf); + outp += sprintf(outp, "c1: %016llX\n", t->c1); + outp += sprintf(outp, "msr0x%x: %08llX\n", extra_delta_offset32, t->extra_delta32); - fprintf(stderr, "msr0x%x: %016llX\n", + outp += sprintf(outp, "msr0x%x: %016llX\n", extra_delta_offset64, t->extra_delta64); - fprintf(stderr, "msr0x%x: %08llX\n", + outp += sprintf(outp, "msr0x%x: %08llX\n", extra_msr_offset32, t->extra_msr32); - fprintf(stderr, "msr0x%x: %016llX\n", + outp += sprintf(outp, "msr0x%x: %016llX\n", extra_msr_offset64, t->extra_msr64); if (do_smi) - fprintf(stderr, "SMI: %08X\n", t->smi_count); + outp += sprintf(outp, "SMI: %08X\n", t->smi_count); } if (c) { - fprintf(stderr, "core: %d\n", c->core_id); - fprintf(stderr, "c3: %016llX\n", c->c3); - fprintf(stderr, "c6: %016llX\n", c->c6); - fprintf(stderr, "c7: %016llX\n", c->c7); - fprintf(stderr, "DTS: %dC\n", c->core_temp_c); + outp += sprintf(outp, "core: %d\n", c->core_id); + outp += sprintf(outp, "c3: %016llX\n", c->c3); + outp += sprintf(outp, "c6: %016llX\n", c->c6); + outp += sprintf(outp, "c7: %016llX\n", c->c7); + outp += sprintf(outp, "DTS: %dC\n", c->core_temp_c); } if (p) { - fprintf(stderr, "package: %d\n", p->package_id); - fprintf(stderr, "pc2: %016llX\n", p->pc2); - fprintf(stderr, "pc3: %016llX\n", p->pc3); - fprintf(stderr, "pc6: %016llX\n", p->pc6); - fprintf(stderr, "pc7: %016llX\n", p->pc7); - fprintf(stderr, "pc8: %016llX\n", p->pc8); - fprintf(stderr, "pc9: %016llX\n", p->pc9); - fprintf(stderr, "pc10: %016llX\n", p->pc10); - fprintf(stderr, "Joules PKG: %0X\n", p->energy_pkg); - fprintf(stderr, "Joules COR: %0X\n", p->energy_cores); - fprintf(stderr, "Joules GFX: %0X\n", p->energy_gfx); - fprintf(stderr, "Joules RAM: %0X\n", p->energy_dram); - fprintf(stderr, "Throttle PKG: %0X\n", p->rapl_pkg_perf_status); - fprintf(stderr, "Throttle RAM: %0X\n", p->rapl_dram_perf_status); - fprintf(stderr, "PTM: %dC\n", p->pkg_temp_c); + outp += sprintf(outp, "package: %d\n", p->package_id); + outp += sprintf(outp, "pc2: %016llX\n", p->pc2); + outp += sprintf(outp, "pc3: %016llX\n", p->pc3); + outp += sprintf(outp, "pc6: %016llX\n", p->pc6); + outp += sprintf(outp, "pc7: %016llX\n", p->pc7); + outp += sprintf(outp, "pc8: %016llX\n", p->pc8); + outp += sprintf(outp, "pc9: %016llX\n", p->pc9); + outp += sprintf(outp, "pc10: %016llX\n", p->pc10); + outp += sprintf(outp, "Joules PKG: %0X\n", p->energy_pkg); + outp += sprintf(outp, "Joules COR: %0X\n", p->energy_cores); + outp += sprintf(outp, "Joules GFX: %0X\n", p->energy_gfx); + outp += sprintf(outp, "Joules RAM: %0X\n", p->energy_dram); + outp += sprintf(outp, "Throttle PKG: %0X\n", + p->rapl_pkg_perf_status); + outp += sprintf(outp, "Throttle RAM: %0X\n", + p->rapl_dram_perf_status); + outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c); } + + outp += sprintf(outp, "\n"); + return 0; } @@ -527,19 +572,39 @@ int format_counters(struct thread_data *t, struct core_data *c, fmt6 = " %4.0f**"; } - if (do_rapl & RAPL_PKG) - outp += sprintf(outp, fmt6, p->energy_pkg * rapl_energy_units / interval_float); - if (do_rapl & RAPL_CORES) - outp += sprintf(outp, fmt6, p->energy_cores * rapl_energy_units / interval_float); - if (do_rapl & RAPL_GFX) - outp += sprintf(outp, fmt5, p->energy_gfx * rapl_energy_units / interval_float); - if (do_rapl & RAPL_DRAM) - outp += sprintf(outp, fmt5, p->energy_dram * rapl_energy_units / interval_float); - if (do_rapl & RAPL_PKG_PERF_STATUS ) - outp += sprintf(outp, fmt5, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); - if (do_rapl & RAPL_DRAM_PERF_STATUS ) - outp += sprintf(outp, fmt5, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); + if (do_rapl && !rapl_joules) { + if (do_rapl & RAPL_PKG) + outp += sprintf(outp, fmt6, p->energy_pkg * rapl_energy_units / interval_float); + if (do_rapl & RAPL_CORES) + outp += sprintf(outp, fmt6, p->energy_cores * rapl_energy_units / interval_float); + if (do_rapl & RAPL_GFX) + outp += sprintf(outp, fmt5, p->energy_gfx * rapl_energy_units / interval_float); + if (do_rapl & RAPL_DRAM) + outp += sprintf(outp, fmt5, p->energy_dram * rapl_energy_units / interval_float); + if (do_rapl & RAPL_PKG_PERF_STATUS) + outp += sprintf(outp, fmt5, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); + if (do_rapl & RAPL_DRAM_PERF_STATUS) + outp += sprintf(outp, fmt5, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); + } else { + if (do_rapl & RAPL_PKG) + outp += sprintf(outp, fmt6, + p->energy_pkg * rapl_energy_units); + if (do_rapl & RAPL_CORES) + outp += sprintf(outp, fmt6, + p->energy_cores * rapl_energy_units); + if (do_rapl & RAPL_GFX) + outp += sprintf(outp, fmt5, + p->energy_gfx * rapl_energy_units); + if (do_rapl & RAPL_DRAM) + outp += sprintf(outp, fmt5, + p->energy_dram * rapl_energy_units); + if (do_rapl & RAPL_PKG_PERF_STATUS) + outp += sprintf(outp, fmt5, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); + if (do_rapl & RAPL_DRAM_PERF_STATUS) + outp += sprintf(outp, fmt5, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); + outp += sprintf(outp, fmt5, interval_float); + } done: outp += sprintf(outp, "\n"); @@ -622,12 +687,10 @@ delta_thread(struct thread_data *new, struct thread_data *old, old->tsc = new->tsc - old->tsc; /* check for TSC < 1 Mcycles over interval */ - if (old->tsc < (1000 * 1000)) { - fprintf(stderr, "Insanely slow TSC rate, TSC stops in idle?\n"); - fprintf(stderr, "You can disable all c-states by booting with \"idle=poll\"\n"); - fprintf(stderr, "or just the deep ones with \"processor.max_cstate=1\"\n"); - exit(-3); - } + if (old->tsc < (1000 * 1000)) + errx(-3, "Insanely slow TSC rate, TSC stops in idle?\n" + "You can disable all c-states by booting with \"idle=poll\"\n" + "or just the deep ones with \"processor.max_cstate=1\""); old->c1 = new->c1 - old->c1; @@ -1173,24 +1236,43 @@ void free_all_buffers(void) } /* + * Open a file, and exit on failure + */ +FILE *fopen_or_die(const char *path, const char *mode) +{ + FILE *filep = fopen(path, "r"); + if (!filep) + err(1, "%s: open failed", path); + return filep; +} + +/* + * Parse a file containing a single int. + */ +int parse_int_file(const char *fmt, ...) +{ + va_list args; + char path[PATH_MAX]; + FILE *filep; + int value; + + va_start(args, fmt); + vsnprintf(path, sizeof(path), fmt, args); + va_end(args); + filep = fopen_or_die(path, "r"); + if (fscanf(filep, "%d", &value) != 1) + err(1, "%s: failed to parse number from file", path); + fclose(filep); + return value; +} + +/* * cpu_is_first_sibling_in_core(cpu) * return 1 if given CPU is 1st HT sibling in the core */ int cpu_is_first_sibling_in_core(int cpu) { - char path[64]; - FILE *filep; - int first_cpu; - - sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu); - filep = fopen(path, "r"); - if (filep == NULL) { - perror(path); - exit(1); - } - fscanf(filep, "%d", &first_cpu); - fclose(filep); - return (cpu == first_cpu); + return cpu == parse_int_file("/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu); } /* @@ -1199,53 +1281,17 @@ int cpu_is_first_sibling_in_core(int cpu) */ int cpu_is_first_core_in_package(int cpu) { - char path[64]; - FILE *filep; - int first_cpu; - - sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/core_siblings_list", cpu); - filep = fopen(path, "r"); - if (filep == NULL) { - perror(path); - exit(1); - } - fscanf(filep, "%d", &first_cpu); - fclose(filep); - return (cpu == first_cpu); + return cpu == parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_siblings_list", cpu); } int get_physical_package_id(int cpu) { - char path[80]; - FILE *filep; - int pkg; - - sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu); - filep = fopen(path, "r"); - if (filep == NULL) { - perror(path); - exit(1); - } - fscanf(filep, "%d", &pkg); - fclose(filep); - return pkg; + return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu); } int get_core_id(int cpu) { - char path[80]; - FILE *filep; - int core; - - sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/core_id", cpu); - filep = fopen(path, "r"); - if (filep == NULL) { - perror(path); - exit(1); - } - fscanf(filep, "%d", &core); - fclose(filep); - return core; + return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_id", cpu); } int get_num_ht_siblings(int cpu) @@ -1257,11 +1303,7 @@ int get_num_ht_siblings(int cpu) char character; sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu); - filep = fopen(path, "r"); - if (filep == NULL) { - perror(path); - exit(1); - } + filep = fopen_or_die(path, "r"); /* * file format: * 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)) int cpu_num; int retval; - fp = fopen(proc_stat, "r"); - if (fp == NULL) { - perror(proc_stat); - exit(1); - } + fp = fopen_or_die(proc_stat, "r"); retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n"); - if (retval != 0) { - perror("/proc/stat format"); - exit(1); - } + if (retval != 0) + err(1, "%s: failed to parse format", proc_stat); while (1) { 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() { struct stat sb; - if (stat("/dev/cpu/0/msr", &sb)) { - fprintf(stderr, "no /dev/cpu/0/msr\n"); - fprintf(stderr, "Try \"# modprobe msr\"\n"); - exit(-5); - } + if (stat("/dev/cpu/0/msr", &sb)) + err(-5, "no /dev/cpu/0/msr\n" + "Try \"# modprobe msr\""); } void check_super_user() { - if (getuid() != 0) { - fprintf(stderr, "must be root\n"); - exit(-6); - } + if (getuid() != 0) + errx(-6, "must be root"); } 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) case 0x3A: /* IVB */ case 0x3E: /* IVB Xeon */ case 0x3C: /* HSW */ - case 0x3F: /* HSW */ + case 0x3F: /* HSX */ case 0x45: /* HSW */ case 0x46: /* HSW */ case 0x37: /* BYT */ @@ -1595,11 +1627,13 @@ void rapl_probe(unsigned int family, unsigned int model) case 0x2A: case 0x3A: case 0x3C: /* HSW */ - case 0x3F: /* HSW */ case 0x45: /* HSW */ case 0x46: /* HSW */ do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO; break; + case 0x3F: /* HSX */ + do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO; + break; case 0x2D: case 0x3E: 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() eax = ebx = ecx = edx = 0; - asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0)); + __get_cpuid(0, &max_level, &ebx, &ecx, &edx); if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e) genuine_intel = 1; @@ -1987,7 +2021,7 @@ void check_cpuid() fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ", (char *)&ebx, (char *)&edx, (char *)&ecx); - asm("cpuid" : "=a" (fms), "=c" (ecx), "=d" (edx) : "a" (1) : "ebx"); + __get_cpuid(1, &fms, &ebx, &ecx, &edx); family = (fms >> 8) & 0xf; model = (fms >> 4) & 0xf; stepping = fms & 0xf; @@ -1998,10 +2032,8 @@ void check_cpuid() fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n", max_level, family, model, stepping, family, model, stepping); - if (!(edx & (1 << 5))) { - fprintf(stderr, "CPUID: no MSR\n"); - exit(1); - } + if (!(edx & (1 << 5))) + errx(1, "CPUID: no MSR"); /* * check max extended function levels of CPUID. @@ -2009,31 +2041,27 @@ void check_cpuid() * This check is valid for both Intel and AMD. */ ebx = ecx = edx = 0; - asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x80000000)); + __get_cpuid(0x80000000, &max_level, &ebx, &ecx, &edx); - if (max_level < 0x80000007) { - fprintf(stderr, "CPUID: no invariant TSC (max_level 0x%x)\n", max_level); - exit(1); - } + if (max_level < 0x80000007) + errx(1, "CPUID: no invariant TSC (max_level 0x%x)", max_level); /* * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8 * this check is valid for both Intel and AMD */ - asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x80000007)); + __get_cpuid(0x80000007, &eax, &ebx, &ecx, &edx); has_invariant_tsc = edx & (1 << 8); - if (!has_invariant_tsc) { - fprintf(stderr, "No invariant TSC\n"); - exit(1); - } + if (!has_invariant_tsc) + errx(1, "No invariant TSC"); /* * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0 * this check is valid for both Intel and AMD */ - asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x6)); + __get_cpuid(0x6, &eax, &ebx, &ecx, &edx); has_aperf = ecx & (1 << 0); do_dts = eax & (1 << 0); do_ptm = eax & (1 << 6); @@ -2047,7 +2075,7 @@ void check_cpuid() has_epb ? ", EPB": ""); if (!has_aperf) - exit(-1); + errx(-1, "No APERF"); do_nehalem_platform_info = genuine_intel && has_invariant_tsc; do_nhm_cstates = genuine_intel; /* all Intel w/ non-stop TSC have NHM counters */ @@ -2067,9 +2095,8 @@ void check_cpuid() void usage() { - fprintf(stderr, "%s: [-v][-R][-T][-p|-P|-S][-c MSR# | -s]][-C MSR#][-m MSR#][-M MSR#][-i interval_sec | command ...]\n", - progname); - exit(1); + errx(1, "%s: [-v][-R][-T][-p|-P|-S][-c MSR#][-C MSR#][-m MSR#][-M MSR#][-i interval_sec | command ...]\n", + progname); } @@ -2112,19 +2139,15 @@ void topology_probe() fprintf(stderr, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num); cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology)); - if (cpus == NULL) { - perror("calloc cpus"); - exit(1); - } + if (cpus == NULL) + err(1, "calloc cpus"); /* * Allocate and initialize cpu_present_set */ cpu_present_set = CPU_ALLOC((topo.max_cpu_num + 1)); - if (cpu_present_set == NULL) { - perror("CPU_ALLOC"); - exit(3); - } + if (cpu_present_set == NULL) + err(3, "CPU_ALLOC"); cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); CPU_ZERO_S(cpu_present_setsize, cpu_present_set); for_all_proc_cpus(mark_cpu_present); @@ -2133,10 +2156,8 @@ void topology_probe() * Allocate and initialize cpu_affinity_set */ cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1)); - if (cpu_affinity_set == NULL) { - perror("CPU_ALLOC"); - exit(3); - } + if (cpu_affinity_set == NULL) + err(3, "CPU_ALLOC"); cpu_affinity_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set); @@ -2220,8 +2241,7 @@ allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data return; error: - perror("calloc counters"); - exit(1); + err(1, "calloc counters"); } /* * init_counter() @@ -2276,12 +2296,10 @@ int initialize_counters(int cpu_id) void allocate_output_buffer() { - output_buffer = calloc(1, (1 + topo.num_cpus) * 256); + output_buffer = calloc(1, (1 + topo.num_cpus) * 1024); outp = output_buffer; - if (outp == NULL) { - perror("calloc"); - exit(-1); - } + if (outp == NULL) + err(-1, "calloc output buffer"); } void setup_all_buffers(void) @@ -2292,6 +2310,7 @@ void setup_all_buffers(void) allocate_output_buffer(); for_all_proc_cpus(initialize_counters); } + void turbostat_init() { check_cpuid(); @@ -2335,17 +2354,13 @@ int fork_it(char **argv) } else { /* parent */ - if (child_pid == -1) { - perror("fork"); - exit(1); - } + if (child_pid == -1) + err(1, "fork"); signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); - if (waitpid(child_pid, &status, 0) == -1) { - perror("wait"); - exit(status); - } + if (waitpid(child_pid, &status, 0) == -1) + err(status, "waitpid"); } /* * n.b. fork_it() does not check for errors from for_all_cpus() @@ -2364,13 +2379,30 @@ int fork_it(char **argv) return status; } +int get_and_dump_counters(void) +{ + int status; + + status = for_all_cpus(get_counters, ODD_COUNTERS); + if (status) + return status; + + status = for_all_cpus(dump_counters, ODD_COUNTERS); + if (status) + return status; + + flush_stdout(); + + return status; +} + void cmdline(int argc, char **argv) { int opt; progname = argv[0]; - while ((opt = getopt(argc, argv, "+pPSvi:sc:sC:m:M:RT:")) != -1) { + while ((opt = getopt(argc, argv, "+pPsSvi:c:C:m:M:RJT:")) != -1) { switch (opt) { case 'p': show_core_only++; @@ -2378,6 +2410,9 @@ void cmdline(int argc, char **argv) case 'P': show_pkg_only++; break; + case 's': + dump_only++; + break; case 'S': summary_only++; break; @@ -2405,6 +2440,10 @@ void cmdline(int argc, char **argv) case 'T': tcc_activation_temp_override = atoi(optarg); break; + case 'J': + rapl_joules++; + break; + default: usage(); } @@ -2416,11 +2455,15 @@ int main(int argc, char **argv) cmdline(argc, argv); if (verbose) - fprintf(stderr, "turbostat v3.5 April 26, 2013" + fprintf(stderr, "turbostat v3.6 Dec 2, 2013" " - Len Brown <lenb@kernel.org>\n"); turbostat_init(); + /* dump counters and exit */ + if (dump_only) + return get_and_dump_counters(); + /* * if any params left, it must be a command to fork */ |