aboutsummaryrefslogtreecommitdiffstats
path: root/tools/power/cpupower/utils
diff options
context:
space:
mode:
Diffstat (limited to 'tools/power/cpupower/utils')
-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
7 files changed, 84 insertions, 56 deletions
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++) {