aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-10-24 04:20:57 -0400
committerIngo Molnar <mingo@kernel.org>2012-10-24 04:20:57 -0400
commitef8c029fa793423439e67ef0416b220d3fa3321a (patch)
tree4199cefa6e1dcad1783040755246a14371f029af /tools
parent6fcdb1ed2ef3548d5a9428d6ae60158ddd46a608 (diff)
parentc13d38e4a1fd5dd07135403c613c8091af444169 (diff)
Merge branch 'perf/urgent' into perf/core
Pick up v3.7-rc2 and fixes before applying more patches. Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rwxr-xr-xtools/hv/hv_get_dhcp_info.sh28
-rwxr-xr-xtools/hv/hv_get_dns_info.sh13
-rw-r--r--tools/hv/hv_kvp_daemon.c1036
-rwxr-xr-xtools/hv/hv_set_ifconfig.sh68
-rw-r--r--tools/lguest/lguest.c1
-rw-r--r--tools/lib/traceevent/event-parse.c9
-rw-r--r--tools/lib/traceevent/parse-filter.c15
-rw-r--r--tools/perf/Makefile33
-rw-r--r--tools/perf/builtin-help.c2
-rw-r--r--tools/perf/builtin-trace.c18
-rw-r--r--tools/perf/perf.h10
-rw-r--r--tools/perf/ui/browsers/hists.c6
-rw-r--r--tools/perf/util/callchain.h2
-rw-r--r--tools/perf/util/evsel.c2
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/include/asm/byteorder.h2
-rw-r--r--tools/perf/util/include/linux/const.h2
-rw-r--r--tools/perf/util/include/linux/rbtree_augmented.h2
-rw-r--r--tools/perf/util/parse-events-test.c14
-rw-r--r--tools/perf/util/parse-events.c3
-rw-r--r--tools/perf/util/parse-events.h2
-rw-r--r--tools/perf/util/pmu.h2
-rw-r--r--tools/perf/util/python-ext-sources2
-rw-r--r--tools/perf/util/session.h2
-rw-r--r--tools/perf/util/setup.py2
-rw-r--r--tools/perf/util/sort.c6
-rw-r--r--tools/perf/util/thread.c1
-rw-r--r--tools/power/acpi/Makefile18
-rw-r--r--tools/power/acpi/acpidump.859
-rw-r--r--tools/power/acpi/acpidump.c559
-rw-r--r--tools/power/cpupower/Makefile2
-rw-r--r--tools/power/x86/turbostat/turbostat.855
-rw-r--r--tools/power/x86/turbostat/turbostat.c214
-rw-r--r--tools/testing/ktest/examples/include/defaults.conf2
-rw-r--r--tools/testing/ktest/examples/include/tests.conf2
-rwxr-xr-xtools/testing/ktest/ktest.pl19
-rw-r--r--tools/testing/selftests/Makefile2
-rw-r--r--tools/testing/selftests/epoll/Makefile11
-rw-r--r--tools/testing/selftests/epoll/test_epoll.c344
-rw-r--r--tools/testing/selftests/vm/run_vmtests6
-rw-r--r--tools/usb/testusb.c25
-rw-r--r--tools/virtio/virtio-trace/Makefile13
-rw-r--r--tools/virtio/virtio-trace/README118
-rw-r--r--tools/virtio/virtio-trace/trace-agent-ctl.c137
-rw-r--r--tools/virtio/virtio-trace/trace-agent-rw.c192
-rw-r--r--tools/virtio/virtio-trace/trace-agent.c270
-rw-r--r--tools/virtio/virtio-trace/trace-agent.h75
-rw-r--r--tools/vm/page-types.c2
49 files changed, 3179 insertions, 233 deletions
diff --git a/tools/hv/hv_get_dhcp_info.sh b/tools/hv/hv_get_dhcp_info.sh
new file mode 100755
index 00000000000..ccd3e953276
--- /dev/null
+++ b/tools/hv/hv_get_dhcp_info.sh
@@ -0,0 +1,28 @@
1#!/bin/bash
2
3# This example script retrieves the DHCP state of a given interface.
4# In the interest of keeping the KVP daemon code free of distro specific
5# information; the kvp daemon code invokes this external script to gather
6# DHCP setting for the specific interface.
7#
8# Input: Name of the interface
9#
10# Output: The script prints the string "Enabled" to stdout to indicate
11# that DHCP is enabled on the interface. If DHCP is not enabled,
12# the script prints the string "Disabled" to stdout.
13#
14# Each Distro is expected to implement this script in a distro specific
15# fashion. For instance on Distros that ship with Network Manager enabled,
16# this script can be based on the Network Manager APIs for retrieving DHCP
17# information.
18
19if_file="/etc/sysconfig/network-scripts/ifcfg-"$1
20
21dhcp=$(grep "dhcp" $if_file 2>/dev/null)
22
23if [ "$dhcp" != "" ];
24then
25echo "Enabled"
26else
27echo "Disabled"
28fi
diff --git a/tools/hv/hv_get_dns_info.sh b/tools/hv/hv_get_dns_info.sh
new file mode 100755
index 00000000000..058c17b46ff
--- /dev/null
+++ b/tools/hv/hv_get_dns_info.sh
@@ -0,0 +1,13 @@
1#!/bin/bash
2
3# This example script parses /etc/resolv.conf to retrive DNS information.
4# In the interest of keeping the KVP daemon code free of distro specific
5# information; the kvp daemon code invokes this external script to gather
6# DNS information.
7# This script is expected to print the nameserver values to stdout.
8# Each Distro is expected to implement this script in a distro specific
9# fashion. For instance on Distros that ship with Network Manager enabled,
10# this script can be based on the Network Manager APIs for retrieving DNS
11# entries.
12
13cat /etc/resolv.conf 2>/dev/null | awk '/^nameserver/ { print $2 }'
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index d9834b36294..5959affd882 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -31,6 +31,7 @@
31#include <stdlib.h> 31#include <stdlib.h>
32#include <unistd.h> 32#include <unistd.h>
33#include <string.h> 33#include <string.h>
34#include <ctype.h>
34#include <errno.h> 35#include <errno.h>
35#include <arpa/inet.h> 36#include <arpa/inet.h>
36#include <linux/connector.h> 37#include <linux/connector.h>
@@ -41,6 +42,7 @@
41#include <syslog.h> 42#include <syslog.h>
42#include <sys/stat.h> 43#include <sys/stat.h>
43#include <fcntl.h> 44#include <fcntl.h>
45#include <dirent.h>
44 46
45/* 47/*
46 * KVP protocol: The user mode component first registers with the 48 * KVP protocol: The user mode component first registers with the
@@ -68,25 +70,39 @@ enum key_index {
68 ProcessorArchitecture 70 ProcessorArchitecture
69}; 71};
70 72
73
74enum {
75 IPADDR = 0,
76 NETMASK,
77 GATEWAY,
78 DNS
79};
80
71static char kvp_send_buffer[4096]; 81static char kvp_send_buffer[4096];
72static char kvp_recv_buffer[4096]; 82static char kvp_recv_buffer[4096 * 2];
73static struct sockaddr_nl addr; 83static struct sockaddr_nl addr;
84static int in_hand_shake = 1;
74 85
75static char *os_name = ""; 86static char *os_name = "";
76static char *os_major = ""; 87static char *os_major = "";
77static char *os_minor = ""; 88static char *os_minor = "";
78static char *processor_arch; 89static char *processor_arch;
79static char *os_build; 90static char *os_build;
80static char *lic_version; 91static char *lic_version = "Unknown version";
81static struct utsname uts_buf; 92static struct utsname uts_buf;
82 93
94/*
95 * The location of the interface configuration file.
96 */
97
98#define KVP_CONFIG_LOC "/var/opt/"
83 99
84#define MAX_FILE_NAME 100 100#define MAX_FILE_NAME 100
85#define ENTRIES_PER_BLOCK 50 101#define ENTRIES_PER_BLOCK 50
86 102
87struct kvp_record { 103struct kvp_record {
88 __u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; 104 char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
89 __u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; 105 char value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
90}; 106};
91 107
92struct kvp_file_state { 108struct kvp_file_state {
@@ -94,7 +110,7 @@ struct kvp_file_state {
94 int num_blocks; 110 int num_blocks;
95 struct kvp_record *records; 111 struct kvp_record *records;
96 int num_records; 112 int num_records;
97 __u8 fname[MAX_FILE_NAME]; 113 char fname[MAX_FILE_NAME];
98}; 114};
99 115
100static struct kvp_file_state kvp_file_info[KVP_POOL_COUNT]; 116static struct kvp_file_state kvp_file_info[KVP_POOL_COUNT];
@@ -106,7 +122,7 @@ static void kvp_acquire_lock(int pool)
106 122
107 if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) { 123 if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) {
108 syslog(LOG_ERR, "Failed to acquire the lock pool: %d", pool); 124 syslog(LOG_ERR, "Failed to acquire the lock pool: %d", pool);
109 exit(-1); 125 exit(EXIT_FAILURE);
110 } 126 }
111} 127}
112 128
@@ -118,7 +134,7 @@ static void kvp_release_lock(int pool)
118 if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) { 134 if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) {
119 perror("fcntl"); 135 perror("fcntl");
120 syslog(LOG_ERR, "Failed to release the lock pool: %d", pool); 136 syslog(LOG_ERR, "Failed to release the lock pool: %d", pool);
121 exit(-1); 137 exit(EXIT_FAILURE);
122 } 138 }
123} 139}
124 140
@@ -137,14 +153,19 @@ static void kvp_update_file(int pool)
137 if (!filep) { 153 if (!filep) {
138 kvp_release_lock(pool); 154 kvp_release_lock(pool);
139 syslog(LOG_ERR, "Failed to open file, pool: %d", pool); 155 syslog(LOG_ERR, "Failed to open file, pool: %d", pool);
140 exit(-1); 156 exit(EXIT_FAILURE);
141 } 157 }
142 158
143 bytes_written = fwrite(kvp_file_info[pool].records, 159 bytes_written = fwrite(kvp_file_info[pool].records,
144 sizeof(struct kvp_record), 160 sizeof(struct kvp_record),
145 kvp_file_info[pool].num_records, filep); 161 kvp_file_info[pool].num_records, filep);
146 162
147 fflush(filep); 163 if (ferror(filep) || fclose(filep)) {
164 kvp_release_lock(pool);
165 syslog(LOG_ERR, "Failed to write file, pool: %d", pool);
166 exit(EXIT_FAILURE);
167 }
168
148 kvp_release_lock(pool); 169 kvp_release_lock(pool);
149} 170}
150 171
@@ -163,14 +184,19 @@ static void kvp_update_mem_state(int pool)
163 if (!filep) { 184 if (!filep) {
164 kvp_release_lock(pool); 185 kvp_release_lock(pool);
165 syslog(LOG_ERR, "Failed to open file, pool: %d", pool); 186 syslog(LOG_ERR, "Failed to open file, pool: %d", pool);
166 exit(-1); 187 exit(EXIT_FAILURE);
167 } 188 }
168 while (!feof(filep)) { 189 for (;;) {
169 readp = &record[records_read]; 190 readp = &record[records_read];
170 records_read += fread(readp, sizeof(struct kvp_record), 191 records_read += fread(readp, sizeof(struct kvp_record),
171 ENTRIES_PER_BLOCK * num_blocks, 192 ENTRIES_PER_BLOCK * num_blocks,
172 filep); 193 filep);
173 194
195 if (ferror(filep)) {
196 syslog(LOG_ERR, "Failed to read file, pool: %d", pool);
197 exit(EXIT_FAILURE);
198 }
199
174 if (!feof(filep)) { 200 if (!feof(filep)) {
175 /* 201 /*
176 * We have more data to read. 202 * We have more data to read.
@@ -180,7 +206,7 @@ static void kvp_update_mem_state(int pool)
180 206
181 if (record == NULL) { 207 if (record == NULL) {
182 syslog(LOG_ERR, "malloc failed"); 208 syslog(LOG_ERR, "malloc failed");
183 exit(-1); 209 exit(EXIT_FAILURE);
184 } 210 }
185 continue; 211 continue;
186 } 212 }
@@ -191,14 +217,15 @@ static void kvp_update_mem_state(int pool)
191 kvp_file_info[pool].records = record; 217 kvp_file_info[pool].records = record;
192 kvp_file_info[pool].num_records = records_read; 218 kvp_file_info[pool].num_records = records_read;
193 219
220 fclose(filep);
194 kvp_release_lock(pool); 221 kvp_release_lock(pool);
195} 222}
196static int kvp_file_init(void) 223static int kvp_file_init(void)
197{ 224{
198 int ret, fd; 225 int fd;
199 FILE *filep; 226 FILE *filep;
200 size_t records_read; 227 size_t records_read;
201 __u8 *fname; 228 char *fname;
202 struct kvp_record *record; 229 struct kvp_record *record;
203 struct kvp_record *readp; 230 struct kvp_record *readp;
204 int num_blocks; 231 int num_blocks;
@@ -208,7 +235,7 @@ static int kvp_file_init(void)
208 if (access("/var/opt/hyperv", F_OK)) { 235 if (access("/var/opt/hyperv", F_OK)) {
209 if (mkdir("/var/opt/hyperv", S_IRUSR | S_IWUSR | S_IROTH)) { 236 if (mkdir("/var/opt/hyperv", S_IRUSR | S_IWUSR | S_IROTH)) {
210 syslog(LOG_ERR, " Failed to create /var/opt/hyperv"); 237 syslog(LOG_ERR, " Failed to create /var/opt/hyperv");
211 exit(-1); 238 exit(EXIT_FAILURE);
212 } 239 }
213 } 240 }
214 241
@@ -232,12 +259,18 @@ static int kvp_file_init(void)
232 fclose(filep); 259 fclose(filep);
233 return 1; 260 return 1;
234 } 261 }
235 while (!feof(filep)) { 262 for (;;) {
236 readp = &record[records_read]; 263 readp = &record[records_read];
237 records_read += fread(readp, sizeof(struct kvp_record), 264 records_read += fread(readp, sizeof(struct kvp_record),
238 ENTRIES_PER_BLOCK, 265 ENTRIES_PER_BLOCK,
239 filep); 266 filep);
240 267
268 if (ferror(filep)) {
269 syslog(LOG_ERR, "Failed to read file, pool: %d",
270 i);
271 exit(EXIT_FAILURE);
272 }
273
241 if (!feof(filep)) { 274 if (!feof(filep)) {
242 /* 275 /*
243 * We have more data to read. 276 * We have more data to read.
@@ -311,7 +344,6 @@ static int kvp_key_add_or_modify(int pool, __u8 *key, int key_size, __u8 *value,
311 int value_size) 344 int value_size)
312{ 345{
313 int i; 346 int i;
314 int j, k;
315 int num_records; 347 int num_records;
316 struct kvp_record *record; 348 struct kvp_record *record;
317 int num_blocks; 349 int num_blocks;
@@ -394,7 +426,7 @@ static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
394 return 1; 426 return 1;
395} 427}
396 428
397static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size, 429static int kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
398 __u8 *value, int value_size) 430 __u8 *value, int value_size)
399{ 431{
400 struct kvp_record *record; 432 struct kvp_record *record;
@@ -406,16 +438,12 @@ static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
406 record = kvp_file_info[pool].records; 438 record = kvp_file_info[pool].records;
407 439
408 if (index >= kvp_file_info[pool].num_records) { 440 if (index >= kvp_file_info[pool].num_records) {
409 /* 441 return 1;
410 * This is an invalid index; terminate enumeration;
411 * - a NULL value will do the trick.
412 */
413 strcpy(value, "");
414 return;
415 } 442 }
416 443
417 memcpy(key, record[index].key, key_size); 444 memcpy(key, record[index].key, key_size);
418 memcpy(value, record[index].value, value_size); 445 memcpy(value, record[index].value, value_size);
446 return 0;
419} 447}
420 448
421 449
@@ -426,6 +454,7 @@ void kvp_get_os_info(void)
426 454
427 uname(&uts_buf); 455 uname(&uts_buf);
428 os_build = uts_buf.release; 456 os_build = uts_buf.release;
457 os_name = uts_buf.sysname;
429 processor_arch = uts_buf.machine; 458 processor_arch = uts_buf.machine;
430 459
431 /* 460 /*
@@ -437,20 +466,70 @@ void kvp_get_os_info(void)
437 if (p) 466 if (p)
438 *p = '\0'; 467 *p = '\0';
439 468
469 /*
470 * Parse the /etc/os-release file if present:
471 * http://www.freedesktop.org/software/systemd/man/os-release.html
472 */
473 file = fopen("/etc/os-release", "r");
474 if (file != NULL) {
475 while (fgets(buf, sizeof(buf), file)) {
476 char *value, *q;
477
478 /* Ignore comments */
479 if (buf[0] == '#')
480 continue;
481
482 /* Split into name=value */
483 p = strchr(buf, '=');
484 if (!p)
485 continue;
486 *p++ = 0;
487
488 /* Remove quotes and newline; un-escape */
489 value = p;
490 q = p;
491 while (*p) {
492 if (*p == '\\') {
493 ++p;
494 if (!*p)
495 break;
496 *q++ = *p++;
497 } else if (*p == '\'' || *p == '"' ||
498 *p == '\n') {
499 ++p;
500 } else {
501 *q++ = *p++;
502 }
503 }
504 *q = 0;
505
506 if (!strcmp(buf, "NAME")) {
507 p = strdup(value);
508 if (!p)
509 break;
510 os_name = p;
511 } else if (!strcmp(buf, "VERSION_ID")) {
512 p = strdup(value);
513 if (!p)
514 break;
515 os_major = p;
516 }
517 }
518 fclose(file);
519 return;
520 }
521
522 /* Fallback for older RH/SUSE releases */
440 file = fopen("/etc/SuSE-release", "r"); 523 file = fopen("/etc/SuSE-release", "r");
441 if (file != NULL) 524 if (file != NULL)
442 goto kvp_osinfo_found; 525 goto kvp_osinfo_found;
443 file = fopen("/etc/redhat-release", "r"); 526 file = fopen("/etc/redhat-release", "r");
444 if (file != NULL) 527 if (file != NULL)
445 goto kvp_osinfo_found; 528 goto kvp_osinfo_found;
446 /*
447 * Add code for other supported platforms.
448 */
449 529
450 /* 530 /*
451 * We don't have information about the os. 531 * We don't have information about the os.
452 */ 532 */
453 os_name = uts_buf.sysname;
454 return; 533 return;
455 534
456kvp_osinfo_found: 535kvp_osinfo_found:
@@ -494,82 +573,458 @@ done:
494 return; 573 return;
495} 574}
496 575
576
577
578/*
579 * Retrieve an interface name corresponding to the specified guid.
580 * If there is a match, the function returns a pointer
581 * to the interface name and if not, a NULL is returned.
582 * If a match is found, the caller is responsible for
583 * freeing the memory.
584 */
585
586static char *kvp_get_if_name(char *guid)
587{
588 DIR *dir;
589 struct dirent *entry;
590 FILE *file;
591 char *p, *q, *x;
592 char *if_name = NULL;
593 char buf[256];
594 char *kvp_net_dir = "/sys/class/net/";
595 char dev_id[256];
596
597 dir = opendir(kvp_net_dir);
598 if (dir == NULL)
599 return NULL;
600
601 snprintf(dev_id, sizeof(dev_id), "%s", kvp_net_dir);
602 q = dev_id + strlen(kvp_net_dir);
603
604 while ((entry = readdir(dir)) != NULL) {
605 /*
606 * Set the state for the next pass.
607 */
608 *q = '\0';
609 strcat(dev_id, entry->d_name);
610 strcat(dev_id, "/device/device_id");
611
612 file = fopen(dev_id, "r");
613 if (file == NULL)
614 continue;
615
616 p = fgets(buf, sizeof(buf), file);
617 if (p) {
618 x = strchr(p, '\n');
619 if (x)
620 *x = '\0';
621
622 if (!strcmp(p, guid)) {
623 /*
624 * Found the guid match; return the interface
625 * name. The caller will free the memory.
626 */
627 if_name = strdup(entry->d_name);
628 fclose(file);
629 break;
630 }
631 }
632 fclose(file);
633 }
634
635 closedir(dir);
636 return if_name;
637}
638
639/*
640 * Retrieve the MAC address given the interface name.
641 */
642
643static char *kvp_if_name_to_mac(char *if_name)
644{
645 FILE *file;
646 char *p, *x;
647 char buf[256];
648 char addr_file[256];
649 int i;
650 char *mac_addr = NULL;
651
652 snprintf(addr_file, sizeof(addr_file), "%s%s%s", "/sys/class/net/",
653 if_name, "/address");
654
655 file = fopen(addr_file, "r");
656 if (file == NULL)
657 return NULL;
658
659 p = fgets(buf, sizeof(buf), file);
660 if (p) {
661 x = strchr(p, '\n');
662 if (x)
663 *x = '\0';
664 for (i = 0; i < strlen(p); i++)
665 p[i] = toupper(p[i]);
666 mac_addr = strdup(p);
667 }
668
669 fclose(file);
670 return mac_addr;
671}
672
673
674/*
675 * Retrieve the interface name given tha MAC address.
676 */
677
678static char *kvp_mac_to_if_name(char *mac)
679{
680 DIR *dir;
681 struct dirent *entry;
682 FILE *file;
683 char *p, *q, *x;
684 char *if_name = NULL;
685 char buf[256];
686 char *kvp_net_dir = "/sys/class/net/";
687 char dev_id[256];
688 int i;
689
690 dir = opendir(kvp_net_dir);
691 if (dir == NULL)
692 return NULL;
693
694 snprintf(dev_id, sizeof(dev_id), kvp_net_dir);
695 q = dev_id + strlen(kvp_net_dir);
696
697 while ((entry = readdir(dir)) != NULL) {
698 /*
699 * Set the state for the next pass.
700 */
701 *q = '\0';
702
703 strcat(dev_id, entry->d_name);
704 strcat(dev_id, "/address");
705
706 file = fopen(dev_id, "r");
707 if (file == NULL)
708 continue;
709
710 p = fgets(buf, sizeof(buf), file);
711 if (p) {
712 x = strchr(p, '\n');
713 if (x)
714 *x = '\0';
715
716 for (i = 0; i < strlen(p); i++)
717 p[i] = toupper(p[i]);
718
719 if (!strcmp(p, mac)) {
720 /*
721 * Found the MAC match; return the interface
722 * name. The caller will free the memory.
723 */
724 if_name = strdup(entry->d_name);
725 fclose(file);
726 break;
727 }
728 }
729 fclose(file);
730 }
731
732 closedir(dir);
733 return if_name;
734}
735
736
737static void kvp_process_ipconfig_file(char *cmd,
738 char *config_buf, int len,
739 int element_size, int offset)
740{
741 char buf[256];
742 char *p;
743 char *x;
744 FILE *file;
745
746 /*
747 * First execute the command.
748 */
749 file = popen(cmd, "r");
750 if (file == NULL)
751 return;
752
753 if (offset == 0)
754 memset(config_buf, 0, len);
755 while ((p = fgets(buf, sizeof(buf), file)) != NULL) {
756 if ((len - strlen(config_buf)) < (element_size + 1))
757 break;
758
759 x = strchr(p, '\n');
760 *x = '\0';
761 strcat(config_buf, p);
762 strcat(config_buf, ";");
763 }
764 pclose(file);
765}
766
767static void kvp_get_ipconfig_info(char *if_name,
768 struct hv_kvp_ipaddr_value *buffer)
769{
770 char cmd[512];
771 char dhcp_info[128];
772 char *p;
773 FILE *file;
774
775 /*
776 * Get the address of default gateway (ipv4).
777 */
778 sprintf(cmd, "%s %s", "ip route show dev", if_name);
779 strcat(cmd, " | awk '/default/ {print $3 }'");
780
781 /*
782 * Execute the command to gather gateway info.
783 */
784 kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way,
785 (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0);
786
787 /*
788 * Get the address of default gateway (ipv6).
789 */
790 sprintf(cmd, "%s %s", "ip -f inet6 route show dev", if_name);
791 strcat(cmd, " | awk '/default/ {print $3 }'");
792
793 /*
794 * Execute the command to gather gateway info (ipv6).
795 */
796 kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way,
797 (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1);
798
799
800 /*
801 * Gather the DNS state.
802 * Since there is no standard way to get this information
803 * across various distributions of interest; we just invoke
804 * an external script that needs to be ported across distros
805 * of interest.
806 *
807 * Following is the expected format of the information from the script:
808 *
809 * ipaddr1 (nameserver1)
810 * ipaddr2 (nameserver2)
811 * .
812 * .
813 */
814
815 sprintf(cmd, "%s", "hv_get_dns_info");
816
817 /*
818 * Execute the command to gather DNS info.
819 */
820 kvp_process_ipconfig_file(cmd, (char *)buffer->dns_addr,
821 (MAX_IP_ADDR_SIZE * 2), INET_ADDRSTRLEN, 0);
822
823 /*
824 * Gather the DHCP state.
825 * We will gather this state by invoking an external script.
826 * The parameter to the script is the interface name.
827 * Here is the expected output:
828 *
829 * Enabled: DHCP enabled.
830 */
831
832 sprintf(cmd, "%s %s", "hv_get_dhcp_info", if_name);
833
834 file = popen(cmd, "r");
835 if (file == NULL)
836 return;
837
838 p = fgets(dhcp_info, sizeof(dhcp_info), file);
839 if (p == NULL) {
840 pclose(file);
841 return;
842 }
843
844 if (!strncmp(p, "Enabled", 7))
845 buffer->dhcp_enabled = 1;
846 else
847 buffer->dhcp_enabled = 0;
848
849 pclose(file);
850}
851
852
853static unsigned int hweight32(unsigned int *w)
854{
855 unsigned int res = *w - ((*w >> 1) & 0x55555555);
856 res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
857 res = (res + (res >> 4)) & 0x0F0F0F0F;
858 res = res + (res >> 8);
859 return (res + (res >> 16)) & 0x000000FF;
860}
861
862static int kvp_process_ip_address(void *addrp,
863 int family, char *buffer,
864 int length, int *offset)
865{
866 struct sockaddr_in *addr;
867 struct sockaddr_in6 *addr6;
868 int addr_length;
869 char tmp[50];
870 const char *str;
871
872 if (family == AF_INET) {
873 addr = (struct sockaddr_in *)addrp;
874 str = inet_ntop(family, &addr->sin_addr, tmp, 50);
875 addr_length = INET_ADDRSTRLEN;
876 } else {
877 addr6 = (struct sockaddr_in6 *)addrp;
878 str = inet_ntop(family, &addr6->sin6_addr.s6_addr, tmp, 50);
879 addr_length = INET6_ADDRSTRLEN;
880 }
881
882 if ((length - *offset) < addr_length + 1)
883 return HV_E_FAIL;
884 if (str == NULL) {
885 strcpy(buffer, "inet_ntop failed\n");
886 return HV_E_FAIL;
887 }
888 if (*offset == 0)
889 strcpy(buffer, tmp);
890 else
891 strcat(buffer, tmp);
892 strcat(buffer, ";");
893
894 *offset += strlen(str) + 1;
895 return 0;
896}
897
497static int 898static int
498kvp_get_ip_address(int family, char *buffer, int length) 899kvp_get_ip_info(int family, char *if_name, int op,
900 void *out_buffer, int length)
499{ 901{
500 struct ifaddrs *ifap; 902 struct ifaddrs *ifap;
501 struct ifaddrs *curp; 903 struct ifaddrs *curp;
502 int ipv4_len = strlen("255.255.255.255") + 1;
503 int ipv6_len = strlen("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")+1;
504 int offset = 0; 904 int offset = 0;
505 const char *str; 905 int sn_offset = 0;
506 char tmp[50];
507 int error = 0; 906 int error = 0;
508 907 char *buffer;
908 struct hv_kvp_ipaddr_value *ip_buffer;
909 char cidr_mask[5]; /* /xyz */
910 int weight;
911 int i;
912 unsigned int *w;
913 char *sn_str;
914 struct sockaddr_in6 *addr6;
915
916 if (op == KVP_OP_ENUMERATE) {
917 buffer = out_buffer;
918 } else {
919 ip_buffer = out_buffer;
920 buffer = (char *)ip_buffer->ip_addr;
921 ip_buffer->addr_family = 0;
922 }
509 /* 923 /*
510 * On entry into this function, the buffer is capable of holding the 924 * On entry into this function, the buffer is capable of holding the
511 * maximum key value (2048 bytes). 925 * maximum key value.
512 */ 926 */
513 927
514 if (getifaddrs(&ifap)) { 928 if (getifaddrs(&ifap)) {
515 strcpy(buffer, "getifaddrs failed\n"); 929 strcpy(buffer, "getifaddrs failed\n");
516 return 1; 930 return HV_E_FAIL;
517 } 931 }
518 932
519 curp = ifap; 933 curp = ifap;
520 while (curp != NULL) { 934 while (curp != NULL) {
521 if ((curp->ifa_addr != NULL) && 935 if (curp->ifa_addr == NULL) {
522 (curp->ifa_addr->sa_family == family)) { 936 curp = curp->ifa_next;
523 if (family == AF_INET) { 937 continue;
524 struct sockaddr_in *addr = 938 }
525 (struct sockaddr_in *) curp->ifa_addr;
526
527 str = inet_ntop(family, &addr->sin_addr,
528 tmp, 50);
529 if (str == NULL) {
530 strcpy(buffer, "inet_ntop failed\n");
531 error = 1;
532 goto getaddr_done;
533 }
534 if (offset == 0)
535 strcpy(buffer, tmp);
536 else
537 strcat(buffer, tmp);
538 strcat(buffer, ";");
539 939
540 offset += strlen(str) + 1; 940 if ((if_name != NULL) &&
541 if ((length - offset) < (ipv4_len + 1)) 941 (strncmp(curp->ifa_name, if_name, strlen(if_name)))) {
542 goto getaddr_done; 942 /*
943 * We want info about a specific interface;
944 * just continue.
945 */
946 curp = curp->ifa_next;
947 continue;
948 }
543 949
544 } else { 950 /*
951 * We only support two address families: AF_INET and AF_INET6.
952 * If a family value of 0 is specified, we collect both
953 * supported address families; if not we gather info on
954 * the specified address family.
955 */
956 if ((family != 0) && (curp->ifa_addr->sa_family != family)) {
957 curp = curp->ifa_next;
958 continue;
959 }
960 if ((curp->ifa_addr->sa_family != AF_INET) &&
961 (curp->ifa_addr->sa_family != AF_INET6)) {
962 curp = curp->ifa_next;
963 continue;
964 }
545 965
966 if (op == KVP_OP_GET_IP_INFO) {
546 /* 967 /*
547 * We only support AF_INET and AF_INET6 968 * Gather info other than the IP address.
548 * and the list of addresses is separated by a ";". 969 * IP address info will be gathered later.
549 */ 970 */
550 struct sockaddr_in6 *addr = 971 if (curp->ifa_addr->sa_family == AF_INET) {
551 (struct sockaddr_in6 *) curp->ifa_addr; 972 ip_buffer->addr_family |= ADDR_FAMILY_IPV4;
552 973 /*
553 str = inet_ntop(family, 974 * Get subnet info.
554 &addr->sin6_addr.s6_addr, 975 */
555 tmp, 50); 976 error = kvp_process_ip_address(
556 if (str == NULL) { 977 curp->ifa_netmask,
557 strcpy(buffer, "inet_ntop failed\n"); 978 AF_INET,
558 error = 1; 979 (char *)
559 goto getaddr_done; 980 ip_buffer->sub_net,
560 } 981 length,
561 if (offset == 0) 982 &sn_offset);
562 strcpy(buffer, tmp); 983 if (error)
563 else 984 goto gather_ipaddr;
564 strcat(buffer, tmp); 985 } else {
565 strcat(buffer, ";"); 986 ip_buffer->addr_family |= ADDR_FAMILY_IPV6;
566 offset += strlen(str) + 1;
567 if ((length - offset) < (ipv6_len + 1))
568 goto getaddr_done;
569 987
988 /*
989 * Get subnet info in CIDR format.
990 */
991 weight = 0;
992 sn_str = (char *)ip_buffer->sub_net;
993 addr6 = (struct sockaddr_in6 *)
994 curp->ifa_netmask;
995 w = addr6->sin6_addr.s6_addr32;
996
997 for (i = 0; i < 4; i++)
998 weight += hweight32(&w[i]);
999
1000 sprintf(cidr_mask, "/%d", weight);
1001 if ((length - sn_offset) <
1002 (strlen(cidr_mask) + 1))
1003 goto gather_ipaddr;
1004
1005 if (sn_offset == 0)
1006 strcpy(sn_str, cidr_mask);
1007 else
1008 strcat(sn_str, cidr_mask);
1009 strcat((char *)ip_buffer->sub_net, ";");
1010 sn_offset += strlen(sn_str) + 1;
570 } 1011 }
571 1012
1013 /*
1014 * Collect other ip related configuration info.
1015 */
1016
1017 kvp_get_ipconfig_info(if_name, ip_buffer);
572 } 1018 }
1019
1020gather_ipaddr:
1021 error = kvp_process_ip_address(curp->ifa_addr,
1022 curp->ifa_addr->sa_family,
1023 buffer,
1024 length, &offset);
1025 if (error)
1026 goto getaddr_done;
1027
573 curp = curp->ifa_next; 1028 curp = curp->ifa_next;
574 } 1029 }
575 1030
@@ -579,6 +1034,315 @@ getaddr_done:
579} 1034}
580 1035
581 1036
1037static int expand_ipv6(char *addr, int type)
1038{
1039 int ret;
1040 struct in6_addr v6_addr;
1041
1042 ret = inet_pton(AF_INET6, addr, &v6_addr);
1043
1044 if (ret != 1) {
1045 if (type == NETMASK)
1046 return 1;
1047 return 0;
1048 }
1049
1050 sprintf(addr, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
1051 "%02x%02x:%02x%02x:%02x%02x",
1052 (int)v6_addr.s6_addr[0], (int)v6_addr.s6_addr[1],
1053 (int)v6_addr.s6_addr[2], (int)v6_addr.s6_addr[3],
1054 (int)v6_addr.s6_addr[4], (int)v6_addr.s6_addr[5],
1055 (int)v6_addr.s6_addr[6], (int)v6_addr.s6_addr[7],
1056 (int)v6_addr.s6_addr[8], (int)v6_addr.s6_addr[9],
1057 (int)v6_addr.s6_addr[10], (int)v6_addr.s6_addr[11],
1058 (int)v6_addr.s6_addr[12], (int)v6_addr.s6_addr[13],
1059 (int)v6_addr.s6_addr[14], (int)v6_addr.s6_addr[15]);
1060
1061 return 1;
1062
1063}
1064
1065static int is_ipv4(char *addr)
1066{
1067 int ret;
1068 struct in_addr ipv4_addr;
1069
1070 ret = inet_pton(AF_INET, addr, &ipv4_addr);
1071
1072 if (ret == 1)
1073 return 1;
1074 return 0;
1075}
1076
1077static int parse_ip_val_buffer(char *in_buf, int *offset,
1078 char *out_buf, int out_len)
1079{
1080 char *x;
1081 char *start;
1082
1083 /*
1084 * in_buf has sequence of characters that are seperated by
1085 * the character ';'. The last sequence does not have the
1086 * terminating ";" character.
1087 */
1088 start = in_buf + *offset;
1089
1090 x = strchr(start, ';');
1091 if (x)
1092 *x = 0;
1093 else
1094 x = start + strlen(start);
1095
1096 if (strlen(start) != 0) {
1097 int i = 0;
1098 /*
1099 * Get rid of leading spaces.
1100 */
1101 while (start[i] == ' ')
1102 i++;
1103
1104 if ((x - start) <= out_len) {
1105 strcpy(out_buf, (start + i));
1106 *offset += (x - start) + 1;
1107 return 1;
1108 }
1109 }
1110 return 0;
1111}
1112
1113static int kvp_write_file(FILE *f, char *s1, char *s2, char *s3)
1114{
1115 int ret;
1116
1117 ret = fprintf(f, "%s%s%s%s\n", s1, s2, "=", s3);
1118
1119 if (ret < 0)
1120 return HV_E_FAIL;
1121
1122 return 0;
1123}
1124
1125
1126static int process_ip_string(FILE *f, char *ip_string, int type)
1127{
1128 int error = 0;
1129 char addr[INET6_ADDRSTRLEN];
1130 int i = 0;
1131 int j = 0;
1132 char str[256];
1133 char sub_str[10];
1134 int offset = 0;
1135
1136 memset(addr, 0, sizeof(addr));
1137
1138 while (parse_ip_val_buffer(ip_string, &offset, addr,
1139 (MAX_IP_ADDR_SIZE * 2))) {
1140
1141 sub_str[0] = 0;
1142 if (is_ipv4(addr)) {
1143 switch (type) {
1144 case IPADDR:
1145 snprintf(str, sizeof(str), "%s", "IPADDR");
1146 break;
1147 case NETMASK:
1148 snprintf(str, sizeof(str), "%s", "NETMASK");
1149 break;
1150 case GATEWAY:
1151 snprintf(str, sizeof(str), "%s", "GATEWAY");
1152 break;
1153 case DNS:
1154 snprintf(str, sizeof(str), "%s", "DNS");
1155 break;
1156 }
1157 if (i != 0) {
1158 if (type != DNS) {
1159 snprintf(sub_str, sizeof(sub_str),
1160 "_%d", i++);
1161 } else {
1162 snprintf(sub_str, sizeof(sub_str),
1163 "%d", ++i);
1164 }
1165 } else if (type == DNS) {
1166 snprintf(sub_str, sizeof(sub_str), "%d", ++i);
1167 }
1168
1169
1170 } else if (expand_ipv6(addr, type)) {
1171 switch (type) {
1172 case IPADDR:
1173 snprintf(str, sizeof(str), "%s", "IPV6ADDR");
1174 break;
1175 case NETMASK:
1176 snprintf(str, sizeof(str), "%s", "IPV6NETMASK");
1177 break;
1178 case GATEWAY:
1179 snprintf(str, sizeof(str), "%s",
1180 "IPV6_DEFAULTGW");
1181 break;
1182 case DNS:
1183 snprintf(str, sizeof(str), "%s", "DNS");
1184 break;
1185 }
1186 if ((j != 0) || (type == DNS)) {
1187 if (type != DNS) {
1188 snprintf(sub_str, sizeof(sub_str),
1189 "_%d", j++);
1190 } else {
1191 snprintf(sub_str, sizeof(sub_str),
1192 "%d", ++i);
1193 }
1194 } else if (type == DNS) {
1195 snprintf(sub_str, sizeof(sub_str),
1196 "%d", ++i);
1197 }
1198 } else {
1199 return HV_INVALIDARG;
1200 }
1201
1202 error = kvp_write_file(f, str, sub_str, addr);
1203 if (error)
1204 return error;
1205 memset(addr, 0, sizeof(addr));
1206 }
1207
1208 return 0;
1209}
1210
1211static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
1212{
1213 int error = 0;
1214 char if_file[128];
1215 FILE *file;
1216 char cmd[512];
1217 char *mac_addr;
1218
1219 /*
1220 * Set the configuration for the specified interface with
1221 * the information provided. Since there is no standard
1222 * way to configure an interface, we will have an external
1223 * script that does the job of configuring the interface and
1224 * flushing the configuration.
1225 *
1226 * The parameters passed to this external script are:
1227 * 1. A configuration file that has the specified configuration.
1228 *
1229 * We will embed the name of the interface in the configuration
1230 * file: ifcfg-ethx (where ethx is the interface name).
1231 *
1232 * The information provided here may be more than what is needed
1233 * in a given distro to configure the interface and so are free
1234 * ignore information that may not be relevant.
1235 *
1236 * Here is the format of the ip configuration file:
1237 *
1238 * HWADDR=macaddr
1239 * IF_NAME=interface name
1240 * DHCP=yes (This is optional; if yes, DHCP is configured)
1241 *
1242 * IPADDR=ipaddr1
1243 * IPADDR_1=ipaddr2
1244 * IPADDR_x=ipaddry (where y = x + 1)
1245 *
1246 * NETMASK=netmask1
1247 * NETMASK_x=netmasky (where y = x + 1)
1248 *
1249 * GATEWAY=ipaddr1
1250 * GATEWAY_x=ipaddry (where y = x + 1)
1251 *
1252 * DNSx=ipaddrx (where first DNS address is tagged as DNS1 etc)
1253 *
1254 * IPV6 addresses will be tagged as IPV6ADDR, IPV6 gateway will be
1255 * tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as
1256 * IPV6NETMASK.
1257 *
1258 * The host can specify multiple ipv4 and ipv6 addresses to be
1259 * configured for the interface. Furthermore, the configuration
1260 * needs to be persistent. A subsequent GET call on the interface
1261 * is expected to return the configuration that is set via the SET
1262 * call.
1263 */
1264
1265 snprintf(if_file, sizeof(if_file), "%s%s%s", KVP_CONFIG_LOC,
1266 "hyperv/ifcfg-", if_name);
1267
1268 file = fopen(if_file, "w");
1269
1270 if (file == NULL) {
1271 syslog(LOG_ERR, "Failed to open config file");
1272 return HV_E_FAIL;
1273 }
1274
1275 /*
1276 * First write out the MAC address.
1277 */
1278
1279 mac_addr = kvp_if_name_to_mac(if_name);
1280 if (mac_addr == NULL) {
1281 error = HV_E_FAIL;
1282 goto setval_error;
1283 }
1284
1285 error = kvp_write_file(file, "HWADDR", "", mac_addr);
1286 if (error)
1287 goto setval_error;
1288
1289 error = kvp_write_file(file, "IF_NAME", "", if_name);
1290 if (error)
1291 goto setval_error;
1292
1293 if (new_val->dhcp_enabled) {
1294 error = kvp_write_file(file, "DHCP", "", "yes");
1295 if (error)
1296 goto setval_error;
1297
1298 /*
1299 * We are done!.
1300 */
1301 goto setval_done;
1302 }
1303
1304 /*
1305 * Write the configuration for ipaddress, netmask, gateway and
1306 * name servers.
1307 */
1308
1309 error = process_ip_string(file, (char *)new_val->ip_addr, IPADDR);
1310 if (error)
1311 goto setval_error;
1312
1313 error = process_ip_string(file, (char *)new_val->sub_net, NETMASK);
1314 if (error)
1315 goto setval_error;
1316
1317 error = process_ip_string(file, (char *)new_val->gate_way, GATEWAY);
1318 if (error)
1319 goto setval_error;
1320
1321 error = process_ip_string(file, (char *)new_val->dns_addr, DNS);
1322 if (error)
1323 goto setval_error;
1324
1325setval_done:
1326 free(mac_addr);
1327 fclose(file);
1328
1329 /*
1330 * Now that we have populated the configuration file,
1331 * invoke the external script to do its magic.
1332 */
1333
1334 snprintf(cmd, sizeof(cmd), "%s %s", "hv_set_ifconfig", if_file);
1335 system(cmd);
1336 return 0;
1337
1338setval_error:
1339 syslog(LOG_ERR, "Failed to write config file");
1340 free(mac_addr);
1341 fclose(file);
1342 return error;
1343}
1344
1345
582static int 1346static int
583kvp_get_domain_name(char *buffer, int length) 1347kvp_get_domain_name(char *buffer, int length)
584{ 1348{
@@ -646,6 +1410,10 @@ int main(void)
646 char *p; 1410 char *p;
647 char *key_value; 1411 char *key_value;
648 char *key_name; 1412 char *key_name;
1413 int op;
1414 int pool;
1415 char *if_name;
1416 struct hv_kvp_ipaddr_value *kvp_ip_val;
649 1417
650 daemon(1, 0); 1418 daemon(1, 0);
651 openlog("KVP", 0, LOG_USER); 1419 openlog("KVP", 0, LOG_USER);
@@ -657,13 +1425,13 @@ int main(void)
657 1425
658 if (kvp_file_init()) { 1426 if (kvp_file_init()) {
659 syslog(LOG_ERR, "Failed to initialize the pools"); 1427 syslog(LOG_ERR, "Failed to initialize the pools");
660 exit(-1); 1428 exit(EXIT_FAILURE);
661 } 1429 }
662 1430
663 fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); 1431 fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
664 if (fd < 0) { 1432 if (fd < 0) {
665 syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); 1433 syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd);
666 exit(-1); 1434 exit(EXIT_FAILURE);
667 } 1435 }
668 addr.nl_family = AF_NETLINK; 1436 addr.nl_family = AF_NETLINK;
669 addr.nl_pad = 0; 1437 addr.nl_pad = 0;
@@ -675,7 +1443,7 @@ int main(void)
675 if (error < 0) { 1443 if (error < 0) {
676 syslog(LOG_ERR, "bind failed; error:%d", error); 1444 syslog(LOG_ERR, "bind failed; error:%d", error);
677 close(fd); 1445 close(fd);
678 exit(-1); 1446 exit(EXIT_FAILURE);
679 } 1447 }
680 sock_opt = addr.nl_groups; 1448 sock_opt = addr.nl_groups;
681 setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt)); 1449 setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt));
@@ -687,7 +1455,7 @@ int main(void)
687 message->id.val = CN_KVP_VAL; 1455 message->id.val = CN_KVP_VAL;
688 1456
689 hv_msg = (struct hv_kvp_msg *)message->data; 1457 hv_msg = (struct hv_kvp_msg *)message->data;
690 hv_msg->kvp_hdr.operation = KVP_OP_REGISTER; 1458 hv_msg->kvp_hdr.operation = KVP_OP_REGISTER1;
691 message->ack = 0; 1459 message->ack = 0;
692 message->len = sizeof(struct hv_kvp_msg); 1460 message->len = sizeof(struct hv_kvp_msg);
693 1461
@@ -695,7 +1463,7 @@ int main(void)
695 if (len < 0) { 1463 if (len < 0) {
696 syslog(LOG_ERR, "netlink_send failed; error:%d", len); 1464 syslog(LOG_ERR, "netlink_send failed; error:%d", len);
697 close(fd); 1465 close(fd);
698 exit(-1); 1466 exit(EXIT_FAILURE);
699 } 1467 }
700 1468
701 pfd.fd = fd; 1469 pfd.fd = fd;
@@ -721,12 +1489,21 @@ int main(void)
721 incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); 1489 incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
722 hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; 1490 hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
723 1491
724 switch (hv_msg->kvp_hdr.operation) { 1492 /*
725 case KVP_OP_REGISTER: 1493 * We will use the KVP header information to pass back
1494 * the error from this daemon. So, first copy the state
1495 * and set the error code to success.
1496 */
1497 op = hv_msg->kvp_hdr.operation;
1498 pool = hv_msg->kvp_hdr.pool;
1499 hv_msg->error = HV_S_OK;
1500
1501 if ((in_hand_shake) && (op == KVP_OP_REGISTER1)) {
726 /* 1502 /*
727 * Driver is registering with us; stash away the version 1503 * Driver is registering with us; stash away the version
728 * information. 1504 * information.
729 */ 1505 */
1506 in_hand_shake = 0;
730 p = (char *)hv_msg->body.kvp_register.version; 1507 p = (char *)hv_msg->body.kvp_register.version;
731 lic_version = malloc(strlen(p) + 1); 1508 lic_version = malloc(strlen(p) + 1);
732 if (lic_version) { 1509 if (lic_version) {
@@ -737,44 +1514,82 @@ int main(void)
737 syslog(LOG_ERR, "malloc failed"); 1514 syslog(LOG_ERR, "malloc failed");
738 } 1515 }
739 continue; 1516 continue;
1517 }
740 1518
741 /* 1519 switch (op) {
742 * The current protocol with the kernel component uses a 1520 case KVP_OP_GET_IP_INFO:
743 * NULL key name to pass an error condition. 1521 kvp_ip_val = &hv_msg->body.kvp_ip_val;
744 * For the SET, GET and DELETE operations, 1522 if_name =
745 * use the existing protocol to pass back error. 1523 kvp_mac_to_if_name((char *)kvp_ip_val->adapter_id);
746 */ 1524
1525 if (if_name == NULL) {
1526 /*
1527 * We could not map the mac address to an
1528 * interface name; return error.
1529 */
1530 hv_msg->error = HV_E_FAIL;
1531 break;
1532 }
1533 error = kvp_get_ip_info(
1534 0, if_name, KVP_OP_GET_IP_INFO,
1535 kvp_ip_val,
1536 (MAX_IP_ADDR_SIZE * 2));
1537
1538 if (error)
1539 hv_msg->error = error;
1540
1541 free(if_name);
1542 break;
1543
1544 case KVP_OP_SET_IP_INFO:
1545 kvp_ip_val = &hv_msg->body.kvp_ip_val;
1546 if_name = kvp_get_if_name(
1547 (char *)kvp_ip_val->adapter_id);
1548 if (if_name == NULL) {
1549 /*
1550 * We could not map the guid to an
1551 * interface name; return error.
1552 */
1553 hv_msg->error = HV_GUID_NOTFOUND;
1554 break;
1555 }
1556 error = kvp_set_ip_info(if_name, kvp_ip_val);
1557 if (error)
1558 hv_msg->error = error;
1559
1560 free(if_name);
1561 break;
747 1562
748 case KVP_OP_SET: 1563 case KVP_OP_SET:
749 if (kvp_key_add_or_modify(hv_msg->kvp_hdr.pool, 1564 if (kvp_key_add_or_modify(pool,
750 hv_msg->body.kvp_set.data.key, 1565 hv_msg->body.kvp_set.data.key,
751 hv_msg->body.kvp_set.data.key_size, 1566 hv_msg->body.kvp_set.data.key_size,
752 hv_msg->body.kvp_set.data.value, 1567 hv_msg->body.kvp_set.data.value,
753 hv_msg->body.kvp_set.data.value_size)) 1568 hv_msg->body.kvp_set.data.value_size))
754 strcpy(hv_msg->body.kvp_set.data.key, ""); 1569 hv_msg->error = HV_S_CONT;
755 break; 1570 break;
756 1571
757 case KVP_OP_GET: 1572 case KVP_OP_GET:
758 if (kvp_get_value(hv_msg->kvp_hdr.pool, 1573 if (kvp_get_value(pool,
759 hv_msg->body.kvp_set.data.key, 1574 hv_msg->body.kvp_set.data.key,
760 hv_msg->body.kvp_set.data.key_size, 1575 hv_msg->body.kvp_set.data.key_size,
761 hv_msg->body.kvp_set.data.value, 1576 hv_msg->body.kvp_set.data.value,
762 hv_msg->body.kvp_set.data.value_size)) 1577 hv_msg->body.kvp_set.data.value_size))
763 strcpy(hv_msg->body.kvp_set.data.key, ""); 1578 hv_msg->error = HV_S_CONT;
764 break; 1579 break;
765 1580
766 case KVP_OP_DELETE: 1581 case KVP_OP_DELETE:
767 if (kvp_key_delete(hv_msg->kvp_hdr.pool, 1582 if (kvp_key_delete(pool,
768 hv_msg->body.kvp_delete.key, 1583 hv_msg->body.kvp_delete.key,
769 hv_msg->body.kvp_delete.key_size)) 1584 hv_msg->body.kvp_delete.key_size))
770 strcpy(hv_msg->body.kvp_delete.key, ""); 1585 hv_msg->error = HV_S_CONT;
771 break; 1586 break;
772 1587
773 default: 1588 default:
774 break; 1589 break;
775 } 1590 }
776 1591
777 if (hv_msg->kvp_hdr.operation != KVP_OP_ENUMERATE) 1592 if (op != KVP_OP_ENUMERATE)
778 goto kvp_done; 1593 goto kvp_done;
779 1594
780 /* 1595 /*
@@ -782,13 +1597,14 @@ int main(void)
782 * both the key and the value; if not read from the 1597 * both the key and the value; if not read from the
783 * appropriate pool. 1598 * appropriate pool.
784 */ 1599 */
785 if (hv_msg->kvp_hdr.pool != KVP_POOL_AUTO) { 1600 if (pool != KVP_POOL_AUTO) {
786 kvp_pool_enumerate(hv_msg->kvp_hdr.pool, 1601 if (kvp_pool_enumerate(pool,
787 hv_msg->body.kvp_enum_data.index, 1602 hv_msg->body.kvp_enum_data.index,
788 hv_msg->body.kvp_enum_data.data.key, 1603 hv_msg->body.kvp_enum_data.data.key,
789 HV_KVP_EXCHANGE_MAX_KEY_SIZE, 1604 HV_KVP_EXCHANGE_MAX_KEY_SIZE,
790 hv_msg->body.kvp_enum_data.data.value, 1605 hv_msg->body.kvp_enum_data.data.value,
791 HV_KVP_EXCHANGE_MAX_VALUE_SIZE); 1606 HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
1607 hv_msg->error = HV_S_CONT;
792 goto kvp_done; 1608 goto kvp_done;
793 } 1609 }
794 1610
@@ -807,13 +1623,13 @@ int main(void)
807 strcpy(key_value, lic_version); 1623 strcpy(key_value, lic_version);
808 break; 1624 break;
809 case NetworkAddressIPv4: 1625 case NetworkAddressIPv4:
810 kvp_get_ip_address(AF_INET, key_value, 1626 kvp_get_ip_info(AF_INET, NULL, KVP_OP_ENUMERATE,
811 HV_KVP_EXCHANGE_MAX_VALUE_SIZE); 1627 key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
812 strcpy(key_name, "NetworkAddressIPv4"); 1628 strcpy(key_name, "NetworkAddressIPv4");
813 break; 1629 break;
814 case NetworkAddressIPv6: 1630 case NetworkAddressIPv6:
815 kvp_get_ip_address(AF_INET6, key_value, 1631 kvp_get_ip_info(AF_INET6, NULL, KVP_OP_ENUMERATE,
816 HV_KVP_EXCHANGE_MAX_VALUE_SIZE); 1632 key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
817 strcpy(key_name, "NetworkAddressIPv6"); 1633 strcpy(key_name, "NetworkAddressIPv6");
818 break; 1634 break;
819 case OSBuildNumber: 1635 case OSBuildNumber:
@@ -841,11 +1657,7 @@ int main(void)
841 strcpy(key_name, "ProcessorArchitecture"); 1657 strcpy(key_name, "ProcessorArchitecture");
842 break; 1658 break;
843 default: 1659 default:
844 strcpy(key_value, "Unknown Key"); 1660 hv_msg->error = HV_S_CONT;
845 /*
846 * We use a null key name to terminate enumeration.
847 */
848 strcpy(key_name, "");
849 break; 1661 break;
850 } 1662 }
851 /* 1663 /*
@@ -863,7 +1675,7 @@ kvp_done:
863 len = netlink_send(fd, incoming_cn_msg); 1675 len = netlink_send(fd, incoming_cn_msg);
864 if (len < 0) { 1676 if (len < 0) {
865 syslog(LOG_ERR, "net_link send failed; error:%d", len); 1677 syslog(LOG_ERR, "net_link send failed; error:%d", len);
866 exit(-1); 1678 exit(EXIT_FAILURE);
867 } 1679 }
868 } 1680 }
869 1681
diff --git a/tools/hv/hv_set_ifconfig.sh b/tools/hv/hv_set_ifconfig.sh
new file mode 100755
index 00000000000..3e9427e08d8
--- /dev/null
+++ b/tools/hv/hv_set_ifconfig.sh
@@ -0,0 +1,68 @@
1#!/bin/bash
2
3# This example script activates an interface based on the specified
4# configuration.
5#
6# In the interest of keeping the KVP daemon code free of distro specific
7# information; the kvp daemon code invokes this external script to configure
8# the interface.
9#
10# The only argument to this script is the configuration file that is to
11# be used to configure the interface.
12#
13# Each Distro is expected to implement this script in a distro specific
14# fashion. For instance on Distros that ship with Network Manager enabled,
15# this script can be based on the Network Manager APIs for configuring the
16# interface.
17#
18# This example script is based on a RHEL environment.
19#
20# Here is the format of the ip configuration file:
21#
22# HWADDR=macaddr
23# IF_NAME=interface name
24# DHCP=yes (This is optional; if yes, DHCP is configured)
25#
26# IPADDR=ipaddr1
27# IPADDR_1=ipaddr2
28# IPADDR_x=ipaddry (where y = x + 1)
29#
30# NETMASK=netmask1
31# NETMASK_x=netmasky (where y = x + 1)
32#
33# GATEWAY=ipaddr1
34# GATEWAY_x=ipaddry (where y = x + 1)
35#
36# DNSx=ipaddrx (where first DNS address is tagged as DNS1 etc)
37#
38# IPV6 addresses will be tagged as IPV6ADDR, IPV6 gateway will be
39# tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as
40# IPV6NETMASK.
41#
42# The host can specify multiple ipv4 and ipv6 addresses to be
43# configured for the interface. Furthermore, the configuration
44# needs to be persistent. A subsequent GET call on the interface
45# is expected to return the configuration that is set via the SET
46# call.
47#
48
49
50
51echo "IPV6INIT=yes" >> $1
52echo "NM_CONTROLLED=no" >> $1
53echo "PEERDNS=yes" >> $1
54echo "ONBOOT=yes" >> $1
55
56dhcp=$(grep "DHCP" $1 2>/dev/null)
57if [ "$dhcp" != "" ];
58then
59echo "BOOTPROTO=dhcp" >> $1;
60fi
61
62cp $1 /etc/sysconfig/network-scripts/
63
64
65interface=$(echo $1 | awk -F - '{ print $2 }')
66
67/sbin/ifdown $interface 2>/dev/null
68/sbin/ifup $interfac 2>/dev/null
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c
index f759f4f097c..fd2f9221b24 100644
--- a/tools/lguest/lguest.c
+++ b/tools/lguest/lguest.c
@@ -1299,6 +1299,7 @@ static struct device *new_device(const char *name, u16 type)
1299 dev->feature_len = 0; 1299 dev->feature_len = 0;
1300 dev->num_vq = 0; 1300 dev->num_vq = 0;
1301 dev->running = false; 1301 dev->running = false;
1302 dev->next = NULL;
1302 1303
1303 /* 1304 /*
1304 * Append to device list. Prepending to a single-linked list is 1305 * Append to device list. Prepending to a single-linked list is
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 47264b4652b..f2989c525e4 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -2602,6 +2602,9 @@ find_func_handler(struct pevent *pevent, char *func_name)
2602{ 2602{
2603 struct pevent_function_handler *func; 2603 struct pevent_function_handler *func;
2604 2604
2605 if (!pevent)
2606 return NULL;
2607
2605 for (func = pevent->func_handlers; func; func = func->next) { 2608 for (func = pevent->func_handlers; func; func = func->next) {
2606 if (strcmp(func->name, func_name) == 0) 2609 if (strcmp(func->name, func_name) == 0)
2607 break; 2610 break;
@@ -4938,6 +4941,9 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
4938 goto event_alloc_failed; 4941 goto event_alloc_failed;
4939 } 4942 }
4940 4943
4944 /* Add pevent to event so that it can be referenced */
4945 event->pevent = pevent;
4946
4941 ret = event_read_format(event); 4947 ret = event_read_format(event);
4942 if (ret < 0) { 4948 if (ret < 0) {
4943 ret = PEVENT_ERRNO__READ_FORMAT_FAILED; 4949 ret = PEVENT_ERRNO__READ_FORMAT_FAILED;
@@ -5041,9 +5047,6 @@ enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
5041 if (event == NULL) 5047 if (event == NULL)
5042 return ret; 5048 return ret;
5043 5049
5044 /* Add pevent to event so that it can be referenced */
5045 event->pevent = pevent;
5046
5047 if (add_event(pevent, event)) { 5050 if (add_event(pevent, event)) {
5048 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; 5051 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5049 goto event_add_failed; 5052 goto event_add_failed;
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index ad17855528f..5ea4326ad11 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -209,7 +209,16 @@ static void free_arg(struct filter_arg *arg)
209 switch (arg->type) { 209 switch (arg->type) {
210 case FILTER_ARG_NONE: 210 case FILTER_ARG_NONE:
211 case FILTER_ARG_BOOLEAN: 211 case FILTER_ARG_BOOLEAN:
212 break;
213
212 case FILTER_ARG_NUM: 214 case FILTER_ARG_NUM:
215 free_arg(arg->num.left);
216 free_arg(arg->num.right);
217 break;
218
219 case FILTER_ARG_EXP:
220 free_arg(arg->exp.left);
221 free_arg(arg->exp.right);
213 break; 222 break;
214 223
215 case FILTER_ARG_STR: 224 case FILTER_ARG_STR:
@@ -218,6 +227,12 @@ static void free_arg(struct filter_arg *arg)
218 free(arg->str.buffer); 227 free(arg->str.buffer);
219 break; 228 break;
220 229
230 case FILTER_ARG_VALUE:
231 if (arg->value.type == FILTER_STRING ||
232 arg->value.type == FILTER_CHAR)
233 free(arg->value.str);
234 break;
235
221 case FILTER_ARG_OP: 236 case FILTER_ARG_OP:
222 free_arg(arg->op.left); 237 free_arg(arg->op.left);
223 free_arg(arg->op.right); 238 free_arg(arg->op.right);
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 318bec8e14e..f530502630a 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -74,7 +74,7 @@ ifeq ($(ARCH),x86_64)
74 override ARCH := x86 74 override ARCH := x86
75 IS_X86_64 := 0 75 IS_X86_64 := 0
76 ifeq (, $(findstring m32,$(EXTRA_CFLAGS))) 76 ifeq (, $(findstring m32,$(EXTRA_CFLAGS)))
77 IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) 77 IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1)
78 endif 78 endif
79 ifeq (${IS_X86_64}, 1) 79 ifeq (${IS_X86_64}, 1)
80 RAW_ARCH := x86_64 80 RAW_ARCH := x86_64
@@ -191,9 +191,22 @@ SCRIPT_SH += perf-archive.sh
191grep-libs = $(filter -l%,$(1)) 191grep-libs = $(filter -l%,$(1))
192strip-libs = $(filter-out -l%,$(1)) 192strip-libs = $(filter-out -l%,$(1))
193 193
194TRACE_EVENT_DIR = ../lib/traceevent/
195
196ifneq ($(OUTPUT),)
197 TE_PATH=$(OUTPUT)
198else
199 TE_PATH=$(TRACE_EVENT_DIR)
200endif
201
202LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
203TE_LIB := -L$(TE_PATH) -ltraceevent
204
194PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 205PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
195PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py 206PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py
196 207
208export LIBTRACEEVENT
209
197$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) 210$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
198 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ 211 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
199 --quiet build_ext; \ 212 --quiet build_ext; \
@@ -205,17 +218,6 @@ $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
205 218
206SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) 219SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
207 220
208TRACE_EVENT_DIR = ../lib/traceevent/
209
210ifneq ($(OUTPUT),)
211 TE_PATH=$(OUTPUT)
212else
213 TE_PATH=$(TRACE_EVENT_DIR)
214endif
215
216LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
217TE_LIB := -L$(TE_PATH) -ltraceevent
218
219# 221#
220# Single 'perf' binary right now: 222# Single 'perf' binary right now:
221# 223#
@@ -259,10 +261,10 @@ $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
259 261
260LIB_FILE=$(OUTPUT)libperf.a 262LIB_FILE=$(OUTPUT)libperf.a
261 263
262LIB_H += ../../include/linux/perf_event.h 264LIB_H += ../../include/uapi/linux/perf_event.h
263LIB_H += ../../include/linux/rbtree.h 265LIB_H += ../../include/linux/rbtree.h
264LIB_H += ../../include/linux/list.h 266LIB_H += ../../include/linux/list.h
265LIB_H += ../../include/linux/const.h 267LIB_H += ../../include/uapi/linux/const.h
266LIB_H += ../../include/linux/hash.h 268LIB_H += ../../include/linux/hash.h
267LIB_H += ../../include/linux/stringify.h 269LIB_H += ../../include/linux/stringify.h
268LIB_H += util/include/linux/bitmap.h 270LIB_H += util/include/linux/bitmap.h
@@ -277,6 +279,7 @@ LIB_H += util/include/linux/magic.h
277LIB_H += util/include/linux/poison.h 279LIB_H += util/include/linux/poison.h
278LIB_H += util/include/linux/prefetch.h 280LIB_H += util/include/linux/prefetch.h
279LIB_H += util/include/linux/rbtree.h 281LIB_H += util/include/linux/rbtree.h
282LIB_H += util/include/linux/rbtree_augmented.h
280LIB_H += util/include/linux/string.h 283LIB_H += util/include/linux/string.h
281LIB_H += util/include/linux/types.h 284LIB_H += util/include/linux/types.h
282LIB_H += util/include/linux/linkage.h 285LIB_H += util/include/linux/linkage.h
@@ -902,7 +905,7 @@ $(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
902 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 905 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
903 906
904$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 907$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
905 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 908 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
906 909
907$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS 910$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
908 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-redundant-decls $< 911 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-redundant-decls $<
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 411ee5664e9..178b88ae3d2 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -414,7 +414,7 @@ static int show_html_page(const char *perf_cmd)
414int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused) 414int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
415{ 415{
416 bool show_all = false; 416 bool show_all = false;
417 enum help_format help_format = HELP_FORMAT_NONE; 417 enum help_format help_format = HELP_FORMAT_MAN;
418 struct option builtin_help_options[] = { 418 struct option builtin_help_options[] = {
419 OPT_BOOLEAN('a', "all", &show_all, "print all available commands"), 419 OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
420 OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN), 420 OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 4e9320bf11e..14b32296180 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -63,6 +63,10 @@ static int trace__read_syscall_info(struct trace *trace, int id)
63{ 63{
64 char tp_name[128]; 64 char tp_name[128];
65 struct syscall *sc; 65 struct syscall *sc;
66 const char *name = audit_syscall_to_name(id, trace->audit_machine);
67
68 if (name == NULL)
69 return -1;
66 70
67 if (id > trace->syscalls.max) { 71 if (id > trace->syscalls.max) {
68 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc)); 72 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
@@ -82,11 +86,8 @@ static int trace__read_syscall_info(struct trace *trace, int id)
82 } 86 }
83 87
84 sc = trace->syscalls.table + id; 88 sc = trace->syscalls.table + id;
85 sc->name = audit_syscall_to_name(id, trace->audit_machine); 89 sc->name = name;
86 if (sc->name == NULL) 90 sc->fmt = syscall_fmt__find(sc->name);
87 return -1;
88
89 sc->fmt = syscall_fmt__find(sc->name);
90 91
91 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); 92 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
92 sc->tp_format = event_format__new("syscalls", tp_name); 93 sc->tp_format = event_format__new("syscalls", tp_name);
@@ -290,6 +291,13 @@ again:
290 if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1) 291 if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
291 printf("%d ", sample.tid); 292 printf("%d ", sample.tid);
292 293
294 if (sample.raw_data == NULL) {
295 printf("%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
296 perf_evsel__name(evsel), sample.tid,
297 sample.cpu, sample.raw_size);
298 continue;
299 }
300
293 handler = evsel->handler.func; 301 handler = evsel->handler.func;
294 handler(trace, evsel, &sample); 302 handler(trace, evsel, &sample);
295 } 303 }
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 87f4ec6d1f3..c50985eaec4 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -57,7 +57,7 @@ void get_term_dimensions(struct winsize *ws);
57#endif 57#endif
58 58
59#ifdef __sparc__ 59#ifdef __sparc__
60#include "../../arch/sparc/include/asm/unistd.h" 60#include "../../arch/sparc/include/uapi/asm/unistd.h"
61#define rmb() asm volatile("":::"memory") 61#define rmb() asm volatile("":::"memory")
62#define cpu_relax() asm volatile("":::"memory") 62#define cpu_relax() asm volatile("":::"memory")
63#define CPUINFO_PROC "cpu" 63#define CPUINFO_PROC "cpu"
@@ -88,6 +88,12 @@ void get_term_dimensions(struct winsize *ws);
88#define CPUINFO_PROC "Processor" 88#define CPUINFO_PROC "Processor"
89#endif 89#endif
90 90
91#ifdef __aarch64__
92#include "../../arch/arm64/include/asm/unistd.h"
93#define rmb() asm volatile("dmb ld" ::: "memory")
94#define cpu_relax() asm volatile("yield" ::: "memory")
95#endif
96
91#ifdef __mips__ 97#ifdef __mips__
92#include "../../arch/mips/include/asm/unistd.h" 98#include "../../arch/mips/include/asm/unistd.h"
93#define rmb() asm volatile( \ 99#define rmb() asm volatile( \
@@ -106,7 +112,7 @@ void get_term_dimensions(struct winsize *ws);
106#include <sys/types.h> 112#include <sys/types.h>
107#include <sys/syscall.h> 113#include <sys/syscall.h>
108 114
109#include "../../include/linux/perf_event.h" 115#include "../../include/uapi/linux/perf_event.h"
110#include "util/types.h" 116#include "util/types.h"
111#include <stdbool.h> 117#include <stdbool.h>
112 118
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 0568536ecf6..ef2f93ca749 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -610,6 +610,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
610 char folded_sign = ' '; 610 char folded_sign = ' ';
611 bool current_entry = ui_browser__is_current_entry(&browser->b, row); 611 bool current_entry = ui_browser__is_current_entry(&browser->b, row);
612 off_t row_offset = entry->row_offset; 612 off_t row_offset = entry->row_offset;
613 bool first = true;
613 614
614 if (current_entry) { 615 if (current_entry) {
615 browser->he_selection = entry; 616 browser->he_selection = entry;
@@ -633,10 +634,11 @@ static int hist_browser__show_entry(struct hist_browser *browser,
633 if (!perf_hpp__format[i].cond) 634 if (!perf_hpp__format[i].cond)
634 continue; 635 continue;
635 636
636 if (i) { 637 if (!first) {
637 slsmg_printf(" "); 638 slsmg_printf(" ");
638 width -= 2; 639 width -= 2;
639 } 640 }
641 first = false;
640 642
641 if (perf_hpp__format[i].color) { 643 if (perf_hpp__format[i].color) {
642 hpp.ptr = &percent; 644 hpp.ptr = &percent;
@@ -645,7 +647,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
645 647
646 ui_browser__set_percent_color(&browser->b, percent, current_entry); 648 ui_browser__set_percent_color(&browser->b, percent, current_entry);
647 649
648 if (i == 0 && symbol_conf.use_callchain) { 650 if (i == PERF_HPP__OVERHEAD && symbol_conf.use_callchain) {
649 slsmg_printf("%c ", folded_sign); 651 slsmg_printf("%c ", folded_sign);
650 width -= 2; 652 width -= 2;
651 } 653 }
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 3bdb407f9cd..eb340571e7d 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -58,7 +58,7 @@ struct callchain_list {
58/* 58/*
59 * A callchain cursor is a single linked list that 59 * A callchain cursor is a single linked list that
60 * let one feed a callchain progressively. 60 * let one feed a callchain progressively.
61 * It keeps persitent allocated entries to minimize 61 * It keeps persistent allocated entries to minimize
62 * allocations. 62 * allocations.
63 */ 63 */
64struct callchain_cursor_node { 64struct callchain_cursor_node {
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ffdd94e9c9c..618d41140ab 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -19,7 +19,7 @@
19#include "thread_map.h" 19#include "thread_map.h"
20#include "target.h" 20#include "target.h"
21#include "../../../include/linux/hw_breakpoint.h" 21#include "../../../include/linux/hw_breakpoint.h"
22#include "../../include/linux/perf_event.h" 22#include "../../../include/uapi/linux/perf_event.h"
23#include "perf_regs.h" 23#include "perf_regs.h"
24 24
25#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 25#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 3ead0d59c03..6f94d6dea00 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -3,7 +3,7 @@
3 3
4#include <linux/list.h> 4#include <linux/list.h>
5#include <stdbool.h> 5#include <stdbool.h>
6#include "../../../include/linux/perf_event.h" 6#include "../../../include/uapi/linux/perf_event.h"
7#include "types.h" 7#include "types.h"
8#include "xyarray.h" 8#include "xyarray.h"
9#include "cgroup.h" 9#include "cgroup.h"
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 99bdd3abce5..879d215cdac 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -1,7 +1,7 @@
1#ifndef __PERF_HEADER_H 1#ifndef __PERF_HEADER_H
2#define __PERF_HEADER_H 2#define __PERF_HEADER_H
3 3
4#include "../../../include/linux/perf_event.h" 4#include "../../../include/uapi/linux/perf_event.h"
5#include <sys/types.h> 5#include <sys/types.h>
6#include <stdbool.h> 6#include <stdbool.h>
7#include "types.h" 7#include "types.h"
diff --git a/tools/perf/util/include/asm/byteorder.h b/tools/perf/util/include/asm/byteorder.h
index b722abe3a62..2a9bdc06630 100644
--- a/tools/perf/util/include/asm/byteorder.h
+++ b/tools/perf/util/include/asm/byteorder.h
@@ -1,2 +1,2 @@
1#include <asm/types.h> 1#include <asm/types.h>
2#include "../../../../include/linux/swab.h" 2#include "../../../../include/uapi/linux/swab.h"
diff --git a/tools/perf/util/include/linux/const.h b/tools/perf/util/include/linux/const.h
index 1b476c9ae64..c10a35e1afb 100644
--- a/tools/perf/util/include/linux/const.h
+++ b/tools/perf/util/include/linux/const.h
@@ -1 +1 @@
#include "../../../../include/linux/const.h" #include "../../../../include/uapi/linux/const.h"
diff --git a/tools/perf/util/include/linux/rbtree_augmented.h b/tools/perf/util/include/linux/rbtree_augmented.h
new file mode 100644
index 00000000000..9d6fcdf1788
--- /dev/null
+++ b/tools/perf/util/include/linux/rbtree_augmented.h
@@ -0,0 +1,2 @@
1#include <stdbool.h>
2#include "../../../../include/linux/rbtree_augmented.h"
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index d7244e55367..516ecd9ddd6 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -513,7 +513,8 @@ static int test__group1(struct perf_evlist *evlist)
513 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); 513 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
514 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 514 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
515 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 515 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
516 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); 516 /* use of precise requires exclude_guest */
517 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
517 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 518 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
518 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); 519 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
519 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 520 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
@@ -599,7 +600,8 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
599 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); 600 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
600 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); 601 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
601 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 602 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
602 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); 603 /* use of precise requires exclude_guest */
604 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
603 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 605 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
604 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3); 606 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3);
605 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 607 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
@@ -662,7 +664,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
662 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); 664 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
663 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 665 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
664 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 666 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
665 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); 667 /* use of precise requires exclude_guest */
668 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
666 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 669 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
667 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1); 670 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);
668 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 671 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
@@ -676,7 +679,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
676 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); 679 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
677 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); 680 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
678 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 681 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
679 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); 682 /* use of precise requires exclude_guest */
683 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
680 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 684 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
681 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); 685 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
682 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 686 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
@@ -1016,7 +1020,7 @@ static int test_pmu(void)
1016 1020
1017 ret = stat(path, &st); 1021 ret = stat(path, &st);
1018 if (ret) 1022 if (ret)
1019 pr_debug("ommiting PMU cpu tests\n"); 1023 pr_debug("omitting PMU cpu tests\n");
1020 return !ret; 1024 return !ret;
1021} 1025}
1022 1026
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index aed38e4b9df..75c7b0fca6d 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -690,6 +690,9 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
690 eH = 0; 690 eH = 0;
691 } else if (*str == 'p') { 691 } else if (*str == 'p') {
692 precise++; 692 precise++;
693 /* use of precise requires exclude_guest */
694 if (!exclude_GH)
695 eG = 1;
693 } else 696 } else
694 break; 697 break;
695 698
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index c356e443448..839230ceb18 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -7,7 +7,7 @@
7#include <linux/list.h> 7#include <linux/list.h>
8#include <stdbool.h> 8#include <stdbool.h>
9#include "types.h" 9#include "types.h"
10#include "../../../include/linux/perf_event.h" 10#include "../../../include/uapi/linux/perf_event.h"
11#include "types.h" 11#include "types.h"
12 12
13struct list_head; 13struct list_head;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 53c7794fc4b..39f3abac774 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -2,7 +2,7 @@
2#define __PMU_H 2#define __PMU_H
3 3
4#include <linux/bitops.h> 4#include <linux/bitops.h>
5#include "../../../include/linux/perf_event.h" 5#include "../../../include/uapi/linux/perf_event.h"
6 6
7enum { 7enum {
8 PERF_PMU_FORMAT_VALUE_CONFIG, 8 PERF_PMU_FORMAT_VALUE_CONFIG,
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 213362850ab..c40c2d33199 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -1,5 +1,5 @@
1# 1#
2# List of files needed by perf python extention 2# List of files needed by perf python extension
3# 3#
4# Each source file must be placed on its own line so that it can be 4# Each source file must be placed on its own line so that it can be
5# processed by Makefile and util/setup.py accordingly. 5# processed by Makefile and util/setup.py accordingly.
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index aab414fbb64..dd6426163ba 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -7,7 +7,7 @@
7#include "symbol.h" 7#include "symbol.h"
8#include "thread.h" 8#include "thread.h"
9#include <linux/rbtree.h> 9#include <linux/rbtree.h>
10#include "../../../include/linux/perf_event.h" 10#include "../../../include/uapi/linux/perf_event.h"
11 11
12struct sample_queue; 12struct sample_queue;
13struct ip_callchain; 13struct ip_callchain;
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index d0f9f29cf18..73d51026978 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -23,6 +23,7 @@ cflags += getenv('CFLAGS', '').split()
23 23
24build_lib = getenv('PYTHON_EXTBUILD_LIB') 24build_lib = getenv('PYTHON_EXTBUILD_LIB')
25build_tmp = getenv('PYTHON_EXTBUILD_TMP') 25build_tmp = getenv('PYTHON_EXTBUILD_TMP')
26libtraceevent = getenv('LIBTRACEEVENT')
26 27
27ext_sources = [f.strip() for f in file('util/python-ext-sources') 28ext_sources = [f.strip() for f in file('util/python-ext-sources')
28 if len(f.strip()) > 0 and f[0] != '#'] 29 if len(f.strip()) > 0 and f[0] != '#']
@@ -31,6 +32,7 @@ perf = Extension('perf',
31 sources = ext_sources, 32 sources = ext_sources,
32 include_dirs = ['util/include'], 33 include_dirs = ['util/include'],
33 extra_compile_args = cflags, 34 extra_compile_args = cflags,
35 extra_objects = [libtraceevent],
34 ) 36 )
35 37
36setup(name='perf', 38setup(name='perf',
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index b5b1b921196..cfd1c0feb32 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -260,6 +260,12 @@ static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
260 if (path != NULL) 260 if (path != NULL)
261 goto out_path; 261 goto out_path;
262 262
263 if (!self->ms.map)
264 goto out_ip;
265
266 if (!strncmp(self->ms.map->dso->long_name, "/tmp/perf-", 10))
267 goto out_ip;
268
263 snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64, 269 snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
264 self->ms.map->dso->long_name, self->ip); 270 self->ms.map->dso->long_name, self->ip);
265 fp = popen(cmd, "r"); 271 fp = popen(cmd, "r");
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index fe3bb1ec188..df59623ac76 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -39,7 +39,6 @@ int thread__set_comm(struct thread *self, const char *comm)
39 err = self->comm == NULL ? -ENOMEM : 0; 39 err = self->comm == NULL ? -ENOMEM : 0;
40 if (!err) { 40 if (!err) {
41 self->comm_set = true; 41 self->comm_set = true;
42 map_groups__flush(&self->mg);
43 } 42 }
44 return err; 43 return err;
45} 44}
diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile
new file mode 100644
index 00000000000..6b9cf7a987c
--- /dev/null
+++ b/tools/power/acpi/Makefile
@@ -0,0 +1,18 @@
1PROG= acpidump
2SRCS= acpidump.c
3KERNEL_INCLUDE := ../../../include
4CFLAGS += -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Os -s -D_LINUX -DDEFINE_ALTERNATE_TYPES -I$(KERNEL_INCLUDE)
5
6all: acpidump
7$(PROG) : $(SRCS)
8 $(CC) $(CFLAGS) $(SRCS) -o $(PROG)
9
10CLEANFILES= $(PROG)
11
12clean :
13 rm -f $(CLEANFILES) $(patsubst %.c,%.o, $(SRCS)) *~
14
15install :
16 install acpidump /usr/bin/acpidump
17 install acpidump.8 /usr/share/man/man8
18
diff --git a/tools/power/acpi/acpidump.8 b/tools/power/acpi/acpidump.8
new file mode 100644
index 00000000000..adfa99166e5
--- /dev/null
+++ b/tools/power/acpi/acpidump.8
@@ -0,0 +1,59 @@
1.TH ACPIDUMP 8
2.SH NAME
3acpidump \- Dump system's ACPI tables to an ASCII file.
4.SH SYNOPSIS
5.ft B
6.B acpidump > acpidump.out
7.SH DESCRIPTION
8\fBacpidump \fP dumps the systems ACPI tables to an ASCII file
9appropriate for attaching to a bug report.
10
11Subsequently, they can be processed by utilities in the ACPICA package.
12.SS Options
13no options worth worrying about.
14.PP
15.SH EXAMPLE
16
17.nf
18# acpidump > acpidump.out
19
20$ acpixtract -a acpidump.out
21 Acpi table [DSDT] - 15974 bytes written to DSDT.dat
22 Acpi table [FACS] - 64 bytes written to FACS.dat
23 Acpi table [FACP] - 116 bytes written to FACP.dat
24 Acpi table [APIC] - 120 bytes written to APIC.dat
25 Acpi table [MCFG] - 60 bytes written to MCFG.dat
26 Acpi table [SSDT] - 444 bytes written to SSDT1.dat
27 Acpi table [SSDT] - 439 bytes written to SSDT2.dat
28 Acpi table [SSDT] - 439 bytes written to SSDT3.dat
29 Acpi table [SSDT] - 439 bytes written to SSDT4.dat
30 Acpi table [SSDT] - 439 bytes written to SSDT5.dat
31 Acpi table [RSDT] - 76 bytes written to RSDT.dat
32 Acpi table [RSDP] - 20 bytes written to RSDP.dat
33
34$ iasl -d *.dat
35...
36.fi
37creates *.dsl, a human readable form which can be edited
38and compiled using iasl.
39
40
41.SH NOTES
42
43.B "acpidump "
44must be run as root.
45
46.SH REFERENCES
47ACPICA: https://acpica.org/
48
49.SH FILES
50.ta
51.nf
52/dev/mem
53/sys/firmware/acpi/tables/dynamic/*
54.fi
55
56.PP
57.SH AUTHOR
58.nf
59Written by Len Brown <len.brown@intel.com>
diff --git a/tools/power/acpi/acpidump.c b/tools/power/acpi/acpidump.c
new file mode 100644
index 00000000000..a84553a0e0d
--- /dev/null
+++ b/tools/power/acpi/acpidump.c
@@ -0,0 +1,559 @@
1/*
2 * (c) Alexey Starikovskiy, Intel, 2005-2006.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions, and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * substantially similar to the "NO WARRANTY" disclaimer below
13 * ("Disclaimer") and any redistribution must be conditioned upon
14 * including a substantially similar Disclaimer requirement for further
15 * binary redistribution.
16 * 3. Neither the names of the above-listed copyright holders nor the names
17 * of any contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * NO WARRANTY
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
34 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGES.
36 */
37
38#ifdef DEFINE_ALTERNATE_TYPES
39/* hack to enable building old application with new headers -lenb */
40#define acpi_fadt_descriptor acpi_table_fadt
41#define acpi_rsdp_descriptor acpi_table_rsdp
42#define DSDT_SIG ACPI_SIG_DSDT
43#define FACS_SIG ACPI_SIG_FACS
44#define FADT_SIG ACPI_SIG_FADT
45#define xfirmware_ctrl Xfacs
46#define firmware_ctrl facs
47
48typedef int s32;
49typedef unsigned char u8;
50typedef unsigned short u16;
51typedef unsigned int u32;
52typedef unsigned long long u64;
53typedef long long s64;
54#endif
55
56#include <sys/mman.h>
57#include <sys/types.h>
58#include <sys/stat.h>
59#include <fcntl.h>
60#include <stdio.h>
61#include <string.h>
62#include <unistd.h>
63#include <getopt.h>
64
65#include <dirent.h>
66
67#include <acpi/acconfig.h>
68#include <acpi/platform/acenv.h>
69#include <acpi/actypes.h>
70#include <acpi/actbl.h>
71
72static inline u8 checksum(u8 * buffer, u32 length)
73{
74 u8 sum = 0, *i = buffer;
75 buffer += length;
76 for (; i < buffer; sum += *(i++));
77 return sum;
78}
79
80static unsigned long psz, addr, length;
81static int print, connect, skip;
82static u8 select_sig[4];
83
84static unsigned long read_efi_systab( void )
85{
86 char buffer[80];
87 unsigned long addr;
88 FILE *f = fopen("/sys/firmware/efi/systab", "r");
89 if (f) {
90 while (fgets(buffer, 80, f)) {
91 if (sscanf(buffer, "ACPI20=0x%lx", &addr) == 1)
92 return addr;
93 }
94 fclose(f);
95 }
96 return 0;
97}
98
99static u8 *acpi_map_memory(unsigned long where, unsigned length)
100{
101 unsigned long offset;
102 u8 *there;
103 int fd = open("/dev/mem", O_RDONLY);
104 if (fd < 0) {
105 fprintf(stderr, "acpi_os_map_memory: cannot open /dev/mem\n");
106 exit(1);
107 }
108 offset = where % psz;
109 there = mmap(NULL, length + offset, PROT_READ, MAP_PRIVATE,
110 fd, where - offset);
111 close(fd);
112 if (there == MAP_FAILED) return 0;
113 return (there + offset);
114}
115
116static void acpi_unmap_memory(u8 * there, unsigned length)
117{
118 unsigned long offset = (unsigned long)there % psz;
119 munmap(there - offset, length + offset);
120}
121
122static struct acpi_table_header *acpi_map_table(unsigned long where, char *sig)
123{
124 unsigned size;
125 struct acpi_table_header *tbl = (struct acpi_table_header *)
126 acpi_map_memory(where, sizeof(struct acpi_table_header));
127 if (!tbl || (sig && memcmp(sig, tbl->signature, 4))) return 0;
128 size = tbl->length;
129 acpi_unmap_memory((u8 *) tbl, sizeof(struct acpi_table_header));
130 return (struct acpi_table_header *)acpi_map_memory(where, size);
131}
132
133static void acpi_unmap_table(struct acpi_table_header *tbl)
134{
135 acpi_unmap_memory((u8 *)tbl, tbl->length);
136}
137
138static struct acpi_rsdp_descriptor *acpi_scan_for_rsdp(u8 *begin, u32 length)
139{
140 struct acpi_rsdp_descriptor *rsdp;
141 u8 *i, *end = begin + length;
142 /* Search from given start address for the requested length */
143 for (i = begin; i < end; i += ACPI_RSDP_SCAN_STEP) {
144 /* The signature and checksum must both be correct */
145 if (memcmp((char *)i, "RSD PTR ", 8)) continue;
146 rsdp = (struct acpi_rsdp_descriptor *)i;
147 /* Signature matches, check the appropriate checksum */
148 if (!checksum((u8 *) rsdp, (rsdp->revision < 2) ?
149 ACPI_RSDP_CHECKSUM_LENGTH :
150 ACPI_RSDP_XCHECKSUM_LENGTH))
151 /* Checksum valid, we have found a valid RSDP */
152 return rsdp;
153 }
154 /* Searched entire block, no RSDP was found */
155 return 0;
156}
157
158/*
159 * Output data
160 */
161static void acpi_show_data(int fd, u8 * data, int size)
162{
163 char buffer[256];
164 int len;
165 int i, remain = size;
166 while (remain > 0) {
167 len = snprintf(buffer, 256, " %04x:", size - remain);
168 for (i = 0; i < 16 && i < remain; i++) {
169 len +=
170 snprintf(&buffer[len], 256 - len, " %02x", data[i]);
171 }
172 for (; i < 16; i++) {
173 len += snprintf(&buffer[len], 256 - len, " ");
174 }
175 len += snprintf(&buffer[len], 256 - len, " ");
176 for (i = 0; i < 16 && i < remain; i++) {
177 buffer[len++] = (isprint(data[i])) ? data[i] : '.';
178 }
179 buffer[len++] = '\n';
180 write(fd, buffer, len);
181 data += 16;
182 remain -= 16;
183 }
184}
185
186/*
187 * Output ACPI table
188 */
189static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned long addr)
190{
191 char buff[80];
192 int len = snprintf(buff, 80, "%.4s @ %p\n", table->signature, (void *)addr);
193 write(fd, buff, len);
194 acpi_show_data(fd, (u8 *) table, table->length);
195 buff[0] = '\n';
196 write(fd, buff, 1);
197}
198
199static void write_table(int fd, struct acpi_table_header *tbl, unsigned long addr)
200{
201 static int select_done = 0;
202 if (!select_sig[0]) {
203 if (print) {
204 acpi_show_table(fd, tbl, addr);
205 } else {
206 write(fd, tbl, tbl->length);
207 }
208 } else if (!select_done && !memcmp(select_sig, tbl->signature, 4)) {
209 if (skip > 0) {
210 --skip;
211 return;
212 }
213 if (print) {
214 acpi_show_table(fd, tbl, addr);
215 } else {
216 write(fd, tbl, tbl->length);
217 }
218 select_done = 1;
219 }
220}
221
222static void acpi_dump_FADT(int fd, struct acpi_table_header *tbl, unsigned long xaddr) {
223 struct acpi_fadt_descriptor x;
224 unsigned long addr;
225 size_t len = sizeof(struct acpi_fadt_descriptor);
226 if (len > tbl->length) len = tbl->length;
227 memcpy(&x, tbl, len);
228 x.header.length = len;
229 if (checksum((u8 *)tbl, len)) {
230 fprintf(stderr, "Wrong checksum for FADT!\n");
231 }
232 if (x.header.length >= 148 && x.Xdsdt) {
233 addr = (unsigned long)x.Xdsdt;
234 if (connect) {
235 x.Xdsdt = lseek(fd, 0, SEEK_CUR);
236 }
237 } else if (x.header.length >= 44 && x.dsdt) {
238 addr = (unsigned long)x.dsdt;
239 if (connect) {
240 x.dsdt = lseek(fd, 0, SEEK_CUR);
241 }
242 } else {
243 fprintf(stderr, "No DSDT in FADT!\n");
244 goto no_dsdt;
245 }
246 tbl = acpi_map_table(addr, DSDT_SIG);
247 if (!tbl) goto no_dsdt;
248 if (checksum((u8 *)tbl, tbl->length))
249 fprintf(stderr, "Wrong checksum for DSDT!\n");
250 write_table(fd, tbl, addr);
251 acpi_unmap_table(tbl);
252no_dsdt:
253 if (x.header.length >= 140 && x.xfirmware_ctrl) {
254 addr = (unsigned long)x.xfirmware_ctrl;
255 if (connect) {
256 x.xfirmware_ctrl = lseek(fd, 0, SEEK_CUR);
257 }
258 } else if (x.header.length >= 40 && x.firmware_ctrl) {
259 addr = (unsigned long)x.firmware_ctrl;
260 if (connect) {
261 x.firmware_ctrl = lseek(fd, 0, SEEK_CUR);
262 }
263 } else {
264 fprintf(stderr, "No FACS in FADT!\n");
265 goto no_facs;
266 }
267 tbl = acpi_map_table(addr, FACS_SIG);
268 if (!tbl) goto no_facs;
269 /* do not checksum FACS */
270 write_table(fd, tbl, addr);
271 acpi_unmap_table(tbl);
272no_facs:
273 write_table(fd, (struct acpi_table_header *)&x, xaddr);
274}
275
276static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp)
277{
278 struct acpi_table_header *sdt, *tbl = 0;
279 int xsdt = 1, i, num;
280 char *offset;
281 unsigned long addr;
282 if (rsdp->revision > 1 && rsdp->xsdt_physical_address) {
283 tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT");
284 }
285 if (!tbl && rsdp->rsdt_physical_address) {
286 xsdt = 0;
287 tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT");
288 }
289 if (!tbl) return 0;
290 sdt = malloc(tbl->length);
291 memcpy(sdt, tbl, tbl->length);
292 acpi_unmap_table(tbl);
293 if (checksum((u8 *)sdt, sdt->length))
294 fprintf(stderr, "Wrong checksum for %s!\n", (xsdt)?"XSDT":"RSDT");
295 num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32));
296 offset = (char *)sdt + sizeof(struct acpi_table_header);
297 for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(u64) : sizeof(u32))) {
298 addr = (xsdt) ? (unsigned long)(*(u64 *)offset):
299 (unsigned long)(*(u32 *)offset);
300 if (!addr) continue;
301 tbl = acpi_map_table(addr, 0);
302 if (!tbl) continue;
303 if (!memcmp(tbl->signature, FADT_SIG, 4)) {
304 acpi_dump_FADT(fd, tbl, addr);
305 } else {
306 if (checksum((u8 *)tbl, tbl->length))
307 fprintf(stderr, "Wrong checksum for generic table!\n");
308 write_table(fd, tbl, addr);
309 }
310 acpi_unmap_table(tbl);
311 if (connect) {
312 if (xsdt)
313 (*(u64*)offset) = lseek(fd, 0, SEEK_CUR);
314 else
315 (*(u32*)offset) = lseek(fd, 0, SEEK_CUR);
316 }
317 }
318 if (xsdt) {
319 addr = (unsigned long)rsdp->xsdt_physical_address;
320 if (connect) {
321 rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR);
322 }
323 } else {
324 addr = (unsigned long)rsdp->rsdt_physical_address;
325 if (connect) {
326 rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR);
327 }
328 }
329 write_table(fd, sdt, addr);
330 free (sdt);
331 return 1;
332}
333
334#define DYNAMIC_SSDT "/sys/firmware/acpi/tables/dynamic"
335
336static void acpi_dump_dynamic_SSDT(int fd)
337{
338 struct stat file_stat;
339 char filename[256], *ptr;
340 DIR *tabledir;
341 struct dirent *entry;
342 FILE *fp;
343 int count, readcount, length;
344 struct acpi_table_header table_header, *ptable;
345
346 if (stat(DYNAMIC_SSDT, &file_stat) == -1) {
347 /* The directory doesn't exist */
348 return;
349 }
350 tabledir = opendir(DYNAMIC_SSDT);
351 if(!tabledir){
352 /*can't open the directory */
353 return;
354 }
355
356 while ((entry = readdir(tabledir)) != 0){
357 /* skip the file of . /.. */
358 if (entry->d_name[0] == '.')
359 continue;
360
361 sprintf(filename, "%s/%s", DYNAMIC_SSDT, entry->d_name);
362 fp = fopen(filename, "r");
363 if (fp == NULL) {
364 fprintf(stderr, "Can't open the file of %s\n",
365 filename);
366 continue;
367 }
368 /* Read the Table header to parse the table length */
369 count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp);
370 if (count < sizeof(table_header)) {
371 /* the length is lessn than ACPI table header. skip it */
372 fclose(fp);
373 continue;
374 }
375 length = table_header.length;
376 ptr = malloc(table_header.length);
377 fseek(fp, 0, SEEK_SET);
378 readcount = 0;
379 while(!feof(fp) && readcount < length) {
380 count = fread(ptr + readcount, 1, 256, fp);
381 readcount += count;
382 }
383 fclose(fp);
384 ptable = (struct acpi_table_header *) ptr;
385 if (checksum((u8 *) ptable, ptable->length))
386 fprintf(stderr, "Wrong checksum "
387 "for dynamic SSDT table!\n");
388 write_table(fd, ptable, 0);
389 free(ptr);
390 }
391 closedir(tabledir);
392 return;
393}
394
395static void usage(const char *progname)
396{
397 puts("Usage:");
398 printf("%s [--addr 0x1234][--table DSDT][--output filename]"
399 "[--binary][--length 0x456][--help]\n", progname);
400 puts("\t--addr 0x1234 or -a 0x1234 -- look for tables at this physical address");
401 puts("\t--table DSDT or -t DSDT -- only dump table with DSDT signature");
402 puts("\t--output filename or -o filename -- redirect output from stdin to filename");
403 puts("\t--binary or -b -- dump data in binary form rather than in hex-dump format");
404 puts("\t--length 0x456 or -l 0x456 -- works only with --addr, dump physical memory"
405 "\n\t\tregion without trying to understand it's contents");
406 puts("\t--skip 2 or -s 2 -- skip 2 tables of the given name and output only 3rd one");
407 puts("\t--help or -h -- this help message");
408 exit(0);
409}
410
411static struct option long_options[] = {
412 {"addr", 1, 0, 0},
413 {"table", 1, 0, 0},
414 {"output", 1, 0, 0},
415 {"binary", 0, 0, 0},
416 {"length", 1, 0, 0},
417 {"skip", 1, 0, 0},
418 {"help", 0, 0, 0},
419 {0, 0, 0, 0}
420};
421int main(int argc, char **argv)
422{
423 int option_index, c, fd;
424 u8 *raw;
425 struct acpi_rsdp_descriptor rsdpx, *x = 0;
426 char *filename = 0;
427 char buff[80];
428 memset(select_sig, 0, 4);
429 print = 1;
430 connect = 0;
431 addr = length = 0;
432 skip = 0;
433 while (1) {
434 option_index = 0;
435 c = getopt_long(argc, argv, "a:t:o:bl:s:h",
436 long_options, &option_index);
437 if (c == -1)
438 break;
439
440 switch (c) {
441 case 0:
442 switch (option_index) {
443 case 0:
444 addr = strtoul(optarg, (char **)NULL, 16);
445 break;
446 case 1:
447 memcpy(select_sig, optarg, 4);
448 break;
449 case 2:
450 filename = optarg;
451 break;
452 case 3:
453 print = 0;
454 break;
455 case 4:
456 length = strtoul(optarg, (char **)NULL, 16);
457 break;
458 case 5:
459 skip = strtoul(optarg, (char **)NULL, 10);
460 break;
461 case 6:
462 usage(argv[0]);
463 exit(0);
464 }
465 break;
466 case 'a':
467 addr = strtoul(optarg, (char **)NULL, 16);
468 break;
469 case 't':
470 memcpy(select_sig, optarg, 4);
471 break;
472 case 'o':
473 filename = optarg;
474 break;
475 case 'b':
476 print = 0;
477 break;
478 case 'l':
479 length = strtoul(optarg, (char **)NULL, 16);
480 break;
481 case 's':
482 skip = strtoul(optarg, (char **)NULL, 10);
483 break;
484 case 'h':
485 usage(argv[0]);
486 exit(0);
487 default:
488 printf("Unknown option!\n");
489 usage(argv[0]);
490 exit(0);
491 }
492 }
493
494 fd = STDOUT_FILENO;
495 if (filename) {
496 fd = creat(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
497 if (fd < 0)
498 return fd;
499 }
500
501 if (!select_sig[0] && !print) {
502 connect = 1;
503 }
504
505 psz = sysconf(_SC_PAGESIZE);
506 if (length && addr) {
507 /* We know length and address, it means we just want a memory dump */
508 if (!(raw = acpi_map_memory(addr, length)))
509 goto not_found;
510 write(fd, raw, length);
511 acpi_unmap_memory(raw, length);
512 close(fd);
513 return 0;
514 }
515
516 length = sizeof(struct acpi_rsdp_descriptor);
517 if (!addr) {
518 addr = read_efi_systab();
519 if (!addr) {
520 addr = ACPI_HI_RSDP_WINDOW_BASE;
521 length = ACPI_HI_RSDP_WINDOW_SIZE;
522 }
523 }
524
525 if (!(raw = acpi_map_memory(addr, length)) ||
526 !(x = acpi_scan_for_rsdp(raw, length)))
527 goto not_found;
528
529 /* Find RSDP and print all found tables */
530 memcpy(&rsdpx, x, sizeof(struct acpi_rsdp_descriptor));
531 acpi_unmap_memory(raw, length);
532 if (connect) {
533 lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET);
534 }
535 if (!acpi_dump_SDT(fd, &rsdpx))
536 goto not_found;
537 if (connect) {
538 lseek(fd, 0, SEEK_SET);
539 write(fd, x, (rsdpx.revision < 2) ?
540 ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH);
541 } else if (!select_sig[0] || !memcmp("RSD PTR ", select_sig, 4)) {
542 addr += (long)x - (long)raw;
543 length = snprintf(buff, 80, "RSD PTR @ %p\n", (void *)addr);
544 write(fd, buff, length);
545 acpi_show_data(fd, (u8 *) & rsdpx, (rsdpx.revision < 2) ?
546 ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH);
547 buff[0] = '\n';
548 write(fd, buff, 1);
549 }
550 acpi_dump_dynamic_SSDT(fd);
551 close(fd);
552 return 0;
553not_found:
554 close(fd);
555 fprintf(stderr, "ACPI tables were not found. If you know location "
556 "of RSD PTR table (from dmesg, etc), "
557 "supply it with either --addr or -a option\n");
558 return 1;
559}
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index a93e06cfcc2..cf397bd26d0 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -111,7 +111,7 @@ GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo $(OUTPUT)po/$$HLANG.gmo;
111export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS 111export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS
112 112
113# check if compiler option is supported 113# check if compiler option is supported
114cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;} 114cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -x c /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;}
115 115
116# use '-Os' optimization if available, else use -O2 116# use '-Os' optimization if available, else use -O2
117OPTIMIZATION := $(call cc-supports,-Os,-O2) 117OPTIMIZATION := $(call cc-supports,-Os,-O2)
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index 74e44507dfe..e4d0690cccf 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -4,15 +4,11 @@ turbostat \- Report processor frequency and idle statistics
4.SH SYNOPSIS 4.SH SYNOPSIS
5.ft B 5.ft B
6.B turbostat 6.B turbostat
7.RB [ "\-s" ] 7.RB [ Options ]
8.RB [ "\-v" ]
9.RB [ "\-M MSR#" ]
10.RB command 8.RB command
11.br 9.br
12.B turbostat 10.B turbostat
13.RB [ "\-s" ] 11.RB [ Options ]
14.RB [ "\-v" ]
15.RB [ "\-M MSR#" ]
16.RB [ "\-i interval_sec" ] 12.RB [ "\-i interval_sec" ]
17.SH DESCRIPTION 13.SH DESCRIPTION
18\fBturbostat \fP reports processor topology, frequency 14\fBturbostat \fP reports processor topology, frequency
@@ -27,16 +23,23 @@ supports an "invariant" TSC, plus the APERF and MPERF MSRs.
27on processors that additionally support C-state residency counters. 23on processors that additionally support C-state residency counters.
28 24
29.SS Options 25.SS Options
30The \fB-s\fP option limits output to a 1-line system summary for each interval. 26The \fB-p\fP option limits output to the 1st thread in 1st core of each package.
31.PP 27.PP
32The \fB-c\fP option limits output to the 1st thread in each core. 28The \fB-P\fP option limits output to the 1st thread in each Package.
33.PP 29.PP
34The \fB-p\fP option limits output to the 1st thread in each package. 30The \fB-S\fP option limits output to a 1-line System Summary for each interval.
35.PP 31.PP
36The \fB-v\fP option increases verbosity. 32The \fB-v\fP option increases verbosity.
37.PP 33.PP
38The \fB-M MSR#\fP option dumps the specified MSR, 34The \fB-s\fP option prints the SMI counter, equivalent to "-c 0x34"
39in addition to the usual frequency and idle statistics. 35.PP
36The \fB-c MSR#\fP option includes the delta of the specified 32-bit MSR counter.
37.PP
38The \fB-C MSR#\fP option includes the delta of the specified 64-bit MSR counter.
39.PP
40The \fB-m MSR#\fP option includes the the specified 32-bit MSR value.
41.PP
42The \fB-M MSR#\fP option includes the the specified 64-bit MSR value.
40.PP 43.PP
41The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds. 44The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds.
42The default is 5 seconds. 45The default is 5 seconds.
@@ -150,6 +153,29 @@ Note that turbostat reports average GHz of 3.63, while
150the arithmetic average of the GHz column above is lower. 153the arithmetic average of the GHz column above is lower.
151This is a weighted average, where the weight is %c0. ie. it is the total number of 154This is a weighted average, where the weight is %c0. ie. it is the total number of
152un-halted cycles elapsed per time divided by the number of CPUs. 155un-halted cycles elapsed per time divided by the number of CPUs.
156.SH SMI COUNTING EXAMPLE
157On Intel Nehalem and newer processors, MSR 0x34 is a System Management Mode Interrupt (SMI) counter.
158Using the -m option, you can display how many SMIs have fired since reset, or if there
159are SMIs during the measurement interval, you can display the delta using the -d option.
160.nf
161[root@x980 ~]# turbostat -m 0x34
162cor CPU %c0 GHz TSC MSR 0x034 %c1 %c3 %c6 %pc3 %pc6
163 1.41 1.82 3.38 0x00000000 8.92 37.82 51.85 17.37 0.55
164 0 0 3.73 2.03 3.38 0x00000055 1.72 48.25 46.31 17.38 0.55
165 0 6 0.14 1.63 3.38 0x00000056 5.30
166 1 2 2.51 1.80 3.38 0x00000056 15.65 29.33 52.52
167 1 8 0.10 1.65 3.38 0x00000056 18.05
168 2 4 1.16 1.68 3.38 0x00000056 5.87 24.47 68.50
169 2 10 0.10 1.63 3.38 0x00000056 6.93
170 8 1 3.84 1.91 3.38 0x00000056 1.36 50.65 44.16
171 8 7 0.08 1.64 3.38 0x00000056 5.12
172 9 3 1.82 1.73 3.38 0x00000056 7.59 24.21 66.38
173 9 9 0.09 1.68 3.38 0x00000056 9.32
174 10 5 1.66 1.65 3.38 0x00000056 15.10 50.00 33.23
175 10 11 1.72 1.65 3.38 0x00000056 15.05
176^C
177[root@x980 ~]#
178.fi
153.SH NOTES 179.SH NOTES
154 180
155.B "turbostat " 181.B "turbostat "
@@ -165,6 +191,13 @@ may work poorly on Linux-2.6.20 through 2.6.29,
165as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF 191as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF
166in those kernels. 192in those kernels.
167 193
194If the TSC column does not make sense, then
195the other numbers will also make no sense.
196Turbostat is lightweight, and its data collection is not atomic.
197These issues are usually caused by an extremely short measurement
198interval (much less than 1 second), or system activity that prevents
199turbostat from being able to run on all CPUS to quickly collect data.
200
168The APERF, MPERF MSRs are defined to count non-halted cycles. 201The APERF, MPERF MSRs are defined to count non-halted cycles.
169Although it is not guaranteed by the architecture, turbostat assumes 202Although it is not guaranteed by the architecture, turbostat assumes
170that they count at TSC rate, which is true on all processors tested to date. 203that they count at TSC rate, which is true on all processors tested to date.
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 861d7719020..2655ae9a3ad 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -35,9 +35,9 @@
35#include <ctype.h> 35#include <ctype.h>
36#include <sched.h> 36#include <sched.h>
37 37
38#define MSR_TSC 0x10
39#define MSR_NEHALEM_PLATFORM_INFO 0xCE 38#define MSR_NEHALEM_PLATFORM_INFO 0xCE
40#define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD 39#define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD
40#define MSR_IVT_TURBO_RATIO_LIMIT 0x1AE
41#define MSR_APERF 0xE8 41#define MSR_APERF 0xE8
42#define MSR_MPERF 0xE7 42#define MSR_MPERF 0xE7
43#define MSR_PKG_C2_RESIDENCY 0x60D /* SNB only */ 43#define MSR_PKG_C2_RESIDENCY 0x60D /* SNB only */
@@ -62,7 +62,11 @@ unsigned int genuine_intel;
62unsigned int has_invariant_tsc; 62unsigned int has_invariant_tsc;
63unsigned int do_nehalem_platform_info; 63unsigned int do_nehalem_platform_info;
64unsigned int do_nehalem_turbo_ratio_limit; 64unsigned int do_nehalem_turbo_ratio_limit;
65unsigned int extra_msr_offset; 65unsigned int do_ivt_turbo_ratio_limit;
66unsigned int extra_msr_offset32;
67unsigned int extra_msr_offset64;
68unsigned int extra_delta_offset32;
69unsigned int extra_delta_offset64;
66double bclk; 70double bclk;
67unsigned int show_pkg; 71unsigned int show_pkg;
68unsigned int show_core; 72unsigned int show_core;
@@ -83,7 +87,10 @@ struct thread_data {
83 unsigned long long aperf; 87 unsigned long long aperf;
84 unsigned long long mperf; 88 unsigned long long mperf;
85 unsigned long long c1; /* derived */ 89 unsigned long long c1; /* derived */
86 unsigned long long extra_msr; 90 unsigned long long extra_msr64;
91 unsigned long long extra_delta64;
92 unsigned long long extra_msr32;
93 unsigned long long extra_delta32;
87 unsigned int cpu_id; 94 unsigned int cpu_id;
88 unsigned int flags; 95 unsigned int flags;
89#define CPU_IS_FIRST_THREAD_IN_CORE 0x2 96#define CPU_IS_FIRST_THREAD_IN_CORE 0x2
@@ -222,6 +229,14 @@ void print_header(void)
222 if (has_aperf) 229 if (has_aperf)
223 outp += sprintf(outp, " GHz"); 230 outp += sprintf(outp, " GHz");
224 outp += sprintf(outp, " TSC"); 231 outp += sprintf(outp, " TSC");
232 if (extra_delta_offset32)
233 outp += sprintf(outp, " count 0x%03X", extra_delta_offset32);
234 if (extra_delta_offset64)
235 outp += sprintf(outp, " COUNT 0x%03X", extra_delta_offset64);
236 if (extra_msr_offset32)
237 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32);
238 if (extra_msr_offset64)
239 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64);
225 if (do_nhm_cstates) 240 if (do_nhm_cstates)
226 outp += sprintf(outp, " %%c1"); 241 outp += sprintf(outp, " %%c1");
227 if (do_nhm_cstates) 242 if (do_nhm_cstates)
@@ -238,8 +253,6 @@ void print_header(void)
238 outp += sprintf(outp, " %%pc6"); 253 outp += sprintf(outp, " %%pc6");
239 if (do_snb_cstates) 254 if (do_snb_cstates)
240 outp += sprintf(outp, " %%pc7"); 255 outp += sprintf(outp, " %%pc7");
241 if (extra_msr_offset)
242 outp += sprintf(outp, " MSR 0x%x ", extra_msr_offset);
243 256
244 outp += sprintf(outp, "\n"); 257 outp += sprintf(outp, "\n");
245} 258}
@@ -255,8 +268,14 @@ int dump_counters(struct thread_data *t, struct core_data *c,
255 fprintf(stderr, "aperf: %016llX\n", t->aperf); 268 fprintf(stderr, "aperf: %016llX\n", t->aperf);
256 fprintf(stderr, "mperf: %016llX\n", t->mperf); 269 fprintf(stderr, "mperf: %016llX\n", t->mperf);
257 fprintf(stderr, "c1: %016llX\n", t->c1); 270 fprintf(stderr, "c1: %016llX\n", t->c1);
271 fprintf(stderr, "msr0x%x: %08llX\n",
272 extra_delta_offset32, t->extra_delta32);
258 fprintf(stderr, "msr0x%x: %016llX\n", 273 fprintf(stderr, "msr0x%x: %016llX\n",
259 extra_msr_offset, t->extra_msr); 274 extra_delta_offset64, t->extra_delta64);
275 fprintf(stderr, "msr0x%x: %08llX\n",
276 extra_msr_offset32, t->extra_msr32);
277 fprintf(stderr, "msr0x%x: %016llX\n",
278 extra_msr_offset64, t->extra_msr64);
260 } 279 }
261 280
262 if (c) { 281 if (c) {
@@ -360,6 +379,21 @@ int format_counters(struct thread_data *t, struct core_data *c,
360 /* TSC */ 379 /* TSC */
361 outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float); 380 outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float);
362 381
382 /* delta */
383 if (extra_delta_offset32)
384 outp += sprintf(outp, " %11llu", t->extra_delta32);
385
386 /* DELTA */
387 if (extra_delta_offset64)
388 outp += sprintf(outp, " %11llu", t->extra_delta64);
389 /* msr */
390 if (extra_msr_offset32)
391 outp += sprintf(outp, " 0x%08llx", t->extra_msr32);
392
393 /* MSR */
394 if (extra_msr_offset64)
395 outp += sprintf(outp, " 0x%016llx", t->extra_msr64);
396
363 if (do_nhm_cstates) { 397 if (do_nhm_cstates) {
364 if (!skip_c1) 398 if (!skip_c1)
365 outp += sprintf(outp, " %6.2f", 100.0 * t->c1/t->tsc); 399 outp += sprintf(outp, " %6.2f", 100.0 * t->c1/t->tsc);
@@ -391,8 +425,6 @@ int format_counters(struct thread_data *t, struct core_data *c,
391 if (do_snb_cstates) 425 if (do_snb_cstates)
392 outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc); 426 outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc);
393done: 427done:
394 if (extra_msr_offset)
395 outp += sprintf(outp, " 0x%016llx", t->extra_msr);
396 outp += sprintf(outp, "\n"); 428 outp += sprintf(outp, "\n");
397 429
398 return 0; 430 return 0;
@@ -502,10 +534,16 @@ delta_thread(struct thread_data *new, struct thread_data *old,
502 old->mperf = 1; /* divide by 0 protection */ 534 old->mperf = 1; /* divide by 0 protection */
503 } 535 }
504 536
537 old->extra_delta32 = new->extra_delta32 - old->extra_delta32;
538 old->extra_delta32 &= 0xFFFFFFFF;
539
540 old->extra_delta64 = new->extra_delta64 - old->extra_delta64;
541
505 /* 542 /*
506 * for "extra msr", just copy the latest w/o subtracting 543 * Extra MSR is just a snapshot, simply copy latest w/o subtracting
507 */ 544 */
508 old->extra_msr = new->extra_msr; 545 old->extra_msr32 = new->extra_msr32;
546 old->extra_msr64 = new->extra_msr64;
509} 547}
510 548
511int delta_cpu(struct thread_data *t, struct core_data *c, 549int delta_cpu(struct thread_data *t, struct core_data *c,
@@ -533,6 +571,9 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
533 t->mperf = 0; 571 t->mperf = 0;
534 t->c1 = 0; 572 t->c1 = 0;
535 573
574 t->extra_delta32 = 0;
575 t->extra_delta64 = 0;
576
536 /* tells format_counters to dump all fields from this set */ 577 /* tells format_counters to dump all fields from this set */
537 t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE; 578 t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE;
538 579
@@ -553,6 +594,9 @@ int sum_counters(struct thread_data *t, struct core_data *c,
553 average.threads.mperf += t->mperf; 594 average.threads.mperf += t->mperf;
554 average.threads.c1 += t->c1; 595 average.threads.c1 += t->c1;
555 596
597 average.threads.extra_delta32 += t->extra_delta32;
598 average.threads.extra_delta64 += t->extra_delta64;
599
556 /* sum per-core values only for 1st thread in core */ 600 /* sum per-core values only for 1st thread in core */
557 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 601 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
558 return 0; 602 return 0;
@@ -588,6 +632,11 @@ void compute_average(struct thread_data *t, struct core_data *c,
588 average.threads.mperf /= topo.num_cpus; 632 average.threads.mperf /= topo.num_cpus;
589 average.threads.c1 /= topo.num_cpus; 633 average.threads.c1 /= topo.num_cpus;
590 634
635 average.threads.extra_delta32 /= topo.num_cpus;
636 average.threads.extra_delta32 &= 0xFFFFFFFF;
637
638 average.threads.extra_delta64 /= topo.num_cpus;
639
591 average.cores.c3 /= topo.num_cores; 640 average.cores.c3 /= topo.num_cores;
592 average.cores.c6 /= topo.num_cores; 641 average.cores.c6 /= topo.num_cores;
593 average.cores.c7 /= topo.num_cores; 642 average.cores.c7 /= topo.num_cores;
@@ -629,8 +678,24 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
629 return -4; 678 return -4;
630 } 679 }
631 680
632 if (extra_msr_offset) 681 if (extra_delta_offset32) {
633 if (get_msr(cpu, extra_msr_offset, &t->extra_msr)) 682 if (get_msr(cpu, extra_delta_offset32, &t->extra_delta32))
683 return -5;
684 t->extra_delta32 &= 0xFFFFFFFF;
685 }
686
687 if (extra_delta_offset64)
688 if (get_msr(cpu, extra_delta_offset64, &t->extra_delta64))
689 return -5;
690
691 if (extra_msr_offset32) {
692 if (get_msr(cpu, extra_msr_offset32, &t->extra_msr32))
693 return -5;
694 t->extra_msr32 &= 0xFFFFFFFF;
695 }
696
697 if (extra_msr_offset64)
698 if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64))
634 return -5; 699 return -5;
635 700
636 /* collect core counters only for 1st thread in core */ 701 /* collect core counters only for 1st thread in core */
@@ -677,6 +742,9 @@ void print_verbose_header(void)
677 742
678 get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr); 743 get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr);
679 744
745 if (verbose > 1)
746 fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr);
747
680 ratio = (msr >> 40) & 0xFF; 748 ratio = (msr >> 40) & 0xFF;
681 fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n", 749 fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n",
682 ratio, bclk, ratio * bclk); 750 ratio, bclk, ratio * bclk);
@@ -685,14 +753,84 @@ void print_verbose_header(void)
685 fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n", 753 fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n",
686 ratio, bclk, ratio * bclk); 754 ratio, bclk, ratio * bclk);
687 755
756 if (!do_ivt_turbo_ratio_limit)
757 goto print_nhm_turbo_ratio_limits;
758
759 get_msr(0, MSR_IVT_TURBO_RATIO_LIMIT, &msr);
760
688 if (verbose > 1) 761 if (verbose > 1)
689 fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr); 762 fprintf(stderr, "MSR_IVT_TURBO_RATIO_LIMIT: 0x%llx\n", msr);
763
764 ratio = (msr >> 56) & 0xFF;
765 if (ratio)
766 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 16 active cores\n",
767 ratio, bclk, ratio * bclk);
768
769 ratio = (msr >> 48) & 0xFF;
770 if (ratio)
771 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 15 active cores\n",
772 ratio, bclk, ratio * bclk);
773
774 ratio = (msr >> 40) & 0xFF;
775 if (ratio)
776 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 14 active cores\n",
777 ratio, bclk, ratio * bclk);
778
779 ratio = (msr >> 32) & 0xFF;
780 if (ratio)
781 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 13 active cores\n",
782 ratio, bclk, ratio * bclk);
783
784 ratio = (msr >> 24) & 0xFF;
785 if (ratio)
786 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 12 active cores\n",
787 ratio, bclk, ratio * bclk);
788
789 ratio = (msr >> 16) & 0xFF;
790 if (ratio)
791 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 11 active cores\n",
792 ratio, bclk, ratio * bclk);
793
794 ratio = (msr >> 8) & 0xFF;
795 if (ratio)
796 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 10 active cores\n",
797 ratio, bclk, ratio * bclk);
798
799 ratio = (msr >> 0) & 0xFF;
800 if (ratio)
801 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 9 active cores\n",
802 ratio, bclk, ratio * bclk);
803
804print_nhm_turbo_ratio_limits:
690 805
691 if (!do_nehalem_turbo_ratio_limit) 806 if (!do_nehalem_turbo_ratio_limit)
692 return; 807 return;
693 808
694 get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr); 809 get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr);
695 810
811 if (verbose > 1)
812 fprintf(stderr, "MSR_NEHALEM_TURBO_RATIO_LIMIT: 0x%llx\n", msr);
813
814 ratio = (msr >> 56) & 0xFF;
815 if (ratio)
816 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 8 active cores\n",
817 ratio, bclk, ratio * bclk);
818
819 ratio = (msr >> 48) & 0xFF;
820 if (ratio)
821 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 7 active cores\n",
822 ratio, bclk, ratio * bclk);
823
824 ratio = (msr >> 40) & 0xFF;
825 if (ratio)
826 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 6 active cores\n",
827 ratio, bclk, ratio * bclk);
828
829 ratio = (msr >> 32) & 0xFF;
830 if (ratio)
831 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 5 active cores\n",
832 ratio, bclk, ratio * bclk);
833
696 ratio = (msr >> 24) & 0xFF; 834 ratio = (msr >> 24) & 0xFF;
697 if (ratio) 835 if (ratio)
698 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n", 836 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n",
@@ -712,7 +850,6 @@ void print_verbose_header(void)
712 if (ratio) 850 if (ratio)
713 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n", 851 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n",
714 ratio, bclk, ratio * bclk); 852 ratio, bclk, ratio * bclk);
715
716} 853}
717 854
718void free_all_buffers(void) 855void free_all_buffers(void)
@@ -1038,7 +1175,7 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
1038 case 0x2A: /* SNB */ 1175 case 0x2A: /* SNB */
1039 case 0x2D: /* SNB Xeon */ 1176 case 0x2D: /* SNB Xeon */
1040 case 0x3A: /* IVB */ 1177 case 0x3A: /* IVB */
1041 case 0x3D: /* IVB Xeon */ 1178 case 0x3E: /* IVB Xeon */
1042 return 1; 1179 return 1;
1043 case 0x2E: /* Nehalem-EX Xeon - Beckton */ 1180 case 0x2E: /* Nehalem-EX Xeon - Beckton */
1044 case 0x2F: /* Westmere-EX Xeon - Eagleton */ 1181 case 0x2F: /* Westmere-EX Xeon - Eagleton */
@@ -1046,6 +1183,22 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
1046 return 0; 1183 return 0;
1047 } 1184 }
1048} 1185}
1186int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
1187{
1188 if (!genuine_intel)
1189 return 0;
1190
1191 if (family != 6)
1192 return 0;
1193
1194 switch (model) {
1195 case 0x3E: /* IVB Xeon */
1196 return 1;
1197 default:
1198 return 0;
1199 }
1200}
1201
1049 1202
1050int is_snb(unsigned int family, unsigned int model) 1203int is_snb(unsigned int family, unsigned int model)
1051{ 1204{
@@ -1056,7 +1209,7 @@ int is_snb(unsigned int family, unsigned int model)
1056 case 0x2A: 1209 case 0x2A:
1057 case 0x2D: 1210 case 0x2D:
1058 case 0x3A: /* IVB */ 1211 case 0x3A: /* IVB */
1059 case 0x3D: /* IVB Xeon */ 1212 case 0x3E: /* IVB Xeon */
1060 return 1; 1213 return 1;
1061 } 1214 }
1062 return 0; 1215 return 0;
@@ -1145,12 +1298,13 @@ void check_cpuid()
1145 bclk = discover_bclk(family, model); 1298 bclk = discover_bclk(family, model);
1146 1299
1147 do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model); 1300 do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model);
1301 do_ivt_turbo_ratio_limit = has_ivt_turbo_ratio_limit(family, model);
1148} 1302}
1149 1303
1150 1304
1151void usage() 1305void usage()
1152{ 1306{
1153 fprintf(stderr, "%s: [-v] [-M MSR#] [-i interval_sec | command ...]\n", 1307 fprintf(stderr, "%s: [-v][-p|-P|-S][-c MSR# | -s]][-C MSR#][-m MSR#][-M MSR#][-i interval_sec | command ...]\n",
1154 progname); 1308 progname);
1155 exit(1); 1309 exit(1);
1156} 1310}
@@ -1440,15 +1594,15 @@ void cmdline(int argc, char **argv)
1440 1594
1441 progname = argv[0]; 1595 progname = argv[0];
1442 1596
1443 while ((opt = getopt(argc, argv, "+cpsvi:M:")) != -1) { 1597 while ((opt = getopt(argc, argv, "+pPSvisc:sC:m:M:")) != -1) {
1444 switch (opt) { 1598 switch (opt) {
1445 case 'c': 1599 case 'p':
1446 show_core_only++; 1600 show_core_only++;
1447 break; 1601 break;
1448 case 'p': 1602 case 'P':
1449 show_pkg_only++; 1603 show_pkg_only++;
1450 break; 1604 break;
1451 case 's': 1605 case 'S':
1452 summary_only++; 1606 summary_only++;
1453 break; 1607 break;
1454 case 'v': 1608 case 'v':
@@ -1457,10 +1611,20 @@ void cmdline(int argc, char **argv)
1457 case 'i': 1611 case 'i':
1458 interval_sec = atoi(optarg); 1612 interval_sec = atoi(optarg);
1459 break; 1613 break;
1614 case 'c':
1615 sscanf(optarg, "%x", &extra_delta_offset32);
1616 break;
1617 case 's':
1618 extra_delta_offset32 = 0x34; /* SMI counter */
1619 break;
1620 case 'C':
1621 sscanf(optarg, "%x", &extra_delta_offset64);
1622 break;
1623 case 'm':
1624 sscanf(optarg, "%x", &extra_msr_offset32);
1625 break;
1460 case 'M': 1626 case 'M':
1461 sscanf(optarg, "%x", &extra_msr_offset); 1627 sscanf(optarg, "%x", &extra_msr_offset64);
1462 if (verbose > 1)
1463 fprintf(stderr, "MSR 0x%X\n", extra_msr_offset);
1464 break; 1628 break;
1465 default: 1629 default:
1466 usage(); 1630 usage();
@@ -1473,7 +1637,7 @@ int main(int argc, char **argv)
1473 cmdline(argc, argv); 1637 cmdline(argc, argv);
1474 1638
1475 if (verbose > 1) 1639 if (verbose > 1)
1476 fprintf(stderr, "turbostat v2.0 May 16, 2012" 1640 fprintf(stderr, "turbostat v2.1 October 6, 2012"
1477 " - Len Brown <lenb@kernel.org>\n"); 1641 " - Len Brown <lenb@kernel.org>\n");
1478 1642
1479 turbostat_init(); 1643 turbostat_init();
diff --git a/tools/testing/ktest/examples/include/defaults.conf b/tools/testing/ktest/examples/include/defaults.conf
index 323a552ce64..63a1a83f4f0 100644
--- a/tools/testing/ktest/examples/include/defaults.conf
+++ b/tools/testing/ktest/examples/include/defaults.conf
@@ -33,7 +33,7 @@ DEFAULTS
33THIS_DIR := ${PWD} 33THIS_DIR := ${PWD}
34 34
35 35
36# to orginize your configs, having each machine save their configs 36# to organize your configs, having each machine save their configs
37# into a separate directly is useful. 37# into a separate directly is useful.
38CONFIG_DIR := ${THIS_DIR}/configs/${MACHINE} 38CONFIG_DIR := ${THIS_DIR}/configs/${MACHINE}
39 39
diff --git a/tools/testing/ktest/examples/include/tests.conf b/tools/testing/ktest/examples/include/tests.conf
index 4fdb811bd81..60cedb1a115 100644
--- a/tools/testing/ktest/examples/include/tests.conf
+++ b/tools/testing/ktest/examples/include/tests.conf
@@ -47,7 +47,7 @@ BUILD_NOCLEAN = 1
47# Build, install, boot and test with a randconfg 10 times. 47# Build, install, boot and test with a randconfg 10 times.
48# It is important that you have set MIN_CONFIG in the config 48# It is important that you have set MIN_CONFIG in the config
49# that includes this file otherwise it is likely that the 49# that includes this file otherwise it is likely that the
50# randconfig will not have the neccessary configs needed to 50# randconfig will not have the necessary configs needed to
51# boot your box. This version of the test requires a min 51# boot your box. This version of the test requires a min
52# config that has enough to make sure the target has network 52# config that has enough to make sure the target has network
53# working. 53# working.
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index 52b7959cd51..b51d787176d 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -840,7 +840,9 @@ sub __read_config {
840 840
841 if ($rest =~ /\sIF\s+(.*)/) { 841 if ($rest =~ /\sIF\s+(.*)/) {
842 # May be a ELSE IF section. 842 # May be a ELSE IF section.
843 if (!process_if($name, $1)) { 843 if (process_if($name, $1)) {
844 $if_set = 1;
845 } else {
844 $skip = 1; 846 $skip = 1;
845 } 847 }
846 $rest = ""; 848 $rest = "";
@@ -1871,10 +1873,10 @@ sub make_oldconfig {
1871 apply_min_config; 1873 apply_min_config;
1872 } 1874 }
1873 1875
1874 if (!run_command "$make oldnoconfig") { 1876 if (!run_command "$make olddefconfig") {
1875 # Perhaps oldnoconfig doesn't exist in this version of the kernel 1877 # Perhaps olddefconfig doesn't exist in this version of the kernel
1876 # try a yes '' | oldconfig 1878 # try a yes '' | oldconfig
1877 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 1879 doprint "olddefconfig failed, trying yes '' | make oldconfig\n";
1878 run_command "yes '' | $make oldconfig" or 1880 run_command "yes '' | $make oldconfig" or
1879 dodie "failed make config oldconfig"; 1881 dodie "failed make config oldconfig";
1880 } 1882 }
@@ -1927,7 +1929,7 @@ sub build {
1927 1929
1928 # old config can ask questions 1930 # old config can ask questions
1929 if ($type eq "oldconfig") { 1931 if ($type eq "oldconfig") {
1930 $type = "oldnoconfig"; 1932 $type = "olddefconfig";
1931 1933
1932 # allow for empty configs 1934 # allow for empty configs
1933 run_command "touch $output_config"; 1935 run_command "touch $output_config";
@@ -1957,7 +1959,7 @@ sub build {
1957 load_force_config($minconfig); 1959 load_force_config($minconfig);
1958 } 1960 }
1959 1961
1960 if ($type ne "oldnoconfig") { 1962 if ($type ne "olddefconfig") {
1961 run_command "$make $type" or 1963 run_command "$make $type" or
1962 dodie "failed make config"; 1964 dodie "failed make config";
1963 } 1965 }
@@ -2456,8 +2458,7 @@ my %config_set;
2456 2458
2457# config_off holds the set of configs that the bad config had disabled. 2459# config_off holds the set of configs that the bad config had disabled.
2458# We need to record them and set them in the .config when running 2460# We need to record them and set them in the .config when running
2459# oldnoconfig, because oldnoconfig does not turn off new symbols, but 2461# olddefconfig, because olddefconfig keeps the defaults.
2460# instead just keeps the defaults.
2461my %config_off; 2462my %config_off;
2462 2463
2463# config_off_tmp holds a set of configs to turn off for now 2464# config_off_tmp holds a set of configs to turn off for now
@@ -3248,7 +3249,7 @@ sub test_this_config {
3248 } 3249 }
3249 3250
3250 # Remove this config from the list of configs 3251 # Remove this config from the list of configs
3251 # do a make oldnoconfig and then read the resulting 3252 # do a make olddefconfig and then read the resulting
3252 # .config to make sure it is missing the config that 3253 # .config to make sure it is missing the config that
3253 # we had before 3254 # we had before
3254 my %configs = %min_configs; 3255 my %configs = %min_configs;
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 85baf11e2ac..43480149119 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -1,4 +1,4 @@
1TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug 1TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug epoll
2 2
3all: 3all:
4 for TARGET in $(TARGETS); do \ 4 for TARGET in $(TARGETS); do \
diff --git a/tools/testing/selftests/epoll/Makefile b/tools/testing/selftests/epoll/Makefile
new file mode 100644
index 00000000000..19806ed62f5
--- /dev/null
+++ b/tools/testing/selftests/epoll/Makefile
@@ -0,0 +1,11 @@
1# Makefile for epoll selftests
2
3all: test_epoll
4%: %.c
5 gcc -pthread -g -o $@ $^
6
7run_tests: all
8 ./test_epoll
9
10clean:
11 $(RM) test_epoll
diff --git a/tools/testing/selftests/epoll/test_epoll.c b/tools/testing/selftests/epoll/test_epoll.c
new file mode 100644
index 00000000000..e0fcff1e833
--- /dev/null
+++ b/tools/testing/selftests/epoll/test_epoll.c
@@ -0,0 +1,344 @@
1/*
2 * tools/testing/selftests/epoll/test_epoll.c
3 *
4 * Copyright 2012 Adobe Systems Incorporated
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * Paton J. Lewis <palewis@adobe.com>
12 *
13 */
14
15#include <errno.h>
16#include <fcntl.h>
17#include <pthread.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <unistd.h>
21#include <sys/epoll.h>
22#include <sys/socket.h>
23
24/*
25 * A pointer to an epoll_item_private structure will be stored in the epoll
26 * item's event structure so that we can get access to the epoll_item_private
27 * data after calling epoll_wait:
28 */
29struct epoll_item_private {
30 int index; /* Position of this struct within the epoll_items array. */
31 int fd;
32 uint32_t events;
33 pthread_mutex_t mutex; /* Guards the following variables... */
34 int stop;
35 int status; /* Stores any error encountered while handling item. */
36 /* The following variable allows us to test whether we have encountered
37 a problem while attempting to cancel and delete the associated
38 event. When the test program exits, 'deleted' should be exactly
39 one. If it is greater than one, then the failed test reflects a real
40 world situation where we would have tried to access the epoll item's
41 private data after deleting it: */
42 int deleted;
43};
44
45struct epoll_item_private *epoll_items;
46
47/*
48 * Delete the specified item from the epoll set. In a real-world secneario this
49 * is where we would free the associated data structure, but in this testing
50 * environment we retain the structure so that we can test for double-deletion:
51 */
52void delete_item(int index)
53{
54 __sync_fetch_and_add(&epoll_items[index].deleted, 1);
55}
56
57/*
58 * A pointer to a read_thread_data structure will be passed as the argument to
59 * each read thread:
60 */
61struct read_thread_data {
62 int stop;
63 int status; /* Indicates any error encountered by the read thread. */
64 int epoll_set;
65};
66
67/*
68 * The function executed by the read threads:
69 */
70void *read_thread_function(void *function_data)
71{
72 struct read_thread_data *thread_data =
73 (struct read_thread_data *)function_data;
74 struct epoll_event event_data;
75 struct epoll_item_private *item_data;
76 char socket_data;
77
78 /* Handle events until we encounter an error or this thread's 'stop'
79 condition is set: */
80 while (1) {
81 int result = epoll_wait(thread_data->epoll_set,
82 &event_data,
83 1, /* Number of desired events */
84 1000); /* Timeout in ms */
85 if (result < 0) {
86 /* Breakpoints signal all threads. Ignore that while
87 debugging: */
88 if (errno == EINTR)
89 continue;
90 thread_data->status = errno;
91 return 0;
92 } else if (thread_data->stop)
93 return 0;
94 else if (result == 0) /* Timeout */
95 continue;
96
97 /* We need the mutex here because checking for the stop
98 condition and re-enabling the epoll item need to be done
99 together as one atomic operation when EPOLL_CTL_DISABLE is
100 available: */
101 item_data = (struct epoll_item_private *)event_data.data.ptr;
102 pthread_mutex_lock(&item_data->mutex);
103
104 /* Remove the item from the epoll set if we want to stop
105 handling that event: */
106 if (item_data->stop)
107 delete_item(item_data->index);
108 else {
109 /* Clear the data that was written to the other end of
110 our non-blocking socket: */
111 do {
112 if (read(item_data->fd, &socket_data, 1) < 1) {
113 if ((errno == EAGAIN) ||
114 (errno == EWOULDBLOCK))
115 break;
116 else
117 goto error_unlock;
118 }
119 } while (item_data->events & EPOLLET);
120
121 /* The item was one-shot, so re-enable it: */
122 event_data.events = item_data->events;
123 if (epoll_ctl(thread_data->epoll_set,
124 EPOLL_CTL_MOD,
125 item_data->fd,
126 &event_data) < 0)
127 goto error_unlock;
128 }
129
130 pthread_mutex_unlock(&item_data->mutex);
131 }
132
133error_unlock:
134 thread_data->status = item_data->status = errno;
135 pthread_mutex_unlock(&item_data->mutex);
136 return 0;
137}
138
139/*
140 * A pointer to a write_thread_data structure will be passed as the argument to
141 * the write thread:
142 */
143struct write_thread_data {
144 int stop;
145 int status; /* Indicates any error encountered by the write thread. */
146 int n_fds;
147 int *fds;
148};
149
150/*
151 * The function executed by the write thread. It writes a single byte to each
152 * socket in turn until the stop condition for this thread is set. If writing to
153 * a socket would block (i.e. errno was EAGAIN), we leave that socket alone for
154 * the moment and just move on to the next socket in the list. We don't care
155 * about the order in which we deliver events to the epoll set. In fact we don't
156 * care about the data we're writing to the pipes at all; we just want to
157 * trigger epoll events:
158 */
159void *write_thread_function(void *function_data)
160{
161 const char data = 'X';
162 int index;
163 struct write_thread_data *thread_data =
164 (struct write_thread_data *)function_data;
165 while (!write_thread_data->stop)
166 for (index = 0;
167 !thread_data->stop && (index < thread_data->n_fds);
168 ++index)
169 if ((write(thread_data->fds[index], &data, 1) < 1) &&
170 (errno != EAGAIN) &&
171 (errno != EWOULDBLOCK)) {
172 write_thread_data->status = errno;
173 return;
174 }
175}
176
177/*
178 * Arguments are currently ignored:
179 */
180int main(int argc, char **argv)
181{
182 const int n_read_threads = 100;
183 const int n_epoll_items = 500;
184 int index;
185 int epoll_set = epoll_create1(0);
186 struct write_thread_data write_thread_data = {
187 0, 0, n_epoll_items, malloc(n_epoll_items * sizeof(int))
188 };
189 struct read_thread_data *read_thread_data =
190 malloc(n_read_threads * sizeof(struct read_thread_data));
191 pthread_t *read_threads = malloc(n_read_threads * sizeof(pthread_t));
192 pthread_t write_thread;
193
194 printf("-----------------\n");
195 printf("Runing test_epoll\n");
196 printf("-----------------\n");
197
198 epoll_items = malloc(n_epoll_items * sizeof(struct epoll_item_private));
199
200 if (epoll_set < 0 || epoll_items == 0 || write_thread_data.fds == 0 ||
201 read_thread_data == 0 || read_threads == 0)
202 goto error;
203
204 if (sysconf(_SC_NPROCESSORS_ONLN) < 2) {
205 printf("Error: please run this test on a multi-core system.\n");
206 goto error;
207 }
208
209 /* Create the socket pairs and epoll items: */
210 for (index = 0; index < n_epoll_items; ++index) {
211 int socket_pair[2];
212 struct epoll_event event_data;
213 if (socketpair(AF_UNIX,
214 SOCK_STREAM | SOCK_NONBLOCK,
215 0,
216 socket_pair) < 0)
217 goto error;
218 write_thread_data.fds[index] = socket_pair[0];
219 epoll_items[index].index = index;
220 epoll_items[index].fd = socket_pair[1];
221 if (pthread_mutex_init(&epoll_items[index].mutex, NULL) != 0)
222 goto error;
223 /* We always use EPOLLONESHOT because this test is currently
224 structured to demonstrate the need for EPOLL_CTL_DISABLE,
225 which only produces useful information in the EPOLLONESHOT
226 case (without EPOLLONESHOT, calling epoll_ctl with
227 EPOLL_CTL_DISABLE will never return EBUSY). If support for
228 testing events without EPOLLONESHOT is desired, it should
229 probably be implemented in a separate unit test. */
230 epoll_items[index].events = EPOLLIN | EPOLLONESHOT;
231 if (index < n_epoll_items / 2)
232 epoll_items[index].events |= EPOLLET;
233 epoll_items[index].stop = 0;
234 epoll_items[index].status = 0;
235 epoll_items[index].deleted = 0;
236 event_data.events = epoll_items[index].events;
237 event_data.data.ptr = &epoll_items[index];
238 if (epoll_ctl(epoll_set,
239 EPOLL_CTL_ADD,
240 epoll_items[index].fd,
241 &event_data) < 0)
242 goto error;
243 }
244
245 /* Create and start the read threads: */
246 for (index = 0; index < n_read_threads; ++index) {
247 read_thread_data[index].stop = 0;
248 read_thread_data[index].status = 0;
249 read_thread_data[index].epoll_set = epoll_set;
250 if (pthread_create(&read_threads[index],
251 NULL,
252 read_thread_function,
253 &read_thread_data[index]) != 0)
254 goto error;
255 }
256
257 if (pthread_create(&write_thread,
258 NULL,
259 write_thread_function,
260 &write_thread_data) != 0)
261 goto error;
262
263 /* Cancel all event pollers: */
264#ifdef EPOLL_CTL_DISABLE
265 for (index = 0; index < n_epoll_items; ++index) {
266 pthread_mutex_lock(&epoll_items[index].mutex);
267 ++epoll_items[index].stop;
268 if (epoll_ctl(epoll_set,
269 EPOLL_CTL_DISABLE,
270 epoll_items[index].fd,
271 NULL) == 0)
272 delete_item(index);
273 else if (errno != EBUSY) {
274 pthread_mutex_unlock(&epoll_items[index].mutex);
275 goto error;
276 }
277 /* EBUSY means events were being handled; allow the other thread
278 to delete the item. */
279 pthread_mutex_unlock(&epoll_items[index].mutex);
280 }
281#else
282 for (index = 0; index < n_epoll_items; ++index) {
283 pthread_mutex_lock(&epoll_items[index].mutex);
284 ++epoll_items[index].stop;
285 pthread_mutex_unlock(&epoll_items[index].mutex);
286 /* Wait in case a thread running read_thread_function is
287 currently executing code between epoll_wait and
288 pthread_mutex_lock with this item. Note that a longer delay
289 would make double-deletion less likely (at the expense of
290 performance), but there is no guarantee that any delay would
291 ever be sufficient. Note also that we delete all event
292 pollers at once for testing purposes, but in a real-world
293 environment we are likely to want to be able to cancel event
294 pollers at arbitrary times. Therefore we can't improve this
295 situation by just splitting this loop into two loops
296 (i.e. signal 'stop' for all items, sleep, and then delete all
297 items). We also can't fix the problem via EPOLL_CTL_DEL
298 because that command can't prevent the case where some other
299 thread is executing read_thread_function within the region
300 mentioned above: */
301 usleep(1);
302 pthread_mutex_lock(&epoll_items[index].mutex);
303 if (!epoll_items[index].deleted)
304 delete_item(index);
305 pthread_mutex_unlock(&epoll_items[index].mutex);
306 }
307#endif
308
309 /* Shut down the read threads: */
310 for (index = 0; index < n_read_threads; ++index)
311 __sync_fetch_and_add(&read_thread_data[index].stop, 1);
312 for (index = 0; index < n_read_threads; ++index) {
313 if (pthread_join(read_threads[index], NULL) != 0)
314 goto error;
315 if (read_thread_data[index].status)
316 goto error;
317 }
318
319 /* Shut down the write thread: */
320 __sync_fetch_and_add(&write_thread_data.stop, 1);
321 if ((pthread_join(write_thread, NULL) != 0) || write_thread_data.status)
322 goto error;
323
324 /* Check for final error conditions: */
325 for (index = 0; index < n_epoll_items; ++index) {
326 if (epoll_items[index].status != 0)
327 goto error;
328 if (pthread_mutex_destroy(&epoll_items[index].mutex) < 0)
329 goto error;
330 }
331 for (index = 0; index < n_epoll_items; ++index)
332 if (epoll_items[index].deleted != 1) {
333 printf("Error: item data deleted %1d times.\n",
334 epoll_items[index].deleted);
335 goto error;
336 }
337
338 printf("[PASS]\n");
339 return 0;
340
341 error:
342 printf("[FAIL]\n");
343 return errno;
344}
diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests
index 8b40bd5e5cc..4c53cae6c27 100644
--- a/tools/testing/selftests/vm/run_vmtests
+++ b/tools/testing/selftests/vm/run_vmtests
@@ -36,7 +36,7 @@ mkdir $mnt
36mount -t hugetlbfs none $mnt 36mount -t hugetlbfs none $mnt
37 37
38echo "--------------------" 38echo "--------------------"
39echo "runing hugepage-mmap" 39echo "running hugepage-mmap"
40echo "--------------------" 40echo "--------------------"
41./hugepage-mmap 41./hugepage-mmap
42if [ $? -ne 0 ]; then 42if [ $? -ne 0 ]; then
@@ -50,7 +50,7 @@ shmall=`cat /proc/sys/kernel/shmall`
50echo 268435456 > /proc/sys/kernel/shmmax 50echo 268435456 > /proc/sys/kernel/shmmax
51echo 4194304 > /proc/sys/kernel/shmall 51echo 4194304 > /proc/sys/kernel/shmall
52echo "--------------------" 52echo "--------------------"
53echo "runing hugepage-shm" 53echo "running hugepage-shm"
54echo "--------------------" 54echo "--------------------"
55./hugepage-shm 55./hugepage-shm
56if [ $? -ne 0 ]; then 56if [ $? -ne 0 ]; then
@@ -62,7 +62,7 @@ echo $shmmax > /proc/sys/kernel/shmmax
62echo $shmall > /proc/sys/kernel/shmall 62echo $shmall > /proc/sys/kernel/shmall
63 63
64echo "--------------------" 64echo "--------------------"
65echo "runing map_hugetlb" 65echo "running map_hugetlb"
66echo "--------------------" 66echo "--------------------"
67./map_hugetlb 67./map_hugetlb
68if [ $? -ne 0 ]; then 68if [ $? -ne 0 ]; then
diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c
index b0adb2710c0..68d0734b208 100644
--- a/tools/usb/testusb.c
+++ b/tools/usb/testusb.c
@@ -253,9 +253,6 @@ static int find_testdev(const char *name, const struct stat *sb, int flag)
253 253
254 if (flag != FTW_F) 254 if (flag != FTW_F)
255 return 0; 255 return 0;
256 /* ignore /proc/bus/usb/{devices,drivers} */
257 if (strrchr(name, '/')[1] == 'd')
258 return 0;
259 256
260 fd = fopen(name, "rb"); 257 fd = fopen(name, "rb");
261 if (!fd) { 258 if (!fd) {
@@ -356,28 +353,8 @@ restart:
356 353
357static const char *usbfs_dir_find(void) 354static const char *usbfs_dir_find(void)
358{ 355{
359 static char usbfs_path_0[] = "/dev/usb/devices";
360 static char usbfs_path_1[] = "/proc/bus/usb/devices";
361 static char udev_usb_path[] = "/dev/bus/usb"; 356 static char udev_usb_path[] = "/dev/bus/usb";
362 357
363 static char *const usbfs_paths[] = {
364 usbfs_path_0, usbfs_path_1
365 };
366
367 static char *const *
368 end = usbfs_paths + sizeof usbfs_paths / sizeof *usbfs_paths;
369
370 char *const *it = usbfs_paths;
371 do {
372 int fd = open(*it, O_RDONLY);
373 close(fd);
374 if (fd >= 0) {
375 strrchr(*it, '/')[0] = '\0';
376 return *it;
377 }
378 } while (++it != end);
379
380 /* real device-nodes managed by udev */
381 if (access(udev_usb_path, F_OK) == 0) 358 if (access(udev_usb_path, F_OK) == 0)
382 return udev_usb_path; 359 return udev_usb_path;
383 360
@@ -489,7 +466,7 @@ usage:
489 goto usage; 466 goto usage;
490 if (!all && !device) { 467 if (!all && !device) {
491 fprintf (stderr, "must specify '-a' or '-D dev', " 468 fprintf (stderr, "must specify '-a' or '-D dev', "
492 "or DEVICE=/proc/bus/usb/BBB/DDD in env\n"); 469 "or DEVICE=/dev/bus/usb/BBB/DDD in env\n");
493 goto usage; 470 goto usage;
494 } 471 }
495 472
diff --git a/tools/virtio/virtio-trace/Makefile b/tools/virtio/virtio-trace/Makefile
new file mode 100644
index 00000000000..0d238163347
--- /dev/null
+++ b/tools/virtio/virtio-trace/Makefile
@@ -0,0 +1,13 @@
1CC = gcc
2CFLAGS = -O2 -Wall -pthread
3
4all: trace-agent
5
6.c.o:
7 $(CC) $(CFLAGS) -c $^ -o $@
8
9trace-agent: trace-agent.o trace-agent-ctl.o trace-agent-rw.o
10 $(CC) $(CFLAGS) -o $@ $^
11
12clean:
13 rm -f *.o trace-agent
diff --git a/tools/virtio/virtio-trace/README b/tools/virtio/virtio-trace/README
new file mode 100644
index 00000000000..b64845b823a
--- /dev/null
+++ b/tools/virtio/virtio-trace/README
@@ -0,0 +1,118 @@
1Trace Agent for virtio-trace
2============================
3
4Trace agent is a user tool for sending trace data of a guest to a Host in low
5overhead. Trace agent has the following functions:
6 - splice a page of ring-buffer to read_pipe without memory copying
7 - splice the page from write_pipe to virtio-console without memory copying
8 - write trace data to stdout by using -o option
9 - controlled by start/stop orders from a Host
10
11The trace agent operates as follows:
12 1) Initialize all structures.
13 2) Create a read/write thread per CPU. Each thread is bound to a CPU.
14 The read/write threads hold it.
15 3) A controller thread does poll() for a start order of a host.
16 4) After the controller of the trace agent receives a start order from a host,
17 the controller wake read/write threads.
18 5) The read/write threads start to read trace data from ring-buffers and
19 write the data to virtio-serial.
20 6) If the controller receives a stop order from a host, the read/write threads
21 stop to read trace data.
22
23
24Files
25=====
26
27README: this file
28Makefile: Makefile of trace agent for virtio-trace
29trace-agent.c: includes main function, sets up for operating trace agent
30trace-agent.h: includes all structures and some macros
31trace-agent-ctl.c: includes controller function for read/write threads
32trace-agent-rw.c: includes read/write threads function
33
34
35Setup
36=====
37
38To use this trace agent for virtio-trace, we need to prepare some virtio-serial
39I/Fs.
40
411) Make FIFO in a host
42 virtio-trace uses virtio-serial pipe as trace data paths as to the number
43of CPUs and a control path, so FIFO (named pipe) should be created as follows:
44 # mkdir /tmp/virtio-trace/
45 # mkfifo /tmp/virtio-trace/trace-path-cpu{0,1,2,...,X}.{in,out}
46 # mkfifo /tmp/virtio-trace/agent-ctl-path.{in,out}
47
48For example, if a guest use three CPUs, the names are
49 trace-path-cpu{0,1,2}.{in.out}
50and
51 agent-ctl-path.{in,out}.
52
532) Set up of virtio-serial pipe in a host
54 Add qemu option to use virtio-serial pipe.
55
56 ##virtio-serial device##
57 -device virtio-serial-pci,id=virtio-serial0\
58 ##control path##
59 -chardev pipe,id=charchannel0,path=/tmp/virtio-trace/agent-ctl-path\
60 -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,\
61 id=channel0,name=agent-ctl-path\
62 ##data path##
63 -chardev pipe,id=charchannel1,path=/tmp/virtio-trace/trace-path-cpu0\
64 -device virtserialport,bus=virtio-serial0.0,nr=2,chardev=charchannel0,\
65 id=channel1,name=trace-path-cpu0\
66 ...
67
68If you manage guests with libvirt, add the following tags to domain XML files.
69Then, libvirt passes the same command option to qemu.
70
71 <channel type='pipe'>
72 <source path='/tmp/virtio-trace/agent-ctl-path'/>
73 <target type='virtio' name='agent-ctl-path'/>
74 <address type='virtio-serial' controller='0' bus='0' port='0'/>
75 </channel>
76 <channel type='pipe'>
77 <source path='/tmp/virtio-trace/trace-path-cpu0'/>
78 <target type='virtio' name='trace-path-cpu0'/>
79 <address type='virtio-serial' controller='0' bus='0' port='1'/>
80 </channel>
81 ...
82Here, chardev names are restricted to trace-path-cpuX and agent-ctl-path. For
83example, if a guest use three CPUs, chardev names should be trace-path-cpu0,
84trace-path-cpu1, trace-path-cpu2, and agent-ctl-path.
85
863) Boot the guest
87 You can find some chardev in /dev/virtio-ports/ in the guest.
88
89
90Run
91===
92
930) Build trace agent in a guest
94 $ make
95
961) Enable ftrace in the guest
97 <Example>
98 # echo 1 > /sys/kernel/debug/tracing/events/sched/enable
99
1002) Run trace agent in the guest
101 This agent must be operated as root.
102 # ./trace-agent
103read/write threads in the agent wait for start order from host. If you add -o
104option, trace data are output via stdout in the guest.
105
1063) Open FIFO in a host
107 # cat /tmp/virtio-trace/trace-path-cpu0.out
108If a host does not open these, trace data get stuck in buffers of virtio. Then,
109the guest will stop by specification of chardev in QEMU. This blocking mode may
110be solved in the future.
111
1124) Start to read trace data by ordering from a host
113 A host injects read start order to the guest via virtio-serial.
114 # echo 1 > /tmp/virtio-trace/agent-ctl-path.in
115
1165) Stop to read trace data by ordering from a host
117 A host injects read stop order to the guest via virtio-serial.
118 # echo 0 > /tmp/virtio-trace/agent-ctl-path.in
diff --git a/tools/virtio/virtio-trace/trace-agent-ctl.c b/tools/virtio/virtio-trace/trace-agent-ctl.c
new file mode 100644
index 00000000000..a2d0403c4f9
--- /dev/null
+++ b/tools/virtio/virtio-trace/trace-agent-ctl.c
@@ -0,0 +1,137 @@
1/*
2 * Controller of read/write threads for virtio-trace
3 *
4 * Copyright (C) 2012 Hitachi, Ltd.
5 * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
6 * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
7 *
8 * Licensed under GPL version 2 only.
9 *
10 */
11
12#define _GNU_SOURCE
13#include <fcntl.h>
14#include <poll.h>
15#include <signal.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <unistd.h>
19#include "trace-agent.h"
20
21#define HOST_MSG_SIZE 256
22#define EVENT_WAIT_MSEC 100
23
24static volatile sig_atomic_t global_signal_val;
25bool global_sig_receive; /* default false */
26bool global_run_operation; /* default false*/
27
28/* Handle SIGTERM/SIGINT/SIGQUIT to exit */
29static void signal_handler(int sig)
30{
31 global_signal_val = sig;
32}
33
34int rw_ctl_init(const char *ctl_path)
35{
36 int ctl_fd;
37
38 ctl_fd = open(ctl_path, O_RDONLY);
39 if (ctl_fd == -1) {
40 pr_err("Cannot open ctl_fd\n");
41 goto error;
42 }
43
44 return ctl_fd;
45
46error:
47 exit(EXIT_FAILURE);
48}
49
50static int wait_order(int ctl_fd)
51{
52 struct pollfd poll_fd;
53 int ret = 0;
54
55 while (!global_sig_receive) {
56 poll_fd.fd = ctl_fd;
57 poll_fd.events = POLLIN;
58
59 ret = poll(&poll_fd, 1, EVENT_WAIT_MSEC);
60
61 if (global_signal_val) {
62 global_sig_receive = true;
63 pr_info("Receive interrupt %d\n", global_signal_val);
64
65 /* Wakes rw-threads when they are sleeping */
66 if (!global_run_operation)
67 pthread_cond_broadcast(&cond_wakeup);
68
69 ret = -1;
70 break;
71 }
72
73 if (ret < 0) {
74 pr_err("Polling error\n");
75 goto error;
76 }
77
78 if (ret)
79 break;
80 };
81
82 return ret;
83
84error:
85 exit(EXIT_FAILURE);
86}
87
88/*
89 * contol read/write threads by handling global_run_operation
90 */
91void *rw_ctl_loop(int ctl_fd)
92{
93 ssize_t rlen;
94 char buf[HOST_MSG_SIZE];
95 int ret;
96
97 /* Setup signal handlers */
98 signal(SIGTERM, signal_handler);
99 signal(SIGINT, signal_handler);
100 signal(SIGQUIT, signal_handler);
101
102 while (!global_sig_receive) {
103
104 ret = wait_order(ctl_fd);
105 if (ret < 0)
106 break;
107
108 rlen = read(ctl_fd, buf, sizeof(buf));
109 if (rlen < 0) {
110 pr_err("read data error in ctl thread\n");
111 goto error;
112 }
113
114 if (rlen == 2 && buf[0] == '1') {
115 /*
116 * If host writes '1' to a control path,
117 * this controller wakes all read/write threads.
118 */
119 global_run_operation = true;
120 pthread_cond_broadcast(&cond_wakeup);
121 pr_debug("Wake up all read/write threads\n");
122 } else if (rlen == 2 && buf[0] == '0') {
123 /*
124 * If host writes '0' to a control path, read/write
125 * threads will wait for notification from Host.
126 */
127 global_run_operation = false;
128 pr_debug("Stop all read/write threads\n");
129 } else
130 pr_info("Invalid host notification: %s\n", buf);
131 }
132
133 return NULL;
134
135error:
136 exit(EXIT_FAILURE);
137}
diff --git a/tools/virtio/virtio-trace/trace-agent-rw.c b/tools/virtio/virtio-trace/trace-agent-rw.c
new file mode 100644
index 00000000000..3aace5ea484
--- /dev/null
+++ b/tools/virtio/virtio-trace/trace-agent-rw.c
@@ -0,0 +1,192 @@
1/*
2 * Read/write thread of a guest agent for virtio-trace
3 *
4 * Copyright (C) 2012 Hitachi, Ltd.
5 * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
6 * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
7 *
8 * Licensed under GPL version 2 only.
9 *
10 */
11
12#define _GNU_SOURCE
13#include <fcntl.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <unistd.h>
17#include <sys/syscall.h>
18#include "trace-agent.h"
19
20#define READ_WAIT_USEC 100000
21
22void *rw_thread_info_new(void)
23{
24 struct rw_thread_info *rw_ti;
25
26 rw_ti = zalloc(sizeof(struct rw_thread_info));
27 if (rw_ti == NULL) {
28 pr_err("rw_thread_info zalloc error\n");
29 exit(EXIT_FAILURE);
30 }
31
32 rw_ti->cpu_num = -1;
33 rw_ti->in_fd = -1;
34 rw_ti->out_fd = -1;
35 rw_ti->read_pipe = -1;
36 rw_ti->write_pipe = -1;
37 rw_ti->pipe_size = PIPE_INIT;
38
39 return rw_ti;
40}
41
42void *rw_thread_init(int cpu, const char *in_path, const char *out_path,
43 bool stdout_flag, unsigned long pipe_size,
44 struct rw_thread_info *rw_ti)
45{
46 int data_pipe[2];
47
48 rw_ti->cpu_num = cpu;
49
50 /* set read(input) fd */
51 rw_ti->in_fd = open(in_path, O_RDONLY);
52 if (rw_ti->in_fd == -1) {
53 pr_err("Could not open in_fd (CPU:%d)\n", cpu);
54 goto error;
55 }
56
57 /* set write(output) fd */
58 if (!stdout_flag) {
59 /* virtio-serial output mode */
60 rw_ti->out_fd = open(out_path, O_WRONLY);
61 if (rw_ti->out_fd == -1) {
62 pr_err("Could not open out_fd (CPU:%d)\n", cpu);
63 goto error;
64 }
65 } else
66 /* stdout mode */
67 rw_ti->out_fd = STDOUT_FILENO;
68
69 if (pipe2(data_pipe, O_NONBLOCK) < 0) {
70 pr_err("Could not create pipe in rw-thread(%d)\n", cpu);
71 goto error;
72 }
73
74 /*
75 * Size of pipe is 64kB in default based on fs/pipe.c.
76 * To read/write trace data speedy, pipe size is changed.
77 */
78 if (fcntl(*data_pipe, F_SETPIPE_SZ, pipe_size) < 0) {
79 pr_err("Could not change pipe size in rw-thread(%d)\n", cpu);
80 goto error;
81 }
82
83 rw_ti->read_pipe = data_pipe[1];
84 rw_ti->write_pipe = data_pipe[0];
85 rw_ti->pipe_size = pipe_size;
86
87 return NULL;
88
89error:
90 exit(EXIT_FAILURE);
91}
92
93/* Bind a thread to a cpu */
94static void bind_cpu(int cpu_num)
95{
96 cpu_set_t mask;
97
98 CPU_ZERO(&mask);
99 CPU_SET(cpu_num, &mask);
100
101 /* bind my thread to cpu_num by assigning zero to the first argument */
102 if (sched_setaffinity(0, sizeof(mask), &mask) == -1)
103 pr_err("Could not set CPU#%d affinity\n", (int)cpu_num);
104}
105
106static void *rw_thread_main(void *thread_info)
107{
108 ssize_t rlen, wlen;
109 ssize_t ret;
110 struct rw_thread_info *ts = (struct rw_thread_info *)thread_info;
111
112 bind_cpu(ts->cpu_num);
113
114 while (1) {
115 /* Wait for a read order of trace data by Host OS */
116 if (!global_run_operation) {
117 pthread_mutex_lock(&mutex_notify);
118 pthread_cond_wait(&cond_wakeup, &mutex_notify);
119 pthread_mutex_unlock(&mutex_notify);
120 }
121
122 if (global_sig_receive)
123 break;
124
125 /*
126 * Each thread read trace_pipe_raw of each cpu bounding the
127 * thread, so contention of multi-threads does not occur.
128 */
129 rlen = splice(ts->in_fd, NULL, ts->read_pipe, NULL,
130 ts->pipe_size, SPLICE_F_MOVE | SPLICE_F_MORE);
131
132 if (rlen < 0) {
133 pr_err("Splice_read in rw-thread(%d)\n", ts->cpu_num);
134 goto error;
135 } else if (rlen == 0) {
136 /*
137 * If trace data do not exist or are unreadable not
138 * for exceeding the page size, splice_read returns
139 * NULL. Then, this waits for being filled the data in a
140 * ring-buffer.
141 */
142 usleep(READ_WAIT_USEC);
143 pr_debug("Read retry(cpu:%d)\n", ts->cpu_num);
144 continue;
145 }
146
147 wlen = 0;
148
149 do {
150 ret = splice(ts->write_pipe, NULL, ts->out_fd, NULL,
151 rlen - wlen,
152 SPLICE_F_MOVE | SPLICE_F_MORE);
153
154 if (ret < 0) {
155 pr_err("Splice_write in rw-thread(%d)\n",
156 ts->cpu_num);
157 goto error;
158 } else if (ret == 0)
159 /*
160 * When host reader is not in time for reading
161 * trace data, guest will be stopped. This is
162 * because char dev in QEMU is not supported
163 * non-blocking mode. Then, writer might be
164 * sleep in that case.
165 * This sleep will be removed by supporting
166 * non-blocking mode.
167 */
168 sleep(1);
169 wlen += ret;
170 } while (wlen < rlen);
171 }
172
173 return NULL;
174
175error:
176 exit(EXIT_FAILURE);
177}
178
179
180pthread_t rw_thread_run(struct rw_thread_info *rw_ti)
181{
182 int ret;
183 pthread_t rw_thread_per_cpu;
184
185 ret = pthread_create(&rw_thread_per_cpu, NULL, rw_thread_main, rw_ti);
186 if (ret != 0) {
187 pr_err("Could not create a rw thread(%d)\n", rw_ti->cpu_num);
188 exit(EXIT_FAILURE);
189 }
190
191 return rw_thread_per_cpu;
192}
diff --git a/tools/virtio/virtio-trace/trace-agent.c b/tools/virtio/virtio-trace/trace-agent.c
new file mode 100644
index 00000000000..0a0a7dd4eff
--- /dev/null
+++ b/tools/virtio/virtio-trace/trace-agent.c
@@ -0,0 +1,270 @@
1/*
2 * Guest agent for virtio-trace
3 *
4 * Copyright (C) 2012 Hitachi, Ltd.
5 * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
6 * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
7 *
8 * Licensed under GPL version 2 only.
9 *
10 */
11
12#define _GNU_SOURCE
13#include <limits.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <unistd.h>
17#include "trace-agent.h"
18
19#define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
20#define PIPE_DEF_BUFS 16
21#define PIPE_MIN_SIZE (PAGE_SIZE*PIPE_DEF_BUFS)
22#define PIPE_MAX_SIZE (1024*1024)
23#define READ_PATH_FMT \
24 "/sys/kernel/debug/tracing/per_cpu/cpu%d/trace_pipe_raw"
25#define WRITE_PATH_FMT "/dev/virtio-ports/trace-path-cpu%d"
26#define CTL_PATH "/dev/virtio-ports/agent-ctl-path"
27
28pthread_mutex_t mutex_notify = PTHREAD_MUTEX_INITIALIZER;
29pthread_cond_t cond_wakeup = PTHREAD_COND_INITIALIZER;
30
31static int get_total_cpus(void)
32{
33 int nr_cpus = (int)sysconf(_SC_NPROCESSORS_CONF);
34
35 if (nr_cpus <= 0) {
36 pr_err("Could not read cpus\n");
37 goto error;
38 } else if (nr_cpus > MAX_CPUS) {
39 pr_err("Exceed max cpus(%d)\n", (int)MAX_CPUS);
40 goto error;
41 }
42
43 return nr_cpus;
44
45error:
46 exit(EXIT_FAILURE);
47}
48
49static void *agent_info_new(void)
50{
51 struct agent_info *s;
52 int i;
53
54 s = zalloc(sizeof(struct agent_info));
55 if (s == NULL) {
56 pr_err("agent_info zalloc error\n");
57 exit(EXIT_FAILURE);
58 }
59
60 s->pipe_size = PIPE_INIT;
61 s->use_stdout = false;
62 s->cpus = get_total_cpus();
63 s->ctl_fd = -1;
64
65 /* read/write threads init */
66 for (i = 0; i < s->cpus; i++)
67 s->rw_ti[i] = rw_thread_info_new();
68
69 return s;
70}
71
72static unsigned long parse_size(const char *arg)
73{
74 unsigned long value, round;
75 char *ptr;
76
77 value = strtoul(arg, &ptr, 10);
78 switch (*ptr) {
79 case 'K': case 'k':
80 value <<= 10;
81 break;
82 case 'M': case 'm':
83 value <<= 20;
84 break;
85 default:
86 break;
87 }
88
89 if (value > PIPE_MAX_SIZE) {
90 pr_err("Pipe size must be less than 1MB\n");
91 goto error;
92 } else if (value < PIPE_MIN_SIZE) {
93 pr_err("Pipe size must be over 64KB\n");
94 goto error;
95 }
96
97 /* Align buffer size with page unit */
98 round = value & (PAGE_SIZE - 1);
99 value = value - round;
100
101 return value;
102error:
103 return 0;
104}
105
106static void usage(char const *prg)
107{
108 pr_err("usage: %s [-h] [-o] [-s <size of pipe>]\n", prg);
109}
110
111static const char *make_path(int cpu_num, bool this_is_write_path)
112{
113 int ret;
114 char *buf;
115
116 buf = zalloc(PATH_MAX);
117 if (buf == NULL) {
118 pr_err("Could not allocate buffer\n");
119 goto error;
120 }
121
122 if (this_is_write_path)
123 /* write(output) path */
124 ret = snprintf(buf, PATH_MAX, WRITE_PATH_FMT, cpu_num);
125 else
126 /* read(input) path */
127 ret = snprintf(buf, PATH_MAX, READ_PATH_FMT, cpu_num);
128
129 if (ret <= 0) {
130 pr_err("Failed to generate %s path(CPU#%d):%d\n",
131 this_is_write_path ? "read" : "write", cpu_num, ret);
132 goto error;
133 }
134
135 return buf;
136
137error:
138 free(buf);
139 return NULL;
140}
141
142static const char *make_input_path(int cpu_num)
143{
144 return make_path(cpu_num, false);
145}
146
147static const char *make_output_path(int cpu_num)
148{
149 return make_path(cpu_num, true);
150}
151
152static void *agent_info_init(struct agent_info *s)
153{
154 int cpu;
155 const char *in_path = NULL;
156 const char *out_path = NULL;
157
158 /* init read/write threads */
159 for (cpu = 0; cpu < s->cpus; cpu++) {
160 /* set read(input) path per read/write thread */
161 in_path = make_input_path(cpu);
162 if (in_path == NULL)
163 goto error;
164
165 /* set write(output) path per read/write thread*/
166 if (!s->use_stdout) {
167 out_path = make_output_path(cpu);
168 if (out_path == NULL)
169 goto error;
170 } else
171 /* stdout mode */
172 pr_debug("stdout mode\n");
173
174 rw_thread_init(cpu, in_path, out_path, s->use_stdout,
175 s->pipe_size, s->rw_ti[cpu]);
176 }
177
178 /* init controller of read/write threads */
179 s->ctl_fd = rw_ctl_init((const char *)CTL_PATH);
180
181 return NULL;
182
183error:
184 exit(EXIT_FAILURE);
185}
186
187static void *parse_args(int argc, char *argv[], struct agent_info *s)
188{
189 int cmd;
190 unsigned long size;
191
192 while ((cmd = getopt(argc, argv, "hos:")) != -1) {
193 switch (cmd) {
194 /* stdout mode */
195 case 'o':
196 s->use_stdout = true;
197 break;
198 /* size of pipe */
199 case 's':
200 size = parse_size(optarg);
201 if (size == 0)
202 goto error;
203 s->pipe_size = size;
204 break;
205 case 'h':
206 default:
207 usage(argv[0]);
208 goto error;
209 }
210 }
211
212 agent_info_init(s);
213
214 return NULL;
215
216error:
217 exit(EXIT_FAILURE);
218}
219
220static void agent_main_loop(struct agent_info *s)
221{
222 int cpu;
223 pthread_t rw_thread_per_cpu[MAX_CPUS];
224
225 /* Start all read/write threads */
226 for (cpu = 0; cpu < s->cpus; cpu++)
227 rw_thread_per_cpu[cpu] = rw_thread_run(s->rw_ti[cpu]);
228
229 rw_ctl_loop(s->ctl_fd);
230
231 /* Finish all read/write threads */
232 for (cpu = 0; cpu < s->cpus; cpu++) {
233 int ret;
234
235 ret = pthread_join(rw_thread_per_cpu[cpu], NULL);
236 if (ret != 0) {
237 pr_err("pthread_join() error:%d (cpu %d)\n", ret, cpu);
238 exit(EXIT_FAILURE);
239 }
240 }
241}
242
243static void agent_info_free(struct agent_info *s)
244{
245 int i;
246
247 close(s->ctl_fd);
248 for (i = 0; i < s->cpus; i++) {
249 close(s->rw_ti[i]->in_fd);
250 close(s->rw_ti[i]->out_fd);
251 close(s->rw_ti[i]->read_pipe);
252 close(s->rw_ti[i]->write_pipe);
253 free(s->rw_ti[i]);
254 }
255 free(s);
256}
257
258int main(int argc, char *argv[])
259{
260 struct agent_info *s = NULL;
261
262 s = agent_info_new();
263 parse_args(argc, argv, s);
264
265 agent_main_loop(s);
266
267 agent_info_free(s);
268
269 return 0;
270}
diff --git a/tools/virtio/virtio-trace/trace-agent.h b/tools/virtio/virtio-trace/trace-agent.h
new file mode 100644
index 00000000000..8de79bfeaa7
--- /dev/null
+++ b/tools/virtio/virtio-trace/trace-agent.h
@@ -0,0 +1,75 @@
1#ifndef __TRACE_AGENT_H__
2#define __TRACE_AGENT_H__
3#include <pthread.h>
4#include <stdbool.h>
5
6#define MAX_CPUS 256
7#define PIPE_INIT (1024*1024)
8
9/*
10 * agent_info - structure managing total information of guest agent
11 * @pipe_size: size of pipe (default 1MB)
12 * @use_stdout: set to true when o option is added (default false)
13 * @cpus: total number of CPUs
14 * @ctl_fd: fd of control path, /dev/virtio-ports/agent-ctl-path
15 * @rw_ti: structure managing information of read/write threads
16 */
17struct agent_info {
18 unsigned long pipe_size;
19 bool use_stdout;
20 int cpus;
21 int ctl_fd;
22 struct rw_thread_info *rw_ti[MAX_CPUS];
23};
24
25/*
26 * rw_thread_info - structure managing a read/write thread a cpu
27 * @cpu_num: cpu number operating this read/write thread
28 * @in_fd: fd of reading trace data path in cpu_num
29 * @out_fd: fd of writing trace data path in cpu_num
30 * @read_pipe: fd of read pipe
31 * @write_pipe: fd of write pipe
32 * @pipe_size: size of pipe (default 1MB)
33 */
34struct rw_thread_info {
35 int cpu_num;
36 int in_fd;
37 int out_fd;
38 int read_pipe;
39 int write_pipe;
40 unsigned long pipe_size;
41};
42
43/* use for stopping rw threads */
44extern bool global_sig_receive;
45
46/* use for notification */
47extern bool global_run_operation;
48extern pthread_mutex_t mutex_notify;
49extern pthread_cond_t cond_wakeup;
50
51/* for controller of read/write threads */
52extern int rw_ctl_init(const char *ctl_path);
53extern void *rw_ctl_loop(int ctl_fd);
54
55/* for trace read/write thread */
56extern void *rw_thread_info_new(void);
57extern void *rw_thread_init(int cpu, const char *in_path, const char *out_path,
58 bool stdout_flag, unsigned long pipe_size,
59 struct rw_thread_info *rw_ti);
60extern pthread_t rw_thread_run(struct rw_thread_info *rw_ti);
61
62static inline void *zalloc(size_t size)
63{
64 return calloc(1, size);
65}
66
67#define pr_err(format, ...) fprintf(stderr, format, ## __VA_ARGS__)
68#define pr_info(format, ...) fprintf(stdout, format, ## __VA_ARGS__)
69#ifdef DEBUG
70#define pr_debug(format, ...) fprintf(stderr, format, ## __VA_ARGS__)
71#else
72#define pr_debug(format, ...) do {} while (0)
73#endif
74
75#endif /*__TRACE_AGENT_H__*/
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c
index f576971f655..cd1b03e8089 100644
--- a/tools/vm/page-types.c
+++ b/tools/vm/page-types.c
@@ -34,7 +34,7 @@
34#include <sys/fcntl.h> 34#include <sys/fcntl.h>
35#include <sys/mount.h> 35#include <sys/mount.h>
36#include <sys/statfs.h> 36#include <sys/statfs.h>
37#include "../../include/linux/magic.h" 37#include "../../include/uapi/linux/magic.h"
38#include "../../include/linux/kernel-page-flags.h" 38#include "../../include/linux/kernel-page-flags.h"
39 39
40 40