diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/hv/hv_kvp_daemon.c | 40 | ||||
-rw-r--r-- | tools/power/cpupower/.gitignore | 7 | ||||
-rw-r--r-- | tools/power/cpupower/Makefile | 3 | ||||
-rw-r--r-- | tools/power/cpupower/debug/i386/Makefile | 5 | ||||
-rw-r--r-- | tools/power/cpupower/man/cpupower-monitor.1 | 15 | ||||
-rw-r--r-- | tools/power/cpupower/utils/helpers/cpuid.c | 2 | ||||
-rw-r--r-- | tools/power/cpupower/utils/helpers/helpers.h | 18 | ||||
-rw-r--r-- | tools/power/cpupower/utils/helpers/sysfs.c | 19 | ||||
-rw-r--r-- | tools/power/cpupower/utils/helpers/topology.c | 53 | ||||
-rw-r--r-- | tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c | 21 | ||||
-rw-r--r-- | tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h | 17 | ||||
-rw-r--r-- | tools/power/cpupower/utils/idle_monitor/snb_idle.c | 10 | ||||
-rw-r--r-- | tools/testing/selftests/vm/Makefile | 4 | ||||
-rw-r--r-- | tools/testing/selftests/vm/thuge-gen.c | 254 |
14 files changed, 393 insertions, 75 deletions
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 5959affd8820..d25a46925e61 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <sys/stat.h> | 43 | #include <sys/stat.h> |
44 | #include <fcntl.h> | 44 | #include <fcntl.h> |
45 | #include <dirent.h> | 45 | #include <dirent.h> |
46 | #include <net/if.h> | ||
46 | 47 | ||
47 | /* | 48 | /* |
48 | * KVP protocol: The user mode component first registers with the | 49 | * KVP protocol: The user mode component first registers with the |
@@ -88,6 +89,7 @@ static char *os_major = ""; | |||
88 | static char *os_minor = ""; | 89 | static char *os_minor = ""; |
89 | static char *processor_arch; | 90 | static char *processor_arch; |
90 | static char *os_build; | 91 | static char *os_build; |
92 | static char *os_version; | ||
91 | static char *lic_version = "Unknown version"; | 93 | static char *lic_version = "Unknown version"; |
92 | static struct utsname uts_buf; | 94 | static struct utsname uts_buf; |
93 | 95 | ||
@@ -297,7 +299,7 @@ static int kvp_file_init(void) | |||
297 | return 0; | 299 | return 0; |
298 | } | 300 | } |
299 | 301 | ||
300 | static int kvp_key_delete(int pool, __u8 *key, int key_size) | 302 | static int kvp_key_delete(int pool, const char *key, int key_size) |
301 | { | 303 | { |
302 | int i; | 304 | int i; |
303 | int j, k; | 305 | int j, k; |
@@ -340,7 +342,7 @@ static int kvp_key_delete(int pool, __u8 *key, int key_size) | |||
340 | return 1; | 342 | return 1; |
341 | } | 343 | } |
342 | 344 | ||
343 | static int kvp_key_add_or_modify(int pool, __u8 *key, int key_size, __u8 *value, | 345 | static int kvp_key_add_or_modify(int pool, const char *key, int key_size, const char *value, |
344 | int value_size) | 346 | int value_size) |
345 | { | 347 | { |
346 | int i; | 348 | int i; |
@@ -394,7 +396,7 @@ static int kvp_key_add_or_modify(int pool, __u8 *key, int key_size, __u8 *value, | |||
394 | return 0; | 396 | return 0; |
395 | } | 397 | } |
396 | 398 | ||
397 | static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value, | 399 | static int kvp_get_value(int pool, const char *key, int key_size, char *value, |
398 | int value_size) | 400 | int value_size) |
399 | { | 401 | { |
400 | int i; | 402 | int i; |
@@ -426,8 +428,8 @@ static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value, | |||
426 | return 1; | 428 | return 1; |
427 | } | 429 | } |
428 | 430 | ||
429 | static int kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size, | 431 | static int kvp_pool_enumerate(int pool, int index, char *key, int key_size, |
430 | __u8 *value, int value_size) | 432 | char *value, int value_size) |
431 | { | 433 | { |
432 | struct kvp_record *record; | 434 | struct kvp_record *record; |
433 | 435 | ||
@@ -453,7 +455,9 @@ void kvp_get_os_info(void) | |||
453 | char *p, buf[512]; | 455 | char *p, buf[512]; |
454 | 456 | ||
455 | uname(&uts_buf); | 457 | uname(&uts_buf); |
456 | os_build = uts_buf.release; | 458 | os_version = uts_buf.release; |
459 | os_build = strdup(uts_buf.release); | ||
460 | |||
457 | os_name = uts_buf.sysname; | 461 | os_name = uts_buf.sysname; |
458 | processor_arch = uts_buf.machine; | 462 | processor_arch = uts_buf.machine; |
459 | 463 | ||
@@ -462,7 +466,7 @@ void kvp_get_os_info(void) | |||
462 | * string to be of the form: x.y.z | 466 | * string to be of the form: x.y.z |
463 | * Strip additional information we may have. | 467 | * Strip additional information we may have. |
464 | */ | 468 | */ |
465 | p = strchr(os_build, '-'); | 469 | p = strchr(os_version, '-'); |
466 | if (p) | 470 | if (p) |
467 | *p = '\0'; | 471 | *p = '\0'; |
468 | 472 | ||
@@ -879,7 +883,7 @@ static int kvp_process_ip_address(void *addrp, | |||
879 | addr_length = INET6_ADDRSTRLEN; | 883 | addr_length = INET6_ADDRSTRLEN; |
880 | } | 884 | } |
881 | 885 | ||
882 | if ((length - *offset) < addr_length + 1) | 886 | if ((length - *offset) < addr_length + 2) |
883 | return HV_E_FAIL; | 887 | return HV_E_FAIL; |
884 | if (str == NULL) { | 888 | if (str == NULL) { |
885 | strcpy(buffer, "inet_ntop failed\n"); | 889 | strcpy(buffer, "inet_ntop failed\n"); |
@@ -887,11 +891,13 @@ static int kvp_process_ip_address(void *addrp, | |||
887 | } | 891 | } |
888 | if (*offset == 0) | 892 | if (*offset == 0) |
889 | strcpy(buffer, tmp); | 893 | strcpy(buffer, tmp); |
890 | else | 894 | else { |
895 | strcat(buffer, ";"); | ||
891 | strcat(buffer, tmp); | 896 | strcat(buffer, tmp); |
892 | strcat(buffer, ";"); | 897 | } |
893 | 898 | ||
894 | *offset += strlen(str) + 1; | 899 | *offset += strlen(str) + 1; |
900 | |||
895 | return 0; | 901 | return 0; |
896 | } | 902 | } |
897 | 903 | ||
@@ -953,7 +959,9 @@ kvp_get_ip_info(int family, char *if_name, int op, | |||
953 | * supported address families; if not we gather info on | 959 | * supported address families; if not we gather info on |
954 | * the specified address family. | 960 | * the specified address family. |
955 | */ | 961 | */ |
956 | if ((family != 0) && (curp->ifa_addr->sa_family != family)) { | 962 | if ((((family != 0) && |
963 | (curp->ifa_addr->sa_family != family))) || | ||
964 | (curp->ifa_flags & IFF_LOOPBACK)) { | ||
957 | curp = curp->ifa_next; | 965 | curp = curp->ifa_next; |
958 | continue; | 966 | continue; |
959 | } | 967 | } |
@@ -1478,13 +1486,19 @@ int main(void) | |||
1478 | len = recvfrom(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0, | 1486 | len = recvfrom(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0, |
1479 | addr_p, &addr_l); | 1487 | addr_p, &addr_l); |
1480 | 1488 | ||
1481 | if (len < 0 || addr.nl_pid) { | 1489 | if (len < 0) { |
1482 | syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s", | 1490 | syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s", |
1483 | addr.nl_pid, errno, strerror(errno)); | 1491 | addr.nl_pid, errno, strerror(errno)); |
1484 | close(fd); | 1492 | close(fd); |
1485 | return -1; | 1493 | return -1; |
1486 | } | 1494 | } |
1487 | 1495 | ||
1496 | if (addr.nl_pid) { | ||
1497 | syslog(LOG_WARNING, "Received packet from untrusted pid:%u", | ||
1498 | addr.nl_pid); | ||
1499 | continue; | ||
1500 | } | ||
1501 | |||
1488 | incoming_msg = (struct nlmsghdr *)kvp_recv_buffer; | 1502 | incoming_msg = (struct nlmsghdr *)kvp_recv_buffer; |
1489 | incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); | 1503 | incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); |
1490 | hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; | 1504 | hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; |
@@ -1649,7 +1663,7 @@ int main(void) | |||
1649 | strcpy(key_name, "OSMinorVersion"); | 1663 | strcpy(key_name, "OSMinorVersion"); |
1650 | break; | 1664 | break; |
1651 | case OSVersion: | 1665 | case OSVersion: |
1652 | strcpy(key_value, os_build); | 1666 | strcpy(key_value, os_version); |
1653 | strcpy(key_name, "OSVersion"); | 1667 | strcpy(key_name, "OSVersion"); |
1654 | break; | 1668 | break; |
1655 | case ProcessorArchitecture: | 1669 | case ProcessorArchitecture: |
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 | |||
20 | utils/cpufreq-aperf.o | 20 | utils/cpufreq-aperf.o |
21 | cpupower | 21 | cpupower |
22 | bench/cpufreq-bench | 22 | bench/cpufreq-bench |
23 | debug/kernel/Module.symvers | ||
24 | debug/i386/centrino-decode | ||
25 | debug/i386/dump_psb | ||
26 | debug/i386/intel_gsic | ||
27 | debug/i386/powernow-k8-decode | ||
28 | debug/x86_64/centrino-decode | ||
29 | debug/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 | |||
26 | all: $(OUTPUT)centrino-decode $(OUTPUT)dump_psb $(OUTPUT)intel_gsic $(OUTPUT)powernow-k8-decode | 26 | all: $(OUTPUT)centrino-decode $(OUTPUT)dump_psb $(OUTPUT)intel_gsic $(OUTPUT)powernow-k8-decode |
27 | 27 | ||
28 | clean: | 28 | clean: |
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 | ||
31 | install: | 34 | install: |
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 | |||
64 | Measure intervall. | 64 | Measure intervall. |
65 | .RE | 65 | .RE |
66 | .PP | 66 | .PP |
67 | \-c | ||
68 | .RS 4 | ||
69 | Schedule the process on every core before starting and ending measuring. | ||
70 | This could be needed for the Idle_Stats monitor when no other MSR based | ||
71 | monitor (has to be run on the core that is measured) is run in parallel. | ||
72 | This is to wake up the processors from deeper sleep states and let the | ||
73 | kernel re | ||
74 | -account its cpuidle (C-state) information before reading the | ||
75 | cpuidle timings from sysfs. | ||
76 | .RE | ||
77 | .PP | ||
67 | command | 78 | command |
68 | .RS 4 | 79 | .RS 4 |
69 | Measure idle and frequency characteristics of an arbitrary command/workload. | 80 | Measure 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); | |||
92 | extern struct cpupower_cpu_info cpupower_cpu_info; | 92 | extern struct cpupower_cpu_info cpupower_cpu_info; |
93 | /* cpuid and cpuinfo helpers **************************/ | 93 | /* cpuid and cpuinfo helpers **************************/ |
94 | 94 | ||
95 | struct 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 ******************/ |
97 | struct cpupower_topology { | 105 | struct 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 | ||
114 | extern int get_cpu_topology(struct cpupower_topology *cpu_top); | 115 | extern int get_cpu_topology(struct cpupower_topology *cpu_top); |
115 | extern void cpu_topology_release(struct cpupower_topology cpu_top); | 116 | extern 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 | ||
40 | static 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 */ |
23 | int sysfs_topology_read_file(unsigned int cpu, const char *fname) | 23 | static 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 | ||
40 | struct 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 | |||
48 | static int __compare(const void *t1, const void *t2) | 39 | static 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 | */ |
74 | int get_cpu_topology(struct cpupower_topology *cpu_top) | 65 | int 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; | |||
39 | static int interval = 1; | 39 | static int interval = 1; |
40 | static char *show_monitors_param; | 40 | static char *show_monitors_param; |
41 | static struct cpupower_topology cpu_top; | 41 | static struct cpupower_topology cpu_top; |
42 | static unsigned int wake_cpus; | ||
42 | 43 | ||
43 | /* ToDo: Document this in the manpage */ | 44 | /* ToDo: Document this in the manpage */ |
44 | static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', }; | 45 | static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', }; |
@@ -84,7 +85,7 @@ int fill_string_with_spaces(char *s, int n) | |||
84 | void print_header(int topology_depth) | 85 | void 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) | |||
315 | int do_interval_measure(int i) | 315 | int 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> | ||
73 | static 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++) { |
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile index b336b24aa6c0..7300d0702efe 100644 --- a/tools/testing/selftests/vm/Makefile +++ b/tools/testing/selftests/vm/Makefile | |||
@@ -1,9 +1,9 @@ | |||
1 | # Makefile for vm selftests | 1 | # Makefile for vm selftests |
2 | 2 | ||
3 | CC = $(CROSS_COMPILE)gcc | 3 | CC = $(CROSS_COMPILE)gcc |
4 | CFLAGS = -Wall -Wextra | 4 | CFLAGS = -Wall |
5 | 5 | ||
6 | all: hugepage-mmap hugepage-shm map_hugetlb | 6 | all: hugepage-mmap hugepage-shm map_hugetlb thuge-gen |
7 | %: %.c | 7 | %: %.c |
8 | $(CC) $(CFLAGS) -o $@ $^ | 8 | $(CC) $(CFLAGS) -o $@ $^ |
9 | 9 | ||
diff --git a/tools/testing/selftests/vm/thuge-gen.c b/tools/testing/selftests/vm/thuge-gen.c new file mode 100644 index 000000000000..c87957295f74 --- /dev/null +++ b/tools/testing/selftests/vm/thuge-gen.c | |||
@@ -0,0 +1,254 @@ | |||
1 | /* Test selecting other page sizes for mmap/shmget. | ||
2 | |||
3 | Before running this huge pages for each huge page size must have been | ||
4 | reserved. | ||
5 | For large pages beyond MAX_ORDER (like 1GB on x86) boot options must be used. | ||
6 | Also shmmax must be increased. | ||
7 | And you need to run as root to work around some weird permissions in shm. | ||
8 | And nothing using huge pages should run in parallel. | ||
9 | When the program aborts you may need to clean up the shm segments with | ||
10 | ipcrm -m by hand, like this | ||
11 | sudo ipcs | awk '$1 == "0x00000000" {print $2}' | xargs -n1 sudo ipcrm -m | ||
12 | (warning this will remove all if someone else uses them) */ | ||
13 | |||
14 | #define _GNU_SOURCE 1 | ||
15 | #include <sys/mman.h> | ||
16 | #include <stdlib.h> | ||
17 | #include <stdio.h> | ||
18 | #include <sys/ipc.h> | ||
19 | #include <sys/shm.h> | ||
20 | #include <sys/stat.h> | ||
21 | #include <glob.h> | ||
22 | #include <assert.h> | ||
23 | #include <unistd.h> | ||
24 | #include <stdarg.h> | ||
25 | #include <string.h> | ||
26 | |||
27 | #define err(x) perror(x), exit(1) | ||
28 | |||
29 | #define MAP_HUGE_2MB (21 << MAP_HUGE_SHIFT) | ||
30 | #define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT) | ||
31 | #define MAP_HUGE_SHIFT 26 | ||
32 | #define MAP_HUGE_MASK 0x3f | ||
33 | #define MAP_HUGETLB 0x40000 | ||
34 | |||
35 | #define SHM_HUGETLB 04000 /* segment will use huge TLB pages */ | ||
36 | #define SHM_HUGE_SHIFT 26 | ||
37 | #define SHM_HUGE_MASK 0x3f | ||
38 | #define SHM_HUGE_2MB (21 << SHM_HUGE_SHIFT) | ||
39 | #define SHM_HUGE_1GB (30 << SHM_HUGE_SHIFT) | ||
40 | |||
41 | #define NUM_PAGESIZES 5 | ||
42 | |||
43 | #define NUM_PAGES 4 | ||
44 | |||
45 | #define Dprintf(fmt...) // printf(fmt) | ||
46 | |||
47 | unsigned long page_sizes[NUM_PAGESIZES]; | ||
48 | int num_page_sizes; | ||
49 | |||
50 | int ilog2(unsigned long v) | ||
51 | { | ||
52 | int l = 0; | ||
53 | while ((1UL << l) < v) | ||
54 | l++; | ||
55 | return l; | ||
56 | } | ||
57 | |||
58 | void find_pagesizes(void) | ||
59 | { | ||
60 | glob_t g; | ||
61 | int i; | ||
62 | glob("/sys/kernel/mm/hugepages/hugepages-*kB", 0, NULL, &g); | ||
63 | assert(g.gl_pathc <= NUM_PAGESIZES); | ||
64 | for (i = 0; i < g.gl_pathc; i++) { | ||
65 | sscanf(g.gl_pathv[i], "/sys/kernel/mm/hugepages/hugepages-%lukB", | ||
66 | &page_sizes[i]); | ||
67 | page_sizes[i] <<= 10; | ||
68 | printf("Found %luMB\n", page_sizes[i] >> 20); | ||
69 | } | ||
70 | num_page_sizes = g.gl_pathc; | ||
71 | globfree(&g); | ||
72 | } | ||
73 | |||
74 | unsigned long default_huge_page_size(void) | ||
75 | { | ||
76 | unsigned long hps = 0; | ||
77 | char *line = NULL; | ||
78 | size_t linelen = 0; | ||
79 | FILE *f = fopen("/proc/meminfo", "r"); | ||
80 | if (!f) | ||
81 | return 0; | ||
82 | while (getline(&line, &linelen, f) > 0) { | ||
83 | if (sscanf(line, "Hugepagesize: %lu kB", &hps) == 1) { | ||
84 | hps <<= 10; | ||
85 | break; | ||
86 | } | ||
87 | } | ||
88 | free(line); | ||
89 | return hps; | ||
90 | } | ||
91 | |||
92 | void show(unsigned long ps) | ||
93 | { | ||
94 | char buf[100]; | ||
95 | if (ps == getpagesize()) | ||
96 | return; | ||
97 | printf("%luMB: ", ps >> 20); | ||
98 | fflush(stdout); | ||
99 | snprintf(buf, sizeof buf, | ||
100 | "cat /sys/kernel/mm/hugepages/hugepages-%lukB/free_hugepages", | ||
101 | ps >> 10); | ||
102 | system(buf); | ||
103 | } | ||
104 | |||
105 | unsigned long read_sysfs(int warn, char *fmt, ...) | ||
106 | { | ||
107 | char *line = NULL; | ||
108 | size_t linelen = 0; | ||
109 | char buf[100]; | ||
110 | FILE *f; | ||
111 | va_list ap; | ||
112 | unsigned long val = 0; | ||
113 | |||
114 | va_start(ap, fmt); | ||
115 | vsnprintf(buf, sizeof buf, fmt, ap); | ||
116 | va_end(ap); | ||
117 | |||
118 | f = fopen(buf, "r"); | ||
119 | if (!f) { | ||
120 | if (warn) | ||
121 | printf("missing %s\n", buf); | ||
122 | return 0; | ||
123 | } | ||
124 | if (getline(&line, &linelen, f) > 0) { | ||
125 | sscanf(line, "%lu", &val); | ||
126 | } | ||
127 | fclose(f); | ||
128 | free(line); | ||
129 | return val; | ||
130 | } | ||
131 | |||
132 | unsigned long read_free(unsigned long ps) | ||
133 | { | ||
134 | return read_sysfs(ps != getpagesize(), | ||
135 | "/sys/kernel/mm/hugepages/hugepages-%lukB/free_hugepages", | ||
136 | ps >> 10); | ||
137 | } | ||
138 | |||
139 | void test_mmap(unsigned long size, unsigned flags) | ||
140 | { | ||
141 | char *map; | ||
142 | unsigned long before, after; | ||
143 | int err; | ||
144 | |||
145 | before = read_free(size); | ||
146 | map = mmap(NULL, size*NUM_PAGES, PROT_READ|PROT_WRITE, | ||
147 | MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|flags, 0, 0); | ||
148 | |||
149 | if (map == (char *)-1) err("mmap"); | ||
150 | memset(map, 0xff, size*NUM_PAGES); | ||
151 | after = read_free(size); | ||
152 | Dprintf("before %lu after %lu diff %ld size %lu\n", | ||
153 | before, after, before - after, size); | ||
154 | assert(size == getpagesize() || (before - after) == NUM_PAGES); | ||
155 | show(size); | ||
156 | err = munmap(map, size); | ||
157 | assert(!err); | ||
158 | } | ||
159 | |||
160 | void test_shmget(unsigned long size, unsigned flags) | ||
161 | { | ||
162 | int id; | ||
163 | unsigned long before, after; | ||
164 | int err; | ||
165 | |||
166 | before = read_free(size); | ||
167 | id = shmget(IPC_PRIVATE, size * NUM_PAGES, IPC_CREAT|0600|flags); | ||
168 | if (id < 0) err("shmget"); | ||
169 | |||
170 | struct shm_info i; | ||
171 | if (shmctl(id, SHM_INFO, (void *)&i) < 0) err("shmctl"); | ||
172 | Dprintf("alloc %lu res %lu\n", i.shm_tot, i.shm_rss); | ||
173 | |||
174 | |||
175 | Dprintf("id %d\n", id); | ||
176 | char *map = shmat(id, NULL, 0600); | ||
177 | if (map == (char*)-1) err("shmat"); | ||
178 | |||
179 | shmctl(id, IPC_RMID, NULL); | ||
180 | |||
181 | memset(map, 0xff, size*NUM_PAGES); | ||
182 | after = read_free(size); | ||
183 | |||
184 | Dprintf("before %lu after %lu diff %ld size %lu\n", | ||
185 | before, after, before - after, size); | ||
186 | assert(size == getpagesize() || (before - after) == NUM_PAGES); | ||
187 | show(size); | ||
188 | err = shmdt(map); | ||
189 | assert(!err); | ||
190 | } | ||
191 | |||
192 | void sanity_checks(void) | ||
193 | { | ||
194 | int i; | ||
195 | unsigned long largest = getpagesize(); | ||
196 | |||
197 | for (i = 0; i < num_page_sizes; i++) { | ||
198 | if (page_sizes[i] > largest) | ||
199 | largest = page_sizes[i]; | ||
200 | |||
201 | if (read_free(page_sizes[i]) < NUM_PAGES) { | ||
202 | printf("Not enough huge pages for page size %lu MB, need %u\n", | ||
203 | page_sizes[i] >> 20, | ||
204 | NUM_PAGES); | ||
205 | exit(0); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | if (read_sysfs(0, "/proc/sys/kernel/shmmax") < NUM_PAGES * largest) { | ||
210 | printf("Please do echo %lu > /proc/sys/kernel/shmmax", largest * NUM_PAGES); | ||
211 | exit(0); | ||
212 | } | ||
213 | |||
214 | #if defined(__x86_64__) | ||
215 | if (largest != 1U<<30) { | ||
216 | printf("No GB pages available on x86-64\n" | ||
217 | "Please boot with hugepagesz=1G hugepages=%d\n", NUM_PAGES); | ||
218 | exit(0); | ||
219 | } | ||
220 | #endif | ||
221 | } | ||
222 | |||
223 | int main(void) | ||
224 | { | ||
225 | int i; | ||
226 | unsigned default_hps = default_huge_page_size(); | ||
227 | |||
228 | find_pagesizes(); | ||
229 | |||
230 | sanity_checks(); | ||
231 | |||
232 | for (i = 0; i < num_page_sizes; i++) { | ||
233 | unsigned long ps = page_sizes[i]; | ||
234 | int arg = ilog2(ps) << MAP_HUGE_SHIFT; | ||
235 | printf("Testing %luMB mmap with shift %x\n", ps >> 20, arg); | ||
236 | test_mmap(ps, MAP_HUGETLB | arg); | ||
237 | } | ||
238 | printf("Testing default huge mmap\n"); | ||
239 | test_mmap(default_hps, SHM_HUGETLB); | ||
240 | |||
241 | puts("Testing non-huge shmget"); | ||
242 | test_shmget(getpagesize(), 0); | ||
243 | |||
244 | for (i = 0; i < num_page_sizes; i++) { | ||
245 | unsigned long ps = page_sizes[i]; | ||
246 | int arg = ilog2(ps) << SHM_HUGE_SHIFT; | ||
247 | printf("Testing %luMB shmget with shift %x\n", ps >> 20, arg); | ||
248 | test_shmget(ps, SHM_HUGETLB | arg); | ||
249 | } | ||
250 | puts("default huge shmget"); | ||
251 | test_shmget(default_hps, SHM_HUGETLB); | ||
252 | |||
253 | return 0; | ||
254 | } | ||