aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/power/cpupower/.gitignore7
-rw-r--r--tools/power/cpupower/Makefile3
-rw-r--r--tools/power/cpupower/debug/i386/Makefile5
-rw-r--r--tools/power/cpupower/man/cpupower-monitor.115
-rw-r--r--tools/power/cpupower/utils/helpers/cpuid.c2
-rw-r--r--tools/power/cpupower/utils/helpers/helpers.h18
-rw-r--r--tools/power/cpupower/utils/helpers/sysfs.c19
-rw-r--r--tools/power/cpupower/utils/helpers/topology.c53
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c21
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h17
-rw-r--r--tools/power/cpupower/utils/idle_monitor/snb_idle.c10
11 files changed, 110 insertions, 60 deletions
diff --git a/tools/power/cpupower/.gitignore b/tools/power/cpupower/.gitignore
index 8a83dd2ffc11..d42073f12609 100644
--- a/tools/power/cpupower/.gitignore
+++ b/tools/power/cpupower/.gitignore
@@ -20,3 +20,10 @@ utils/cpufreq-set.o
20utils/cpufreq-aperf.o 20utils/cpufreq-aperf.o
21cpupower 21cpupower
22bench/cpufreq-bench 22bench/cpufreq-bench
23debug/kernel/Module.symvers
24debug/i386/centrino-decode
25debug/i386/dump_psb
26debug/i386/intel_gsic
27debug/i386/powernow-k8-decode
28debug/x86_64/centrino-decode
29debug/x86_64/powernow-k8-decode
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index cf397bd26d0c..d875a74a3bdf 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -253,7 +253,8 @@ clean:
253 | xargs rm -f 253 | xargs rm -f
254 -rm -f $(OUTPUT)cpupower 254 -rm -f $(OUTPUT)cpupower
255 -rm -f $(OUTPUT)libcpupower.so* 255 -rm -f $(OUTPUT)libcpupower.so*
256 -rm -rf $(OUTPUT)po/*.{gmo,pot} 256 -rm -rf $(OUTPUT)po/*.gmo
257 -rm -rf $(OUTPUT)po/*.pot
257 $(MAKE) -C bench O=$(OUTPUT) clean 258 $(MAKE) -C bench O=$(OUTPUT) clean
258 259
259 260
diff --git a/tools/power/cpupower/debug/i386/Makefile b/tools/power/cpupower/debug/i386/Makefile
index 3ba158f0e287..c05cc0ac80c7 100644
--- a/tools/power/cpupower/debug/i386/Makefile
+++ b/tools/power/cpupower/debug/i386/Makefile
@@ -26,7 +26,10 @@ $(OUTPUT)powernow-k8-decode: powernow-k8-decode.c
26all: $(OUTPUT)centrino-decode $(OUTPUT)dump_psb $(OUTPUT)intel_gsic $(OUTPUT)powernow-k8-decode 26all: $(OUTPUT)centrino-decode $(OUTPUT)dump_psb $(OUTPUT)intel_gsic $(OUTPUT)powernow-k8-decode
27 27
28clean: 28clean:
29 rm -rf $(OUTPUT){centrino-decode,dump_psb,intel_gsic,powernow-k8-decode} 29 rm -rf $(OUTPUT)centrino-decode
30 rm -rf $(OUTPUT)dump_psb
31 rm -rf $(OUTPUT)intel_gsic
32 rm -rf $(OUTPUT)powernow-k8-decode
30 33
31install: 34install:
32 $(INSTALL) -d $(DESTDIR)${bindir} 35 $(INSTALL) -d $(DESTDIR)${bindir}
diff --git a/tools/power/cpupower/man/cpupower-monitor.1 b/tools/power/cpupower/man/cpupower-monitor.1
index 1141c2073719..e01c35d13b6e 100644
--- a/tools/power/cpupower/man/cpupower-monitor.1
+++ b/tools/power/cpupower/man/cpupower-monitor.1
@@ -7,11 +7,11 @@ cpupower\-monitor \- Report processor frequency and idle statistics
7.RB "\-l" 7.RB "\-l"
8 8
9.B cpupower monitor 9.B cpupower monitor
10.RB [ "\-m <mon1>," [ "<mon2>,..." ] ] 10.RB [ -c ] [ "\-m <mon1>," [ "<mon2>,..." ] ]
11.RB [ "\-i seconds" ] 11.RB [ "\-i seconds" ]
12.br 12.br
13.B cpupower monitor 13.B cpupower monitor
14.RB [ "\-m <mon1>," [ "<mon2>,..." ] ] 14.RB [ -c ][ "\-m <mon1>," [ "<mon2>,..." ] ]
15.RB command 15.RB command
16.br 16.br
17.SH DESCRIPTION 17.SH DESCRIPTION
@@ -64,6 +64,17 @@ Only display specific monitors. Use the monitor string(s) provided by \-l option
64Measure intervall. 64Measure intervall.
65.RE 65.RE
66.PP 66.PP
67\-c
68.RS 4
69Schedule the process on every core before starting and ending measuring.
70This could be needed for the Idle_Stats monitor when no other MSR based
71monitor (has to be run on the core that is measured) is run in parallel.
72This is to wake up the processors from deeper sleep states and let the
73kernel re
74-account its cpuidle (C-state) information before reading the
75cpuidle timings from sysfs.
76.RE
77.PP
67command 78command
68.RS 4 79.RS 4
69Measure idle and frequency characteristics of an arbitrary command/workload. 80Measure idle and frequency characteristics of an arbitrary command/workload.
diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
index 906895d21cce..93b0aa74ca03 100644
--- a/tools/power/cpupower/utils/helpers/cpuid.c
+++ b/tools/power/cpupower/utils/helpers/cpuid.c
@@ -158,6 +158,8 @@ out:
158 cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO; 158 cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
159 case 0x2A: /* SNB */ 159 case 0x2A: /* SNB */
160 case 0x2D: /* SNB Xeon */ 160 case 0x2D: /* SNB Xeon */
161 case 0x3A: /* IVB */
162 case 0x3E: /* IVB Xeon */
161 cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO; 163 cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
162 cpu_info->caps |= CPUPOWER_CAP_IS_SNB; 164 cpu_info->caps |= CPUPOWER_CAP_IS_SNB;
163 break; 165 break;
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
index 2eb584cf2f55..aa9e95486a2d 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -92,6 +92,14 @@ extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info);
92extern struct cpupower_cpu_info cpupower_cpu_info; 92extern struct cpupower_cpu_info cpupower_cpu_info;
93/* cpuid and cpuinfo helpers **************************/ 93/* cpuid and cpuinfo helpers **************************/
94 94
95struct cpuid_core_info {
96 int pkg;
97 int core;
98 int cpu;
99
100 /* flags */
101 unsigned int is_online:1;
102};
95 103
96/* CPU topology/hierarchy parsing ******************/ 104/* CPU topology/hierarchy parsing ******************/
97struct cpupower_topology { 105struct cpupower_topology {
@@ -101,18 +109,12 @@ struct cpupower_topology {
101 unsigned int threads; /* per core */ 109 unsigned int threads; /* per core */
102 110
103 /* Array gets mallocated with cores entries, holding per core info */ 111 /* Array gets mallocated with cores entries, holding per core info */
104 struct { 112 struct cpuid_core_info *core_info;
105 int pkg;
106 int core;
107 int cpu;
108
109 /* flags */
110 unsigned int is_online:1;
111 } *core_info;
112}; 113};
113 114
114extern int get_cpu_topology(struct cpupower_topology *cpu_top); 115extern int get_cpu_topology(struct cpupower_topology *cpu_top);
115extern void cpu_topology_release(struct cpupower_topology cpu_top); 116extern void cpu_topology_release(struct cpupower_topology cpu_top);
117
116/* CPU topology/hierarchy parsing ******************/ 118/* CPU topology/hierarchy parsing ******************/
117 119
118/* X86 ONLY ****************************************/ 120/* X86 ONLY ****************************************/
diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c
index 96e28c124b5c..38ab91629463 100644
--- a/tools/power/cpupower/utils/helpers/sysfs.c
+++ b/tools/power/cpupower/utils/helpers/sysfs.c
@@ -37,25 +37,6 @@ unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
37 return (unsigned int) numread; 37 return (unsigned int) numread;
38} 38}
39 39
40static unsigned int sysfs_write_file(const char *path,
41 const char *value, size_t len)
42{
43 int fd;
44 ssize_t numwrite;
45
46 fd = open(path, O_WRONLY);
47 if (fd == -1)
48 return 0;
49
50 numwrite = write(fd, value, len);
51 if (numwrite < 1) {
52 close(fd);
53 return 0;
54 }
55 close(fd);
56 return (unsigned int) numwrite;
57}
58
59/* 40/*
60 * Detect whether a CPU is online 41 * Detect whether a CPU is online
61 * 42 *
diff --git a/tools/power/cpupower/utils/helpers/topology.c b/tools/power/cpupower/utils/helpers/topology.c
index 4eae2c47ba48..c13120af519b 100644
--- a/tools/power/cpupower/utils/helpers/topology.c
+++ b/tools/power/cpupower/utils/helpers/topology.c
@@ -20,9 +20,8 @@
20#include <helpers/sysfs.h> 20#include <helpers/sysfs.h>
21 21
22/* returns -1 on failure, 0 on success */ 22/* returns -1 on failure, 0 on success */
23int sysfs_topology_read_file(unsigned int cpu, const char *fname) 23static int sysfs_topology_read_file(unsigned int cpu, const char *fname, int *result)
24{ 24{
25 unsigned long value;
26 char linebuf[MAX_LINE_LEN]; 25 char linebuf[MAX_LINE_LEN];
27 char *endp; 26 char *endp;
28 char path[SYSFS_PATH_MAX]; 27 char path[SYSFS_PATH_MAX];
@@ -31,20 +30,12 @@ int sysfs_topology_read_file(unsigned int cpu, const char *fname)
31 cpu, fname); 30 cpu, fname);
32 if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0) 31 if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
33 return -1; 32 return -1;
34 value = strtoul(linebuf, &endp, 0); 33 *result = strtol(linebuf, &endp, 0);
35 if (endp == linebuf || errno == ERANGE) 34 if (endp == linebuf || errno == ERANGE)
36 return -1; 35 return -1;
37 return value; 36 return 0;
38} 37}
39 38
40struct cpuid_core_info {
41 unsigned int pkg;
42 unsigned int thread;
43 unsigned int cpu;
44 /* flags */
45 unsigned int is_online:1;
46};
47
48static int __compare(const void *t1, const void *t2) 39static int __compare(const void *t1, const void *t2)
49{ 40{
50 struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1; 41 struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
@@ -53,9 +44,9 @@ static int __compare(const void *t1, const void *t2)
53 return -1; 44 return -1;
54 else if (top1->pkg > top2->pkg) 45 else if (top1->pkg > top2->pkg)
55 return 1; 46 return 1;
56 else if (top1->thread < top2->thread) 47 else if (top1->core < top2->core)
57 return -1; 48 return -1;
58 else if (top1->thread > top2->thread) 49 else if (top1->core > top2->core)
59 return 1; 50 return 1;
60 else if (top1->cpu < top2->cpu) 51 else if (top1->cpu < top2->cpu)
61 return -1; 52 return -1;
@@ -73,28 +64,42 @@ static int __compare(const void *t1, const void *t2)
73 */ 64 */
74int get_cpu_topology(struct cpupower_topology *cpu_top) 65int get_cpu_topology(struct cpupower_topology *cpu_top)
75{ 66{
76 int cpu, cpus = sysconf(_SC_NPROCESSORS_CONF); 67 int cpu, last_pkg, cpus = sysconf(_SC_NPROCESSORS_CONF);
77 68
78 cpu_top->core_info = malloc(sizeof(struct cpupower_topology) * cpus); 69 cpu_top->core_info = malloc(sizeof(struct cpuid_core_info) * cpus);
79 if (cpu_top->core_info == NULL) 70 if (cpu_top->core_info == NULL)
80 return -ENOMEM; 71 return -ENOMEM;
81 cpu_top->pkgs = cpu_top->cores = 0; 72 cpu_top->pkgs = cpu_top->cores = 0;
82 for (cpu = 0; cpu < cpus; cpu++) { 73 for (cpu = 0; cpu < cpus; cpu++) {
83 cpu_top->core_info[cpu].cpu = cpu; 74 cpu_top->core_info[cpu].cpu = cpu;
84 cpu_top->core_info[cpu].is_online = sysfs_is_cpu_online(cpu); 75 cpu_top->core_info[cpu].is_online = sysfs_is_cpu_online(cpu);
85 cpu_top->core_info[cpu].pkg = 76 if(sysfs_topology_read_file(
86 sysfs_topology_read_file(cpu, "physical_package_id"); 77 cpu,
87 if ((int)cpu_top->core_info[cpu].pkg != -1 && 78 "physical_package_id",
88 cpu_top->core_info[cpu].pkg > cpu_top->pkgs) 79 &(cpu_top->core_info[cpu].pkg)) < 0)
89 cpu_top->pkgs = cpu_top->core_info[cpu].pkg; 80 return -1;
90 cpu_top->core_info[cpu].core = 81 if(sysfs_topology_read_file(
91 sysfs_topology_read_file(cpu, "core_id"); 82 cpu,
83 "core_id",
84 &(cpu_top->core_info[cpu].core)) < 0)
85 return -1;
92 } 86 }
93 cpu_top->pkgs++;
94 87
95 qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info), 88 qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
96 __compare); 89 __compare);
97 90
91 /* Count the number of distinct pkgs values. This works
92 because the primary sort of the core_info struct was just
93 done by pkg value. */
94 last_pkg = cpu_top->core_info[0].pkg;
95 for(cpu = 1; cpu < cpus; cpu++) {
96 if(cpu_top->core_info[cpu].pkg != last_pkg) {
97 last_pkg = cpu_top->core_info[cpu].pkg;
98 cpu_top->pkgs++;
99 }
100 }
101 cpu_top->pkgs++;
102
98 /* Intel's cores count is not consecutively numbered, there may 103 /* Intel's cores count is not consecutively numbered, there may
99 * be a core_id of 3, but none of 2. Assume there always is 0 104 * be a core_id of 3, but none of 2. Assume there always is 0
100 * Get amount of cores by counting duplicates in a package 105 * Get amount of cores by counting duplicates in a package
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
index 0d6571e418db..c4bae9203a69 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
+++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
@@ -39,6 +39,7 @@ static int mode;
39static int interval = 1; 39static int interval = 1;
40static char *show_monitors_param; 40static char *show_monitors_param;
41static struct cpupower_topology cpu_top; 41static struct cpupower_topology cpu_top;
42static unsigned int wake_cpus;
42 43
43/* ToDo: Document this in the manpage */ 44/* ToDo: Document this in the manpage */
44static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', }; 45static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', };
@@ -84,7 +85,7 @@ int fill_string_with_spaces(char *s, int n)
84void print_header(int topology_depth) 85void print_header(int topology_depth)
85{ 86{
86 int unsigned mon; 87 int unsigned mon;
87 int state, need_len, pr_mon_len; 88 int state, need_len;
88 cstate_t s; 89 cstate_t s;
89 char buf[128] = ""; 90 char buf[128] = "";
90 int percent_width = 4; 91 int percent_width = 4;
@@ -93,7 +94,6 @@ void print_header(int topology_depth)
93 printf("%s|", buf); 94 printf("%s|", buf);
94 95
95 for (mon = 0; mon < avail_monitors; mon++) { 96 for (mon = 0; mon < avail_monitors; mon++) {
96 pr_mon_len = 0;
97 need_len = monitors[mon]->hw_states_num * (percent_width + 3) 97 need_len = monitors[mon]->hw_states_num * (percent_width + 3)
98 - 1; 98 - 1;
99 if (mon != 0) { 99 if (mon != 0) {
@@ -315,16 +315,28 @@ int fork_it(char **argv)
315int do_interval_measure(int i) 315int do_interval_measure(int i)
316{ 316{
317 unsigned int num; 317 unsigned int num;
318 int cpu;
319
320 if (wake_cpus)
321 for (cpu = 0; cpu < cpu_count; cpu++)
322 bind_cpu(cpu);
318 323
319 for (num = 0; num < avail_monitors; num++) { 324 for (num = 0; num < avail_monitors; num++) {
320 dprint("HW C-state residency monitor: %s - States: %d\n", 325 dprint("HW C-state residency monitor: %s - States: %d\n",
321 monitors[num]->name, monitors[num]->hw_states_num); 326 monitors[num]->name, monitors[num]->hw_states_num);
322 monitors[num]->start(); 327 monitors[num]->start();
323 } 328 }
329
324 sleep(i); 330 sleep(i);
331
332 if (wake_cpus)
333 for (cpu = 0; cpu < cpu_count; cpu++)
334 bind_cpu(cpu);
335
325 for (num = 0; num < avail_monitors; num++) 336 for (num = 0; num < avail_monitors; num++)
326 monitors[num]->stop(); 337 monitors[num]->stop();
327 338
339
328 return 0; 340 return 0;
329} 341}
330 342
@@ -333,7 +345,7 @@ static void cmdline(int argc, char *argv[])
333 int opt; 345 int opt;
334 progname = basename(argv[0]); 346 progname = basename(argv[0]);
335 347
336 while ((opt = getopt(argc, argv, "+li:m:")) != -1) { 348 while ((opt = getopt(argc, argv, "+lci:m:")) != -1) {
337 switch (opt) { 349 switch (opt) {
338 case 'l': 350 case 'l':
339 if (mode) 351 if (mode)
@@ -352,6 +364,9 @@ static void cmdline(int argc, char *argv[])
352 mode = show; 364 mode = show;
353 show_monitors_param = optarg; 365 show_monitors_param = optarg;
354 break; 366 break;
367 case 'c':
368 wake_cpus = 1;
369 break;
355 default: 370 default:
356 print_wrong_arg_exit(); 371 print_wrong_arg_exit();
357 } 372 }
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
index 9312ee1f2dbc..9e43f3371fbc 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
+++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
@@ -65,4 +65,21 @@ extern long long timespec_diff_us(struct timespec start, struct timespec end);
65 "could be inaccurate\n"), mes, ov); \ 65 "could be inaccurate\n"), mes, ov); \
66} 66}
67 67
68
69/* Taken over from x86info project sources -> return 0 on success */
70#include <sched.h>
71#include <sys/types.h>
72#include <unistd.h>
73static inline int bind_cpu(int cpu)
74{
75 cpu_set_t set;
76
77 if (sched_getaffinity(getpid(), sizeof(set), &set) == 0) {
78 CPU_ZERO(&set);
79 CPU_SET(cpu, &set);
80 return sched_setaffinity(getpid(), sizeof(set), &set);
81 }
82 return 1;
83}
84
68#endif /* __CPUIDLE_INFO_HW__ */ 85#endif /* __CPUIDLE_INFO_HW__ */
diff --git a/tools/power/cpupower/utils/idle_monitor/snb_idle.c b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
index a1bc07cd53e1..a99b43b97d6d 100644
--- a/tools/power/cpupower/utils/idle_monitor/snb_idle.c
+++ b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
@@ -150,9 +150,15 @@ static struct cpuidle_monitor *snb_register(void)
150 || cpupower_cpu_info.family != 6) 150 || cpupower_cpu_info.family != 6)
151 return NULL; 151 return NULL;
152 152
153 if (cpupower_cpu_info.model != 0x2A 153 switch (cpupower_cpu_info.model) {
154 && cpupower_cpu_info.model != 0x2D) 154 case 0x2A: /* SNB */
155 case 0x2D: /* SNB Xeon */
156 case 0x3A: /* IVB */
157 case 0x3E: /* IVB Xeon */
158 break;
159 default:
155 return NULL; 160 return NULL;
161 }
156 162
157 is_valid = calloc(cpu_count, sizeof(int)); 163 is_valid = calloc(cpu_count, sizeof(int));
158 for (num = 0; num < SNB_CSTATE_COUNT; num++) { 164 for (num = 0; num < SNB_CSTATE_COUNT; num++) {