diff options
Diffstat (limited to 'tools')
282 files changed, 7583 insertions, 3670 deletions
diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c index 8f96b3ee0724..f437d739f37d 100644 --- a/tools/hv/hv_fcopy_daemon.c +++ b/tools/hv/hv_fcopy_daemon.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <sys/stat.h> | 33 | #include <sys/stat.h> |
34 | #include <fcntl.h> | 34 | #include <fcntl.h> |
35 | #include <dirent.h> | 35 | #include <dirent.h> |
36 | #include <getopt.h> | ||
36 | 37 | ||
37 | static int target_fd; | 38 | static int target_fd; |
38 | static char target_fname[W_MAX_PATH]; | 39 | static char target_fname[W_MAX_PATH]; |
@@ -126,15 +127,43 @@ static int hv_copy_cancel(void) | |||
126 | 127 | ||
127 | } | 128 | } |
128 | 129 | ||
129 | int main(void) | 130 | void print_usage(char *argv[]) |
131 | { | ||
132 | fprintf(stderr, "Usage: %s [options]\n" | ||
133 | "Options are:\n" | ||
134 | " -n, --no-daemon stay in foreground, don't daemonize\n" | ||
135 | " -h, --help print this help\n", argv[0]); | ||
136 | } | ||
137 | |||
138 | int main(int argc, char *argv[]) | ||
130 | { | 139 | { |
131 | int fd, fcopy_fd, len; | 140 | int fd, fcopy_fd, len; |
132 | int error; | 141 | int error; |
142 | int daemonize = 1, long_index = 0, opt; | ||
133 | int version = FCOPY_CURRENT_VERSION; | 143 | int version = FCOPY_CURRENT_VERSION; |
134 | char *buffer[4096 * 2]; | 144 | char *buffer[4096 * 2]; |
135 | struct hv_fcopy_hdr *in_msg; | 145 | struct hv_fcopy_hdr *in_msg; |
136 | 146 | ||
137 | if (daemon(1, 0)) { | 147 | static struct option long_options[] = { |
148 | {"help", no_argument, 0, 'h' }, | ||
149 | {"no-daemon", no_argument, 0, 'n' }, | ||
150 | {0, 0, 0, 0 } | ||
151 | }; | ||
152 | |||
153 | while ((opt = getopt_long(argc, argv, "hn", long_options, | ||
154 | &long_index)) != -1) { | ||
155 | switch (opt) { | ||
156 | case 'n': | ||
157 | daemonize = 0; | ||
158 | break; | ||
159 | case 'h': | ||
160 | default: | ||
161 | print_usage(argv); | ||
162 | exit(EXIT_FAILURE); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | if (daemonize && daemon(1, 0)) { | ||
138 | syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno)); | 167 | syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno)); |
139 | exit(EXIT_FAILURE); | 168 | exit(EXIT_FAILURE); |
140 | } | 169 | } |
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 4088b816a3ee..6a6432a20a1d 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <fcntl.h> | 43 | #include <fcntl.h> |
44 | #include <dirent.h> | 44 | #include <dirent.h> |
45 | #include <net/if.h> | 45 | #include <net/if.h> |
46 | #include <getopt.h> | ||
46 | 47 | ||
47 | /* | 48 | /* |
48 | * KVP protocol: The user mode component first registers with the | 49 | * KVP protocol: The user mode component first registers with the |
@@ -1417,7 +1418,15 @@ netlink_send(int fd, struct cn_msg *msg) | |||
1417 | return sendmsg(fd, &message, 0); | 1418 | return sendmsg(fd, &message, 0); |
1418 | } | 1419 | } |
1419 | 1420 | ||
1420 | int main(void) | 1421 | void print_usage(char *argv[]) |
1422 | { | ||
1423 | fprintf(stderr, "Usage: %s [options]\n" | ||
1424 | "Options are:\n" | ||
1425 | " -n, --no-daemon stay in foreground, don't daemonize\n" | ||
1426 | " -h, --help print this help\n", argv[0]); | ||
1427 | } | ||
1428 | |||
1429 | int main(int argc, char *argv[]) | ||
1421 | { | 1430 | { |
1422 | int fd, len, nl_group; | 1431 | int fd, len, nl_group; |
1423 | int error; | 1432 | int error; |
@@ -1435,9 +1444,30 @@ int main(void) | |||
1435 | struct hv_kvp_ipaddr_value *kvp_ip_val; | 1444 | struct hv_kvp_ipaddr_value *kvp_ip_val; |
1436 | char *kvp_recv_buffer; | 1445 | char *kvp_recv_buffer; |
1437 | size_t kvp_recv_buffer_len; | 1446 | size_t kvp_recv_buffer_len; |
1447 | int daemonize = 1, long_index = 0, opt; | ||
1448 | |||
1449 | static struct option long_options[] = { | ||
1450 | {"help", no_argument, 0, 'h' }, | ||
1451 | {"no-daemon", no_argument, 0, 'n' }, | ||
1452 | {0, 0, 0, 0 } | ||
1453 | }; | ||
1454 | |||
1455 | while ((opt = getopt_long(argc, argv, "hn", long_options, | ||
1456 | &long_index)) != -1) { | ||
1457 | switch (opt) { | ||
1458 | case 'n': | ||
1459 | daemonize = 0; | ||
1460 | break; | ||
1461 | case 'h': | ||
1462 | default: | ||
1463 | print_usage(argv); | ||
1464 | exit(EXIT_FAILURE); | ||
1465 | } | ||
1466 | } | ||
1438 | 1467 | ||
1439 | if (daemon(1, 0)) | 1468 | if (daemonize && daemon(1, 0)) |
1440 | return 1; | 1469 | return 1; |
1470 | |||
1441 | openlog("KVP", 0, LOG_USER); | 1471 | openlog("KVP", 0, LOG_USER); |
1442 | syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); | 1472 | syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); |
1443 | 1473 | ||
@@ -1529,8 +1559,15 @@ int main(void) | |||
1529 | addr_p, &addr_l); | 1559 | addr_p, &addr_l); |
1530 | 1560 | ||
1531 | if (len < 0) { | 1561 | if (len < 0) { |
1562 | int saved_errno = errno; | ||
1532 | syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s", | 1563 | syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s", |
1533 | addr.nl_pid, errno, strerror(errno)); | 1564 | addr.nl_pid, errno, strerror(errno)); |
1565 | |||
1566 | if (saved_errno == ENOBUFS) { | ||
1567 | syslog(LOG_ERR, "receive error: ignored"); | ||
1568 | continue; | ||
1569 | } | ||
1570 | |||
1534 | close(fd); | 1571 | close(fd); |
1535 | return -1; | 1572 | return -1; |
1536 | } | 1573 | } |
@@ -1733,8 +1770,15 @@ kvp_done: | |||
1733 | 1770 | ||
1734 | len = netlink_send(fd, incoming_cn_msg); | 1771 | len = netlink_send(fd, incoming_cn_msg); |
1735 | if (len < 0) { | 1772 | if (len < 0) { |
1773 | int saved_errno = errno; | ||
1736 | syslog(LOG_ERR, "net_link send failed; error: %d %s", errno, | 1774 | syslog(LOG_ERR, "net_link send failed; error: %d %s", errno, |
1737 | strerror(errno)); | 1775 | strerror(errno)); |
1776 | |||
1777 | if (saved_errno == ENOMEM || saved_errno == ENOBUFS) { | ||
1778 | syslog(LOG_ERR, "send error: ignored"); | ||
1779 | continue; | ||
1780 | } | ||
1781 | |||
1738 | exit(EXIT_FAILURE); | 1782 | exit(EXIT_FAILURE); |
1739 | } | 1783 | } |
1740 | } | 1784 | } |
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c index 6a213b8cd7b9..5e63f70bd956 100644 --- a/tools/hv/hv_vss_daemon.c +++ b/tools/hv/hv_vss_daemon.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/hyperv.h> | 36 | #include <linux/hyperv.h> |
37 | #include <linux/netlink.h> | 37 | #include <linux/netlink.h> |
38 | #include <syslog.h> | 38 | #include <syslog.h> |
39 | #include <getopt.h> | ||
39 | 40 | ||
40 | static struct sockaddr_nl addr; | 41 | static struct sockaddr_nl addr; |
41 | 42 | ||
@@ -44,35 +45,51 @@ static struct sockaddr_nl addr; | |||
44 | #endif | 45 | #endif |
45 | 46 | ||
46 | 47 | ||
47 | static int vss_do_freeze(char *dir, unsigned int cmd, char *fs_op) | 48 | /* Don't use syslog() in the function since that can cause write to disk */ |
49 | static int vss_do_freeze(char *dir, unsigned int cmd) | ||
48 | { | 50 | { |
49 | int ret, fd = open(dir, O_RDONLY); | 51 | int ret, fd = open(dir, O_RDONLY); |
50 | 52 | ||
51 | if (fd < 0) | 53 | if (fd < 0) |
52 | return 1; | 54 | return 1; |
55 | |||
53 | ret = ioctl(fd, cmd, 0); | 56 | ret = ioctl(fd, cmd, 0); |
54 | syslog(LOG_INFO, "VSS: %s of %s: %s\n", fs_op, dir, strerror(errno)); | 57 | |
58 | /* | ||
59 | * If a partition is mounted more than once, only the first | ||
60 | * FREEZE/THAW can succeed and the later ones will get | ||
61 | * EBUSY/EINVAL respectively: there could be 2 cases: | ||
62 | * 1) a user may mount the same partition to differnt directories | ||
63 | * by mistake or on purpose; | ||
64 | * 2) The subvolume of btrfs appears to have the same partition | ||
65 | * mounted more than once. | ||
66 | */ | ||
67 | if (ret) { | ||
68 | if ((cmd == FIFREEZE && errno == EBUSY) || | ||
69 | (cmd == FITHAW && errno == EINVAL)) { | ||
70 | close(fd); | ||
71 | return 0; | ||
72 | } | ||
73 | } | ||
74 | |||
55 | close(fd); | 75 | close(fd); |
56 | return !!ret; | 76 | return !!ret; |
57 | } | 77 | } |
58 | 78 | ||
59 | static int vss_operate(int operation) | 79 | static int vss_operate(int operation) |
60 | { | 80 | { |
61 | char *fs_op; | ||
62 | char match[] = "/dev/"; | 81 | char match[] = "/dev/"; |
63 | FILE *mounts; | 82 | FILE *mounts; |
64 | struct mntent *ent; | 83 | struct mntent *ent; |
65 | unsigned int cmd; | 84 | unsigned int cmd; |
66 | int error = 0, root_seen = 0; | 85 | int error = 0, root_seen = 0, save_errno = 0; |
67 | 86 | ||
68 | switch (operation) { | 87 | switch (operation) { |
69 | case VSS_OP_FREEZE: | 88 | case VSS_OP_FREEZE: |
70 | cmd = FIFREEZE; | 89 | cmd = FIFREEZE; |
71 | fs_op = "freeze"; | ||
72 | break; | 90 | break; |
73 | case VSS_OP_THAW: | 91 | case VSS_OP_THAW: |
74 | cmd = FITHAW; | 92 | cmd = FITHAW; |
75 | fs_op = "thaw"; | ||
76 | break; | 93 | break; |
77 | default: | 94 | default: |
78 | return -1; | 95 | return -1; |
@@ -85,7 +102,7 @@ static int vss_operate(int operation) | |||
85 | while ((ent = getmntent(mounts))) { | 102 | while ((ent = getmntent(mounts))) { |
86 | if (strncmp(ent->mnt_fsname, match, strlen(match))) | 103 | if (strncmp(ent->mnt_fsname, match, strlen(match))) |
87 | continue; | 104 | continue; |
88 | if (strcmp(ent->mnt_type, "iso9660") == 0) | 105 | if (hasmntopt(ent, MNTOPT_RO) != NULL) |
89 | continue; | 106 | continue; |
90 | if (strcmp(ent->mnt_type, "vfat") == 0) | 107 | if (strcmp(ent->mnt_type, "vfat") == 0) |
91 | continue; | 108 | continue; |
@@ -93,14 +110,30 @@ static int vss_operate(int operation) | |||
93 | root_seen = 1; | 110 | root_seen = 1; |
94 | continue; | 111 | continue; |
95 | } | 112 | } |
96 | error |= vss_do_freeze(ent->mnt_dir, cmd, fs_op); | 113 | error |= vss_do_freeze(ent->mnt_dir, cmd); |
114 | if (error && operation == VSS_OP_FREEZE) | ||
115 | goto err; | ||
97 | } | 116 | } |
98 | endmntent(mounts); | ||
99 | 117 | ||
100 | if (root_seen) { | 118 | if (root_seen) { |
101 | error |= vss_do_freeze("/", cmd, fs_op); | 119 | error |= vss_do_freeze("/", cmd); |
120 | if (error && operation == VSS_OP_FREEZE) | ||
121 | goto err; | ||
102 | } | 122 | } |
103 | 123 | ||
124 | goto out; | ||
125 | err: | ||
126 | save_errno = errno; | ||
127 | vss_operate(VSS_OP_THAW); | ||
128 | /* Call syslog after we thaw all filesystems */ | ||
129 | if (ent) | ||
130 | syslog(LOG_ERR, "FREEZE of %s failed; error:%d %s", | ||
131 | ent->mnt_dir, save_errno, strerror(save_errno)); | ||
132 | else | ||
133 | syslog(LOG_ERR, "FREEZE of / failed; error:%d %s", save_errno, | ||
134 | strerror(save_errno)); | ||
135 | out: | ||
136 | endmntent(mounts); | ||
104 | return error; | 137 | return error; |
105 | } | 138 | } |
106 | 139 | ||
@@ -131,7 +164,15 @@ static int netlink_send(int fd, struct cn_msg *msg) | |||
131 | return sendmsg(fd, &message, 0); | 164 | return sendmsg(fd, &message, 0); |
132 | } | 165 | } |
133 | 166 | ||
134 | int main(void) | 167 | void print_usage(char *argv[]) |
168 | { | ||
169 | fprintf(stderr, "Usage: %s [options]\n" | ||
170 | "Options are:\n" | ||
171 | " -n, --no-daemon stay in foreground, don't daemonize\n" | ||
172 | " -h, --help print this help\n", argv[0]); | ||
173 | } | ||
174 | |||
175 | int main(int argc, char *argv[]) | ||
135 | { | 176 | { |
136 | int fd, len, nl_group; | 177 | int fd, len, nl_group; |
137 | int error; | 178 | int error; |
@@ -143,8 +184,28 @@ int main(void) | |||
143 | struct hv_vss_msg *vss_msg; | 184 | struct hv_vss_msg *vss_msg; |
144 | char *vss_recv_buffer; | 185 | char *vss_recv_buffer; |
145 | size_t vss_recv_buffer_len; | 186 | size_t vss_recv_buffer_len; |
187 | int daemonize = 1, long_index = 0, opt; | ||
188 | |||
189 | static struct option long_options[] = { | ||
190 | {"help", no_argument, 0, 'h' }, | ||
191 | {"no-daemon", no_argument, 0, 'n' }, | ||
192 | {0, 0, 0, 0 } | ||
193 | }; | ||
194 | |||
195 | while ((opt = getopt_long(argc, argv, "hn", long_options, | ||
196 | &long_index)) != -1) { | ||
197 | switch (opt) { | ||
198 | case 'n': | ||
199 | daemonize = 0; | ||
200 | break; | ||
201 | case 'h': | ||
202 | default: | ||
203 | print_usage(argv); | ||
204 | exit(EXIT_FAILURE); | ||
205 | } | ||
206 | } | ||
146 | 207 | ||
147 | if (daemon(1, 0)) | 208 | if (daemonize && daemon(1, 0)) |
148 | return 1; | 209 | return 1; |
149 | 210 | ||
150 | openlog("Hyper-V VSS", 0, LOG_USER); | 211 | openlog("Hyper-V VSS", 0, LOG_USER); |
@@ -249,8 +310,16 @@ int main(void) | |||
249 | case VSS_OP_FREEZE: | 310 | case VSS_OP_FREEZE: |
250 | case VSS_OP_THAW: | 311 | case VSS_OP_THAW: |
251 | error = vss_operate(op); | 312 | error = vss_operate(op); |
252 | if (error) | 313 | syslog(LOG_INFO, "VSS: op=%s: %s\n", |
314 | op == VSS_OP_FREEZE ? "FREEZE" : "THAW", | ||
315 | error ? "failed" : "succeeded"); | ||
316 | |||
317 | if (error) { | ||
253 | error = HV_E_FAIL; | 318 | error = HV_E_FAIL; |
319 | syslog(LOG_ERR, "op=%d failed!", op); | ||
320 | syslog(LOG_ERR, "report it with these files:"); | ||
321 | syslog(LOG_ERR, "/etc/fstab and /proc/mounts"); | ||
322 | } | ||
254 | break; | 323 | break; |
255 | default: | 324 | default: |
256 | syslog(LOG_ERR, "Illegal op:%d\n", op); | 325 | syslog(LOG_ERR, "Illegal op:%d\n", op); |
diff --git a/tools/include/asm-generic/bitops.h b/tools/include/asm-generic/bitops.h new file mode 100644 index 000000000000..653d1bad77de --- /dev/null +++ b/tools/include/asm-generic/bitops.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #ifndef __TOOLS_ASM_GENERIC_BITOPS_H | ||
2 | #define __TOOLS_ASM_GENERIC_BITOPS_H | ||
3 | |||
4 | /* | ||
5 | * tools/ copied this from include/asm-generic/bitops.h, bit by bit as it needed | ||
6 | * some functions. | ||
7 | * | ||
8 | * For the benefit of those who are trying to port Linux to another | ||
9 | * architecture, here are some C-language equivalents. You should | ||
10 | * recode these in the native assembly language, if at all possible. | ||
11 | * | ||
12 | * C language equivalents written by Theodore Ts'o, 9/26/92 | ||
13 | */ | ||
14 | |||
15 | #include <asm-generic/bitops/__ffs.h> | ||
16 | #include <asm-generic/bitops/fls.h> | ||
17 | #include <asm-generic/bitops/__fls.h> | ||
18 | #include <asm-generic/bitops/fls64.h> | ||
19 | #include <asm-generic/bitops/find.h> | ||
20 | |||
21 | #ifndef _TOOLS_LINUX_BITOPS_H_ | ||
22 | #error only <linux/bitops.h> can be included directly | ||
23 | #endif | ||
24 | |||
25 | #include <asm-generic/bitops/hweight.h> | ||
26 | |||
27 | #include <asm-generic/bitops/atomic.h> | ||
28 | |||
29 | #endif /* __TOOLS_ASM_GENERIC_BITOPS_H */ | ||
diff --git a/tools/include/asm-generic/bitops/__ffs.h b/tools/include/asm-generic/bitops/__ffs.h new file mode 100644 index 000000000000..c94175015a82 --- /dev/null +++ b/tools/include/asm-generic/bitops/__ffs.h | |||
@@ -0,0 +1,43 @@ | |||
1 | #ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_ | ||
2 | #define _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_ | ||
3 | |||
4 | #include <asm/types.h> | ||
5 | |||
6 | /** | ||
7 | * __ffs - find first bit in word. | ||
8 | * @word: The word to search | ||
9 | * | ||
10 | * Undefined if no bit exists, so code should check against 0 first. | ||
11 | */ | ||
12 | static __always_inline unsigned long __ffs(unsigned long word) | ||
13 | { | ||
14 | int num = 0; | ||
15 | |||
16 | #if __BITS_PER_LONG == 64 | ||
17 | if ((word & 0xffffffff) == 0) { | ||
18 | num += 32; | ||
19 | word >>= 32; | ||
20 | } | ||
21 | #endif | ||
22 | if ((word & 0xffff) == 0) { | ||
23 | num += 16; | ||
24 | word >>= 16; | ||
25 | } | ||
26 | if ((word & 0xff) == 0) { | ||
27 | num += 8; | ||
28 | word >>= 8; | ||
29 | } | ||
30 | if ((word & 0xf) == 0) { | ||
31 | num += 4; | ||
32 | word >>= 4; | ||
33 | } | ||
34 | if ((word & 0x3) == 0) { | ||
35 | num += 2; | ||
36 | word >>= 2; | ||
37 | } | ||
38 | if ((word & 0x1) == 0) | ||
39 | num += 1; | ||
40 | return num; | ||
41 | } | ||
42 | |||
43 | #endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_ */ | ||
diff --git a/tools/include/asm-generic/bitops/__fls.h b/tools/include/asm-generic/bitops/__fls.h new file mode 100644 index 000000000000..2218b9add4c1 --- /dev/null +++ b/tools/include/asm-generic/bitops/__fls.h | |||
@@ -0,0 +1 @@ | |||
#include <../../../../include/asm-generic/bitops/__fls.h> | |||
diff --git a/tools/include/asm-generic/bitops/arch_hweight.h b/tools/include/asm-generic/bitops/arch_hweight.h new file mode 100644 index 000000000000..318bb2b202b0 --- /dev/null +++ b/tools/include/asm-generic/bitops/arch_hweight.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../../include/asm-generic/bitops/arch_hweight.h" | |||
diff --git a/tools/include/asm-generic/bitops/atomic.h b/tools/include/asm-generic/bitops/atomic.h new file mode 100644 index 000000000000..4bccd7c3d5d6 --- /dev/null +++ b/tools/include/asm-generic/bitops/atomic.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_ | ||
2 | #define _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_ | ||
3 | |||
4 | #include <asm/types.h> | ||
5 | |||
6 | static inline void set_bit(int nr, unsigned long *addr) | ||
7 | { | ||
8 | addr[nr / __BITS_PER_LONG] |= 1UL << (nr % __BITS_PER_LONG); | ||
9 | } | ||
10 | |||
11 | static inline void clear_bit(int nr, unsigned long *addr) | ||
12 | { | ||
13 | addr[nr / __BITS_PER_LONG] &= ~(1UL << (nr % __BITS_PER_LONG)); | ||
14 | } | ||
15 | |||
16 | static __always_inline int test_bit(unsigned int nr, const unsigned long *addr) | ||
17 | { | ||
18 | return ((1UL << (nr % __BITS_PER_LONG)) & | ||
19 | (((unsigned long *)addr)[nr / __BITS_PER_LONG])) != 0; | ||
20 | } | ||
21 | |||
22 | #endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_ */ | ||
diff --git a/tools/include/asm-generic/bitops/const_hweight.h b/tools/include/asm-generic/bitops/const_hweight.h new file mode 100644 index 000000000000..0afd644aff83 --- /dev/null +++ b/tools/include/asm-generic/bitops/const_hweight.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../../include/asm-generic/bitops/const_hweight.h" | |||
diff --git a/tools/include/asm-generic/bitops/find.h b/tools/include/asm-generic/bitops/find.h new file mode 100644 index 000000000000..31f51547fcd4 --- /dev/null +++ b/tools/include/asm-generic/bitops/find.h | |||
@@ -0,0 +1,33 @@ | |||
1 | #ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ | ||
2 | #define _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ | ||
3 | |||
4 | #ifndef find_next_bit | ||
5 | /** | ||
6 | * find_next_bit - find the next set bit in a memory region | ||
7 | * @addr: The address to base the search on | ||
8 | * @offset: The bitnumber to start searching at | ||
9 | * @size: The bitmap size in bits | ||
10 | * | ||
11 | * Returns the bit number for the next set bit | ||
12 | * If no bits are set, returns @size. | ||
13 | */ | ||
14 | extern unsigned long find_next_bit(const unsigned long *addr, unsigned long | ||
15 | size, unsigned long offset); | ||
16 | #endif | ||
17 | |||
18 | #ifndef find_first_bit | ||
19 | |||
20 | /** | ||
21 | * find_first_bit - find the first set bit in a memory region | ||
22 | * @addr: The address to start the search at | ||
23 | * @size: The maximum number of bits to search | ||
24 | * | ||
25 | * Returns the bit number of the first set bit. | ||
26 | * If no bits are set, returns @size. | ||
27 | */ | ||
28 | extern unsigned long find_first_bit(const unsigned long *addr, | ||
29 | unsigned long size); | ||
30 | |||
31 | #endif /* find_first_bit */ | ||
32 | |||
33 | #endif /*_TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ */ | ||
diff --git a/tools/include/asm-generic/bitops/fls.h b/tools/include/asm-generic/bitops/fls.h new file mode 100644 index 000000000000..dbf711a28f71 --- /dev/null +++ b/tools/include/asm-generic/bitops/fls.h | |||
@@ -0,0 +1 @@ | |||
#include <../../../../include/asm-generic/bitops/fls.h> | |||
diff --git a/tools/include/asm-generic/bitops/fls64.h b/tools/include/asm-generic/bitops/fls64.h new file mode 100644 index 000000000000..980b1f63c047 --- /dev/null +++ b/tools/include/asm-generic/bitops/fls64.h | |||
@@ -0,0 +1 @@ | |||
#include <../../../../include/asm-generic/bitops/fls64.h> | |||
diff --git a/tools/include/asm-generic/bitops/hweight.h b/tools/include/asm-generic/bitops/hweight.h new file mode 100644 index 000000000000..290120c01a8e --- /dev/null +++ b/tools/include/asm-generic/bitops/hweight.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_ | ||
2 | #define _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_ | ||
3 | |||
4 | #include <asm-generic/bitops/arch_hweight.h> | ||
5 | #include <asm-generic/bitops/const_hweight.h> | ||
6 | |||
7 | #endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_ */ | ||
diff --git a/tools/include/linux/bitops.h b/tools/include/linux/bitops.h new file mode 100644 index 000000000000..5ad9ee1dd7f6 --- /dev/null +++ b/tools/include/linux/bitops.h | |||
@@ -0,0 +1,58 @@ | |||
1 | #ifndef _TOOLS_LINUX_BITOPS_H_ | ||
2 | #define _TOOLS_LINUX_BITOPS_H_ | ||
3 | |||
4 | #include <asm/types.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/compiler.h> | ||
7 | |||
8 | #ifndef __WORDSIZE | ||
9 | #define __WORDSIZE (__SIZEOF_LONG__ * 8) | ||
10 | #endif | ||
11 | |||
12 | #define BITS_PER_LONG __WORDSIZE | ||
13 | |||
14 | #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) | ||
15 | #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) | ||
16 | #define BITS_PER_BYTE 8 | ||
17 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) | ||
18 | #define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64)) | ||
19 | #define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32)) | ||
20 | #define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE) | ||
21 | |||
22 | extern unsigned int __sw_hweight8(unsigned int w); | ||
23 | extern unsigned int __sw_hweight16(unsigned int w); | ||
24 | extern unsigned int __sw_hweight32(unsigned int w); | ||
25 | extern unsigned long __sw_hweight64(__u64 w); | ||
26 | |||
27 | /* | ||
28 | * Include this here because some architectures need generic_ffs/fls in | ||
29 | * scope | ||
30 | * | ||
31 | * XXX: this needs to be asm/bitops.h, when we get to per arch optimizations | ||
32 | */ | ||
33 | #include <asm-generic/bitops.h> | ||
34 | |||
35 | #define for_each_set_bit(bit, addr, size) \ | ||
36 | for ((bit) = find_first_bit((addr), (size)); \ | ||
37 | (bit) < (size); \ | ||
38 | (bit) = find_next_bit((addr), (size), (bit) + 1)) | ||
39 | |||
40 | /* same as for_each_set_bit() but use bit as value to start with */ | ||
41 | #define for_each_set_bit_from(bit, addr, size) \ | ||
42 | for ((bit) = find_next_bit((addr), (size), (bit)); \ | ||
43 | (bit) < (size); \ | ||
44 | (bit) = find_next_bit((addr), (size), (bit) + 1)) | ||
45 | |||
46 | static inline unsigned long hweight_long(unsigned long w) | ||
47 | { | ||
48 | return sizeof(w) == 4 ? hweight32(w) : hweight64(w); | ||
49 | } | ||
50 | |||
51 | static inline unsigned fls_long(unsigned long l) | ||
52 | { | ||
53 | if (sizeof(l) == 4) | ||
54 | return fls(l); | ||
55 | return fls64(l); | ||
56 | } | ||
57 | |||
58 | #endif | ||
diff --git a/tools/include/linux/log2.h b/tools/include/linux/log2.h new file mode 100644 index 000000000000..41446668ccce --- /dev/null +++ b/tools/include/linux/log2.h | |||
@@ -0,0 +1,185 @@ | |||
1 | /* Integer base 2 logarithm calculation | ||
2 | * | ||
3 | * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _TOOLS_LINUX_LOG2_H | ||
13 | #define _TOOLS_LINUX_LOG2_H | ||
14 | |||
15 | /* | ||
16 | * deal with unrepresentable constant logarithms | ||
17 | */ | ||
18 | extern __attribute__((const, noreturn)) | ||
19 | int ____ilog2_NaN(void); | ||
20 | |||
21 | /* | ||
22 | * non-constant log of base 2 calculators | ||
23 | * - the arch may override these in asm/bitops.h if they can be implemented | ||
24 | * more efficiently than using fls() and fls64() | ||
25 | * - the arch is not required to handle n==0 if implementing the fallback | ||
26 | */ | ||
27 | static inline __attribute__((const)) | ||
28 | int __ilog2_u32(u32 n) | ||
29 | { | ||
30 | return fls(n) - 1; | ||
31 | } | ||
32 | |||
33 | static inline __attribute__((const)) | ||
34 | int __ilog2_u64(u64 n) | ||
35 | { | ||
36 | return fls64(n) - 1; | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * Determine whether some value is a power of two, where zero is | ||
41 | * *not* considered a power of two. | ||
42 | */ | ||
43 | |||
44 | static inline __attribute__((const)) | ||
45 | bool is_power_of_2(unsigned long n) | ||
46 | { | ||
47 | return (n != 0 && ((n & (n - 1)) == 0)); | ||
48 | } | ||
49 | |||
50 | /* | ||
51 | * round up to nearest power of two | ||
52 | */ | ||
53 | static inline __attribute__((const)) | ||
54 | unsigned long __roundup_pow_of_two(unsigned long n) | ||
55 | { | ||
56 | return 1UL << fls_long(n - 1); | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * round down to nearest power of two | ||
61 | */ | ||
62 | static inline __attribute__((const)) | ||
63 | unsigned long __rounddown_pow_of_two(unsigned long n) | ||
64 | { | ||
65 | return 1UL << (fls_long(n) - 1); | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value | ||
70 | * @n - parameter | ||
71 | * | ||
72 | * constant-capable log of base 2 calculation | ||
73 | * - this can be used to initialise global variables from constant data, hence | ||
74 | * the massive ternary operator construction | ||
75 | * | ||
76 | * selects the appropriately-sized optimised version depending on sizeof(n) | ||
77 | */ | ||
78 | #define ilog2(n) \ | ||
79 | ( \ | ||
80 | __builtin_constant_p(n) ? ( \ | ||
81 | (n) < 1 ? ____ilog2_NaN() : \ | ||
82 | (n) & (1ULL << 63) ? 63 : \ | ||
83 | (n) & (1ULL << 62) ? 62 : \ | ||
84 | (n) & (1ULL << 61) ? 61 : \ | ||
85 | (n) & (1ULL << 60) ? 60 : \ | ||
86 | (n) & (1ULL << 59) ? 59 : \ | ||
87 | (n) & (1ULL << 58) ? 58 : \ | ||
88 | (n) & (1ULL << 57) ? 57 : \ | ||
89 | (n) & (1ULL << 56) ? 56 : \ | ||
90 | (n) & (1ULL << 55) ? 55 : \ | ||
91 | (n) & (1ULL << 54) ? 54 : \ | ||
92 | (n) & (1ULL << 53) ? 53 : \ | ||
93 | (n) & (1ULL << 52) ? 52 : \ | ||
94 | (n) & (1ULL << 51) ? 51 : \ | ||
95 | (n) & (1ULL << 50) ? 50 : \ | ||
96 | (n) & (1ULL << 49) ? 49 : \ | ||
97 | (n) & (1ULL << 48) ? 48 : \ | ||
98 | (n) & (1ULL << 47) ? 47 : \ | ||
99 | (n) & (1ULL << 46) ? 46 : \ | ||
100 | (n) & (1ULL << 45) ? 45 : \ | ||
101 | (n) & (1ULL << 44) ? 44 : \ | ||
102 | (n) & (1ULL << 43) ? 43 : \ | ||
103 | (n) & (1ULL << 42) ? 42 : \ | ||
104 | (n) & (1ULL << 41) ? 41 : \ | ||
105 | (n) & (1ULL << 40) ? 40 : \ | ||
106 | (n) & (1ULL << 39) ? 39 : \ | ||
107 | (n) & (1ULL << 38) ? 38 : \ | ||
108 | (n) & (1ULL << 37) ? 37 : \ | ||
109 | (n) & (1ULL << 36) ? 36 : \ | ||
110 | (n) & (1ULL << 35) ? 35 : \ | ||
111 | (n) & (1ULL << 34) ? 34 : \ | ||
112 | (n) & (1ULL << 33) ? 33 : \ | ||
113 | (n) & (1ULL << 32) ? 32 : \ | ||
114 | (n) & (1ULL << 31) ? 31 : \ | ||
115 | (n) & (1ULL << 30) ? 30 : \ | ||
116 | (n) & (1ULL << 29) ? 29 : \ | ||
117 | (n) & (1ULL << 28) ? 28 : \ | ||
118 | (n) & (1ULL << 27) ? 27 : \ | ||
119 | (n) & (1ULL << 26) ? 26 : \ | ||
120 | (n) & (1ULL << 25) ? 25 : \ | ||
121 | (n) & (1ULL << 24) ? 24 : \ | ||
122 | (n) & (1ULL << 23) ? 23 : \ | ||
123 | (n) & (1ULL << 22) ? 22 : \ | ||
124 | (n) & (1ULL << 21) ? 21 : \ | ||
125 | (n) & (1ULL << 20) ? 20 : \ | ||
126 | (n) & (1ULL << 19) ? 19 : \ | ||
127 | (n) & (1ULL << 18) ? 18 : \ | ||
128 | (n) & (1ULL << 17) ? 17 : \ | ||
129 | (n) & (1ULL << 16) ? 16 : \ | ||
130 | (n) & (1ULL << 15) ? 15 : \ | ||
131 | (n) & (1ULL << 14) ? 14 : \ | ||
132 | (n) & (1ULL << 13) ? 13 : \ | ||
133 | (n) & (1ULL << 12) ? 12 : \ | ||
134 | (n) & (1ULL << 11) ? 11 : \ | ||
135 | (n) & (1ULL << 10) ? 10 : \ | ||
136 | (n) & (1ULL << 9) ? 9 : \ | ||
137 | (n) & (1ULL << 8) ? 8 : \ | ||
138 | (n) & (1ULL << 7) ? 7 : \ | ||
139 | (n) & (1ULL << 6) ? 6 : \ | ||
140 | (n) & (1ULL << 5) ? 5 : \ | ||
141 | (n) & (1ULL << 4) ? 4 : \ | ||
142 | (n) & (1ULL << 3) ? 3 : \ | ||
143 | (n) & (1ULL << 2) ? 2 : \ | ||
144 | (n) & (1ULL << 1) ? 1 : \ | ||
145 | (n) & (1ULL << 0) ? 0 : \ | ||
146 | ____ilog2_NaN() \ | ||
147 | ) : \ | ||
148 | (sizeof(n) <= 4) ? \ | ||
149 | __ilog2_u32(n) : \ | ||
150 | __ilog2_u64(n) \ | ||
151 | ) | ||
152 | |||
153 | /** | ||
154 | * roundup_pow_of_two - round the given value up to nearest power of two | ||
155 | * @n - parameter | ||
156 | * | ||
157 | * round the given value up to the nearest power of two | ||
158 | * - the result is undefined when n == 0 | ||
159 | * - this can be used to initialise global variables from constant data | ||
160 | */ | ||
161 | #define roundup_pow_of_two(n) \ | ||
162 | ( \ | ||
163 | __builtin_constant_p(n) ? ( \ | ||
164 | (n == 1) ? 1 : \ | ||
165 | (1UL << (ilog2((n) - 1) + 1)) \ | ||
166 | ) : \ | ||
167 | __roundup_pow_of_two(n) \ | ||
168 | ) | ||
169 | |||
170 | /** | ||
171 | * rounddown_pow_of_two - round the given value down to nearest power of two | ||
172 | * @n - parameter | ||
173 | * | ||
174 | * round the given value down to the nearest power of two | ||
175 | * - the result is undefined when n == 0 | ||
176 | * - this can be used to initialise global variables from constant data | ||
177 | */ | ||
178 | #define rounddown_pow_of_two(n) \ | ||
179 | ( \ | ||
180 | __builtin_constant_p(n) ? ( \ | ||
181 | (1UL << ilog2(n))) : \ | ||
182 | __rounddown_pow_of_two(n) \ | ||
183 | ) | ||
184 | |||
185 | #endif /* _TOOLS_LINUX_LOG2_H */ | ||
diff --git a/tools/lib/api/fs/debugfs.c b/tools/lib/api/fs/debugfs.c index a74fba6d7743..86ea2d7b8845 100644 --- a/tools/lib/api/fs/debugfs.c +++ b/tools/lib/api/fs/debugfs.c | |||
@@ -67,7 +67,7 @@ int debugfs_valid_mountpoint(const char *debugfs) | |||
67 | 67 | ||
68 | if (statfs(debugfs, &st_fs) < 0) | 68 | if (statfs(debugfs, &st_fs) < 0) |
69 | return -ENOENT; | 69 | return -ENOENT; |
70 | else if (st_fs.f_type != (long) DEBUGFS_MAGIC) | 70 | else if ((long)st_fs.f_type != (long)DEBUGFS_MAGIC) |
71 | return -ENOENT; | 71 | return -ENOENT; |
72 | 72 | ||
73 | return 0; | 73 | return 0; |
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c index c1b49c36a951..128ef6332a6b 100644 --- a/tools/lib/api/fs/fs.c +++ b/tools/lib/api/fs/fs.c | |||
@@ -7,6 +7,10 @@ | |||
7 | #include <stdlib.h> | 7 | #include <stdlib.h> |
8 | #include <string.h> | 8 | #include <string.h> |
9 | #include <sys/vfs.h> | 9 | #include <sys/vfs.h> |
10 | #include <sys/types.h> | ||
11 | #include <sys/stat.h> | ||
12 | #include <fcntl.h> | ||
13 | #include <unistd.h> | ||
10 | 14 | ||
11 | #include "debugfs.h" | 15 | #include "debugfs.h" |
12 | #include "fs.h" | 16 | #include "fs.h" |
@@ -75,7 +79,7 @@ static int fs__valid_mount(const char *fs, long magic) | |||
75 | 79 | ||
76 | if (statfs(fs, &st_fs) < 0) | 80 | if (statfs(fs, &st_fs) < 0) |
77 | return -ENOENT; | 81 | return -ENOENT; |
78 | else if (st_fs.f_type != magic) | 82 | else if ((long)st_fs.f_type != magic) |
79 | return -ENOENT; | 83 | return -ENOENT; |
80 | 84 | ||
81 | return 0; | 85 | return 0; |
@@ -163,3 +167,33 @@ const char *name##__mountpoint(void) \ | |||
163 | 167 | ||
164 | FS__MOUNTPOINT(sysfs, FS__SYSFS); | 168 | FS__MOUNTPOINT(sysfs, FS__SYSFS); |
165 | FS__MOUNTPOINT(procfs, FS__PROCFS); | 169 | FS__MOUNTPOINT(procfs, FS__PROCFS); |
170 | |||
171 | int filename__read_int(const char *filename, int *value) | ||
172 | { | ||
173 | char line[64]; | ||
174 | int fd = open(filename, O_RDONLY), err = -1; | ||
175 | |||
176 | if (fd < 0) | ||
177 | return -1; | ||
178 | |||
179 | if (read(fd, line, sizeof(line)) > 0) { | ||
180 | *value = atoi(line); | ||
181 | err = 0; | ||
182 | } | ||
183 | |||
184 | close(fd); | ||
185 | return err; | ||
186 | } | ||
187 | |||
188 | int sysctl__read_int(const char *sysctl, int *value) | ||
189 | { | ||
190 | char path[PATH_MAX]; | ||
191 | const char *procfs = procfs__mountpoint(); | ||
192 | |||
193 | if (!procfs) | ||
194 | return -1; | ||
195 | |||
196 | snprintf(path, sizeof(path), "%s/sys/%s", procfs, sysctl); | ||
197 | |||
198 | return filename__read_int(path, value); | ||
199 | } | ||
diff --git a/tools/lib/api/fs/fs.h b/tools/lib/api/fs/fs.h index cb7049551f33..6caa2bbc6cec 100644 --- a/tools/lib/api/fs/fs.h +++ b/tools/lib/api/fs/fs.h | |||
@@ -11,4 +11,7 @@ | |||
11 | 11 | ||
12 | const char *sysfs__mountpoint(void); | 12 | const char *sysfs__mountpoint(void); |
13 | const char *procfs__mountpoint(void); | 13 | const char *procfs__mountpoint(void); |
14 | |||
15 | int filename__read_int(const char *filename, int *value); | ||
16 | int sysctl__read_int(const char *sysctl, int *value); | ||
14 | #endif /* __API_FS__ */ | 17 | #endif /* __API_FS__ */ |
diff --git a/tools/lib/lockdep/preload.c b/tools/lib/lockdep/preload.c index 6f803609e498..0b0112c80f22 100644 --- a/tools/lib/lockdep/preload.c +++ b/tools/lib/lockdep/preload.c | |||
@@ -317,7 +317,7 @@ int pthread_mutex_destroy(pthread_mutex_t *mutex) | |||
317 | * | 317 | * |
318 | * TODO: Hook into free() and add that check there as well. | 318 | * TODO: Hook into free() and add that check there as well. |
319 | */ | 319 | */ |
320 | debug_check_no_locks_freed(mutex, mutex + sizeof(*mutex)); | 320 | debug_check_no_locks_freed(mutex, sizeof(*mutex)); |
321 | __del_lock(__get_lock(mutex)); | 321 | __del_lock(__get_lock(mutex)); |
322 | return ll_pthread_mutex_destroy(mutex); | 322 | return ll_pthread_mutex_destroy(mutex); |
323 | } | 323 | } |
@@ -341,7 +341,7 @@ int pthread_rwlock_destroy(pthread_rwlock_t *rwlock) | |||
341 | { | 341 | { |
342 | try_init_preload(); | 342 | try_init_preload(); |
343 | 343 | ||
344 | debug_check_no_locks_freed(rwlock, rwlock + sizeof(*rwlock)); | 344 | debug_check_no_locks_freed(rwlock, sizeof(*rwlock)); |
345 | __del_lock(__get_lock(rwlock)); | 345 | __del_lock(__get_lock(rwlock)); |
346 | return ll_pthread_rwlock_destroy(rwlock); | 346 | return ll_pthread_rwlock_destroy(rwlock); |
347 | } | 347 | } |
diff --git a/tools/lib/traceevent/plugin_scsi.c b/tools/lib/traceevent/plugin_scsi.c index eda326fc8620..3727de48c8d5 100644 --- a/tools/lib/traceevent/plugin_scsi.c +++ b/tools/lib/traceevent/plugin_scsi.c | |||
@@ -85,8 +85,9 @@ typedef unsigned int u32; | |||
85 | #define MOVE_MEDIUM 0xa5 | 85 | #define MOVE_MEDIUM 0xa5 |
86 | #define EXCHANGE_MEDIUM 0xa6 | 86 | #define EXCHANGE_MEDIUM 0xa6 |
87 | #define READ_12 0xa8 | 87 | #define READ_12 0xa8 |
88 | #define SERVICE_ACTION_OUT_12 0xa9 | ||
88 | #define WRITE_12 0xaa | 89 | #define WRITE_12 0xaa |
89 | #define READ_MEDIA_SERIAL_NUMBER 0xab | 90 | #define SERVICE_ACTION_IN_12 0xab |
90 | #define WRITE_VERIFY_12 0xae | 91 | #define WRITE_VERIFY_12 0xae |
91 | #define VERIFY_12 0xaf | 92 | #define VERIFY_12 0xaf |
92 | #define SEARCH_HIGH_12 0xb0 | 93 | #define SEARCH_HIGH_12 0xb0 |
@@ -107,7 +108,9 @@ typedef unsigned int u32; | |||
107 | #define VERIFY_16 0x8f | 108 | #define VERIFY_16 0x8f |
108 | #define SYNCHRONIZE_CACHE_16 0x91 | 109 | #define SYNCHRONIZE_CACHE_16 0x91 |
109 | #define WRITE_SAME_16 0x93 | 110 | #define WRITE_SAME_16 0x93 |
110 | #define SERVICE_ACTION_IN 0x9e | 111 | #define SERVICE_ACTION_BIDIRECTIONAL 0x9d |
112 | #define SERVICE_ACTION_IN_16 0x9e | ||
113 | #define SERVICE_ACTION_OUT_16 0x9f | ||
111 | /* values for service action in */ | 114 | /* values for service action in */ |
112 | #define SAI_READ_CAPACITY_16 0x10 | 115 | #define SAI_READ_CAPACITY_16 0x10 |
113 | #define SAI_GET_LBA_STATUS 0x12 | 116 | #define SAI_GET_LBA_STATUS 0x12 |
@@ -393,7 +396,7 @@ scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len) | |||
393 | return scsi_trace_rw16(p, cdb, len); | 396 | return scsi_trace_rw16(p, cdb, len); |
394 | case UNMAP: | 397 | case UNMAP: |
395 | return scsi_trace_unmap(p, cdb, len); | 398 | return scsi_trace_unmap(p, cdb, len); |
396 | case SERVICE_ACTION_IN: | 399 | case SERVICE_ACTION_IN_16: |
397 | return scsi_trace_service_action_in(p, cdb, len); | 400 | return scsi_trace_service_action_in(p, cdb, len); |
398 | case VARIABLE_LENGTH_CMD: | 401 | case VARIABLE_LENGTH_CMD: |
399 | return scsi_trace_varlen(p, cdb, len); | 402 | return scsi_trace_varlen(p, cdb, len); |
diff --git a/tools/lib/util/find_next_bit.c b/tools/lib/util/find_next_bit.c new file mode 100644 index 000000000000..41b44f65a79e --- /dev/null +++ b/tools/lib/util/find_next_bit.c | |||
@@ -0,0 +1,89 @@ | |||
1 | /* find_next_bit.c: fallback find next bit implementation | ||
2 | * | ||
3 | * Copied from lib/find_next_bit.c to tools/lib/next_bit.c | ||
4 | * | ||
5 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | ||
6 | * Written by David Howells (dhowells@redhat.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/bitops.h> | ||
15 | #include <asm/types.h> | ||
16 | #include <asm/byteorder.h> | ||
17 | |||
18 | #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) | ||
19 | |||
20 | #ifndef find_next_bit | ||
21 | /* | ||
22 | * Find the next set bit in a memory region. | ||
23 | */ | ||
24 | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, | ||
25 | unsigned long offset) | ||
26 | { | ||
27 | const unsigned long *p = addr + BITOP_WORD(offset); | ||
28 | unsigned long result = offset & ~(BITS_PER_LONG-1); | ||
29 | unsigned long tmp; | ||
30 | |||
31 | if (offset >= size) | ||
32 | return size; | ||
33 | size -= result; | ||
34 | offset %= BITS_PER_LONG; | ||
35 | if (offset) { | ||
36 | tmp = *(p++); | ||
37 | tmp &= (~0UL << offset); | ||
38 | if (size < BITS_PER_LONG) | ||
39 | goto found_first; | ||
40 | if (tmp) | ||
41 | goto found_middle; | ||
42 | size -= BITS_PER_LONG; | ||
43 | result += BITS_PER_LONG; | ||
44 | } | ||
45 | while (size & ~(BITS_PER_LONG-1)) { | ||
46 | if ((tmp = *(p++))) | ||
47 | goto found_middle; | ||
48 | result += BITS_PER_LONG; | ||
49 | size -= BITS_PER_LONG; | ||
50 | } | ||
51 | if (!size) | ||
52 | return result; | ||
53 | tmp = *p; | ||
54 | |||
55 | found_first: | ||
56 | tmp &= (~0UL >> (BITS_PER_LONG - size)); | ||
57 | if (tmp == 0UL) /* Are any bits set? */ | ||
58 | return result + size; /* Nope. */ | ||
59 | found_middle: | ||
60 | return result + __ffs(tmp); | ||
61 | } | ||
62 | #endif | ||
63 | |||
64 | #ifndef find_first_bit | ||
65 | /* | ||
66 | * Find the first set bit in a memory region. | ||
67 | */ | ||
68 | unsigned long find_first_bit(const unsigned long *addr, unsigned long size) | ||
69 | { | ||
70 | const unsigned long *p = addr; | ||
71 | unsigned long result = 0; | ||
72 | unsigned long tmp; | ||
73 | |||
74 | while (size & ~(BITS_PER_LONG-1)) { | ||
75 | if ((tmp = *(p++))) | ||
76 | goto found; | ||
77 | result += BITS_PER_LONG; | ||
78 | size -= BITS_PER_LONG; | ||
79 | } | ||
80 | if (!size) | ||
81 | return result; | ||
82 | |||
83 | tmp = (*p) & (~0UL >> (BITS_PER_LONG - size)); | ||
84 | if (tmp == 0UL) /* Are any bits set? */ | ||
85 | return result + size; /* Nope. */ | ||
86 | found: | ||
87 | return result + __ffs(tmp); | ||
88 | } | ||
89 | #endif | ||
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore index 717221e98450..40399c3d97d6 100644 --- a/tools/perf/.gitignore +++ b/tools/perf/.gitignore | |||
@@ -2,6 +2,8 @@ PERF-CFLAGS | |||
2 | PERF-GUI-VARS | 2 | PERF-GUI-VARS |
3 | PERF-VERSION-FILE | 3 | PERF-VERSION-FILE |
4 | perf | 4 | perf |
5 | perf-read-vdso32 | ||
6 | perf-read-vdsox32 | ||
5 | perf-help | 7 | perf-help |
6 | perf-record | 8 | perf-record |
7 | perf-report | 9 | perf-report |
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 398f8d53bd6d..af9a54ece024 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
@@ -214,6 +214,12 @@ if combined with -a or -C options. | |||
214 | After starting the program, wait msecs before measuring. This is useful to | 214 | After starting the program, wait msecs before measuring. This is useful to |
215 | filter out the startup phase of the program, which is often very different. | 215 | filter out the startup phase of the program, which is often very different. |
216 | 216 | ||
217 | -I:: | ||
218 | --intr-regs:: | ||
219 | Capture machine state (registers) at interrupt, i.e., on counter overflows for | ||
220 | each sample. List of captured registers depends on the architecture. This option | ||
221 | is off by default. | ||
222 | |||
217 | SEE ALSO | 223 | SEE ALSO |
218 | -------- | 224 | -------- |
219 | linkperf:perf-stat[1], linkperf:perf-list[1] | 225 | linkperf:perf-stat[1], linkperf:perf-list[1] |
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 0927bf4e6c2a..dd7cccdde498 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
@@ -159,7 +159,7 @@ OPTIONS | |||
159 | --dump-raw-trace:: | 159 | --dump-raw-trace:: |
160 | Dump raw trace in ASCII. | 160 | Dump raw trace in ASCII. |
161 | 161 | ||
162 | -g [type,min[,limit],order[,key]]:: | 162 | -g [type,min[,limit],order[,key][,branch]]:: |
163 | --call-graph:: | 163 | --call-graph:: |
164 | Display call chains using type, min percent threshold, optional print | 164 | Display call chains using type, min percent threshold, optional print |
165 | limit and order. | 165 | limit and order. |
@@ -177,6 +177,11 @@ OPTIONS | |||
177 | - function: compare on functions | 177 | - function: compare on functions |
178 | - address: compare on individual code addresses | 178 | - address: compare on individual code addresses |
179 | 179 | ||
180 | branch can be: | ||
181 | - branch: include last branch information in callgraph | ||
182 | when available. Usually more convenient to use --branch-history | ||
183 | for this. | ||
184 | |||
180 | Default: fractal,0.5,callee,function. | 185 | Default: fractal,0.5,callee,function. |
181 | 186 | ||
182 | --children:: | 187 | --children:: |
@@ -266,6 +271,11 @@ OPTIONS | |||
266 | branch stacks and it will automatically switch to the branch view mode, | 271 | branch stacks and it will automatically switch to the branch view mode, |
267 | unless --no-branch-stack is used. | 272 | unless --no-branch-stack is used. |
268 | 273 | ||
274 | --branch-history:: | ||
275 | Add the addresses of sampled taken branches to the callstack. | ||
276 | This allows to examine the path the program took to each sample. | ||
277 | The data collection must have used -b (or -j) and -g. | ||
278 | |||
269 | --objdump=<path>:: | 279 | --objdump=<path>:: |
270 | Path to objdump binary. | 280 | Path to objdump binary. |
271 | 281 | ||
diff --git a/tools/perf/Documentation/perf.txt b/tools/perf/Documentation/perf.txt index d240bb2e5b22..1e8e400b4493 100644 --- a/tools/perf/Documentation/perf.txt +++ b/tools/perf/Documentation/perf.txt | |||
@@ -18,6 +18,10 @@ OPTIONS | |||
18 | --debug verbose # sets verbose = 1 | 18 | --debug verbose # sets verbose = 1 |
19 | --debug verbose=2 # sets verbose = 2 | 19 | --debug verbose=2 # sets verbose = 2 |
20 | 20 | ||
21 | --buildid-dir:: | ||
22 | Setup buildid cache directory. It has higher priority than | ||
23 | buildid.dir config file option. | ||
24 | |||
21 | DESCRIPTION | 25 | DESCRIPTION |
22 | ----------- | 26 | ----------- |
23 | Performance counters for Linux are a new kernel-based subsystem | 27 | Performance counters for Linux are a new kernel-based subsystem |
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index 344c4d3d0a4a..fbbfdc39271d 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST | |||
@@ -4,17 +4,37 @@ tools/lib/traceevent | |||
4 | tools/lib/api | 4 | tools/lib/api |
5 | tools/lib/symbol/kallsyms.c | 5 | tools/lib/symbol/kallsyms.c |
6 | tools/lib/symbol/kallsyms.h | 6 | tools/lib/symbol/kallsyms.h |
7 | tools/lib/util/find_next_bit.c | ||
7 | tools/include/asm/bug.h | 8 | tools/include/asm/bug.h |
9 | tools/include/asm-generic/bitops/arch_hweight.h | ||
10 | tools/include/asm-generic/bitops/atomic.h | ||
11 | tools/include/asm-generic/bitops/const_hweight.h | ||
12 | tools/include/asm-generic/bitops/__ffs.h | ||
13 | tools/include/asm-generic/bitops/__fls.h | ||
14 | tools/include/asm-generic/bitops/find.h | ||
15 | tools/include/asm-generic/bitops/fls64.h | ||
16 | tools/include/asm-generic/bitops/fls.h | ||
17 | tools/include/asm-generic/bitops/hweight.h | ||
18 | tools/include/asm-generic/bitops.h | ||
19 | tools/include/linux/bitops.h | ||
8 | tools/include/linux/compiler.h | 20 | tools/include/linux/compiler.h |
9 | tools/include/linux/hash.h | ||
10 | tools/include/linux/export.h | 21 | tools/include/linux/export.h |
22 | tools/include/linux/hash.h | ||
23 | tools/include/linux/log2.h | ||
11 | tools/include/linux/types.h | 24 | tools/include/linux/types.h |
25 | include/asm-generic/bitops/arch_hweight.h | ||
26 | include/asm-generic/bitops/const_hweight.h | ||
27 | include/asm-generic/bitops/fls64.h | ||
28 | include/asm-generic/bitops/__fls.h | ||
29 | include/asm-generic/bitops/fls.h | ||
12 | include/linux/const.h | 30 | include/linux/const.h |
13 | include/linux/perf_event.h | 31 | include/linux/perf_event.h |
14 | include/linux/rbtree.h | 32 | include/linux/rbtree.h |
15 | include/linux/list.h | 33 | include/linux/list.h |
16 | include/linux/hash.h | 34 | include/linux/hash.h |
17 | include/linux/stringify.h | 35 | include/linux/stringify.h |
36 | lib/find_next_bit.c | ||
37 | lib/hweight.c | ||
18 | lib/rbtree.c | 38 | lib/rbtree.c |
19 | include/linux/swab.h | 39 | include/linux/swab.h |
20 | arch/*/include/asm/unistd*.h | 40 | arch/*/include/asm/unistd*.h |
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 262916f4a377..aa6a50447c32 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
@@ -60,6 +60,15 @@ include config/utilities.mak | |||
60 | # | 60 | # |
61 | # Define NO_LIBDW_DWARF_UNWIND if you do not want libdw support | 61 | # Define NO_LIBDW_DWARF_UNWIND if you do not want libdw support |
62 | # for dwarf backtrace post unwind. | 62 | # for dwarf backtrace post unwind. |
63 | # | ||
64 | # Define NO_PERF_READ_VDSO32 if you do not want to build perf-read-vdso32 | ||
65 | # for reading the 32-bit compatibility VDSO in 64-bit mode | ||
66 | # | ||
67 | # Define NO_PERF_READ_VDSOX32 if you do not want to build perf-read-vdsox32 | ||
68 | # for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode | ||
69 | # | ||
70 | # Define NO_ZLIB if you do not want to support compressed kernel modules | ||
71 | |||
63 | 72 | ||
64 | ifeq ($(srctree),) | 73 | ifeq ($(srctree),) |
65 | srctree := $(patsubst %/,%,$(dir $(shell pwd))) | 74 | srctree := $(patsubst %/,%,$(dir $(shell pwd))) |
@@ -171,11 +180,16 @@ $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) | |||
171 | 180 | ||
172 | SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) | 181 | SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) |
173 | 182 | ||
174 | # | ||
175 | # Single 'perf' binary right now: | ||
176 | # | ||
177 | PROGRAMS += $(OUTPUT)perf | 183 | PROGRAMS += $(OUTPUT)perf |
178 | 184 | ||
185 | ifndef NO_PERF_READ_VDSO32 | ||
186 | PROGRAMS += $(OUTPUT)perf-read-vdso32 | ||
187 | endif | ||
188 | |||
189 | ifndef NO_PERF_READ_VDSOX32 | ||
190 | PROGRAMS += $(OUTPUT)perf-read-vdsox32 | ||
191 | endif | ||
192 | |||
179 | # what 'all' will build and 'install' will install, in perfexecdir | 193 | # what 'all' will build and 'install' will install, in perfexecdir |
180 | ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) | 194 | ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) |
181 | 195 | ||
@@ -217,8 +231,19 @@ LIB_H += ../../include/uapi/linux/const.h | |||
217 | LIB_H += ../include/linux/hash.h | 231 | LIB_H += ../include/linux/hash.h |
218 | LIB_H += ../../include/linux/stringify.h | 232 | LIB_H += ../../include/linux/stringify.h |
219 | LIB_H += util/include/linux/bitmap.h | 233 | LIB_H += util/include/linux/bitmap.h |
220 | LIB_H += util/include/linux/bitops.h | 234 | LIB_H += ../include/linux/bitops.h |
235 | LIB_H += ../include/asm-generic/bitops/arch_hweight.h | ||
236 | LIB_H += ../include/asm-generic/bitops/atomic.h | ||
237 | LIB_H += ../include/asm-generic/bitops/const_hweight.h | ||
238 | LIB_H += ../include/asm-generic/bitops/find.h | ||
239 | LIB_H += ../include/asm-generic/bitops/fls64.h | ||
240 | LIB_H += ../include/asm-generic/bitops/fls.h | ||
241 | LIB_H += ../include/asm-generic/bitops/__ffs.h | ||
242 | LIB_H += ../include/asm-generic/bitops/__fls.h | ||
243 | LIB_H += ../include/asm-generic/bitops/hweight.h | ||
244 | LIB_H += ../include/asm-generic/bitops.h | ||
221 | LIB_H += ../include/linux/compiler.h | 245 | LIB_H += ../include/linux/compiler.h |
246 | LIB_H += ../include/linux/log2.h | ||
222 | LIB_H += util/include/linux/const.h | 247 | LIB_H += util/include/linux/const.h |
223 | LIB_H += util/include/linux/ctype.h | 248 | LIB_H += util/include/linux/ctype.h |
224 | LIB_H += util/include/linux/kernel.h | 249 | LIB_H += util/include/linux/kernel.h |
@@ -233,7 +258,6 @@ LIB_H += util/include/linux/linkage.h | |||
233 | LIB_H += util/include/asm/asm-offsets.h | 258 | LIB_H += util/include/asm/asm-offsets.h |
234 | LIB_H += ../include/asm/bug.h | 259 | LIB_H += ../include/asm/bug.h |
235 | LIB_H += util/include/asm/byteorder.h | 260 | LIB_H += util/include/asm/byteorder.h |
236 | LIB_H += util/include/asm/hweight.h | ||
237 | LIB_H += util/include/asm/swab.h | 261 | LIB_H += util/include/asm/swab.h |
238 | LIB_H += util/include/asm/system.h | 262 | LIB_H += util/include/asm/system.h |
239 | LIB_H += util/include/asm/uaccess.h | 263 | LIB_H += util/include/asm/uaccess.h |
@@ -247,12 +271,14 @@ LIB_H += util/annotate.h | |||
247 | LIB_H += util/cache.h | 271 | LIB_H += util/cache.h |
248 | LIB_H += util/callchain.h | 272 | LIB_H += util/callchain.h |
249 | LIB_H += util/build-id.h | 273 | LIB_H += util/build-id.h |
274 | LIB_H += util/db-export.h | ||
250 | LIB_H += util/debug.h | 275 | LIB_H += util/debug.h |
251 | LIB_H += util/pmu.h | 276 | LIB_H += util/pmu.h |
252 | LIB_H += util/event.h | 277 | LIB_H += util/event.h |
253 | LIB_H += util/evsel.h | 278 | LIB_H += util/evsel.h |
254 | LIB_H += util/evlist.h | 279 | LIB_H += util/evlist.h |
255 | LIB_H += util/exec_cmd.h | 280 | LIB_H += util/exec_cmd.h |
281 | LIB_H += util/find-vdso-map.c | ||
256 | LIB_H += util/levenshtein.h | 282 | LIB_H += util/levenshtein.h |
257 | LIB_H += util/machine.h | 283 | LIB_H += util/machine.h |
258 | LIB_H += util/map.h | 284 | LIB_H += util/map.h |
@@ -304,6 +330,7 @@ LIB_H += ui/util.h | |||
304 | LIB_H += ui/ui.h | 330 | LIB_H += ui/ui.h |
305 | LIB_H += util/data.h | 331 | LIB_H += util/data.h |
306 | LIB_H += util/kvm-stat.h | 332 | LIB_H += util/kvm-stat.h |
333 | LIB_H += util/thread-stack.h | ||
307 | 334 | ||
308 | LIB_OBJS += $(OUTPUT)util/abspath.o | 335 | LIB_OBJS += $(OUTPUT)util/abspath.o |
309 | LIB_OBJS += $(OUTPUT)util/alias.o | 336 | LIB_OBJS += $(OUTPUT)util/alias.o |
@@ -311,12 +338,14 @@ LIB_OBJS += $(OUTPUT)util/annotate.o | |||
311 | LIB_OBJS += $(OUTPUT)util/build-id.o | 338 | LIB_OBJS += $(OUTPUT)util/build-id.o |
312 | LIB_OBJS += $(OUTPUT)util/config.o | 339 | LIB_OBJS += $(OUTPUT)util/config.o |
313 | LIB_OBJS += $(OUTPUT)util/ctype.o | 340 | LIB_OBJS += $(OUTPUT)util/ctype.o |
341 | LIB_OBJS += $(OUTPUT)util/db-export.o | ||
314 | LIB_OBJS += $(OUTPUT)util/pmu.o | 342 | LIB_OBJS += $(OUTPUT)util/pmu.o |
315 | LIB_OBJS += $(OUTPUT)util/environment.o | 343 | LIB_OBJS += $(OUTPUT)util/environment.o |
316 | LIB_OBJS += $(OUTPUT)util/event.o | 344 | LIB_OBJS += $(OUTPUT)util/event.o |
317 | LIB_OBJS += $(OUTPUT)util/evlist.o | 345 | LIB_OBJS += $(OUTPUT)util/evlist.o |
318 | LIB_OBJS += $(OUTPUT)util/evsel.o | 346 | LIB_OBJS += $(OUTPUT)util/evsel.o |
319 | LIB_OBJS += $(OUTPUT)util/exec_cmd.o | 347 | LIB_OBJS += $(OUTPUT)util/exec_cmd.o |
348 | LIB_OBJS += $(OUTPUT)util/find_next_bit.o | ||
320 | LIB_OBJS += $(OUTPUT)util/help.o | 349 | LIB_OBJS += $(OUTPUT)util/help.o |
321 | LIB_OBJS += $(OUTPUT)util/kallsyms.o | 350 | LIB_OBJS += $(OUTPUT)util/kallsyms.o |
322 | LIB_OBJS += $(OUTPUT)util/levenshtein.o | 351 | LIB_OBJS += $(OUTPUT)util/levenshtein.o |
@@ -380,6 +409,7 @@ LIB_OBJS += $(OUTPUT)util/srcline.o | |||
380 | LIB_OBJS += $(OUTPUT)util/data.o | 409 | LIB_OBJS += $(OUTPUT)util/data.o |
381 | LIB_OBJS += $(OUTPUT)util/tsc.o | 410 | LIB_OBJS += $(OUTPUT)util/tsc.o |
382 | LIB_OBJS += $(OUTPUT)util/cloexec.o | 411 | LIB_OBJS += $(OUTPUT)util/cloexec.o |
412 | LIB_OBJS += $(OUTPUT)util/thread-stack.o | ||
383 | 413 | ||
384 | LIB_OBJS += $(OUTPUT)ui/setup.o | 414 | LIB_OBJS += $(OUTPUT)ui/setup.o |
385 | LIB_OBJS += $(OUTPUT)ui/helpline.o | 415 | LIB_OBJS += $(OUTPUT)ui/helpline.o |
@@ -434,12 +464,13 @@ BUILTIN_OBJS += $(OUTPUT)builtin-bench.o | |||
434 | # Benchmark modules | 464 | # Benchmark modules |
435 | BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o | 465 | BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o |
436 | BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o | 466 | BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o |
437 | ifeq ($(RAW_ARCH),x86_64) | 467 | ifeq ($(ARCH), x86) |
468 | ifeq ($(IS_64_BIT), 1) | ||
438 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o | 469 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o |
439 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o | 470 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o |
440 | endif | 471 | endif |
472 | endif | ||
441 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o | 473 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o |
442 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o | ||
443 | BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o | 474 | BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o |
444 | BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o | 475 | BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o |
445 | BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o | 476 | BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o |
@@ -478,8 +509,6 @@ ifneq ($(OUTPUT),) | |||
478 | endif | 509 | endif |
479 | 510 | ||
480 | ifdef NO_LIBELF | 511 | ifdef NO_LIBELF |
481 | EXTLIBS := $(filter-out -lelf,$(EXTLIBS)) | ||
482 | |||
483 | # Remove ELF/DWARF dependent codes | 512 | # Remove ELF/DWARF dependent codes |
484 | LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS)) | 513 | LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS)) |
485 | LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS)) | 514 | LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS)) |
@@ -568,6 +597,10 @@ ifndef NO_LIBNUMA | |||
568 | BUILTIN_OBJS += $(OUTPUT)bench/numa.o | 597 | BUILTIN_OBJS += $(OUTPUT)bench/numa.o |
569 | endif | 598 | endif |
570 | 599 | ||
600 | ifndef NO_ZLIB | ||
601 | LIB_OBJS += $(OUTPUT)util/zlib.o | ||
602 | endif | ||
603 | |||
571 | ifdef ASCIIDOC8 | 604 | ifdef ASCIIDOC8 |
572 | export ASCIIDOC8 | 605 | export ASCIIDOC8 |
573 | endif | 606 | endif |
@@ -714,6 +747,12 @@ $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS | |||
714 | $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS | 747 | $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS |
715 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< | 748 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< |
716 | 749 | ||
750 | $(OUTPUT)util/hweight.o: ../../lib/hweight.c $(OUTPUT)PERF-CFLAGS | ||
751 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< | ||
752 | |||
753 | $(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c $(OUTPUT)PERF-CFLAGS | ||
754 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< | ||
755 | |||
717 | $(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS | 756 | $(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS |
718 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $< | 757 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $< |
719 | 758 | ||
@@ -732,6 +771,16 @@ $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Uti | |||
732 | $(OUTPUT)perf-%: %.o $(PERFLIBS) | 771 | $(OUTPUT)perf-%: %.o $(PERFLIBS) |
733 | $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS) | 772 | $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS) |
734 | 773 | ||
774 | ifndef NO_PERF_READ_VDSO32 | ||
775 | $(OUTPUT)perf-read-vdso32: perf-read-vdso.c util/find-vdso-map.c | ||
776 | $(QUIET_CC)$(CC) -m32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c | ||
777 | endif | ||
778 | |||
779 | ifndef NO_PERF_READ_VDSOX32 | ||
780 | $(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-vdso-map.c | ||
781 | $(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c | ||
782 | endif | ||
783 | |||
735 | $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) | 784 | $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) |
736 | $(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) | 785 | $(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) |
737 | 786 | ||
@@ -876,6 +925,14 @@ install-bin: all install-gtk | |||
876 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \ | 925 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \ |
877 | $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \ | 926 | $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \ |
878 | $(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace' | 927 | $(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace' |
928 | ifndef NO_PERF_READ_VDSO32 | ||
929 | $(call QUIET_INSTALL, perf-read-vdso32) \ | ||
930 | $(INSTALL) $(OUTPUT)perf-read-vdso32 '$(DESTDIR_SQ)$(bindir_SQ)'; | ||
931 | endif | ||
932 | ifndef NO_PERF_READ_VDSOX32 | ||
933 | $(call QUIET_INSTALL, perf-read-vdsox32) \ | ||
934 | $(INSTALL) $(OUTPUT)perf-read-vdsox32 '$(DESTDIR_SQ)$(bindir_SQ)'; | ||
935 | endif | ||
879 | $(call QUIET_INSTALL, libexec) \ | 936 | $(call QUIET_INSTALL, libexec) \ |
880 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' | 937 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' |
881 | $(call QUIET_INSTALL, perf-archive) \ | 938 | $(call QUIET_INSTALL, perf-archive) \ |
@@ -928,7 +985,7 @@ config-clean: | |||
928 | 985 | ||
929 | clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean | 986 | clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean |
930 | $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) | 987 | $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) |
931 | $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf | 988 | $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 |
932 | $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* | 989 | $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* |
933 | $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean | 990 | $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean |
934 | $(python-clean) | 991 | $(python-clean) |
diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c index d73ef8bb08c7..0c370f81e002 100644 --- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c +++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c | |||
@@ -103,7 +103,7 @@ static Dwarf_Frame *get_eh_frame(Dwfl_Module *mod, Dwarf_Addr pc) | |||
103 | return NULL; | 103 | return NULL; |
104 | } | 104 | } |
105 | 105 | ||
106 | result = dwarf_cfi_addrframe(cfi, pc, &frame); | 106 | result = dwarf_cfi_addrframe(cfi, pc-bias, &frame); |
107 | if (result) { | 107 | if (result) { |
108 | pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1)); | 108 | pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1)); |
109 | return NULL; | 109 | return NULL; |
@@ -128,7 +128,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc) | |||
128 | return NULL; | 128 | return NULL; |
129 | } | 129 | } |
130 | 130 | ||
131 | result = dwarf_cfi_addrframe(cfi, pc, &frame); | 131 | result = dwarf_cfi_addrframe(cfi, pc-bias, &frame); |
132 | if (result) { | 132 | if (result) { |
133 | pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1)); | 133 | pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1)); |
134 | return NULL; | 134 | return NULL; |
@@ -145,7 +145,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc) | |||
145 | * yet used) | 145 | * yet used) |
146 | * -1 in case of errors | 146 | * -1 in case of errors |
147 | */ | 147 | */ |
148 | static int check_return_addr(const char *exec_file, Dwarf_Addr pc) | 148 | static int check_return_addr(struct dso *dso, u64 map_start, Dwarf_Addr pc) |
149 | { | 149 | { |
150 | int rc = -1; | 150 | int rc = -1; |
151 | Dwfl *dwfl; | 151 | Dwfl *dwfl; |
@@ -155,16 +155,31 @@ static int check_return_addr(const char *exec_file, Dwarf_Addr pc) | |||
155 | Dwarf_Addr start = pc; | 155 | Dwarf_Addr start = pc; |
156 | Dwarf_Addr end = pc; | 156 | Dwarf_Addr end = pc; |
157 | bool signalp; | 157 | bool signalp; |
158 | const char *exec_file = dso->long_name; | ||
158 | 159 | ||
159 | dwfl = dwfl_begin(&offline_callbacks); | 160 | dwfl = dso->dwfl; |
160 | if (!dwfl) { | ||
161 | pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1)); | ||
162 | return -1; | ||
163 | } | ||
164 | 161 | ||
165 | if (dwfl_report_offline(dwfl, "", exec_file, -1) == NULL) { | 162 | if (!dwfl) { |
166 | pr_debug("dwfl_report_offline() failed %s\n", dwarf_errmsg(-1)); | 163 | dwfl = dwfl_begin(&offline_callbacks); |
167 | goto out; | 164 | if (!dwfl) { |
165 | pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1)); | ||
166 | return -1; | ||
167 | } | ||
168 | |||
169 | mod = dwfl_report_elf(dwfl, exec_file, exec_file, -1, | ||
170 | map_start, false); | ||
171 | if (!mod) { | ||
172 | pr_debug("dwfl_report_elf() failed %s\n", | ||
173 | dwarf_errmsg(-1)); | ||
174 | /* | ||
175 | * We normally cache the DWARF debug info and never | ||
176 | * call dwfl_end(). But to prevent fd leak, free in | ||
177 | * case of error. | ||
178 | */ | ||
179 | dwfl_end(dwfl); | ||
180 | goto out; | ||
181 | } | ||
182 | dso->dwfl = dwfl; | ||
168 | } | 183 | } |
169 | 184 | ||
170 | mod = dwfl_addrmodule(dwfl, pc); | 185 | mod = dwfl_addrmodule(dwfl, pc); |
@@ -194,7 +209,6 @@ static int check_return_addr(const char *exec_file, Dwarf_Addr pc) | |||
194 | rc = check_return_reg(ra_regno, frame); | 209 | rc = check_return_reg(ra_regno, frame); |
195 | 210 | ||
196 | out: | 211 | out: |
197 | dwfl_end(dwfl); | ||
198 | return rc; | 212 | return rc; |
199 | } | 213 | } |
200 | 214 | ||
@@ -221,8 +235,7 @@ out: | |||
221 | * index: of callchain entry that needs to be ignored (if any) | 235 | * index: of callchain entry that needs to be ignored (if any) |
222 | * -1 if no entry needs to be ignored or in case of errors | 236 | * -1 if no entry needs to be ignored or in case of errors |
223 | */ | 237 | */ |
224 | int arch_skip_callchain_idx(struct machine *machine, struct thread *thread, | 238 | int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain) |
225 | struct ip_callchain *chain) | ||
226 | { | 239 | { |
227 | struct addr_location al; | 240 | struct addr_location al; |
228 | struct dso *dso = NULL; | 241 | struct dso *dso = NULL; |
@@ -235,7 +248,7 @@ int arch_skip_callchain_idx(struct machine *machine, struct thread *thread, | |||
235 | 248 | ||
236 | ip = chain->ips[2]; | 249 | ip = chain->ips[2]; |
237 | 250 | ||
238 | thread__find_addr_location(thread, machine, PERF_RECORD_MISC_USER, | 251 | thread__find_addr_location(thread, PERF_RECORD_MISC_USER, |
239 | MAP__FUNCTION, ip, &al); | 252 | MAP__FUNCTION, ip, &al); |
240 | 253 | ||
241 | if (al.map) | 254 | if (al.map) |
@@ -246,10 +259,10 @@ int arch_skip_callchain_idx(struct machine *machine, struct thread *thread, | |||
246 | return skip_slot; | 259 | return skip_slot; |
247 | } | 260 | } |
248 | 261 | ||
249 | rc = check_return_addr(dso->long_name, ip); | 262 | rc = check_return_addr(dso, al.map->start, ip); |
250 | 263 | ||
251 | pr_debug("DSO %s, nr %" PRIx64 ", ip 0x%" PRIx64 "rc %d\n", | 264 | pr_debug("[DSO %s, sym %s, ip 0x%" PRIx64 "] rc %d\n", |
252 | dso->long_name, chain->nr, ip, rc); | 265 | dso->long_name, al.sym->name, ip, rc); |
253 | 266 | ||
254 | if (rc == 0) { | 267 | if (rc == 0) { |
255 | /* | 268 | /* |
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c index 2465141b554b..6c14afe8c1b1 100644 --- a/tools/perf/bench/mem-memcpy.c +++ b/tools/perf/bench/mem-memcpy.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include "../util/cloexec.h" | 13 | #include "../util/cloexec.h" |
14 | #include "bench.h" | 14 | #include "bench.h" |
15 | #include "mem-memcpy-arch.h" | 15 | #include "mem-memcpy-arch.h" |
16 | #include "mem-memset-arch.h" | ||
16 | 17 | ||
17 | #include <stdio.h> | 18 | #include <stdio.h> |
18 | #include <stdlib.h> | 19 | #include <stdlib.h> |
@@ -48,20 +49,24 @@ static const struct option options[] = { | |||
48 | }; | 49 | }; |
49 | 50 | ||
50 | typedef void *(*memcpy_t)(void *, const void *, size_t); | 51 | typedef void *(*memcpy_t)(void *, const void *, size_t); |
52 | typedef void *(*memset_t)(void *, int, size_t); | ||
51 | 53 | ||
52 | struct routine { | 54 | struct routine { |
53 | const char *name; | 55 | const char *name; |
54 | const char *desc; | 56 | const char *desc; |
55 | memcpy_t fn; | 57 | union { |
58 | memcpy_t memcpy; | ||
59 | memset_t memset; | ||
60 | } fn; | ||
56 | }; | 61 | }; |
57 | 62 | ||
58 | struct routine routines[] = { | 63 | struct routine memcpy_routines[] = { |
59 | { "default", | 64 | { .name = "default", |
60 | "Default memcpy() provided by glibc", | 65 | .desc = "Default memcpy() provided by glibc", |
61 | memcpy }, | 66 | .fn.memcpy = memcpy }, |
62 | #ifdef HAVE_ARCH_X86_64_SUPPORT | 67 | #ifdef HAVE_ARCH_X86_64_SUPPORT |
63 | 68 | ||
64 | #define MEMCPY_FN(fn, name, desc) { name, desc, fn }, | 69 | #define MEMCPY_FN(_fn, _name, _desc) {.name = _name, .desc = _desc, .fn.memcpy = _fn}, |
65 | #include "mem-memcpy-x86-64-asm-def.h" | 70 | #include "mem-memcpy-x86-64-asm-def.h" |
66 | #undef MEMCPY_FN | 71 | #undef MEMCPY_FN |
67 | 72 | ||
@@ -69,7 +74,7 @@ struct routine routines[] = { | |||
69 | 74 | ||
70 | { NULL, | 75 | { NULL, |
71 | NULL, | 76 | NULL, |
72 | NULL } | 77 | {NULL} } |
73 | }; | 78 | }; |
74 | 79 | ||
75 | static const char * const bench_mem_memcpy_usage[] = { | 80 | static const char * const bench_mem_memcpy_usage[] = { |
@@ -110,63 +115,6 @@ static double timeval2double(struct timeval *ts) | |||
110 | (double)ts->tv_usec / (double)1000000; | 115 | (double)ts->tv_usec / (double)1000000; |
111 | } | 116 | } |
112 | 117 | ||
113 | static void alloc_mem(void **dst, void **src, size_t length) | ||
114 | { | ||
115 | *dst = zalloc(length); | ||
116 | if (!*dst) | ||
117 | die("memory allocation failed - maybe length is too large?\n"); | ||
118 | |||
119 | *src = zalloc(length); | ||
120 | if (!*src) | ||
121 | die("memory allocation failed - maybe length is too large?\n"); | ||
122 | /* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */ | ||
123 | memset(*src, 0, length); | ||
124 | } | ||
125 | |||
126 | static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault) | ||
127 | { | ||
128 | u64 cycle_start = 0ULL, cycle_end = 0ULL; | ||
129 | void *src = NULL, *dst = NULL; | ||
130 | int i; | ||
131 | |||
132 | alloc_mem(&src, &dst, len); | ||
133 | |||
134 | if (prefault) | ||
135 | fn(dst, src, len); | ||
136 | |||
137 | cycle_start = get_cycle(); | ||
138 | for (i = 0; i < iterations; ++i) | ||
139 | fn(dst, src, len); | ||
140 | cycle_end = get_cycle(); | ||
141 | |||
142 | free(src); | ||
143 | free(dst); | ||
144 | return cycle_end - cycle_start; | ||
145 | } | ||
146 | |||
147 | static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault) | ||
148 | { | ||
149 | struct timeval tv_start, tv_end, tv_diff; | ||
150 | void *src = NULL, *dst = NULL; | ||
151 | int i; | ||
152 | |||
153 | alloc_mem(&src, &dst, len); | ||
154 | |||
155 | if (prefault) | ||
156 | fn(dst, src, len); | ||
157 | |||
158 | BUG_ON(gettimeofday(&tv_start, NULL)); | ||
159 | for (i = 0; i < iterations; ++i) | ||
160 | fn(dst, src, len); | ||
161 | BUG_ON(gettimeofday(&tv_end, NULL)); | ||
162 | |||
163 | timersub(&tv_end, &tv_start, &tv_diff); | ||
164 | |||
165 | free(src); | ||
166 | free(dst); | ||
167 | return (double)((double)len / timeval2double(&tv_diff)); | ||
168 | } | ||
169 | |||
170 | #define pf (no_prefault ? 0 : 1) | 118 | #define pf (no_prefault ? 0 : 1) |
171 | 119 | ||
172 | #define print_bps(x) do { \ | 120 | #define print_bps(x) do { \ |
@@ -180,16 +128,25 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault) | |||
180 | printf(" %14lf GB/Sec", x / K / K / K); \ | 128 | printf(" %14lf GB/Sec", x / K / K / K); \ |
181 | } while (0) | 129 | } while (0) |
182 | 130 | ||
183 | int bench_mem_memcpy(int argc, const char **argv, | 131 | struct bench_mem_info { |
184 | const char *prefix __maybe_unused) | 132 | const struct routine *routines; |
133 | u64 (*do_cycle)(const struct routine *r, size_t len, bool prefault); | ||
134 | double (*do_gettimeofday)(const struct routine *r, size_t len, bool prefault); | ||
135 | const char *const *usage; | ||
136 | }; | ||
137 | |||
138 | static int bench_mem_common(int argc, const char **argv, | ||
139 | const char *prefix __maybe_unused, | ||
140 | struct bench_mem_info *info) | ||
185 | { | 141 | { |
186 | int i; | 142 | int i; |
187 | size_t len; | 143 | size_t len; |
144 | double totallen; | ||
188 | double result_bps[2]; | 145 | double result_bps[2]; |
189 | u64 result_cycle[2]; | 146 | u64 result_cycle[2]; |
190 | 147 | ||
191 | argc = parse_options(argc, argv, options, | 148 | argc = parse_options(argc, argv, options, |
192 | bench_mem_memcpy_usage, 0); | 149 | info->usage, 0); |
193 | 150 | ||
194 | if (no_prefault && only_prefault) { | 151 | if (no_prefault && only_prefault) { |
195 | fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n"); | 152 | fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n"); |
@@ -200,6 +157,7 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
200 | init_cycle(); | 157 | init_cycle(); |
201 | 158 | ||
202 | len = (size_t)perf_atoll((char *)length_str); | 159 | len = (size_t)perf_atoll((char *)length_str); |
160 | totallen = (double)len * iterations; | ||
203 | 161 | ||
204 | result_cycle[0] = result_cycle[1] = 0ULL; | 162 | result_cycle[0] = result_cycle[1] = 0ULL; |
205 | result_bps[0] = result_bps[1] = 0.0; | 163 | result_bps[0] = result_bps[1] = 0.0; |
@@ -213,16 +171,16 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
213 | if (only_prefault && no_prefault) | 171 | if (only_prefault && no_prefault) |
214 | only_prefault = no_prefault = false; | 172 | only_prefault = no_prefault = false; |
215 | 173 | ||
216 | for (i = 0; routines[i].name; i++) { | 174 | for (i = 0; info->routines[i].name; i++) { |
217 | if (!strcmp(routines[i].name, routine)) | 175 | if (!strcmp(info->routines[i].name, routine)) |
218 | break; | 176 | break; |
219 | } | 177 | } |
220 | if (!routines[i].name) { | 178 | if (!info->routines[i].name) { |
221 | printf("Unknown routine:%s\n", routine); | 179 | printf("Unknown routine:%s\n", routine); |
222 | printf("Available routines...\n"); | 180 | printf("Available routines...\n"); |
223 | for (i = 0; routines[i].name; i++) { | 181 | for (i = 0; info->routines[i].name; i++) { |
224 | printf("\t%s ... %s\n", | 182 | printf("\t%s ... %s\n", |
225 | routines[i].name, routines[i].desc); | 183 | info->routines[i].name, info->routines[i].desc); |
226 | } | 184 | } |
227 | return 1; | 185 | return 1; |
228 | } | 186 | } |
@@ -234,25 +192,25 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
234 | /* show both of results */ | 192 | /* show both of results */ |
235 | if (use_cycle) { | 193 | if (use_cycle) { |
236 | result_cycle[0] = | 194 | result_cycle[0] = |
237 | do_memcpy_cycle(routines[i].fn, len, false); | 195 | info->do_cycle(&info->routines[i], len, false); |
238 | result_cycle[1] = | 196 | result_cycle[1] = |
239 | do_memcpy_cycle(routines[i].fn, len, true); | 197 | info->do_cycle(&info->routines[i], len, true); |
240 | } else { | 198 | } else { |
241 | result_bps[0] = | 199 | result_bps[0] = |
242 | do_memcpy_gettimeofday(routines[i].fn, | 200 | info->do_gettimeofday(&info->routines[i], |
243 | len, false); | 201 | len, false); |
244 | result_bps[1] = | 202 | result_bps[1] = |
245 | do_memcpy_gettimeofday(routines[i].fn, | 203 | info->do_gettimeofday(&info->routines[i], |
246 | len, true); | 204 | len, true); |
247 | } | 205 | } |
248 | } else { | 206 | } else { |
249 | if (use_cycle) { | 207 | if (use_cycle) { |
250 | result_cycle[pf] = | 208 | result_cycle[pf] = |
251 | do_memcpy_cycle(routines[i].fn, | 209 | info->do_cycle(&info->routines[i], |
252 | len, only_prefault); | 210 | len, only_prefault); |
253 | } else { | 211 | } else { |
254 | result_bps[pf] = | 212 | result_bps[pf] = |
255 | do_memcpy_gettimeofday(routines[i].fn, | 213 | info->do_gettimeofday(&info->routines[i], |
256 | len, only_prefault); | 214 | len, only_prefault); |
257 | } | 215 | } |
258 | } | 216 | } |
@@ -263,10 +221,10 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
263 | if (use_cycle) { | 221 | if (use_cycle) { |
264 | printf(" %14lf Cycle/Byte\n", | 222 | printf(" %14lf Cycle/Byte\n", |
265 | (double)result_cycle[0] | 223 | (double)result_cycle[0] |
266 | / (double)len); | 224 | / totallen); |
267 | printf(" %14lf Cycle/Byte (with prefault)\n", | 225 | printf(" %14lf Cycle/Byte (with prefault)\n", |
268 | (double)result_cycle[1] | 226 | (double)result_cycle[1] |
269 | / (double)len); | 227 | / totallen); |
270 | } else { | 228 | } else { |
271 | print_bps(result_bps[0]); | 229 | print_bps(result_bps[0]); |
272 | printf("\n"); | 230 | printf("\n"); |
@@ -277,7 +235,7 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
277 | if (use_cycle) { | 235 | if (use_cycle) { |
278 | printf(" %14lf Cycle/Byte", | 236 | printf(" %14lf Cycle/Byte", |
279 | (double)result_cycle[pf] | 237 | (double)result_cycle[pf] |
280 | / (double)len); | 238 | / totallen); |
281 | } else | 239 | } else |
282 | print_bps(result_bps[pf]); | 240 | print_bps(result_bps[pf]); |
283 | 241 | ||
@@ -288,8 +246,8 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
288 | if (!only_prefault && !no_prefault) { | 246 | if (!only_prefault && !no_prefault) { |
289 | if (use_cycle) { | 247 | if (use_cycle) { |
290 | printf("%lf %lf\n", | 248 | printf("%lf %lf\n", |
291 | (double)result_cycle[0] / (double)len, | 249 | (double)result_cycle[0] / totallen, |
292 | (double)result_cycle[1] / (double)len); | 250 | (double)result_cycle[1] / totallen); |
293 | } else { | 251 | } else { |
294 | printf("%lf %lf\n", | 252 | printf("%lf %lf\n", |
295 | result_bps[0], result_bps[1]); | 253 | result_bps[0], result_bps[1]); |
@@ -297,7 +255,7 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
297 | } else { | 255 | } else { |
298 | if (use_cycle) { | 256 | if (use_cycle) { |
299 | printf("%lf\n", (double)result_cycle[pf] | 257 | printf("%lf\n", (double)result_cycle[pf] |
300 | / (double)len); | 258 | / totallen); |
301 | } else | 259 | } else |
302 | printf("%lf\n", result_bps[pf]); | 260 | printf("%lf\n", result_bps[pf]); |
303 | } | 261 | } |
@@ -310,3 +268,163 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
310 | 268 | ||
311 | return 0; | 269 | return 0; |
312 | } | 270 | } |
271 | |||
272 | static void memcpy_alloc_mem(void **dst, void **src, size_t length) | ||
273 | { | ||
274 | *dst = zalloc(length); | ||
275 | if (!*dst) | ||
276 | die("memory allocation failed - maybe length is too large?\n"); | ||
277 | |||
278 | *src = zalloc(length); | ||
279 | if (!*src) | ||
280 | die("memory allocation failed - maybe length is too large?\n"); | ||
281 | /* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */ | ||
282 | memset(*src, 0, length); | ||
283 | } | ||
284 | |||
285 | static u64 do_memcpy_cycle(const struct routine *r, size_t len, bool prefault) | ||
286 | { | ||
287 | u64 cycle_start = 0ULL, cycle_end = 0ULL; | ||
288 | void *src = NULL, *dst = NULL; | ||
289 | memcpy_t fn = r->fn.memcpy; | ||
290 | int i; | ||
291 | |||
292 | memcpy_alloc_mem(&src, &dst, len); | ||
293 | |||
294 | if (prefault) | ||
295 | fn(dst, src, len); | ||
296 | |||
297 | cycle_start = get_cycle(); | ||
298 | for (i = 0; i < iterations; ++i) | ||
299 | fn(dst, src, len); | ||
300 | cycle_end = get_cycle(); | ||
301 | |||
302 | free(src); | ||
303 | free(dst); | ||
304 | return cycle_end - cycle_start; | ||
305 | } | ||
306 | |||
307 | static double do_memcpy_gettimeofday(const struct routine *r, size_t len, | ||
308 | bool prefault) | ||
309 | { | ||
310 | struct timeval tv_start, tv_end, tv_diff; | ||
311 | memcpy_t fn = r->fn.memcpy; | ||
312 | void *src = NULL, *dst = NULL; | ||
313 | int i; | ||
314 | |||
315 | memcpy_alloc_mem(&src, &dst, len); | ||
316 | |||
317 | if (prefault) | ||
318 | fn(dst, src, len); | ||
319 | |||
320 | BUG_ON(gettimeofday(&tv_start, NULL)); | ||
321 | for (i = 0; i < iterations; ++i) | ||
322 | fn(dst, src, len); | ||
323 | BUG_ON(gettimeofday(&tv_end, NULL)); | ||
324 | |||
325 | timersub(&tv_end, &tv_start, &tv_diff); | ||
326 | |||
327 | free(src); | ||
328 | free(dst); | ||
329 | return (double)(((double)len * iterations) / timeval2double(&tv_diff)); | ||
330 | } | ||
331 | |||
332 | int bench_mem_memcpy(int argc, const char **argv, | ||
333 | const char *prefix __maybe_unused) | ||
334 | { | ||
335 | struct bench_mem_info info = { | ||
336 | .routines = memcpy_routines, | ||
337 | .do_cycle = do_memcpy_cycle, | ||
338 | .do_gettimeofday = do_memcpy_gettimeofday, | ||
339 | .usage = bench_mem_memcpy_usage, | ||
340 | }; | ||
341 | |||
342 | return bench_mem_common(argc, argv, prefix, &info); | ||
343 | } | ||
344 | |||
345 | static void memset_alloc_mem(void **dst, size_t length) | ||
346 | { | ||
347 | *dst = zalloc(length); | ||
348 | if (!*dst) | ||
349 | die("memory allocation failed - maybe length is too large?\n"); | ||
350 | } | ||
351 | |||
352 | static u64 do_memset_cycle(const struct routine *r, size_t len, bool prefault) | ||
353 | { | ||
354 | u64 cycle_start = 0ULL, cycle_end = 0ULL; | ||
355 | memset_t fn = r->fn.memset; | ||
356 | void *dst = NULL; | ||
357 | int i; | ||
358 | |||
359 | memset_alloc_mem(&dst, len); | ||
360 | |||
361 | if (prefault) | ||
362 | fn(dst, -1, len); | ||
363 | |||
364 | cycle_start = get_cycle(); | ||
365 | for (i = 0; i < iterations; ++i) | ||
366 | fn(dst, i, len); | ||
367 | cycle_end = get_cycle(); | ||
368 | |||
369 | free(dst); | ||
370 | return cycle_end - cycle_start; | ||
371 | } | ||
372 | |||
373 | static double do_memset_gettimeofday(const struct routine *r, size_t len, | ||
374 | bool prefault) | ||
375 | { | ||
376 | struct timeval tv_start, tv_end, tv_diff; | ||
377 | memset_t fn = r->fn.memset; | ||
378 | void *dst = NULL; | ||
379 | int i; | ||
380 | |||
381 | memset_alloc_mem(&dst, len); | ||
382 | |||
383 | if (prefault) | ||
384 | fn(dst, -1, len); | ||
385 | |||
386 | BUG_ON(gettimeofday(&tv_start, NULL)); | ||
387 | for (i = 0; i < iterations; ++i) | ||
388 | fn(dst, i, len); | ||
389 | BUG_ON(gettimeofday(&tv_end, NULL)); | ||
390 | |||
391 | timersub(&tv_end, &tv_start, &tv_diff); | ||
392 | |||
393 | free(dst); | ||
394 | return (double)(((double)len * iterations) / timeval2double(&tv_diff)); | ||
395 | } | ||
396 | |||
397 | static const char * const bench_mem_memset_usage[] = { | ||
398 | "perf bench mem memset <options>", | ||
399 | NULL | ||
400 | }; | ||
401 | |||
402 | static const struct routine memset_routines[] = { | ||
403 | { .name ="default", | ||
404 | .desc = "Default memset() provided by glibc", | ||
405 | .fn.memset = memset }, | ||
406 | #ifdef HAVE_ARCH_X86_64_SUPPORT | ||
407 | |||
408 | #define MEMSET_FN(_fn, _name, _desc) { .name = _name, .desc = _desc, .fn.memset = _fn }, | ||
409 | #include "mem-memset-x86-64-asm-def.h" | ||
410 | #undef MEMSET_FN | ||
411 | |||
412 | #endif | ||
413 | |||
414 | { .name = NULL, | ||
415 | .desc = NULL, | ||
416 | .fn.memset = NULL } | ||
417 | }; | ||
418 | |||
419 | int bench_mem_memset(int argc, const char **argv, | ||
420 | const char *prefix __maybe_unused) | ||
421 | { | ||
422 | struct bench_mem_info info = { | ||
423 | .routines = memset_routines, | ||
424 | .do_cycle = do_memset_cycle, | ||
425 | .do_gettimeofday = do_memset_gettimeofday, | ||
426 | .usage = bench_mem_memset_usage, | ||
427 | }; | ||
428 | |||
429 | return bench_mem_common(argc, argv, prefix, &info); | ||
430 | } | ||
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c deleted file mode 100644 index 75fc3e65fb2a..000000000000 --- a/tools/perf/bench/mem-memset.c +++ /dev/null | |||
@@ -1,304 +0,0 @@ | |||
1 | /* | ||
2 | * mem-memset.c | ||
3 | * | ||
4 | * memset: Simple memory set in various ways | ||
5 | * | ||
6 | * Trivial clone of mem-memcpy.c. | ||
7 | */ | ||
8 | |||
9 | #include "../perf.h" | ||
10 | #include "../util/util.h" | ||
11 | #include "../util/parse-options.h" | ||
12 | #include "../util/header.h" | ||
13 | #include "../util/cloexec.h" | ||
14 | #include "bench.h" | ||
15 | #include "mem-memset-arch.h" | ||
16 | |||
17 | #include <stdio.h> | ||
18 | #include <stdlib.h> | ||
19 | #include <string.h> | ||
20 | #include <sys/time.h> | ||
21 | #include <errno.h> | ||
22 | |||
23 | #define K 1024 | ||
24 | |||
25 | static const char *length_str = "1MB"; | ||
26 | static const char *routine = "default"; | ||
27 | static int iterations = 1; | ||
28 | static bool use_cycle; | ||
29 | static int cycle_fd; | ||
30 | static bool only_prefault; | ||
31 | static bool no_prefault; | ||
32 | |||
33 | static const struct option options[] = { | ||
34 | OPT_STRING('l', "length", &length_str, "1MB", | ||
35 | "Specify length of memory to set. " | ||
36 | "Available units: B, KB, MB, GB and TB (upper and lower)"), | ||
37 | OPT_STRING('r', "routine", &routine, "default", | ||
38 | "Specify routine to set"), | ||
39 | OPT_INTEGER('i', "iterations", &iterations, | ||
40 | "repeat memset() invocation this number of times"), | ||
41 | OPT_BOOLEAN('c', "cycle", &use_cycle, | ||
42 | "Use cycles event instead of gettimeofday() for measuring"), | ||
43 | OPT_BOOLEAN('o', "only-prefault", &only_prefault, | ||
44 | "Show only the result with page faults before memset()"), | ||
45 | OPT_BOOLEAN('n', "no-prefault", &no_prefault, | ||
46 | "Show only the result without page faults before memset()"), | ||
47 | OPT_END() | ||
48 | }; | ||
49 | |||
50 | typedef void *(*memset_t)(void *, int, size_t); | ||
51 | |||
52 | struct routine { | ||
53 | const char *name; | ||
54 | const char *desc; | ||
55 | memset_t fn; | ||
56 | }; | ||
57 | |||
58 | static const struct routine routines[] = { | ||
59 | { "default", | ||
60 | "Default memset() provided by glibc", | ||
61 | memset }, | ||
62 | #ifdef HAVE_ARCH_X86_64_SUPPORT | ||
63 | |||
64 | #define MEMSET_FN(fn, name, desc) { name, desc, fn }, | ||
65 | #include "mem-memset-x86-64-asm-def.h" | ||
66 | #undef MEMSET_FN | ||
67 | |||
68 | #endif | ||
69 | |||
70 | { NULL, | ||
71 | NULL, | ||
72 | NULL } | ||
73 | }; | ||
74 | |||
75 | static const char * const bench_mem_memset_usage[] = { | ||
76 | "perf bench mem memset <options>", | ||
77 | NULL | ||
78 | }; | ||
79 | |||
80 | static struct perf_event_attr cycle_attr = { | ||
81 | .type = PERF_TYPE_HARDWARE, | ||
82 | .config = PERF_COUNT_HW_CPU_CYCLES | ||
83 | }; | ||
84 | |||
85 | static void init_cycle(void) | ||
86 | { | ||
87 | cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, | ||
88 | perf_event_open_cloexec_flag()); | ||
89 | |||
90 | if (cycle_fd < 0 && errno == ENOSYS) | ||
91 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); | ||
92 | else | ||
93 | BUG_ON(cycle_fd < 0); | ||
94 | } | ||
95 | |||
96 | static u64 get_cycle(void) | ||
97 | { | ||
98 | int ret; | ||
99 | u64 clk; | ||
100 | |||
101 | ret = read(cycle_fd, &clk, sizeof(u64)); | ||
102 | BUG_ON(ret != sizeof(u64)); | ||
103 | |||
104 | return clk; | ||
105 | } | ||
106 | |||
107 | static double timeval2double(struct timeval *ts) | ||
108 | { | ||
109 | return (double)ts->tv_sec + | ||
110 | (double)ts->tv_usec / (double)1000000; | ||
111 | } | ||
112 | |||
113 | static void alloc_mem(void **dst, size_t length) | ||
114 | { | ||
115 | *dst = zalloc(length); | ||
116 | if (!*dst) | ||
117 | die("memory allocation failed - maybe length is too large?\n"); | ||
118 | } | ||
119 | |||
120 | static u64 do_memset_cycle(memset_t fn, size_t len, bool prefault) | ||
121 | { | ||
122 | u64 cycle_start = 0ULL, cycle_end = 0ULL; | ||
123 | void *dst = NULL; | ||
124 | int i; | ||
125 | |||
126 | alloc_mem(&dst, len); | ||
127 | |||
128 | if (prefault) | ||
129 | fn(dst, -1, len); | ||
130 | |||
131 | cycle_start = get_cycle(); | ||
132 | for (i = 0; i < iterations; ++i) | ||
133 | fn(dst, i, len); | ||
134 | cycle_end = get_cycle(); | ||
135 | |||
136 | free(dst); | ||
137 | return cycle_end - cycle_start; | ||
138 | } | ||
139 | |||
140 | static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault) | ||
141 | { | ||
142 | struct timeval tv_start, tv_end, tv_diff; | ||
143 | void *dst = NULL; | ||
144 | int i; | ||
145 | |||
146 | alloc_mem(&dst, len); | ||
147 | |||
148 | if (prefault) | ||
149 | fn(dst, -1, len); | ||
150 | |||
151 | BUG_ON(gettimeofday(&tv_start, NULL)); | ||
152 | for (i = 0; i < iterations; ++i) | ||
153 | fn(dst, i, len); | ||
154 | BUG_ON(gettimeofday(&tv_end, NULL)); | ||
155 | |||
156 | timersub(&tv_end, &tv_start, &tv_diff); | ||
157 | |||
158 | free(dst); | ||
159 | return (double)((double)len / timeval2double(&tv_diff)); | ||
160 | } | ||
161 | |||
162 | #define pf (no_prefault ? 0 : 1) | ||
163 | |||
164 | #define print_bps(x) do { \ | ||
165 | if (x < K) \ | ||
166 | printf(" %14lf B/Sec", x); \ | ||
167 | else if (x < K * K) \ | ||
168 | printf(" %14lfd KB/Sec", x / K); \ | ||
169 | else if (x < K * K * K) \ | ||
170 | printf(" %14lf MB/Sec", x / K / K); \ | ||
171 | else \ | ||
172 | printf(" %14lf GB/Sec", x / K / K / K); \ | ||
173 | } while (0) | ||
174 | |||
175 | int bench_mem_memset(int argc, const char **argv, | ||
176 | const char *prefix __maybe_unused) | ||
177 | { | ||
178 | int i; | ||
179 | size_t len; | ||
180 | double result_bps[2]; | ||
181 | u64 result_cycle[2]; | ||
182 | |||
183 | argc = parse_options(argc, argv, options, | ||
184 | bench_mem_memset_usage, 0); | ||
185 | |||
186 | if (no_prefault && only_prefault) { | ||
187 | fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n"); | ||
188 | return 1; | ||
189 | } | ||
190 | |||
191 | if (use_cycle) | ||
192 | init_cycle(); | ||
193 | |||
194 | len = (size_t)perf_atoll((char *)length_str); | ||
195 | |||
196 | result_cycle[0] = result_cycle[1] = 0ULL; | ||
197 | result_bps[0] = result_bps[1] = 0.0; | ||
198 | |||
199 | if ((s64)len <= 0) { | ||
200 | fprintf(stderr, "Invalid length:%s\n", length_str); | ||
201 | return 1; | ||
202 | } | ||
203 | |||
204 | /* same to without specifying either of prefault and no-prefault */ | ||
205 | if (only_prefault && no_prefault) | ||
206 | only_prefault = no_prefault = false; | ||
207 | |||
208 | for (i = 0; routines[i].name; i++) { | ||
209 | if (!strcmp(routines[i].name, routine)) | ||
210 | break; | ||
211 | } | ||
212 | if (!routines[i].name) { | ||
213 | printf("Unknown routine:%s\n", routine); | ||
214 | printf("Available routines...\n"); | ||
215 | for (i = 0; routines[i].name; i++) { | ||
216 | printf("\t%s ... %s\n", | ||
217 | routines[i].name, routines[i].desc); | ||
218 | } | ||
219 | return 1; | ||
220 | } | ||
221 | |||
222 | if (bench_format == BENCH_FORMAT_DEFAULT) | ||
223 | printf("# Copying %s Bytes ...\n\n", length_str); | ||
224 | |||
225 | if (!only_prefault && !no_prefault) { | ||
226 | /* show both of results */ | ||
227 | if (use_cycle) { | ||
228 | result_cycle[0] = | ||
229 | do_memset_cycle(routines[i].fn, len, false); | ||
230 | result_cycle[1] = | ||
231 | do_memset_cycle(routines[i].fn, len, true); | ||
232 | } else { | ||
233 | result_bps[0] = | ||
234 | do_memset_gettimeofday(routines[i].fn, | ||
235 | len, false); | ||
236 | result_bps[1] = | ||
237 | do_memset_gettimeofday(routines[i].fn, | ||
238 | len, true); | ||
239 | } | ||
240 | } else { | ||
241 | if (use_cycle) { | ||
242 | result_cycle[pf] = | ||
243 | do_memset_cycle(routines[i].fn, | ||
244 | len, only_prefault); | ||
245 | } else { | ||
246 | result_bps[pf] = | ||
247 | do_memset_gettimeofday(routines[i].fn, | ||
248 | len, only_prefault); | ||
249 | } | ||
250 | } | ||
251 | |||
252 | switch (bench_format) { | ||
253 | case BENCH_FORMAT_DEFAULT: | ||
254 | if (!only_prefault && !no_prefault) { | ||
255 | if (use_cycle) { | ||
256 | printf(" %14lf Cycle/Byte\n", | ||
257 | (double)result_cycle[0] | ||
258 | / (double)len); | ||
259 | printf(" %14lf Cycle/Byte (with prefault)\n ", | ||
260 | (double)result_cycle[1] | ||
261 | / (double)len); | ||
262 | } else { | ||
263 | print_bps(result_bps[0]); | ||
264 | printf("\n"); | ||
265 | print_bps(result_bps[1]); | ||
266 | printf(" (with prefault)\n"); | ||
267 | } | ||
268 | } else { | ||
269 | if (use_cycle) { | ||
270 | printf(" %14lf Cycle/Byte", | ||
271 | (double)result_cycle[pf] | ||
272 | / (double)len); | ||
273 | } else | ||
274 | print_bps(result_bps[pf]); | ||
275 | |||
276 | printf("%s\n", only_prefault ? " (with prefault)" : ""); | ||
277 | } | ||
278 | break; | ||
279 | case BENCH_FORMAT_SIMPLE: | ||
280 | if (!only_prefault && !no_prefault) { | ||
281 | if (use_cycle) { | ||
282 | printf("%lf %lf\n", | ||
283 | (double)result_cycle[0] / (double)len, | ||
284 | (double)result_cycle[1] / (double)len); | ||
285 | } else { | ||
286 | printf("%lf %lf\n", | ||
287 | result_bps[0], result_bps[1]); | ||
288 | } | ||
289 | } else { | ||
290 | if (use_cycle) { | ||
291 | printf("%lf\n", (double)result_cycle[pf] | ||
292 | / (double)len); | ||
293 | } else | ||
294 | printf("%lf\n", result_bps[pf]); | ||
295 | } | ||
296 | break; | ||
297 | default: | ||
298 | /* reaching this means there's some disaster: */ | ||
299 | die("unknown format: %d\n", bench_format); | ||
300 | break; | ||
301 | } | ||
302 | |||
303 | return 0; | ||
304 | } | ||
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c index 07a8d7646a15..005cc283790c 100644 --- a/tools/perf/bench/sched-pipe.c +++ b/tools/perf/bench/sched-pipe.c | |||
@@ -19,12 +19,12 @@ | |||
19 | #include <stdlib.h> | 19 | #include <stdlib.h> |
20 | #include <signal.h> | 20 | #include <signal.h> |
21 | #include <sys/wait.h> | 21 | #include <sys/wait.h> |
22 | #include <linux/unistd.h> | ||
23 | #include <string.h> | 22 | #include <string.h> |
24 | #include <errno.h> | 23 | #include <errno.h> |
25 | #include <assert.h> | 24 | #include <assert.h> |
26 | #include <sys/time.h> | 25 | #include <sys/time.h> |
27 | #include <sys/types.h> | 26 | #include <sys/types.h> |
27 | #include <sys/syscall.h> | ||
28 | 28 | ||
29 | #include <pthread.h> | 29 | #include <pthread.h> |
30 | 30 | ||
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index e7417fe97a97..747f86103599 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -232,7 +232,7 @@ static int __cmd_annotate(struct perf_annotate *ann) | |||
232 | if (nr_samples > 0) { | 232 | if (nr_samples > 0) { |
233 | total_nr_samples += nr_samples; | 233 | total_nr_samples += nr_samples; |
234 | hists__collapse_resort(hists, NULL); | 234 | hists__collapse_resort(hists, NULL); |
235 | hists__output_resort(hists); | 235 | hists__output_resort(hists, NULL); |
236 | 236 | ||
237 | if (symbol_conf.event_group && | 237 | if (symbol_conf.event_group && |
238 | !perf_evsel__is_group_leader(pos)) | 238 | !perf_evsel__is_group_leader(pos)) |
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c index 70385756da63..77d5cae54c6a 100644 --- a/tools/perf/builtin-buildid-cache.c +++ b/tools/perf/builtin-buildid-cache.c | |||
@@ -285,12 +285,11 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
285 | struct str_node *pos; | 285 | struct str_node *pos; |
286 | int ret = 0; | 286 | int ret = 0; |
287 | bool force = false; | 287 | bool force = false; |
288 | char debugdir[PATH_MAX]; | ||
289 | char const *add_name_list_str = NULL, | 288 | char const *add_name_list_str = NULL, |
290 | *remove_name_list_str = NULL, | 289 | *remove_name_list_str = NULL, |
291 | *missing_filename = NULL, | 290 | *missing_filename = NULL, |
292 | *update_name_list_str = NULL, | 291 | *update_name_list_str = NULL, |
293 | *kcore_filename; | 292 | *kcore_filename = NULL; |
294 | char sbuf[STRERR_BUFSIZE]; | 293 | char sbuf[STRERR_BUFSIZE]; |
295 | 294 | ||
296 | struct perf_data_file file = { | 295 | struct perf_data_file file = { |
@@ -335,13 +334,11 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
335 | 334 | ||
336 | setup_pager(); | 335 | setup_pager(); |
337 | 336 | ||
338 | snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir); | ||
339 | |||
340 | if (add_name_list_str) { | 337 | if (add_name_list_str) { |
341 | list = strlist__new(true, add_name_list_str); | 338 | list = strlist__new(true, add_name_list_str); |
342 | if (list) { | 339 | if (list) { |
343 | strlist__for_each(pos, list) | 340 | strlist__for_each(pos, list) |
344 | if (build_id_cache__add_file(pos->s, debugdir)) { | 341 | if (build_id_cache__add_file(pos->s, buildid_dir)) { |
345 | if (errno == EEXIST) { | 342 | if (errno == EEXIST) { |
346 | pr_debug("%s already in the cache\n", | 343 | pr_debug("%s already in the cache\n", |
347 | pos->s); | 344 | pos->s); |
@@ -359,7 +356,7 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
359 | list = strlist__new(true, remove_name_list_str); | 356 | list = strlist__new(true, remove_name_list_str); |
360 | if (list) { | 357 | if (list) { |
361 | strlist__for_each(pos, list) | 358 | strlist__for_each(pos, list) |
362 | if (build_id_cache__remove_file(pos->s, debugdir)) { | 359 | if (build_id_cache__remove_file(pos->s, buildid_dir)) { |
363 | if (errno == ENOENT) { | 360 | if (errno == ENOENT) { |
364 | pr_debug("%s wasn't in the cache\n", | 361 | pr_debug("%s wasn't in the cache\n", |
365 | pos->s); | 362 | pos->s); |
@@ -380,7 +377,7 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
380 | list = strlist__new(true, update_name_list_str); | 377 | list = strlist__new(true, update_name_list_str); |
381 | if (list) { | 378 | if (list) { |
382 | strlist__for_each(pos, list) | 379 | strlist__for_each(pos, list) |
383 | if (build_id_cache__update_file(pos->s, debugdir)) { | 380 | if (build_id_cache__update_file(pos->s, buildid_dir)) { |
384 | if (errno == ENOENT) { | 381 | if (errno == ENOENT) { |
385 | pr_debug("%s wasn't in the cache\n", | 382 | pr_debug("%s wasn't in the cache\n", |
386 | pos->s); | 383 | pos->s); |
@@ -395,7 +392,7 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
395 | } | 392 | } |
396 | 393 | ||
397 | if (kcore_filename && | 394 | if (kcore_filename && |
398 | build_id_cache__add_kcore(kcore_filename, debugdir, force)) | 395 | build_id_cache__add_kcore(kcore_filename, buildid_dir, force)) |
399 | pr_warning("Couldn't add %s\n", kcore_filename); | 396 | pr_warning("Couldn't add %s\n", kcore_filename); |
400 | 397 | ||
401 | out: | 398 | out: |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 25114c9a6801..1fd96c13f199 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -357,6 +357,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, | |||
357 | static struct perf_tool tool = { | 357 | static struct perf_tool tool = { |
358 | .sample = diff__process_sample_event, | 358 | .sample = diff__process_sample_event, |
359 | .mmap = perf_event__process_mmap, | 359 | .mmap = perf_event__process_mmap, |
360 | .mmap2 = perf_event__process_mmap2, | ||
360 | .comm = perf_event__process_comm, | 361 | .comm = perf_event__process_comm, |
361 | .exit = perf_event__process_exit, | 362 | .exit = perf_event__process_exit, |
362 | .fork = perf_event__process_fork, | 363 | .fork = perf_event__process_fork, |
@@ -544,6 +545,42 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, | |||
544 | return __hist_entry__cmp_compute(p_left, p_right, c); | 545 | return __hist_entry__cmp_compute(p_left, p_right, c); |
545 | } | 546 | } |
546 | 547 | ||
548 | static int64_t | ||
549 | hist_entry__cmp_nop(struct hist_entry *left __maybe_unused, | ||
550 | struct hist_entry *right __maybe_unused) | ||
551 | { | ||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | static int64_t | ||
556 | hist_entry__cmp_baseline(struct hist_entry *left, struct hist_entry *right) | ||
557 | { | ||
558 | if (sort_compute) | ||
559 | return 0; | ||
560 | |||
561 | if (left->stat.period == right->stat.period) | ||
562 | return 0; | ||
563 | return left->stat.period > right->stat.period ? 1 : -1; | ||
564 | } | ||
565 | |||
566 | static int64_t | ||
567 | hist_entry__cmp_delta(struct hist_entry *left, struct hist_entry *right) | ||
568 | { | ||
569 | return hist_entry__cmp_compute(right, left, COMPUTE_DELTA); | ||
570 | } | ||
571 | |||
572 | static int64_t | ||
573 | hist_entry__cmp_ratio(struct hist_entry *left, struct hist_entry *right) | ||
574 | { | ||
575 | return hist_entry__cmp_compute(right, left, COMPUTE_RATIO); | ||
576 | } | ||
577 | |||
578 | static int64_t | ||
579 | hist_entry__cmp_wdiff(struct hist_entry *left, struct hist_entry *right) | ||
580 | { | ||
581 | return hist_entry__cmp_compute(right, left, COMPUTE_WEIGHTED_DIFF); | ||
582 | } | ||
583 | |||
547 | static void insert_hist_entry_by_compute(struct rb_root *root, | 584 | static void insert_hist_entry_by_compute(struct rb_root *root, |
548 | struct hist_entry *he, | 585 | struct hist_entry *he, |
549 | int c) | 586 | int c) |
@@ -604,7 +641,7 @@ static void hists__process(struct hists *hists) | |||
604 | hists__precompute(hists); | 641 | hists__precompute(hists); |
605 | hists__compute_resort(hists); | 642 | hists__compute_resort(hists); |
606 | } else { | 643 | } else { |
607 | hists__output_resort(hists); | 644 | hists__output_resort(hists, NULL); |
608 | } | 645 | } |
609 | 646 | ||
610 | hists__fprintf(hists, true, 0, 0, 0, stdout); | 647 | hists__fprintf(hists, true, 0, 0, 0, stdout); |
@@ -1037,27 +1074,35 @@ static void data__hpp_register(struct data__file *d, int idx) | |||
1037 | fmt->header = hpp__header; | 1074 | fmt->header = hpp__header; |
1038 | fmt->width = hpp__width; | 1075 | fmt->width = hpp__width; |
1039 | fmt->entry = hpp__entry_global; | 1076 | fmt->entry = hpp__entry_global; |
1077 | fmt->cmp = hist_entry__cmp_nop; | ||
1078 | fmt->collapse = hist_entry__cmp_nop; | ||
1040 | 1079 | ||
1041 | /* TODO more colors */ | 1080 | /* TODO more colors */ |
1042 | switch (idx) { | 1081 | switch (idx) { |
1043 | case PERF_HPP_DIFF__BASELINE: | 1082 | case PERF_HPP_DIFF__BASELINE: |
1044 | fmt->color = hpp__color_baseline; | 1083 | fmt->color = hpp__color_baseline; |
1084 | fmt->sort = hist_entry__cmp_baseline; | ||
1045 | break; | 1085 | break; |
1046 | case PERF_HPP_DIFF__DELTA: | 1086 | case PERF_HPP_DIFF__DELTA: |
1047 | fmt->color = hpp__color_delta; | 1087 | fmt->color = hpp__color_delta; |
1088 | fmt->sort = hist_entry__cmp_delta; | ||
1048 | break; | 1089 | break; |
1049 | case PERF_HPP_DIFF__RATIO: | 1090 | case PERF_HPP_DIFF__RATIO: |
1050 | fmt->color = hpp__color_ratio; | 1091 | fmt->color = hpp__color_ratio; |
1092 | fmt->sort = hist_entry__cmp_ratio; | ||
1051 | break; | 1093 | break; |
1052 | case PERF_HPP_DIFF__WEIGHTED_DIFF: | 1094 | case PERF_HPP_DIFF__WEIGHTED_DIFF: |
1053 | fmt->color = hpp__color_wdiff; | 1095 | fmt->color = hpp__color_wdiff; |
1096 | fmt->sort = hist_entry__cmp_wdiff; | ||
1054 | break; | 1097 | break; |
1055 | default: | 1098 | default: |
1099 | fmt->sort = hist_entry__cmp_nop; | ||
1056 | break; | 1100 | break; |
1057 | } | 1101 | } |
1058 | 1102 | ||
1059 | init_header(d, dfmt); | 1103 | init_header(d, dfmt); |
1060 | perf_hpp__column_register(fmt); | 1104 | perf_hpp__column_register(fmt); |
1105 | perf_hpp__register_sort_field(fmt); | ||
1061 | } | 1106 | } |
1062 | 1107 | ||
1063 | static void ui_init(void) | 1108 | static void ui_init(void) |
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index de99ca1bb942..84df2deed988 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
@@ -217,8 +217,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool, | |||
217 | goto repipe; | 217 | goto repipe; |
218 | } | 218 | } |
219 | 219 | ||
220 | thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, | 220 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, &al); |
221 | sample->ip, &al); | ||
222 | 221 | ||
223 | if (al.map != NULL) { | 222 | if (al.map != NULL) { |
224 | if (!al.map->dso->hit) { | 223 | if (!al.map->dso->hit) { |
@@ -410,6 +409,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
410 | .tracing_data = perf_event__repipe_op2_synth, | 409 | .tracing_data = perf_event__repipe_op2_synth, |
411 | .finished_round = perf_event__repipe_op2_synth, | 410 | .finished_round = perf_event__repipe_op2_synth, |
412 | .build_id = perf_event__repipe_op2_synth, | 411 | .build_id = perf_event__repipe_op2_synth, |
412 | .id_index = perf_event__repipe_op2_synth, | ||
413 | }, | 413 | }, |
414 | .input_name = "-", | 414 | .input_name = "-", |
415 | .samples = LIST_HEAD_INIT(inject.samples), | 415 | .samples = LIST_HEAD_INIT(inject.samples), |
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index b65eb0507b38..0894a817f67e 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -1132,6 +1132,10 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv) | |||
1132 | "-m", "1024", | 1132 | "-m", "1024", |
1133 | "-c", "1", | 1133 | "-c", "1", |
1134 | }; | 1134 | }; |
1135 | const char * const kvm_stat_record_usage[] = { | ||
1136 | "perf kvm stat record [<options>]", | ||
1137 | NULL | ||
1138 | }; | ||
1135 | const char * const *events_tp; | 1139 | const char * const *events_tp; |
1136 | events_tp_size = 0; | 1140 | events_tp_size = 0; |
1137 | 1141 | ||
@@ -1159,6 +1163,27 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv) | |||
1159 | for (j = 1; j < (unsigned int)argc; j++, i++) | 1163 | for (j = 1; j < (unsigned int)argc; j++, i++) |
1160 | rec_argv[i] = argv[j]; | 1164 | rec_argv[i] = argv[j]; |
1161 | 1165 | ||
1166 | set_option_flag(record_options, 'e', "event", PARSE_OPT_HIDDEN); | ||
1167 | set_option_flag(record_options, 0, "filter", PARSE_OPT_HIDDEN); | ||
1168 | set_option_flag(record_options, 'R', "raw-samples", PARSE_OPT_HIDDEN); | ||
1169 | |||
1170 | set_option_flag(record_options, 'F', "freq", PARSE_OPT_DISABLED); | ||
1171 | set_option_flag(record_options, 0, "group", PARSE_OPT_DISABLED); | ||
1172 | set_option_flag(record_options, 'g', NULL, PARSE_OPT_DISABLED); | ||
1173 | set_option_flag(record_options, 0, "call-graph", PARSE_OPT_DISABLED); | ||
1174 | set_option_flag(record_options, 'd', "data", PARSE_OPT_DISABLED); | ||
1175 | set_option_flag(record_options, 'T', "timestamp", PARSE_OPT_DISABLED); | ||
1176 | set_option_flag(record_options, 'P', "period", PARSE_OPT_DISABLED); | ||
1177 | set_option_flag(record_options, 'n', "no-samples", PARSE_OPT_DISABLED); | ||
1178 | set_option_flag(record_options, 'N', "no-buildid-cache", PARSE_OPT_DISABLED); | ||
1179 | set_option_flag(record_options, 'B', "no-buildid", PARSE_OPT_DISABLED); | ||
1180 | set_option_flag(record_options, 'G', "cgroup", PARSE_OPT_DISABLED); | ||
1181 | set_option_flag(record_options, 'b', "branch-any", PARSE_OPT_DISABLED); | ||
1182 | set_option_flag(record_options, 'j', "branch-filter", PARSE_OPT_DISABLED); | ||
1183 | set_option_flag(record_options, 'W', "weight", PARSE_OPT_DISABLED); | ||
1184 | set_option_flag(record_options, 0, "transaction", PARSE_OPT_DISABLED); | ||
1185 | |||
1186 | record_usage = kvm_stat_record_usage; | ||
1162 | return cmd_record(i, rec_argv, NULL); | 1187 | return cmd_record(i, rec_argv, NULL); |
1163 | } | 1188 | } |
1164 | 1189 | ||
@@ -1268,7 +1293,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, | |||
1268 | OPT_UINTEGER('d', "display", &kvm->display_time, | 1293 | OPT_UINTEGER('d', "display", &kvm->display_time, |
1269 | "time in seconds between display updates"), | 1294 | "time in seconds between display updates"), |
1270 | OPT_STRING(0, "event", &kvm->report_event, "report event", | 1295 | OPT_STRING(0, "event", &kvm->report_event, "report event", |
1271 | "event for reporting: vmexit, mmio, ioport"), | 1296 | "event for reporting: " |
1297 | "vmexit, mmio (x86 only), ioport (x86 only)"), | ||
1272 | OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu, | 1298 | OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu, |
1273 | "vcpu id to report"), | 1299 | "vcpu id to report"), |
1274 | OPT_STRING('k', "key", &kvm->sort_key, "sort-key", | 1300 | OPT_STRING('k', "key", &kvm->sort_key, "sort-key", |
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index 011195e38f21..198f3c3aff95 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c | |||
@@ -19,7 +19,9 @@ | |||
19 | int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | 19 | int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) |
20 | { | 20 | { |
21 | int i; | 21 | int i; |
22 | const struct option list_options[] = { | 22 | bool raw_dump = false; |
23 | struct option list_options[] = { | ||
24 | OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"), | ||
23 | OPT_END() | 25 | OPT_END() |
24 | }; | 26 | }; |
25 | const char * const list_usage[] = { | 27 | const char * const list_usage[] = { |
@@ -27,11 +29,18 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | |||
27 | NULL | 29 | NULL |
28 | }; | 30 | }; |
29 | 31 | ||
32 | set_option_flag(list_options, 0, "raw-dump", PARSE_OPT_HIDDEN); | ||
33 | |||
30 | argc = parse_options(argc, argv, list_options, list_usage, | 34 | argc = parse_options(argc, argv, list_options, list_usage, |
31 | PARSE_OPT_STOP_AT_NON_OPTION); | 35 | PARSE_OPT_STOP_AT_NON_OPTION); |
32 | 36 | ||
33 | setup_pager(); | 37 | setup_pager(); |
34 | 38 | ||
39 | if (raw_dump) { | ||
40 | print_events(NULL, true); | ||
41 | return 0; | ||
42 | } | ||
43 | |||
35 | if (argc == 0) { | 44 | if (argc == 0) { |
36 | print_events(NULL, false); | 45 | print_events(NULL, false); |
37 | return 0; | 46 | return 0; |
@@ -53,8 +62,6 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | |||
53 | print_hwcache_events(NULL, false); | 62 | print_hwcache_events(NULL, false); |
54 | else if (strcmp(argv[i], "pmu") == 0) | 63 | else if (strcmp(argv[i], "pmu") == 0) |
55 | print_pmu_events(NULL, false); | 64 | print_pmu_events(NULL, false); |
56 | else if (strcmp(argv[i], "--raw-dump") == 0) | ||
57 | print_events(NULL, true); | ||
58 | else { | 65 | else { |
59 | char *sep = strchr(argv[i], ':'), *s; | 66 | char *sep = strchr(argv[i], ':'), *s; |
60 | int sep_idx; | 67 | int sep_idx; |
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 7af26acf06d9..921bb6942503 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -55,6 +55,7 @@ static struct { | |||
55 | bool show_funcs; | 55 | bool show_funcs; |
56 | bool mod_events; | 56 | bool mod_events; |
57 | bool uprobes; | 57 | bool uprobes; |
58 | bool quiet; | ||
58 | int nevents; | 59 | int nevents; |
59 | struct perf_probe_event events[MAX_PROBES]; | 60 | struct perf_probe_event events[MAX_PROBES]; |
60 | struct strlist *dellist; | 61 | struct strlist *dellist; |
@@ -312,9 +313,11 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
312 | #endif | 313 | #endif |
313 | NULL | 314 | NULL |
314 | }; | 315 | }; |
315 | const struct option options[] = { | 316 | struct option options[] = { |
316 | OPT_INCR('v', "verbose", &verbose, | 317 | OPT_INCR('v', "verbose", &verbose, |
317 | "be more verbose (show parsed arguments, etc)"), | 318 | "be more verbose (show parsed arguments, etc)"), |
319 | OPT_BOOLEAN('q', "quiet", ¶ms.quiet, | ||
320 | "be quiet (do not show any mesages)"), | ||
318 | OPT_BOOLEAN('l', "list", ¶ms.list_events, | 321 | OPT_BOOLEAN('l', "list", ¶ms.list_events, |
319 | "list up current probe events"), | 322 | "list up current probe events"), |
320 | OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", | 323 | OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", |
@@ -382,6 +385,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
382 | }; | 385 | }; |
383 | int ret; | 386 | int ret; |
384 | 387 | ||
388 | set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE); | ||
389 | set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE); | ||
390 | set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE); | ||
391 | #ifdef HAVE_DWARF_SUPPORT | ||
392 | set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE); | ||
393 | set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE); | ||
394 | #endif | ||
395 | |||
385 | argc = parse_options(argc, argv, options, probe_usage, | 396 | argc = parse_options(argc, argv, options, probe_usage, |
386 | PARSE_OPT_STOP_AT_NON_OPTION); | 397 | PARSE_OPT_STOP_AT_NON_OPTION); |
387 | if (argc > 0) { | 398 | if (argc > 0) { |
@@ -396,6 +407,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
396 | } | 407 | } |
397 | } | 408 | } |
398 | 409 | ||
410 | if (params.quiet) { | ||
411 | if (verbose != 0) { | ||
412 | pr_err(" Error: -v and -q are exclusive.\n"); | ||
413 | return -EINVAL; | ||
414 | } | ||
415 | verbose = -1; | ||
416 | } | ||
417 | |||
399 | if (params.max_probe_points == 0) | 418 | if (params.max_probe_points == 0) |
400 | params.max_probe_points = MAX_PROBES; | 419 | params.max_probe_points = MAX_PROBES; |
401 | 420 | ||
@@ -409,22 +428,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
409 | symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); | 428 | symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); |
410 | 429 | ||
411 | if (params.list_events) { | 430 | if (params.list_events) { |
412 | if (params.mod_events) { | ||
413 | pr_err(" Error: Don't use --list with --add/--del.\n"); | ||
414 | usage_with_options(probe_usage, options); | ||
415 | } | ||
416 | if (params.show_lines) { | ||
417 | pr_err(" Error: Don't use --list with --line.\n"); | ||
418 | usage_with_options(probe_usage, options); | ||
419 | } | ||
420 | if (params.show_vars) { | ||
421 | pr_err(" Error: Don't use --list with --vars.\n"); | ||
422 | usage_with_options(probe_usage, options); | ||
423 | } | ||
424 | if (params.show_funcs) { | ||
425 | pr_err(" Error: Don't use --list with --funcs.\n"); | ||
426 | usage_with_options(probe_usage, options); | ||
427 | } | ||
428 | if (params.uprobes) { | 431 | if (params.uprobes) { |
429 | pr_warning(" Error: Don't use --list with --exec.\n"); | 432 | pr_warning(" Error: Don't use --list with --exec.\n"); |
430 | usage_with_options(probe_usage, options); | 433 | usage_with_options(probe_usage, options); |
@@ -435,19 +438,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
435 | return ret; | 438 | return ret; |
436 | } | 439 | } |
437 | if (params.show_funcs) { | 440 | if (params.show_funcs) { |
438 | if (params.nevents != 0 || params.dellist) { | ||
439 | pr_err(" Error: Don't use --funcs with" | ||
440 | " --add/--del.\n"); | ||
441 | usage_with_options(probe_usage, options); | ||
442 | } | ||
443 | if (params.show_lines) { | ||
444 | pr_err(" Error: Don't use --funcs with --line.\n"); | ||
445 | usage_with_options(probe_usage, options); | ||
446 | } | ||
447 | if (params.show_vars) { | ||
448 | pr_err(" Error: Don't use --funcs with --vars.\n"); | ||
449 | usage_with_options(probe_usage, options); | ||
450 | } | ||
451 | if (!params.filter) | 441 | if (!params.filter) |
452 | params.filter = strfilter__new(DEFAULT_FUNC_FILTER, | 442 | params.filter = strfilter__new(DEFAULT_FUNC_FILTER, |
453 | NULL); | 443 | NULL); |
@@ -462,16 +452,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
462 | 452 | ||
463 | #ifdef HAVE_DWARF_SUPPORT | 453 | #ifdef HAVE_DWARF_SUPPORT |
464 | if (params.show_lines) { | 454 | if (params.show_lines) { |
465 | if (params.mod_events) { | ||
466 | pr_err(" Error: Don't use --line with" | ||
467 | " --add/--del.\n"); | ||
468 | usage_with_options(probe_usage, options); | ||
469 | } | ||
470 | if (params.show_vars) { | ||
471 | pr_err(" Error: Don't use --line with --vars.\n"); | ||
472 | usage_with_options(probe_usage, options); | ||
473 | } | ||
474 | |||
475 | ret = show_line_range(¶ms.line_range, params.target, | 455 | ret = show_line_range(¶ms.line_range, params.target, |
476 | params.uprobes); | 456 | params.uprobes); |
477 | if (ret < 0) | 457 | if (ret < 0) |
@@ -479,11 +459,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
479 | return ret; | 459 | return ret; |
480 | } | 460 | } |
481 | if (params.show_vars) { | 461 | if (params.show_vars) { |
482 | if (params.mod_events) { | ||
483 | pr_err(" Error: Don't use --vars with" | ||
484 | " --add/--del.\n"); | ||
485 | usage_with_options(probe_usage, options); | ||
486 | } | ||
487 | if (!params.filter) | 462 | if (!params.filter) |
488 | params.filter = strfilter__new(DEFAULT_VAR_FILTER, | 463 | params.filter = strfilter__new(DEFAULT_VAR_FILTER, |
489 | NULL); | 464 | NULL); |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 2583a9b04317..8648c6d3003d 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -200,6 +200,17 @@ static int process_buildids(struct record *rec) | |||
200 | if (size == 0) | 200 | if (size == 0) |
201 | return 0; | 201 | return 0; |
202 | 202 | ||
203 | /* | ||
204 | * During this process, it'll load kernel map and replace the | ||
205 | * dso->long_name to a real pathname it found. In this case | ||
206 | * we prefer the vmlinux path like | ||
207 | * /lib/modules/3.16.4/build/vmlinux | ||
208 | * | ||
209 | * rather than build-id path (in debug directory). | ||
210 | * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 | ||
211 | */ | ||
212 | symbol_conf.ignore_vmlinux_buildid = true; | ||
213 | |||
203 | return __perf_session__process_events(session, start, | 214 | return __perf_session__process_events(session, start, |
204 | size - start, | 215 | size - start, |
205 | size, &build_id__mark_dso_hit_ops); | 216 | size, &build_id__mark_dso_hit_ops); |
@@ -680,11 +691,12 @@ static int perf_record_config(const char *var, const char *value, void *cb) | |||
680 | return perf_default_config(var, value, cb); | 691 | return perf_default_config(var, value, cb); |
681 | } | 692 | } |
682 | 693 | ||
683 | static const char * const record_usage[] = { | 694 | static const char * const __record_usage[] = { |
684 | "perf record [<options>] [<command>]", | 695 | "perf record [<options>] [<command>]", |
685 | "perf record [<options>] -- <command> [<options>]", | 696 | "perf record [<options>] -- <command> [<options>]", |
686 | NULL | 697 | NULL |
687 | }; | 698 | }; |
699 | const char * const *record_usage = __record_usage; | ||
688 | 700 | ||
689 | /* | 701 | /* |
690 | * XXX Ideally would be local to cmd_record() and passed to a record__new | 702 | * XXX Ideally would be local to cmd_record() and passed to a record__new |
@@ -725,7 +737,7 @@ const char record_callchain_help[] = CALLCHAIN_HELP "fp"; | |||
725 | * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', | 737 | * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', |
726 | * using pipes, etc. | 738 | * using pipes, etc. |
727 | */ | 739 | */ |
728 | const struct option record_options[] = { | 740 | struct option __record_options[] = { |
729 | OPT_CALLBACK('e', "event", &record.evlist, "event", | 741 | OPT_CALLBACK('e', "event", &record.evlist, "event", |
730 | "event selector. use 'perf list' to list available events", | 742 | "event selector. use 'perf list' to list available events", |
731 | parse_events_option), | 743 | parse_events_option), |
@@ -799,9 +811,13 @@ const struct option record_options[] = { | |||
799 | "sample transaction flags (special events only)"), | 811 | "sample transaction flags (special events only)"), |
800 | OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, | 812 | OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, |
801 | "use per-thread mmaps"), | 813 | "use per-thread mmaps"), |
814 | OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs, | ||
815 | "Sample machine registers on interrupt"), | ||
802 | OPT_END() | 816 | OPT_END() |
803 | }; | 817 | }; |
804 | 818 | ||
819 | struct option *record_options = __record_options; | ||
820 | |||
805 | int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) | 821 | int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) |
806 | { | 822 | { |
807 | int err = -ENOMEM; | 823 | int err = -ENOMEM; |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 140a6cd88351..072ae8ad67fc 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -226,8 +226,9 @@ static int report__setup_sample_type(struct report *rep) | |||
226 | return -EINVAL; | 226 | return -EINVAL; |
227 | } | 227 | } |
228 | if (symbol_conf.use_callchain) { | 228 | if (symbol_conf.use_callchain) { |
229 | ui__error("Selected -g but no callchain data. Did " | 229 | ui__error("Selected -g or --branch-history but no " |
230 | "you call 'perf record' without -g?\n"); | 230 | "callchain data. Did\n" |
231 | "you call 'perf record' without -g?\n"); | ||
231 | return -1; | 232 | return -1; |
232 | } | 233 | } |
233 | } else if (!rep->dont_use_callchains && | 234 | } else if (!rep->dont_use_callchains && |
@@ -456,6 +457,19 @@ static void report__collapse_hists(struct report *rep) | |||
456 | ui_progress__finish(); | 457 | ui_progress__finish(); |
457 | } | 458 | } |
458 | 459 | ||
460 | static void report__output_resort(struct report *rep) | ||
461 | { | ||
462 | struct ui_progress prog; | ||
463 | struct perf_evsel *pos; | ||
464 | |||
465 | ui_progress__init(&prog, rep->nr_entries, "Sorting events for output..."); | ||
466 | |||
467 | evlist__for_each(rep->session->evlist, pos) | ||
468 | hists__output_resort(evsel__hists(pos), &prog); | ||
469 | |||
470 | ui_progress__finish(); | ||
471 | } | ||
472 | |||
459 | static int __cmd_report(struct report *rep) | 473 | static int __cmd_report(struct report *rep) |
460 | { | 474 | { |
461 | int ret; | 475 | int ret; |
@@ -504,13 +518,20 @@ static int __cmd_report(struct report *rep) | |||
504 | if (session_done()) | 518 | if (session_done()) |
505 | return 0; | 519 | return 0; |
506 | 520 | ||
521 | /* | ||
522 | * recalculate number of entries after collapsing since it | ||
523 | * might be changed during the collapse phase. | ||
524 | */ | ||
525 | rep->nr_entries = 0; | ||
526 | evlist__for_each(session->evlist, pos) | ||
527 | rep->nr_entries += evsel__hists(pos)->nr_entries; | ||
528 | |||
507 | if (rep->nr_entries == 0) { | 529 | if (rep->nr_entries == 0) { |
508 | ui__error("The %s file has no samples!\n", file->path); | 530 | ui__error("The %s file has no samples!\n", file->path); |
509 | return 0; | 531 | return 0; |
510 | } | 532 | } |
511 | 533 | ||
512 | evlist__for_each(session->evlist, pos) | 534 | report__output_resort(rep); |
513 | hists__output_resort(evsel__hists(pos)); | ||
514 | 535 | ||
515 | return report__browse_hists(rep); | 536 | return report__browse_hists(rep); |
516 | } | 537 | } |
@@ -575,6 +596,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
575 | struct stat st; | 596 | struct stat st; |
576 | bool has_br_stack = false; | 597 | bool has_br_stack = false; |
577 | int branch_mode = -1; | 598 | int branch_mode = -1; |
599 | bool branch_call_mode = false; | ||
578 | char callchain_default_opt[] = "fractal,0.5,callee"; | 600 | char callchain_default_opt[] = "fractal,0.5,callee"; |
579 | const char * const report_usage[] = { | 601 | const char * const report_usage[] = { |
580 | "perf report [<options>]", | 602 | "perf report [<options>]", |
@@ -637,8 +659,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
637 | "regex filter to identify parent, see: '--sort parent'"), | 659 | "regex filter to identify parent, see: '--sort parent'"), |
638 | OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, | 660 | OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, |
639 | "Only display entries with parent-match"), | 661 | "Only display entries with parent-match"), |
640 | OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order", | 662 | OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order[,branch]", |
641 | "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). " | 663 | "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address), add branches. " |
642 | "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt), | 664 | "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt), |
643 | OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, | 665 | OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, |
644 | "Accumulate callchains of children and show total overhead as well"), | 666 | "Accumulate callchains of children and show total overhead as well"), |
@@ -684,7 +706,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
684 | OPT_BOOLEAN(0, "group", &symbol_conf.event_group, | 706 | OPT_BOOLEAN(0, "group", &symbol_conf.event_group, |
685 | "Show event group information together"), | 707 | "Show event group information together"), |
686 | OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "", | 708 | OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "", |
687 | "use branch records for histogram filling", parse_branch_mode), | 709 | "use branch records for per branch histogram filling", |
710 | parse_branch_mode), | ||
711 | OPT_BOOLEAN(0, "branch-history", &branch_call_mode, | ||
712 | "add last branch records to call history"), | ||
688 | OPT_STRING(0, "objdump", &objdump_path, "path", | 713 | OPT_STRING(0, "objdump", &objdump_path, "path", |
689 | "objdump binary to use for disassembly and annotations"), | 714 | "objdump binary to use for disassembly and annotations"), |
690 | OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, | 715 | OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, |
@@ -745,10 +770,24 @@ repeat: | |||
745 | has_br_stack = perf_header__has_feat(&session->header, | 770 | has_br_stack = perf_header__has_feat(&session->header, |
746 | HEADER_BRANCH_STACK); | 771 | HEADER_BRANCH_STACK); |
747 | 772 | ||
748 | if ((branch_mode == -1 && has_br_stack) || branch_mode == 1) { | 773 | /* |
774 | * Branch mode is a tristate: | ||
775 | * -1 means default, so decide based on the file having branch data. | ||
776 | * 0/1 means the user chose a mode. | ||
777 | */ | ||
778 | if (((branch_mode == -1 && has_br_stack) || branch_mode == 1) && | ||
779 | branch_call_mode == -1) { | ||
749 | sort__mode = SORT_MODE__BRANCH; | 780 | sort__mode = SORT_MODE__BRANCH; |
750 | symbol_conf.cumulate_callchain = false; | 781 | symbol_conf.cumulate_callchain = false; |
751 | } | 782 | } |
783 | if (branch_call_mode) { | ||
784 | callchain_param.key = CCKEY_ADDRESS; | ||
785 | callchain_param.branch_callstack = 1; | ||
786 | symbol_conf.use_callchain = true; | ||
787 | callchain_register_param(&callchain_param); | ||
788 | if (sort_order == NULL) | ||
789 | sort_order = "srcline,symbol,dso"; | ||
790 | } | ||
752 | 791 | ||
753 | if (report.mem_mode) { | 792 | if (report.mem_mode) { |
754 | if (sort__mode == SORT_MODE__BRANCH) { | 793 | if (sort__mode == SORT_MODE__BRANCH) { |
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 9708a1290571..ce304dfd962a 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -23,7 +23,6 @@ static char const *generate_script_lang; | |||
23 | static bool debug_mode; | 23 | static bool debug_mode; |
24 | static u64 last_timestamp; | 24 | static u64 last_timestamp; |
25 | static u64 nr_unordered; | 25 | static u64 nr_unordered; |
26 | extern const struct option record_options[]; | ||
27 | static bool no_callchain; | 26 | static bool no_callchain; |
28 | static bool latency_format; | 27 | static bool latency_format; |
29 | static bool system_wide; | 28 | static bool system_wide; |
@@ -379,7 +378,6 @@ static void print_sample_start(struct perf_sample *sample, | |||
379 | 378 | ||
380 | static void print_sample_addr(union perf_event *event, | 379 | static void print_sample_addr(union perf_event *event, |
381 | struct perf_sample *sample, | 380 | struct perf_sample *sample, |
382 | struct machine *machine, | ||
383 | struct thread *thread, | 381 | struct thread *thread, |
384 | struct perf_event_attr *attr) | 382 | struct perf_event_attr *attr) |
385 | { | 383 | { |
@@ -390,7 +388,7 @@ static void print_sample_addr(union perf_event *event, | |||
390 | if (!sample_addr_correlates_sym(attr)) | 388 | if (!sample_addr_correlates_sym(attr)) |
391 | return; | 389 | return; |
392 | 390 | ||
393 | perf_event__preprocess_sample_addr(event, sample, machine, thread, &al); | 391 | perf_event__preprocess_sample_addr(event, sample, thread, &al); |
394 | 392 | ||
395 | if (PRINT_FIELD(SYM)) { | 393 | if (PRINT_FIELD(SYM)) { |
396 | printf(" "); | 394 | printf(" "); |
@@ -438,7 +436,7 @@ static void print_sample_bts(union perf_event *event, | |||
438 | ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && | 436 | ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && |
439 | !output[attr->type].user_set)) { | 437 | !output[attr->type].user_set)) { |
440 | printf(" => "); | 438 | printf(" => "); |
441 | print_sample_addr(event, sample, al->machine, thread, attr); | 439 | print_sample_addr(event, sample, thread, attr); |
442 | } | 440 | } |
443 | 441 | ||
444 | if (print_srcline_last) | 442 | if (print_srcline_last) |
@@ -475,7 +473,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample, | |||
475 | event_format__print(evsel->tp_format, sample->cpu, | 473 | event_format__print(evsel->tp_format, sample->cpu, |
476 | sample->raw_data, sample->raw_size); | 474 | sample->raw_data, sample->raw_size); |
477 | if (PRINT_FIELD(ADDR)) | 475 | if (PRINT_FIELD(ADDR)) |
478 | print_sample_addr(event, sample, al->machine, thread, attr); | 476 | print_sample_addr(event, sample, thread, attr); |
479 | 477 | ||
480 | if (PRINT_FIELD(IP)) { | 478 | if (PRINT_FIELD(IP)) { |
481 | if (!symbol_conf.use_callchain) | 479 | if (!symbol_conf.use_callchain) |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 055ce9232c9e..891086376381 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -388,20 +388,102 @@ static void update_shadow_stats(struct perf_evsel *counter, u64 *count) | |||
388 | update_stats(&runtime_itlb_cache_stats[0], count[0]); | 388 | update_stats(&runtime_itlb_cache_stats[0], count[0]); |
389 | } | 389 | } |
390 | 390 | ||
391 | static void zero_per_pkg(struct perf_evsel *counter) | ||
392 | { | ||
393 | if (counter->per_pkg_mask) | ||
394 | memset(counter->per_pkg_mask, 0, MAX_NR_CPUS); | ||
395 | } | ||
396 | |||
397 | static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip) | ||
398 | { | ||
399 | unsigned long *mask = counter->per_pkg_mask; | ||
400 | struct cpu_map *cpus = perf_evsel__cpus(counter); | ||
401 | int s; | ||
402 | |||
403 | *skip = false; | ||
404 | |||
405 | if (!counter->per_pkg) | ||
406 | return 0; | ||
407 | |||
408 | if (cpu_map__empty(cpus)) | ||
409 | return 0; | ||
410 | |||
411 | if (!mask) { | ||
412 | mask = zalloc(MAX_NR_CPUS); | ||
413 | if (!mask) | ||
414 | return -ENOMEM; | ||
415 | |||
416 | counter->per_pkg_mask = mask; | ||
417 | } | ||
418 | |||
419 | s = cpu_map__get_socket(cpus, cpu); | ||
420 | if (s < 0) | ||
421 | return -1; | ||
422 | |||
423 | *skip = test_and_set_bit(s, mask) == 1; | ||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused, | ||
428 | struct perf_counts_values *count) | ||
429 | { | ||
430 | struct perf_counts_values *aggr = &evsel->counts->aggr; | ||
431 | static struct perf_counts_values zero; | ||
432 | bool skip = false; | ||
433 | |||
434 | if (check_per_pkg(evsel, cpu, &skip)) { | ||
435 | pr_err("failed to read per-pkg counter\n"); | ||
436 | return -1; | ||
437 | } | ||
438 | |||
439 | if (skip) | ||
440 | count = &zero; | ||
441 | |||
442 | switch (aggr_mode) { | ||
443 | case AGGR_CORE: | ||
444 | case AGGR_SOCKET: | ||
445 | case AGGR_NONE: | ||
446 | if (!evsel->snapshot) | ||
447 | perf_evsel__compute_deltas(evsel, cpu, count); | ||
448 | perf_counts_values__scale(count, scale, NULL); | ||
449 | evsel->counts->cpu[cpu] = *count; | ||
450 | update_shadow_stats(evsel, count->values); | ||
451 | break; | ||
452 | case AGGR_GLOBAL: | ||
453 | aggr->val += count->val; | ||
454 | if (scale) { | ||
455 | aggr->ena += count->ena; | ||
456 | aggr->run += count->run; | ||
457 | } | ||
458 | default: | ||
459 | break; | ||
460 | } | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static int read_counter(struct perf_evsel *counter); | ||
466 | |||
391 | /* | 467 | /* |
392 | * Read out the results of a single counter: | 468 | * Read out the results of a single counter: |
393 | * aggregate counts across CPUs in system-wide mode | 469 | * aggregate counts across CPUs in system-wide mode |
394 | */ | 470 | */ |
395 | static int read_counter_aggr(struct perf_evsel *counter) | 471 | static int read_counter_aggr(struct perf_evsel *counter) |
396 | { | 472 | { |
473 | struct perf_counts_values *aggr = &counter->counts->aggr; | ||
397 | struct perf_stat *ps = counter->priv; | 474 | struct perf_stat *ps = counter->priv; |
398 | u64 *count = counter->counts->aggr.values; | 475 | u64 *count = counter->counts->aggr.values; |
399 | int i; | 476 | int i; |
400 | 477 | ||
401 | if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter), | 478 | aggr->val = aggr->ena = aggr->run = 0; |
402 | thread_map__nr(evsel_list->threads), scale) < 0) | 479 | |
480 | if (read_counter(counter)) | ||
403 | return -1; | 481 | return -1; |
404 | 482 | ||
483 | if (!counter->snapshot) | ||
484 | perf_evsel__compute_deltas(counter, -1, aggr); | ||
485 | perf_counts_values__scale(aggr, scale, &counter->counts->scaled); | ||
486 | |||
405 | for (i = 0; i < 3; i++) | 487 | for (i = 0; i < 3; i++) |
406 | update_stats(&ps->res_stats[i], count[i]); | 488 | update_stats(&ps->res_stats[i], count[i]); |
407 | 489 | ||
@@ -424,16 +506,21 @@ static int read_counter_aggr(struct perf_evsel *counter) | |||
424 | */ | 506 | */ |
425 | static int read_counter(struct perf_evsel *counter) | 507 | static int read_counter(struct perf_evsel *counter) |
426 | { | 508 | { |
427 | u64 *count; | 509 | int nthreads = thread_map__nr(evsel_list->threads); |
428 | int cpu; | 510 | int ncpus = perf_evsel__nr_cpus(counter); |
511 | int cpu, thread; | ||
429 | 512 | ||
430 | for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { | 513 | if (counter->system_wide) |
431 | if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) | 514 | nthreads = 1; |
432 | return -1; | ||
433 | 515 | ||
434 | count = counter->counts->cpu[cpu].values; | 516 | if (counter->per_pkg) |
517 | zero_per_pkg(counter); | ||
435 | 518 | ||
436 | update_shadow_stats(counter, count); | 519 | for (thread = 0; thread < nthreads; thread++) { |
520 | for (cpu = 0; cpu < ncpus; cpu++) { | ||
521 | if (perf_evsel__read_cb(counter, cpu, thread, read_cb)) | ||
522 | return -1; | ||
523 | } | ||
437 | } | 524 | } |
438 | 525 | ||
439 | return 0; | 526 | return 0; |
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 35b425b6293f..f3bb1a4bf060 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -528,7 +528,7 @@ static const char *cat_backtrace(union perf_event *event, | |||
528 | } | 528 | } |
529 | 529 | ||
530 | tal.filtered = 0; | 530 | tal.filtered = 0; |
531 | thread__find_addr_location(al.thread, machine, cpumode, | 531 | thread__find_addr_location(al.thread, cpumode, |
532 | MAP__FUNCTION, ip, &tal); | 532 | MAP__FUNCTION, ip, &tal); |
533 | 533 | ||
534 | if (tal.sym) | 534 | if (tal.sym) |
@@ -1963,7 +1963,7 @@ int cmd_timechart(int argc, const char **argv, | |||
1963 | NULL | 1963 | NULL |
1964 | }; | 1964 | }; |
1965 | 1965 | ||
1966 | const struct option record_options[] = { | 1966 | const struct option timechart_record_options[] = { |
1967 | OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"), | 1967 | OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"), |
1968 | OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only, | 1968 | OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only, |
1969 | "output processes data only"), | 1969 | "output processes data only"), |
@@ -1972,7 +1972,7 @@ int cmd_timechart(int argc, const char **argv, | |||
1972 | OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"), | 1972 | OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"), |
1973 | OPT_END() | 1973 | OPT_END() |
1974 | }; | 1974 | }; |
1975 | const char * const record_usage[] = { | 1975 | const char * const timechart_record_usage[] = { |
1976 | "perf timechart record [<options>]", | 1976 | "perf timechart record [<options>]", |
1977 | NULL | 1977 | NULL |
1978 | }; | 1978 | }; |
@@ -1985,7 +1985,8 @@ int cmd_timechart(int argc, const char **argv, | |||
1985 | } | 1985 | } |
1986 | 1986 | ||
1987 | if (argc && !strncmp(argv[0], "rec", 3)) { | 1987 | if (argc && !strncmp(argv[0], "rec", 3)) { |
1988 | argc = parse_options(argc, argv, record_options, record_usage, | 1988 | argc = parse_options(argc, argv, timechart_record_options, |
1989 | timechart_record_usage, | ||
1989 | PARSE_OPT_STOP_AT_NON_OPTION); | 1990 | PARSE_OPT_STOP_AT_NON_OPTION); |
1990 | 1991 | ||
1991 | if (tchart.power_only && tchart.tasks_only) { | 1992 | if (tchart.power_only && tchart.tasks_only) { |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 0aa7747ff139..616f0fcb4701 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -66,7 +66,6 @@ | |||
66 | #include <sys/utsname.h> | 66 | #include <sys/utsname.h> |
67 | #include <sys/mman.h> | 67 | #include <sys/mman.h> |
68 | 68 | ||
69 | #include <linux/unistd.h> | ||
70 | #include <linux/types.h> | 69 | #include <linux/types.h> |
71 | 70 | ||
72 | static volatile int done; | 71 | static volatile int done; |
@@ -285,7 +284,7 @@ static void perf_top__print_sym_table(struct perf_top *top) | |||
285 | } | 284 | } |
286 | 285 | ||
287 | hists__collapse_resort(hists, NULL); | 286 | hists__collapse_resort(hists, NULL); |
288 | hists__output_resort(hists); | 287 | hists__output_resort(hists, NULL); |
289 | 288 | ||
290 | hists__output_recalc_col_len(hists, top->print_entries - printed); | 289 | hists__output_recalc_col_len(hists, top->print_entries - printed); |
291 | putchar('\n'); | 290 | putchar('\n'); |
@@ -554,7 +553,7 @@ static void perf_top__sort_new_samples(void *arg) | |||
554 | } | 553 | } |
555 | 554 | ||
556 | hists__collapse_resort(hists, NULL); | 555 | hists__collapse_resort(hists, NULL); |
557 | hists__output_resort(hists); | 556 | hists__output_resort(hists, NULL); |
558 | } | 557 | } |
559 | 558 | ||
560 | static void *display_thread_tui(void *arg) | 559 | static void *display_thread_tui(void *arg) |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index fb126459b134..badfabc6a01f 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -1846,7 +1846,7 @@ static int trace__pgfault(struct trace *trace, | |||
1846 | if (trace->summary_only) | 1846 | if (trace->summary_only) |
1847 | return 0; | 1847 | return 0; |
1848 | 1848 | ||
1849 | thread__find_addr_location(thread, trace->host, cpumode, MAP__FUNCTION, | 1849 | thread__find_addr_location(thread, cpumode, MAP__FUNCTION, |
1850 | sample->ip, &al); | 1850 | sample->ip, &al); |
1851 | 1851 | ||
1852 | trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output); | 1852 | trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output); |
@@ -1859,11 +1859,11 @@ static int trace__pgfault(struct trace *trace, | |||
1859 | 1859 | ||
1860 | fprintf(trace->output, "] => "); | 1860 | fprintf(trace->output, "] => "); |
1861 | 1861 | ||
1862 | thread__find_addr_location(thread, trace->host, cpumode, MAP__VARIABLE, | 1862 | thread__find_addr_location(thread, cpumode, MAP__VARIABLE, |
1863 | sample->addr, &al); | 1863 | sample->addr, &al); |
1864 | 1864 | ||
1865 | if (!al.map) { | 1865 | if (!al.map) { |
1866 | thread__find_addr_location(thread, trace->host, cpumode, | 1866 | thread__find_addr_location(thread, cpumode, |
1867 | MAP__FUNCTION, sample->addr, &al); | 1867 | MAP__FUNCTION, sample->addr, &al); |
1868 | 1868 | ||
1869 | if (al.map) | 1869 | if (al.map) |
@@ -2045,7 +2045,6 @@ static int trace__run(struct trace *trace, int argc, const char **argv) | |||
2045 | unsigned long before; | 2045 | unsigned long before; |
2046 | const bool forks = argc > 0; | 2046 | const bool forks = argc > 0; |
2047 | bool draining = false; | 2047 | bool draining = false; |
2048 | char sbuf[STRERR_BUFSIZE]; | ||
2049 | 2048 | ||
2050 | trace->live = true; | 2049 | trace->live = true; |
2051 | 2050 | ||
@@ -2106,11 +2105,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv) | |||
2106 | goto out_error_open; | 2105 | goto out_error_open; |
2107 | 2106 | ||
2108 | err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false); | 2107 | err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false); |
2109 | if (err < 0) { | 2108 | if (err < 0) |
2110 | fprintf(trace->output, "Couldn't mmap the events: %s\n", | 2109 | goto out_error_mmap; |
2111 | strerror_r(errno, sbuf, sizeof(sbuf))); | ||
2112 | goto out_delete_evlist; | ||
2113 | } | ||
2114 | 2110 | ||
2115 | perf_evlist__enable(evlist); | 2111 | perf_evlist__enable(evlist); |
2116 | 2112 | ||
@@ -2210,6 +2206,10 @@ out_error_tp: | |||
2210 | perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf)); | 2206 | perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf)); |
2211 | goto out_error; | 2207 | goto out_error; |
2212 | 2208 | ||
2209 | out_error_mmap: | ||
2210 | perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf)); | ||
2211 | goto out_error; | ||
2212 | |||
2213 | out_error_open: | 2213 | out_error_open: |
2214 | perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); | 2214 | perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); |
2215 | 2215 | ||
@@ -2485,7 +2485,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) | |||
2485 | .user_freq = UINT_MAX, | 2485 | .user_freq = UINT_MAX, |
2486 | .user_interval = ULLONG_MAX, | 2486 | .user_interval = ULLONG_MAX, |
2487 | .no_buffering = true, | 2487 | .no_buffering = true, |
2488 | .mmap_pages = 1024, | 2488 | .mmap_pages = UINT_MAX, |
2489 | }, | 2489 | }, |
2490 | .output = stdout, | 2490 | .output = stdout, |
2491 | .show_comm = true, | 2491 | .show_comm = true, |
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 58f609198c6d..648e31ff4021 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
@@ -20,7 +20,7 @@ NO_PERF_REGS := 1 | |||
20 | 20 | ||
21 | # Additional ARCH settings for x86 | 21 | # Additional ARCH settings for x86 |
22 | ifeq ($(ARCH),x86) | 22 | ifeq ($(ARCH),x86) |
23 | ifeq (${IS_X86_64}, 1) | 23 | ifeq (${IS_64_BIT}, 1) |
24 | CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT | 24 | CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT |
25 | ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S | 25 | ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S |
26 | LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 | 26 | LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 |
@@ -150,7 +150,7 @@ CFLAGS += -std=gnu99 | |||
150 | # adding assembler files missing the .GNU-stack linker note. | 150 | # adding assembler files missing the .GNU-stack linker note. |
151 | LDFLAGS += -Wl,-z,noexecstack | 151 | LDFLAGS += -Wl,-z,noexecstack |
152 | 152 | ||
153 | EXTLIBS = -lelf -lpthread -lrt -lm -ldl | 153 | EXTLIBS = -lpthread -lrt -lm -ldl |
154 | 154 | ||
155 | ifneq ($(OUTPUT),) | 155 | ifneq ($(OUTPUT),) |
156 | OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/ | 156 | OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/ |
@@ -200,7 +200,8 @@ CORE_FEATURE_TESTS = \ | |||
200 | libunwind \ | 200 | libunwind \ |
201 | stackprotector-all \ | 201 | stackprotector-all \ |
202 | timerfd \ | 202 | timerfd \ |
203 | libdw-dwarf-unwind | 203 | libdw-dwarf-unwind \ |
204 | zlib | ||
204 | 205 | ||
205 | LIB_FEATURE_TESTS = \ | 206 | LIB_FEATURE_TESTS = \ |
206 | dwarf \ | 207 | dwarf \ |
@@ -214,7 +215,8 @@ LIB_FEATURE_TESTS = \ | |||
214 | libpython \ | 215 | libpython \ |
215 | libslang \ | 216 | libslang \ |
216 | libunwind \ | 217 | libunwind \ |
217 | libdw-dwarf-unwind | 218 | libdw-dwarf-unwind \ |
219 | zlib | ||
218 | 220 | ||
219 | VF_FEATURE_TESTS = \ | 221 | VF_FEATURE_TESTS = \ |
220 | backtrace \ | 222 | backtrace \ |
@@ -230,7 +232,9 @@ VF_FEATURE_TESTS = \ | |||
230 | bionic \ | 232 | bionic \ |
231 | liberty \ | 233 | liberty \ |
232 | liberty-z \ | 234 | liberty-z \ |
233 | cplus-demangle | 235 | cplus-demangle \ |
236 | compile-32 \ | ||
237 | compile-x32 | ||
234 | 238 | ||
235 | # Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features. | 239 | # Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features. |
236 | # If in the future we need per-feature checks/flags for features not | 240 | # If in the future we need per-feature checks/flags for features not |
@@ -350,6 +354,7 @@ endif # NO_LIBELF | |||
350 | 354 | ||
351 | ifndef NO_LIBELF | 355 | ifndef NO_LIBELF |
352 | CFLAGS += -DHAVE_LIBELF_SUPPORT | 356 | CFLAGS += -DHAVE_LIBELF_SUPPORT |
357 | EXTLIBS += -lelf | ||
353 | 358 | ||
354 | ifeq ($(feature-libelf-mmap), 1) | 359 | ifeq ($(feature-libelf-mmap), 1) |
355 | CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT | 360 | CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT |
@@ -369,7 +374,7 @@ ifndef NO_LIBELF | |||
369 | else | 374 | else |
370 | CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS) | 375 | CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS) |
371 | LDFLAGS += $(LIBDW_LDFLAGS) | 376 | LDFLAGS += $(LIBDW_LDFLAGS) |
372 | EXTLIBS += -lelf -ldw | 377 | EXTLIBS += -ldw |
373 | endif # PERF_HAVE_DWARF_REGS | 378 | endif # PERF_HAVE_DWARF_REGS |
374 | endif # NO_DWARF | 379 | endif # NO_DWARF |
375 | endif # NO_LIBELF | 380 | endif # NO_LIBELF |
@@ -602,6 +607,15 @@ ifneq ($(filter -lbfd,$(EXTLIBS)),) | |||
602 | CFLAGS += -DHAVE_LIBBFD_SUPPORT | 607 | CFLAGS += -DHAVE_LIBBFD_SUPPORT |
603 | endif | 608 | endif |
604 | 609 | ||
610 | ifndef NO_ZLIB | ||
611 | ifeq ($(feature-zlib), 1) | ||
612 | CFLAGS += -DHAVE_ZLIB_SUPPORT | ||
613 | EXTLIBS += -lz | ||
614 | else | ||
615 | NO_ZLIB := 1 | ||
616 | endif | ||
617 | endif | ||
618 | |||
605 | ifndef NO_BACKTRACE | 619 | ifndef NO_BACKTRACE |
606 | ifeq ($(feature-backtrace), 1) | 620 | ifeq ($(feature-backtrace), 1) |
607 | CFLAGS += -DHAVE_BACKTRACE_SUPPORT | 621 | CFLAGS += -DHAVE_BACKTRACE_SUPPORT |
@@ -622,6 +636,31 @@ ifdef HAVE_KVM_STAT_SUPPORT | |||
622 | CFLAGS += -DHAVE_KVM_STAT_SUPPORT | 636 | CFLAGS += -DHAVE_KVM_STAT_SUPPORT |
623 | endif | 637 | endif |
624 | 638 | ||
639 | ifeq (${IS_64_BIT}, 1) | ||
640 | ifndef NO_PERF_READ_VDSO32 | ||
641 | $(call feature_check,compile-32) | ||
642 | ifeq ($(feature-compile-32), 1) | ||
643 | CFLAGS += -DHAVE_PERF_READ_VDSO32 | ||
644 | else | ||
645 | NO_PERF_READ_VDSO32 := 1 | ||
646 | endif | ||
647 | endif | ||
648 | ifneq (${IS_X86_64}, 1) | ||
649 | NO_PERF_READ_VDSOX32 := 1 | ||
650 | endif | ||
651 | ifndef NO_PERF_READ_VDSOX32 | ||
652 | $(call feature_check,compile-x32) | ||
653 | ifeq ($(feature-compile-x32), 1) | ||
654 | CFLAGS += -DHAVE_PERF_READ_VDSOX32 | ||
655 | else | ||
656 | NO_PERF_READ_VDSOX32 := 1 | ||
657 | endif | ||
658 | endif | ||
659 | else | ||
660 | NO_PERF_READ_VDSO32 := 1 | ||
661 | NO_PERF_READ_VDSOX32 := 1 | ||
662 | endif | ||
663 | |||
625 | # Among the variables below, these: | 664 | # Among the variables below, these: |
626 | # perfexecdir | 665 | # perfexecdir |
627 | # template_dir | 666 | # template_dir |
diff --git a/tools/perf/config/Makefile.arch b/tools/perf/config/Makefile.arch index 4b06719ee984..ff95a68741d1 100644 --- a/tools/perf/config/Makefile.arch +++ b/tools/perf/config/Makefile.arch | |||
@@ -1,7 +1,7 @@ | |||
1 | 1 | ||
2 | uname_M := $(shell uname -m 2>/dev/null || echo not) | 2 | uname_M := $(shell uname -m 2>/dev/null || echo not) |
3 | 3 | ||
4 | ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ | 4 | RAW_ARCH := $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ |
5 | -e s/arm.*/arm/ -e s/sa110/arm/ \ | 5 | -e s/arm.*/arm/ -e s/sa110/arm/ \ |
6 | -e s/s390x/s390/ -e s/parisc64/parisc/ \ | 6 | -e s/s390x/s390/ -e s/parisc64/parisc/ \ |
7 | -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ | 7 | -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ |
@@ -9,15 +9,23 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ | |||
9 | -e s/tile.*/tile/ ) | 9 | -e s/tile.*/tile/ ) |
10 | 10 | ||
11 | # Additional ARCH settings for x86 | 11 | # Additional ARCH settings for x86 |
12 | ifeq ($(ARCH),i386) | 12 | ifeq ($(RAW_ARCH),i386) |
13 | override ARCH := x86 | 13 | ARCH ?= x86 |
14 | endif | 14 | endif |
15 | 15 | ||
16 | ifeq ($(ARCH),x86_64) | 16 | ifeq ($(RAW_ARCH),x86_64) |
17 | override ARCH := x86 | 17 | ARCH ?= x86 |
18 | IS_X86_64 := 0 | 18 | |
19 | ifeq (, $(findstring m32,$(CFLAGS))) | 19 | ifneq (, $(findstring m32,$(CFLAGS))) |
20 | IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1) | 20 | RAW_ARCH := x86_32 |
21 | RAW_ARCH := x86_64 | ||
22 | endif | 21 | endif |
23 | endif | 22 | endif |
23 | |||
24 | ARCH ?= $(RAW_ARCH) | ||
25 | |||
26 | LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) | ||
27 | ifeq ($(LP64), 1) | ||
28 | IS_64_BIT := 1 | ||
29 | else | ||
30 | IS_64_BIT := 0 | ||
31 | endif | ||
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile index 72ab2984718e..53f19b5dbc37 100644 --- a/tools/perf/config/feature-checks/Makefile +++ b/tools/perf/config/feature-checks/Makefile | |||
@@ -27,7 +27,10 @@ FILES= \ | |||
27 | test-libunwind-debug-frame.bin \ | 27 | test-libunwind-debug-frame.bin \ |
28 | test-stackprotector-all.bin \ | 28 | test-stackprotector-all.bin \ |
29 | test-timerfd.bin \ | 29 | test-timerfd.bin \ |
30 | test-libdw-dwarf-unwind.bin | 30 | test-libdw-dwarf-unwind.bin \ |
31 | test-compile-32.bin \ | ||
32 | test-compile-x32.bin \ | ||
33 | test-zlib.bin | ||
31 | 34 | ||
32 | CC := $(CROSS_COMPILE)gcc -MD | 35 | CC := $(CROSS_COMPILE)gcc -MD |
33 | PKG_CONFIG := $(CROSS_COMPILE)pkg-config | 36 | PKG_CONFIG := $(CROSS_COMPILE)pkg-config |
@@ -39,7 +42,7 @@ BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS) | |||
39 | ############################### | 42 | ############################### |
40 | 43 | ||
41 | test-all.bin: | 44 | test-all.bin: |
42 | $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl | 45 | $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz |
43 | 46 | ||
44 | test-hello.bin: | 47 | test-hello.bin: |
45 | $(BUILD) | 48 | $(BUILD) |
@@ -131,6 +134,15 @@ test-libdw-dwarf-unwind.bin: | |||
131 | test-sync-compare-and-swap.bin: | 134 | test-sync-compare-and-swap.bin: |
132 | $(BUILD) -Werror | 135 | $(BUILD) -Werror |
133 | 136 | ||
137 | test-compile-32.bin: | ||
138 | $(CC) -m32 -o $(OUTPUT)$@ test-compile.c | ||
139 | |||
140 | test-compile-x32.bin: | ||
141 | $(CC) -mx32 -o $(OUTPUT)$@ test-compile.c | ||
142 | |||
143 | test-zlib.bin: | ||
144 | $(BUILD) -lz | ||
145 | |||
134 | -include *.d | 146 | -include *.d |
135 | 147 | ||
136 | ############################### | 148 | ############################### |
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c index a7d022e161c0..652e0098eba6 100644 --- a/tools/perf/config/feature-checks/test-all.c +++ b/tools/perf/config/feature-checks/test-all.c | |||
@@ -93,6 +93,10 @@ | |||
93 | # include "test-sync-compare-and-swap.c" | 93 | # include "test-sync-compare-and-swap.c" |
94 | #undef main | 94 | #undef main |
95 | 95 | ||
96 | #define main main_test_zlib | ||
97 | # include "test-zlib.c" | ||
98 | #undef main | ||
99 | |||
96 | int main(int argc, char *argv[]) | 100 | int main(int argc, char *argv[]) |
97 | { | 101 | { |
98 | main_test_libpython(); | 102 | main_test_libpython(); |
@@ -116,6 +120,7 @@ int main(int argc, char *argv[]) | |||
116 | main_test_stackprotector_all(); | 120 | main_test_stackprotector_all(); |
117 | main_test_libdw_dwarf_unwind(); | 121 | main_test_libdw_dwarf_unwind(); |
118 | main_test_sync_compare_and_swap(argc, argv); | 122 | main_test_sync_compare_and_swap(argc, argv); |
123 | main_test_zlib(); | ||
119 | 124 | ||
120 | return 0; | 125 | return 0; |
121 | } | 126 | } |
diff --git a/tools/perf/config/feature-checks/test-compile.c b/tools/perf/config/feature-checks/test-compile.c new file mode 100644 index 000000000000..31dbf45bf99c --- /dev/null +++ b/tools/perf/config/feature-checks/test-compile.c | |||
@@ -0,0 +1,4 @@ | |||
1 | int main(void) | ||
2 | { | ||
3 | return 0; | ||
4 | } | ||
diff --git a/tools/perf/config/feature-checks/test-zlib.c b/tools/perf/config/feature-checks/test-zlib.c new file mode 100644 index 000000000000..e111fff6240e --- /dev/null +++ b/tools/perf/config/feature-checks/test-zlib.c | |||
@@ -0,0 +1,9 @@ | |||
1 | #include <zlib.h> | ||
2 | |||
3 | int main(void) | ||
4 | { | ||
5 | z_stream zs; | ||
6 | |||
7 | inflateInit(&zs); | ||
8 | return 0; | ||
9 | } | ||
diff --git a/tools/perf/perf-read-vdso.c b/tools/perf/perf-read-vdso.c new file mode 100644 index 000000000000..764e2547c25a --- /dev/null +++ b/tools/perf/perf-read-vdso.c | |||
@@ -0,0 +1,34 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <string.h> | ||
3 | |||
4 | #define VDSO__MAP_NAME "[vdso]" | ||
5 | |||
6 | /* | ||
7 | * Include definition of find_vdso_map() also used in util/vdso.c for | ||
8 | * building perf. | ||
9 | */ | ||
10 | #include "util/find-vdso-map.c" | ||
11 | |||
12 | int main(void) | ||
13 | { | ||
14 | void *start, *end; | ||
15 | size_t size, written; | ||
16 | |||
17 | if (find_vdso_map(&start, &end)) | ||
18 | return 1; | ||
19 | |||
20 | size = end - start; | ||
21 | |||
22 | while (size) { | ||
23 | written = fwrite(start, 1, size, stdout); | ||
24 | if (!written) | ||
25 | return 1; | ||
26 | start += written; | ||
27 | size -= written; | ||
28 | } | ||
29 | |||
30 | if (fflush(stdout)) | ||
31 | return 1; | ||
32 | |||
33 | return 0; | ||
34 | } | ||
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h index a3b13d7dc1d4..6ef68165c9db 100644 --- a/tools/perf/perf-sys.h +++ b/tools/perf/perf-sys.h | |||
@@ -6,7 +6,6 @@ | |||
6 | #include <sys/syscall.h> | 6 | #include <sys/syscall.h> |
7 | #include <linux/types.h> | 7 | #include <linux/types.h> |
8 | #include <linux/perf_event.h> | 8 | #include <linux/perf_event.h> |
9 | #include <asm/unistd.h> | ||
10 | 9 | ||
11 | #if defined(__i386__) | 10 | #if defined(__i386__) |
12 | #define mb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") | 11 | #define mb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") |
diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 452a8474d29d..3700a7faca6c 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c | |||
@@ -200,6 +200,16 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) | |||
200 | *envchanged = 1; | 200 | *envchanged = 1; |
201 | (*argv)++; | 201 | (*argv)++; |
202 | (*argc)--; | 202 | (*argc)--; |
203 | } else if (!strcmp(cmd, "--buildid-dir")) { | ||
204 | if (*argc < 2) { | ||
205 | fprintf(stderr, "No directory given for --buildid-dir.\n"); | ||
206 | usage(perf_usage_string); | ||
207 | } | ||
208 | set_buildid_dir((*argv)[1]); | ||
209 | if (envchanged) | ||
210 | *envchanged = 1; | ||
211 | (*argv)++; | ||
212 | (*argc)--; | ||
203 | } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { | 213 | } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { |
204 | perf_debugfs_set_path(cmd + strlen(CMD_DEBUGFS_DIR)); | 214 | perf_debugfs_set_path(cmd + strlen(CMD_DEBUGFS_DIR)); |
205 | fprintf(stderr, "dir: %s\n", debugfs_mountpoint); | 215 | fprintf(stderr, "dir: %s\n", debugfs_mountpoint); |
@@ -499,7 +509,7 @@ int main(int argc, const char **argv) | |||
499 | } | 509 | } |
500 | if (!prefixcmp(cmd, "trace")) { | 510 | if (!prefixcmp(cmd, "trace")) { |
501 | #ifdef HAVE_LIBAUDIT_SUPPORT | 511 | #ifdef HAVE_LIBAUDIT_SUPPORT |
502 | set_buildid_dir(); | 512 | set_buildid_dir(NULL); |
503 | setup_path(); | 513 | setup_path(); |
504 | argv[0] = "trace"; | 514 | argv[0] = "trace"; |
505 | return cmd_trace(argc, argv, NULL); | 515 | return cmd_trace(argc, argv, NULL); |
@@ -514,7 +524,7 @@ int main(int argc, const char **argv) | |||
514 | argc--; | 524 | argc--; |
515 | handle_options(&argv, &argc, NULL); | 525 | handle_options(&argv, &argc, NULL); |
516 | commit_pager_choice(); | 526 | commit_pager_choice(); |
517 | set_buildid_dir(); | 527 | set_buildid_dir(NULL); |
518 | 528 | ||
519 | if (argc > 0) { | 529 | if (argc > 0) { |
520 | if (!prefixcmp(argv[0], "--")) | 530 | if (!prefixcmp(argv[0], "--")) |
diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 220d44e44c1b..1dabb8553499 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h | |||
@@ -52,6 +52,7 @@ struct record_opts { | |||
52 | bool sample_weight; | 52 | bool sample_weight; |
53 | bool sample_time; | 53 | bool sample_time; |
54 | bool period; | 54 | bool period; |
55 | bool sample_intr_regs; | ||
55 | unsigned int freq; | 56 | unsigned int freq; |
56 | unsigned int mmap_pages; | 57 | unsigned int mmap_pages; |
57 | unsigned int user_freq; | 58 | unsigned int user_freq; |
@@ -62,4 +63,7 @@ struct record_opts { | |||
62 | unsigned initial_delay; | 63 | unsigned initial_delay; |
63 | }; | 64 | }; |
64 | 65 | ||
66 | struct option; | ||
67 | extern const char * const *record_usage; | ||
68 | extern struct option *record_options; | ||
65 | #endif | 69 | #endif |
diff --git a/tools/perf/scripts/python/bin/export-to-postgresql-record b/tools/perf/scripts/python/bin/export-to-postgresql-record new file mode 100644 index 000000000000..221d66e05713 --- /dev/null +++ b/tools/perf/scripts/python/bin/export-to-postgresql-record | |||
@@ -0,0 +1,8 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | # | ||
4 | # export perf data to a postgresql database. Can cover | ||
5 | # perf ip samples (excluding the tracepoints). No special | ||
6 | # record requirements, just record what you want to export. | ||
7 | # | ||
8 | perf record $@ | ||
diff --git a/tools/perf/scripts/python/bin/export-to-postgresql-report b/tools/perf/scripts/python/bin/export-to-postgresql-report new file mode 100644 index 000000000000..cd335b6e2a01 --- /dev/null +++ b/tools/perf/scripts/python/bin/export-to-postgresql-report | |||
@@ -0,0 +1,29 @@ | |||
1 | #!/bin/bash | ||
2 | # description: export perf data to a postgresql database | ||
3 | # args: [database name] [columns] [calls] | ||
4 | n_args=0 | ||
5 | for i in "$@" | ||
6 | do | ||
7 | if expr match "$i" "-" > /dev/null ; then | ||
8 | break | ||
9 | fi | ||
10 | n_args=$(( $n_args + 1 )) | ||
11 | done | ||
12 | if [ "$n_args" -gt 3 ] ; then | ||
13 | echo "usage: export-to-postgresql-report [database name] [columns] [calls]" | ||
14 | exit | ||
15 | fi | ||
16 | if [ "$n_args" -gt 2 ] ; then | ||
17 | dbname=$1 | ||
18 | columns=$2 | ||
19 | calls=$3 | ||
20 | shift 3 | ||
21 | elif [ "$n_args" -gt 1 ] ; then | ||
22 | dbname=$1 | ||
23 | columns=$2 | ||
24 | shift 2 | ||
25 | elif [ "$n_args" -gt 0 ] ; then | ||
26 | dbname=$1 | ||
27 | shift | ||
28 | fi | ||
29 | perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/export-to-postgresql.py $dbname $columns $calls | ||
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py new file mode 100644 index 000000000000..4cdafd880074 --- /dev/null +++ b/tools/perf/scripts/python/export-to-postgresql.py | |||
@@ -0,0 +1,444 @@ | |||
1 | # export-to-postgresql.py: export perf data to a postgresql database | ||
2 | # Copyright (c) 2014, Intel Corporation. | ||
3 | # | ||
4 | # This program is free software; you can redistribute it and/or modify it | ||
5 | # under the terms and conditions of the GNU General Public License, | ||
6 | # version 2, as published by the Free Software Foundation. | ||
7 | # | ||
8 | # This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | # more details. | ||
12 | |||
13 | import os | ||
14 | import sys | ||
15 | import struct | ||
16 | import datetime | ||
17 | |||
18 | from PySide.QtSql import * | ||
19 | |||
20 | # Need to access PostgreSQL C library directly to use COPY FROM STDIN | ||
21 | from ctypes import * | ||
22 | libpq = CDLL("libpq.so.5") | ||
23 | PQconnectdb = libpq.PQconnectdb | ||
24 | PQconnectdb.restype = c_void_p | ||
25 | PQfinish = libpq.PQfinish | ||
26 | PQstatus = libpq.PQstatus | ||
27 | PQexec = libpq.PQexec | ||
28 | PQexec.restype = c_void_p | ||
29 | PQresultStatus = libpq.PQresultStatus | ||
30 | PQputCopyData = libpq.PQputCopyData | ||
31 | PQputCopyData.argtypes = [ c_void_p, c_void_p, c_int ] | ||
32 | PQputCopyEnd = libpq.PQputCopyEnd | ||
33 | PQputCopyEnd.argtypes = [ c_void_p, c_void_p ] | ||
34 | |||
35 | sys.path.append(os.environ['PERF_EXEC_PATH'] + \ | ||
36 | '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') | ||
37 | |||
38 | # These perf imports are not used at present | ||
39 | #from perf_trace_context import * | ||
40 | #from Core import * | ||
41 | |||
42 | perf_db_export_mode = True | ||
43 | perf_db_export_calls = False | ||
44 | |||
45 | def usage(): | ||
46 | print >> sys.stderr, "Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>]" | ||
47 | print >> sys.stderr, "where: columns 'all' or 'branches'" | ||
48 | print >> sys.stderr, " calls 'calls' => create calls table" | ||
49 | raise Exception("Too few arguments") | ||
50 | |||
51 | if (len(sys.argv) < 2): | ||
52 | usage() | ||
53 | |||
54 | dbname = sys.argv[1] | ||
55 | |||
56 | if (len(sys.argv) >= 3): | ||
57 | columns = sys.argv[2] | ||
58 | else: | ||
59 | columns = "all" | ||
60 | |||
61 | if columns not in ("all", "branches"): | ||
62 | usage() | ||
63 | |||
64 | branches = (columns == "branches") | ||
65 | |||
66 | if (len(sys.argv) >= 4): | ||
67 | if (sys.argv[3] == "calls"): | ||
68 | perf_db_export_calls = True | ||
69 | else: | ||
70 | usage() | ||
71 | |||
72 | output_dir_name = os.getcwd() + "/" + dbname + "-perf-data" | ||
73 | os.mkdir(output_dir_name) | ||
74 | |||
75 | def do_query(q, s): | ||
76 | if (q.exec_(s)): | ||
77 | return | ||
78 | raise Exception("Query failed: " + q.lastError().text()) | ||
79 | |||
80 | print datetime.datetime.today(), "Creating database..." | ||
81 | |||
82 | db = QSqlDatabase.addDatabase('QPSQL') | ||
83 | query = QSqlQuery(db) | ||
84 | db.setDatabaseName('postgres') | ||
85 | db.open() | ||
86 | try: | ||
87 | do_query(query, 'CREATE DATABASE ' + dbname) | ||
88 | except: | ||
89 | os.rmdir(output_dir_name) | ||
90 | raise | ||
91 | query.finish() | ||
92 | query.clear() | ||
93 | db.close() | ||
94 | |||
95 | db.setDatabaseName(dbname) | ||
96 | db.open() | ||
97 | |||
98 | query = QSqlQuery(db) | ||
99 | do_query(query, 'SET client_min_messages TO WARNING') | ||
100 | |||
101 | do_query(query, 'CREATE TABLE selected_events (' | ||
102 | 'id bigint NOT NULL,' | ||
103 | 'name varchar(80))') | ||
104 | do_query(query, 'CREATE TABLE machines (' | ||
105 | 'id bigint NOT NULL,' | ||
106 | 'pid integer,' | ||
107 | 'root_dir varchar(4096))') | ||
108 | do_query(query, 'CREATE TABLE threads (' | ||
109 | 'id bigint NOT NULL,' | ||
110 | 'machine_id bigint,' | ||
111 | 'process_id bigint,' | ||
112 | 'pid integer,' | ||
113 | 'tid integer)') | ||
114 | do_query(query, 'CREATE TABLE comms (' | ||
115 | 'id bigint NOT NULL,' | ||
116 | 'comm varchar(16))') | ||
117 | do_query(query, 'CREATE TABLE comm_threads (' | ||
118 | 'id bigint NOT NULL,' | ||
119 | 'comm_id bigint,' | ||
120 | 'thread_id bigint)') | ||
121 | do_query(query, 'CREATE TABLE dsos (' | ||
122 | 'id bigint NOT NULL,' | ||
123 | 'machine_id bigint,' | ||
124 | 'short_name varchar(256),' | ||
125 | 'long_name varchar(4096),' | ||
126 | 'build_id varchar(64))') | ||
127 | do_query(query, 'CREATE TABLE symbols (' | ||
128 | 'id bigint NOT NULL,' | ||
129 | 'dso_id bigint,' | ||
130 | 'sym_start bigint,' | ||
131 | 'sym_end bigint,' | ||
132 | 'binding integer,' | ||
133 | 'name varchar(2048))') | ||
134 | do_query(query, 'CREATE TABLE branch_types (' | ||
135 | 'id integer NOT NULL,' | ||
136 | 'name varchar(80))') | ||
137 | |||
138 | if branches: | ||
139 | do_query(query, 'CREATE TABLE samples (' | ||
140 | 'id bigint NOT NULL,' | ||
141 | 'evsel_id bigint,' | ||
142 | 'machine_id bigint,' | ||
143 | 'thread_id bigint,' | ||
144 | 'comm_id bigint,' | ||
145 | 'dso_id bigint,' | ||
146 | 'symbol_id bigint,' | ||
147 | 'sym_offset bigint,' | ||
148 | 'ip bigint,' | ||
149 | 'time bigint,' | ||
150 | 'cpu integer,' | ||
151 | 'to_dso_id bigint,' | ||
152 | 'to_symbol_id bigint,' | ||
153 | 'to_sym_offset bigint,' | ||
154 | 'to_ip bigint,' | ||
155 | 'branch_type integer,' | ||
156 | 'in_tx boolean)') | ||
157 | else: | ||
158 | do_query(query, 'CREATE TABLE samples (' | ||
159 | 'id bigint NOT NULL,' | ||
160 | 'evsel_id bigint,' | ||
161 | 'machine_id bigint,' | ||
162 | 'thread_id bigint,' | ||
163 | 'comm_id bigint,' | ||
164 | 'dso_id bigint,' | ||
165 | 'symbol_id bigint,' | ||
166 | 'sym_offset bigint,' | ||
167 | 'ip bigint,' | ||
168 | 'time bigint,' | ||
169 | 'cpu integer,' | ||
170 | 'to_dso_id bigint,' | ||
171 | 'to_symbol_id bigint,' | ||
172 | 'to_sym_offset bigint,' | ||
173 | 'to_ip bigint,' | ||
174 | 'period bigint,' | ||
175 | 'weight bigint,' | ||
176 | 'transaction bigint,' | ||
177 | 'data_src bigint,' | ||
178 | 'branch_type integer,' | ||
179 | 'in_tx boolean)') | ||
180 | |||
181 | if perf_db_export_calls: | ||
182 | do_query(query, 'CREATE TABLE call_paths (' | ||
183 | 'id bigint NOT NULL,' | ||
184 | 'parent_id bigint,' | ||
185 | 'symbol_id bigint,' | ||
186 | 'ip bigint)') | ||
187 | do_query(query, 'CREATE TABLE calls (' | ||
188 | 'id bigint NOT NULL,' | ||
189 | 'thread_id bigint,' | ||
190 | 'comm_id bigint,' | ||
191 | 'call_path_id bigint,' | ||
192 | 'call_time bigint,' | ||
193 | 'return_time bigint,' | ||
194 | 'branch_count bigint,' | ||
195 | 'call_id bigint,' | ||
196 | 'return_id bigint,' | ||
197 | 'parent_call_path_id bigint,' | ||
198 | 'flags integer)') | ||
199 | |||
200 | do_query(query, 'CREATE VIEW samples_view AS ' | ||
201 | 'SELECT ' | ||
202 | 'id,' | ||
203 | 'time,' | ||
204 | 'cpu,' | ||
205 | '(SELECT pid FROM threads WHERE id = thread_id) AS pid,' | ||
206 | '(SELECT tid FROM threads WHERE id = thread_id) AS tid,' | ||
207 | '(SELECT comm FROM comms WHERE id = comm_id) AS command,' | ||
208 | '(SELECT name FROM selected_events WHERE id = evsel_id) AS event,' | ||
209 | 'to_hex(ip) AS ip_hex,' | ||
210 | '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,' | ||
211 | 'sym_offset,' | ||
212 | '(SELECT short_name FROM dsos WHERE id = dso_id) AS dso_short_name,' | ||
213 | 'to_hex(to_ip) AS to_ip_hex,' | ||
214 | '(SELECT name FROM symbols WHERE id = to_symbol_id) AS to_symbol,' | ||
215 | 'to_sym_offset,' | ||
216 | '(SELECT short_name FROM dsos WHERE id = to_dso_id) AS to_dso_short_name,' | ||
217 | '(SELECT name FROM branch_types WHERE id = branch_type) AS branch_type_name,' | ||
218 | 'in_tx' | ||
219 | ' FROM samples') | ||
220 | |||
221 | |||
222 | file_header = struct.pack("!11sii", "PGCOPY\n\377\r\n\0", 0, 0) | ||
223 | file_trailer = "\377\377" | ||
224 | |||
225 | def open_output_file(file_name): | ||
226 | path_name = output_dir_name + "/" + file_name | ||
227 | file = open(path_name, "w+") | ||
228 | file.write(file_header) | ||
229 | return file | ||
230 | |||
231 | def close_output_file(file): | ||
232 | file.write(file_trailer) | ||
233 | file.close() | ||
234 | |||
235 | def copy_output_file_direct(file, table_name): | ||
236 | close_output_file(file) | ||
237 | sql = "COPY " + table_name + " FROM '" + file.name + "' (FORMAT 'binary')" | ||
238 | do_query(query, sql) | ||
239 | |||
240 | # Use COPY FROM STDIN because security may prevent postgres from accessing the files directly | ||
241 | def copy_output_file(file, table_name): | ||
242 | conn = PQconnectdb("dbname = " + dbname) | ||
243 | if (PQstatus(conn)): | ||
244 | raise Exception("COPY FROM STDIN PQconnectdb failed") | ||
245 | file.write(file_trailer) | ||
246 | file.seek(0) | ||
247 | sql = "COPY " + table_name + " FROM STDIN (FORMAT 'binary')" | ||
248 | res = PQexec(conn, sql) | ||
249 | if (PQresultStatus(res) != 4): | ||
250 | raise Exception("COPY FROM STDIN PQexec failed") | ||
251 | data = file.read(65536) | ||
252 | while (len(data)): | ||
253 | ret = PQputCopyData(conn, data, len(data)) | ||
254 | if (ret != 1): | ||
255 | raise Exception("COPY FROM STDIN PQputCopyData failed, error " + str(ret)) | ||
256 | data = file.read(65536) | ||
257 | ret = PQputCopyEnd(conn, None) | ||
258 | if (ret != 1): | ||
259 | raise Exception("COPY FROM STDIN PQputCopyEnd failed, error " + str(ret)) | ||
260 | PQfinish(conn) | ||
261 | |||
262 | def remove_output_file(file): | ||
263 | name = file.name | ||
264 | file.close() | ||
265 | os.unlink(name) | ||
266 | |||
267 | evsel_file = open_output_file("evsel_table.bin") | ||
268 | machine_file = open_output_file("machine_table.bin") | ||
269 | thread_file = open_output_file("thread_table.bin") | ||
270 | comm_file = open_output_file("comm_table.bin") | ||
271 | comm_thread_file = open_output_file("comm_thread_table.bin") | ||
272 | dso_file = open_output_file("dso_table.bin") | ||
273 | symbol_file = open_output_file("symbol_table.bin") | ||
274 | branch_type_file = open_output_file("branch_type_table.bin") | ||
275 | sample_file = open_output_file("sample_table.bin") | ||
276 | if perf_db_export_calls: | ||
277 | call_path_file = open_output_file("call_path_table.bin") | ||
278 | call_file = open_output_file("call_table.bin") | ||
279 | |||
280 | def trace_begin(): | ||
281 | print datetime.datetime.today(), "Writing to intermediate files..." | ||
282 | # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs | ||
283 | evsel_table(0, "unknown") | ||
284 | machine_table(0, 0, "unknown") | ||
285 | thread_table(0, 0, 0, -1, -1) | ||
286 | comm_table(0, "unknown") | ||
287 | dso_table(0, 0, "unknown", "unknown", "") | ||
288 | symbol_table(0, 0, 0, 0, 0, "unknown") | ||
289 | sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | ||
290 | if perf_db_export_calls: | ||
291 | call_path_table(0, 0, 0, 0) | ||
292 | |||
293 | unhandled_count = 0 | ||
294 | |||
295 | def trace_end(): | ||
296 | print datetime.datetime.today(), "Copying to database..." | ||
297 | copy_output_file(evsel_file, "selected_events") | ||
298 | copy_output_file(machine_file, "machines") | ||
299 | copy_output_file(thread_file, "threads") | ||
300 | copy_output_file(comm_file, "comms") | ||
301 | copy_output_file(comm_thread_file, "comm_threads") | ||
302 | copy_output_file(dso_file, "dsos") | ||
303 | copy_output_file(symbol_file, "symbols") | ||
304 | copy_output_file(branch_type_file, "branch_types") | ||
305 | copy_output_file(sample_file, "samples") | ||
306 | if perf_db_export_calls: | ||
307 | copy_output_file(call_path_file, "call_paths") | ||
308 | copy_output_file(call_file, "calls") | ||
309 | |||
310 | print datetime.datetime.today(), "Removing intermediate files..." | ||
311 | remove_output_file(evsel_file) | ||
312 | remove_output_file(machine_file) | ||
313 | remove_output_file(thread_file) | ||
314 | remove_output_file(comm_file) | ||
315 | remove_output_file(comm_thread_file) | ||
316 | remove_output_file(dso_file) | ||
317 | remove_output_file(symbol_file) | ||
318 | remove_output_file(branch_type_file) | ||
319 | remove_output_file(sample_file) | ||
320 | if perf_db_export_calls: | ||
321 | remove_output_file(call_path_file) | ||
322 | remove_output_file(call_file) | ||
323 | os.rmdir(output_dir_name) | ||
324 | print datetime.datetime.today(), "Adding primary keys" | ||
325 | do_query(query, 'ALTER TABLE selected_events ADD PRIMARY KEY (id)') | ||
326 | do_query(query, 'ALTER TABLE machines ADD PRIMARY KEY (id)') | ||
327 | do_query(query, 'ALTER TABLE threads ADD PRIMARY KEY (id)') | ||
328 | do_query(query, 'ALTER TABLE comms ADD PRIMARY KEY (id)') | ||
329 | do_query(query, 'ALTER TABLE comm_threads ADD PRIMARY KEY (id)') | ||
330 | do_query(query, 'ALTER TABLE dsos ADD PRIMARY KEY (id)') | ||
331 | do_query(query, 'ALTER TABLE symbols ADD PRIMARY KEY (id)') | ||
332 | do_query(query, 'ALTER TABLE branch_types ADD PRIMARY KEY (id)') | ||
333 | do_query(query, 'ALTER TABLE samples ADD PRIMARY KEY (id)') | ||
334 | if perf_db_export_calls: | ||
335 | do_query(query, 'ALTER TABLE call_paths ADD PRIMARY KEY (id)') | ||
336 | do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)') | ||
337 | |||
338 | print datetime.datetime.today(), "Adding foreign keys" | ||
339 | do_query(query, 'ALTER TABLE threads ' | ||
340 | 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),' | ||
341 | 'ADD CONSTRAINT processfk FOREIGN KEY (process_id) REFERENCES threads (id)') | ||
342 | do_query(query, 'ALTER TABLE comm_threads ' | ||
343 | 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),' | ||
344 | 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id)') | ||
345 | do_query(query, 'ALTER TABLE dsos ' | ||
346 | 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id)') | ||
347 | do_query(query, 'ALTER TABLE symbols ' | ||
348 | 'ADD CONSTRAINT dsofk FOREIGN KEY (dso_id) REFERENCES dsos (id)') | ||
349 | do_query(query, 'ALTER TABLE samples ' | ||
350 | 'ADD CONSTRAINT evselfk FOREIGN KEY (evsel_id) REFERENCES selected_events (id),' | ||
351 | 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),' | ||
352 | 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id),' | ||
353 | 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),' | ||
354 | 'ADD CONSTRAINT dsofk FOREIGN KEY (dso_id) REFERENCES dsos (id),' | ||
355 | 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id),' | ||
356 | 'ADD CONSTRAINT todsofk FOREIGN KEY (to_dso_id) REFERENCES dsos (id),' | ||
357 | 'ADD CONSTRAINT tosymbolfk FOREIGN KEY (to_symbol_id) REFERENCES symbols (id)') | ||
358 | if perf_db_export_calls: | ||
359 | do_query(query, 'ALTER TABLE call_paths ' | ||
360 | 'ADD CONSTRAINT parentfk FOREIGN KEY (parent_id) REFERENCES call_paths (id),' | ||
361 | 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id)') | ||
362 | do_query(query, 'ALTER TABLE calls ' | ||
363 | 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id),' | ||
364 | 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),' | ||
365 | 'ADD CONSTRAINT call_pathfk FOREIGN KEY (call_path_id) REFERENCES call_paths (id),' | ||
366 | 'ADD CONSTRAINT callfk FOREIGN KEY (call_id) REFERENCES samples (id),' | ||
367 | 'ADD CONSTRAINT returnfk FOREIGN KEY (return_id) REFERENCES samples (id),' | ||
368 | 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)') | ||
369 | do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') | ||
370 | |||
371 | if (unhandled_count): | ||
372 | print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" | ||
373 | print datetime.datetime.today(), "Done" | ||
374 | |||
375 | def trace_unhandled(event_name, context, event_fields_dict): | ||
376 | global unhandled_count | ||
377 | unhandled_count += 1 | ||
378 | |||
379 | def sched__sched_switch(*x): | ||
380 | pass | ||
381 | |||
382 | def evsel_table(evsel_id, evsel_name, *x): | ||
383 | n = len(evsel_name) | ||
384 | fmt = "!hiqi" + str(n) + "s" | ||
385 | value = struct.pack(fmt, 2, 8, evsel_id, n, evsel_name) | ||
386 | evsel_file.write(value) | ||
387 | |||
388 | def machine_table(machine_id, pid, root_dir, *x): | ||
389 | n = len(root_dir) | ||
390 | fmt = "!hiqiii" + str(n) + "s" | ||
391 | value = struct.pack(fmt, 3, 8, machine_id, 4, pid, n, root_dir) | ||
392 | machine_file.write(value) | ||
393 | |||
394 | def thread_table(thread_id, machine_id, process_id, pid, tid, *x): | ||
395 | value = struct.pack("!hiqiqiqiiii", 5, 8, thread_id, 8, machine_id, 8, process_id, 4, pid, 4, tid) | ||
396 | thread_file.write(value) | ||
397 | |||
398 | def comm_table(comm_id, comm_str, *x): | ||
399 | n = len(comm_str) | ||
400 | fmt = "!hiqi" + str(n) + "s" | ||
401 | value = struct.pack(fmt, 2, 8, comm_id, n, comm_str) | ||
402 | comm_file.write(value) | ||
403 | |||
404 | def comm_thread_table(comm_thread_id, comm_id, thread_id, *x): | ||
405 | fmt = "!hiqiqiq" | ||
406 | value = struct.pack(fmt, 3, 8, comm_thread_id, 8, comm_id, 8, thread_id) | ||
407 | comm_thread_file.write(value) | ||
408 | |||
409 | def dso_table(dso_id, machine_id, short_name, long_name, build_id, *x): | ||
410 | n1 = len(short_name) | ||
411 | n2 = len(long_name) | ||
412 | n3 = len(build_id) | ||
413 | fmt = "!hiqiqi" + str(n1) + "si" + str(n2) + "si" + str(n3) + "s" | ||
414 | value = struct.pack(fmt, 5, 8, dso_id, 8, machine_id, n1, short_name, n2, long_name, n3, build_id) | ||
415 | dso_file.write(value) | ||
416 | |||
417 | def symbol_table(symbol_id, dso_id, sym_start, sym_end, binding, symbol_name, *x): | ||
418 | n = len(symbol_name) | ||
419 | fmt = "!hiqiqiqiqiii" + str(n) + "s" | ||
420 | value = struct.pack(fmt, 6, 8, symbol_id, 8, dso_id, 8, sym_start, 8, sym_end, 4, binding, n, symbol_name) | ||
421 | symbol_file.write(value) | ||
422 | |||
423 | def branch_type_table(branch_type, name, *x): | ||
424 | n = len(name) | ||
425 | fmt = "!hiii" + str(n) + "s" | ||
426 | value = struct.pack(fmt, 2, 4, branch_type, n, name) | ||
427 | branch_type_file.write(value) | ||
428 | |||
429 | def sample_table(sample_id, evsel_id, machine_id, thread_id, comm_id, dso_id, symbol_id, sym_offset, ip, time, cpu, to_dso_id, to_symbol_id, to_sym_offset, to_ip, period, weight, transaction, data_src, branch_type, in_tx, *x): | ||
430 | if branches: | ||
431 | value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiiiB", 17, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 4, branch_type, 1, in_tx) | ||
432 | else: | ||
433 | value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiqiqiqiqiiiB", 21, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 8, period, 8, weight, 8, transaction, 8, data_src, 4, branch_type, 1, in_tx) | ||
434 | sample_file.write(value) | ||
435 | |||
436 | def call_path_table(cp_id, parent_id, symbol_id, ip, *x): | ||
437 | fmt = "!hiqiqiqiq" | ||
438 | value = struct.pack(fmt, 4, 8, cp_id, 8, parent_id, 8, symbol_id, 8, ip) | ||
439 | call_path_file.write(value) | ||
440 | |||
441 | def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, *x): | ||
442 | fmt = "!hiqiqiqiqiqiqiqiqiqiqii" | ||
443 | value = struct.pack(fmt, 11, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags) | ||
444 | call_file.write(value) | ||
diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record index f710b92ccff6..d3095dafed36 100644 --- a/tools/perf/tests/attr/base-record +++ b/tools/perf/tests/attr/base-record | |||
@@ -5,7 +5,7 @@ group_fd=-1 | |||
5 | flags=0|8 | 5 | flags=0|8 |
6 | cpu=* | 6 | cpu=* |
7 | type=0|1 | 7 | type=0|1 |
8 | size=96 | 8 | size=104 |
9 | config=0 | 9 | config=0 |
10 | sample_period=4000 | 10 | sample_period=4000 |
11 | sample_type=263 | 11 | sample_type=263 |
diff --git a/tools/perf/tests/attr/base-stat b/tools/perf/tests/attr/base-stat index dc3ada2470c0..872ed7e24c7c 100644 --- a/tools/perf/tests/attr/base-stat +++ b/tools/perf/tests/attr/base-stat | |||
@@ -5,7 +5,7 @@ group_fd=-1 | |||
5 | flags=0|8 | 5 | flags=0|8 |
6 | cpu=* | 6 | cpu=* |
7 | type=0 | 7 | type=0 |
8 | size=96 | 8 | size=104 |
9 | config=0 | 9 | config=0 |
10 | sample_period=0 | 10 | sample_period=0 |
11 | sample_type=0 | 11 | sample_type=0 |
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 162c978f1491..4b7d9ab0f049 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c | |||
@@ -85,7 +85,7 @@ static struct test { | |||
85 | .func = test__hists_link, | 85 | .func = test__hists_link, |
86 | }, | 86 | }, |
87 | { | 87 | { |
88 | .desc = "Try 'use perf' in python, checking link problems", | 88 | .desc = "Try 'import perf' in python, checking link problems", |
89 | .func = test__python_use, | 89 | .func = test__python_use, |
90 | }, | 90 | }, |
91 | { | 91 | { |
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 67f2d6323558..f671ec37a7c4 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c | |||
@@ -133,8 +133,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf, | |||
133 | } | 133 | } |
134 | 134 | ||
135 | static int read_object_code(u64 addr, size_t len, u8 cpumode, | 135 | static int read_object_code(u64 addr, size_t len, u8 cpumode, |
136 | struct thread *thread, struct machine *machine, | 136 | struct thread *thread, struct state *state) |
137 | struct state *state) | ||
138 | { | 137 | { |
139 | struct addr_location al; | 138 | struct addr_location al; |
140 | unsigned char buf1[BUFSZ]; | 139 | unsigned char buf1[BUFSZ]; |
@@ -145,8 +144,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, | |||
145 | 144 | ||
146 | pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); | 145 | pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); |
147 | 146 | ||
148 | thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, addr, | 147 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al); |
149 | &al); | ||
150 | if (!al.map || !al.map->dso) { | 148 | if (!al.map || !al.map->dso) { |
151 | pr_debug("thread__find_addr_map failed\n"); | 149 | pr_debug("thread__find_addr_map failed\n"); |
152 | return -1; | 150 | return -1; |
@@ -170,8 +168,8 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, | |||
170 | len = al.map->end - addr; | 168 | len = al.map->end - addr; |
171 | 169 | ||
172 | /* Read the object code using perf */ | 170 | /* Read the object code using perf */ |
173 | ret_len = dso__data_read_offset(al.map->dso, machine, al.addr, buf1, | 171 | ret_len = dso__data_read_offset(al.map->dso, thread->mg->machine, |
174 | len); | 172 | al.addr, buf1, len); |
175 | if (ret_len != len) { | 173 | if (ret_len != len) { |
176 | pr_debug("dso__data_read_offset failed\n"); | 174 | pr_debug("dso__data_read_offset failed\n"); |
177 | return -1; | 175 | return -1; |
@@ -264,8 +262,7 @@ static int process_sample_event(struct machine *machine, | |||
264 | 262 | ||
265 | cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 263 | cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
266 | 264 | ||
267 | return read_object_code(sample.ip, READLEN, cpumode, thread, machine, | 265 | return read_object_code(sample.ip, READLEN, cpumode, thread, state); |
268 | state); | ||
269 | } | 266 | } |
270 | 267 | ||
271 | static int process_event(struct machine *machine, struct perf_evlist *evlist, | 268 | static int process_event(struct machine *machine, struct perf_evlist *evlist, |
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c index fc25e57f4a5d..0bf06bec68c7 100644 --- a/tools/perf/tests/dwarf-unwind.c +++ b/tools/perf/tests/dwarf-unwind.c | |||
@@ -11,6 +11,9 @@ | |||
11 | #include "thread.h" | 11 | #include "thread.h" |
12 | #include "callchain.h" | 12 | #include "callchain.h" |
13 | 13 | ||
14 | /* For bsearch. We try to unwind functions in shared object. */ | ||
15 | #include <stdlib.h> | ||
16 | |||
14 | static int mmap_handler(struct perf_tool *tool __maybe_unused, | 17 | static int mmap_handler(struct perf_tool *tool __maybe_unused, |
15 | union perf_event *event, | 18 | union perf_event *event, |
16 | struct perf_sample *sample __maybe_unused, | 19 | struct perf_sample *sample __maybe_unused, |
@@ -28,7 +31,7 @@ static int init_live_machine(struct machine *machine) | |||
28 | mmap_handler, machine, true); | 31 | mmap_handler, machine, true); |
29 | } | 32 | } |
30 | 33 | ||
31 | #define MAX_STACK 6 | 34 | #define MAX_STACK 8 |
32 | 35 | ||
33 | static int unwind_entry(struct unwind_entry *entry, void *arg) | 36 | static int unwind_entry(struct unwind_entry *entry, void *arg) |
34 | { | 37 | { |
@@ -37,6 +40,8 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) | |||
37 | static const char *funcs[MAX_STACK] = { | 40 | static const char *funcs[MAX_STACK] = { |
38 | "test__arch_unwind_sample", | 41 | "test__arch_unwind_sample", |
39 | "unwind_thread", | 42 | "unwind_thread", |
43 | "compare", | ||
44 | "bsearch", | ||
40 | "krava_3", | 45 | "krava_3", |
41 | "krava_2", | 46 | "krava_2", |
42 | "krava_1", | 47 | "krava_1", |
@@ -59,7 +64,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) | |||
59 | } | 64 | } |
60 | 65 | ||
61 | __attribute__ ((noinline)) | 66 | __attribute__ ((noinline)) |
62 | static int unwind_thread(struct thread *thread, struct machine *machine) | 67 | static int unwind_thread(struct thread *thread) |
63 | { | 68 | { |
64 | struct perf_sample sample; | 69 | struct perf_sample sample; |
65 | unsigned long cnt = 0; | 70 | unsigned long cnt = 0; |
@@ -72,7 +77,7 @@ static int unwind_thread(struct thread *thread, struct machine *machine) | |||
72 | goto out; | 77 | goto out; |
73 | } | 78 | } |
74 | 79 | ||
75 | err = unwind__get_entries(unwind_entry, &cnt, machine, thread, | 80 | err = unwind__get_entries(unwind_entry, &cnt, thread, |
76 | &sample, MAX_STACK); | 81 | &sample, MAX_STACK); |
77 | if (err) | 82 | if (err) |
78 | pr_debug("unwind failed\n"); | 83 | pr_debug("unwind failed\n"); |
@@ -88,22 +93,49 @@ static int unwind_thread(struct thread *thread, struct machine *machine) | |||
88 | return err; | 93 | return err; |
89 | } | 94 | } |
90 | 95 | ||
96 | static int global_unwind_retval = -INT_MAX; | ||
97 | |||
98 | __attribute__ ((noinline)) | ||
99 | static int compare(void *p1, void *p2) | ||
100 | { | ||
101 | /* Any possible value should be 'thread' */ | ||
102 | struct thread *thread = *(struct thread **)p1; | ||
103 | |||
104 | if (global_unwind_retval == -INT_MAX) | ||
105 | global_unwind_retval = unwind_thread(thread); | ||
106 | |||
107 | return p1 - p2; | ||
108 | } | ||
109 | |||
91 | __attribute__ ((noinline)) | 110 | __attribute__ ((noinline)) |
92 | static int krava_3(struct thread *thread, struct machine *machine) | 111 | static int krava_3(struct thread *thread) |
93 | { | 112 | { |
94 | return unwind_thread(thread, machine); | 113 | struct thread *array[2] = {thread, thread}; |
114 | void *fp = &bsearch; | ||
115 | /* | ||
116 | * make _bsearch a volatile function pointer to | ||
117 | * prevent potential optimization, which may expand | ||
118 | * bsearch and call compare directly from this function, | ||
119 | * instead of libc shared object. | ||
120 | */ | ||
121 | void *(*volatile _bsearch)(void *, void *, size_t, | ||
122 | size_t, int (*)(void *, void *)); | ||
123 | |||
124 | _bsearch = fp; | ||
125 | _bsearch(array, &thread, 2, sizeof(struct thread **), compare); | ||
126 | return global_unwind_retval; | ||
95 | } | 127 | } |
96 | 128 | ||
97 | __attribute__ ((noinline)) | 129 | __attribute__ ((noinline)) |
98 | static int krava_2(struct thread *thread, struct machine *machine) | 130 | static int krava_2(struct thread *thread) |
99 | { | 131 | { |
100 | return krava_3(thread, machine); | 132 | return krava_3(thread); |
101 | } | 133 | } |
102 | 134 | ||
103 | __attribute__ ((noinline)) | 135 | __attribute__ ((noinline)) |
104 | static int krava_1(struct thread *thread, struct machine *machine) | 136 | static int krava_1(struct thread *thread) |
105 | { | 137 | { |
106 | return krava_2(thread, machine); | 138 | return krava_2(thread); |
107 | } | 139 | } |
108 | 140 | ||
109 | int test__dwarf_unwind(void) | 141 | int test__dwarf_unwind(void) |
@@ -137,7 +169,7 @@ int test__dwarf_unwind(void) | |||
137 | goto out; | 169 | goto out; |
138 | } | 170 | } |
139 | 171 | ||
140 | err = krava_1(thread, machine); | 172 | err = krava_1(thread); |
141 | 173 | ||
142 | out: | 174 | out: |
143 | machine__delete_threads(machine); | 175 | machine__delete_threads(machine); |
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c index 614d5c4978ab..8d110dec393e 100644 --- a/tools/perf/tests/hists_cumulate.c +++ b/tools/perf/tests/hists_cumulate.c | |||
@@ -187,7 +187,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec | |||
187 | * function since TEST_ASSERT_VAL() returns in case of failure. | 187 | * function since TEST_ASSERT_VAL() returns in case of failure. |
188 | */ | 188 | */ |
189 | hists__collapse_resort(hists, NULL); | 189 | hists__collapse_resort(hists, NULL); |
190 | hists__output_resort(hists); | 190 | hists__output_resort(hists, NULL); |
191 | 191 | ||
192 | if (verbose > 2) { | 192 | if (verbose > 2) { |
193 | pr_info("use callchain: %d, cumulate callchain: %d\n", | 193 | pr_info("use callchain: %d, cumulate callchain: %d\n", |
@@ -454,12 +454,12 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) | |||
454 | * 30.00% 10.00% perf perf [.] cmd_record | 454 | * 30.00% 10.00% perf perf [.] cmd_record |
455 | * 20.00% 0.00% bash libc [.] malloc | 455 | * 20.00% 0.00% bash libc [.] malloc |
456 | * 10.00% 10.00% bash [kernel] [k] page_fault | 456 | * 10.00% 10.00% bash [kernel] [k] page_fault |
457 | * 10.00% 10.00% perf [kernel] [k] schedule | 457 | * 10.00% 10.00% bash bash [.] xmalloc |
458 | * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open | ||
459 | * 10.00% 10.00% perf [kernel] [k] page_fault | 458 | * 10.00% 10.00% perf [kernel] [k] page_fault |
460 | * 10.00% 10.00% perf libc [.] free | ||
461 | * 10.00% 10.00% perf libc [.] malloc | 459 | * 10.00% 10.00% perf libc [.] malloc |
462 | * 10.00% 10.00% bash bash [.] xmalloc | 460 | * 10.00% 10.00% perf [kernel] [k] schedule |
461 | * 10.00% 10.00% perf libc [.] free | ||
462 | * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open | ||
463 | */ | 463 | */ |
464 | struct result expected[] = { | 464 | struct result expected[] = { |
465 | { 7000, 2000, "perf", "perf", "main" }, | 465 | { 7000, 2000, "perf", "perf", "main" }, |
@@ -468,12 +468,12 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) | |||
468 | { 3000, 1000, "perf", "perf", "cmd_record" }, | 468 | { 3000, 1000, "perf", "perf", "cmd_record" }, |
469 | { 2000, 0, "bash", "libc", "malloc" }, | 469 | { 2000, 0, "bash", "libc", "malloc" }, |
470 | { 1000, 1000, "bash", "[kernel]", "page_fault" }, | 470 | { 1000, 1000, "bash", "[kernel]", "page_fault" }, |
471 | { 1000, 1000, "perf", "[kernel]", "schedule" }, | 471 | { 1000, 1000, "bash", "bash", "xmalloc" }, |
472 | { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, | ||
473 | { 1000, 1000, "perf", "[kernel]", "page_fault" }, | 472 | { 1000, 1000, "perf", "[kernel]", "page_fault" }, |
473 | { 1000, 1000, "perf", "[kernel]", "schedule" }, | ||
474 | { 1000, 1000, "perf", "libc", "free" }, | 474 | { 1000, 1000, "perf", "libc", "free" }, |
475 | { 1000, 1000, "perf", "libc", "malloc" }, | 475 | { 1000, 1000, "perf", "libc", "malloc" }, |
476 | { 1000, 1000, "bash", "bash", "xmalloc" }, | 476 | { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, |
477 | }; | 477 | }; |
478 | 478 | ||
479 | symbol_conf.use_callchain = false; | 479 | symbol_conf.use_callchain = false; |
@@ -537,10 +537,13 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
537 | * malloc | 537 | * malloc |
538 | * main | 538 | * main |
539 | * | 539 | * |
540 | * 10.00% 10.00% perf [kernel] [k] schedule | 540 | * 10.00% 10.00% bash bash [.] xmalloc |
541 | * | | 541 | * | |
542 | * --- schedule | 542 | * --- xmalloc |
543 | * run_command | 543 | * malloc |
544 | * xmalloc <--- NOTE: there's a cycle | ||
545 | * malloc | ||
546 | * xmalloc | ||
544 | * main | 547 | * main |
545 | * | 548 | * |
546 | * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open | 549 | * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open |
@@ -556,6 +559,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
556 | * run_command | 559 | * run_command |
557 | * main | 560 | * main |
558 | * | 561 | * |
562 | * 10.00% 10.00% perf [kernel] [k] schedule | ||
563 | * | | ||
564 | * --- schedule | ||
565 | * run_command | ||
566 | * main | ||
567 | * | ||
559 | * 10.00% 10.00% perf libc [.] free | 568 | * 10.00% 10.00% perf libc [.] free |
560 | * | | 569 | * | |
561 | * --- free | 570 | * --- free |
@@ -570,15 +579,6 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
570 | * run_command | 579 | * run_command |
571 | * main | 580 | * main |
572 | * | 581 | * |
573 | * 10.00% 10.00% bash bash [.] xmalloc | ||
574 | * | | ||
575 | * --- xmalloc | ||
576 | * malloc | ||
577 | * xmalloc <--- NOTE: there's a cycle | ||
578 | * malloc | ||
579 | * xmalloc | ||
580 | * main | ||
581 | * | ||
582 | */ | 582 | */ |
583 | struct result expected[] = { | 583 | struct result expected[] = { |
584 | { 7000, 2000, "perf", "perf", "main" }, | 584 | { 7000, 2000, "perf", "perf", "main" }, |
@@ -587,12 +587,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
587 | { 3000, 1000, "perf", "perf", "cmd_record" }, | 587 | { 3000, 1000, "perf", "perf", "cmd_record" }, |
588 | { 2000, 0, "bash", "libc", "malloc" }, | 588 | { 2000, 0, "bash", "libc", "malloc" }, |
589 | { 1000, 1000, "bash", "[kernel]", "page_fault" }, | 589 | { 1000, 1000, "bash", "[kernel]", "page_fault" }, |
590 | { 1000, 1000, "perf", "[kernel]", "schedule" }, | 590 | { 1000, 1000, "bash", "bash", "xmalloc" }, |
591 | { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, | 591 | { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, |
592 | { 1000, 1000, "perf", "[kernel]", "page_fault" }, | 592 | { 1000, 1000, "perf", "[kernel]", "page_fault" }, |
593 | { 1000, 1000, "perf", "[kernel]", "schedule" }, | ||
593 | { 1000, 1000, "perf", "libc", "free" }, | 594 | { 1000, 1000, "perf", "libc", "free" }, |
594 | { 1000, 1000, "perf", "libc", "malloc" }, | 595 | { 1000, 1000, "perf", "libc", "malloc" }, |
595 | { 1000, 1000, "bash", "bash", "xmalloc" }, | ||
596 | }; | 596 | }; |
597 | struct callchain_result expected_callchain[] = { | 597 | struct callchain_result expected_callchain[] = { |
598 | { | 598 | { |
@@ -622,9 +622,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
622 | { "bash", "main" }, }, | 622 | { "bash", "main" }, }, |
623 | }, | 623 | }, |
624 | { | 624 | { |
625 | 3, { { "[kernel]", "schedule" }, | 625 | 6, { { "bash", "xmalloc" }, |
626 | { "perf", "run_command" }, | 626 | { "libc", "malloc" }, |
627 | { "perf", "main" }, }, | 627 | { "bash", "xmalloc" }, |
628 | { "libc", "malloc" }, | ||
629 | { "bash", "xmalloc" }, | ||
630 | { "bash", "main" }, }, | ||
628 | }, | 631 | }, |
629 | { | 632 | { |
630 | 3, { { "[kernel]", "sys_perf_event_open" }, | 633 | 3, { { "[kernel]", "sys_perf_event_open" }, |
@@ -638,6 +641,11 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
638 | { "perf", "main" }, }, | 641 | { "perf", "main" }, }, |
639 | }, | 642 | }, |
640 | { | 643 | { |
644 | 3, { { "[kernel]", "schedule" }, | ||
645 | { "perf", "run_command" }, | ||
646 | { "perf", "main" }, }, | ||
647 | }, | ||
648 | { | ||
641 | 4, { { "libc", "free" }, | 649 | 4, { { "libc", "free" }, |
642 | { "perf", "cmd_record" }, | 650 | { "perf", "cmd_record" }, |
643 | { "perf", "run_command" }, | 651 | { "perf", "run_command" }, |
@@ -649,14 +657,6 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
649 | { "perf", "run_command" }, | 657 | { "perf", "run_command" }, |
650 | { "perf", "main" }, }, | 658 | { "perf", "main" }, }, |
651 | }, | 659 | }, |
652 | { | ||
653 | 6, { { "bash", "xmalloc" }, | ||
654 | { "libc", "malloc" }, | ||
655 | { "bash", "xmalloc" }, | ||
656 | { "libc", "malloc" }, | ||
657 | { "bash", "xmalloc" }, | ||
658 | { "bash", "main" }, }, | ||
659 | }, | ||
660 | }; | 660 | }; |
661 | 661 | ||
662 | symbol_conf.use_callchain = true; | 662 | symbol_conf.use_callchain = true; |
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index 5a31787cc6b9..59e53db7914c 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c | |||
@@ -43,7 +43,7 @@ static struct sample fake_samples[] = { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | static int add_hist_entries(struct perf_evlist *evlist, | 45 | static int add_hist_entries(struct perf_evlist *evlist, |
46 | struct machine *machine __maybe_unused) | 46 | struct machine *machine) |
47 | { | 47 | { |
48 | struct perf_evsel *evsel; | 48 | struct perf_evsel *evsel; |
49 | struct addr_location al; | 49 | struct addr_location al; |
@@ -138,7 +138,7 @@ int test__hists_filter(void) | |||
138 | struct hists *hists = evsel__hists(evsel); | 138 | struct hists *hists = evsel__hists(evsel); |
139 | 139 | ||
140 | hists__collapse_resort(hists, NULL); | 140 | hists__collapse_resort(hists, NULL); |
141 | hists__output_resort(hists); | 141 | hists__output_resort(hists, NULL); |
142 | 142 | ||
143 | if (verbose > 2) { | 143 | if (verbose > 2) { |
144 | pr_info("Normal histogram\n"); | 144 | pr_info("Normal histogram\n"); |
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c index a748f2be1222..f5547610da02 100644 --- a/tools/perf/tests/hists_output.c +++ b/tools/perf/tests/hists_output.c | |||
@@ -152,7 +152,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine) | |||
152 | goto out; | 152 | goto out; |
153 | 153 | ||
154 | hists__collapse_resort(hists, NULL); | 154 | hists__collapse_resort(hists, NULL); |
155 | hists__output_resort(hists); | 155 | hists__output_resort(hists, NULL); |
156 | 156 | ||
157 | if (verbose > 2) { | 157 | if (verbose > 2) { |
158 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | 158 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); |
@@ -252,7 +252,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine) | |||
252 | goto out; | 252 | goto out; |
253 | 253 | ||
254 | hists__collapse_resort(hists, NULL); | 254 | hists__collapse_resort(hists, NULL); |
255 | hists__output_resort(hists); | 255 | hists__output_resort(hists, NULL); |
256 | 256 | ||
257 | if (verbose > 2) { | 257 | if (verbose > 2) { |
258 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | 258 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); |
@@ -306,7 +306,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) | |||
306 | goto out; | 306 | goto out; |
307 | 307 | ||
308 | hists__collapse_resort(hists, NULL); | 308 | hists__collapse_resort(hists, NULL); |
309 | hists__output_resort(hists); | 309 | hists__output_resort(hists, NULL); |
310 | 310 | ||
311 | if (verbose > 2) { | 311 | if (verbose > 2) { |
312 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | 312 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); |
@@ -384,7 +384,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
384 | goto out; | 384 | goto out; |
385 | 385 | ||
386 | hists__collapse_resort(hists, NULL); | 386 | hists__collapse_resort(hists, NULL); |
387 | hists__output_resort(hists); | 387 | hists__output_resort(hists, NULL); |
388 | 388 | ||
389 | if (verbose > 2) { | 389 | if (verbose > 2) { |
390 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | 390 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); |
@@ -487,7 +487,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine) | |||
487 | goto out; | 487 | goto out; |
488 | 488 | ||
489 | hists__collapse_resort(hists, NULL); | 489 | hists__collapse_resort(hists, NULL); |
490 | hists__output_resort(hists); | 490 | hists__output_resort(hists, NULL); |
491 | 491 | ||
492 | if (verbose > 2) { | 492 | if (verbose > 2) { |
493 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | 493 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); |
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c index 4a456fef66ca..2113f1c8611f 100644 --- a/tools/perf/tests/mmap-thread-lookup.c +++ b/tools/perf/tests/mmap-thread-lookup.c | |||
@@ -187,7 +187,7 @@ static int mmap_events(synth_cb synth) | |||
187 | 187 | ||
188 | pr_debug("looking for map %p\n", td->map); | 188 | pr_debug("looking for map %p\n", td->map); |
189 | 189 | ||
190 | thread__find_addr_map(thread, machine, | 190 | thread__find_addr_map(thread, |
191 | PERF_RECORD_MISC_USER, MAP__FUNCTION, | 191 | PERF_RECORD_MISC_USER, MAP__FUNCTION, |
192 | (unsigned long) (td->map + 1), &al); | 192 | (unsigned long) (td->map + 1), &al); |
193 | 193 | ||
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c index ca292f9a4ae2..4908c648a597 100644 --- a/tools/perf/tests/sample-parsing.c +++ b/tools/perf/tests/sample-parsing.c | |||
@@ -126,16 +126,28 @@ static bool samples_same(const struct perf_sample *s1, | |||
126 | if (type & PERF_SAMPLE_TRANSACTION) | 126 | if (type & PERF_SAMPLE_TRANSACTION) |
127 | COMP(transaction); | 127 | COMP(transaction); |
128 | 128 | ||
129 | if (type & PERF_SAMPLE_REGS_INTR) { | ||
130 | size_t sz = hweight_long(s1->intr_regs.mask) * sizeof(u64); | ||
131 | |||
132 | COMP(intr_regs.mask); | ||
133 | COMP(intr_regs.abi); | ||
134 | if (s1->intr_regs.abi && | ||
135 | (!s1->intr_regs.regs || !s2->intr_regs.regs || | ||
136 | memcmp(s1->intr_regs.regs, s2->intr_regs.regs, sz))) { | ||
137 | pr_debug("Samples differ at 'intr_regs'\n"); | ||
138 | return false; | ||
139 | } | ||
140 | } | ||
141 | |||
129 | return true; | 142 | return true; |
130 | } | 143 | } |
131 | 144 | ||
132 | static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format) | 145 | static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) |
133 | { | 146 | { |
134 | struct perf_evsel evsel = { | 147 | struct perf_evsel evsel = { |
135 | .needs_swap = false, | 148 | .needs_swap = false, |
136 | .attr = { | 149 | .attr = { |
137 | .sample_type = sample_type, | 150 | .sample_type = sample_type, |
138 | .sample_regs_user = sample_regs_user, | ||
139 | .read_format = read_format, | 151 | .read_format = read_format, |
140 | }, | 152 | }, |
141 | }; | 153 | }; |
@@ -154,7 +166,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format) | |||
154 | /* 1 branch_entry */ | 166 | /* 1 branch_entry */ |
155 | .data = {1, 211, 212, 213}, | 167 | .data = {1, 211, 212, 213}, |
156 | }; | 168 | }; |
157 | u64 user_regs[64]; | 169 | u64 regs[64]; |
158 | const u64 raw_data[] = {0x123456780a0b0c0dULL, 0x1102030405060708ULL}; | 170 | const u64 raw_data[] = {0x123456780a0b0c0dULL, 0x1102030405060708ULL}; |
159 | const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL}; | 171 | const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL}; |
160 | struct perf_sample sample = { | 172 | struct perf_sample sample = { |
@@ -176,8 +188,8 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format) | |||
176 | .branch_stack = &branch_stack.branch_stack, | 188 | .branch_stack = &branch_stack.branch_stack, |
177 | .user_regs = { | 189 | .user_regs = { |
178 | .abi = PERF_SAMPLE_REGS_ABI_64, | 190 | .abi = PERF_SAMPLE_REGS_ABI_64, |
179 | .mask = sample_regs_user, | 191 | .mask = sample_regs, |
180 | .regs = user_regs, | 192 | .regs = regs, |
181 | }, | 193 | }, |
182 | .user_stack = { | 194 | .user_stack = { |
183 | .size = sizeof(data), | 195 | .size = sizeof(data), |
@@ -187,14 +199,25 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format) | |||
187 | .time_enabled = 0x030a59d664fca7deULL, | 199 | .time_enabled = 0x030a59d664fca7deULL, |
188 | .time_running = 0x011b6ae553eb98edULL, | 200 | .time_running = 0x011b6ae553eb98edULL, |
189 | }, | 201 | }, |
202 | .intr_regs = { | ||
203 | .abi = PERF_SAMPLE_REGS_ABI_64, | ||
204 | .mask = sample_regs, | ||
205 | .regs = regs, | ||
206 | }, | ||
190 | }; | 207 | }; |
191 | struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},}; | 208 | struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},}; |
192 | struct perf_sample sample_out; | 209 | struct perf_sample sample_out; |
193 | size_t i, sz, bufsz; | 210 | size_t i, sz, bufsz; |
194 | int err, ret = -1; | 211 | int err, ret = -1; |
195 | 212 | ||
196 | for (i = 0; i < sizeof(user_regs); i++) | 213 | if (sample_type & PERF_SAMPLE_REGS_USER) |
197 | *(i + (u8 *)user_regs) = i & 0xfe; | 214 | evsel.attr.sample_regs_user = sample_regs; |
215 | |||
216 | if (sample_type & PERF_SAMPLE_REGS_INTR) | ||
217 | evsel.attr.sample_regs_intr = sample_regs; | ||
218 | |||
219 | for (i = 0; i < sizeof(regs); i++) | ||
220 | *(i + (u8 *)regs) = i & 0xfe; | ||
198 | 221 | ||
199 | if (read_format & PERF_FORMAT_GROUP) { | 222 | if (read_format & PERF_FORMAT_GROUP) { |
200 | sample.read.group.nr = 4; | 223 | sample.read.group.nr = 4; |
@@ -271,7 +294,7 @@ int test__sample_parsing(void) | |||
271 | { | 294 | { |
272 | const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15}; | 295 | const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15}; |
273 | u64 sample_type; | 296 | u64 sample_type; |
274 | u64 sample_regs_user; | 297 | u64 sample_regs; |
275 | size_t i; | 298 | size_t i; |
276 | int err; | 299 | int err; |
277 | 300 | ||
@@ -280,7 +303,7 @@ int test__sample_parsing(void) | |||
280 | * were added. Please actually update the test rather than just change | 303 | * were added. Please actually update the test rather than just change |
281 | * the condition below. | 304 | * the condition below. |
282 | */ | 305 | */ |
283 | if (PERF_SAMPLE_MAX > PERF_SAMPLE_TRANSACTION << 1) { | 306 | if (PERF_SAMPLE_MAX > PERF_SAMPLE_REGS_INTR << 1) { |
284 | pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n"); | 307 | pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n"); |
285 | return -1; | 308 | return -1; |
286 | } | 309 | } |
@@ -297,22 +320,24 @@ int test__sample_parsing(void) | |||
297 | } | 320 | } |
298 | continue; | 321 | continue; |
299 | } | 322 | } |
323 | sample_regs = 0; | ||
300 | 324 | ||
301 | if (sample_type == PERF_SAMPLE_REGS_USER) | 325 | if (sample_type == PERF_SAMPLE_REGS_USER) |
302 | sample_regs_user = 0x3fff; | 326 | sample_regs = 0x3fff; |
303 | else | 327 | |
304 | sample_regs_user = 0; | 328 | if (sample_type == PERF_SAMPLE_REGS_INTR) |
329 | sample_regs = 0xff0fff; | ||
305 | 330 | ||
306 | err = do_test(sample_type, sample_regs_user, 0); | 331 | err = do_test(sample_type, sample_regs, 0); |
307 | if (err) | 332 | if (err) |
308 | return err; | 333 | return err; |
309 | } | 334 | } |
310 | 335 | ||
311 | /* Test all sample format bits together */ | 336 | /* Test all sample format bits together */ |
312 | sample_type = PERF_SAMPLE_MAX - 1; | 337 | sample_type = PERF_SAMPLE_MAX - 1; |
313 | sample_regs_user = 0x3fff; | 338 | sample_regs = 0x3fff; /* shared yb intr and user regs */ |
314 | for (i = 0; i < ARRAY_SIZE(rf); i++) { | 339 | for (i = 0; i < ARRAY_SIZE(rf); i++) { |
315 | err = do_test(sample_type, sample_regs_user, rf[i]); | 340 | err = do_test(sample_type, sample_regs, rf[i]); |
316 | if (err) | 341 | if (err) |
317 | return err; | 342 | return err; |
318 | } | 343 | } |
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index f0697a3aede0..1e0a2fd80115 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c | |||
@@ -27,6 +27,7 @@ static struct annotate_browser_opt { | |||
27 | bool hide_src_code, | 27 | bool hide_src_code, |
28 | use_offset, | 28 | use_offset, |
29 | jump_arrows, | 29 | jump_arrows, |
30 | show_linenr, | ||
30 | show_nr_jumps; | 31 | show_nr_jumps; |
31 | } annotate_browser__opts = { | 32 | } annotate_browser__opts = { |
32 | .use_offset = true, | 33 | .use_offset = true, |
@@ -128,7 +129,11 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int | |||
128 | if (!*dl->line) | 129 | if (!*dl->line) |
129 | slsmg_write_nstring(" ", width - pcnt_width); | 130 | slsmg_write_nstring(" ", width - pcnt_width); |
130 | else if (dl->offset == -1) { | 131 | else if (dl->offset == -1) { |
131 | printed = scnprintf(bf, sizeof(bf), "%*s ", | 132 | if (dl->line_nr && annotate_browser__opts.show_linenr) |
133 | printed = scnprintf(bf, sizeof(bf), "%-*d ", | ||
134 | ab->addr_width + 1, dl->line_nr); | ||
135 | else | ||
136 | printed = scnprintf(bf, sizeof(bf), "%*s ", | ||
132 | ab->addr_width, " "); | 137 | ab->addr_width, " "); |
133 | slsmg_write_nstring(bf, printed); | 138 | slsmg_write_nstring(bf, printed); |
134 | slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1); | 139 | slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1); |
@@ -733,6 +738,7 @@ static int annotate_browser__run(struct annotate_browser *browser, | |||
733 | "o Toggle disassembler output/simplified view\n" | 738 | "o Toggle disassembler output/simplified view\n" |
734 | "s Toggle source code view\n" | 739 | "s Toggle source code view\n" |
735 | "/ Search string\n" | 740 | "/ Search string\n" |
741 | "k Toggle line numbers\n" | ||
736 | "r Run available scripts\n" | 742 | "r Run available scripts\n" |
737 | "? Search string backwards\n"); | 743 | "? Search string backwards\n"); |
738 | continue; | 744 | continue; |
@@ -741,6 +747,10 @@ static int annotate_browser__run(struct annotate_browser *browser, | |||
741 | script_browse(NULL); | 747 | script_browse(NULL); |
742 | continue; | 748 | continue; |
743 | } | 749 | } |
750 | case 'k': | ||
751 | annotate_browser__opts.show_linenr = | ||
752 | !annotate_browser__opts.show_linenr; | ||
753 | break; | ||
744 | case 'H': | 754 | case 'H': |
745 | nd = browser->curr_hot; | 755 | nd = browser->curr_hot; |
746 | break; | 756 | break; |
@@ -984,6 +994,7 @@ static struct annotate_config { | |||
984 | } annotate__configs[] = { | 994 | } annotate__configs[] = { |
985 | ANNOTATE_CFG(hide_src_code), | 995 | ANNOTATE_CFG(hide_src_code), |
986 | ANNOTATE_CFG(jump_arrows), | 996 | ANNOTATE_CFG(jump_arrows), |
997 | ANNOTATE_CFG(show_linenr), | ||
987 | ANNOTATE_CFG(show_nr_jumps), | 998 | ANNOTATE_CFG(show_nr_jumps), |
988 | ANNOTATE_CFG(use_offset), | 999 | ANNOTATE_CFG(use_offset), |
989 | }; | 1000 | }; |
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index cfb976b3de3a..788506eef567 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -227,10 +227,14 @@ static void callchain_node__init_have_children_rb_tree(struct callchain_node *no | |||
227 | } | 227 | } |
228 | } | 228 | } |
229 | 229 | ||
230 | static void callchain_node__init_have_children(struct callchain_node *node) | 230 | static void callchain_node__init_have_children(struct callchain_node *node, |
231 | bool has_sibling) | ||
231 | { | 232 | { |
232 | struct callchain_list *chain; | 233 | struct callchain_list *chain; |
233 | 234 | ||
235 | chain = list_entry(node->val.next, struct callchain_list, list); | ||
236 | chain->ms.has_children = has_sibling; | ||
237 | |||
234 | if (!list_empty(&node->val)) { | 238 | if (!list_empty(&node->val)) { |
235 | chain = list_entry(node->val.prev, struct callchain_list, list); | 239 | chain = list_entry(node->val.prev, struct callchain_list, list); |
236 | chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root); | 240 | chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root); |
@@ -241,11 +245,12 @@ static void callchain_node__init_have_children(struct callchain_node *node) | |||
241 | 245 | ||
242 | static void callchain__init_have_children(struct rb_root *root) | 246 | static void callchain__init_have_children(struct rb_root *root) |
243 | { | 247 | { |
244 | struct rb_node *nd; | 248 | struct rb_node *nd = rb_first(root); |
249 | bool has_sibling = nd && rb_next(nd); | ||
245 | 250 | ||
246 | for (nd = rb_first(root); nd; nd = rb_next(nd)) { | 251 | for (nd = rb_first(root); nd; nd = rb_next(nd)) { |
247 | struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node); | 252 | struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node); |
248 | callchain_node__init_have_children(node); | 253 | callchain_node__init_have_children(node, has_sibling); |
249 | } | 254 | } |
250 | } | 255 | } |
251 | 256 | ||
@@ -463,23 +468,6 @@ out: | |||
463 | return key; | 468 | return key; |
464 | } | 469 | } |
465 | 470 | ||
466 | static char *callchain_list__sym_name(struct callchain_list *cl, | ||
467 | char *bf, size_t bfsize, bool show_dso) | ||
468 | { | ||
469 | int printed; | ||
470 | |||
471 | if (cl->ms.sym) | ||
472 | printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name); | ||
473 | else | ||
474 | printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip); | ||
475 | |||
476 | if (show_dso) | ||
477 | scnprintf(bf + printed, bfsize - printed, " %s", | ||
478 | cl->ms.map ? cl->ms.map->dso->short_name : "unknown"); | ||
479 | |||
480 | return bf; | ||
481 | } | ||
482 | |||
483 | struct callchain_print_arg { | 471 | struct callchain_print_arg { |
484 | /* for hists browser */ | 472 | /* for hists browser */ |
485 | off_t row_offset; | 473 | off_t row_offset; |
@@ -559,8 +547,11 @@ static int hist_browser__show_callchain(struct hist_browser *browser, | |||
559 | struct rb_node *node; | 547 | struct rb_node *node; |
560 | int first_row = row, offset = level * LEVEL_OFFSET_STEP; | 548 | int first_row = row, offset = level * LEVEL_OFFSET_STEP; |
561 | u64 new_total; | 549 | u64 new_total; |
550 | bool need_percent; | ||
562 | 551 | ||
563 | node = rb_first(root); | 552 | node = rb_first(root); |
553 | need_percent = node && rb_next(node); | ||
554 | |||
564 | while (node) { | 555 | while (node) { |
565 | struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); | 556 | struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); |
566 | struct rb_node *next = rb_next(node); | 557 | struct rb_node *next = rb_next(node); |
@@ -577,7 +568,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser, | |||
577 | 568 | ||
578 | if (first) | 569 | if (first) |
579 | first = false; | 570 | first = false; |
580 | else if (level > 1) | 571 | else if (need_percent) |
581 | extra_offset = LEVEL_OFFSET_STEP; | 572 | extra_offset = LEVEL_OFFSET_STEP; |
582 | 573 | ||
583 | folded_sign = callchain_list__folded(chain); | 574 | folded_sign = callchain_list__folded(chain); |
@@ -590,7 +581,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser, | |||
590 | str = callchain_list__sym_name(chain, bf, sizeof(bf), | 581 | str = callchain_list__sym_name(chain, bf, sizeof(bf), |
591 | browser->show_dso); | 582 | browser->show_dso); |
592 | 583 | ||
593 | if (was_first && level > 1) { | 584 | if (was_first && need_percent) { |
594 | double percent = cumul * 100.0 / total; | 585 | double percent = cumul * 100.0 / total; |
595 | 586 | ||
596 | if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0) | 587 | if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0) |
@@ -807,6 +798,13 @@ static int hist_browser__show_entry(struct hist_browser *browser, | |||
807 | .is_current_entry = current_entry, | 798 | .is_current_entry = current_entry, |
808 | }; | 799 | }; |
809 | 800 | ||
801 | if (callchain_param.mode == CHAIN_GRAPH_REL) { | ||
802 | if (symbol_conf.cumulate_callchain) | ||
803 | total = entry->stat_acc->period; | ||
804 | else | ||
805 | total = entry->stat.period; | ||
806 | } | ||
807 | |||
810 | printed += hist_browser__show_callchain(browser, | 808 | printed += hist_browser__show_callchain(browser, |
811 | &entry->sorted_chain, 1, row, total, | 809 | &entry->sorted_chain, 1, row, total, |
812 | hist_browser__show_callchain_entry, &arg, | 810 | hist_browser__show_callchain_entry, &arg, |
@@ -1254,7 +1252,7 @@ static int hists__browser_title(struct hists *hists, | |||
1254 | 1252 | ||
1255 | nr_samples = convert_unit(nr_samples, &unit); | 1253 | nr_samples = convert_unit(nr_samples, &unit); |
1256 | printed = scnprintf(bf, size, | 1254 | printed = scnprintf(bf, size, |
1257 | "Samples: %lu%c of event '%s', Event count (approx.): %lu", | 1255 | "Samples: %lu%c of event '%s', Event count (approx.): %" PRIu64, |
1258 | nr_samples, unit, ev_name, nr_events); | 1256 | nr_samples, unit, ev_name, nr_events); |
1259 | 1257 | ||
1260 | 1258 | ||
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index fc654fb77ace..4b3585eed1e8 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c | |||
@@ -89,15 +89,6 @@ void perf_gtk__init_hpp(void) | |||
89 | perf_gtk__hpp_color_overhead_acc; | 89 | perf_gtk__hpp_color_overhead_acc; |
90 | } | 90 | } |
91 | 91 | ||
92 | static void callchain_list__sym_name(struct callchain_list *cl, | ||
93 | char *bf, size_t bfsize) | ||
94 | { | ||
95 | if (cl->ms.sym) | ||
96 | scnprintf(bf, bfsize, "%s", cl->ms.sym->name); | ||
97 | else | ||
98 | scnprintf(bf, bfsize, "%#" PRIx64, cl->ip); | ||
99 | } | ||
100 | |||
101 | static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, | 92 | static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, |
102 | GtkTreeIter *parent, int col, u64 total) | 93 | GtkTreeIter *parent, int col, u64 total) |
103 | { | 94 | { |
@@ -128,7 +119,7 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, | |||
128 | scnprintf(buf, sizeof(buf), "%5.2f%%", percent); | 119 | scnprintf(buf, sizeof(buf), "%5.2f%%", percent); |
129 | gtk_tree_store_set(store, &iter, 0, buf, -1); | 120 | gtk_tree_store_set(store, &iter, 0, buf, -1); |
130 | 121 | ||
131 | callchain_list__sym_name(chain, buf, sizeof(buf)); | 122 | callchain_list__sym_name(chain, buf, sizeof(buf), false); |
132 | gtk_tree_store_set(store, &iter, col, buf, -1); | 123 | gtk_tree_store_set(store, &iter, col, buf, -1); |
133 | 124 | ||
134 | if (need_new_parent) { | 125 | if (need_new_parent) { |
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 2af18376b077..482adae3cc44 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c | |||
@@ -162,8 +162,8 @@ static int __hpp__sort(struct hist_entry *a, struct hist_entry *b, | |||
162 | return ret; | 162 | return ret; |
163 | 163 | ||
164 | nr_members = evsel->nr_members; | 164 | nr_members = evsel->nr_members; |
165 | fields_a = calloc(sizeof(*fields_a), nr_members); | 165 | fields_a = calloc(nr_members, sizeof(*fields_a)); |
166 | fields_b = calloc(sizeof(*fields_b), nr_members); | 166 | fields_b = calloc(nr_members, sizeof(*fields_b)); |
167 | 167 | ||
168 | if (!fields_a || !fields_b) | 168 | if (!fields_a || !fields_b) |
169 | goto out; | 169 | goto out; |
@@ -204,6 +204,9 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b, | |||
204 | if (ret) | 204 | if (ret) |
205 | return ret; | 205 | return ret; |
206 | 206 | ||
207 | if (a->thread != b->thread || !symbol_conf.use_callchain) | ||
208 | return 0; | ||
209 | |||
207 | ret = b->callchain->max_depth - a->callchain->max_depth; | 210 | ret = b->callchain->max_depth - a->callchain->max_depth; |
208 | } | 211 | } |
209 | return ret; | 212 | return ret; |
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 15b451acbde6..dfcbc90146ef 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c | |||
@@ -41,6 +41,7 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, | |||
41 | { | 41 | { |
42 | int i; | 42 | int i; |
43 | size_t ret = 0; | 43 | size_t ret = 0; |
44 | char bf[1024]; | ||
44 | 45 | ||
45 | ret += callchain__fprintf_left_margin(fp, left_margin); | 46 | ret += callchain__fprintf_left_margin(fp, left_margin); |
46 | for (i = 0; i < depth; i++) { | 47 | for (i = 0; i < depth; i++) { |
@@ -56,11 +57,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, | |||
56 | } else | 57 | } else |
57 | ret += fprintf(fp, "%s", " "); | 58 | ret += fprintf(fp, "%s", " "); |
58 | } | 59 | } |
59 | if (chain->ms.sym) | 60 | fputs(callchain_list__sym_name(chain, bf, sizeof(bf), false), fp); |
60 | ret += fprintf(fp, "%s\n", chain->ms.sym->name); | 61 | fputc('\n', fp); |
61 | else | ||
62 | ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip); | ||
63 | |||
64 | return ret; | 62 | return ret; |
65 | } | 63 | } |
66 | 64 | ||
@@ -168,6 +166,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, | |||
168 | struct rb_node *node; | 166 | struct rb_node *node; |
169 | int i = 0; | 167 | int i = 0; |
170 | int ret = 0; | 168 | int ret = 0; |
169 | char bf[1024]; | ||
171 | 170 | ||
172 | /* | 171 | /* |
173 | * If have one single callchain root, don't bother printing | 172 | * If have one single callchain root, don't bother printing |
@@ -196,10 +195,8 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, | |||
196 | } else | 195 | } else |
197 | ret += callchain__fprintf_left_margin(fp, left_margin); | 196 | ret += callchain__fprintf_left_margin(fp, left_margin); |
198 | 197 | ||
199 | if (chain->ms.sym) | 198 | ret += fprintf(fp, "%s\n", callchain_list__sym_name(chain, bf, sizeof(bf), |
200 | ret += fprintf(fp, " %s\n", chain->ms.sym->name); | 199 | false)); |
201 | else | ||
202 | ret += fprintf(fp, " %p\n", (void *)(long)chain->ip); | ||
203 | 200 | ||
204 | if (++entries_printed == callchain_param.print_limit) | 201 | if (++entries_printed == callchain_param.print_limit) |
205 | break; | 202 | break; |
@@ -219,6 +216,7 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node, | |||
219 | { | 216 | { |
220 | struct callchain_list *chain; | 217 | struct callchain_list *chain; |
221 | size_t ret = 0; | 218 | size_t ret = 0; |
219 | char bf[1024]; | ||
222 | 220 | ||
223 | if (!node) | 221 | if (!node) |
224 | return 0; | 222 | return 0; |
@@ -229,11 +227,8 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node, | |||
229 | list_for_each_entry(chain, &node->val, list) { | 227 | list_for_each_entry(chain, &node->val, list) { |
230 | if (chain->ip >= PERF_CONTEXT_MAX) | 228 | if (chain->ip >= PERF_CONTEXT_MAX) |
231 | continue; | 229 | continue; |
232 | if (chain->ms.sym) | 230 | ret += fprintf(fp, " %s\n", callchain_list__sym_name(chain, |
233 | ret += fprintf(fp, " %s\n", chain->ms.sym->name); | 231 | bf, sizeof(bf), false)); |
234 | else | ||
235 | ret += fprintf(fp, " %p\n", | ||
236 | (void *)(long)chain->ip); | ||
237 | } | 232 | } |
238 | 233 | ||
239 | return ret; | 234 | return ret; |
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c index 2f612562978c..3c38f25b1695 100644 --- a/tools/perf/ui/tui/setup.c +++ b/tools/perf/ui/tui/setup.c | |||
@@ -1,5 +1,8 @@ | |||
1 | #include <signal.h> | 1 | #include <signal.h> |
2 | #include <stdbool.h> | 2 | #include <stdbool.h> |
3 | #ifdef HAVE_BACKTRACE_SUPPORT | ||
4 | #include <execinfo.h> | ||
5 | #endif | ||
3 | 6 | ||
4 | #include "../../util/cache.h" | 7 | #include "../../util/cache.h" |
5 | #include "../../util/debug.h" | 8 | #include "../../util/debug.h" |
@@ -88,6 +91,25 @@ int ui__getch(int delay_secs) | |||
88 | return SLkp_getkey(); | 91 | return SLkp_getkey(); |
89 | } | 92 | } |
90 | 93 | ||
94 | #ifdef HAVE_BACKTRACE_SUPPORT | ||
95 | static void ui__signal_backtrace(int sig) | ||
96 | { | ||
97 | void *stackdump[32]; | ||
98 | size_t size; | ||
99 | |||
100 | ui__exit(false); | ||
101 | psignal(sig, "perf"); | ||
102 | |||
103 | printf("-------- backtrace --------\n"); | ||
104 | size = backtrace(stackdump, ARRAY_SIZE(stackdump)); | ||
105 | backtrace_symbols_fd(stackdump, size, STDOUT_FILENO); | ||
106 | |||
107 | exit(0); | ||
108 | } | ||
109 | #else | ||
110 | # define ui__signal_backtrace ui__signal | ||
111 | #endif | ||
112 | |||
91 | static void ui__signal(int sig) | 113 | static void ui__signal(int sig) |
92 | { | 114 | { |
93 | ui__exit(false); | 115 | ui__exit(false); |
@@ -122,8 +144,8 @@ int ui__init(void) | |||
122 | ui_browser__init(); | 144 | ui_browser__init(); |
123 | tui_progress__init(); | 145 | tui_progress__init(); |
124 | 146 | ||
125 | signal(SIGSEGV, ui__signal); | 147 | signal(SIGSEGV, ui__signal_backtrace); |
126 | signal(SIGFPE, ui__signal); | 148 | signal(SIGFPE, ui__signal_backtrace); |
127 | signal(SIGINT, ui__signal); | 149 | signal(SIGINT, ui__signal); |
128 | signal(SIGQUIT, ui__signal); | 150 | signal(SIGQUIT, ui__signal); |
129 | signal(SIGTERM, ui__signal); | 151 | signal(SIGTERM, ui__signal); |
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 7dabde14ea54..79999ceaf2be 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
@@ -17,11 +17,13 @@ | |||
17 | #include "debug.h" | 17 | #include "debug.h" |
18 | #include "annotate.h" | 18 | #include "annotate.h" |
19 | #include "evsel.h" | 19 | #include "evsel.h" |
20 | #include <regex.h> | ||
20 | #include <pthread.h> | 21 | #include <pthread.h> |
21 | #include <linux/bitops.h> | 22 | #include <linux/bitops.h> |
22 | 23 | ||
23 | const char *disassembler_style; | 24 | const char *disassembler_style; |
24 | const char *objdump_path; | 25 | const char *objdump_path; |
26 | static regex_t file_lineno; | ||
25 | 27 | ||
26 | static struct ins *ins__find(const char *name); | 28 | static struct ins *ins__find(const char *name); |
27 | static int disasm_line__parse(char *line, char **namep, char **rawp); | 29 | static int disasm_line__parse(char *line, char **namep, char **rawp); |
@@ -570,13 +572,15 @@ out_free_name: | |||
570 | return -1; | 572 | return -1; |
571 | } | 573 | } |
572 | 574 | ||
573 | static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize) | 575 | static struct disasm_line *disasm_line__new(s64 offset, char *line, |
576 | size_t privsize, int line_nr) | ||
574 | { | 577 | { |
575 | struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); | 578 | struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); |
576 | 579 | ||
577 | if (dl != NULL) { | 580 | if (dl != NULL) { |
578 | dl->offset = offset; | 581 | dl->offset = offset; |
579 | dl->line = strdup(line); | 582 | dl->line = strdup(line); |
583 | dl->line_nr = line_nr; | ||
580 | if (dl->line == NULL) | 584 | if (dl->line == NULL) |
581 | goto out_delete; | 585 | goto out_delete; |
582 | 586 | ||
@@ -788,13 +792,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st | |||
788 | * The ops.raw part will be parsed further according to type of the instruction. | 792 | * The ops.raw part will be parsed further according to type of the instruction. |
789 | */ | 793 | */ |
790 | static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | 794 | static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, |
791 | FILE *file, size_t privsize) | 795 | FILE *file, size_t privsize, |
796 | int *line_nr) | ||
792 | { | 797 | { |
793 | struct annotation *notes = symbol__annotation(sym); | 798 | struct annotation *notes = symbol__annotation(sym); |
794 | struct disasm_line *dl; | 799 | struct disasm_line *dl; |
795 | char *line = NULL, *parsed_line, *tmp, *tmp2, *c; | 800 | char *line = NULL, *parsed_line, *tmp, *tmp2, *c; |
796 | size_t line_len; | 801 | size_t line_len; |
797 | s64 line_ip, offset = -1; | 802 | s64 line_ip, offset = -1; |
803 | regmatch_t match[2]; | ||
798 | 804 | ||
799 | if (getline(&line, &line_len, file) < 0) | 805 | if (getline(&line, &line_len, file) < 0) |
800 | return -1; | 806 | return -1; |
@@ -812,6 +818,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | |||
812 | line_ip = -1; | 818 | line_ip = -1; |
813 | parsed_line = line; | 819 | parsed_line = line; |
814 | 820 | ||
821 | /* /filename:linenr ? Save line number and ignore. */ | ||
822 | if (regexec(&file_lineno, line, 2, match, 0) == 0) { | ||
823 | *line_nr = atoi(line + match[1].rm_so); | ||
824 | return 0; | ||
825 | } | ||
826 | |||
815 | /* | 827 | /* |
816 | * Strip leading spaces: | 828 | * Strip leading spaces: |
817 | */ | 829 | */ |
@@ -842,8 +854,9 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | |||
842 | parsed_line = tmp2 + 1; | 854 | parsed_line = tmp2 + 1; |
843 | } | 855 | } |
844 | 856 | ||
845 | dl = disasm_line__new(offset, parsed_line, privsize); | 857 | dl = disasm_line__new(offset, parsed_line, privsize, *line_nr); |
846 | free(line); | 858 | free(line); |
859 | (*line_nr)++; | ||
847 | 860 | ||
848 | if (dl == NULL) | 861 | if (dl == NULL) |
849 | return -1; | 862 | return -1; |
@@ -869,6 +882,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | |||
869 | return 0; | 882 | return 0; |
870 | } | 883 | } |
871 | 884 | ||
885 | static __attribute__((constructor)) void symbol__init_regexpr(void) | ||
886 | { | ||
887 | regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED); | ||
888 | } | ||
889 | |||
872 | static void delete_last_nop(struct symbol *sym) | 890 | static void delete_last_nop(struct symbol *sym) |
873 | { | 891 | { |
874 | struct annotation *notes = symbol__annotation(sym); | 892 | struct annotation *notes = symbol__annotation(sym); |
@@ -904,6 +922,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) | |||
904 | char symfs_filename[PATH_MAX]; | 922 | char symfs_filename[PATH_MAX]; |
905 | struct kcore_extract kce; | 923 | struct kcore_extract kce; |
906 | bool delete_extract = false; | 924 | bool delete_extract = false; |
925 | int lineno = 0; | ||
907 | 926 | ||
908 | if (filename) | 927 | if (filename) |
909 | symbol__join_symfs(symfs_filename, filename); | 928 | symbol__join_symfs(symfs_filename, filename); |
@@ -915,6 +934,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) | |||
915 | return -ENOMEM; | 934 | return -ENOMEM; |
916 | } | 935 | } |
917 | goto fallback; | 936 | goto fallback; |
937 | } else if (dso__is_kcore(dso)) { | ||
938 | goto fallback; | ||
918 | } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || | 939 | } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || |
919 | strstr(command, "[kernel.kallsyms]") || | 940 | strstr(command, "[kernel.kallsyms]") || |
920 | access(symfs_filename, R_OK)) { | 941 | access(symfs_filename, R_OK)) { |
@@ -982,7 +1003,7 @@ fallback: | |||
982 | snprintf(command, sizeof(command), | 1003 | snprintf(command, sizeof(command), |
983 | "%s %s%s --start-address=0x%016" PRIx64 | 1004 | "%s %s%s --start-address=0x%016" PRIx64 |
984 | " --stop-address=0x%016" PRIx64 | 1005 | " --stop-address=0x%016" PRIx64 |
985 | " -d %s %s -C %s 2>/dev/null|grep -v %s|expand", | 1006 | " -l -d %s %s -C %s 2>/dev/null|grep -v %s|expand", |
986 | objdump_path ? objdump_path : "objdump", | 1007 | objdump_path ? objdump_path : "objdump", |
987 | disassembler_style ? "-M " : "", | 1008 | disassembler_style ? "-M " : "", |
988 | disassembler_style ? disassembler_style : "", | 1009 | disassembler_style ? disassembler_style : "", |
@@ -999,7 +1020,8 @@ fallback: | |||
999 | goto out_free_filename; | 1020 | goto out_free_filename; |
1000 | 1021 | ||
1001 | while (!feof(file)) | 1022 | while (!feof(file)) |
1002 | if (symbol__parse_objdump_line(sym, map, file, privsize) < 0) | 1023 | if (symbol__parse_objdump_line(sym, map, file, privsize, |
1024 | &lineno) < 0) | ||
1003 | break; | 1025 | break; |
1004 | 1026 | ||
1005 | /* | 1027 | /* |
@@ -1170,7 +1192,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, | |||
1170 | goto next; | 1192 | goto next; |
1171 | 1193 | ||
1172 | offset = start + i; | 1194 | offset = start + i; |
1173 | src_line->path = get_srcline(map->dso, offset); | 1195 | src_line->path = get_srcline(map->dso, offset, NULL, false); |
1174 | insert_source_line(&tmp_root, src_line); | 1196 | insert_source_line(&tmp_root, src_line); |
1175 | 1197 | ||
1176 | next: | 1198 | next: |
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 112d6e268150..cadbdc90a5cb 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h | |||
@@ -58,6 +58,7 @@ struct disasm_line { | |||
58 | char *line; | 58 | char *line; |
59 | char *name; | 59 | char *name; |
60 | struct ins *ins; | 60 | struct ins *ins; |
61 | int line_nr; | ||
61 | struct ins_operands ops; | 62 | struct ins_operands ops; |
62 | }; | 63 | }; |
63 | 64 | ||
@@ -115,11 +116,6 @@ struct annotation { | |||
115 | struct annotated_source *src; | 116 | struct annotated_source *src; |
116 | }; | 117 | }; |
117 | 118 | ||
118 | struct sannotation { | ||
119 | struct annotation annotation; | ||
120 | struct symbol symbol; | ||
121 | }; | ||
122 | |||
123 | static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) | 119 | static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) |
124 | { | 120 | { |
125 | return (((void *)¬es->src->histograms) + | 121 | return (((void *)¬es->src->histograms) + |
@@ -128,8 +124,7 @@ static inline struct sym_hist *annotation__histogram(struct annotation *notes, i | |||
128 | 124 | ||
129 | static inline struct annotation *symbol__annotation(struct symbol *sym) | 125 | static inline struct annotation *symbol__annotation(struct symbol *sym) |
130 | { | 126 | { |
131 | struct sannotation *a = container_of(sym, struct sannotation, symbol); | 127 | return (void *)sym - symbol_conf.priv_size; |
132 | return &a->annotation; | ||
133 | } | 128 | } |
134 | 129 | ||
135 | int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx); | 130 | int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx); |
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index a904a4cfe7d3..0c72680a977f 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -15,6 +15,11 @@ | |||
15 | #include "debug.h" | 15 | #include "debug.h" |
16 | #include "session.h" | 16 | #include "session.h" |
17 | #include "tool.h" | 17 | #include "tool.h" |
18 | #include "header.h" | ||
19 | #include "vdso.h" | ||
20 | |||
21 | |||
22 | static bool no_buildid_cache; | ||
18 | 23 | ||
19 | int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, | 24 | int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, |
20 | union perf_event *event, | 25 | union perf_event *event, |
@@ -33,8 +38,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, | |||
33 | return -1; | 38 | return -1; |
34 | } | 39 | } |
35 | 40 | ||
36 | thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, | 41 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, &al); |
37 | sample->ip, &al); | ||
38 | 42 | ||
39 | if (al.map != NULL) | 43 | if (al.map != NULL) |
40 | al.map->dso->hit = 1; | 44 | al.map->dso->hit = 1; |
@@ -106,3 +110,340 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) | |||
106 | build_id_hex, build_id_hex + 2); | 110 | build_id_hex, build_id_hex + 2); |
107 | return bf; | 111 | return bf; |
108 | } | 112 | } |
113 | |||
114 | #define dsos__for_each_with_build_id(pos, head) \ | ||
115 | list_for_each_entry(pos, head, node) \ | ||
116 | if (!pos->has_build_id) \ | ||
117 | continue; \ | ||
118 | else | ||
119 | |||
120 | static int write_buildid(const char *name, size_t name_len, u8 *build_id, | ||
121 | pid_t pid, u16 misc, int fd) | ||
122 | { | ||
123 | int err; | ||
124 | struct build_id_event b; | ||
125 | size_t len; | ||
126 | |||
127 | len = name_len + 1; | ||
128 | len = PERF_ALIGN(len, NAME_ALIGN); | ||
129 | |||
130 | memset(&b, 0, sizeof(b)); | ||
131 | memcpy(&b.build_id, build_id, BUILD_ID_SIZE); | ||
132 | b.pid = pid; | ||
133 | b.header.misc = misc; | ||
134 | b.header.size = sizeof(b) + len; | ||
135 | |||
136 | err = writen(fd, &b, sizeof(b)); | ||
137 | if (err < 0) | ||
138 | return err; | ||
139 | |||
140 | return write_padded(fd, name, name_len + 1, len); | ||
141 | } | ||
142 | |||
143 | static int __dsos__write_buildid_table(struct list_head *head, | ||
144 | struct machine *machine, | ||
145 | pid_t pid, u16 misc, int fd) | ||
146 | { | ||
147 | char nm[PATH_MAX]; | ||
148 | struct dso *pos; | ||
149 | |||
150 | dsos__for_each_with_build_id(pos, head) { | ||
151 | int err; | ||
152 | const char *name; | ||
153 | size_t name_len; | ||
154 | |||
155 | if (!pos->hit) | ||
156 | continue; | ||
157 | |||
158 | if (dso__is_vdso(pos)) { | ||
159 | name = pos->short_name; | ||
160 | name_len = pos->short_name_len + 1; | ||
161 | } else if (dso__is_kcore(pos)) { | ||
162 | machine__mmap_name(machine, nm, sizeof(nm)); | ||
163 | name = nm; | ||
164 | name_len = strlen(nm) + 1; | ||
165 | } else { | ||
166 | name = pos->long_name; | ||
167 | name_len = pos->long_name_len + 1; | ||
168 | } | ||
169 | |||
170 | err = write_buildid(name, name_len, pos->build_id, | ||
171 | pid, misc, fd); | ||
172 | if (err) | ||
173 | return err; | ||
174 | } | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int machine__write_buildid_table(struct machine *machine, int fd) | ||
180 | { | ||
181 | int err; | ||
182 | u16 kmisc = PERF_RECORD_MISC_KERNEL, | ||
183 | umisc = PERF_RECORD_MISC_USER; | ||
184 | |||
185 | if (!machine__is_host(machine)) { | ||
186 | kmisc = PERF_RECORD_MISC_GUEST_KERNEL; | ||
187 | umisc = PERF_RECORD_MISC_GUEST_USER; | ||
188 | } | ||
189 | |||
190 | err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine, | ||
191 | machine->pid, kmisc, fd); | ||
192 | if (err == 0) | ||
193 | err = __dsos__write_buildid_table(&machine->user_dsos.head, | ||
194 | machine, machine->pid, umisc, | ||
195 | fd); | ||
196 | return err; | ||
197 | } | ||
198 | |||
199 | int perf_session__write_buildid_table(struct perf_session *session, int fd) | ||
200 | { | ||
201 | struct rb_node *nd; | ||
202 | int err = machine__write_buildid_table(&session->machines.host, fd); | ||
203 | |||
204 | if (err) | ||
205 | return err; | ||
206 | |||
207 | for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { | ||
208 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | ||
209 | err = machine__write_buildid_table(pos, fd); | ||
210 | if (err) | ||
211 | break; | ||
212 | } | ||
213 | return err; | ||
214 | } | ||
215 | |||
216 | static int __dsos__hit_all(struct list_head *head) | ||
217 | { | ||
218 | struct dso *pos; | ||
219 | |||
220 | list_for_each_entry(pos, head, node) | ||
221 | pos->hit = true; | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int machine__hit_all_dsos(struct machine *machine) | ||
227 | { | ||
228 | int err; | ||
229 | |||
230 | err = __dsos__hit_all(&machine->kernel_dsos.head); | ||
231 | if (err) | ||
232 | return err; | ||
233 | |||
234 | return __dsos__hit_all(&machine->user_dsos.head); | ||
235 | } | ||
236 | |||
237 | int dsos__hit_all(struct perf_session *session) | ||
238 | { | ||
239 | struct rb_node *nd; | ||
240 | int err; | ||
241 | |||
242 | err = machine__hit_all_dsos(&session->machines.host); | ||
243 | if (err) | ||
244 | return err; | ||
245 | |||
246 | for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { | ||
247 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | ||
248 | |||
249 | err = machine__hit_all_dsos(pos); | ||
250 | if (err) | ||
251 | return err; | ||
252 | } | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | void disable_buildid_cache(void) | ||
258 | { | ||
259 | no_buildid_cache = true; | ||
260 | } | ||
261 | |||
262 | int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, | ||
263 | const char *name, bool is_kallsyms, bool is_vdso) | ||
264 | { | ||
265 | const size_t size = PATH_MAX; | ||
266 | char *realname, *filename = zalloc(size), | ||
267 | *linkname = zalloc(size), *targetname; | ||
268 | int len, err = -1; | ||
269 | bool slash = is_kallsyms || is_vdso; | ||
270 | |||
271 | if (is_kallsyms) { | ||
272 | if (symbol_conf.kptr_restrict) { | ||
273 | pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n"); | ||
274 | err = 0; | ||
275 | goto out_free; | ||
276 | } | ||
277 | realname = (char *) name; | ||
278 | } else | ||
279 | realname = realpath(name, NULL); | ||
280 | |||
281 | if (realname == NULL || filename == NULL || linkname == NULL) | ||
282 | goto out_free; | ||
283 | |||
284 | len = scnprintf(filename, size, "%s%s%s", | ||
285 | debugdir, slash ? "/" : "", | ||
286 | is_vdso ? DSO__NAME_VDSO : realname); | ||
287 | if (mkdir_p(filename, 0755)) | ||
288 | goto out_free; | ||
289 | |||
290 | snprintf(filename + len, size - len, "/%s", sbuild_id); | ||
291 | |||
292 | if (access(filename, F_OK)) { | ||
293 | if (is_kallsyms) { | ||
294 | if (copyfile("/proc/kallsyms", filename)) | ||
295 | goto out_free; | ||
296 | } else if (link(realname, filename) && copyfile(name, filename)) | ||
297 | goto out_free; | ||
298 | } | ||
299 | |||
300 | len = scnprintf(linkname, size, "%s/.build-id/%.2s", | ||
301 | debugdir, sbuild_id); | ||
302 | |||
303 | if (access(linkname, X_OK) && mkdir_p(linkname, 0755)) | ||
304 | goto out_free; | ||
305 | |||
306 | snprintf(linkname + len, size - len, "/%s", sbuild_id + 2); | ||
307 | targetname = filename + strlen(debugdir) - 5; | ||
308 | memcpy(targetname, "../..", 5); | ||
309 | |||
310 | if (symlink(targetname, linkname) == 0) | ||
311 | err = 0; | ||
312 | out_free: | ||
313 | if (!is_kallsyms) | ||
314 | free(realname); | ||
315 | free(filename); | ||
316 | free(linkname); | ||
317 | return err; | ||
318 | } | ||
319 | |||
320 | static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, | ||
321 | const char *name, const char *debugdir, | ||
322 | bool is_kallsyms, bool is_vdso) | ||
323 | { | ||
324 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | ||
325 | |||
326 | build_id__sprintf(build_id, build_id_size, sbuild_id); | ||
327 | |||
328 | return build_id_cache__add_s(sbuild_id, debugdir, name, | ||
329 | is_kallsyms, is_vdso); | ||
330 | } | ||
331 | |||
332 | int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) | ||
333 | { | ||
334 | const size_t size = PATH_MAX; | ||
335 | char *filename = zalloc(size), | ||
336 | *linkname = zalloc(size); | ||
337 | int err = -1; | ||
338 | |||
339 | if (filename == NULL || linkname == NULL) | ||
340 | goto out_free; | ||
341 | |||
342 | snprintf(linkname, size, "%s/.build-id/%.2s/%s", | ||
343 | debugdir, sbuild_id, sbuild_id + 2); | ||
344 | |||
345 | if (access(linkname, F_OK)) | ||
346 | goto out_free; | ||
347 | |||
348 | if (readlink(linkname, filename, size - 1) < 0) | ||
349 | goto out_free; | ||
350 | |||
351 | if (unlink(linkname)) | ||
352 | goto out_free; | ||
353 | |||
354 | /* | ||
355 | * Since the link is relative, we must make it absolute: | ||
356 | */ | ||
357 | snprintf(linkname, size, "%s/.build-id/%.2s/%s", | ||
358 | debugdir, sbuild_id, filename); | ||
359 | |||
360 | if (unlink(linkname)) | ||
361 | goto out_free; | ||
362 | |||
363 | err = 0; | ||
364 | out_free: | ||
365 | free(filename); | ||
366 | free(linkname); | ||
367 | return err; | ||
368 | } | ||
369 | |||
370 | static int dso__cache_build_id(struct dso *dso, struct machine *machine, | ||
371 | const char *debugdir) | ||
372 | { | ||
373 | bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; | ||
374 | bool is_vdso = dso__is_vdso(dso); | ||
375 | const char *name = dso->long_name; | ||
376 | char nm[PATH_MAX]; | ||
377 | |||
378 | if (dso__is_kcore(dso)) { | ||
379 | is_kallsyms = true; | ||
380 | machine__mmap_name(machine, nm, sizeof(nm)); | ||
381 | name = nm; | ||
382 | } | ||
383 | return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name, | ||
384 | debugdir, is_kallsyms, is_vdso); | ||
385 | } | ||
386 | |||
387 | static int __dsos__cache_build_ids(struct list_head *head, | ||
388 | struct machine *machine, const char *debugdir) | ||
389 | { | ||
390 | struct dso *pos; | ||
391 | int err = 0; | ||
392 | |||
393 | dsos__for_each_with_build_id(pos, head) | ||
394 | if (dso__cache_build_id(pos, machine, debugdir)) | ||
395 | err = -1; | ||
396 | |||
397 | return err; | ||
398 | } | ||
399 | |||
400 | static int machine__cache_build_ids(struct machine *machine, const char *debugdir) | ||
401 | { | ||
402 | int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine, | ||
403 | debugdir); | ||
404 | ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine, | ||
405 | debugdir); | ||
406 | return ret; | ||
407 | } | ||
408 | |||
409 | int perf_session__cache_build_ids(struct perf_session *session) | ||
410 | { | ||
411 | struct rb_node *nd; | ||
412 | int ret; | ||
413 | |||
414 | if (no_buildid_cache) | ||
415 | return 0; | ||
416 | |||
417 | if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST) | ||
418 | return -1; | ||
419 | |||
420 | ret = machine__cache_build_ids(&session->machines.host, buildid_dir); | ||
421 | |||
422 | for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { | ||
423 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | ||
424 | ret |= machine__cache_build_ids(pos, buildid_dir); | ||
425 | } | ||
426 | return ret ? -1 : 0; | ||
427 | } | ||
428 | |||
429 | static bool machine__read_build_ids(struct machine *machine, bool with_hits) | ||
430 | { | ||
431 | bool ret; | ||
432 | |||
433 | ret = __dsos__read_build_ids(&machine->kernel_dsos.head, with_hits); | ||
434 | ret |= __dsos__read_build_ids(&machine->user_dsos.head, with_hits); | ||
435 | return ret; | ||
436 | } | ||
437 | |||
438 | bool perf_session__read_build_ids(struct perf_session *session, bool with_hits) | ||
439 | { | ||
440 | struct rb_node *nd; | ||
441 | bool ret = machine__read_build_ids(&session->machines.host, with_hits); | ||
442 | |||
443 | for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { | ||
444 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | ||
445 | ret |= machine__read_build_ids(pos, with_hits); | ||
446 | } | ||
447 | |||
448 | return ret; | ||
449 | } | ||
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h index ae392561470b..8236319514d5 100644 --- a/tools/perf/util/build-id.h +++ b/tools/perf/util/build-id.h | |||
@@ -15,4 +15,16 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); | |||
15 | int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, | 15 | int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, |
16 | struct perf_sample *sample, struct perf_evsel *evsel, | 16 | struct perf_sample *sample, struct perf_evsel *evsel, |
17 | struct machine *machine); | 17 | struct machine *machine); |
18 | |||
19 | int dsos__hit_all(struct perf_session *session); | ||
20 | |||
21 | bool perf_session__read_build_ids(struct perf_session *session, bool with_hits); | ||
22 | int perf_session__write_buildid_table(struct perf_session *session, int fd); | ||
23 | int perf_session__cache_build_ids(struct perf_session *session); | ||
24 | |||
25 | int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, | ||
26 | const char *name, bool is_kallsyms, bool is_vdso); | ||
27 | int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); | ||
28 | void disable_buildid_cache(void); | ||
29 | |||
18 | #endif | 30 | #endif |
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 5cf9e1b5989d..d04d770d90f6 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h | |||
@@ -71,7 +71,9 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2 | |||
71 | extern char *perf_pathdup(const char *fmt, ...) | 71 | extern char *perf_pathdup(const char *fmt, ...) |
72 | __attribute__((format (printf, 1, 2))); | 72 | __attribute__((format (printf, 1, 2))); |
73 | 73 | ||
74 | #ifndef __UCLIBC__ | ||
74 | /* Matches the libc/libbsd function attribute so we declare this unconditionally: */ | 75 | /* Matches the libc/libbsd function attribute so we declare this unconditionally: */ |
75 | extern size_t strlcpy(char *dest, const char *src, size_t size); | 76 | extern size_t strlcpy(char *dest, const char *src, size_t size); |
77 | #endif | ||
76 | 78 | ||
77 | #endif /* __PERF_CACHE_H */ | 79 | #endif /* __PERF_CACHE_H */ |
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index c84d3f8dcb75..14e7a123d43b 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
@@ -77,7 +77,7 @@ int parse_callchain_record_opt(const char *arg) | |||
77 | ret = 0; | 77 | ret = 0; |
78 | } else | 78 | } else |
79 | pr_err("callchain: No more arguments " | 79 | pr_err("callchain: No more arguments " |
80 | "needed for -g fp\n"); | 80 | "needed for --call-graph fp\n"); |
81 | break; | 81 | break; |
82 | 82 | ||
83 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | 83 | #ifdef HAVE_DWARF_UNWIND_SUPPORT |
@@ -149,6 +149,10 @@ static int parse_callchain_sort_key(const char *value) | |||
149 | callchain_param.key = CCKEY_ADDRESS; | 149 | callchain_param.key = CCKEY_ADDRESS; |
150 | return 0; | 150 | return 0; |
151 | } | 151 | } |
152 | if (!strncmp(value, "branch", strlen(value))) { | ||
153 | callchain_param.branch_callstack = 1; | ||
154 | return 0; | ||
155 | } | ||
152 | return -1; | 156 | return -1; |
153 | } | 157 | } |
154 | 158 | ||
@@ -754,8 +758,8 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent | |||
754 | 758 | ||
755 | if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain || | 759 | if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain || |
756 | sort__has_parent) { | 760 | sort__has_parent) { |
757 | return machine__resolve_callchain(al->machine, evsel, al->thread, | 761 | return thread__resolve_callchain(al->thread, evsel, sample, |
758 | sample, parent, al, max_stack); | 762 | parent, al, max_stack); |
759 | } | 763 | } |
760 | return 0; | 764 | return 0; |
761 | } | 765 | } |
@@ -808,3 +812,62 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node * | |||
808 | out: | 812 | out: |
809 | return 1; | 813 | return 1; |
810 | } | 814 | } |
815 | |||
816 | char *callchain_list__sym_name(struct callchain_list *cl, | ||
817 | char *bf, size_t bfsize, bool show_dso) | ||
818 | { | ||
819 | int printed; | ||
820 | |||
821 | if (cl->ms.sym) { | ||
822 | if (callchain_param.key == CCKEY_ADDRESS && | ||
823 | cl->ms.map && !cl->srcline) | ||
824 | cl->srcline = get_srcline(cl->ms.map->dso, | ||
825 | map__rip_2objdump(cl->ms.map, | ||
826 | cl->ip), | ||
827 | cl->ms.sym, false); | ||
828 | if (cl->srcline) | ||
829 | printed = scnprintf(bf, bfsize, "%s %s", | ||
830 | cl->ms.sym->name, cl->srcline); | ||
831 | else | ||
832 | printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name); | ||
833 | } else | ||
834 | printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip); | ||
835 | |||
836 | if (show_dso) | ||
837 | scnprintf(bf + printed, bfsize - printed, " %s", | ||
838 | cl->ms.map ? | ||
839 | cl->ms.map->dso->short_name : | ||
840 | "unknown"); | ||
841 | |||
842 | return bf; | ||
843 | } | ||
844 | |||
845 | static void free_callchain_node(struct callchain_node *node) | ||
846 | { | ||
847 | struct callchain_list *list, *tmp; | ||
848 | struct callchain_node *child; | ||
849 | struct rb_node *n; | ||
850 | |||
851 | list_for_each_entry_safe(list, tmp, &node->val, list) { | ||
852 | list_del(&list->list); | ||
853 | free(list); | ||
854 | } | ||
855 | |||
856 | n = rb_first(&node->rb_root_in); | ||
857 | while (n) { | ||
858 | child = container_of(n, struct callchain_node, rb_node_in); | ||
859 | n = rb_next(n); | ||
860 | rb_erase(&child->rb_node_in, &node->rb_root_in); | ||
861 | |||
862 | free_callchain_node(child); | ||
863 | free(child); | ||
864 | } | ||
865 | } | ||
866 | |||
867 | void free_callchain(struct callchain_root *root) | ||
868 | { | ||
869 | if (!symbol_conf.use_callchain) | ||
870 | return; | ||
871 | |||
872 | free_callchain_node(&root->node); | ||
873 | } | ||
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 94cfefddf4db..c0ec1acc38e4 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
@@ -63,6 +63,7 @@ struct callchain_param { | |||
63 | sort_chain_func_t sort; | 63 | sort_chain_func_t sort; |
64 | enum chain_order order; | 64 | enum chain_order order; |
65 | enum chain_key key; | 65 | enum chain_key key; |
66 | bool branch_callstack; | ||
66 | }; | 67 | }; |
67 | 68 | ||
68 | extern struct callchain_param callchain_param; | 69 | extern struct callchain_param callchain_param; |
@@ -70,6 +71,7 @@ extern struct callchain_param callchain_param; | |||
70 | struct callchain_list { | 71 | struct callchain_list { |
71 | u64 ip; | 72 | u64 ip; |
72 | struct map_symbol ms; | 73 | struct map_symbol ms; |
74 | char *srcline; | ||
73 | struct list_head list; | 75 | struct list_head list; |
74 | }; | 76 | }; |
75 | 77 | ||
@@ -184,15 +186,18 @@ static inline void callchain_cursor_snapshot(struct callchain_cursor *dest, | |||
184 | } | 186 | } |
185 | 187 | ||
186 | #ifdef HAVE_SKIP_CALLCHAIN_IDX | 188 | #ifdef HAVE_SKIP_CALLCHAIN_IDX |
187 | extern int arch_skip_callchain_idx(struct machine *machine, | 189 | extern int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain); |
188 | struct thread *thread, struct ip_callchain *chain); | ||
189 | #else | 190 | #else |
190 | static inline int arch_skip_callchain_idx(struct machine *machine __maybe_unused, | 191 | static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused, |
191 | struct thread *thread __maybe_unused, | ||
192 | struct ip_callchain *chain __maybe_unused) | 192 | struct ip_callchain *chain __maybe_unused) |
193 | { | 193 | { |
194 | return -1; | 194 | return -1; |
195 | } | 195 | } |
196 | #endif | 196 | #endif |
197 | 197 | ||
198 | char *callchain_list__sym_name(struct callchain_list *cl, | ||
199 | char *bf, size_t bfsize, bool show_dso); | ||
200 | |||
201 | void free_callchain(struct callchain_root *root); | ||
202 | |||
198 | #endif /* __PERF_CALLCHAIN_H */ | 203 | #endif /* __PERF_CALLCHAIN_H */ |
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h index 51c10ab257f8..71c9c39340d4 100644 --- a/tools/perf/util/comm.h +++ b/tools/perf/util/comm.h | |||
@@ -12,6 +12,10 @@ struct comm { | |||
12 | u64 start; | 12 | u64 start; |
13 | struct list_head list; | 13 | struct list_head list; |
14 | bool exec; | 14 | bool exec; |
15 | union { /* Tool specific area */ | ||
16 | void *priv; | ||
17 | u64 db_id; | ||
18 | }; | ||
15 | }; | 19 | }; |
16 | 20 | ||
17 | void comm__free(struct comm *comm); | 21 | void comm__free(struct comm *comm); |
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 57ff826f150b..e18f653cd7db 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c | |||
@@ -522,7 +522,7 @@ static int buildid_dir_command_config(const char *var, const char *value, | |||
522 | const char *v; | 522 | const char *v; |
523 | 523 | ||
524 | /* same dir for all commands */ | 524 | /* same dir for all commands */ |
525 | if (!prefixcmp(var, "buildid.") && !strcmp(var + 8, "dir")) { | 525 | if (!strcmp(var, "buildid.dir")) { |
526 | v = perf_config_dirname(var, value); | 526 | v = perf_config_dirname(var, value); |
527 | if (!v) | 527 | if (!v) |
528 | return -1; | 528 | return -1; |
@@ -539,12 +539,14 @@ static void check_buildid_dir_config(void) | |||
539 | perf_config(buildid_dir_command_config, &c); | 539 | perf_config(buildid_dir_command_config, &c); |
540 | } | 540 | } |
541 | 541 | ||
542 | void set_buildid_dir(void) | 542 | void set_buildid_dir(const char *dir) |
543 | { | 543 | { |
544 | buildid_dir[0] = '\0'; | 544 | if (dir) |
545 | scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir); | ||
545 | 546 | ||
546 | /* try config file */ | 547 | /* try config file */ |
547 | check_buildid_dir_config(); | 548 | if (buildid_dir[0] == '\0') |
549 | check_buildid_dir_config(); | ||
548 | 550 | ||
549 | /* default to $HOME/.debug */ | 551 | /* default to $HOME/.debug */ |
550 | if (buildid_dir[0] == '\0') { | 552 | if (buildid_dir[0] == '\0') { |
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c new file mode 100644 index 000000000000..c81dae399763 --- /dev/null +++ b/tools/perf/util/db-export.c | |||
@@ -0,0 +1,428 @@ | |||
1 | /* | ||
2 | * db-export.c: Support for exporting data suitable for import to a database | ||
3 | * Copyright (c) 2014, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <errno.h> | ||
17 | |||
18 | #include "evsel.h" | ||
19 | #include "machine.h" | ||
20 | #include "thread.h" | ||
21 | #include "comm.h" | ||
22 | #include "symbol.h" | ||
23 | #include "event.h" | ||
24 | #include "util.h" | ||
25 | #include "thread-stack.h" | ||
26 | #include "db-export.h" | ||
27 | |||
28 | struct deferred_export { | ||
29 | struct list_head node; | ||
30 | struct comm *comm; | ||
31 | }; | ||
32 | |||
33 | static int db_export__deferred(struct db_export *dbe) | ||
34 | { | ||
35 | struct deferred_export *de; | ||
36 | int err; | ||
37 | |||
38 | while (!list_empty(&dbe->deferred)) { | ||
39 | de = list_entry(dbe->deferred.next, struct deferred_export, | ||
40 | node); | ||
41 | err = dbe->export_comm(dbe, de->comm); | ||
42 | list_del(&de->node); | ||
43 | free(de); | ||
44 | if (err) | ||
45 | return err; | ||
46 | } | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static void db_export__free_deferred(struct db_export *dbe) | ||
52 | { | ||
53 | struct deferred_export *de; | ||
54 | |||
55 | while (!list_empty(&dbe->deferred)) { | ||
56 | de = list_entry(dbe->deferred.next, struct deferred_export, | ||
57 | node); | ||
58 | list_del(&de->node); | ||
59 | free(de); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | static int db_export__defer_comm(struct db_export *dbe, struct comm *comm) | ||
64 | { | ||
65 | struct deferred_export *de; | ||
66 | |||
67 | de = zalloc(sizeof(struct deferred_export)); | ||
68 | if (!de) | ||
69 | return -ENOMEM; | ||
70 | |||
71 | de->comm = comm; | ||
72 | list_add_tail(&de->node, &dbe->deferred); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | int db_export__init(struct db_export *dbe) | ||
78 | { | ||
79 | memset(dbe, 0, sizeof(struct db_export)); | ||
80 | INIT_LIST_HEAD(&dbe->deferred); | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | int db_export__flush(struct db_export *dbe) | ||
85 | { | ||
86 | return db_export__deferred(dbe); | ||
87 | } | ||
88 | |||
89 | void db_export__exit(struct db_export *dbe) | ||
90 | { | ||
91 | db_export__free_deferred(dbe); | ||
92 | call_return_processor__free(dbe->crp); | ||
93 | dbe->crp = NULL; | ||
94 | } | ||
95 | |||
96 | int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel) | ||
97 | { | ||
98 | if (evsel->db_id) | ||
99 | return 0; | ||
100 | |||
101 | evsel->db_id = ++dbe->evsel_last_db_id; | ||
102 | |||
103 | if (dbe->export_evsel) | ||
104 | return dbe->export_evsel(dbe, evsel); | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | int db_export__machine(struct db_export *dbe, struct machine *machine) | ||
110 | { | ||
111 | if (machine->db_id) | ||
112 | return 0; | ||
113 | |||
114 | machine->db_id = ++dbe->machine_last_db_id; | ||
115 | |||
116 | if (dbe->export_machine) | ||
117 | return dbe->export_machine(dbe, machine); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | int db_export__thread(struct db_export *dbe, struct thread *thread, | ||
123 | struct machine *machine, struct comm *comm) | ||
124 | { | ||
125 | u64 main_thread_db_id = 0; | ||
126 | int err; | ||
127 | |||
128 | if (thread->db_id) | ||
129 | return 0; | ||
130 | |||
131 | thread->db_id = ++dbe->thread_last_db_id; | ||
132 | |||
133 | if (thread->pid_ != -1) { | ||
134 | struct thread *main_thread; | ||
135 | |||
136 | if (thread->pid_ == thread->tid) { | ||
137 | main_thread = thread; | ||
138 | } else { | ||
139 | main_thread = machine__findnew_thread(machine, | ||
140 | thread->pid_, | ||
141 | thread->pid_); | ||
142 | if (!main_thread) | ||
143 | return -ENOMEM; | ||
144 | err = db_export__thread(dbe, main_thread, machine, | ||
145 | comm); | ||
146 | if (err) | ||
147 | return err; | ||
148 | if (comm) { | ||
149 | err = db_export__comm_thread(dbe, comm, thread); | ||
150 | if (err) | ||
151 | return err; | ||
152 | } | ||
153 | } | ||
154 | main_thread_db_id = main_thread->db_id; | ||
155 | } | ||
156 | |||
157 | if (dbe->export_thread) | ||
158 | return dbe->export_thread(dbe, thread, main_thread_db_id, | ||
159 | machine); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | int db_export__comm(struct db_export *dbe, struct comm *comm, | ||
165 | struct thread *main_thread) | ||
166 | { | ||
167 | int err; | ||
168 | |||
169 | if (comm->db_id) | ||
170 | return 0; | ||
171 | |||
172 | comm->db_id = ++dbe->comm_last_db_id; | ||
173 | |||
174 | if (dbe->export_comm) { | ||
175 | if (main_thread->comm_set) | ||
176 | err = dbe->export_comm(dbe, comm); | ||
177 | else | ||
178 | err = db_export__defer_comm(dbe, comm); | ||
179 | if (err) | ||
180 | return err; | ||
181 | } | ||
182 | |||
183 | return db_export__comm_thread(dbe, comm, main_thread); | ||
184 | } | ||
185 | |||
186 | int db_export__comm_thread(struct db_export *dbe, struct comm *comm, | ||
187 | struct thread *thread) | ||
188 | { | ||
189 | u64 db_id; | ||
190 | |||
191 | db_id = ++dbe->comm_thread_last_db_id; | ||
192 | |||
193 | if (dbe->export_comm_thread) | ||
194 | return dbe->export_comm_thread(dbe, db_id, comm, thread); | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | int db_export__dso(struct db_export *dbe, struct dso *dso, | ||
200 | struct machine *machine) | ||
201 | { | ||
202 | if (dso->db_id) | ||
203 | return 0; | ||
204 | |||
205 | dso->db_id = ++dbe->dso_last_db_id; | ||
206 | |||
207 | if (dbe->export_dso) | ||
208 | return dbe->export_dso(dbe, dso, machine); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | int db_export__symbol(struct db_export *dbe, struct symbol *sym, | ||
214 | struct dso *dso) | ||
215 | { | ||
216 | u64 *sym_db_id = symbol__priv(sym); | ||
217 | |||
218 | if (*sym_db_id) | ||
219 | return 0; | ||
220 | |||
221 | *sym_db_id = ++dbe->symbol_last_db_id; | ||
222 | |||
223 | if (dbe->export_symbol) | ||
224 | return dbe->export_symbol(dbe, sym, dso); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static struct thread *get_main_thread(struct machine *machine, struct thread *thread) | ||
230 | { | ||
231 | if (thread->pid_ == thread->tid) | ||
232 | return thread; | ||
233 | |||
234 | if (thread->pid_ == -1) | ||
235 | return NULL; | ||
236 | |||
237 | return machine__find_thread(machine, thread->pid_, thread->pid_); | ||
238 | } | ||
239 | |||
240 | static int db_ids_from_al(struct db_export *dbe, struct addr_location *al, | ||
241 | u64 *dso_db_id, u64 *sym_db_id, u64 *offset) | ||
242 | { | ||
243 | int err; | ||
244 | |||
245 | if (al->map) { | ||
246 | struct dso *dso = al->map->dso; | ||
247 | |||
248 | err = db_export__dso(dbe, dso, al->machine); | ||
249 | if (err) | ||
250 | return err; | ||
251 | *dso_db_id = dso->db_id; | ||
252 | |||
253 | if (!al->sym) { | ||
254 | al->sym = symbol__new(al->addr, 0, 0, "unknown"); | ||
255 | if (al->sym) | ||
256 | symbols__insert(&dso->symbols[al->map->type], | ||
257 | al->sym); | ||
258 | } | ||
259 | |||
260 | if (al->sym) { | ||
261 | u64 *db_id = symbol__priv(al->sym); | ||
262 | |||
263 | err = db_export__symbol(dbe, al->sym, dso); | ||
264 | if (err) | ||
265 | return err; | ||
266 | *sym_db_id = *db_id; | ||
267 | *offset = al->addr - al->sym->start; | ||
268 | } | ||
269 | } | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | int db_export__branch_type(struct db_export *dbe, u32 branch_type, | ||
275 | const char *name) | ||
276 | { | ||
277 | if (dbe->export_branch_type) | ||
278 | return dbe->export_branch_type(dbe, branch_type, name); | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | int db_export__sample(struct db_export *dbe, union perf_event *event, | ||
284 | struct perf_sample *sample, struct perf_evsel *evsel, | ||
285 | struct thread *thread, struct addr_location *al) | ||
286 | { | ||
287 | struct export_sample es = { | ||
288 | .event = event, | ||
289 | .sample = sample, | ||
290 | .evsel = evsel, | ||
291 | .thread = thread, | ||
292 | .al = al, | ||
293 | }; | ||
294 | struct thread *main_thread; | ||
295 | struct comm *comm = NULL; | ||
296 | int err; | ||
297 | |||
298 | err = db_export__evsel(dbe, evsel); | ||
299 | if (err) | ||
300 | return err; | ||
301 | |||
302 | err = db_export__machine(dbe, al->machine); | ||
303 | if (err) | ||
304 | return err; | ||
305 | |||
306 | main_thread = get_main_thread(al->machine, thread); | ||
307 | if (main_thread) | ||
308 | comm = machine__thread_exec_comm(al->machine, main_thread); | ||
309 | |||
310 | err = db_export__thread(dbe, thread, al->machine, comm); | ||
311 | if (err) | ||
312 | return err; | ||
313 | |||
314 | if (comm) { | ||
315 | err = db_export__comm(dbe, comm, main_thread); | ||
316 | if (err) | ||
317 | return err; | ||
318 | es.comm_db_id = comm->db_id; | ||
319 | } | ||
320 | |||
321 | es.db_id = ++dbe->sample_last_db_id; | ||
322 | |||
323 | err = db_ids_from_al(dbe, al, &es.dso_db_id, &es.sym_db_id, &es.offset); | ||
324 | if (err) | ||
325 | return err; | ||
326 | |||
327 | if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && | ||
328 | sample_addr_correlates_sym(&evsel->attr)) { | ||
329 | struct addr_location addr_al; | ||
330 | |||
331 | perf_event__preprocess_sample_addr(event, sample, thread, &addr_al); | ||
332 | err = db_ids_from_al(dbe, &addr_al, &es.addr_dso_db_id, | ||
333 | &es.addr_sym_db_id, &es.addr_offset); | ||
334 | if (err) | ||
335 | return err; | ||
336 | if (dbe->crp) { | ||
337 | err = thread_stack__process(thread, comm, sample, al, | ||
338 | &addr_al, es.db_id, | ||
339 | dbe->crp); | ||
340 | if (err) | ||
341 | return err; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | if (dbe->export_sample) | ||
346 | return dbe->export_sample(dbe, &es); | ||
347 | |||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static struct { | ||
352 | u32 branch_type; | ||
353 | const char *name; | ||
354 | } branch_types[] = { | ||
355 | {0, "no branch"}, | ||
356 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"}, | ||
357 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"}, | ||
358 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "conditional jump"}, | ||
359 | {PERF_IP_FLAG_BRANCH, "unconditional jump"}, | ||
360 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT, | ||
361 | "software interrupt"}, | ||
362 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT, | ||
363 | "return from interrupt"}, | ||
364 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET, | ||
365 | "system call"}, | ||
366 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET, | ||
367 | "return from system call"}, | ||
368 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "asynchronous branch"}, | ||
369 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | | ||
370 | PERF_IP_FLAG_INTERRUPT, "hardware interrupt"}, | ||
371 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "transaction abort"}, | ||
372 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "trace begin"}, | ||
373 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "trace end"}, | ||
374 | {0, NULL} | ||
375 | }; | ||
376 | |||
377 | int db_export__branch_types(struct db_export *dbe) | ||
378 | { | ||
379 | int i, err = 0; | ||
380 | |||
381 | for (i = 0; branch_types[i].name ; i++) { | ||
382 | err = db_export__branch_type(dbe, branch_types[i].branch_type, | ||
383 | branch_types[i].name); | ||
384 | if (err) | ||
385 | break; | ||
386 | } | ||
387 | return err; | ||
388 | } | ||
389 | |||
390 | int db_export__call_path(struct db_export *dbe, struct call_path *cp) | ||
391 | { | ||
392 | int err; | ||
393 | |||
394 | if (cp->db_id) | ||
395 | return 0; | ||
396 | |||
397 | if (cp->parent) { | ||
398 | err = db_export__call_path(dbe, cp->parent); | ||
399 | if (err) | ||
400 | return err; | ||
401 | } | ||
402 | |||
403 | cp->db_id = ++dbe->call_path_last_db_id; | ||
404 | |||
405 | if (dbe->export_call_path) | ||
406 | return dbe->export_call_path(dbe, cp); | ||
407 | |||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | int db_export__call_return(struct db_export *dbe, struct call_return *cr) | ||
412 | { | ||
413 | int err; | ||
414 | |||
415 | if (cr->db_id) | ||
416 | return 0; | ||
417 | |||
418 | err = db_export__call_path(dbe, cr->cp); | ||
419 | if (err) | ||
420 | return err; | ||
421 | |||
422 | cr->db_id = ++dbe->call_return_last_db_id; | ||
423 | |||
424 | if (dbe->export_call_return) | ||
425 | return dbe->export_call_return(dbe, cr); | ||
426 | |||
427 | return 0; | ||
428 | } | ||
diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h new file mode 100644 index 000000000000..adbd22d66798 --- /dev/null +++ b/tools/perf/util/db-export.h | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * db-export.h: Support for exporting data suitable for import to a database | ||
3 | * Copyright (c) 2014, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #ifndef __PERF_DB_EXPORT_H | ||
17 | #define __PERF_DB_EXPORT_H | ||
18 | |||
19 | #include <linux/types.h> | ||
20 | #include <linux/list.h> | ||
21 | |||
22 | struct perf_evsel; | ||
23 | struct machine; | ||
24 | struct thread; | ||
25 | struct comm; | ||
26 | struct dso; | ||
27 | struct perf_sample; | ||
28 | struct addr_location; | ||
29 | struct call_return_processor; | ||
30 | struct call_path; | ||
31 | struct call_return; | ||
32 | |||
33 | struct export_sample { | ||
34 | union perf_event *event; | ||
35 | struct perf_sample *sample; | ||
36 | struct perf_evsel *evsel; | ||
37 | struct thread *thread; | ||
38 | struct addr_location *al; | ||
39 | u64 db_id; | ||
40 | u64 comm_db_id; | ||
41 | u64 dso_db_id; | ||
42 | u64 sym_db_id; | ||
43 | u64 offset; /* ip offset from symbol start */ | ||
44 | u64 addr_dso_db_id; | ||
45 | u64 addr_sym_db_id; | ||
46 | u64 addr_offset; /* addr offset from symbol start */ | ||
47 | }; | ||
48 | |||
49 | struct db_export { | ||
50 | int (*export_evsel)(struct db_export *dbe, struct perf_evsel *evsel); | ||
51 | int (*export_machine)(struct db_export *dbe, struct machine *machine); | ||
52 | int (*export_thread)(struct db_export *dbe, struct thread *thread, | ||
53 | u64 main_thread_db_id, struct machine *machine); | ||
54 | int (*export_comm)(struct db_export *dbe, struct comm *comm); | ||
55 | int (*export_comm_thread)(struct db_export *dbe, u64 db_id, | ||
56 | struct comm *comm, struct thread *thread); | ||
57 | int (*export_dso)(struct db_export *dbe, struct dso *dso, | ||
58 | struct machine *machine); | ||
59 | int (*export_symbol)(struct db_export *dbe, struct symbol *sym, | ||
60 | struct dso *dso); | ||
61 | int (*export_branch_type)(struct db_export *dbe, u32 branch_type, | ||
62 | const char *name); | ||
63 | int (*export_sample)(struct db_export *dbe, struct export_sample *es); | ||
64 | int (*export_call_path)(struct db_export *dbe, struct call_path *cp); | ||
65 | int (*export_call_return)(struct db_export *dbe, | ||
66 | struct call_return *cr); | ||
67 | struct call_return_processor *crp; | ||
68 | u64 evsel_last_db_id; | ||
69 | u64 machine_last_db_id; | ||
70 | u64 thread_last_db_id; | ||
71 | u64 comm_last_db_id; | ||
72 | u64 comm_thread_last_db_id; | ||
73 | u64 dso_last_db_id; | ||
74 | u64 symbol_last_db_id; | ||
75 | u64 sample_last_db_id; | ||
76 | u64 call_path_last_db_id; | ||
77 | u64 call_return_last_db_id; | ||
78 | struct list_head deferred; | ||
79 | }; | ||
80 | |||
81 | int db_export__init(struct db_export *dbe); | ||
82 | int db_export__flush(struct db_export *dbe); | ||
83 | void db_export__exit(struct db_export *dbe); | ||
84 | int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel); | ||
85 | int db_export__machine(struct db_export *dbe, struct machine *machine); | ||
86 | int db_export__thread(struct db_export *dbe, struct thread *thread, | ||
87 | struct machine *machine, struct comm *comm); | ||
88 | int db_export__comm(struct db_export *dbe, struct comm *comm, | ||
89 | struct thread *main_thread); | ||
90 | int db_export__comm_thread(struct db_export *dbe, struct comm *comm, | ||
91 | struct thread *thread); | ||
92 | int db_export__dso(struct db_export *dbe, struct dso *dso, | ||
93 | struct machine *machine); | ||
94 | int db_export__symbol(struct db_export *dbe, struct symbol *sym, | ||
95 | struct dso *dso); | ||
96 | int db_export__branch_type(struct db_export *dbe, u32 branch_type, | ||
97 | const char *name); | ||
98 | int db_export__sample(struct db_export *dbe, union perf_event *event, | ||
99 | struct perf_sample *sample, struct perf_evsel *evsel, | ||
100 | struct thread *thread, struct addr_location *al); | ||
101 | |||
102 | int db_export__branch_types(struct db_export *dbe); | ||
103 | |||
104 | int db_export__call_path(struct db_export *dbe, struct call_path *cp); | ||
105 | int db_export__call_return(struct db_export *dbe, struct call_return *cr); | ||
106 | |||
107 | #endif | ||
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c index ba357f3226c6..ad60b2f20258 100644 --- a/tools/perf/util/debug.c +++ b/tools/perf/util/debug.c | |||
@@ -19,13 +19,14 @@ | |||
19 | int verbose; | 19 | int verbose; |
20 | bool dump_trace = false, quiet = false; | 20 | bool dump_trace = false, quiet = false; |
21 | int debug_ordered_events; | 21 | int debug_ordered_events; |
22 | static int redirect_to_stderr; | ||
22 | 23 | ||
23 | static int _eprintf(int level, int var, const char *fmt, va_list args) | 24 | static int _eprintf(int level, int var, const char *fmt, va_list args) |
24 | { | 25 | { |
25 | int ret = 0; | 26 | int ret = 0; |
26 | 27 | ||
27 | if (var >= level) { | 28 | if (var >= level) { |
28 | if (use_browser >= 1) | 29 | if (use_browser >= 1 && !redirect_to_stderr) |
29 | ui_helpline__vshow(fmt, args); | 30 | ui_helpline__vshow(fmt, args); |
30 | else | 31 | else |
31 | ret = vfprintf(stderr, fmt, args); | 32 | ret = vfprintf(stderr, fmt, args); |
@@ -145,6 +146,7 @@ static struct debug_variable { | |||
145 | } debug_variables[] = { | 146 | } debug_variables[] = { |
146 | { .name = "verbose", .ptr = &verbose }, | 147 | { .name = "verbose", .ptr = &verbose }, |
147 | { .name = "ordered-events", .ptr = &debug_ordered_events}, | 148 | { .name = "ordered-events", .ptr = &debug_ordered_events}, |
149 | { .name = "stderr", .ptr = &redirect_to_stderr}, | ||
148 | { .name = NULL, } | 150 | { .name = NULL, } |
149 | }; | 151 | }; |
150 | 152 | ||
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 0247acfdfaca..45be944d450a 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c | |||
@@ -21,8 +21,10 @@ char dso__symtab_origin(const struct dso *dso) | |||
21 | [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', | 21 | [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', |
22 | [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', | 22 | [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', |
23 | [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', | 23 | [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', |
24 | [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP] = 'm', | ||
24 | [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', | 25 | [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', |
25 | [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', | 26 | [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', |
27 | [DSO_BINARY_TYPE__GUEST_KMODULE_COMP] = 'M', | ||
26 | [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', | 28 | [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', |
27 | }; | 29 | }; |
28 | 30 | ||
@@ -112,11 +114,13 @@ int dso__read_binary_type_filename(const struct dso *dso, | |||
112 | break; | 114 | break; |
113 | 115 | ||
114 | case DSO_BINARY_TYPE__GUEST_KMODULE: | 116 | case DSO_BINARY_TYPE__GUEST_KMODULE: |
117 | case DSO_BINARY_TYPE__GUEST_KMODULE_COMP: | ||
115 | path__join3(filename, size, symbol_conf.symfs, | 118 | path__join3(filename, size, symbol_conf.symfs, |
116 | root_dir, dso->long_name); | 119 | root_dir, dso->long_name); |
117 | break; | 120 | break; |
118 | 121 | ||
119 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: | 122 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: |
123 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: | ||
120 | __symbol__join_symfs(filename, size, dso->long_name); | 124 | __symbol__join_symfs(filename, size, dso->long_name); |
121 | break; | 125 | break; |
122 | 126 | ||
@@ -137,6 +141,73 @@ int dso__read_binary_type_filename(const struct dso *dso, | |||
137 | return ret; | 141 | return ret; |
138 | } | 142 | } |
139 | 143 | ||
144 | static const struct { | ||
145 | const char *fmt; | ||
146 | int (*decompress)(const char *input, int output); | ||
147 | } compressions[] = { | ||
148 | #ifdef HAVE_ZLIB_SUPPORT | ||
149 | { "gz", gzip_decompress_to_file }, | ||
150 | #endif | ||
151 | { NULL, NULL }, | ||
152 | }; | ||
153 | |||
154 | bool is_supported_compression(const char *ext) | ||
155 | { | ||
156 | unsigned i; | ||
157 | |||
158 | for (i = 0; compressions[i].fmt; i++) { | ||
159 | if (!strcmp(ext, compressions[i].fmt)) | ||
160 | return true; | ||
161 | } | ||
162 | return false; | ||
163 | } | ||
164 | |||
165 | bool is_kmodule_extension(const char *ext) | ||
166 | { | ||
167 | if (strncmp(ext, "ko", 2)) | ||
168 | return false; | ||
169 | |||
170 | if (ext[2] == '\0' || (ext[2] == '.' && is_supported_compression(ext+3))) | ||
171 | return true; | ||
172 | |||
173 | return false; | ||
174 | } | ||
175 | |||
176 | bool is_kernel_module(const char *pathname, bool *compressed) | ||
177 | { | ||
178 | const char *ext = strrchr(pathname, '.'); | ||
179 | |||
180 | if (ext == NULL) | ||
181 | return false; | ||
182 | |||
183 | if (is_supported_compression(ext + 1)) { | ||
184 | if (compressed) | ||
185 | *compressed = true; | ||
186 | ext -= 3; | ||
187 | } else if (compressed) | ||
188 | *compressed = false; | ||
189 | |||
190 | return is_kmodule_extension(ext + 1); | ||
191 | } | ||
192 | |||
193 | bool decompress_to_file(const char *ext, const char *filename, int output_fd) | ||
194 | { | ||
195 | unsigned i; | ||
196 | |||
197 | for (i = 0; compressions[i].fmt; i++) { | ||
198 | if (!strcmp(ext, compressions[i].fmt)) | ||
199 | return !compressions[i].decompress(filename, | ||
200 | output_fd); | ||
201 | } | ||
202 | return false; | ||
203 | } | ||
204 | |||
205 | bool dso__needs_decompress(struct dso *dso) | ||
206 | { | ||
207 | return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || | ||
208 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; | ||
209 | } | ||
210 | |||
140 | /* | 211 | /* |
141 | * Global list of open DSOs and the counter. | 212 | * Global list of open DSOs and the counter. |
142 | */ | 213 | */ |
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index acb651acc7fd..3782c82c6e44 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h | |||
@@ -22,7 +22,9 @@ enum dso_binary_type { | |||
22 | DSO_BINARY_TYPE__BUILDID_DEBUGINFO, | 22 | DSO_BINARY_TYPE__BUILDID_DEBUGINFO, |
23 | DSO_BINARY_TYPE__SYSTEM_PATH_DSO, | 23 | DSO_BINARY_TYPE__SYSTEM_PATH_DSO, |
24 | DSO_BINARY_TYPE__GUEST_KMODULE, | 24 | DSO_BINARY_TYPE__GUEST_KMODULE, |
25 | DSO_BINARY_TYPE__GUEST_KMODULE_COMP, | ||
25 | DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, | 26 | DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, |
27 | DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP, | ||
26 | DSO_BINARY_TYPE__KCORE, | 28 | DSO_BINARY_TYPE__KCORE, |
27 | DSO_BINARY_TYPE__GUEST_KCORE, | 29 | DSO_BINARY_TYPE__GUEST_KCORE, |
28 | DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, | 30 | DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, |
@@ -127,6 +129,7 @@ struct dso { | |||
127 | const char *long_name; | 129 | const char *long_name; |
128 | u16 long_name_len; | 130 | u16 long_name_len; |
129 | u16 short_name_len; | 131 | u16 short_name_len; |
132 | void *dwfl; /* DWARF debug info */ | ||
130 | 133 | ||
131 | /* dso data file */ | 134 | /* dso data file */ |
132 | struct { | 135 | struct { |
@@ -138,6 +141,11 @@ struct dso { | |||
138 | struct list_head open_entry; | 141 | struct list_head open_entry; |
139 | } data; | 142 | } data; |
140 | 143 | ||
144 | union { /* Tool specific area */ | ||
145 | void *priv; | ||
146 | u64 db_id; | ||
147 | }; | ||
148 | |||
141 | char name[0]; | 149 | char name[0]; |
142 | }; | 150 | }; |
143 | 151 | ||
@@ -179,6 +187,11 @@ int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir); | |||
179 | char dso__symtab_origin(const struct dso *dso); | 187 | char dso__symtab_origin(const struct dso *dso); |
180 | int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, | 188 | int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, |
181 | char *root_dir, char *filename, size_t size); | 189 | char *root_dir, char *filename, size_t size); |
190 | bool is_supported_compression(const char *ext); | ||
191 | bool is_kmodule_extension(const char *ext); | ||
192 | bool is_kernel_module(const char *pathname, bool *compressed); | ||
193 | bool decompress_to_file(const char *ext, const char *filename, int output_fd); | ||
194 | bool dso__needs_decompress(struct dso *dso); | ||
182 | 195 | ||
183 | /* | 196 | /* |
184 | * The dso__data_* external interface provides following functions: | 197 | * The dso__data_* external interface provides following functions: |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 4af6b279e34a..6c6d044e959a 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -28,6 +28,7 @@ static const char *perf_event__names[] = { | |||
28 | [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", | 28 | [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", |
29 | [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", | 29 | [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", |
30 | [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", | 30 | [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", |
31 | [PERF_RECORD_ID_INDEX] = "ID_INDEX", | ||
31 | }; | 32 | }; |
32 | 33 | ||
33 | const char *perf_event__name(unsigned int id) | 34 | const char *perf_event__name(unsigned int id) |
@@ -730,12 +731,12 @@ int perf_event__process(struct perf_tool *tool __maybe_unused, | |||
730 | return machine__process_event(machine, event, sample); | 731 | return machine__process_event(machine, event, sample); |
731 | } | 732 | } |
732 | 733 | ||
733 | void thread__find_addr_map(struct thread *thread, | 734 | void thread__find_addr_map(struct thread *thread, u8 cpumode, |
734 | struct machine *machine, u8 cpumode, | ||
735 | enum map_type type, u64 addr, | 735 | enum map_type type, u64 addr, |
736 | struct addr_location *al) | 736 | struct addr_location *al) |
737 | { | 737 | { |
738 | struct map_groups *mg = thread->mg; | 738 | struct map_groups *mg = thread->mg; |
739 | struct machine *machine = mg->machine; | ||
739 | bool load_map = false; | 740 | bool load_map = false; |
740 | 741 | ||
741 | al->machine = machine; | 742 | al->machine = machine; |
@@ -806,14 +807,14 @@ try_again: | |||
806 | } | 807 | } |
807 | } | 808 | } |
808 | 809 | ||
809 | void thread__find_addr_location(struct thread *thread, struct machine *machine, | 810 | void thread__find_addr_location(struct thread *thread, |
810 | u8 cpumode, enum map_type type, u64 addr, | 811 | u8 cpumode, enum map_type type, u64 addr, |
811 | struct addr_location *al) | 812 | struct addr_location *al) |
812 | { | 813 | { |
813 | thread__find_addr_map(thread, machine, cpumode, type, addr, al); | 814 | thread__find_addr_map(thread, cpumode, type, addr, al); |
814 | if (al->map != NULL) | 815 | if (al->map != NULL) |
815 | al->sym = map__find_symbol(al->map, al->addr, | 816 | al->sym = map__find_symbol(al->map, al->addr, |
816 | machine->symbol_filter); | 817 | thread->mg->machine->symbol_filter); |
817 | else | 818 | else |
818 | al->sym = NULL; | 819 | al->sym = NULL; |
819 | } | 820 | } |
@@ -842,8 +843,7 @@ int perf_event__preprocess_sample(const union perf_event *event, | |||
842 | machine->vmlinux_maps[MAP__FUNCTION] == NULL) | 843 | machine->vmlinux_maps[MAP__FUNCTION] == NULL) |
843 | machine__create_kernel_maps(machine); | 844 | machine__create_kernel_maps(machine); |
844 | 845 | ||
845 | thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, | 846 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al); |
846 | sample->ip, al); | ||
847 | dump_printf(" ...... dso: %s\n", | 847 | dump_printf(" ...... dso: %s\n", |
848 | al->map ? al->map->dso->long_name : | 848 | al->map ? al->map->dso->long_name : |
849 | al->level == 'H' ? "[hypervisor]" : "<not found>"); | 849 | al->level == 'H' ? "[hypervisor]" : "<not found>"); |
@@ -902,16 +902,14 @@ bool sample_addr_correlates_sym(struct perf_event_attr *attr) | |||
902 | 902 | ||
903 | void perf_event__preprocess_sample_addr(union perf_event *event, | 903 | void perf_event__preprocess_sample_addr(union perf_event *event, |
904 | struct perf_sample *sample, | 904 | struct perf_sample *sample, |
905 | struct machine *machine, | ||
906 | struct thread *thread, | 905 | struct thread *thread, |
907 | struct addr_location *al) | 906 | struct addr_location *al) |
908 | { | 907 | { |
909 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 908 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
910 | 909 | ||
911 | thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, | 910 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->addr, al); |
912 | sample->addr, al); | ||
913 | if (!al->map) | 911 | if (!al->map) |
914 | thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE, | 912 | thread__find_addr_map(thread, cpumode, MAP__VARIABLE, |
915 | sample->addr, al); | 913 | sample->addr, al); |
916 | 914 | ||
917 | al->cpu = sample->cpu; | 915 | al->cpu = sample->cpu; |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 5699e7e2a790..c4ffe2bd0738 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -143,6 +143,32 @@ struct branch_stack { | |||
143 | struct branch_entry entries[0]; | 143 | struct branch_entry entries[0]; |
144 | }; | 144 | }; |
145 | 145 | ||
146 | enum { | ||
147 | PERF_IP_FLAG_BRANCH = 1ULL << 0, | ||
148 | PERF_IP_FLAG_CALL = 1ULL << 1, | ||
149 | PERF_IP_FLAG_RETURN = 1ULL << 2, | ||
150 | PERF_IP_FLAG_CONDITIONAL = 1ULL << 3, | ||
151 | PERF_IP_FLAG_SYSCALLRET = 1ULL << 4, | ||
152 | PERF_IP_FLAG_ASYNC = 1ULL << 5, | ||
153 | PERF_IP_FLAG_INTERRUPT = 1ULL << 6, | ||
154 | PERF_IP_FLAG_TX_ABORT = 1ULL << 7, | ||
155 | PERF_IP_FLAG_TRACE_BEGIN = 1ULL << 8, | ||
156 | PERF_IP_FLAG_TRACE_END = 1ULL << 9, | ||
157 | PERF_IP_FLAG_IN_TX = 1ULL << 10, | ||
158 | }; | ||
159 | |||
160 | #define PERF_BRANCH_MASK (\ | ||
161 | PERF_IP_FLAG_BRANCH |\ | ||
162 | PERF_IP_FLAG_CALL |\ | ||
163 | PERF_IP_FLAG_RETURN |\ | ||
164 | PERF_IP_FLAG_CONDITIONAL |\ | ||
165 | PERF_IP_FLAG_SYSCALLRET |\ | ||
166 | PERF_IP_FLAG_ASYNC |\ | ||
167 | PERF_IP_FLAG_INTERRUPT |\ | ||
168 | PERF_IP_FLAG_TX_ABORT |\ | ||
169 | PERF_IP_FLAG_TRACE_BEGIN |\ | ||
170 | PERF_IP_FLAG_TRACE_END) | ||
171 | |||
146 | struct perf_sample { | 172 | struct perf_sample { |
147 | u64 ip; | 173 | u64 ip; |
148 | u32 pid, tid; | 174 | u32 pid, tid; |
@@ -162,6 +188,7 @@ struct perf_sample { | |||
162 | struct ip_callchain *callchain; | 188 | struct ip_callchain *callchain; |
163 | struct branch_stack *branch_stack; | 189 | struct branch_stack *branch_stack; |
164 | struct regs_dump user_regs; | 190 | struct regs_dump user_regs; |
191 | struct regs_dump intr_regs; | ||
165 | struct stack_dump user_stack; | 192 | struct stack_dump user_stack; |
166 | struct sample_read read; | 193 | struct sample_read read; |
167 | }; | 194 | }; |
@@ -187,6 +214,7 @@ enum perf_user_event_type { /* above any possible kernel type */ | |||
187 | PERF_RECORD_HEADER_TRACING_DATA = 66, | 214 | PERF_RECORD_HEADER_TRACING_DATA = 66, |
188 | PERF_RECORD_HEADER_BUILD_ID = 67, | 215 | PERF_RECORD_HEADER_BUILD_ID = 67, |
189 | PERF_RECORD_FINISHED_ROUND = 68, | 216 | PERF_RECORD_FINISHED_ROUND = 68, |
217 | PERF_RECORD_ID_INDEX = 69, | ||
190 | PERF_RECORD_HEADER_MAX | 218 | PERF_RECORD_HEADER_MAX |
191 | }; | 219 | }; |
192 | 220 | ||
@@ -214,6 +242,7 @@ struct events_stats { | |||
214 | u32 nr_invalid_chains; | 242 | u32 nr_invalid_chains; |
215 | u32 nr_unknown_id; | 243 | u32 nr_unknown_id; |
216 | u32 nr_unprocessable_samples; | 244 | u32 nr_unprocessable_samples; |
245 | u32 nr_unordered_events; | ||
217 | }; | 246 | }; |
218 | 247 | ||
219 | struct attr_event { | 248 | struct attr_event { |
@@ -239,6 +268,19 @@ struct tracing_data_event { | |||
239 | u32 size; | 268 | u32 size; |
240 | }; | 269 | }; |
241 | 270 | ||
271 | struct id_index_entry { | ||
272 | u64 id; | ||
273 | u64 idx; | ||
274 | u64 cpu; | ||
275 | u64 tid; | ||
276 | }; | ||
277 | |||
278 | struct id_index_event { | ||
279 | struct perf_event_header header; | ||
280 | u64 nr; | ||
281 | struct id_index_entry entries[0]; | ||
282 | }; | ||
283 | |||
242 | union perf_event { | 284 | union perf_event { |
243 | struct perf_event_header header; | 285 | struct perf_event_header header; |
244 | struct mmap_event mmap; | 286 | struct mmap_event mmap; |
@@ -253,6 +295,7 @@ union perf_event { | |||
253 | struct event_type_event event_type; | 295 | struct event_type_event event_type; |
254 | struct tracing_data_event tracing_data; | 296 | struct tracing_data_event tracing_data; |
255 | struct build_id_event build_id; | 297 | struct build_id_event build_id; |
298 | struct id_index_event id_index; | ||
256 | }; | 299 | }; |
257 | 300 | ||
258 | void perf_event__print_totals(void); | 301 | void perf_event__print_totals(void); |
@@ -322,7 +365,6 @@ bool is_bts_event(struct perf_event_attr *attr); | |||
322 | bool sample_addr_correlates_sym(struct perf_event_attr *attr); | 365 | bool sample_addr_correlates_sym(struct perf_event_attr *attr); |
323 | void perf_event__preprocess_sample_addr(union perf_event *event, | 366 | void perf_event__preprocess_sample_addr(union perf_event *event, |
324 | struct perf_sample *sample, | 367 | struct perf_sample *sample, |
325 | struct machine *machine, | ||
326 | struct thread *thread, | 368 | struct thread *thread, |
327 | struct addr_location *al); | 369 | struct addr_location *al); |
328 | 370 | ||
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 3c9e77d6b4c2..cbab1fb77b1d 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -8,6 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | #include "util.h" | 9 | #include "util.h" |
10 | #include <api/fs/debugfs.h> | 10 | #include <api/fs/debugfs.h> |
11 | #include <api/fs/fs.h> | ||
11 | #include <poll.h> | 12 | #include <poll.h> |
12 | #include "cpumap.h" | 13 | #include "cpumap.h" |
13 | #include "thread_map.h" | 14 | #include "thread_map.h" |
@@ -24,6 +25,7 @@ | |||
24 | 25 | ||
25 | #include <linux/bitops.h> | 26 | #include <linux/bitops.h> |
26 | #include <linux/hash.h> | 27 | #include <linux/hash.h> |
28 | #include <linux/log2.h> | ||
27 | 29 | ||
28 | static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx); | 30 | static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx); |
29 | static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx); | 31 | static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx); |
@@ -413,7 +415,7 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) | |||
413 | int nfds = 0; | 415 | int nfds = 0; |
414 | struct perf_evsel *evsel; | 416 | struct perf_evsel *evsel; |
415 | 417 | ||
416 | list_for_each_entry(evsel, &evlist->entries, node) { | 418 | evlist__for_each(evlist, evsel) { |
417 | if (evsel->system_wide) | 419 | if (evsel->system_wide) |
418 | nfds += nr_cpus; | 420 | nfds += nr_cpus; |
419 | else | 421 | else |
@@ -527,6 +529,22 @@ static int perf_evlist__id_add_fd(struct perf_evlist *evlist, | |||
527 | return 0; | 529 | return 0; |
528 | } | 530 | } |
529 | 531 | ||
532 | static void perf_evlist__set_sid_idx(struct perf_evlist *evlist, | ||
533 | struct perf_evsel *evsel, int idx, int cpu, | ||
534 | int thread) | ||
535 | { | ||
536 | struct perf_sample_id *sid = SID(evsel, cpu, thread); | ||
537 | sid->idx = idx; | ||
538 | if (evlist->cpus && cpu >= 0) | ||
539 | sid->cpu = evlist->cpus->map[cpu]; | ||
540 | else | ||
541 | sid->cpu = -1; | ||
542 | if (!evsel->system_wide && evlist->threads && thread >= 0) | ||
543 | sid->tid = evlist->threads->map[thread]; | ||
544 | else | ||
545 | sid->tid = -1; | ||
546 | } | ||
547 | |||
530 | struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) | 548 | struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) |
531 | { | 549 | { |
532 | struct hlist_head *head; | 550 | struct hlist_head *head; |
@@ -800,14 +818,26 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, | |||
800 | perf_evlist__mmap_get(evlist, idx); | 818 | perf_evlist__mmap_get(evlist, idx); |
801 | } | 819 | } |
802 | 820 | ||
803 | if (__perf_evlist__add_pollfd(evlist, fd, idx) < 0) { | 821 | /* |
822 | * The system_wide flag causes a selected event to be opened | ||
823 | * always without a pid. Consequently it will never get a | ||
824 | * POLLHUP, but it is used for tracking in combination with | ||
825 | * other events, so it should not need to be polled anyway. | ||
826 | * Therefore don't add it for polling. | ||
827 | */ | ||
828 | if (!evsel->system_wide && | ||
829 | __perf_evlist__add_pollfd(evlist, fd, idx) < 0) { | ||
804 | perf_evlist__mmap_put(evlist, idx); | 830 | perf_evlist__mmap_put(evlist, idx); |
805 | return -1; | 831 | return -1; |
806 | } | 832 | } |
807 | 833 | ||
808 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && | 834 | if (evsel->attr.read_format & PERF_FORMAT_ID) { |
809 | perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) | 835 | if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread, |
810 | return -1; | 836 | fd) < 0) |
837 | return -1; | ||
838 | perf_evlist__set_sid_idx(evlist, evsel, idx, cpu, | ||
839 | thread); | ||
840 | } | ||
811 | } | 841 | } |
812 | 842 | ||
813 | return 0; | 843 | return 0; |
@@ -864,10 +894,24 @@ out_unmap: | |||
864 | 894 | ||
865 | static size_t perf_evlist__mmap_size(unsigned long pages) | 895 | static size_t perf_evlist__mmap_size(unsigned long pages) |
866 | { | 896 | { |
867 | /* 512 kiB: default amount of unprivileged mlocked memory */ | 897 | if (pages == UINT_MAX) { |
868 | if (pages == UINT_MAX) | 898 | int max; |
869 | pages = (512 * 1024) / page_size; | 899 | |
870 | else if (!is_power_of_2(pages)) | 900 | if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) { |
901 | /* | ||
902 | * Pick a once upon a time good value, i.e. things look | ||
903 | * strange since we can't read a sysctl value, but lets not | ||
904 | * die yet... | ||
905 | */ | ||
906 | max = 512; | ||
907 | } else { | ||
908 | max -= (page_size / 1024); | ||
909 | } | ||
910 | |||
911 | pages = (max * 1024) / page_size; | ||
912 | if (!is_power_of_2(pages)) | ||
913 | pages = rounddown_pow_of_two(pages); | ||
914 | } else if (!is_power_of_2(pages)) | ||
871 | return 0; | 915 | return 0; |
872 | 916 | ||
873 | return (pages + 1) * page_size; | 917 | return (pages + 1) * page_size; |
@@ -904,7 +948,7 @@ static long parse_pages_arg(const char *str, unsigned long min, | |||
904 | /* leave number of pages at 0 */ | 948 | /* leave number of pages at 0 */ |
905 | } else if (!is_power_of_2(pages)) { | 949 | } else if (!is_power_of_2(pages)) { |
906 | /* round pages up to next power of 2 */ | 950 | /* round pages up to next power of 2 */ |
907 | pages = next_pow2_l(pages); | 951 | pages = roundup_pow_of_two(pages); |
908 | if (!pages) | 952 | if (!pages) |
909 | return -EINVAL; | 953 | return -EINVAL; |
910 | pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", | 954 | pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", |
@@ -1455,6 +1499,37 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused, | |||
1455 | return 0; | 1499 | return 0; |
1456 | } | 1500 | } |
1457 | 1501 | ||
1502 | int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size) | ||
1503 | { | ||
1504 | char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); | ||
1505 | int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0; | ||
1506 | |||
1507 | switch (err) { | ||
1508 | case EPERM: | ||
1509 | sysctl__read_int("kernel/perf_event_mlock_kb", &pages_max_per_user); | ||
1510 | printed += scnprintf(buf + printed, size - printed, | ||
1511 | "Error:\t%s.\n" | ||
1512 | "Hint:\tCheck /proc/sys/kernel/perf_event_mlock_kb (%d kB) setting.\n" | ||
1513 | "Hint:\tTried using %zd kB.\n", | ||
1514 | emsg, pages_max_per_user, pages_attempted); | ||
1515 | |||
1516 | if (pages_attempted >= pages_max_per_user) { | ||
1517 | printed += scnprintf(buf + printed, size - printed, | ||
1518 | "Hint:\tTry 'sudo sh -c \"echo %d > /proc/sys/kernel/perf_event_mlock_kb\"', or\n", | ||
1519 | pages_max_per_user + pages_attempted); | ||
1520 | } | ||
1521 | |||
1522 | printed += scnprintf(buf + printed, size - printed, | ||
1523 | "Hint:\tTry using a smaller -m/--mmap-pages value."); | ||
1524 | break; | ||
1525 | default: | ||
1526 | scnprintf(buf, size, "%s", emsg); | ||
1527 | break; | ||
1528 | } | ||
1529 | |||
1530 | return 0; | ||
1531 | } | ||
1532 | |||
1458 | void perf_evlist__to_front(struct perf_evlist *evlist, | 1533 | void perf_evlist__to_front(struct perf_evlist *evlist, |
1459 | struct perf_evsel *move_evsel) | 1534 | struct perf_evsel *move_evsel) |
1460 | { | 1535 | { |
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 649b0c597283..0ba93f67ab94 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
@@ -185,6 +185,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp); | |||
185 | 185 | ||
186 | int perf_evlist__strerror_tp(struct perf_evlist *evlist, int err, char *buf, size_t size); | 186 | int perf_evlist__strerror_tp(struct perf_evlist *evlist, int err, char *buf, size_t size); |
187 | int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size); | 187 | int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size); |
188 | int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size); | ||
188 | 189 | ||
189 | static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm) | 190 | static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm) |
190 | { | 191 | { |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 2f9e68025ede..1e90c8557ede 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -658,9 +658,22 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) | |||
658 | attr->mmap_data = track; | 658 | attr->mmap_data = track; |
659 | } | 659 | } |
660 | 660 | ||
661 | /* | ||
662 | * We don't allow user space callchains for function trace | ||
663 | * event, due to issues with page faults while tracing page | ||
664 | * fault handler and its overall trickiness nature. | ||
665 | */ | ||
666 | if (perf_evsel__is_function_event(evsel)) | ||
667 | evsel->attr.exclude_callchain_user = 1; | ||
668 | |||
661 | if (callchain_param.enabled && !evsel->no_aux_samples) | 669 | if (callchain_param.enabled && !evsel->no_aux_samples) |
662 | perf_evsel__config_callgraph(evsel); | 670 | perf_evsel__config_callgraph(evsel); |
663 | 671 | ||
672 | if (opts->sample_intr_regs) { | ||
673 | attr->sample_regs_intr = PERF_REGS_MASK; | ||
674 | perf_evsel__set_sample_bit(evsel, REGS_INTR); | ||
675 | } | ||
676 | |||
664 | if (target__has_cpu(&opts->target)) | 677 | if (target__has_cpu(&opts->target)) |
665 | perf_evsel__set_sample_bit(evsel, CPU); | 678 | perf_evsel__set_sample_bit(evsel, CPU); |
666 | 679 | ||
@@ -853,8 +866,6 @@ void perf_evsel__exit(struct perf_evsel *evsel) | |||
853 | perf_evsel__free_id(evsel); | 866 | perf_evsel__free_id(evsel); |
854 | close_cgroup(evsel->cgrp); | 867 | close_cgroup(evsel->cgrp); |
855 | zfree(&evsel->group_name); | 868 | zfree(&evsel->group_name); |
856 | if (evsel->tp_format) | ||
857 | pevent_free_format(evsel->tp_format); | ||
858 | zfree(&evsel->name); | 869 | zfree(&evsel->name); |
859 | perf_evsel__object.fini(evsel); | 870 | perf_evsel__object.fini(evsel); |
860 | } | 871 | } |
@@ -865,9 +876,8 @@ void perf_evsel__delete(struct perf_evsel *evsel) | |||
865 | free(evsel); | 876 | free(evsel); |
866 | } | 877 | } |
867 | 878 | ||
868 | static inline void compute_deltas(struct perf_evsel *evsel, | 879 | void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, |
869 | int cpu, | 880 | struct perf_counts_values *count) |
870 | struct perf_counts_values *count) | ||
871 | { | 881 | { |
872 | struct perf_counts_values tmp; | 882 | struct perf_counts_values tmp; |
873 | 883 | ||
@@ -887,81 +897,60 @@ static inline void compute_deltas(struct perf_evsel *evsel, | |||
887 | count->run = count->run - tmp.run; | 897 | count->run = count->run - tmp.run; |
888 | } | 898 | } |
889 | 899 | ||
890 | int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, | 900 | void perf_counts_values__scale(struct perf_counts_values *count, |
891 | int cpu, int thread, bool scale) | 901 | bool scale, s8 *pscaled) |
892 | { | 902 | { |
893 | struct perf_counts_values count; | 903 | s8 scaled = 0; |
894 | size_t nv = scale ? 3 : 1; | ||
895 | |||
896 | if (FD(evsel, cpu, thread) < 0) | ||
897 | return -EINVAL; | ||
898 | |||
899 | if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0) | ||
900 | return -ENOMEM; | ||
901 | |||
902 | if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0) | ||
903 | return -errno; | ||
904 | |||
905 | compute_deltas(evsel, cpu, &count); | ||
906 | 904 | ||
907 | if (scale) { | 905 | if (scale) { |
908 | if (count.run == 0) | 906 | if (count->run == 0) { |
909 | count.val = 0; | 907 | scaled = -1; |
910 | else if (count.run < count.ena) | 908 | count->val = 0; |
911 | count.val = (u64)((double)count.val * count.ena / count.run + 0.5); | 909 | } else if (count->run < count->ena) { |
910 | scaled = 1; | ||
911 | count->val = (u64)((double) count->val * count->ena / count->run + 0.5); | ||
912 | } | ||
912 | } else | 913 | } else |
913 | count.ena = count.run = 0; | 914 | count->ena = count->run = 0; |
914 | 915 | ||
915 | evsel->counts->cpu[cpu] = count; | 916 | if (pscaled) |
916 | return 0; | 917 | *pscaled = scaled; |
917 | } | 918 | } |
918 | 919 | ||
919 | int __perf_evsel__read(struct perf_evsel *evsel, | 920 | int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread, |
920 | int ncpus, int nthreads, bool scale) | 921 | perf_evsel__read_cb_t cb) |
921 | { | 922 | { |
922 | size_t nv = scale ? 3 : 1; | 923 | struct perf_counts_values count; |
923 | int cpu, thread; | ||
924 | struct perf_counts_values *aggr = &evsel->counts->aggr, count; | ||
925 | 924 | ||
926 | if (evsel->system_wide) | 925 | memset(&count, 0, sizeof(count)); |
927 | nthreads = 1; | ||
928 | 926 | ||
929 | aggr->val = aggr->ena = aggr->run = 0; | 927 | if (FD(evsel, cpu, thread) < 0) |
928 | return -EINVAL; | ||
930 | 929 | ||
931 | for (cpu = 0; cpu < ncpus; cpu++) { | 930 | if (readn(FD(evsel, cpu, thread), &count, sizeof(count)) < 0) |
932 | for (thread = 0; thread < nthreads; thread++) { | 931 | return -errno; |
933 | if (FD(evsel, cpu, thread) < 0) | ||
934 | continue; | ||
935 | 932 | ||
936 | if (readn(FD(evsel, cpu, thread), | 933 | return cb(evsel, cpu, thread, &count); |
937 | &count, nv * sizeof(u64)) < 0) | 934 | } |
938 | return -errno; | ||
939 | 935 | ||
940 | aggr->val += count.val; | 936 | int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, |
941 | if (scale) { | 937 | int cpu, int thread, bool scale) |
942 | aggr->ena += count.ena; | 938 | { |
943 | aggr->run += count.run; | 939 | struct perf_counts_values count; |
944 | } | 940 | size_t nv = scale ? 3 : 1; |
945 | } | ||
946 | } | ||
947 | 941 | ||
948 | compute_deltas(evsel, -1, aggr); | 942 | if (FD(evsel, cpu, thread) < 0) |
943 | return -EINVAL; | ||
949 | 944 | ||
950 | evsel->counts->scaled = 0; | 945 | if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0) |
951 | if (scale) { | 946 | return -ENOMEM; |
952 | if (aggr->run == 0) { | ||
953 | evsel->counts->scaled = -1; | ||
954 | aggr->val = 0; | ||
955 | return 0; | ||
956 | } | ||
957 | 947 | ||
958 | if (aggr->run < aggr->ena) { | 948 | if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0) |
959 | evsel->counts->scaled = 1; | 949 | return -errno; |
960 | aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5); | ||
961 | } | ||
962 | } else | ||
963 | aggr->ena = aggr->run = 0; | ||
964 | 950 | ||
951 | perf_evsel__compute_deltas(evsel, cpu, &count); | ||
952 | perf_counts_values__scale(&count, scale, NULL); | ||
953 | evsel->counts->cpu[cpu] = count; | ||
965 | return 0; | 954 | return 0; |
966 | } | 955 | } |
967 | 956 | ||
@@ -1039,6 +1028,7 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp) | |||
1039 | ret += PRINT_ATTR_X64(branch_sample_type); | 1028 | ret += PRINT_ATTR_X64(branch_sample_type); |
1040 | ret += PRINT_ATTR_X64(sample_regs_user); | 1029 | ret += PRINT_ATTR_X64(sample_regs_user); |
1041 | ret += PRINT_ATTR_U32(sample_stack_user); | 1030 | ret += PRINT_ATTR_U32(sample_stack_user); |
1031 | ret += PRINT_ATTR_X64(sample_regs_intr); | ||
1042 | 1032 | ||
1043 | ret += fprintf(fp, "%.60s\n", graph_dotted_line); | 1033 | ret += fprintf(fp, "%.60s\n", graph_dotted_line); |
1044 | 1034 | ||
@@ -1538,6 +1528,23 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, | |||
1538 | array++; | 1528 | array++; |
1539 | } | 1529 | } |
1540 | 1530 | ||
1531 | data->intr_regs.abi = PERF_SAMPLE_REGS_ABI_NONE; | ||
1532 | if (type & PERF_SAMPLE_REGS_INTR) { | ||
1533 | OVERFLOW_CHECK_u64(array); | ||
1534 | data->intr_regs.abi = *array; | ||
1535 | array++; | ||
1536 | |||
1537 | if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) { | ||
1538 | u64 mask = evsel->attr.sample_regs_intr; | ||
1539 | |||
1540 | sz = hweight_long(mask) * sizeof(u64); | ||
1541 | OVERFLOW_CHECK(array, sz, max_size); | ||
1542 | data->intr_regs.mask = mask; | ||
1543 | data->intr_regs.regs = (u64 *)array; | ||
1544 | array = (void *)array + sz; | ||
1545 | } | ||
1546 | } | ||
1547 | |||
1541 | return 0; | 1548 | return 0; |
1542 | } | 1549 | } |
1543 | 1550 | ||
@@ -1633,6 +1640,16 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, | |||
1633 | if (type & PERF_SAMPLE_TRANSACTION) | 1640 | if (type & PERF_SAMPLE_TRANSACTION) |
1634 | result += sizeof(u64); | 1641 | result += sizeof(u64); |
1635 | 1642 | ||
1643 | if (type & PERF_SAMPLE_REGS_INTR) { | ||
1644 | if (sample->intr_regs.abi) { | ||
1645 | result += sizeof(u64); | ||
1646 | sz = hweight_long(sample->intr_regs.mask) * sizeof(u64); | ||
1647 | result += sz; | ||
1648 | } else { | ||
1649 | result += sizeof(u64); | ||
1650 | } | ||
1651 | } | ||
1652 | |||
1636 | return result; | 1653 | return result; |
1637 | } | 1654 | } |
1638 | 1655 | ||
@@ -1811,6 +1828,17 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, | |||
1811 | array++; | 1828 | array++; |
1812 | } | 1829 | } |
1813 | 1830 | ||
1831 | if (type & PERF_SAMPLE_REGS_INTR) { | ||
1832 | if (sample->intr_regs.abi) { | ||
1833 | *array++ = sample->intr_regs.abi; | ||
1834 | sz = hweight_long(sample->intr_regs.mask) * sizeof(u64); | ||
1835 | memcpy(array, sample->intr_regs.regs, sz); | ||
1836 | array = (void *)array + sz; | ||
1837 | } else { | ||
1838 | *array++ = 0; | ||
1839 | } | ||
1840 | } | ||
1841 | |||
1814 | return 0; | 1842 | return 0; |
1815 | } | 1843 | } |
1816 | 1844 | ||
@@ -1940,7 +1968,7 @@ static int sample_type__fprintf(FILE *fp, bool *first, u64 value) | |||
1940 | bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), | 1968 | bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), |
1941 | bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), | 1969 | bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), |
1942 | bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), | 1970 | bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), |
1943 | bit_name(IDENTIFIER), | 1971 | bit_name(IDENTIFIER), bit_name(REGS_INTR), |
1944 | { .name = NULL, } | 1972 | { .name = NULL, } |
1945 | }; | 1973 | }; |
1946 | #undef bit_name | 1974 | #undef bit_name |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 163c5604e5d1..38622747d130 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -36,6 +36,9 @@ struct perf_sample_id { | |||
36 | struct hlist_node node; | 36 | struct hlist_node node; |
37 | u64 id; | 37 | u64 id; |
38 | struct perf_evsel *evsel; | 38 | struct perf_evsel *evsel; |
39 | int idx; | ||
40 | int cpu; | ||
41 | pid_t tid; | ||
39 | 42 | ||
40 | /* Holds total ID period value for PERF_SAMPLE_READ processing. */ | 43 | /* Holds total ID period value for PERF_SAMPLE_READ processing. */ |
41 | u64 period; | 44 | u64 period; |
@@ -54,6 +57,7 @@ struct cgroup_sel; | |||
54 | * @is_pos: the position (counting backwards) of the event id (PERF_SAMPLE_ID or | 57 | * @is_pos: the position (counting backwards) of the event id (PERF_SAMPLE_ID or |
55 | * PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if sample_id_all | 58 | * PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if sample_id_all |
56 | * is used there is an id sample appended to non-sample events | 59 | * is used there is an id sample appended to non-sample events |
60 | * @priv: And what is in its containing unnamed union are tool specific | ||
57 | */ | 61 | */ |
58 | struct perf_evsel { | 62 | struct perf_evsel { |
59 | struct list_head node; | 63 | struct list_head node; |
@@ -69,10 +73,12 @@ struct perf_evsel { | |||
69 | char *name; | 73 | char *name; |
70 | double scale; | 74 | double scale; |
71 | const char *unit; | 75 | const char *unit; |
76 | bool snapshot; | ||
72 | struct event_format *tp_format; | 77 | struct event_format *tp_format; |
73 | union { | 78 | union { |
74 | void *priv; | 79 | void *priv; |
75 | off_t id_offset; | 80 | off_t id_offset; |
81 | u64 db_id; | ||
76 | }; | 82 | }; |
77 | struct cgroup_sel *cgrp; | 83 | struct cgroup_sel *cgrp; |
78 | void *handler; | 84 | void *handler; |
@@ -86,6 +92,8 @@ struct perf_evsel { | |||
86 | bool immediate; | 92 | bool immediate; |
87 | bool system_wide; | 93 | bool system_wide; |
88 | bool tracking; | 94 | bool tracking; |
95 | bool per_pkg; | ||
96 | unsigned long *per_pkg_mask; | ||
89 | /* parse modifier helper */ | 97 | /* parse modifier helper */ |
90 | int exclude_GH; | 98 | int exclude_GH; |
91 | int nr_members; | 99 | int nr_members; |
@@ -105,6 +113,12 @@ struct thread_map; | |||
105 | struct perf_evlist; | 113 | struct perf_evlist; |
106 | struct record_opts; | 114 | struct record_opts; |
107 | 115 | ||
116 | void perf_counts_values__scale(struct perf_counts_values *count, | ||
117 | bool scale, s8 *pscaled); | ||
118 | |||
119 | void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, | ||
120 | struct perf_counts_values *count); | ||
121 | |||
108 | int perf_evsel__object_config(size_t object_size, | 122 | int perf_evsel__object_config(size_t object_size, |
109 | int (*init)(struct perf_evsel *evsel), | 123 | int (*init)(struct perf_evsel *evsel), |
110 | void (*fini)(struct perf_evsel *evsel)); | 124 | void (*fini)(struct perf_evsel *evsel)); |
@@ -222,6 +236,13 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1, | |||
222 | (a)->attr.type == (b)->attr.type && \ | 236 | (a)->attr.type == (b)->attr.type && \ |
223 | (a)->attr.config == (b)->attr.config) | 237 | (a)->attr.config == (b)->attr.config) |
224 | 238 | ||
239 | typedef int (perf_evsel__read_cb_t)(struct perf_evsel *evsel, | ||
240 | int cpu, int thread, | ||
241 | struct perf_counts_values *count); | ||
242 | |||
243 | int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread, | ||
244 | perf_evsel__read_cb_t cb); | ||
245 | |||
225 | int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, | 246 | int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, |
226 | int cpu, int thread, bool scale); | 247 | int cpu, int thread, bool scale); |
227 | 248 | ||
@@ -251,35 +272,6 @@ static inline int perf_evsel__read_on_cpu_scaled(struct perf_evsel *evsel, | |||
251 | return __perf_evsel__read_on_cpu(evsel, cpu, thread, true); | 272 | return __perf_evsel__read_on_cpu(evsel, cpu, thread, true); |
252 | } | 273 | } |
253 | 274 | ||
254 | int __perf_evsel__read(struct perf_evsel *evsel, int ncpus, int nthreads, | ||
255 | bool scale); | ||
256 | |||
257 | /** | ||
258 | * perf_evsel__read - Read the aggregate results on all CPUs | ||
259 | * | ||
260 | * @evsel - event selector to read value | ||
261 | * @ncpus - Number of cpus affected, from zero | ||
262 | * @nthreads - Number of threads affected, from zero | ||
263 | */ | ||
264 | static inline int perf_evsel__read(struct perf_evsel *evsel, | ||
265 | int ncpus, int nthreads) | ||
266 | { | ||
267 | return __perf_evsel__read(evsel, ncpus, nthreads, false); | ||
268 | } | ||
269 | |||
270 | /** | ||
271 | * perf_evsel__read_scaled - Read the aggregate results on all CPUs, scaled | ||
272 | * | ||
273 | * @evsel - event selector to read value | ||
274 | * @ncpus - Number of cpus affected, from zero | ||
275 | * @nthreads - Number of threads affected, from zero | ||
276 | */ | ||
277 | static inline int perf_evsel__read_scaled(struct perf_evsel *evsel, | ||
278 | int ncpus, int nthreads) | ||
279 | { | ||
280 | return __perf_evsel__read(evsel, ncpus, nthreads, true); | ||
281 | } | ||
282 | |||
283 | int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, | 275 | int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, |
284 | struct perf_sample *sample); | 276 | struct perf_sample *sample); |
285 | 277 | ||
diff --git a/tools/perf/util/find-vdso-map.c b/tools/perf/util/find-vdso-map.c new file mode 100644 index 000000000000..95ef1cffc056 --- /dev/null +++ b/tools/perf/util/find-vdso-map.c | |||
@@ -0,0 +1,30 @@ | |||
1 | static int find_vdso_map(void **start, void **end) | ||
2 | { | ||
3 | FILE *maps; | ||
4 | char line[128]; | ||
5 | int found = 0; | ||
6 | |||
7 | maps = fopen("/proc/self/maps", "r"); | ||
8 | if (!maps) { | ||
9 | fprintf(stderr, "vdso: cannot open maps\n"); | ||
10 | return -1; | ||
11 | } | ||
12 | |||
13 | while (!found && fgets(line, sizeof(line), maps)) { | ||
14 | int m = -1; | ||
15 | |||
16 | /* We care only about private r-x mappings. */ | ||
17 | if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n", | ||
18 | start, end, &m)) | ||
19 | continue; | ||
20 | if (m < 0) | ||
21 | continue; | ||
22 | |||
23 | if (!strncmp(&line[m], VDSO__MAP_NAME, | ||
24 | sizeof(VDSO__MAP_NAME) - 1)) | ||
25 | found = 1; | ||
26 | } | ||
27 | |||
28 | fclose(maps); | ||
29 | return !found; | ||
30 | } | ||
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 26f5b2fe5dc8..b20e40c74468 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -24,8 +24,6 @@ | |||
24 | #include "build-id.h" | 24 | #include "build-id.h" |
25 | #include "data.h" | 25 | #include "data.h" |
26 | 26 | ||
27 | static bool no_buildid_cache = false; | ||
28 | |||
29 | static u32 header_argc; | 27 | static u32 header_argc; |
30 | static const char **header_argv; | 28 | static const char **header_argv; |
31 | 29 | ||
@@ -79,10 +77,7 @@ static int do_write(int fd, const void *buf, size_t size) | |||
79 | return 0; | 77 | return 0; |
80 | } | 78 | } |
81 | 79 | ||
82 | #define NAME_ALIGN 64 | 80 | int write_padded(int fd, const void *bf, size_t count, size_t count_aligned) |
83 | |||
84 | static int write_padded(int fd, const void *bf, size_t count, | ||
85 | size_t count_aligned) | ||
86 | { | 81 | { |
87 | static const char zero_buf[NAME_ALIGN]; | 82 | static const char zero_buf[NAME_ALIGN]; |
88 | int err = do_write(fd, bf, count); | 83 | int err = do_write(fd, bf, count); |
@@ -171,340 +166,6 @@ perf_header__set_cmdline(int argc, const char **argv) | |||
171 | return 0; | 166 | return 0; |
172 | } | 167 | } |
173 | 168 | ||
174 | #define dsos__for_each_with_build_id(pos, head) \ | ||
175 | list_for_each_entry(pos, head, node) \ | ||
176 | if (!pos->has_build_id) \ | ||
177 | continue; \ | ||
178 | else | ||
179 | |||
180 | static int write_buildid(const char *name, size_t name_len, u8 *build_id, | ||
181 | pid_t pid, u16 misc, int fd) | ||
182 | { | ||
183 | int err; | ||
184 | struct build_id_event b; | ||
185 | size_t len; | ||
186 | |||
187 | len = name_len + 1; | ||
188 | len = PERF_ALIGN(len, NAME_ALIGN); | ||
189 | |||
190 | memset(&b, 0, sizeof(b)); | ||
191 | memcpy(&b.build_id, build_id, BUILD_ID_SIZE); | ||
192 | b.pid = pid; | ||
193 | b.header.misc = misc; | ||
194 | b.header.size = sizeof(b) + len; | ||
195 | |||
196 | err = do_write(fd, &b, sizeof(b)); | ||
197 | if (err < 0) | ||
198 | return err; | ||
199 | |||
200 | return write_padded(fd, name, name_len + 1, len); | ||
201 | } | ||
202 | |||
203 | static int __dsos__hit_all(struct list_head *head) | ||
204 | { | ||
205 | struct dso *pos; | ||
206 | |||
207 | list_for_each_entry(pos, head, node) | ||
208 | pos->hit = true; | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static int machine__hit_all_dsos(struct machine *machine) | ||
214 | { | ||
215 | int err; | ||
216 | |||
217 | err = __dsos__hit_all(&machine->kernel_dsos.head); | ||
218 | if (err) | ||
219 | return err; | ||
220 | |||
221 | return __dsos__hit_all(&machine->user_dsos.head); | ||
222 | } | ||
223 | |||
224 | int dsos__hit_all(struct perf_session *session) | ||
225 | { | ||
226 | struct rb_node *nd; | ||
227 | int err; | ||
228 | |||
229 | err = machine__hit_all_dsos(&session->machines.host); | ||
230 | if (err) | ||
231 | return err; | ||
232 | |||
233 | for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { | ||
234 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | ||
235 | |||
236 | err = machine__hit_all_dsos(pos); | ||
237 | if (err) | ||
238 | return err; | ||
239 | } | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int __dsos__write_buildid_table(struct list_head *head, | ||
245 | struct machine *machine, | ||
246 | pid_t pid, u16 misc, int fd) | ||
247 | { | ||
248 | char nm[PATH_MAX]; | ||
249 | struct dso *pos; | ||
250 | |||
251 | dsos__for_each_with_build_id(pos, head) { | ||
252 | int err; | ||
253 | const char *name; | ||
254 | size_t name_len; | ||
255 | |||
256 | if (!pos->hit) | ||
257 | continue; | ||
258 | |||
259 | if (dso__is_vdso(pos)) { | ||
260 | name = pos->short_name; | ||
261 | name_len = pos->short_name_len + 1; | ||
262 | } else if (dso__is_kcore(pos)) { | ||
263 | machine__mmap_name(machine, nm, sizeof(nm)); | ||
264 | name = nm; | ||
265 | name_len = strlen(nm) + 1; | ||
266 | } else { | ||
267 | name = pos->long_name; | ||
268 | name_len = pos->long_name_len + 1; | ||
269 | } | ||
270 | |||
271 | err = write_buildid(name, name_len, pos->build_id, | ||
272 | pid, misc, fd); | ||
273 | if (err) | ||
274 | return err; | ||
275 | } | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static int machine__write_buildid_table(struct machine *machine, int fd) | ||
281 | { | ||
282 | int err; | ||
283 | u16 kmisc = PERF_RECORD_MISC_KERNEL, | ||
284 | umisc = PERF_RECORD_MISC_USER; | ||
285 | |||
286 | if (!machine__is_host(machine)) { | ||
287 | kmisc = PERF_RECORD_MISC_GUEST_KERNEL; | ||
288 | umisc = PERF_RECORD_MISC_GUEST_USER; | ||
289 | } | ||
290 | |||
291 | err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine, | ||
292 | machine->pid, kmisc, fd); | ||
293 | if (err == 0) | ||
294 | err = __dsos__write_buildid_table(&machine->user_dsos.head, | ||
295 | machine, machine->pid, umisc, | ||
296 | fd); | ||
297 | return err; | ||
298 | } | ||
299 | |||
300 | static int dsos__write_buildid_table(struct perf_header *header, int fd) | ||
301 | { | ||
302 | struct perf_session *session = container_of(header, | ||
303 | struct perf_session, header); | ||
304 | struct rb_node *nd; | ||
305 | int err = machine__write_buildid_table(&session->machines.host, fd); | ||
306 | |||
307 | if (err) | ||
308 | return err; | ||
309 | |||
310 | for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { | ||
311 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | ||
312 | err = machine__write_buildid_table(pos, fd); | ||
313 | if (err) | ||
314 | break; | ||
315 | } | ||
316 | return err; | ||
317 | } | ||
318 | |||
319 | int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, | ||
320 | const char *name, bool is_kallsyms, bool is_vdso) | ||
321 | { | ||
322 | const size_t size = PATH_MAX; | ||
323 | char *realname, *filename = zalloc(size), | ||
324 | *linkname = zalloc(size), *targetname; | ||
325 | int len, err = -1; | ||
326 | bool slash = is_kallsyms || is_vdso; | ||
327 | |||
328 | if (is_kallsyms) { | ||
329 | if (symbol_conf.kptr_restrict) { | ||
330 | pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n"); | ||
331 | err = 0; | ||
332 | goto out_free; | ||
333 | } | ||
334 | realname = (char *) name; | ||
335 | } else | ||
336 | realname = realpath(name, NULL); | ||
337 | |||
338 | if (realname == NULL || filename == NULL || linkname == NULL) | ||
339 | goto out_free; | ||
340 | |||
341 | len = scnprintf(filename, size, "%s%s%s", | ||
342 | debugdir, slash ? "/" : "", | ||
343 | is_vdso ? DSO__NAME_VDSO : realname); | ||
344 | if (mkdir_p(filename, 0755)) | ||
345 | goto out_free; | ||
346 | |||
347 | snprintf(filename + len, size - len, "/%s", sbuild_id); | ||
348 | |||
349 | if (access(filename, F_OK)) { | ||
350 | if (is_kallsyms) { | ||
351 | if (copyfile("/proc/kallsyms", filename)) | ||
352 | goto out_free; | ||
353 | } else if (link(realname, filename) && copyfile(name, filename)) | ||
354 | goto out_free; | ||
355 | } | ||
356 | |||
357 | len = scnprintf(linkname, size, "%s/.build-id/%.2s", | ||
358 | debugdir, sbuild_id); | ||
359 | |||
360 | if (access(linkname, X_OK) && mkdir_p(linkname, 0755)) | ||
361 | goto out_free; | ||
362 | |||
363 | snprintf(linkname + len, size - len, "/%s", sbuild_id + 2); | ||
364 | targetname = filename + strlen(debugdir) - 5; | ||
365 | memcpy(targetname, "../..", 5); | ||
366 | |||
367 | if (symlink(targetname, linkname) == 0) | ||
368 | err = 0; | ||
369 | out_free: | ||
370 | if (!is_kallsyms) | ||
371 | free(realname); | ||
372 | free(filename); | ||
373 | free(linkname); | ||
374 | return err; | ||
375 | } | ||
376 | |||
377 | static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, | ||
378 | const char *name, const char *debugdir, | ||
379 | bool is_kallsyms, bool is_vdso) | ||
380 | { | ||
381 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | ||
382 | |||
383 | build_id__sprintf(build_id, build_id_size, sbuild_id); | ||
384 | |||
385 | return build_id_cache__add_s(sbuild_id, debugdir, name, | ||
386 | is_kallsyms, is_vdso); | ||
387 | } | ||
388 | |||
389 | int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) | ||
390 | { | ||
391 | const size_t size = PATH_MAX; | ||
392 | char *filename = zalloc(size), | ||
393 | *linkname = zalloc(size); | ||
394 | int err = -1; | ||
395 | |||
396 | if (filename == NULL || linkname == NULL) | ||
397 | goto out_free; | ||
398 | |||
399 | snprintf(linkname, size, "%s/.build-id/%.2s/%s", | ||
400 | debugdir, sbuild_id, sbuild_id + 2); | ||
401 | |||
402 | if (access(linkname, F_OK)) | ||
403 | goto out_free; | ||
404 | |||
405 | if (readlink(linkname, filename, size - 1) < 0) | ||
406 | goto out_free; | ||
407 | |||
408 | if (unlink(linkname)) | ||
409 | goto out_free; | ||
410 | |||
411 | /* | ||
412 | * Since the link is relative, we must make it absolute: | ||
413 | */ | ||
414 | snprintf(linkname, size, "%s/.build-id/%.2s/%s", | ||
415 | debugdir, sbuild_id, filename); | ||
416 | |||
417 | if (unlink(linkname)) | ||
418 | goto out_free; | ||
419 | |||
420 | err = 0; | ||
421 | out_free: | ||
422 | free(filename); | ||
423 | free(linkname); | ||
424 | return err; | ||
425 | } | ||
426 | |||
427 | static int dso__cache_build_id(struct dso *dso, struct machine *machine, | ||
428 | const char *debugdir) | ||
429 | { | ||
430 | bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; | ||
431 | bool is_vdso = dso__is_vdso(dso); | ||
432 | const char *name = dso->long_name; | ||
433 | char nm[PATH_MAX]; | ||
434 | |||
435 | if (dso__is_kcore(dso)) { | ||
436 | is_kallsyms = true; | ||
437 | machine__mmap_name(machine, nm, sizeof(nm)); | ||
438 | name = nm; | ||
439 | } | ||
440 | return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name, | ||
441 | debugdir, is_kallsyms, is_vdso); | ||
442 | } | ||
443 | |||
444 | static int __dsos__cache_build_ids(struct list_head *head, | ||
445 | struct machine *machine, const char *debugdir) | ||
446 | { | ||
447 | struct dso *pos; | ||
448 | int err = 0; | ||
449 | |||
450 | dsos__for_each_with_build_id(pos, head) | ||
451 | if (dso__cache_build_id(pos, machine, debugdir)) | ||
452 | err = -1; | ||
453 | |||
454 | return err; | ||
455 | } | ||
456 | |||
457 | static int machine__cache_build_ids(struct machine *machine, const char *debugdir) | ||
458 | { | ||
459 | int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine, | ||
460 | debugdir); | ||
461 | ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine, | ||
462 | debugdir); | ||
463 | return ret; | ||
464 | } | ||
465 | |||
466 | static int perf_session__cache_build_ids(struct perf_session *session) | ||
467 | { | ||
468 | struct rb_node *nd; | ||
469 | int ret; | ||
470 | char debugdir[PATH_MAX]; | ||
471 | |||
472 | snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir); | ||
473 | |||
474 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) | ||
475 | return -1; | ||
476 | |||
477 | ret = machine__cache_build_ids(&session->machines.host, debugdir); | ||
478 | |||
479 | for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { | ||
480 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | ||
481 | ret |= machine__cache_build_ids(pos, debugdir); | ||
482 | } | ||
483 | return ret ? -1 : 0; | ||
484 | } | ||
485 | |||
486 | static bool machine__read_build_ids(struct machine *machine, bool with_hits) | ||
487 | { | ||
488 | bool ret; | ||
489 | |||
490 | ret = __dsos__read_build_ids(&machine->kernel_dsos.head, with_hits); | ||
491 | ret |= __dsos__read_build_ids(&machine->user_dsos.head, with_hits); | ||
492 | return ret; | ||
493 | } | ||
494 | |||
495 | static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits) | ||
496 | { | ||
497 | struct rb_node *nd; | ||
498 | bool ret = machine__read_build_ids(&session->machines.host, with_hits); | ||
499 | |||
500 | for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { | ||
501 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | ||
502 | ret |= machine__read_build_ids(pos, with_hits); | ||
503 | } | ||
504 | |||
505 | return ret; | ||
506 | } | ||
507 | |||
508 | static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, | 169 | static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, |
509 | struct perf_evlist *evlist) | 170 | struct perf_evlist *evlist) |
510 | { | 171 | { |
@@ -523,13 +184,12 @@ static int write_build_id(int fd, struct perf_header *h, | |||
523 | if (!perf_session__read_build_ids(session, true)) | 184 | if (!perf_session__read_build_ids(session, true)) |
524 | return -1; | 185 | return -1; |
525 | 186 | ||
526 | err = dsos__write_buildid_table(h, fd); | 187 | err = perf_session__write_buildid_table(session, fd); |
527 | if (err < 0) { | 188 | if (err < 0) { |
528 | pr_debug("failed to write buildid table\n"); | 189 | pr_debug("failed to write buildid table\n"); |
529 | return err; | 190 | return err; |
530 | } | 191 | } |
531 | if (!no_buildid_cache) | 192 | perf_session__cache_build_ids(session); |
532 | perf_session__cache_build_ids(session); | ||
533 | 193 | ||
534 | return 0; | 194 | return 0; |
535 | } | 195 | } |
@@ -601,8 +261,10 @@ static int __write_cpudesc(int fd, const char *cpuinfo_proc) | |||
601 | break; | 261 | break; |
602 | } | 262 | } |
603 | 263 | ||
604 | if (ret) | 264 | if (ret) { |
265 | ret = -1; | ||
605 | goto done; | 266 | goto done; |
267 | } | ||
606 | 268 | ||
607 | s = buf; | 269 | s = buf; |
608 | 270 | ||
@@ -965,7 +627,8 @@ static int write_total_mem(int fd, struct perf_header *h __maybe_unused, | |||
965 | n = sscanf(buf, "%*s %"PRIu64, &mem); | 627 | n = sscanf(buf, "%*s %"PRIu64, &mem); |
966 | if (n == 1) | 628 | if (n == 1) |
967 | ret = do_write(fd, &mem, sizeof(mem)); | 629 | ret = do_write(fd, &mem, sizeof(mem)); |
968 | } | 630 | } else |
631 | ret = -1; | ||
969 | free(buf); | 632 | free(buf); |
970 | fclose(fp); | 633 | fclose(fp); |
971 | return ret; | 634 | return ret; |
@@ -1603,7 +1266,7 @@ static int __event_process_build_id(struct build_id_event *bev, | |||
1603 | 1266 | ||
1604 | dso__set_build_id(dso, &bev->build_id); | 1267 | dso__set_build_id(dso, &bev->build_id); |
1605 | 1268 | ||
1606 | if (filename[0] == '[') | 1269 | if (!is_kernel_module(filename, NULL)) |
1607 | dso->kernel = dso_type; | 1270 | dso->kernel = dso_type; |
1608 | 1271 | ||
1609 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), | 1272 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), |
@@ -2477,6 +2140,7 @@ static const int attr_file_abi_sizes[] = { | |||
2477 | [1] = PERF_ATTR_SIZE_VER1, | 2140 | [1] = PERF_ATTR_SIZE_VER1, |
2478 | [2] = PERF_ATTR_SIZE_VER2, | 2141 | [2] = PERF_ATTR_SIZE_VER2, |
2479 | [3] = PERF_ATTR_SIZE_VER3, | 2142 | [3] = PERF_ATTR_SIZE_VER3, |
2143 | [4] = PERF_ATTR_SIZE_VER4, | ||
2480 | 0, | 2144 | 0, |
2481 | }; | 2145 | }; |
2482 | 2146 | ||
@@ -3124,8 +2788,3 @@ int perf_event__process_build_id(struct perf_tool *tool __maybe_unused, | |||
3124 | session); | 2788 | session); |
3125 | return 0; | 2789 | return 0; |
3126 | } | 2790 | } |
3127 | |||
3128 | void disable_buildid_cache(void) | ||
3129 | { | ||
3130 | no_buildid_cache = true; | ||
3131 | } | ||
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 8f5cbaea64a5..3bb90ac172a1 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h | |||
@@ -122,10 +122,6 @@ int perf_header__process_sections(struct perf_header *header, int fd, | |||
122 | 122 | ||
123 | int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full); | 123 | int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full); |
124 | 124 | ||
125 | int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, | ||
126 | const char *name, bool is_kallsyms, bool is_vdso); | ||
127 | int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); | ||
128 | |||
129 | int perf_event__synthesize_attr(struct perf_tool *tool, | 125 | int perf_event__synthesize_attr(struct perf_tool *tool, |
130 | struct perf_event_attr *attr, u32 ids, u64 *id, | 126 | struct perf_event_attr *attr, u32 ids, u64 *id, |
131 | perf_event__handler_t process); | 127 | perf_event__handler_t process); |
@@ -151,7 +147,9 @@ int perf_event__process_build_id(struct perf_tool *tool, | |||
151 | struct perf_session *session); | 147 | struct perf_session *session); |
152 | bool is_perf_magic(u64 magic); | 148 | bool is_perf_magic(u64 magic); |
153 | 149 | ||
154 | int dsos__hit_all(struct perf_session *session); | 150 | #define NAME_ALIGN 64 |
151 | |||
152 | int write_padded(int fd, const void *bf, size_t count, size_t count_aligned); | ||
155 | 153 | ||
156 | /* | 154 | /* |
157 | * arch specific callback | 155 | * arch specific callback |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 6e88b9e395df..182395546ddc 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include "evlist.h" | 6 | #include "evlist.h" |
7 | #include "evsel.h" | 7 | #include "evsel.h" |
8 | #include "annotate.h" | 8 | #include "annotate.h" |
9 | #include "ui/progress.h" | ||
9 | #include <math.h> | 10 | #include <math.h> |
10 | 11 | ||
11 | static bool hists__filter_entry_by_dso(struct hists *hists, | 12 | static bool hists__filter_entry_by_dso(struct hists *hists, |
@@ -303,7 +304,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template, | |||
303 | size_t callchain_size = 0; | 304 | size_t callchain_size = 0; |
304 | struct hist_entry *he; | 305 | struct hist_entry *he; |
305 | 306 | ||
306 | if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) | 307 | if (symbol_conf.use_callchain) |
307 | callchain_size = sizeof(struct callchain_root); | 308 | callchain_size = sizeof(struct callchain_root); |
308 | 309 | ||
309 | he = zalloc(sizeof(*he) + callchain_size); | 310 | he = zalloc(sizeof(*he) + callchain_size); |
@@ -736,7 +737,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter, | |||
736 | iter->he = he; | 737 | iter->he = he; |
737 | he_cache[iter->curr++] = he; | 738 | he_cache[iter->curr++] = he; |
738 | 739 | ||
739 | callchain_append(he->callchain, &callchain_cursor, sample->period); | 740 | hist_entry__append_callchain(he, sample); |
740 | 741 | ||
741 | /* | 742 | /* |
742 | * We need to re-initialize the cursor since callchain_append() | 743 | * We need to re-initialize the cursor since callchain_append() |
@@ -809,7 +810,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter, | |||
809 | iter->he = he; | 810 | iter->he = he; |
810 | he_cache[iter->curr++] = he; | 811 | he_cache[iter->curr++] = he; |
811 | 812 | ||
812 | callchain_append(he->callchain, &cursor, sample->period); | 813 | if (symbol_conf.use_callchain) |
814 | callchain_append(he->callchain, &cursor, sample->period); | ||
813 | return 0; | 815 | return 0; |
814 | } | 816 | } |
815 | 817 | ||
@@ -945,6 +947,7 @@ void hist_entry__free(struct hist_entry *he) | |||
945 | zfree(&he->mem_info); | 947 | zfree(&he->mem_info); |
946 | zfree(&he->stat_acc); | 948 | zfree(&he->stat_acc); |
947 | free_srcline(he->srcline); | 949 | free_srcline(he->srcline); |
950 | free_callchain(he->callchain); | ||
948 | free(he); | 951 | free(he); |
949 | } | 952 | } |
950 | 953 | ||
@@ -987,6 +990,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, | |||
987 | else | 990 | else |
988 | p = &(*p)->rb_right; | 991 | p = &(*p)->rb_right; |
989 | } | 992 | } |
993 | hists->nr_entries++; | ||
990 | 994 | ||
991 | rb_link_node(&he->rb_node_in, parent, p); | 995 | rb_link_node(&he->rb_node_in, parent, p); |
992 | rb_insert_color(&he->rb_node_in, root); | 996 | rb_insert_color(&he->rb_node_in, root); |
@@ -1024,7 +1028,10 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog) | |||
1024 | if (!sort__need_collapse) | 1028 | if (!sort__need_collapse) |
1025 | return; | 1029 | return; |
1026 | 1030 | ||
1031 | hists->nr_entries = 0; | ||
1032 | |||
1027 | root = hists__get_rotate_entries_in(hists); | 1033 | root = hists__get_rotate_entries_in(hists); |
1034 | |||
1028 | next = rb_first(root); | 1035 | next = rb_first(root); |
1029 | 1036 | ||
1030 | while (next) { | 1037 | while (next) { |
@@ -1119,7 +1126,7 @@ static void __hists__insert_output_entry(struct rb_root *entries, | |||
1119 | rb_insert_color(&he->rb_node, entries); | 1126 | rb_insert_color(&he->rb_node, entries); |
1120 | } | 1127 | } |
1121 | 1128 | ||
1122 | void hists__output_resort(struct hists *hists) | 1129 | void hists__output_resort(struct hists *hists, struct ui_progress *prog) |
1123 | { | 1130 | { |
1124 | struct rb_root *root; | 1131 | struct rb_root *root; |
1125 | struct rb_node *next; | 1132 | struct rb_node *next; |
@@ -1148,6 +1155,9 @@ void hists__output_resort(struct hists *hists) | |||
1148 | 1155 | ||
1149 | if (!n->filtered) | 1156 | if (!n->filtered) |
1150 | hists__calc_col_len(hists, n); | 1157 | hists__calc_col_len(hists, n); |
1158 | |||
1159 | if (prog) | ||
1160 | ui_progress__update(prog, 1); | ||
1151 | } | 1161 | } |
1152 | } | 1162 | } |
1153 | 1163 | ||
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index d0ef9a19a744..46bd50344f85 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -121,7 +121,7 @@ int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size, | |||
121 | struct hists *hists); | 121 | struct hists *hists); |
122 | void hist_entry__free(struct hist_entry *); | 122 | void hist_entry__free(struct hist_entry *); |
123 | 123 | ||
124 | void hists__output_resort(struct hists *hists); | 124 | void hists__output_resort(struct hists *hists, struct ui_progress *prog); |
125 | void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); | 125 | void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); |
126 | 126 | ||
127 | void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); | 127 | void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); |
diff --git a/tools/perf/util/hweight.c b/tools/perf/util/hweight.c deleted file mode 100644 index 5c1d0d099f0d..000000000000 --- a/tools/perf/util/hweight.c +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | #include <linux/bitops.h> | ||
2 | |||
3 | /** | ||
4 | * hweightN - returns the hamming weight of a N-bit word | ||
5 | * @x: the word to weigh | ||
6 | * | ||
7 | * The Hamming Weight of a number is the total number of bits set in it. | ||
8 | */ | ||
9 | |||
10 | unsigned int hweight32(unsigned int w) | ||
11 | { | ||
12 | unsigned int res = w - ((w >> 1) & 0x55555555); | ||
13 | res = (res & 0x33333333) + ((res >> 2) & 0x33333333); | ||
14 | res = (res + (res >> 4)) & 0x0F0F0F0F; | ||
15 | res = res + (res >> 8); | ||
16 | return (res + (res >> 16)) & 0x000000FF; | ||
17 | } | ||
18 | |||
19 | unsigned long hweight64(__u64 w) | ||
20 | { | ||
21 | #if BITS_PER_LONG == 32 | ||
22 | return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w); | ||
23 | #elif BITS_PER_LONG == 64 | ||
24 | __u64 res = w - ((w >> 1) & 0x5555555555555555ul); | ||
25 | res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul); | ||
26 | res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful; | ||
27 | res = res + (res >> 8); | ||
28 | res = res + (res >> 16); | ||
29 | return (res + (res >> 32)) & 0x00000000000000FFul; | ||
30 | #endif | ||
31 | } | ||
diff --git a/tools/perf/util/include/asm/hash.h b/tools/perf/util/include/asm/hash.h deleted file mode 100644 index d82b170bb216..000000000000 --- a/tools/perf/util/include/asm/hash.h +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #ifndef __ASM_GENERIC_HASH_H | ||
2 | #define __ASM_GENERIC_HASH_H | ||
3 | |||
4 | /* Stub */ | ||
5 | |||
6 | #endif /* __ASM_GENERIC_HASH_H */ | ||
diff --git a/tools/perf/util/include/asm/hweight.h b/tools/perf/util/include/asm/hweight.h deleted file mode 100644 index 36cf26d434a5..000000000000 --- a/tools/perf/util/include/asm/hweight.h +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | #ifndef PERF_HWEIGHT_H | ||
2 | #define PERF_HWEIGHT_H | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | unsigned int hweight32(unsigned int w); | ||
6 | unsigned long hweight64(__u64 w); | ||
7 | |||
8 | #endif /* PERF_HWEIGHT_H */ | ||
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/perf/util/include/linux/bitmap.h index 01ffd12dc791..40bd21488032 100644 --- a/tools/perf/util/include/linux/bitmap.h +++ b/tools/perf/util/include/linux/bitmap.h | |||
@@ -46,4 +46,21 @@ static inline void bitmap_or(unsigned long *dst, const unsigned long *src1, | |||
46 | __bitmap_or(dst, src1, src2, nbits); | 46 | __bitmap_or(dst, src1, src2, nbits); |
47 | } | 47 | } |
48 | 48 | ||
49 | /** | ||
50 | * test_and_set_bit - Set a bit and return its old value | ||
51 | * @nr: Bit to set | ||
52 | * @addr: Address to count from | ||
53 | */ | ||
54 | static inline int test_and_set_bit(int nr, unsigned long *addr) | ||
55 | { | ||
56 | unsigned long mask = BIT_MASK(nr); | ||
57 | unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); | ||
58 | unsigned long old; | ||
59 | |||
60 | old = *p; | ||
61 | *p = old | mask; | ||
62 | |||
63 | return (old & mask) != 0; | ||
64 | } | ||
65 | |||
49 | #endif /* _PERF_BITOPS_H */ | 66 | #endif /* _PERF_BITOPS_H */ |
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h deleted file mode 100644 index dadfa7e54287..000000000000 --- a/tools/perf/util/include/linux/bitops.h +++ /dev/null | |||
@@ -1,160 +0,0 @@ | |||
1 | #ifndef _PERF_LINUX_BITOPS_H_ | ||
2 | #define _PERF_LINUX_BITOPS_H_ | ||
3 | |||
4 | #include <linux/kernel.h> | ||
5 | #include <linux/compiler.h> | ||
6 | #include <asm/hweight.h> | ||
7 | |||
8 | #ifndef __WORDSIZE | ||
9 | #define __WORDSIZE (__SIZEOF_LONG__ * 8) | ||
10 | #endif | ||
11 | |||
12 | #define BITS_PER_LONG __WORDSIZE | ||
13 | #define BITS_PER_BYTE 8 | ||
14 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) | ||
15 | #define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64)) | ||
16 | #define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32)) | ||
17 | #define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE) | ||
18 | |||
19 | #define for_each_set_bit(bit, addr, size) \ | ||
20 | for ((bit) = find_first_bit((addr), (size)); \ | ||
21 | (bit) < (size); \ | ||
22 | (bit) = find_next_bit((addr), (size), (bit) + 1)) | ||
23 | |||
24 | /* same as for_each_set_bit() but use bit as value to start with */ | ||
25 | #define for_each_set_bit_from(bit, addr, size) \ | ||
26 | for ((bit) = find_next_bit((addr), (size), (bit)); \ | ||
27 | (bit) < (size); \ | ||
28 | (bit) = find_next_bit((addr), (size), (bit) + 1)) | ||
29 | |||
30 | static inline void set_bit(int nr, unsigned long *addr) | ||
31 | { | ||
32 | addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG); | ||
33 | } | ||
34 | |||
35 | static inline void clear_bit(int nr, unsigned long *addr) | ||
36 | { | ||
37 | addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG)); | ||
38 | } | ||
39 | |||
40 | static __always_inline int test_bit(unsigned int nr, const unsigned long *addr) | ||
41 | { | ||
42 | return ((1UL << (nr % BITS_PER_LONG)) & | ||
43 | (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0; | ||
44 | } | ||
45 | |||
46 | static inline unsigned long hweight_long(unsigned long w) | ||
47 | { | ||
48 | return sizeof(w) == 4 ? hweight32(w) : hweight64(w); | ||
49 | } | ||
50 | |||
51 | #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) | ||
52 | |||
53 | /** | ||
54 | * __ffs - find first bit in word. | ||
55 | * @word: The word to search | ||
56 | * | ||
57 | * Undefined if no bit exists, so code should check against 0 first. | ||
58 | */ | ||
59 | static __always_inline unsigned long __ffs(unsigned long word) | ||
60 | { | ||
61 | int num = 0; | ||
62 | |||
63 | #if BITS_PER_LONG == 64 | ||
64 | if ((word & 0xffffffff) == 0) { | ||
65 | num += 32; | ||
66 | word >>= 32; | ||
67 | } | ||
68 | #endif | ||
69 | if ((word & 0xffff) == 0) { | ||
70 | num += 16; | ||
71 | word >>= 16; | ||
72 | } | ||
73 | if ((word & 0xff) == 0) { | ||
74 | num += 8; | ||
75 | word >>= 8; | ||
76 | } | ||
77 | if ((word & 0xf) == 0) { | ||
78 | num += 4; | ||
79 | word >>= 4; | ||
80 | } | ||
81 | if ((word & 0x3) == 0) { | ||
82 | num += 2; | ||
83 | word >>= 2; | ||
84 | } | ||
85 | if ((word & 0x1) == 0) | ||
86 | num += 1; | ||
87 | return num; | ||
88 | } | ||
89 | |||
90 | typedef const unsigned long __attribute__((__may_alias__)) long_alias_t; | ||
91 | |||
92 | /* | ||
93 | * Find the first set bit in a memory region. | ||
94 | */ | ||
95 | static inline unsigned long | ||
96 | find_first_bit(const unsigned long *addr, unsigned long size) | ||
97 | { | ||
98 | long_alias_t *p = (long_alias_t *) addr; | ||
99 | unsigned long result = 0; | ||
100 | unsigned long tmp; | ||
101 | |||
102 | while (size & ~(BITS_PER_LONG-1)) { | ||
103 | if ((tmp = *(p++))) | ||
104 | goto found; | ||
105 | result += BITS_PER_LONG; | ||
106 | size -= BITS_PER_LONG; | ||
107 | } | ||
108 | if (!size) | ||
109 | return result; | ||
110 | |||
111 | tmp = (*p) & (~0UL >> (BITS_PER_LONG - size)); | ||
112 | if (tmp == 0UL) /* Are any bits set? */ | ||
113 | return result + size; /* Nope. */ | ||
114 | found: | ||
115 | return result + __ffs(tmp); | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * Find the next set bit in a memory region. | ||
120 | */ | ||
121 | static inline unsigned long | ||
122 | find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset) | ||
123 | { | ||
124 | const unsigned long *p = addr + BITOP_WORD(offset); | ||
125 | unsigned long result = offset & ~(BITS_PER_LONG-1); | ||
126 | unsigned long tmp; | ||
127 | |||
128 | if (offset >= size) | ||
129 | return size; | ||
130 | size -= result; | ||
131 | offset %= BITS_PER_LONG; | ||
132 | if (offset) { | ||
133 | tmp = *(p++); | ||
134 | tmp &= (~0UL << offset); | ||
135 | if (size < BITS_PER_LONG) | ||
136 | goto found_first; | ||
137 | if (tmp) | ||
138 | goto found_middle; | ||
139 | size -= BITS_PER_LONG; | ||
140 | result += BITS_PER_LONG; | ||
141 | } | ||
142 | while (size & ~(BITS_PER_LONG-1)) { | ||
143 | if ((tmp = *(p++))) | ||
144 | goto found_middle; | ||
145 | result += BITS_PER_LONG; | ||
146 | size -= BITS_PER_LONG; | ||
147 | } | ||
148 | if (!size) | ||
149 | return result; | ||
150 | tmp = *p; | ||
151 | |||
152 | found_first: | ||
153 | tmp &= (~0UL >> (BITS_PER_LONG - size)); | ||
154 | if (tmp == 0UL) /* Are any bits set? */ | ||
155 | return result + size; /* Nope. */ | ||
156 | found_middle: | ||
157 | return result + __ffs(tmp); | ||
158 | } | ||
159 | |||
160 | #endif | ||
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 34fc7c8672e4..1bca3a9f2b16 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <stdbool.h> | 12 | #include <stdbool.h> |
13 | #include <symbol/kallsyms.h> | 13 | #include <symbol/kallsyms.h> |
14 | #include "unwind.h" | 14 | #include "unwind.h" |
15 | #include "linux/hash.h" | ||
15 | 16 | ||
16 | static void dsos__init(struct dsos *dsos) | 17 | static void dsos__init(struct dsos *dsos) |
17 | { | 18 | { |
@@ -21,7 +22,7 @@ static void dsos__init(struct dsos *dsos) | |||
21 | 22 | ||
22 | int machine__init(struct machine *machine, const char *root_dir, pid_t pid) | 23 | int machine__init(struct machine *machine, const char *root_dir, pid_t pid) |
23 | { | 24 | { |
24 | map_groups__init(&machine->kmaps); | 25 | map_groups__init(&machine->kmaps, machine); |
25 | RB_CLEAR_NODE(&machine->rb_node); | 26 | RB_CLEAR_NODE(&machine->rb_node); |
26 | dsos__init(&machine->user_dsos); | 27 | dsos__init(&machine->user_dsos); |
27 | dsos__init(&machine->kernel_dsos); | 28 | dsos__init(&machine->kernel_dsos); |
@@ -32,7 +33,6 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) | |||
32 | 33 | ||
33 | machine->vdso_info = NULL; | 34 | machine->vdso_info = NULL; |
34 | 35 | ||
35 | machine->kmaps.machine = machine; | ||
36 | machine->pid = pid; | 36 | machine->pid = pid; |
37 | 37 | ||
38 | machine->symbol_filter = NULL; | 38 | machine->symbol_filter = NULL; |
@@ -319,7 +319,7 @@ static void machine__update_thread_pid(struct machine *machine, | |||
319 | goto out_err; | 319 | goto out_err; |
320 | 320 | ||
321 | if (!leader->mg) | 321 | if (!leader->mg) |
322 | leader->mg = map_groups__new(); | 322 | leader->mg = map_groups__new(machine); |
323 | 323 | ||
324 | if (!leader->mg) | 324 | if (!leader->mg) |
325 | goto out_err; | 325 | goto out_err; |
@@ -389,7 +389,6 @@ static struct thread *__machine__findnew_thread(struct machine *machine, | |||
389 | if (th != NULL) { | 389 | if (th != NULL) { |
390 | rb_link_node(&th->rb_node, parent, p); | 390 | rb_link_node(&th->rb_node, parent, p); |
391 | rb_insert_color(&th->rb_node, &machine->threads); | 391 | rb_insert_color(&th->rb_node, &machine->threads); |
392 | machine->last_match = th; | ||
393 | 392 | ||
394 | /* | 393 | /* |
395 | * We have to initialize map_groups separately | 394 | * We have to initialize map_groups separately |
@@ -400,9 +399,12 @@ static struct thread *__machine__findnew_thread(struct machine *machine, | |||
400 | * leader and that would screwed the rb tree. | 399 | * leader and that would screwed the rb tree. |
401 | */ | 400 | */ |
402 | if (thread__init_map_groups(th, machine)) { | 401 | if (thread__init_map_groups(th, machine)) { |
402 | rb_erase(&th->rb_node, &machine->threads); | ||
403 | thread__delete(th); | 403 | thread__delete(th); |
404 | return NULL; | 404 | return NULL; |
405 | } | 405 | } |
406 | |||
407 | machine->last_match = th; | ||
406 | } | 408 | } |
407 | 409 | ||
408 | return th; | 410 | return th; |
@@ -465,6 +467,7 @@ struct map *machine__new_module(struct machine *machine, u64 start, | |||
465 | { | 467 | { |
466 | struct map *map; | 468 | struct map *map; |
467 | struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); | 469 | struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); |
470 | bool compressed; | ||
468 | 471 | ||
469 | if (dso == NULL) | 472 | if (dso == NULL) |
470 | return NULL; | 473 | return NULL; |
@@ -477,6 +480,11 @@ struct map *machine__new_module(struct machine *machine, u64 start, | |||
477 | dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; | 480 | dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; |
478 | else | 481 | else |
479 | dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; | 482 | dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; |
483 | |||
484 | /* _KMODULE_COMP should be next to _KMODULE */ | ||
485 | if (is_kernel_module(filename, &compressed) && compressed) | ||
486 | dso->symtab_type++; | ||
487 | |||
480 | map_groups__insert(&machine->kmaps, map); | 488 | map_groups__insert(&machine->kmaps, map); |
481 | return map; | 489 | return map; |
482 | } | 490 | } |
@@ -862,8 +870,14 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg, | |||
862 | struct map *map; | 870 | struct map *map; |
863 | char *long_name; | 871 | char *long_name; |
864 | 872 | ||
865 | if (dot == NULL || strcmp(dot, ".ko")) | 873 | if (dot == NULL) |
866 | continue; | 874 | continue; |
875 | |||
876 | /* On some system, modules are compressed like .ko.gz */ | ||
877 | if (is_supported_compression(dot + 1) && | ||
878 | is_kmodule_extension(dot - 2)) | ||
879 | dot -= 3; | ||
880 | |||
867 | snprintf(dso_name, sizeof(dso_name), "[%.*s]", | 881 | snprintf(dso_name, sizeof(dso_name), "[%.*s]", |
868 | (int)(dot - dent->d_name), dent->d_name); | 882 | (int)(dot - dent->d_name), dent->d_name); |
869 | 883 | ||
@@ -1045,6 +1059,11 @@ static int machine__process_kernel_mmap_event(struct machine *machine, | |||
1045 | dot = strrchr(name, '.'); | 1059 | dot = strrchr(name, '.'); |
1046 | if (dot == NULL) | 1060 | if (dot == NULL) |
1047 | goto out_problem; | 1061 | goto out_problem; |
1062 | /* On some system, modules are compressed like .ko.gz */ | ||
1063 | if (is_supported_compression(dot + 1)) | ||
1064 | dot -= 3; | ||
1065 | if (!is_kmodule_extension(dot + 1)) | ||
1066 | goto out_problem; | ||
1048 | snprintf(short_module_name, sizeof(short_module_name), | 1067 | snprintf(short_module_name, sizeof(short_module_name), |
1049 | "[%.*s]", (int)(dot - name), name); | 1068 | "[%.*s]", (int)(dot - name), name); |
1050 | strxfrchar(short_module_name, '-', '_'); | 1069 | strxfrchar(short_module_name, '-', '_'); |
@@ -1069,8 +1088,20 @@ static int machine__process_kernel_mmap_event(struct machine *machine, | |||
1069 | * Should be there already, from the build-id table in | 1088 | * Should be there already, from the build-id table in |
1070 | * the header. | 1089 | * the header. |
1071 | */ | 1090 | */ |
1072 | struct dso *kernel = __dsos__findnew(&machine->kernel_dsos, | 1091 | struct dso *kernel = NULL; |
1073 | kmmap_prefix); | 1092 | struct dso *dso; |
1093 | |||
1094 | list_for_each_entry(dso, &machine->kernel_dsos.head, node) { | ||
1095 | if (is_kernel_module(dso->long_name, NULL)) | ||
1096 | continue; | ||
1097 | |||
1098 | kernel = dso; | ||
1099 | break; | ||
1100 | } | ||
1101 | |||
1102 | if (kernel == NULL) | ||
1103 | kernel = __dsos__findnew(&machine->kernel_dsos, | ||
1104 | kmmap_prefix); | ||
1074 | if (kernel == NULL) | 1105 | if (kernel == NULL) |
1075 | goto out_problem; | 1106 | goto out_problem; |
1076 | 1107 | ||
@@ -1078,6 +1109,9 @@ static int machine__process_kernel_mmap_event(struct machine *machine, | |||
1078 | if (__machine__create_kernel_maps(machine, kernel) < 0) | 1109 | if (__machine__create_kernel_maps(machine, kernel) < 0) |
1079 | goto out_problem; | 1110 | goto out_problem; |
1080 | 1111 | ||
1112 | if (strstr(kernel->long_name, "vmlinux")) | ||
1113 | dso__set_short_name(kernel, "[kernel.vmlinux]", false); | ||
1114 | |||
1081 | machine__set_kernel_mmap_len(machine, event); | 1115 | machine__set_kernel_mmap_len(machine, event); |
1082 | 1116 | ||
1083 | /* | 1117 | /* |
@@ -1290,7 +1324,7 @@ static bool symbol__match_regex(struct symbol *sym, regex_t *regex) | |||
1290 | return 0; | 1324 | return 0; |
1291 | } | 1325 | } |
1292 | 1326 | ||
1293 | static void ip__resolve_ams(struct machine *machine, struct thread *thread, | 1327 | static void ip__resolve_ams(struct thread *thread, |
1294 | struct addr_map_symbol *ams, | 1328 | struct addr_map_symbol *ams, |
1295 | u64 ip) | 1329 | u64 ip) |
1296 | { | 1330 | { |
@@ -1304,7 +1338,7 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread, | |||
1304 | * Thus, we have to try consecutively until we find a match | 1338 | * Thus, we have to try consecutively until we find a match |
1305 | * or else, the symbol is unknown | 1339 | * or else, the symbol is unknown |
1306 | */ | 1340 | */ |
1307 | thread__find_cpumode_addr_location(thread, machine, MAP__FUNCTION, ip, &al); | 1341 | thread__find_cpumode_addr_location(thread, MAP__FUNCTION, ip, &al); |
1308 | 1342 | ||
1309 | ams->addr = ip; | 1343 | ams->addr = ip; |
1310 | ams->al_addr = al.addr; | 1344 | ams->al_addr = al.addr; |
@@ -1312,23 +1346,21 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread, | |||
1312 | ams->map = al.map; | 1346 | ams->map = al.map; |
1313 | } | 1347 | } |
1314 | 1348 | ||
1315 | static void ip__resolve_data(struct machine *machine, struct thread *thread, | 1349 | static void ip__resolve_data(struct thread *thread, |
1316 | u8 m, struct addr_map_symbol *ams, u64 addr) | 1350 | u8 m, struct addr_map_symbol *ams, u64 addr) |
1317 | { | 1351 | { |
1318 | struct addr_location al; | 1352 | struct addr_location al; |
1319 | 1353 | ||
1320 | memset(&al, 0, sizeof(al)); | 1354 | memset(&al, 0, sizeof(al)); |
1321 | 1355 | ||
1322 | thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr, | 1356 | thread__find_addr_location(thread, m, MAP__VARIABLE, addr, &al); |
1323 | &al); | ||
1324 | if (al.map == NULL) { | 1357 | if (al.map == NULL) { |
1325 | /* | 1358 | /* |
1326 | * some shared data regions have execute bit set which puts | 1359 | * some shared data regions have execute bit set which puts |
1327 | * their mapping in the MAP__FUNCTION type array. | 1360 | * their mapping in the MAP__FUNCTION type array. |
1328 | * Check there as a fallback option before dropping the sample. | 1361 | * Check there as a fallback option before dropping the sample. |
1329 | */ | 1362 | */ |
1330 | thread__find_addr_location(thread, machine, m, MAP__FUNCTION, addr, | 1363 | thread__find_addr_location(thread, m, MAP__FUNCTION, addr, &al); |
1331 | &al); | ||
1332 | } | 1364 | } |
1333 | 1365 | ||
1334 | ams->addr = addr; | 1366 | ams->addr = addr; |
@@ -1345,14 +1377,72 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample, | |||
1345 | if (!mi) | 1377 | if (!mi) |
1346 | return NULL; | 1378 | return NULL; |
1347 | 1379 | ||
1348 | ip__resolve_ams(al->machine, al->thread, &mi->iaddr, sample->ip); | 1380 | ip__resolve_ams(al->thread, &mi->iaddr, sample->ip); |
1349 | ip__resolve_data(al->machine, al->thread, al->cpumode, | 1381 | ip__resolve_data(al->thread, al->cpumode, &mi->daddr, sample->addr); |
1350 | &mi->daddr, sample->addr); | ||
1351 | mi->data_src.val = sample->data_src; | 1382 | mi->data_src.val = sample->data_src; |
1352 | 1383 | ||
1353 | return mi; | 1384 | return mi; |
1354 | } | 1385 | } |
1355 | 1386 | ||
1387 | static int add_callchain_ip(struct thread *thread, | ||
1388 | struct symbol **parent, | ||
1389 | struct addr_location *root_al, | ||
1390 | bool branch_history, | ||
1391 | u64 ip) | ||
1392 | { | ||
1393 | struct addr_location al; | ||
1394 | |||
1395 | al.filtered = 0; | ||
1396 | al.sym = NULL; | ||
1397 | if (branch_history) | ||
1398 | thread__find_cpumode_addr_location(thread, MAP__FUNCTION, | ||
1399 | ip, &al); | ||
1400 | else { | ||
1401 | u8 cpumode = PERF_RECORD_MISC_USER; | ||
1402 | |||
1403 | if (ip >= PERF_CONTEXT_MAX) { | ||
1404 | switch (ip) { | ||
1405 | case PERF_CONTEXT_HV: | ||
1406 | cpumode = PERF_RECORD_MISC_HYPERVISOR; | ||
1407 | break; | ||
1408 | case PERF_CONTEXT_KERNEL: | ||
1409 | cpumode = PERF_RECORD_MISC_KERNEL; | ||
1410 | break; | ||
1411 | case PERF_CONTEXT_USER: | ||
1412 | cpumode = PERF_RECORD_MISC_USER; | ||
1413 | break; | ||
1414 | default: | ||
1415 | pr_debug("invalid callchain context: " | ||
1416 | "%"PRId64"\n", (s64) ip); | ||
1417 | /* | ||
1418 | * It seems the callchain is corrupted. | ||
1419 | * Discard all. | ||
1420 | */ | ||
1421 | callchain_cursor_reset(&callchain_cursor); | ||
1422 | return 1; | ||
1423 | } | ||
1424 | return 0; | ||
1425 | } | ||
1426 | thread__find_addr_location(thread, cpumode, MAP__FUNCTION, | ||
1427 | ip, &al); | ||
1428 | } | ||
1429 | |||
1430 | if (al.sym != NULL) { | ||
1431 | if (sort__has_parent && !*parent && | ||
1432 | symbol__match_regex(al.sym, &parent_regex)) | ||
1433 | *parent = al.sym; | ||
1434 | else if (have_ignore_callees && root_al && | ||
1435 | symbol__match_regex(al.sym, &ignore_callees_regex)) { | ||
1436 | /* Treat this symbol as the root, | ||
1437 | forgetting its callees. */ | ||
1438 | *root_al = al; | ||
1439 | callchain_cursor_reset(&callchain_cursor); | ||
1440 | } | ||
1441 | } | ||
1442 | |||
1443 | return callchain_cursor_append(&callchain_cursor, al.addr, al.map, al.sym); | ||
1444 | } | ||
1445 | |||
1356 | struct branch_info *sample__resolve_bstack(struct perf_sample *sample, | 1446 | struct branch_info *sample__resolve_bstack(struct perf_sample *sample, |
1357 | struct addr_location *al) | 1447 | struct addr_location *al) |
1358 | { | 1448 | { |
@@ -1364,43 +1454,140 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample, | |||
1364 | return NULL; | 1454 | return NULL; |
1365 | 1455 | ||
1366 | for (i = 0; i < bs->nr; i++) { | 1456 | for (i = 0; i < bs->nr; i++) { |
1367 | ip__resolve_ams(al->machine, al->thread, &bi[i].to, bs->entries[i].to); | 1457 | ip__resolve_ams(al->thread, &bi[i].to, bs->entries[i].to); |
1368 | ip__resolve_ams(al->machine, al->thread, &bi[i].from, bs->entries[i].from); | 1458 | ip__resolve_ams(al->thread, &bi[i].from, bs->entries[i].from); |
1369 | bi[i].flags = bs->entries[i].flags; | 1459 | bi[i].flags = bs->entries[i].flags; |
1370 | } | 1460 | } |
1371 | return bi; | 1461 | return bi; |
1372 | } | 1462 | } |
1373 | 1463 | ||
1374 | static int machine__resolve_callchain_sample(struct machine *machine, | 1464 | #define CHASHSZ 127 |
1375 | struct thread *thread, | 1465 | #define CHASHBITS 7 |
1466 | #define NO_ENTRY 0xff | ||
1467 | |||
1468 | #define PERF_MAX_BRANCH_DEPTH 127 | ||
1469 | |||
1470 | /* Remove loops. */ | ||
1471 | static int remove_loops(struct branch_entry *l, int nr) | ||
1472 | { | ||
1473 | int i, j, off; | ||
1474 | unsigned char chash[CHASHSZ]; | ||
1475 | |||
1476 | memset(chash, NO_ENTRY, sizeof(chash)); | ||
1477 | |||
1478 | BUG_ON(PERF_MAX_BRANCH_DEPTH > 255); | ||
1479 | |||
1480 | for (i = 0; i < nr; i++) { | ||
1481 | int h = hash_64(l[i].from, CHASHBITS) % CHASHSZ; | ||
1482 | |||
1483 | /* no collision handling for now */ | ||
1484 | if (chash[h] == NO_ENTRY) { | ||
1485 | chash[h] = i; | ||
1486 | } else if (l[chash[h]].from == l[i].from) { | ||
1487 | bool is_loop = true; | ||
1488 | /* check if it is a real loop */ | ||
1489 | off = 0; | ||
1490 | for (j = chash[h]; j < i && i + off < nr; j++, off++) | ||
1491 | if (l[j].from != l[i + off].from) { | ||
1492 | is_loop = false; | ||
1493 | break; | ||
1494 | } | ||
1495 | if (is_loop) { | ||
1496 | memmove(l + i, l + i + off, | ||
1497 | (nr - (i + off)) * sizeof(*l)); | ||
1498 | nr -= off; | ||
1499 | } | ||
1500 | } | ||
1501 | } | ||
1502 | return nr; | ||
1503 | } | ||
1504 | |||
1505 | static int thread__resolve_callchain_sample(struct thread *thread, | ||
1376 | struct ip_callchain *chain, | 1506 | struct ip_callchain *chain, |
1507 | struct branch_stack *branch, | ||
1377 | struct symbol **parent, | 1508 | struct symbol **parent, |
1378 | struct addr_location *root_al, | 1509 | struct addr_location *root_al, |
1379 | int max_stack) | 1510 | int max_stack) |
1380 | { | 1511 | { |
1381 | u8 cpumode = PERF_RECORD_MISC_USER; | ||
1382 | int chain_nr = min(max_stack, (int)chain->nr); | 1512 | int chain_nr = min(max_stack, (int)chain->nr); |
1383 | int i; | 1513 | int i, j, err; |
1384 | int j; | 1514 | int skip_idx = -1; |
1385 | int err; | 1515 | int first_call = 0; |
1386 | int skip_idx __maybe_unused; | 1516 | |
1517 | /* | ||
1518 | * Based on DWARF debug information, some architectures skip | ||
1519 | * a callchain entry saved by the kernel. | ||
1520 | */ | ||
1521 | if (chain->nr < PERF_MAX_STACK_DEPTH) | ||
1522 | skip_idx = arch_skip_callchain_idx(thread, chain); | ||
1387 | 1523 | ||
1388 | callchain_cursor_reset(&callchain_cursor); | 1524 | callchain_cursor_reset(&callchain_cursor); |
1389 | 1525 | ||
1526 | /* | ||
1527 | * Add branches to call stack for easier browsing. This gives | ||
1528 | * more context for a sample than just the callers. | ||
1529 | * | ||
1530 | * This uses individual histograms of paths compared to the | ||
1531 | * aggregated histograms the normal LBR mode uses. | ||
1532 | * | ||
1533 | * Limitations for now: | ||
1534 | * - No extra filters | ||
1535 | * - No annotations (should annotate somehow) | ||
1536 | */ | ||
1537 | |||
1538 | if (branch && callchain_param.branch_callstack) { | ||
1539 | int nr = min(max_stack, (int)branch->nr); | ||
1540 | struct branch_entry be[nr]; | ||
1541 | |||
1542 | if (branch->nr > PERF_MAX_BRANCH_DEPTH) { | ||
1543 | pr_warning("corrupted branch chain. skipping...\n"); | ||
1544 | goto check_calls; | ||
1545 | } | ||
1546 | |||
1547 | for (i = 0; i < nr; i++) { | ||
1548 | if (callchain_param.order == ORDER_CALLEE) { | ||
1549 | be[i] = branch->entries[i]; | ||
1550 | /* | ||
1551 | * Check for overlap into the callchain. | ||
1552 | * The return address is one off compared to | ||
1553 | * the branch entry. To adjust for this | ||
1554 | * assume the calling instruction is not longer | ||
1555 | * than 8 bytes. | ||
1556 | */ | ||
1557 | if (i == skip_idx || | ||
1558 | chain->ips[first_call] >= PERF_CONTEXT_MAX) | ||
1559 | first_call++; | ||
1560 | else if (be[i].from < chain->ips[first_call] && | ||
1561 | be[i].from >= chain->ips[first_call] - 8) | ||
1562 | first_call++; | ||
1563 | } else | ||
1564 | be[i] = branch->entries[branch->nr - i - 1]; | ||
1565 | } | ||
1566 | |||
1567 | nr = remove_loops(be, nr); | ||
1568 | |||
1569 | for (i = 0; i < nr; i++) { | ||
1570 | err = add_callchain_ip(thread, parent, root_al, | ||
1571 | true, be[i].to); | ||
1572 | if (!err) | ||
1573 | err = add_callchain_ip(thread, parent, root_al, | ||
1574 | true, be[i].from); | ||
1575 | if (err == -EINVAL) | ||
1576 | break; | ||
1577 | if (err) | ||
1578 | return err; | ||
1579 | } | ||
1580 | chain_nr -= nr; | ||
1581 | } | ||
1582 | |||
1583 | check_calls: | ||
1390 | if (chain->nr > PERF_MAX_STACK_DEPTH) { | 1584 | if (chain->nr > PERF_MAX_STACK_DEPTH) { |
1391 | pr_warning("corrupted callchain. skipping...\n"); | 1585 | pr_warning("corrupted callchain. skipping...\n"); |
1392 | return 0; | 1586 | return 0; |
1393 | } | 1587 | } |
1394 | 1588 | ||
1395 | /* | 1589 | for (i = first_call; i < chain_nr; i++) { |
1396 | * Based on DWARF debug information, some architectures skip | ||
1397 | * a callchain entry saved by the kernel. | ||
1398 | */ | ||
1399 | skip_idx = arch_skip_callchain_idx(machine, thread, chain); | ||
1400 | |||
1401 | for (i = 0; i < chain_nr; i++) { | ||
1402 | u64 ip; | 1590 | u64 ip; |
1403 | struct addr_location al; | ||
1404 | 1591 | ||
1405 | if (callchain_param.order == ORDER_CALLEE) | 1592 | if (callchain_param.order == ORDER_CALLEE) |
1406 | j = i; | 1593 | j = i; |
@@ -1413,50 +1600,10 @@ static int machine__resolve_callchain_sample(struct machine *machine, | |||
1413 | #endif | 1600 | #endif |
1414 | ip = chain->ips[j]; | 1601 | ip = chain->ips[j]; |
1415 | 1602 | ||
1416 | if (ip >= PERF_CONTEXT_MAX) { | 1603 | err = add_callchain_ip(thread, parent, root_al, false, ip); |
1417 | switch (ip) { | ||
1418 | case PERF_CONTEXT_HV: | ||
1419 | cpumode = PERF_RECORD_MISC_HYPERVISOR; | ||
1420 | break; | ||
1421 | case PERF_CONTEXT_KERNEL: | ||
1422 | cpumode = PERF_RECORD_MISC_KERNEL; | ||
1423 | break; | ||
1424 | case PERF_CONTEXT_USER: | ||
1425 | cpumode = PERF_RECORD_MISC_USER; | ||
1426 | break; | ||
1427 | default: | ||
1428 | pr_debug("invalid callchain context: " | ||
1429 | "%"PRId64"\n", (s64) ip); | ||
1430 | /* | ||
1431 | * It seems the callchain is corrupted. | ||
1432 | * Discard all. | ||
1433 | */ | ||
1434 | callchain_cursor_reset(&callchain_cursor); | ||
1435 | return 0; | ||
1436 | } | ||
1437 | continue; | ||
1438 | } | ||
1439 | 1604 | ||
1440 | al.filtered = 0; | ||
1441 | thread__find_addr_location(thread, machine, cpumode, | ||
1442 | MAP__FUNCTION, ip, &al); | ||
1443 | if (al.sym != NULL) { | ||
1444 | if (sort__has_parent && !*parent && | ||
1445 | symbol__match_regex(al.sym, &parent_regex)) | ||
1446 | *parent = al.sym; | ||
1447 | else if (have_ignore_callees && root_al && | ||
1448 | symbol__match_regex(al.sym, &ignore_callees_regex)) { | ||
1449 | /* Treat this symbol as the root, | ||
1450 | forgetting its callees. */ | ||
1451 | *root_al = al; | ||
1452 | callchain_cursor_reset(&callchain_cursor); | ||
1453 | } | ||
1454 | } | ||
1455 | |||
1456 | err = callchain_cursor_append(&callchain_cursor, | ||
1457 | ip, al.map, al.sym); | ||
1458 | if (err) | 1605 | if (err) |
1459 | return err; | 1606 | return (err < 0) ? err : 0; |
1460 | } | 1607 | } |
1461 | 1608 | ||
1462 | return 0; | 1609 | return 0; |
@@ -1469,19 +1616,16 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) | |||
1469 | entry->map, entry->sym); | 1616 | entry->map, entry->sym); |
1470 | } | 1617 | } |
1471 | 1618 | ||
1472 | int machine__resolve_callchain(struct machine *machine, | 1619 | int thread__resolve_callchain(struct thread *thread, |
1473 | struct perf_evsel *evsel, | 1620 | struct perf_evsel *evsel, |
1474 | struct thread *thread, | 1621 | struct perf_sample *sample, |
1475 | struct perf_sample *sample, | 1622 | struct symbol **parent, |
1476 | struct symbol **parent, | 1623 | struct addr_location *root_al, |
1477 | struct addr_location *root_al, | 1624 | int max_stack) |
1478 | int max_stack) | ||
1479 | { | 1625 | { |
1480 | int ret; | 1626 | int ret = thread__resolve_callchain_sample(thread, sample->callchain, |
1481 | 1627 | sample->branch_stack, | |
1482 | ret = machine__resolve_callchain_sample(machine, thread, | 1628 | parent, root_al, max_stack); |
1483 | sample->callchain, parent, | ||
1484 | root_al, max_stack); | ||
1485 | if (ret) | 1629 | if (ret) |
1486 | return ret; | 1630 | return ret; |
1487 | 1631 | ||
@@ -1495,7 +1639,7 @@ int machine__resolve_callchain(struct machine *machine, | |||
1495 | (!sample->user_stack.size)) | 1639 | (!sample->user_stack.size)) |
1496 | return 0; | 1640 | return 0; |
1497 | 1641 | ||
1498 | return unwind__get_entries(unwind_entry, &callchain_cursor, machine, | 1642 | return unwind__get_entries(unwind_entry, &callchain_cursor, |
1499 | thread, sample, max_stack); | 1643 | thread, sample, max_stack); |
1500 | 1644 | ||
1501 | } | 1645 | } |
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 2b651a7f5d0d..e8b7779a0a3f 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h | |||
@@ -40,6 +40,10 @@ struct machine { | |||
40 | u64 kernel_start; | 40 | u64 kernel_start; |
41 | symbol_filter_t symbol_filter; | 41 | symbol_filter_t symbol_filter; |
42 | pid_t *current_tid; | 42 | pid_t *current_tid; |
43 | union { /* Tool specific area */ | ||
44 | void *priv; | ||
45 | u64 db_id; | ||
46 | }; | ||
43 | }; | 47 | }; |
44 | 48 | ||
45 | static inline | 49 | static inline |
@@ -122,13 +126,12 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample, | |||
122 | struct addr_location *al); | 126 | struct addr_location *al); |
123 | struct mem_info *sample__resolve_mem(struct perf_sample *sample, | 127 | struct mem_info *sample__resolve_mem(struct perf_sample *sample, |
124 | struct addr_location *al); | 128 | struct addr_location *al); |
125 | int machine__resolve_callchain(struct machine *machine, | 129 | int thread__resolve_callchain(struct thread *thread, |
126 | struct perf_evsel *evsel, | 130 | struct perf_evsel *evsel, |
127 | struct thread *thread, | 131 | struct perf_sample *sample, |
128 | struct perf_sample *sample, | 132 | struct symbol **parent, |
129 | struct symbol **parent, | 133 | struct addr_location *root_al, |
130 | struct addr_location *root_al, | 134 | int max_stack); |
131 | int max_stack); | ||
132 | 135 | ||
133 | /* | 136 | /* |
134 | * Default guest kernel is defined by parameter --guestkallsyms | 137 | * Default guest kernel is defined by parameter --guestkallsyms |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 2137c4596ec7..62ca9f2607d5 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -360,7 +360,7 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix, | |||
360 | 360 | ||
361 | if (map && map->dso) { | 361 | if (map && map->dso) { |
362 | srcline = get_srcline(map->dso, | 362 | srcline = get_srcline(map->dso, |
363 | map__rip_2objdump(map, addr)); | 363 | map__rip_2objdump(map, addr), NULL, true); |
364 | if (srcline != SRCLINE_UNKNOWN) | 364 | if (srcline != SRCLINE_UNKNOWN) |
365 | ret = fprintf(fp, "%s%s", prefix, srcline); | 365 | ret = fprintf(fp, "%s%s", prefix, srcline); |
366 | free_srcline(srcline); | 366 | free_srcline(srcline); |
@@ -413,14 +413,14 @@ u64 map__objdump_2mem(struct map *map, u64 ip) | |||
413 | return ip + map->reloc; | 413 | return ip + map->reloc; |
414 | } | 414 | } |
415 | 415 | ||
416 | void map_groups__init(struct map_groups *mg) | 416 | void map_groups__init(struct map_groups *mg, struct machine *machine) |
417 | { | 417 | { |
418 | int i; | 418 | int i; |
419 | for (i = 0; i < MAP__NR_TYPES; ++i) { | 419 | for (i = 0; i < MAP__NR_TYPES; ++i) { |
420 | mg->maps[i] = RB_ROOT; | 420 | mg->maps[i] = RB_ROOT; |
421 | INIT_LIST_HEAD(&mg->removed_maps[i]); | 421 | INIT_LIST_HEAD(&mg->removed_maps[i]); |
422 | } | 422 | } |
423 | mg->machine = NULL; | 423 | mg->machine = machine; |
424 | mg->refcnt = 1; | 424 | mg->refcnt = 1; |
425 | } | 425 | } |
426 | 426 | ||
@@ -471,12 +471,12 @@ bool map_groups__empty(struct map_groups *mg) | |||
471 | return true; | 471 | return true; |
472 | } | 472 | } |
473 | 473 | ||
474 | struct map_groups *map_groups__new(void) | 474 | struct map_groups *map_groups__new(struct machine *machine) |
475 | { | 475 | { |
476 | struct map_groups *mg = malloc(sizeof(*mg)); | 476 | struct map_groups *mg = malloc(sizeof(*mg)); |
477 | 477 | ||
478 | if (mg != NULL) | 478 | if (mg != NULL) |
479 | map_groups__init(mg); | 479 | map_groups__init(mg, machine); |
480 | 480 | ||
481 | return mg; | 481 | return mg; |
482 | } | 482 | } |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 2f83954af050..6951a9d42339 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
@@ -64,7 +64,7 @@ struct map_groups { | |||
64 | int refcnt; | 64 | int refcnt; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | struct map_groups *map_groups__new(void); | 67 | struct map_groups *map_groups__new(struct machine *machine); |
68 | void map_groups__delete(struct map_groups *mg); | 68 | void map_groups__delete(struct map_groups *mg); |
69 | bool map_groups__empty(struct map_groups *mg); | 69 | bool map_groups__empty(struct map_groups *mg); |
70 | 70 | ||
@@ -150,7 +150,7 @@ void maps__remove(struct rb_root *maps, struct map *map); | |||
150 | struct map *maps__find(struct rb_root *maps, u64 addr); | 150 | struct map *maps__find(struct rb_root *maps, u64 addr); |
151 | struct map *maps__first(struct rb_root *maps); | 151 | struct map *maps__first(struct rb_root *maps); |
152 | struct map *maps__next(struct map *map); | 152 | struct map *maps__next(struct map *map); |
153 | void map_groups__init(struct map_groups *mg); | 153 | void map_groups__init(struct map_groups *mg, struct machine *machine); |
154 | void map_groups__exit(struct map_groups *mg); | 154 | void map_groups__exit(struct map_groups *mg); |
155 | int map_groups__clone(struct map_groups *mg, | 155 | int map_groups__clone(struct map_groups *mg, |
156 | struct map_groups *parent, enum map_type type); | 156 | struct map_groups *parent, enum map_type type); |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index c659a3ca1283..77b43fe43d55 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -681,6 +681,8 @@ int parse_events_add_pmu(struct list_head *list, int *idx, | |||
681 | if (evsel) { | 681 | if (evsel) { |
682 | evsel->unit = info.unit; | 682 | evsel->unit = info.unit; |
683 | evsel->scale = info.scale; | 683 | evsel->scale = info.scale; |
684 | evsel->per_pkg = info.per_pkg; | ||
685 | evsel->snapshot = info.snapshot; | ||
684 | } | 686 | } |
685 | 687 | ||
686 | return evsel ? 0 : -ENOMEM; | 688 | return evsel ? 0 : -ENOMEM; |
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index bf48092983c6..f62dee7bd924 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c | |||
@@ -42,7 +42,26 @@ static int get_value(struct parse_opt_ctx_t *p, | |||
42 | return opterror(opt, "takes no value", flags); | 42 | return opterror(opt, "takes no value", flags); |
43 | if (unset && (opt->flags & PARSE_OPT_NONEG)) | 43 | if (unset && (opt->flags & PARSE_OPT_NONEG)) |
44 | return opterror(opt, "isn't available", flags); | 44 | return opterror(opt, "isn't available", flags); |
45 | 45 | if (opt->flags & PARSE_OPT_DISABLED) | |
46 | return opterror(opt, "is not usable", flags); | ||
47 | |||
48 | if (opt->flags & PARSE_OPT_EXCLUSIVE) { | ||
49 | if (p->excl_opt) { | ||
50 | char msg[128]; | ||
51 | |||
52 | if (((flags & OPT_SHORT) && p->excl_opt->short_name) || | ||
53 | p->excl_opt->long_name == NULL) { | ||
54 | scnprintf(msg, sizeof(msg), "cannot be used with switch `%c'", | ||
55 | p->excl_opt->short_name); | ||
56 | } else { | ||
57 | scnprintf(msg, sizeof(msg), "cannot be used with %s", | ||
58 | p->excl_opt->long_name); | ||
59 | } | ||
60 | opterror(opt, msg, flags); | ||
61 | return -3; | ||
62 | } | ||
63 | p->excl_opt = opt; | ||
64 | } | ||
46 | if (!(flags & OPT_SHORT) && p->opt) { | 65 | if (!(flags & OPT_SHORT) && p->opt) { |
47 | switch (opt->type) { | 66 | switch (opt->type) { |
48 | case OPTION_CALLBACK: | 67 | case OPTION_CALLBACK: |
@@ -343,13 +362,14 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
343 | const char * const usagestr[]) | 362 | const char * const usagestr[]) |
344 | { | 363 | { |
345 | int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); | 364 | int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); |
365 | int excl_short_opt = 1; | ||
366 | const char *arg; | ||
346 | 367 | ||
347 | /* we must reset ->opt, unknown short option leave it dangling */ | 368 | /* we must reset ->opt, unknown short option leave it dangling */ |
348 | ctx->opt = NULL; | 369 | ctx->opt = NULL; |
349 | 370 | ||
350 | for (; ctx->argc; ctx->argc--, ctx->argv++) { | 371 | for (; ctx->argc; ctx->argc--, ctx->argv++) { |
351 | const char *arg = ctx->argv[0]; | 372 | arg = ctx->argv[0]; |
352 | |||
353 | if (*arg != '-' || !arg[1]) { | 373 | if (*arg != '-' || !arg[1]) { |
354 | if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) | 374 | if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) |
355 | break; | 375 | break; |
@@ -358,19 +378,21 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
358 | } | 378 | } |
359 | 379 | ||
360 | if (arg[1] != '-') { | 380 | if (arg[1] != '-') { |
361 | ctx->opt = arg + 1; | 381 | ctx->opt = ++arg; |
362 | if (internal_help && *ctx->opt == 'h') | 382 | if (internal_help && *ctx->opt == 'h') |
363 | return usage_with_options_internal(usagestr, options, 0); | 383 | return usage_with_options_internal(usagestr, options, 0); |
364 | switch (parse_short_opt(ctx, options)) { | 384 | switch (parse_short_opt(ctx, options)) { |
365 | case -1: | 385 | case -1: |
366 | return parse_options_usage(usagestr, options, arg + 1, 1); | 386 | return parse_options_usage(usagestr, options, arg, 1); |
367 | case -2: | 387 | case -2: |
368 | goto unknown; | 388 | goto unknown; |
389 | case -3: | ||
390 | goto exclusive; | ||
369 | default: | 391 | default: |
370 | break; | 392 | break; |
371 | } | 393 | } |
372 | if (ctx->opt) | 394 | if (ctx->opt) |
373 | check_typos(arg + 1, options); | 395 | check_typos(arg, options); |
374 | while (ctx->opt) { | 396 | while (ctx->opt) { |
375 | if (internal_help && *ctx->opt == 'h') | 397 | if (internal_help && *ctx->opt == 'h') |
376 | return usage_with_options_internal(usagestr, options, 0); | 398 | return usage_with_options_internal(usagestr, options, 0); |
@@ -387,6 +409,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
387 | ctx->argv[0] = strdup(ctx->opt - 1); | 409 | ctx->argv[0] = strdup(ctx->opt - 1); |
388 | *(char *)ctx->argv[0] = '-'; | 410 | *(char *)ctx->argv[0] = '-'; |
389 | goto unknown; | 411 | goto unknown; |
412 | case -3: | ||
413 | goto exclusive; | ||
390 | default: | 414 | default: |
391 | break; | 415 | break; |
392 | } | 416 | } |
@@ -402,19 +426,23 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
402 | break; | 426 | break; |
403 | } | 427 | } |
404 | 428 | ||
405 | if (internal_help && !strcmp(arg + 2, "help-all")) | 429 | arg += 2; |
430 | if (internal_help && !strcmp(arg, "help-all")) | ||
406 | return usage_with_options_internal(usagestr, options, 1); | 431 | return usage_with_options_internal(usagestr, options, 1); |
407 | if (internal_help && !strcmp(arg + 2, "help")) | 432 | if (internal_help && !strcmp(arg, "help")) |
408 | return usage_with_options_internal(usagestr, options, 0); | 433 | return usage_with_options_internal(usagestr, options, 0); |
409 | if (!strcmp(arg + 2, "list-opts")) | 434 | if (!strcmp(arg, "list-opts")) |
410 | return PARSE_OPT_LIST_OPTS; | 435 | return PARSE_OPT_LIST_OPTS; |
411 | if (!strcmp(arg + 2, "list-cmds")) | 436 | if (!strcmp(arg, "list-cmds")) |
412 | return PARSE_OPT_LIST_SUBCMDS; | 437 | return PARSE_OPT_LIST_SUBCMDS; |
413 | switch (parse_long_opt(ctx, arg + 2, options)) { | 438 | switch (parse_long_opt(ctx, arg, options)) { |
414 | case -1: | 439 | case -1: |
415 | return parse_options_usage(usagestr, options, arg + 2, 0); | 440 | return parse_options_usage(usagestr, options, arg, 0); |
416 | case -2: | 441 | case -2: |
417 | goto unknown; | 442 | goto unknown; |
443 | case -3: | ||
444 | excl_short_opt = 0; | ||
445 | goto exclusive; | ||
418 | default: | 446 | default: |
419 | break; | 447 | break; |
420 | } | 448 | } |
@@ -426,6 +454,17 @@ unknown: | |||
426 | ctx->opt = NULL; | 454 | ctx->opt = NULL; |
427 | } | 455 | } |
428 | return PARSE_OPT_DONE; | 456 | return PARSE_OPT_DONE; |
457 | |||
458 | exclusive: | ||
459 | parse_options_usage(usagestr, options, arg, excl_short_opt); | ||
460 | if ((excl_short_opt && ctx->excl_opt->short_name) || | ||
461 | ctx->excl_opt->long_name == NULL) { | ||
462 | char opt = ctx->excl_opt->short_name; | ||
463 | parse_options_usage(NULL, options, &opt, 1); | ||
464 | } else { | ||
465 | parse_options_usage(NULL, options, ctx->excl_opt->long_name, 0); | ||
466 | } | ||
467 | return PARSE_OPT_HELP; | ||
429 | } | 468 | } |
430 | 469 | ||
431 | int parse_options_end(struct parse_opt_ctx_t *ctx) | 470 | int parse_options_end(struct parse_opt_ctx_t *ctx) |
@@ -509,6 +548,8 @@ static void print_option_help(const struct option *opts, int full) | |||
509 | } | 548 | } |
510 | if (!full && (opts->flags & PARSE_OPT_HIDDEN)) | 549 | if (!full && (opts->flags & PARSE_OPT_HIDDEN)) |
511 | return; | 550 | return; |
551 | if (opts->flags & PARSE_OPT_DISABLED) | ||
552 | return; | ||
512 | 553 | ||
513 | pos = fprintf(stderr, " "); | 554 | pos = fprintf(stderr, " "); |
514 | if (opts->short_name) | 555 | if (opts->short_name) |
@@ -679,3 +720,16 @@ int parse_opt_verbosity_cb(const struct option *opt, | |||
679 | } | 720 | } |
680 | return 0; | 721 | return 0; |
681 | } | 722 | } |
723 | |||
724 | void set_option_flag(struct option *opts, int shortopt, const char *longopt, | ||
725 | int flag) | ||
726 | { | ||
727 | for (; opts->type != OPTION_END; opts++) { | ||
728 | if ((shortopt && opts->short_name == shortopt) || | ||
729 | (opts->long_name && longopt && | ||
730 | !strcmp(opts->long_name, longopt))) { | ||
731 | opts->flags |= flag; | ||
732 | break; | ||
733 | } | ||
734 | } | ||
735 | } | ||
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index b59ba858e73d..97b153fb4999 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h | |||
@@ -38,6 +38,8 @@ enum parse_opt_option_flags { | |||
38 | PARSE_OPT_NONEG = 4, | 38 | PARSE_OPT_NONEG = 4, |
39 | PARSE_OPT_HIDDEN = 8, | 39 | PARSE_OPT_HIDDEN = 8, |
40 | PARSE_OPT_LASTARG_DEFAULT = 16, | 40 | PARSE_OPT_LASTARG_DEFAULT = 16, |
41 | PARSE_OPT_DISABLED = 32, | ||
42 | PARSE_OPT_EXCLUSIVE = 64, | ||
41 | }; | 43 | }; |
42 | 44 | ||
43 | struct option; | 45 | struct option; |
@@ -173,6 +175,7 @@ struct parse_opt_ctx_t { | |||
173 | const char **out; | 175 | const char **out; |
174 | int argc, cpidx; | 176 | int argc, cpidx; |
175 | const char *opt; | 177 | const char *opt; |
178 | const struct option *excl_opt; | ||
176 | int flags; | 179 | int flags; |
177 | }; | 180 | }; |
178 | 181 | ||
@@ -211,4 +214,5 @@ extern int parse_opt_verbosity_cb(const struct option *, const char *, int); | |||
211 | 214 | ||
212 | extern const char *parse_options_fix_filename(const char *prefix, const char *file); | 215 | extern const char *parse_options_fix_filename(const char *prefix, const char *file); |
213 | 216 | ||
217 | void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag); | ||
214 | #endif /* __PERF_PARSE_OPTIONS_H */ | 218 | #endif /* __PERF_PARSE_OPTIONS_H */ |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index e243ad962a4d..5c9c4947cfb4 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
@@ -163,6 +163,41 @@ error: | |||
163 | return -1; | 163 | return -1; |
164 | } | 164 | } |
165 | 165 | ||
166 | static int | ||
167 | perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name) | ||
168 | { | ||
169 | char path[PATH_MAX]; | ||
170 | int fd; | ||
171 | |||
172 | snprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name); | ||
173 | |||
174 | fd = open(path, O_RDONLY); | ||
175 | if (fd == -1) | ||
176 | return -1; | ||
177 | |||
178 | close(fd); | ||
179 | |||
180 | alias->per_pkg = true; | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, | ||
185 | char *dir, char *name) | ||
186 | { | ||
187 | char path[PATH_MAX]; | ||
188 | int fd; | ||
189 | |||
190 | snprintf(path, PATH_MAX, "%s/%s.snapshot", dir, name); | ||
191 | |||
192 | fd = open(path, O_RDONLY); | ||
193 | if (fd == -1) | ||
194 | return -1; | ||
195 | |||
196 | alias->snapshot = true; | ||
197 | close(fd); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
166 | static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file) | 201 | static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file) |
167 | { | 202 | { |
168 | struct perf_pmu_alias *alias; | 203 | struct perf_pmu_alias *alias; |
@@ -181,6 +216,7 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI | |||
181 | INIT_LIST_HEAD(&alias->terms); | 216 | INIT_LIST_HEAD(&alias->terms); |
182 | alias->scale = 1.0; | 217 | alias->scale = 1.0; |
183 | alias->unit[0] = '\0'; | 218 | alias->unit[0] = '\0'; |
219 | alias->per_pkg = false; | ||
184 | 220 | ||
185 | ret = parse_events_terms(&alias->terms, buf); | 221 | ret = parse_events_terms(&alias->terms, buf); |
186 | if (ret) { | 222 | if (ret) { |
@@ -194,6 +230,8 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI | |||
194 | */ | 230 | */ |
195 | perf_pmu__parse_unit(alias, dir, name); | 231 | perf_pmu__parse_unit(alias, dir, name); |
196 | perf_pmu__parse_scale(alias, dir, name); | 232 | perf_pmu__parse_scale(alias, dir, name); |
233 | perf_pmu__parse_per_pkg(alias, dir, name); | ||
234 | perf_pmu__parse_snapshot(alias, dir, name); | ||
197 | 235 | ||
198 | list_add_tail(&alias->list, list); | 236 | list_add_tail(&alias->list, list); |
199 | 237 | ||
@@ -209,6 +247,10 @@ static inline bool pmu_alias_info_file(char *name) | |||
209 | return true; | 247 | return true; |
210 | if (len > 6 && !strcmp(name + len - 6, ".scale")) | 248 | if (len > 6 && !strcmp(name + len - 6, ".scale")) |
211 | return true; | 249 | return true; |
250 | if (len > 8 && !strcmp(name + len - 8, ".per-pkg")) | ||
251 | return true; | ||
252 | if (len > 9 && !strcmp(name + len - 9, ".snapshot")) | ||
253 | return true; | ||
212 | 254 | ||
213 | return false; | 255 | return false; |
214 | } | 256 | } |
@@ -617,23 +659,27 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, | |||
617 | } | 659 | } |
618 | 660 | ||
619 | 661 | ||
620 | static int check_unit_scale(struct perf_pmu_alias *alias, | 662 | static int check_info_data(struct perf_pmu_alias *alias, |
621 | const char **unit, double *scale) | 663 | struct perf_pmu_info *info) |
622 | { | 664 | { |
623 | /* | 665 | /* |
624 | * Only one term in event definition can | 666 | * Only one term in event definition can |
625 | * define unit and scale, fail if there's | 667 | * define unit, scale and snapshot, fail |
626 | * more than one. | 668 | * if there's more than one. |
627 | */ | 669 | */ |
628 | if ((*unit && alias->unit) || | 670 | if ((info->unit && alias->unit) || |
629 | (*scale && alias->scale)) | 671 | (info->scale && alias->scale) || |
672 | (info->snapshot && alias->snapshot)) | ||
630 | return -EINVAL; | 673 | return -EINVAL; |
631 | 674 | ||
632 | if (alias->unit) | 675 | if (alias->unit) |
633 | *unit = alias->unit; | 676 | info->unit = alias->unit; |
634 | 677 | ||
635 | if (alias->scale) | 678 | if (alias->scale) |
636 | *scale = alias->scale; | 679 | info->scale = alias->scale; |
680 | |||
681 | if (alias->snapshot) | ||
682 | info->snapshot = alias->snapshot; | ||
637 | 683 | ||
638 | return 0; | 684 | return 0; |
639 | } | 685 | } |
@@ -649,12 +695,15 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, | |||
649 | struct perf_pmu_alias *alias; | 695 | struct perf_pmu_alias *alias; |
650 | int ret; | 696 | int ret; |
651 | 697 | ||
698 | info->per_pkg = false; | ||
699 | |||
652 | /* | 700 | /* |
653 | * Mark unit and scale as not set | 701 | * Mark unit and scale as not set |
654 | * (different from default values, see below) | 702 | * (different from default values, see below) |
655 | */ | 703 | */ |
656 | info->unit = NULL; | 704 | info->unit = NULL; |
657 | info->scale = 0.0; | 705 | info->scale = 0.0; |
706 | info->snapshot = false; | ||
658 | 707 | ||
659 | list_for_each_entry_safe(term, h, head_terms, list) { | 708 | list_for_each_entry_safe(term, h, head_terms, list) { |
660 | alias = pmu_find_alias(pmu, term); | 709 | alias = pmu_find_alias(pmu, term); |
@@ -664,10 +713,13 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, | |||
664 | if (ret) | 713 | if (ret) |
665 | return ret; | 714 | return ret; |
666 | 715 | ||
667 | ret = check_unit_scale(alias, &info->unit, &info->scale); | 716 | ret = check_info_data(alias, info); |
668 | if (ret) | 717 | if (ret) |
669 | return ret; | 718 | return ret; |
670 | 719 | ||
720 | if (alias->per_pkg) | ||
721 | info->per_pkg = true; | ||
722 | |||
671 | list_del(&term->list); | 723 | list_del(&term->list); |
672 | free(term); | 724 | free(term); |
673 | } | 725 | } |
@@ -747,15 +799,18 @@ void print_pmu_events(const char *event_glob, bool name_only) | |||
747 | 799 | ||
748 | pmu = NULL; | 800 | pmu = NULL; |
749 | len = 0; | 801 | len = 0; |
750 | while ((pmu = perf_pmu__scan(pmu)) != NULL) | 802 | while ((pmu = perf_pmu__scan(pmu)) != NULL) { |
751 | list_for_each_entry(alias, &pmu->aliases, list) | 803 | list_for_each_entry(alias, &pmu->aliases, list) |
752 | len++; | 804 | len++; |
753 | aliases = malloc(sizeof(char *) * len); | 805 | if (pmu->selectable) |
806 | len++; | ||
807 | } | ||
808 | aliases = zalloc(sizeof(char *) * len); | ||
754 | if (!aliases) | 809 | if (!aliases) |
755 | return; | 810 | goto out_enomem; |
756 | pmu = NULL; | 811 | pmu = NULL; |
757 | j = 0; | 812 | j = 0; |
758 | while ((pmu = perf_pmu__scan(pmu)) != NULL) | 813 | while ((pmu = perf_pmu__scan(pmu)) != NULL) { |
759 | list_for_each_entry(alias, &pmu->aliases, list) { | 814 | list_for_each_entry(alias, &pmu->aliases, list) { |
760 | char *name = format_alias(buf, sizeof(buf), pmu, alias); | 815 | char *name = format_alias(buf, sizeof(buf), pmu, alias); |
761 | bool is_cpu = !strcmp(pmu->name, "cpu"); | 816 | bool is_cpu = !strcmp(pmu->name, "cpu"); |
@@ -765,13 +820,23 @@ void print_pmu_events(const char *event_glob, bool name_only) | |||
765 | (!is_cpu && strglobmatch(alias->name, | 820 | (!is_cpu && strglobmatch(alias->name, |
766 | event_glob)))) | 821 | event_glob)))) |
767 | continue; | 822 | continue; |
768 | aliases[j] = name; | 823 | |
769 | if (is_cpu && !name_only) | 824 | if (is_cpu && !name_only) |
770 | aliases[j] = format_alias_or(buf, sizeof(buf), | 825 | name = format_alias_or(buf, sizeof(buf), pmu, alias); |
771 | pmu, alias); | 826 | |
772 | aliases[j] = strdup(aliases[j]); | 827 | aliases[j] = strdup(name); |
828 | if (aliases[j] == NULL) | ||
829 | goto out_enomem; | ||
773 | j++; | 830 | j++; |
774 | } | 831 | } |
832 | if (pmu->selectable) { | ||
833 | char *s; | ||
834 | if (asprintf(&s, "%s//", pmu->name) < 0) | ||
835 | goto out_enomem; | ||
836 | aliases[j] = s; | ||
837 | j++; | ||
838 | } | ||
839 | } | ||
775 | len = j; | 840 | len = j; |
776 | qsort(aliases, len, sizeof(char *), cmp_string); | 841 | qsort(aliases, len, sizeof(char *), cmp_string); |
777 | for (j = 0; j < len; j++) { | 842 | for (j = 0; j < len; j++) { |
@@ -780,12 +845,20 @@ void print_pmu_events(const char *event_glob, bool name_only) | |||
780 | continue; | 845 | continue; |
781 | } | 846 | } |
782 | printf(" %-50s [Kernel PMU event]\n", aliases[j]); | 847 | printf(" %-50s [Kernel PMU event]\n", aliases[j]); |
783 | zfree(&aliases[j]); | ||
784 | printed++; | 848 | printed++; |
785 | } | 849 | } |
786 | if (printed) | 850 | if (printed) |
787 | printf("\n"); | 851 | printf("\n"); |
788 | free(aliases); | 852 | out_free: |
853 | for (j = 0; j < len; j++) | ||
854 | zfree(&aliases[j]); | ||
855 | zfree(&aliases); | ||
856 | return; | ||
857 | |||
858 | out_enomem: | ||
859 | printf("FATAL: not enough memory to print PMU events\n"); | ||
860 | if (aliases) | ||
861 | goto out_free; | ||
789 | } | 862 | } |
790 | 863 | ||
791 | bool pmu_have_event(const char *pname, const char *name) | 864 | bool pmu_have_event(const char *pname, const char *name) |
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index fe9dfbee8eed..6b1249fbdb5f 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h | |||
@@ -18,6 +18,7 @@ struct perf_event_attr; | |||
18 | struct perf_pmu { | 18 | struct perf_pmu { |
19 | char *name; | 19 | char *name; |
20 | __u32 type; | 20 | __u32 type; |
21 | bool selectable; | ||
21 | struct perf_event_attr *default_config; | 22 | struct perf_event_attr *default_config; |
22 | struct cpu_map *cpus; | 23 | struct cpu_map *cpus; |
23 | struct list_head format; /* HEAD struct perf_pmu_format -> list */ | 24 | struct list_head format; /* HEAD struct perf_pmu_format -> list */ |
@@ -28,6 +29,8 @@ struct perf_pmu { | |||
28 | struct perf_pmu_info { | 29 | struct perf_pmu_info { |
29 | const char *unit; | 30 | const char *unit; |
30 | double scale; | 31 | double scale; |
32 | bool per_pkg; | ||
33 | bool snapshot; | ||
31 | }; | 34 | }; |
32 | 35 | ||
33 | #define UNIT_MAX_LEN 31 /* max length for event unit name */ | 36 | #define UNIT_MAX_LEN 31 /* max length for event unit name */ |
@@ -38,6 +41,8 @@ struct perf_pmu_alias { | |||
38 | struct list_head list; /* ELEM */ | 41 | struct list_head list; /* ELEM */ |
39 | char unit[UNIT_MAX_LEN+1]; | 42 | char unit[UNIT_MAX_LEN+1]; |
40 | double scale; | 43 | double scale; |
44 | bool per_pkg; | ||
45 | bool snapshot; | ||
41 | }; | 46 | }; |
42 | 47 | ||
43 | struct perf_pmu *perf_pmu__find(const char *name); | 48 | struct perf_pmu *perf_pmu__find(const char *name); |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index c150ca4343eb..94a717bf007d 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -495,9 +495,11 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | |||
495 | } | 495 | } |
496 | 496 | ||
497 | if (ntevs == 0) { /* No error but failed to find probe point. */ | 497 | if (ntevs == 0) { /* No error but failed to find probe point. */ |
498 | pr_warning("Probe point '%s' not found.\n", | 498 | pr_warning("Probe point '%s' not found in debuginfo.\n", |
499 | synthesize_perf_probe_point(&pev->point)); | 499 | synthesize_perf_probe_point(&pev->point)); |
500 | return -ENOENT; | 500 | if (need_dwarf) |
501 | return -ENOENT; | ||
502 | return 0; | ||
501 | } | 503 | } |
502 | /* Error path : ntevs < 0 */ | 504 | /* Error path : ntevs < 0 */ |
503 | pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); | 505 | pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); |
@@ -1910,21 +1912,21 @@ static int show_perf_probe_event(struct perf_probe_event *pev, | |||
1910 | if (ret < 0) | 1912 | if (ret < 0) |
1911 | return ret; | 1913 | return ret; |
1912 | 1914 | ||
1913 | printf(" %-20s (on %s", buf, place); | 1915 | pr_info(" %-20s (on %s", buf, place); |
1914 | if (module) | 1916 | if (module) |
1915 | printf(" in %s", module); | 1917 | pr_info(" in %s", module); |
1916 | 1918 | ||
1917 | if (pev->nargs > 0) { | 1919 | if (pev->nargs > 0) { |
1918 | printf(" with"); | 1920 | pr_info(" with"); |
1919 | for (i = 0; i < pev->nargs; i++) { | 1921 | for (i = 0; i < pev->nargs; i++) { |
1920 | ret = synthesize_perf_probe_arg(&pev->args[i], | 1922 | ret = synthesize_perf_probe_arg(&pev->args[i], |
1921 | buf, 128); | 1923 | buf, 128); |
1922 | if (ret < 0) | 1924 | if (ret < 0) |
1923 | break; | 1925 | break; |
1924 | printf(" %s", buf); | 1926 | pr_info(" %s", buf); |
1925 | } | 1927 | } |
1926 | } | 1928 | } |
1927 | printf(")\n"); | 1929 | pr_info(")\n"); |
1928 | free(place); | 1930 | free(place); |
1929 | return ret; | 1931 | return ret; |
1930 | } | 1932 | } |
@@ -2050,9 +2052,11 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev) | |||
2050 | pr_debug("Writing event: %s\n", buf); | 2052 | pr_debug("Writing event: %s\n", buf); |
2051 | if (!probe_event_dry_run) { | 2053 | if (!probe_event_dry_run) { |
2052 | ret = write(fd, buf, strlen(buf)); | 2054 | ret = write(fd, buf, strlen(buf)); |
2053 | if (ret <= 0) | 2055 | if (ret <= 0) { |
2056 | ret = -errno; | ||
2054 | pr_warning("Failed to write event: %s\n", | 2057 | pr_warning("Failed to write event: %s\n", |
2055 | strerror_r(errno, sbuf, sizeof(sbuf))); | 2058 | strerror_r(errno, sbuf, sizeof(sbuf))); |
2059 | } | ||
2056 | } | 2060 | } |
2057 | free(buf); | 2061 | free(buf); |
2058 | return ret; | 2062 | return ret; |
@@ -2124,7 +2128,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev, | |||
2124 | } | 2128 | } |
2125 | 2129 | ||
2126 | ret = 0; | 2130 | ret = 0; |
2127 | printf("Added new event%s\n", (ntevs > 1) ? "s:" : ":"); | 2131 | pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":"); |
2128 | for (i = 0; i < ntevs; i++) { | 2132 | for (i = 0; i < ntevs; i++) { |
2129 | tev = &tevs[i]; | 2133 | tev = &tevs[i]; |
2130 | if (pev->event) | 2134 | if (pev->event) |
@@ -2179,8 +2183,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev, | |||
2179 | 2183 | ||
2180 | if (ret >= 0) { | 2184 | if (ret >= 0) { |
2181 | /* Show how to use the event. */ | 2185 | /* Show how to use the event. */ |
2182 | printf("\nYou can now use it in all perf tools, such as:\n\n"); | 2186 | pr_info("\nYou can now use it in all perf tools, such as:\n\n"); |
2183 | printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, | 2187 | pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, |
2184 | tev->event); | 2188 | tev->event); |
2185 | } | 2189 | } |
2186 | 2190 | ||
@@ -2444,7 +2448,7 @@ static int __del_trace_probe_event(int fd, struct str_node *ent) | |||
2444 | goto error; | 2448 | goto error; |
2445 | } | 2449 | } |
2446 | 2450 | ||
2447 | printf("Removed event: %s\n", ent->s); | 2451 | pr_info("Removed event: %s\n", ent->s); |
2448 | return 0; | 2452 | return 0; |
2449 | error: | 2453 | error: |
2450 | pr_warning("Failed to delete event: %s\n", | 2454 | pr_warning("Failed to delete event: %s\n", |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index c7918f83b300..b5247d777f0e 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -989,8 +989,24 @@ static int debuginfo__find_probes(struct debuginfo *dbg, | |||
989 | int ret = 0; | 989 | int ret = 0; |
990 | 990 | ||
991 | #if _ELFUTILS_PREREQ(0, 142) | 991 | #if _ELFUTILS_PREREQ(0, 142) |
992 | Elf *elf; | ||
993 | GElf_Ehdr ehdr; | ||
994 | GElf_Shdr shdr; | ||
995 | |||
992 | /* Get the call frame information from this dwarf */ | 996 | /* Get the call frame information from this dwarf */ |
993 | pf->cfi = dwarf_getcfi_elf(dwarf_getelf(dbg->dbg)); | 997 | elf = dwarf_getelf(dbg->dbg); |
998 | if (elf == NULL) | ||
999 | return -EINVAL; | ||
1000 | |||
1001 | if (gelf_getehdr(elf, &ehdr) == NULL) | ||
1002 | return -EINVAL; | ||
1003 | |||
1004 | if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) && | ||
1005 | shdr.sh_type == SHT_PROGBITS) { | ||
1006 | pf->cfi = dwarf_getcfi_elf(elf); | ||
1007 | } else { | ||
1008 | pf->cfi = dwarf_getcfi(dbg->dbg); | ||
1009 | } | ||
994 | #endif | 1010 | #endif |
995 | 1011 | ||
996 | off = 0; | 1012 | off = 0; |
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index 16a475a7d492..6c6a6953fa93 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources | |||
@@ -10,7 +10,7 @@ util/ctype.c | |||
10 | util/evlist.c | 10 | util/evlist.c |
11 | util/evsel.c | 11 | util/evsel.c |
12 | util/cpumap.c | 12 | util/cpumap.c |
13 | util/hweight.c | 13 | ../../lib/hweight.c |
14 | util/thread_map.c | 14 | util/thread_map.c |
15 | util/util.c | 15 | util/util.c |
16 | util/xyarray.c | 16 | util/xyarray.c |
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index cf69325b985f..8acd0df88b5c 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c | |||
@@ -137,16 +137,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) | |||
137 | 137 | ||
138 | static int get_max_rate(unsigned int *rate) | 138 | static int get_max_rate(unsigned int *rate) |
139 | { | 139 | { |
140 | char path[PATH_MAX]; | 140 | return sysctl__read_int("kernel/perf_event_max_sample_rate", (int *)rate); |
141 | const char *procfs = procfs__mountpoint(); | ||
142 | |||
143 | if (!procfs) | ||
144 | return -1; | ||
145 | |||
146 | snprintf(path, PATH_MAX, | ||
147 | "%s/sys/kernel/perf_event_max_sample_rate", procfs); | ||
148 | |||
149 | return filename__read_int(path, (int *) rate); | ||
150 | } | 141 | } |
151 | 142 | ||
152 | static int record_opts__config_freq(struct record_opts *opts) | 143 | static int record_opts__config_freq(struct record_opts *opts) |
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 0a01bac4ce02..22ebc46226e7 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <string.h> | 24 | #include <string.h> |
25 | #include <ctype.h> | 25 | #include <ctype.h> |
26 | #include <errno.h> | 26 | #include <errno.h> |
27 | #include <linux/bitmap.h> | ||
27 | 28 | ||
28 | #include "../util.h" | 29 | #include "../util.h" |
29 | #include <EXTERN.h> | 30 | #include <EXTERN.h> |
@@ -57,7 +58,7 @@ INTERP my_perl; | |||
57 | #define FTRACE_MAX_EVENT \ | 58 | #define FTRACE_MAX_EVENT \ |
58 | ((1 << (sizeof(unsigned short) * 8)) - 1) | 59 | ((1 << (sizeof(unsigned short) * 8)) - 1) |
59 | 60 | ||
60 | struct event_format *events[FTRACE_MAX_EVENT]; | 61 | static DECLARE_BITMAP(events_defined, FTRACE_MAX_EVENT); |
61 | 62 | ||
62 | extern struct scripting_context *scripting_context; | 63 | extern struct scripting_context *scripting_context; |
63 | 64 | ||
@@ -238,35 +239,15 @@ static void define_event_symbols(struct event_format *event, | |||
238 | define_event_symbols(event, ev_name, args->next); | 239 | define_event_symbols(event, ev_name, args->next); |
239 | } | 240 | } |
240 | 241 | ||
241 | static inline struct event_format *find_cache_event(struct perf_evsel *evsel) | ||
242 | { | ||
243 | static char ev_name[256]; | ||
244 | struct event_format *event; | ||
245 | int type = evsel->attr.config; | ||
246 | |||
247 | if (events[type]) | ||
248 | return events[type]; | ||
249 | |||
250 | events[type] = event = evsel->tp_format; | ||
251 | if (!event) | ||
252 | return NULL; | ||
253 | |||
254 | sprintf(ev_name, "%s::%s", event->system, event->name); | ||
255 | |||
256 | define_event_symbols(event, ev_name, event->print_fmt.args); | ||
257 | |||
258 | return event; | ||
259 | } | ||
260 | |||
261 | static void perl_process_tracepoint(struct perf_sample *sample, | 242 | static void perl_process_tracepoint(struct perf_sample *sample, |
262 | struct perf_evsel *evsel, | 243 | struct perf_evsel *evsel, |
263 | struct thread *thread) | 244 | struct thread *thread) |
264 | { | 245 | { |
246 | struct event_format *event = evsel->tp_format; | ||
265 | struct format_field *field; | 247 | struct format_field *field; |
266 | static char handler[256]; | 248 | static char handler[256]; |
267 | unsigned long long val; | 249 | unsigned long long val; |
268 | unsigned long s, ns; | 250 | unsigned long s, ns; |
269 | struct event_format *event; | ||
270 | int pid; | 251 | int pid; |
271 | int cpu = sample->cpu; | 252 | int cpu = sample->cpu; |
272 | void *data = sample->raw_data; | 253 | void *data = sample->raw_data; |
@@ -278,7 +259,6 @@ static void perl_process_tracepoint(struct perf_sample *sample, | |||
278 | if (evsel->attr.type != PERF_TYPE_TRACEPOINT) | 259 | if (evsel->attr.type != PERF_TYPE_TRACEPOINT) |
279 | return; | 260 | return; |
280 | 261 | ||
281 | event = find_cache_event(evsel); | ||
282 | if (!event) | 262 | if (!event) |
283 | die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config); | 263 | die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config); |
284 | 264 | ||
@@ -286,6 +266,9 @@ static void perl_process_tracepoint(struct perf_sample *sample, | |||
286 | 266 | ||
287 | sprintf(handler, "%s::%s", event->system, event->name); | 267 | sprintf(handler, "%s::%s", event->system, event->name); |
288 | 268 | ||
269 | if (!test_and_set_bit(event->id, events_defined)) | ||
270 | define_event_symbols(event, handler, event->print_fmt.args); | ||
271 | |||
289 | s = nsecs / NSECS_PER_SEC; | 272 | s = nsecs / NSECS_PER_SEC; |
290 | ns = nsecs - s * NSECS_PER_SEC; | 273 | ns = nsecs - s * NSECS_PER_SEC; |
291 | 274 | ||
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 496f21cadd97..d808a328f4dc 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -24,7 +24,9 @@ | |||
24 | #include <stdio.h> | 24 | #include <stdio.h> |
25 | #include <stdlib.h> | 25 | #include <stdlib.h> |
26 | #include <string.h> | 26 | #include <string.h> |
27 | #include <stdbool.h> | ||
27 | #include <errno.h> | 28 | #include <errno.h> |
29 | #include <linux/bitmap.h> | ||
28 | 30 | ||
29 | #include "../../perf.h" | 31 | #include "../../perf.h" |
30 | #include "../debug.h" | 32 | #include "../debug.h" |
@@ -33,6 +35,10 @@ | |||
33 | #include "../util.h" | 35 | #include "../util.h" |
34 | #include "../event.h" | 36 | #include "../event.h" |
35 | #include "../thread.h" | 37 | #include "../thread.h" |
38 | #include "../comm.h" | ||
39 | #include "../machine.h" | ||
40 | #include "../db-export.h" | ||
41 | #include "../thread-stack.h" | ||
36 | #include "../trace-event.h" | 42 | #include "../trace-event.h" |
37 | #include "../machine.h" | 43 | #include "../machine.h" |
38 | 44 | ||
@@ -41,7 +47,7 @@ PyMODINIT_FUNC initperf_trace_context(void); | |||
41 | #define FTRACE_MAX_EVENT \ | 47 | #define FTRACE_MAX_EVENT \ |
42 | ((1 << (sizeof(unsigned short) * 8)) - 1) | 48 | ((1 << (sizeof(unsigned short) * 8)) - 1) |
43 | 49 | ||
44 | struct event_format *events[FTRACE_MAX_EVENT]; | 50 | static DECLARE_BITMAP(events_defined, FTRACE_MAX_EVENT); |
45 | 51 | ||
46 | #define MAX_FIELDS 64 | 52 | #define MAX_FIELDS 64 |
47 | #define N_COMMON_FIELDS 7 | 53 | #define N_COMMON_FIELDS 7 |
@@ -53,6 +59,24 @@ static int zero_flag_atom; | |||
53 | 59 | ||
54 | static PyObject *main_module, *main_dict; | 60 | static PyObject *main_module, *main_dict; |
55 | 61 | ||
62 | struct tables { | ||
63 | struct db_export dbe; | ||
64 | PyObject *evsel_handler; | ||
65 | PyObject *machine_handler; | ||
66 | PyObject *thread_handler; | ||
67 | PyObject *comm_handler; | ||
68 | PyObject *comm_thread_handler; | ||
69 | PyObject *dso_handler; | ||
70 | PyObject *symbol_handler; | ||
71 | PyObject *branch_type_handler; | ||
72 | PyObject *sample_handler; | ||
73 | PyObject *call_path_handler; | ||
74 | PyObject *call_return_handler; | ||
75 | bool db_export_mode; | ||
76 | }; | ||
77 | |||
78 | static struct tables tables_global; | ||
79 | |||
56 | static void handler_call_die(const char *handler_name) NORETURN; | 80 | static void handler_call_die(const char *handler_name) NORETURN; |
57 | static void handler_call_die(const char *handler_name) | 81 | static void handler_call_die(const char *handler_name) |
58 | { | 82 | { |
@@ -232,31 +256,6 @@ static void define_event_symbols(struct event_format *event, | |||
232 | define_event_symbols(event, ev_name, args->next); | 256 | define_event_symbols(event, ev_name, args->next); |
233 | } | 257 | } |
234 | 258 | ||
235 | static inline struct event_format *find_cache_event(struct perf_evsel *evsel) | ||
236 | { | ||
237 | static char ev_name[256]; | ||
238 | struct event_format *event; | ||
239 | int type = evsel->attr.config; | ||
240 | |||
241 | /* | ||
242 | * XXX: Do we really need to cache this since now we have evsel->tp_format | ||
243 | * cached already? Need to re-read this "cache" routine that as well calls | ||
244 | * define_event_symbols() :-\ | ||
245 | */ | ||
246 | if (events[type]) | ||
247 | return events[type]; | ||
248 | |||
249 | events[type] = event = evsel->tp_format; | ||
250 | if (!event) | ||
251 | return NULL; | ||
252 | |||
253 | sprintf(ev_name, "%s__%s", event->system, event->name); | ||
254 | |||
255 | define_event_symbols(event, ev_name, event->print_fmt.args); | ||
256 | |||
257 | return event; | ||
258 | } | ||
259 | |||
260 | static PyObject *get_field_numeric_entry(struct event_format *event, | 259 | static PyObject *get_field_numeric_entry(struct event_format *event, |
261 | struct format_field *field, void *data) | 260 | struct format_field *field, void *data) |
262 | { | 261 | { |
@@ -312,9 +311,9 @@ static PyObject *python_process_callchain(struct perf_sample *sample, | |||
312 | if (!symbol_conf.use_callchain || !sample->callchain) | 311 | if (!symbol_conf.use_callchain || !sample->callchain) |
313 | goto exit; | 312 | goto exit; |
314 | 313 | ||
315 | if (machine__resolve_callchain(al->machine, evsel, al->thread, | 314 | if (thread__resolve_callchain(al->thread, evsel, |
316 | sample, NULL, NULL, | 315 | sample, NULL, NULL, |
317 | PERF_MAX_STACK_DEPTH) != 0) { | 316 | PERF_MAX_STACK_DEPTH) != 0) { |
318 | pr_err("Failed to resolve callchain. Skipping\n"); | 317 | pr_err("Failed to resolve callchain. Skipping\n"); |
319 | goto exit; | 318 | goto exit; |
320 | } | 319 | } |
@@ -380,12 +379,12 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
380 | struct thread *thread, | 379 | struct thread *thread, |
381 | struct addr_location *al) | 380 | struct addr_location *al) |
382 | { | 381 | { |
382 | struct event_format *event = evsel->tp_format; | ||
383 | PyObject *handler, *context, *t, *obj, *callchain; | 383 | PyObject *handler, *context, *t, *obj, *callchain; |
384 | PyObject *dict = NULL; | 384 | PyObject *dict = NULL; |
385 | static char handler_name[256]; | 385 | static char handler_name[256]; |
386 | struct format_field *field; | 386 | struct format_field *field; |
387 | unsigned long s, ns; | 387 | unsigned long s, ns; |
388 | struct event_format *event; | ||
389 | unsigned n = 0; | 388 | unsigned n = 0; |
390 | int pid; | 389 | int pid; |
391 | int cpu = sample->cpu; | 390 | int cpu = sample->cpu; |
@@ -397,7 +396,6 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
397 | if (!t) | 396 | if (!t) |
398 | Py_FatalError("couldn't create Python tuple"); | 397 | Py_FatalError("couldn't create Python tuple"); |
399 | 398 | ||
400 | event = find_cache_event(evsel); | ||
401 | if (!event) | 399 | if (!event) |
402 | die("ug! no event found for type %d", (int)evsel->attr.config); | 400 | die("ug! no event found for type %d", (int)evsel->attr.config); |
403 | 401 | ||
@@ -405,6 +403,9 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
405 | 403 | ||
406 | sprintf(handler_name, "%s__%s", event->system, event->name); | 404 | sprintf(handler_name, "%s__%s", event->system, event->name); |
407 | 405 | ||
406 | if (!test_and_set_bit(event->id, events_defined)) | ||
407 | define_event_symbols(event, handler_name, event->print_fmt.args); | ||
408 | |||
408 | handler = get_handler(handler_name); | 409 | handler = get_handler(handler_name); |
409 | if (!handler) { | 410 | if (!handler) { |
410 | dict = PyDict_New(); | 411 | dict = PyDict_New(); |
@@ -475,6 +476,289 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
475 | Py_DECREF(t); | 476 | Py_DECREF(t); |
476 | } | 477 | } |
477 | 478 | ||
479 | static PyObject *tuple_new(unsigned int sz) | ||
480 | { | ||
481 | PyObject *t; | ||
482 | |||
483 | t = PyTuple_New(sz); | ||
484 | if (!t) | ||
485 | Py_FatalError("couldn't create Python tuple"); | ||
486 | return t; | ||
487 | } | ||
488 | |||
489 | static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) | ||
490 | { | ||
491 | #if BITS_PER_LONG == 64 | ||
492 | return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); | ||
493 | #endif | ||
494 | #if BITS_PER_LONG == 32 | ||
495 | return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val)); | ||
496 | #endif | ||
497 | } | ||
498 | |||
499 | static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val) | ||
500 | { | ||
501 | return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); | ||
502 | } | ||
503 | |||
504 | static int tuple_set_string(PyObject *t, unsigned int pos, const char *s) | ||
505 | { | ||
506 | return PyTuple_SetItem(t, pos, PyString_FromString(s)); | ||
507 | } | ||
508 | |||
509 | static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel) | ||
510 | { | ||
511 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
512 | PyObject *t; | ||
513 | |||
514 | t = tuple_new(2); | ||
515 | |||
516 | tuple_set_u64(t, 0, evsel->db_id); | ||
517 | tuple_set_string(t, 1, perf_evsel__name(evsel)); | ||
518 | |||
519 | call_object(tables->evsel_handler, t, "evsel_table"); | ||
520 | |||
521 | Py_DECREF(t); | ||
522 | |||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | static int python_export_machine(struct db_export *dbe, | ||
527 | struct machine *machine) | ||
528 | { | ||
529 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
530 | PyObject *t; | ||
531 | |||
532 | t = tuple_new(3); | ||
533 | |||
534 | tuple_set_u64(t, 0, machine->db_id); | ||
535 | tuple_set_s32(t, 1, machine->pid); | ||
536 | tuple_set_string(t, 2, machine->root_dir ? machine->root_dir : ""); | ||
537 | |||
538 | call_object(tables->machine_handler, t, "machine_table"); | ||
539 | |||
540 | Py_DECREF(t); | ||
541 | |||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | static int python_export_thread(struct db_export *dbe, struct thread *thread, | ||
546 | u64 main_thread_db_id, struct machine *machine) | ||
547 | { | ||
548 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
549 | PyObject *t; | ||
550 | |||
551 | t = tuple_new(5); | ||
552 | |||
553 | tuple_set_u64(t, 0, thread->db_id); | ||
554 | tuple_set_u64(t, 1, machine->db_id); | ||
555 | tuple_set_u64(t, 2, main_thread_db_id); | ||
556 | tuple_set_s32(t, 3, thread->pid_); | ||
557 | tuple_set_s32(t, 4, thread->tid); | ||
558 | |||
559 | call_object(tables->thread_handler, t, "thread_table"); | ||
560 | |||
561 | Py_DECREF(t); | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | static int python_export_comm(struct db_export *dbe, struct comm *comm) | ||
567 | { | ||
568 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
569 | PyObject *t; | ||
570 | |||
571 | t = tuple_new(2); | ||
572 | |||
573 | tuple_set_u64(t, 0, comm->db_id); | ||
574 | tuple_set_string(t, 1, comm__str(comm)); | ||
575 | |||
576 | call_object(tables->comm_handler, t, "comm_table"); | ||
577 | |||
578 | Py_DECREF(t); | ||
579 | |||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static int python_export_comm_thread(struct db_export *dbe, u64 db_id, | ||
584 | struct comm *comm, struct thread *thread) | ||
585 | { | ||
586 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
587 | PyObject *t; | ||
588 | |||
589 | t = tuple_new(3); | ||
590 | |||
591 | tuple_set_u64(t, 0, db_id); | ||
592 | tuple_set_u64(t, 1, comm->db_id); | ||
593 | tuple_set_u64(t, 2, thread->db_id); | ||
594 | |||
595 | call_object(tables->comm_thread_handler, t, "comm_thread_table"); | ||
596 | |||
597 | Py_DECREF(t); | ||
598 | |||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | static int python_export_dso(struct db_export *dbe, struct dso *dso, | ||
603 | struct machine *machine) | ||
604 | { | ||
605 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
606 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | ||
607 | PyObject *t; | ||
608 | |||
609 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); | ||
610 | |||
611 | t = tuple_new(5); | ||
612 | |||
613 | tuple_set_u64(t, 0, dso->db_id); | ||
614 | tuple_set_u64(t, 1, machine->db_id); | ||
615 | tuple_set_string(t, 2, dso->short_name); | ||
616 | tuple_set_string(t, 3, dso->long_name); | ||
617 | tuple_set_string(t, 4, sbuild_id); | ||
618 | |||
619 | call_object(tables->dso_handler, t, "dso_table"); | ||
620 | |||
621 | Py_DECREF(t); | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static int python_export_symbol(struct db_export *dbe, struct symbol *sym, | ||
627 | struct dso *dso) | ||
628 | { | ||
629 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
630 | u64 *sym_db_id = symbol__priv(sym); | ||
631 | PyObject *t; | ||
632 | |||
633 | t = tuple_new(6); | ||
634 | |||
635 | tuple_set_u64(t, 0, *sym_db_id); | ||
636 | tuple_set_u64(t, 1, dso->db_id); | ||
637 | tuple_set_u64(t, 2, sym->start); | ||
638 | tuple_set_u64(t, 3, sym->end); | ||
639 | tuple_set_s32(t, 4, sym->binding); | ||
640 | tuple_set_string(t, 5, sym->name); | ||
641 | |||
642 | call_object(tables->symbol_handler, t, "symbol_table"); | ||
643 | |||
644 | Py_DECREF(t); | ||
645 | |||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | static int python_export_branch_type(struct db_export *dbe, u32 branch_type, | ||
650 | const char *name) | ||
651 | { | ||
652 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
653 | PyObject *t; | ||
654 | |||
655 | t = tuple_new(2); | ||
656 | |||
657 | tuple_set_s32(t, 0, branch_type); | ||
658 | tuple_set_string(t, 1, name); | ||
659 | |||
660 | call_object(tables->branch_type_handler, t, "branch_type_table"); | ||
661 | |||
662 | Py_DECREF(t); | ||
663 | |||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static int python_export_sample(struct db_export *dbe, | ||
668 | struct export_sample *es) | ||
669 | { | ||
670 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
671 | PyObject *t; | ||
672 | |||
673 | t = tuple_new(21); | ||
674 | |||
675 | tuple_set_u64(t, 0, es->db_id); | ||
676 | tuple_set_u64(t, 1, es->evsel->db_id); | ||
677 | tuple_set_u64(t, 2, es->al->machine->db_id); | ||
678 | tuple_set_u64(t, 3, es->thread->db_id); | ||
679 | tuple_set_u64(t, 4, es->comm_db_id); | ||
680 | tuple_set_u64(t, 5, es->dso_db_id); | ||
681 | tuple_set_u64(t, 6, es->sym_db_id); | ||
682 | tuple_set_u64(t, 7, es->offset); | ||
683 | tuple_set_u64(t, 8, es->sample->ip); | ||
684 | tuple_set_u64(t, 9, es->sample->time); | ||
685 | tuple_set_s32(t, 10, es->sample->cpu); | ||
686 | tuple_set_u64(t, 11, es->addr_dso_db_id); | ||
687 | tuple_set_u64(t, 12, es->addr_sym_db_id); | ||
688 | tuple_set_u64(t, 13, es->addr_offset); | ||
689 | tuple_set_u64(t, 14, es->sample->addr); | ||
690 | tuple_set_u64(t, 15, es->sample->period); | ||
691 | tuple_set_u64(t, 16, es->sample->weight); | ||
692 | tuple_set_u64(t, 17, es->sample->transaction); | ||
693 | tuple_set_u64(t, 18, es->sample->data_src); | ||
694 | tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); | ||
695 | tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX)); | ||
696 | |||
697 | call_object(tables->sample_handler, t, "sample_table"); | ||
698 | |||
699 | Py_DECREF(t); | ||
700 | |||
701 | return 0; | ||
702 | } | ||
703 | |||
704 | static int python_export_call_path(struct db_export *dbe, struct call_path *cp) | ||
705 | { | ||
706 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
707 | PyObject *t; | ||
708 | u64 parent_db_id, sym_db_id; | ||
709 | |||
710 | parent_db_id = cp->parent ? cp->parent->db_id : 0; | ||
711 | sym_db_id = cp->sym ? *(u64 *)symbol__priv(cp->sym) : 0; | ||
712 | |||
713 | t = tuple_new(4); | ||
714 | |||
715 | tuple_set_u64(t, 0, cp->db_id); | ||
716 | tuple_set_u64(t, 1, parent_db_id); | ||
717 | tuple_set_u64(t, 2, sym_db_id); | ||
718 | tuple_set_u64(t, 3, cp->ip); | ||
719 | |||
720 | call_object(tables->call_path_handler, t, "call_path_table"); | ||
721 | |||
722 | Py_DECREF(t); | ||
723 | |||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | static int python_export_call_return(struct db_export *dbe, | ||
728 | struct call_return *cr) | ||
729 | { | ||
730 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
731 | u64 comm_db_id = cr->comm ? cr->comm->db_id : 0; | ||
732 | PyObject *t; | ||
733 | |||
734 | t = tuple_new(11); | ||
735 | |||
736 | tuple_set_u64(t, 0, cr->db_id); | ||
737 | tuple_set_u64(t, 1, cr->thread->db_id); | ||
738 | tuple_set_u64(t, 2, comm_db_id); | ||
739 | tuple_set_u64(t, 3, cr->cp->db_id); | ||
740 | tuple_set_u64(t, 4, cr->call_time); | ||
741 | tuple_set_u64(t, 5, cr->return_time); | ||
742 | tuple_set_u64(t, 6, cr->branch_count); | ||
743 | tuple_set_u64(t, 7, cr->call_ref); | ||
744 | tuple_set_u64(t, 8, cr->return_ref); | ||
745 | tuple_set_u64(t, 9, cr->cp->parent->db_id); | ||
746 | tuple_set_s32(t, 10, cr->flags); | ||
747 | |||
748 | call_object(tables->call_return_handler, t, "call_return_table"); | ||
749 | |||
750 | Py_DECREF(t); | ||
751 | |||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | static int python_process_call_return(struct call_return *cr, void *data) | ||
756 | { | ||
757 | struct db_export *dbe = data; | ||
758 | |||
759 | return db_export__call_return(dbe, cr); | ||
760 | } | ||
761 | |||
478 | static void python_process_general_event(struct perf_sample *sample, | 762 | static void python_process_general_event(struct perf_sample *sample, |
479 | struct perf_evsel *evsel, | 763 | struct perf_evsel *evsel, |
480 | struct thread *thread, | 764 | struct thread *thread, |
@@ -551,19 +835,25 @@ exit: | |||
551 | Py_DECREF(t); | 835 | Py_DECREF(t); |
552 | } | 836 | } |
553 | 837 | ||
554 | static void python_process_event(union perf_event *event __maybe_unused, | 838 | static void python_process_event(union perf_event *event, |
555 | struct perf_sample *sample, | 839 | struct perf_sample *sample, |
556 | struct perf_evsel *evsel, | 840 | struct perf_evsel *evsel, |
557 | struct thread *thread, | 841 | struct thread *thread, |
558 | struct addr_location *al) | 842 | struct addr_location *al) |
559 | { | 843 | { |
844 | struct tables *tables = &tables_global; | ||
845 | |||
560 | switch (evsel->attr.type) { | 846 | switch (evsel->attr.type) { |
561 | case PERF_TYPE_TRACEPOINT: | 847 | case PERF_TYPE_TRACEPOINT: |
562 | python_process_tracepoint(sample, evsel, thread, al); | 848 | python_process_tracepoint(sample, evsel, thread, al); |
563 | break; | 849 | break; |
564 | /* Reserve for future process_hw/sw/raw APIs */ | 850 | /* Reserve for future process_hw/sw/raw APIs */ |
565 | default: | 851 | default: |
566 | python_process_general_event(sample, evsel, thread, al); | 852 | if (tables->db_export_mode) |
853 | db_export__sample(&tables->dbe, event, sample, evsel, | ||
854 | thread, al); | ||
855 | else | ||
856 | python_process_general_event(sample, evsel, thread, al); | ||
567 | } | 857 | } |
568 | } | 858 | } |
569 | 859 | ||
@@ -589,11 +879,79 @@ error: | |||
589 | return -1; | 879 | return -1; |
590 | } | 880 | } |
591 | 881 | ||
882 | #define SET_TABLE_HANDLER_(name, handler_name, table_name) do { \ | ||
883 | tables->handler_name = get_handler(#table_name); \ | ||
884 | if (tables->handler_name) \ | ||
885 | tables->dbe.export_ ## name = python_export_ ## name; \ | ||
886 | } while (0) | ||
887 | |||
888 | #define SET_TABLE_HANDLER(name) \ | ||
889 | SET_TABLE_HANDLER_(name, name ## _handler, name ## _table) | ||
890 | |||
891 | static void set_table_handlers(struct tables *tables) | ||
892 | { | ||
893 | const char *perf_db_export_mode = "perf_db_export_mode"; | ||
894 | const char *perf_db_export_calls = "perf_db_export_calls"; | ||
895 | PyObject *db_export_mode, *db_export_calls; | ||
896 | bool export_calls = false; | ||
897 | int ret; | ||
898 | |||
899 | memset(tables, 0, sizeof(struct tables)); | ||
900 | if (db_export__init(&tables->dbe)) | ||
901 | Py_FatalError("failed to initialize export"); | ||
902 | |||
903 | db_export_mode = PyDict_GetItemString(main_dict, perf_db_export_mode); | ||
904 | if (!db_export_mode) | ||
905 | return; | ||
906 | |||
907 | ret = PyObject_IsTrue(db_export_mode); | ||
908 | if (ret == -1) | ||
909 | handler_call_die(perf_db_export_mode); | ||
910 | if (!ret) | ||
911 | return; | ||
912 | |||
913 | tables->dbe.crp = NULL; | ||
914 | db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls); | ||
915 | if (db_export_calls) { | ||
916 | ret = PyObject_IsTrue(db_export_calls); | ||
917 | if (ret == -1) | ||
918 | handler_call_die(perf_db_export_calls); | ||
919 | export_calls = !!ret; | ||
920 | } | ||
921 | |||
922 | if (export_calls) { | ||
923 | tables->dbe.crp = | ||
924 | call_return_processor__new(python_process_call_return, | ||
925 | &tables->dbe); | ||
926 | if (!tables->dbe.crp) | ||
927 | Py_FatalError("failed to create calls processor"); | ||
928 | } | ||
929 | |||
930 | tables->db_export_mode = true; | ||
931 | /* | ||
932 | * Reserve per symbol space for symbol->db_id via symbol__priv() | ||
933 | */ | ||
934 | symbol_conf.priv_size = sizeof(u64); | ||
935 | |||
936 | SET_TABLE_HANDLER(evsel); | ||
937 | SET_TABLE_HANDLER(machine); | ||
938 | SET_TABLE_HANDLER(thread); | ||
939 | SET_TABLE_HANDLER(comm); | ||
940 | SET_TABLE_HANDLER(comm_thread); | ||
941 | SET_TABLE_HANDLER(dso); | ||
942 | SET_TABLE_HANDLER(symbol); | ||
943 | SET_TABLE_HANDLER(branch_type); | ||
944 | SET_TABLE_HANDLER(sample); | ||
945 | SET_TABLE_HANDLER(call_path); | ||
946 | SET_TABLE_HANDLER(call_return); | ||
947 | } | ||
948 | |||
592 | /* | 949 | /* |
593 | * Start trace script | 950 | * Start trace script |
594 | */ | 951 | */ |
595 | static int python_start_script(const char *script, int argc, const char **argv) | 952 | static int python_start_script(const char *script, int argc, const char **argv) |
596 | { | 953 | { |
954 | struct tables *tables = &tables_global; | ||
597 | const char **command_line; | 955 | const char **command_line; |
598 | char buf[PATH_MAX]; | 956 | char buf[PATH_MAX]; |
599 | int i, err = 0; | 957 | int i, err = 0; |
@@ -632,6 +990,14 @@ static int python_start_script(const char *script, int argc, const char **argv) | |||
632 | 990 | ||
633 | free(command_line); | 991 | free(command_line); |
634 | 992 | ||
993 | set_table_handlers(tables); | ||
994 | |||
995 | if (tables->db_export_mode) { | ||
996 | err = db_export__branch_types(&tables->dbe); | ||
997 | if (err) | ||
998 | goto error; | ||
999 | } | ||
1000 | |||
635 | return err; | 1001 | return err; |
636 | error: | 1002 | error: |
637 | Py_Finalize(); | 1003 | Py_Finalize(); |
@@ -642,7 +1008,9 @@ error: | |||
642 | 1008 | ||
643 | static int python_flush_script(void) | 1009 | static int python_flush_script(void) |
644 | { | 1010 | { |
645 | return 0; | 1011 | struct tables *tables = &tables_global; |
1012 | |||
1013 | return db_export__flush(&tables->dbe); | ||
646 | } | 1014 | } |
647 | 1015 | ||
648 | /* | 1016 | /* |
@@ -650,8 +1018,12 @@ static int python_flush_script(void) | |||
650 | */ | 1018 | */ |
651 | static int python_stop_script(void) | 1019 | static int python_stop_script(void) |
652 | { | 1020 | { |
1021 | struct tables *tables = &tables_global; | ||
1022 | |||
653 | try_call_object("trace_end", NULL); | 1023 | try_call_object("trace_end", NULL); |
654 | 1024 | ||
1025 | db_export__exit(&tables->dbe); | ||
1026 | |||
655 | Py_XDECREF(main_dict); | 1027 | Py_XDECREF(main_dict); |
656 | Py_XDECREF(main_module); | 1028 | Py_XDECREF(main_module); |
657 | Py_Finalize(); | 1029 | Py_Finalize(); |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 6702ac28754b..5f0e05a76c05 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -228,6 +228,15 @@ static int process_finished_round(struct perf_tool *tool, | |||
228 | union perf_event *event, | 228 | union perf_event *event, |
229 | struct perf_session *session); | 229 | struct perf_session *session); |
230 | 230 | ||
231 | static int process_id_index_stub(struct perf_tool *tool __maybe_unused, | ||
232 | union perf_event *event __maybe_unused, | ||
233 | struct perf_session *perf_session | ||
234 | __maybe_unused) | ||
235 | { | ||
236 | dump_printf(": unhandled!\n"); | ||
237 | return 0; | ||
238 | } | ||
239 | |||
231 | void perf_tool__fill_defaults(struct perf_tool *tool) | 240 | void perf_tool__fill_defaults(struct perf_tool *tool) |
232 | { | 241 | { |
233 | if (tool->sample == NULL) | 242 | if (tool->sample == NULL) |
@@ -262,6 +271,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) | |||
262 | else | 271 | else |
263 | tool->finished_round = process_finished_round_stub; | 272 | tool->finished_round = process_finished_round_stub; |
264 | } | 273 | } |
274 | if (tool->id_index == NULL) | ||
275 | tool->id_index = process_id_index_stub; | ||
265 | } | 276 | } |
266 | 277 | ||
267 | static void swap_sample_id_all(union perf_event *event, void *data) | 278 | static void swap_sample_id_all(union perf_event *event, void *data) |
@@ -460,6 +471,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { | |||
460 | [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, | 471 | [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, |
461 | [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, | 472 | [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, |
462 | [PERF_RECORD_HEADER_BUILD_ID] = NULL, | 473 | [PERF_RECORD_HEADER_BUILD_ID] = NULL, |
474 | [PERF_RECORD_ID_INDEX] = perf_event__all64_swap, | ||
463 | [PERF_RECORD_HEADER_MAX] = NULL, | 475 | [PERF_RECORD_HEADER_MAX] = NULL, |
464 | }; | 476 | }; |
465 | 477 | ||
@@ -521,15 +533,11 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event, | |||
521 | return -ETIME; | 533 | return -ETIME; |
522 | 534 | ||
523 | if (timestamp < oe->last_flush) { | 535 | if (timestamp < oe->last_flush) { |
524 | WARN_ONCE(1, "Timestamp below last timeslice flush\n"); | 536 | pr_oe_time(timestamp, "out of order event\n"); |
525 | |||
526 | pr_oe_time(timestamp, "out of order event"); | ||
527 | pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n", | 537 | pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n", |
528 | oe->last_flush_type); | 538 | oe->last_flush_type); |
529 | 539 | ||
530 | /* We could get out of order messages after forced flush. */ | 540 | s->stats.nr_unordered_events++; |
531 | if (oe->last_flush_type != OE_FLUSH__HALF) | ||
532 | return -EINVAL; | ||
533 | } | 541 | } |
534 | 542 | ||
535 | new = ordered_events__new(oe, timestamp, event); | 543 | new = ordered_events__new(oe, timestamp, event); |
@@ -580,15 +588,46 @@ static void regs_dump__printf(u64 mask, u64 *regs) | |||
580 | } | 588 | } |
581 | } | 589 | } |
582 | 590 | ||
591 | static const char *regs_abi[] = { | ||
592 | [PERF_SAMPLE_REGS_ABI_NONE] = "none", | ||
593 | [PERF_SAMPLE_REGS_ABI_32] = "32-bit", | ||
594 | [PERF_SAMPLE_REGS_ABI_64] = "64-bit", | ||
595 | }; | ||
596 | |||
597 | static inline const char *regs_dump_abi(struct regs_dump *d) | ||
598 | { | ||
599 | if (d->abi > PERF_SAMPLE_REGS_ABI_64) | ||
600 | return "unknown"; | ||
601 | |||
602 | return regs_abi[d->abi]; | ||
603 | } | ||
604 | |||
605 | static void regs__printf(const char *type, struct regs_dump *regs) | ||
606 | { | ||
607 | u64 mask = regs->mask; | ||
608 | |||
609 | printf("... %s regs: mask 0x%" PRIx64 " ABI %s\n", | ||
610 | type, | ||
611 | mask, | ||
612 | regs_dump_abi(regs)); | ||
613 | |||
614 | regs_dump__printf(mask, regs->regs); | ||
615 | } | ||
616 | |||
583 | static void regs_user__printf(struct perf_sample *sample) | 617 | static void regs_user__printf(struct perf_sample *sample) |
584 | { | 618 | { |
585 | struct regs_dump *user_regs = &sample->user_regs; | 619 | struct regs_dump *user_regs = &sample->user_regs; |
586 | 620 | ||
587 | if (user_regs->regs) { | 621 | if (user_regs->regs) |
588 | u64 mask = user_regs->mask; | 622 | regs__printf("user", user_regs); |
589 | printf("... user regs: mask 0x%" PRIx64 "\n", mask); | 623 | } |
590 | regs_dump__printf(mask, user_regs->regs); | 624 | |
591 | } | 625 | static void regs_intr__printf(struct perf_sample *sample) |
626 | { | ||
627 | struct regs_dump *intr_regs = &sample->intr_regs; | ||
628 | |||
629 | if (intr_regs->regs) | ||
630 | regs__printf("intr", intr_regs); | ||
592 | } | 631 | } |
593 | 632 | ||
594 | static void stack_user__printf(struct stack_dump *dump) | 633 | static void stack_user__printf(struct stack_dump *dump) |
@@ -687,6 +726,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event, | |||
687 | if (sample_type & PERF_SAMPLE_REGS_USER) | 726 | if (sample_type & PERF_SAMPLE_REGS_USER) |
688 | regs_user__printf(sample); | 727 | regs_user__printf(sample); |
689 | 728 | ||
729 | if (sample_type & PERF_SAMPLE_REGS_INTR) | ||
730 | regs_intr__printf(sample); | ||
731 | |||
690 | if (sample_type & PERF_SAMPLE_STACK_USER) | 732 | if (sample_type & PERF_SAMPLE_STACK_USER) |
691 | stack_user__printf(&sample->user_stack); | 733 | stack_user__printf(&sample->user_stack); |
692 | 734 | ||
@@ -888,11 +930,26 @@ static s64 perf_session__process_user_event(struct perf_session *session, | |||
888 | return tool->build_id(tool, event, session); | 930 | return tool->build_id(tool, event, session); |
889 | case PERF_RECORD_FINISHED_ROUND: | 931 | case PERF_RECORD_FINISHED_ROUND: |
890 | return tool->finished_round(tool, event, session); | 932 | return tool->finished_round(tool, event, session); |
933 | case PERF_RECORD_ID_INDEX: | ||
934 | return tool->id_index(tool, event, session); | ||
891 | default: | 935 | default: |
892 | return -EINVAL; | 936 | return -EINVAL; |
893 | } | 937 | } |
894 | } | 938 | } |
895 | 939 | ||
940 | int perf_session__deliver_synth_event(struct perf_session *session, | ||
941 | union perf_event *event, | ||
942 | struct perf_sample *sample, | ||
943 | struct perf_tool *tool) | ||
944 | { | ||
945 | events_stats__inc(&session->stats, event->header.type); | ||
946 | |||
947 | if (event->header.type >= PERF_RECORD_USER_TYPE_START) | ||
948 | return perf_session__process_user_event(session, event, tool, 0); | ||
949 | |||
950 | return perf_session__deliver_event(session, event, sample, tool, 0); | ||
951 | } | ||
952 | |||
896 | static void event_swap(union perf_event *event, bool sample_id_all) | 953 | static void event_swap(union perf_event *event, bool sample_id_all) |
897 | { | 954 | { |
898 | perf_event__swap_op swap; | 955 | perf_event__swap_op swap; |
@@ -1057,6 +1114,9 @@ static void perf_session__warn_about_errors(const struct perf_session *session, | |||
1057 | "Do you have a KVM guest running and not using 'perf kvm'?\n", | 1114 | "Do you have a KVM guest running and not using 'perf kvm'?\n", |
1058 | session->stats.nr_unprocessable_samples); | 1115 | session->stats.nr_unprocessable_samples); |
1059 | } | 1116 | } |
1117 | |||
1118 | if (session->stats.nr_unordered_events != 0) | ||
1119 | ui__warning("%u out of order events recorded.\n", session->stats.nr_unordered_events); | ||
1060 | } | 1120 | } |
1061 | 1121 | ||
1062 | volatile int session_done; | 1122 | volatile int session_done; |
@@ -1417,9 +1477,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, | |||
1417 | if (symbol_conf.use_callchain && sample->callchain) { | 1477 | if (symbol_conf.use_callchain && sample->callchain) { |
1418 | struct addr_location node_al; | 1478 | struct addr_location node_al; |
1419 | 1479 | ||
1420 | if (machine__resolve_callchain(al->machine, evsel, al->thread, | 1480 | if (thread__resolve_callchain(al->thread, evsel, |
1421 | sample, NULL, NULL, | 1481 | sample, NULL, NULL, |
1422 | PERF_MAX_STACK_DEPTH) != 0) { | 1482 | PERF_MAX_STACK_DEPTH) != 0) { |
1423 | if (verbose) | 1483 | if (verbose) |
1424 | error("Failed to resolve callchain. Skipping\n"); | 1484 | error("Failed to resolve callchain. Skipping\n"); |
1425 | return; | 1485 | return; |
@@ -1594,3 +1654,111 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session, | |||
1594 | out: | 1654 | out: |
1595 | return err; | 1655 | return err; |
1596 | } | 1656 | } |
1657 | |||
1658 | int perf_event__process_id_index(struct perf_tool *tool __maybe_unused, | ||
1659 | union perf_event *event, | ||
1660 | struct perf_session *session) | ||
1661 | { | ||
1662 | struct perf_evlist *evlist = session->evlist; | ||
1663 | struct id_index_event *ie = &event->id_index; | ||
1664 | size_t i, nr, max_nr; | ||
1665 | |||
1666 | max_nr = (ie->header.size - sizeof(struct id_index_event)) / | ||
1667 | sizeof(struct id_index_entry); | ||
1668 | nr = ie->nr; | ||
1669 | if (nr > max_nr) | ||
1670 | return -EINVAL; | ||
1671 | |||
1672 | if (dump_trace) | ||
1673 | fprintf(stdout, " nr: %zu\n", nr); | ||
1674 | |||
1675 | for (i = 0; i < nr; i++) { | ||
1676 | struct id_index_entry *e = &ie->entries[i]; | ||
1677 | struct perf_sample_id *sid; | ||
1678 | |||
1679 | if (dump_trace) { | ||
1680 | fprintf(stdout, " ... id: %"PRIu64, e->id); | ||
1681 | fprintf(stdout, " idx: %"PRIu64, e->idx); | ||
1682 | fprintf(stdout, " cpu: %"PRId64, e->cpu); | ||
1683 | fprintf(stdout, " tid: %"PRId64"\n", e->tid); | ||
1684 | } | ||
1685 | |||
1686 | sid = perf_evlist__id2sid(evlist, e->id); | ||
1687 | if (!sid) | ||
1688 | return -ENOENT; | ||
1689 | sid->idx = e->idx; | ||
1690 | sid->cpu = e->cpu; | ||
1691 | sid->tid = e->tid; | ||
1692 | } | ||
1693 | return 0; | ||
1694 | } | ||
1695 | |||
1696 | int perf_event__synthesize_id_index(struct perf_tool *tool, | ||
1697 | perf_event__handler_t process, | ||
1698 | struct perf_evlist *evlist, | ||
1699 | struct machine *machine) | ||
1700 | { | ||
1701 | union perf_event *ev; | ||
1702 | struct perf_evsel *evsel; | ||
1703 | size_t nr = 0, i = 0, sz, max_nr, n; | ||
1704 | int err; | ||
1705 | |||
1706 | pr_debug2("Synthesizing id index\n"); | ||
1707 | |||
1708 | max_nr = (UINT16_MAX - sizeof(struct id_index_event)) / | ||
1709 | sizeof(struct id_index_entry); | ||
1710 | |||
1711 | evlist__for_each(evlist, evsel) | ||
1712 | nr += evsel->ids; | ||
1713 | |||
1714 | n = nr > max_nr ? max_nr : nr; | ||
1715 | sz = sizeof(struct id_index_event) + n * sizeof(struct id_index_entry); | ||
1716 | ev = zalloc(sz); | ||
1717 | if (!ev) | ||
1718 | return -ENOMEM; | ||
1719 | |||
1720 | ev->id_index.header.type = PERF_RECORD_ID_INDEX; | ||
1721 | ev->id_index.header.size = sz; | ||
1722 | ev->id_index.nr = n; | ||
1723 | |||
1724 | evlist__for_each(evlist, evsel) { | ||
1725 | u32 j; | ||
1726 | |||
1727 | for (j = 0; j < evsel->ids; j++) { | ||
1728 | struct id_index_entry *e; | ||
1729 | struct perf_sample_id *sid; | ||
1730 | |||
1731 | if (i >= n) { | ||
1732 | err = process(tool, ev, NULL, machine); | ||
1733 | if (err) | ||
1734 | goto out_err; | ||
1735 | nr -= n; | ||
1736 | i = 0; | ||
1737 | } | ||
1738 | |||
1739 | e = &ev->id_index.entries[i++]; | ||
1740 | |||
1741 | e->id = evsel->id[j]; | ||
1742 | |||
1743 | sid = perf_evlist__id2sid(evlist, e->id); | ||
1744 | if (!sid) { | ||
1745 | free(ev); | ||
1746 | return -ENOENT; | ||
1747 | } | ||
1748 | |||
1749 | e->idx = sid->idx; | ||
1750 | e->cpu = sid->cpu; | ||
1751 | e->tid = sid->tid; | ||
1752 | } | ||
1753 | } | ||
1754 | |||
1755 | sz = sizeof(struct id_index_event) + nr * sizeof(struct id_index_entry); | ||
1756 | ev->id_index.header.size = sz; | ||
1757 | ev->id_index.nr = nr; | ||
1758 | |||
1759 | err = process(tool, ev, NULL, machine); | ||
1760 | out_err: | ||
1761 | free(ev); | ||
1762 | |||
1763 | return err; | ||
1764 | } | ||
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index a4be851f1a90..dc26ebf60fe4 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -126,4 +126,19 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session, | |||
126 | extern volatile int session_done; | 126 | extern volatile int session_done; |
127 | 127 | ||
128 | #define session_done() ACCESS_ONCE(session_done) | 128 | #define session_done() ACCESS_ONCE(session_done) |
129 | |||
130 | int perf_session__deliver_synth_event(struct perf_session *session, | ||
131 | union perf_event *event, | ||
132 | struct perf_sample *sample, | ||
133 | struct perf_tool *tool); | ||
134 | |||
135 | int perf_event__process_id_index(struct perf_tool *tool, | ||
136 | union perf_event *event, | ||
137 | struct perf_session *session); | ||
138 | |||
139 | int perf_event__synthesize_id_index(struct perf_tool *tool, | ||
140 | perf_event__handler_t process, | ||
141 | struct perf_evlist *evlist, | ||
142 | struct machine *machine); | ||
143 | |||
129 | #endif /* __PERF_SESSION_H */ | 144 | #endif /* __PERF_SESSION_H */ |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 9402885a77f3..9139dda9f9a3 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -291,7 +291,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) | |||
291 | else { | 291 | else { |
292 | struct map *map = left->ms.map; | 292 | struct map *map = left->ms.map; |
293 | left->srcline = get_srcline(map->dso, | 293 | left->srcline = get_srcline(map->dso, |
294 | map__rip_2objdump(map, left->ip)); | 294 | map__rip_2objdump(map, left->ip), |
295 | left->ms.sym, true); | ||
295 | } | 296 | } |
296 | } | 297 | } |
297 | if (!right->srcline) { | 298 | if (!right->srcline) { |
@@ -300,7 +301,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) | |||
300 | else { | 301 | else { |
301 | struct map *map = right->ms.map; | 302 | struct map *map = right->ms.map; |
302 | right->srcline = get_srcline(map->dso, | 303 | right->srcline = get_srcline(map->dso, |
303 | map__rip_2objdump(map, right->ip)); | 304 | map__rip_2objdump(map, right->ip), |
305 | right->ms.sym, true); | ||
304 | } | 306 | } |
305 | } | 307 | } |
306 | return strcmp(right->srcline, left->srcline); | 308 | return strcmp(right->srcline, left->srcline); |
@@ -309,7 +311,7 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) | |||
309 | static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, | 311 | static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, |
310 | size_t size, unsigned int width) | 312 | size_t size, unsigned int width) |
311 | { | 313 | { |
312 | return repsep_snprintf(bf, size, "%*.*-s", width, width, he->srcline); | 314 | return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcline); |
313 | } | 315 | } |
314 | 316 | ||
315 | struct sort_entry sort_srcline = { | 317 | struct sort_entry sort_srcline = { |
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index f3e4bc5fe5d2..c93fb0c5bd0b 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c | |||
@@ -8,6 +8,8 @@ | |||
8 | #include "util/util.h" | 8 | #include "util/util.h" |
9 | #include "util/debug.h" | 9 | #include "util/debug.h" |
10 | 10 | ||
11 | #include "symbol.h" | ||
12 | |||
11 | #ifdef HAVE_LIBBFD_SUPPORT | 13 | #ifdef HAVE_LIBBFD_SUPPORT |
12 | 14 | ||
13 | /* | 15 | /* |
@@ -18,7 +20,7 @@ | |||
18 | 20 | ||
19 | struct a2l_data { | 21 | struct a2l_data { |
20 | const char *input; | 22 | const char *input; |
21 | unsigned long addr; | 23 | u64 addr; |
22 | 24 | ||
23 | bool found; | 25 | bool found; |
24 | const char *filename; | 26 | const char *filename; |
@@ -145,7 +147,7 @@ static void addr2line_cleanup(struct a2l_data *a2l) | |||
145 | free(a2l); | 147 | free(a2l); |
146 | } | 148 | } |
147 | 149 | ||
148 | static int addr2line(const char *dso_name, unsigned long addr, | 150 | static int addr2line(const char *dso_name, u64 addr, |
149 | char **file, unsigned int *line, struct dso *dso) | 151 | char **file, unsigned int *line, struct dso *dso) |
150 | { | 152 | { |
151 | int ret = 0; | 153 | int ret = 0; |
@@ -191,7 +193,7 @@ void dso__free_a2l(struct dso *dso) | |||
191 | 193 | ||
192 | #else /* HAVE_LIBBFD_SUPPORT */ | 194 | #else /* HAVE_LIBBFD_SUPPORT */ |
193 | 195 | ||
194 | static int addr2line(const char *dso_name, unsigned long addr, | 196 | static int addr2line(const char *dso_name, u64 addr, |
195 | char **file, unsigned int *line_nr, | 197 | char **file, unsigned int *line_nr, |
196 | struct dso *dso __maybe_unused) | 198 | struct dso *dso __maybe_unused) |
197 | { | 199 | { |
@@ -250,7 +252,8 @@ void dso__free_a2l(struct dso *dso __maybe_unused) | |||
250 | */ | 252 | */ |
251 | #define A2L_FAIL_LIMIT 123 | 253 | #define A2L_FAIL_LIMIT 123 |
252 | 254 | ||
253 | char *get_srcline(struct dso *dso, unsigned long addr) | 255 | char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, |
256 | bool show_sym) | ||
254 | { | 257 | { |
255 | char *file = NULL; | 258 | char *file = NULL; |
256 | unsigned line = 0; | 259 | unsigned line = 0; |
@@ -258,7 +261,7 @@ char *get_srcline(struct dso *dso, unsigned long addr) | |||
258 | const char *dso_name; | 261 | const char *dso_name; |
259 | 262 | ||
260 | if (!dso->has_srcline) | 263 | if (!dso->has_srcline) |
261 | return SRCLINE_UNKNOWN; | 264 | goto out; |
262 | 265 | ||
263 | if (dso->symsrc_filename) | 266 | if (dso->symsrc_filename) |
264 | dso_name = dso->symsrc_filename; | 267 | dso_name = dso->symsrc_filename; |
@@ -274,7 +277,7 @@ char *get_srcline(struct dso *dso, unsigned long addr) | |||
274 | if (!addr2line(dso_name, addr, &file, &line, dso)) | 277 | if (!addr2line(dso_name, addr, &file, &line, dso)) |
275 | goto out; | 278 | goto out; |
276 | 279 | ||
277 | if (asprintf(&srcline, "%s:%u", file, line) < 0) { | 280 | if (asprintf(&srcline, "%s:%u", basename(file), line) < 0) { |
278 | free(file); | 281 | free(file); |
279 | goto out; | 282 | goto out; |
280 | } | 283 | } |
@@ -289,7 +292,13 @@ out: | |||
289 | dso->has_srcline = 0; | 292 | dso->has_srcline = 0; |
290 | dso__free_a2l(dso); | 293 | dso__free_a2l(dso); |
291 | } | 294 | } |
292 | return SRCLINE_UNKNOWN; | 295 | if (sym) { |
296 | if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "", | ||
297 | addr - sym->start) < 0) | ||
298 | return SRCLINE_UNKNOWN; | ||
299 | } else if (asprintf(&srcline, "%s[%" PRIx64 "]", dso->short_name, addr) < 0) | ||
300 | return SRCLINE_UNKNOWN; | ||
301 | return srcline; | ||
293 | } | 302 | } |
294 | 303 | ||
295 | void free_srcline(char *srcline) | 304 | void free_srcline(char *srcline) |
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 1e23a5bfb044..06fcd1bf98b6 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -11,6 +11,27 @@ | |||
11 | #include <symbol/kallsyms.h> | 11 | #include <symbol/kallsyms.h> |
12 | #include "debug.h" | 12 | #include "debug.h" |
13 | 13 | ||
14 | #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT | ||
15 | extern char *cplus_demangle(const char *, int); | ||
16 | |||
17 | static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i) | ||
18 | { | ||
19 | return cplus_demangle(c, i); | ||
20 | } | ||
21 | #else | ||
22 | #ifdef NO_DEMANGLE | ||
23 | static inline char *bfd_demangle(void __maybe_unused *v, | ||
24 | const char __maybe_unused *c, | ||
25 | int __maybe_unused i) | ||
26 | { | ||
27 | return NULL; | ||
28 | } | ||
29 | #else | ||
30 | #define PACKAGE 'perf' | ||
31 | #include <bfd.h> | ||
32 | #endif | ||
33 | #endif | ||
34 | |||
14 | #ifndef HAVE_ELF_GETPHDRNUM_SUPPORT | 35 | #ifndef HAVE_ELF_GETPHDRNUM_SUPPORT |
15 | static int elf_getphdrnum(Elf *elf, size_t *dst) | 36 | static int elf_getphdrnum(Elf *elf, size_t *dst) |
16 | { | 37 | { |
@@ -546,6 +567,35 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata) | |||
546 | return 0; | 567 | return 0; |
547 | } | 568 | } |
548 | 569 | ||
570 | static int decompress_kmodule(struct dso *dso, const char *name, | ||
571 | enum dso_binary_type type) | ||
572 | { | ||
573 | int fd; | ||
574 | const char *ext = strrchr(name, '.'); | ||
575 | char tmpbuf[] = "/tmp/perf-kmod-XXXXXX"; | ||
576 | |||
577 | if ((type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP && | ||
578 | type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP) || | ||
579 | type != dso->symtab_type) | ||
580 | return -1; | ||
581 | |||
582 | if (!ext || !is_supported_compression(ext + 1)) | ||
583 | return -1; | ||
584 | |||
585 | fd = mkstemp(tmpbuf); | ||
586 | if (fd < 0) | ||
587 | return -1; | ||
588 | |||
589 | if (!decompress_to_file(ext + 1, name, fd)) { | ||
590 | close(fd); | ||
591 | fd = -1; | ||
592 | } | ||
593 | |||
594 | unlink(tmpbuf); | ||
595 | |||
596 | return fd; | ||
597 | } | ||
598 | |||
549 | bool symsrc__possibly_runtime(struct symsrc *ss) | 599 | bool symsrc__possibly_runtime(struct symsrc *ss) |
550 | { | 600 | { |
551 | return ss->dynsym || ss->opdsec; | 601 | return ss->dynsym || ss->opdsec; |
@@ -571,7 +621,11 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, | |||
571 | Elf *elf; | 621 | Elf *elf; |
572 | int fd; | 622 | int fd; |
573 | 623 | ||
574 | fd = open(name, O_RDONLY); | 624 | if (dso__needs_decompress(dso)) |
625 | fd = decompress_kmodule(dso, name, type); | ||
626 | else | ||
627 | fd = open(name, O_RDONLY); | ||
628 | |||
575 | if (fd < 0) | 629 | if (fd < 0) |
576 | return -1; | 630 | return -1; |
577 | 631 | ||
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index c9541fea9514..d7efb03b3f9a 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c | |||
@@ -129,6 +129,7 @@ int filename__read_build_id(const char *filename, void *bf, size_t size) | |||
129 | 129 | ||
130 | for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) { | 130 | for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) { |
131 | void *tmp; | 131 | void *tmp; |
132 | long offset; | ||
132 | 133 | ||
133 | if (need_swap) { | 134 | if (need_swap) { |
134 | phdr->p_type = bswap_32(phdr->p_type); | 135 | phdr->p_type = bswap_32(phdr->p_type); |
@@ -140,12 +141,13 @@ int filename__read_build_id(const char *filename, void *bf, size_t size) | |||
140 | continue; | 141 | continue; |
141 | 142 | ||
142 | buf_size = phdr->p_filesz; | 143 | buf_size = phdr->p_filesz; |
144 | offset = phdr->p_offset; | ||
143 | tmp = realloc(buf, buf_size); | 145 | tmp = realloc(buf, buf_size); |
144 | if (tmp == NULL) | 146 | if (tmp == NULL) |
145 | goto out_free; | 147 | goto out_free; |
146 | 148 | ||
147 | buf = tmp; | 149 | buf = tmp; |
148 | fseek(fp, phdr->p_offset, SEEK_SET); | 150 | fseek(fp, offset, SEEK_SET); |
149 | if (fread(buf, buf_size, 1, fp) != 1) | 151 | if (fread(buf, buf_size, 1, fp) != 1) |
150 | goto out_free; | 152 | goto out_free; |
151 | 153 | ||
@@ -178,6 +180,7 @@ int filename__read_build_id(const char *filename, void *bf, size_t size) | |||
178 | 180 | ||
179 | for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) { | 181 | for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) { |
180 | void *tmp; | 182 | void *tmp; |
183 | long offset; | ||
181 | 184 | ||
182 | if (need_swap) { | 185 | if (need_swap) { |
183 | phdr->p_type = bswap_32(phdr->p_type); | 186 | phdr->p_type = bswap_32(phdr->p_type); |
@@ -189,12 +192,13 @@ int filename__read_build_id(const char *filename, void *bf, size_t size) | |||
189 | continue; | 192 | continue; |
190 | 193 | ||
191 | buf_size = phdr->p_filesz; | 194 | buf_size = phdr->p_filesz; |
195 | offset = phdr->p_offset; | ||
192 | tmp = realloc(buf, buf_size); | 196 | tmp = realloc(buf, buf_size); |
193 | if (tmp == NULL) | 197 | if (tmp == NULL) |
194 | goto out_free; | 198 | goto out_free; |
195 | 199 | ||
196 | buf = tmp; | 200 | buf = tmp; |
197 | fseek(fp, phdr->p_offset, SEEK_SET); | 201 | fseek(fp, offset, SEEK_SET); |
198 | if (fread(buf, buf_size, 1, fp) != 1) | 202 | if (fread(buf, buf_size, 1, fp) != 1) |
199 | goto out_free; | 203 | goto out_free; |
200 | 204 | ||
@@ -341,7 +345,6 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, | |||
341 | 345 | ||
342 | if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) { | 346 | if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) { |
343 | dso__set_build_id(dso, build_id); | 347 | dso__set_build_id(dso, build_id); |
344 | return 1; | ||
345 | } | 348 | } |
346 | return 0; | 349 | return 0; |
347 | } | 350 | } |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 078331140d8c..c24c5b83156c 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -51,7 +51,9 @@ static enum dso_binary_type binary_type_symtab[] = { | |||
51 | DSO_BINARY_TYPE__BUILDID_DEBUGINFO, | 51 | DSO_BINARY_TYPE__BUILDID_DEBUGINFO, |
52 | DSO_BINARY_TYPE__SYSTEM_PATH_DSO, | 52 | DSO_BINARY_TYPE__SYSTEM_PATH_DSO, |
53 | DSO_BINARY_TYPE__GUEST_KMODULE, | 53 | DSO_BINARY_TYPE__GUEST_KMODULE, |
54 | DSO_BINARY_TYPE__GUEST_KMODULE_COMP, | ||
54 | DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, | 55 | DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, |
56 | DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP, | ||
55 | DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, | 57 | DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, |
56 | DSO_BINARY_TYPE__NOT_FOUND, | 58 | DSO_BINARY_TYPE__NOT_FOUND, |
57 | }; | 59 | }; |
@@ -1300,7 +1302,9 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod, | |||
1300 | return dso->kernel == DSO_TYPE_GUEST_KERNEL; | 1302 | return dso->kernel == DSO_TYPE_GUEST_KERNEL; |
1301 | 1303 | ||
1302 | case DSO_BINARY_TYPE__GUEST_KMODULE: | 1304 | case DSO_BINARY_TYPE__GUEST_KMODULE: |
1305 | case DSO_BINARY_TYPE__GUEST_KMODULE_COMP: | ||
1303 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: | 1306 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: |
1307 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: | ||
1304 | /* | 1308 | /* |
1305 | * kernel modules know their symtab type - it's set when | 1309 | * kernel modules know their symtab type - it's set when |
1306 | * creating a module dso in machine__new_module(). | 1310 | * creating a module dso in machine__new_module(). |
@@ -1368,7 +1372,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
1368 | return -1; | 1372 | return -1; |
1369 | 1373 | ||
1370 | kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || | 1374 | kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || |
1371 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE; | 1375 | dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || |
1376 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE || | ||
1377 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; | ||
1372 | 1378 | ||
1373 | /* | 1379 | /* |
1374 | * Iterate over candidate debug images. | 1380 | * Iterate over candidate debug images. |
@@ -1505,12 +1511,10 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, | |||
1505 | symbol_filter_t filter) | 1511 | symbol_filter_t filter) |
1506 | { | 1512 | { |
1507 | int i, err = 0; | 1513 | int i, err = 0; |
1508 | char *filename; | 1514 | char *filename = NULL; |
1509 | 1515 | ||
1510 | pr_debug("Looking at the vmlinux_path (%d entries long)\n", | 1516 | if (!symbol_conf.ignore_vmlinux_buildid) |
1511 | vmlinux_path__nr_entries + 1); | 1517 | filename = dso__build_id_filename(dso, NULL, 0); |
1512 | |||
1513 | filename = dso__build_id_filename(dso, NULL, 0); | ||
1514 | if (filename != NULL) { | 1518 | if (filename != NULL) { |
1515 | err = dso__load_vmlinux(dso, map, filename, true, filter); | 1519 | err = dso__load_vmlinux(dso, map, filename, true, filter); |
1516 | if (err > 0) | 1520 | if (err > 0) |
@@ -1518,6 +1522,9 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, | |||
1518 | free(filename); | 1522 | free(filename); |
1519 | } | 1523 | } |
1520 | 1524 | ||
1525 | pr_debug("Looking at the vmlinux_path (%d entries long)\n", | ||
1526 | vmlinux_path__nr_entries + 1); | ||
1527 | |||
1521 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { | 1528 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { |
1522 | err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter); | 1529 | err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter); |
1523 | if (err > 0) | 1530 | if (err > 0) |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index eb2c19bf8d90..9d602e9c6f59 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -23,27 +23,6 @@ | |||
23 | 23 | ||
24 | #include "dso.h" | 24 | #include "dso.h" |
25 | 25 | ||
26 | #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT | ||
27 | extern char *cplus_demangle(const char *, int); | ||
28 | |||
29 | static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i) | ||
30 | { | ||
31 | return cplus_demangle(c, i); | ||
32 | } | ||
33 | #else | ||
34 | #ifdef NO_DEMANGLE | ||
35 | static inline char *bfd_demangle(void __maybe_unused *v, | ||
36 | const char __maybe_unused *c, | ||
37 | int __maybe_unused i) | ||
38 | { | ||
39 | return NULL; | ||
40 | } | ||
41 | #else | ||
42 | #define PACKAGE 'perf' | ||
43 | #include <bfd.h> | ||
44 | #endif | ||
45 | #endif | ||
46 | |||
47 | /* | 26 | /* |
48 | * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; | 27 | * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; |
49 | * for newer versions we can use mmap to reduce memory usage: | 28 | * for newer versions we can use mmap to reduce memory usage: |
@@ -105,6 +84,7 @@ struct symbol_conf { | |||
105 | unsigned short nr_events; | 84 | unsigned short nr_events; |
106 | bool try_vmlinux_path, | 85 | bool try_vmlinux_path, |
107 | ignore_vmlinux, | 86 | ignore_vmlinux, |
87 | ignore_vmlinux_buildid, | ||
108 | show_kernel_path, | 88 | show_kernel_path, |
109 | use_modules, | 89 | use_modules, |
110 | sort_by_name, | 90 | sort_by_name, |
@@ -122,7 +102,8 @@ struct symbol_conf { | |||
122 | demangle, | 102 | demangle, |
123 | demangle_kernel, | 103 | demangle_kernel, |
124 | filter_relative, | 104 | filter_relative, |
125 | show_hist_headers; | 105 | show_hist_headers, |
106 | branch_callstack; | ||
126 | const char *vmlinux_name, | 107 | const char *vmlinux_name, |
127 | *kallsyms_name, | 108 | *kallsyms_name, |
128 | *source_prefix, | 109 | *source_prefix, |
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c new file mode 100644 index 000000000000..9ed59a452d1f --- /dev/null +++ b/tools/perf/util/thread-stack.c | |||
@@ -0,0 +1,747 @@ | |||
1 | /* | ||
2 | * thread-stack.c: Synthesize a thread's stack using call / return events | ||
3 | * Copyright (c) 2014, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/rbtree.h> | ||
17 | #include <linux/list.h> | ||
18 | #include "thread.h" | ||
19 | #include "event.h" | ||
20 | #include "machine.h" | ||
21 | #include "util.h" | ||
22 | #include "debug.h" | ||
23 | #include "symbol.h" | ||
24 | #include "comm.h" | ||
25 | #include "thread-stack.h" | ||
26 | |||
27 | #define CALL_PATH_BLOCK_SHIFT 8 | ||
28 | #define CALL_PATH_BLOCK_SIZE (1 << CALL_PATH_BLOCK_SHIFT) | ||
29 | #define CALL_PATH_BLOCK_MASK (CALL_PATH_BLOCK_SIZE - 1) | ||
30 | |||
31 | struct call_path_block { | ||
32 | struct call_path cp[CALL_PATH_BLOCK_SIZE]; | ||
33 | struct list_head node; | ||
34 | }; | ||
35 | |||
36 | /** | ||
37 | * struct call_path_root - root of all call paths. | ||
38 | * @call_path: root call path | ||
39 | * @blocks: list of blocks to store call paths | ||
40 | * @next: next free space | ||
41 | * @sz: number of spaces | ||
42 | */ | ||
43 | struct call_path_root { | ||
44 | struct call_path call_path; | ||
45 | struct list_head blocks; | ||
46 | size_t next; | ||
47 | size_t sz; | ||
48 | }; | ||
49 | |||
50 | /** | ||
51 | * struct call_return_processor - provides a call-back to consume call-return | ||
52 | * information. | ||
53 | * @cpr: call path root | ||
54 | * @process: call-back that accepts call/return information | ||
55 | * @data: anonymous data for call-back | ||
56 | */ | ||
57 | struct call_return_processor { | ||
58 | struct call_path_root *cpr; | ||
59 | int (*process)(struct call_return *cr, void *data); | ||
60 | void *data; | ||
61 | }; | ||
62 | |||
63 | #define STACK_GROWTH 2048 | ||
64 | |||
65 | /** | ||
66 | * struct thread_stack_entry - thread stack entry. | ||
67 | * @ret_addr: return address | ||
68 | * @timestamp: timestamp (if known) | ||
69 | * @ref: external reference (e.g. db_id of sample) | ||
70 | * @branch_count: the branch count when the entry was created | ||
71 | * @cp: call path | ||
72 | * @no_call: a 'call' was not seen | ||
73 | */ | ||
74 | struct thread_stack_entry { | ||
75 | u64 ret_addr; | ||
76 | u64 timestamp; | ||
77 | u64 ref; | ||
78 | u64 branch_count; | ||
79 | struct call_path *cp; | ||
80 | bool no_call; | ||
81 | }; | ||
82 | |||
83 | /** | ||
84 | * struct thread_stack - thread stack constructed from 'call' and 'return' | ||
85 | * branch samples. | ||
86 | * @stack: array that holds the stack | ||
87 | * @cnt: number of entries in the stack | ||
88 | * @sz: current maximum stack size | ||
89 | * @trace_nr: current trace number | ||
90 | * @branch_count: running branch count | ||
91 | * @kernel_start: kernel start address | ||
92 | * @last_time: last timestamp | ||
93 | * @crp: call/return processor | ||
94 | * @comm: current comm | ||
95 | */ | ||
96 | struct thread_stack { | ||
97 | struct thread_stack_entry *stack; | ||
98 | size_t cnt; | ||
99 | size_t sz; | ||
100 | u64 trace_nr; | ||
101 | u64 branch_count; | ||
102 | u64 kernel_start; | ||
103 | u64 last_time; | ||
104 | struct call_return_processor *crp; | ||
105 | struct comm *comm; | ||
106 | }; | ||
107 | |||
108 | static int thread_stack__grow(struct thread_stack *ts) | ||
109 | { | ||
110 | struct thread_stack_entry *new_stack; | ||
111 | size_t sz, new_sz; | ||
112 | |||
113 | new_sz = ts->sz + STACK_GROWTH; | ||
114 | sz = new_sz * sizeof(struct thread_stack_entry); | ||
115 | |||
116 | new_stack = realloc(ts->stack, sz); | ||
117 | if (!new_stack) | ||
118 | return -ENOMEM; | ||
119 | |||
120 | ts->stack = new_stack; | ||
121 | ts->sz = new_sz; | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static struct thread_stack *thread_stack__new(struct thread *thread, | ||
127 | struct call_return_processor *crp) | ||
128 | { | ||
129 | struct thread_stack *ts; | ||
130 | |||
131 | ts = zalloc(sizeof(struct thread_stack)); | ||
132 | if (!ts) | ||
133 | return NULL; | ||
134 | |||
135 | if (thread_stack__grow(ts)) { | ||
136 | free(ts); | ||
137 | return NULL; | ||
138 | } | ||
139 | |||
140 | if (thread->mg && thread->mg->machine) | ||
141 | ts->kernel_start = machine__kernel_start(thread->mg->machine); | ||
142 | else | ||
143 | ts->kernel_start = 1ULL << 63; | ||
144 | ts->crp = crp; | ||
145 | |||
146 | return ts; | ||
147 | } | ||
148 | |||
149 | static int thread_stack__push(struct thread_stack *ts, u64 ret_addr) | ||
150 | { | ||
151 | int err = 0; | ||
152 | |||
153 | if (ts->cnt == ts->sz) { | ||
154 | err = thread_stack__grow(ts); | ||
155 | if (err) { | ||
156 | pr_warning("Out of memory: discarding thread stack\n"); | ||
157 | ts->cnt = 0; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | ts->stack[ts->cnt++].ret_addr = ret_addr; | ||
162 | |||
163 | return err; | ||
164 | } | ||
165 | |||
166 | static void thread_stack__pop(struct thread_stack *ts, u64 ret_addr) | ||
167 | { | ||
168 | size_t i; | ||
169 | |||
170 | /* | ||
171 | * In some cases there may be functions which are not seen to return. | ||
172 | * For example when setjmp / longjmp has been used. Or the perf context | ||
173 | * switch in the kernel which doesn't stop and start tracing in exactly | ||
174 | * the same code path. When that happens the return address will be | ||
175 | * further down the stack. If the return address is not found at all, | ||
176 | * we assume the opposite (i.e. this is a return for a call that wasn't | ||
177 | * seen for some reason) and leave the stack alone. | ||
178 | */ | ||
179 | for (i = ts->cnt; i; ) { | ||
180 | if (ts->stack[--i].ret_addr == ret_addr) { | ||
181 | ts->cnt = i; | ||
182 | return; | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | |||
187 | static bool thread_stack__in_kernel(struct thread_stack *ts) | ||
188 | { | ||
189 | if (!ts->cnt) | ||
190 | return false; | ||
191 | |||
192 | return ts->stack[ts->cnt - 1].cp->in_kernel; | ||
193 | } | ||
194 | |||
195 | static int thread_stack__call_return(struct thread *thread, | ||
196 | struct thread_stack *ts, size_t idx, | ||
197 | u64 timestamp, u64 ref, bool no_return) | ||
198 | { | ||
199 | struct call_return_processor *crp = ts->crp; | ||
200 | struct thread_stack_entry *tse; | ||
201 | struct call_return cr = { | ||
202 | .thread = thread, | ||
203 | .comm = ts->comm, | ||
204 | .db_id = 0, | ||
205 | }; | ||
206 | |||
207 | tse = &ts->stack[idx]; | ||
208 | cr.cp = tse->cp; | ||
209 | cr.call_time = tse->timestamp; | ||
210 | cr.return_time = timestamp; | ||
211 | cr.branch_count = ts->branch_count - tse->branch_count; | ||
212 | cr.call_ref = tse->ref; | ||
213 | cr.return_ref = ref; | ||
214 | if (tse->no_call) | ||
215 | cr.flags |= CALL_RETURN_NO_CALL; | ||
216 | if (no_return) | ||
217 | cr.flags |= CALL_RETURN_NO_RETURN; | ||
218 | |||
219 | return crp->process(&cr, crp->data); | ||
220 | } | ||
221 | |||
222 | static int thread_stack__flush(struct thread *thread, struct thread_stack *ts) | ||
223 | { | ||
224 | struct call_return_processor *crp = ts->crp; | ||
225 | int err; | ||
226 | |||
227 | if (!crp) { | ||
228 | ts->cnt = 0; | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | while (ts->cnt) { | ||
233 | err = thread_stack__call_return(thread, ts, --ts->cnt, | ||
234 | ts->last_time, 0, true); | ||
235 | if (err) { | ||
236 | pr_err("Error flushing thread stack!\n"); | ||
237 | ts->cnt = 0; | ||
238 | return err; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip, | ||
246 | u64 to_ip, u16 insn_len, u64 trace_nr) | ||
247 | { | ||
248 | if (!thread) | ||
249 | return -EINVAL; | ||
250 | |||
251 | if (!thread->ts) { | ||
252 | thread->ts = thread_stack__new(thread, NULL); | ||
253 | if (!thread->ts) { | ||
254 | pr_warning("Out of memory: no thread stack\n"); | ||
255 | return -ENOMEM; | ||
256 | } | ||
257 | thread->ts->trace_nr = trace_nr; | ||
258 | } | ||
259 | |||
260 | /* | ||
261 | * When the trace is discontinuous, the trace_nr changes. In that case | ||
262 | * the stack might be completely invalid. Better to report nothing than | ||
263 | * to report something misleading, so flush the stack. | ||
264 | */ | ||
265 | if (trace_nr != thread->ts->trace_nr) { | ||
266 | if (thread->ts->trace_nr) | ||
267 | thread_stack__flush(thread, thread->ts); | ||
268 | thread->ts->trace_nr = trace_nr; | ||
269 | } | ||
270 | |||
271 | /* Stop here if thread_stack__process() is in use */ | ||
272 | if (thread->ts->crp) | ||
273 | return 0; | ||
274 | |||
275 | if (flags & PERF_IP_FLAG_CALL) { | ||
276 | u64 ret_addr; | ||
277 | |||
278 | if (!to_ip) | ||
279 | return 0; | ||
280 | ret_addr = from_ip + insn_len; | ||
281 | if (ret_addr == to_ip) | ||
282 | return 0; /* Zero-length calls are excluded */ | ||
283 | return thread_stack__push(thread->ts, ret_addr); | ||
284 | } else if (flags & PERF_IP_FLAG_RETURN) { | ||
285 | if (!from_ip) | ||
286 | return 0; | ||
287 | thread_stack__pop(thread->ts, to_ip); | ||
288 | } | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr) | ||
294 | { | ||
295 | if (!thread || !thread->ts) | ||
296 | return; | ||
297 | |||
298 | if (trace_nr != thread->ts->trace_nr) { | ||
299 | if (thread->ts->trace_nr) | ||
300 | thread_stack__flush(thread, thread->ts); | ||
301 | thread->ts->trace_nr = trace_nr; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | void thread_stack__free(struct thread *thread) | ||
306 | { | ||
307 | if (thread->ts) { | ||
308 | thread_stack__flush(thread, thread->ts); | ||
309 | zfree(&thread->ts->stack); | ||
310 | zfree(&thread->ts); | ||
311 | } | ||
312 | } | ||
313 | |||
314 | void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, | ||
315 | size_t sz, u64 ip) | ||
316 | { | ||
317 | size_t i; | ||
318 | |||
319 | if (!thread || !thread->ts) | ||
320 | chain->nr = 1; | ||
321 | else | ||
322 | chain->nr = min(sz, thread->ts->cnt + 1); | ||
323 | |||
324 | chain->ips[0] = ip; | ||
325 | |||
326 | for (i = 1; i < chain->nr; i++) | ||
327 | chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr; | ||
328 | } | ||
329 | |||
330 | static void call_path__init(struct call_path *cp, struct call_path *parent, | ||
331 | struct symbol *sym, u64 ip, bool in_kernel) | ||
332 | { | ||
333 | cp->parent = parent; | ||
334 | cp->sym = sym; | ||
335 | cp->ip = sym ? 0 : ip; | ||
336 | cp->db_id = 0; | ||
337 | cp->in_kernel = in_kernel; | ||
338 | RB_CLEAR_NODE(&cp->rb_node); | ||
339 | cp->children = RB_ROOT; | ||
340 | } | ||
341 | |||
342 | static struct call_path_root *call_path_root__new(void) | ||
343 | { | ||
344 | struct call_path_root *cpr; | ||
345 | |||
346 | cpr = zalloc(sizeof(struct call_path_root)); | ||
347 | if (!cpr) | ||
348 | return NULL; | ||
349 | call_path__init(&cpr->call_path, NULL, NULL, 0, false); | ||
350 | INIT_LIST_HEAD(&cpr->blocks); | ||
351 | return cpr; | ||
352 | } | ||
353 | |||
354 | static void call_path_root__free(struct call_path_root *cpr) | ||
355 | { | ||
356 | struct call_path_block *pos, *n; | ||
357 | |||
358 | list_for_each_entry_safe(pos, n, &cpr->blocks, node) { | ||
359 | list_del(&pos->node); | ||
360 | free(pos); | ||
361 | } | ||
362 | free(cpr); | ||
363 | } | ||
364 | |||
365 | static struct call_path *call_path__new(struct call_path_root *cpr, | ||
366 | struct call_path *parent, | ||
367 | struct symbol *sym, u64 ip, | ||
368 | bool in_kernel) | ||
369 | { | ||
370 | struct call_path_block *cpb; | ||
371 | struct call_path *cp; | ||
372 | size_t n; | ||
373 | |||
374 | if (cpr->next < cpr->sz) { | ||
375 | cpb = list_last_entry(&cpr->blocks, struct call_path_block, | ||
376 | node); | ||
377 | } else { | ||
378 | cpb = zalloc(sizeof(struct call_path_block)); | ||
379 | if (!cpb) | ||
380 | return NULL; | ||
381 | list_add_tail(&cpb->node, &cpr->blocks); | ||
382 | cpr->sz += CALL_PATH_BLOCK_SIZE; | ||
383 | } | ||
384 | |||
385 | n = cpr->next++ & CALL_PATH_BLOCK_MASK; | ||
386 | cp = &cpb->cp[n]; | ||
387 | |||
388 | call_path__init(cp, parent, sym, ip, in_kernel); | ||
389 | |||
390 | return cp; | ||
391 | } | ||
392 | |||
393 | static struct call_path *call_path__findnew(struct call_path_root *cpr, | ||
394 | struct call_path *parent, | ||
395 | struct symbol *sym, u64 ip, u64 ks) | ||
396 | { | ||
397 | struct rb_node **p; | ||
398 | struct rb_node *node_parent = NULL; | ||
399 | struct call_path *cp; | ||
400 | bool in_kernel = ip >= ks; | ||
401 | |||
402 | if (sym) | ||
403 | ip = 0; | ||
404 | |||
405 | if (!parent) | ||
406 | return call_path__new(cpr, parent, sym, ip, in_kernel); | ||
407 | |||
408 | p = &parent->children.rb_node; | ||
409 | while (*p != NULL) { | ||
410 | node_parent = *p; | ||
411 | cp = rb_entry(node_parent, struct call_path, rb_node); | ||
412 | |||
413 | if (cp->sym == sym && cp->ip == ip) | ||
414 | return cp; | ||
415 | |||
416 | if (sym < cp->sym || (sym == cp->sym && ip < cp->ip)) | ||
417 | p = &(*p)->rb_left; | ||
418 | else | ||
419 | p = &(*p)->rb_right; | ||
420 | } | ||
421 | |||
422 | cp = call_path__new(cpr, parent, sym, ip, in_kernel); | ||
423 | if (!cp) | ||
424 | return NULL; | ||
425 | |||
426 | rb_link_node(&cp->rb_node, node_parent, p); | ||
427 | rb_insert_color(&cp->rb_node, &parent->children); | ||
428 | |||
429 | return cp; | ||
430 | } | ||
431 | |||
432 | struct call_return_processor * | ||
433 | call_return_processor__new(int (*process)(struct call_return *cr, void *data), | ||
434 | void *data) | ||
435 | { | ||
436 | struct call_return_processor *crp; | ||
437 | |||
438 | crp = zalloc(sizeof(struct call_return_processor)); | ||
439 | if (!crp) | ||
440 | return NULL; | ||
441 | crp->cpr = call_path_root__new(); | ||
442 | if (!crp->cpr) | ||
443 | goto out_free; | ||
444 | crp->process = process; | ||
445 | crp->data = data; | ||
446 | return crp; | ||
447 | |||
448 | out_free: | ||
449 | free(crp); | ||
450 | return NULL; | ||
451 | } | ||
452 | |||
453 | void call_return_processor__free(struct call_return_processor *crp) | ||
454 | { | ||
455 | if (crp) { | ||
456 | call_path_root__free(crp->cpr); | ||
457 | free(crp); | ||
458 | } | ||
459 | } | ||
460 | |||
461 | static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr, | ||
462 | u64 timestamp, u64 ref, struct call_path *cp, | ||
463 | bool no_call) | ||
464 | { | ||
465 | struct thread_stack_entry *tse; | ||
466 | int err; | ||
467 | |||
468 | if (ts->cnt == ts->sz) { | ||
469 | err = thread_stack__grow(ts); | ||
470 | if (err) | ||
471 | return err; | ||
472 | } | ||
473 | |||
474 | tse = &ts->stack[ts->cnt++]; | ||
475 | tse->ret_addr = ret_addr; | ||
476 | tse->timestamp = timestamp; | ||
477 | tse->ref = ref; | ||
478 | tse->branch_count = ts->branch_count; | ||
479 | tse->cp = cp; | ||
480 | tse->no_call = no_call; | ||
481 | |||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | static int thread_stack__pop_cp(struct thread *thread, struct thread_stack *ts, | ||
486 | u64 ret_addr, u64 timestamp, u64 ref, | ||
487 | struct symbol *sym) | ||
488 | { | ||
489 | int err; | ||
490 | |||
491 | if (!ts->cnt) | ||
492 | return 1; | ||
493 | |||
494 | if (ts->cnt == 1) { | ||
495 | struct thread_stack_entry *tse = &ts->stack[0]; | ||
496 | |||
497 | if (tse->cp->sym == sym) | ||
498 | return thread_stack__call_return(thread, ts, --ts->cnt, | ||
499 | timestamp, ref, false); | ||
500 | } | ||
501 | |||
502 | if (ts->stack[ts->cnt - 1].ret_addr == ret_addr) { | ||
503 | return thread_stack__call_return(thread, ts, --ts->cnt, | ||
504 | timestamp, ref, false); | ||
505 | } else { | ||
506 | size_t i = ts->cnt - 1; | ||
507 | |||
508 | while (i--) { | ||
509 | if (ts->stack[i].ret_addr != ret_addr) | ||
510 | continue; | ||
511 | i += 1; | ||
512 | while (ts->cnt > i) { | ||
513 | err = thread_stack__call_return(thread, ts, | ||
514 | --ts->cnt, | ||
515 | timestamp, ref, | ||
516 | true); | ||
517 | if (err) | ||
518 | return err; | ||
519 | } | ||
520 | return thread_stack__call_return(thread, ts, --ts->cnt, | ||
521 | timestamp, ref, false); | ||
522 | } | ||
523 | } | ||
524 | |||
525 | return 1; | ||
526 | } | ||
527 | |||
528 | static int thread_stack__bottom(struct thread *thread, struct thread_stack *ts, | ||
529 | struct perf_sample *sample, | ||
530 | struct addr_location *from_al, | ||
531 | struct addr_location *to_al, u64 ref) | ||
532 | { | ||
533 | struct call_path_root *cpr = ts->crp->cpr; | ||
534 | struct call_path *cp; | ||
535 | struct symbol *sym; | ||
536 | u64 ip; | ||
537 | |||
538 | if (sample->ip) { | ||
539 | ip = sample->ip; | ||
540 | sym = from_al->sym; | ||
541 | } else if (sample->addr) { | ||
542 | ip = sample->addr; | ||
543 | sym = to_al->sym; | ||
544 | } else { | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | cp = call_path__findnew(cpr, &cpr->call_path, sym, ip, | ||
549 | ts->kernel_start); | ||
550 | if (!cp) | ||
551 | return -ENOMEM; | ||
552 | |||
553 | return thread_stack__push_cp(thread->ts, ip, sample->time, ref, cp, | ||
554 | true); | ||
555 | } | ||
556 | |||
557 | static int thread_stack__no_call_return(struct thread *thread, | ||
558 | struct thread_stack *ts, | ||
559 | struct perf_sample *sample, | ||
560 | struct addr_location *from_al, | ||
561 | struct addr_location *to_al, u64 ref) | ||
562 | { | ||
563 | struct call_path_root *cpr = ts->crp->cpr; | ||
564 | struct call_path *cp, *parent; | ||
565 | u64 ks = ts->kernel_start; | ||
566 | int err; | ||
567 | |||
568 | if (sample->ip >= ks && sample->addr < ks) { | ||
569 | /* Return to userspace, so pop all kernel addresses */ | ||
570 | while (thread_stack__in_kernel(ts)) { | ||
571 | err = thread_stack__call_return(thread, ts, --ts->cnt, | ||
572 | sample->time, ref, | ||
573 | true); | ||
574 | if (err) | ||
575 | return err; | ||
576 | } | ||
577 | |||
578 | /* If the stack is empty, push the userspace address */ | ||
579 | if (!ts->cnt) { | ||
580 | cp = call_path__findnew(cpr, &cpr->call_path, | ||
581 | to_al->sym, sample->addr, | ||
582 | ts->kernel_start); | ||
583 | if (!cp) | ||
584 | return -ENOMEM; | ||
585 | return thread_stack__push_cp(ts, 0, sample->time, ref, | ||
586 | cp, true); | ||
587 | } | ||
588 | } else if (thread_stack__in_kernel(ts) && sample->ip < ks) { | ||
589 | /* Return to userspace, so pop all kernel addresses */ | ||
590 | while (thread_stack__in_kernel(ts)) { | ||
591 | err = thread_stack__call_return(thread, ts, --ts->cnt, | ||
592 | sample->time, ref, | ||
593 | true); | ||
594 | if (err) | ||
595 | return err; | ||
596 | } | ||
597 | } | ||
598 | |||
599 | if (ts->cnt) | ||
600 | parent = ts->stack[ts->cnt - 1].cp; | ||
601 | else | ||
602 | parent = &cpr->call_path; | ||
603 | |||
604 | /* This 'return' had no 'call', so push and pop top of stack */ | ||
605 | cp = call_path__findnew(cpr, parent, from_al->sym, sample->ip, | ||
606 | ts->kernel_start); | ||
607 | if (!cp) | ||
608 | return -ENOMEM; | ||
609 | |||
610 | err = thread_stack__push_cp(ts, sample->addr, sample->time, ref, cp, | ||
611 | true); | ||
612 | if (err) | ||
613 | return err; | ||
614 | |||
615 | return thread_stack__pop_cp(thread, ts, sample->addr, sample->time, ref, | ||
616 | to_al->sym); | ||
617 | } | ||
618 | |||
619 | static int thread_stack__trace_begin(struct thread *thread, | ||
620 | struct thread_stack *ts, u64 timestamp, | ||
621 | u64 ref) | ||
622 | { | ||
623 | struct thread_stack_entry *tse; | ||
624 | int err; | ||
625 | |||
626 | if (!ts->cnt) | ||
627 | return 0; | ||
628 | |||
629 | /* Pop trace end */ | ||
630 | tse = &ts->stack[ts->cnt - 1]; | ||
631 | if (tse->cp->sym == NULL && tse->cp->ip == 0) { | ||
632 | err = thread_stack__call_return(thread, ts, --ts->cnt, | ||
633 | timestamp, ref, false); | ||
634 | if (err) | ||
635 | return err; | ||
636 | } | ||
637 | |||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | static int thread_stack__trace_end(struct thread_stack *ts, | ||
642 | struct perf_sample *sample, u64 ref) | ||
643 | { | ||
644 | struct call_path_root *cpr = ts->crp->cpr; | ||
645 | struct call_path *cp; | ||
646 | u64 ret_addr; | ||
647 | |||
648 | /* No point having 'trace end' on the bottom of the stack */ | ||
649 | if (!ts->cnt || (ts->cnt == 1 && ts->stack[0].ref == ref)) | ||
650 | return 0; | ||
651 | |||
652 | cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp, NULL, 0, | ||
653 | ts->kernel_start); | ||
654 | if (!cp) | ||
655 | return -ENOMEM; | ||
656 | |||
657 | ret_addr = sample->ip + sample->insn_len; | ||
658 | |||
659 | return thread_stack__push_cp(ts, ret_addr, sample->time, ref, cp, | ||
660 | false); | ||
661 | } | ||
662 | |||
663 | int thread_stack__process(struct thread *thread, struct comm *comm, | ||
664 | struct perf_sample *sample, | ||
665 | struct addr_location *from_al, | ||
666 | struct addr_location *to_al, u64 ref, | ||
667 | struct call_return_processor *crp) | ||
668 | { | ||
669 | struct thread_stack *ts = thread->ts; | ||
670 | int err = 0; | ||
671 | |||
672 | if (ts) { | ||
673 | if (!ts->crp) { | ||
674 | /* Supersede thread_stack__event() */ | ||
675 | thread_stack__free(thread); | ||
676 | thread->ts = thread_stack__new(thread, crp); | ||
677 | if (!thread->ts) | ||
678 | return -ENOMEM; | ||
679 | ts = thread->ts; | ||
680 | ts->comm = comm; | ||
681 | } | ||
682 | } else { | ||
683 | thread->ts = thread_stack__new(thread, crp); | ||
684 | if (!thread->ts) | ||
685 | return -ENOMEM; | ||
686 | ts = thread->ts; | ||
687 | ts->comm = comm; | ||
688 | } | ||
689 | |||
690 | /* Flush stack on exec */ | ||
691 | if (ts->comm != comm && thread->pid_ == thread->tid) { | ||
692 | err = thread_stack__flush(thread, ts); | ||
693 | if (err) | ||
694 | return err; | ||
695 | ts->comm = comm; | ||
696 | } | ||
697 | |||
698 | /* If the stack is empty, put the current symbol on the stack */ | ||
699 | if (!ts->cnt) { | ||
700 | err = thread_stack__bottom(thread, ts, sample, from_al, to_al, | ||
701 | ref); | ||
702 | if (err) | ||
703 | return err; | ||
704 | } | ||
705 | |||
706 | ts->branch_count += 1; | ||
707 | ts->last_time = sample->time; | ||
708 | |||
709 | if (sample->flags & PERF_IP_FLAG_CALL) { | ||
710 | struct call_path_root *cpr = ts->crp->cpr; | ||
711 | struct call_path *cp; | ||
712 | u64 ret_addr; | ||
713 | |||
714 | if (!sample->ip || !sample->addr) | ||
715 | return 0; | ||
716 | |||
717 | ret_addr = sample->ip + sample->insn_len; | ||
718 | if (ret_addr == sample->addr) | ||
719 | return 0; /* Zero-length calls are excluded */ | ||
720 | |||
721 | cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp, | ||
722 | to_al->sym, sample->addr, | ||
723 | ts->kernel_start); | ||
724 | if (!cp) | ||
725 | return -ENOMEM; | ||
726 | err = thread_stack__push_cp(ts, ret_addr, sample->time, ref, | ||
727 | cp, false); | ||
728 | } else if (sample->flags & PERF_IP_FLAG_RETURN) { | ||
729 | if (!sample->ip || !sample->addr) | ||
730 | return 0; | ||
731 | |||
732 | err = thread_stack__pop_cp(thread, ts, sample->addr, | ||
733 | sample->time, ref, from_al->sym); | ||
734 | if (err) { | ||
735 | if (err < 0) | ||
736 | return err; | ||
737 | err = thread_stack__no_call_return(thread, ts, sample, | ||
738 | from_al, to_al, ref); | ||
739 | } | ||
740 | } else if (sample->flags & PERF_IP_FLAG_TRACE_BEGIN) { | ||
741 | err = thread_stack__trace_begin(thread, ts, sample->time, ref); | ||
742 | } else if (sample->flags & PERF_IP_FLAG_TRACE_END) { | ||
743 | err = thread_stack__trace_end(ts, sample, ref); | ||
744 | } | ||
745 | |||
746 | return err; | ||
747 | } | ||
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h new file mode 100644 index 000000000000..b843bbef8ba2 --- /dev/null +++ b/tools/perf/util/thread-stack.h | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * thread-stack.h: Synthesize a thread's stack using call / return events | ||
3 | * Copyright (c) 2014, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #ifndef __PERF_THREAD_STACK_H | ||
17 | #define __PERF_THREAD_STACK_H | ||
18 | |||
19 | #include <sys/types.h> | ||
20 | |||
21 | #include <linux/types.h> | ||
22 | #include <linux/rbtree.h> | ||
23 | |||
24 | struct thread; | ||
25 | struct comm; | ||
26 | struct ip_callchain; | ||
27 | struct symbol; | ||
28 | struct dso; | ||
29 | struct call_return_processor; | ||
30 | struct comm; | ||
31 | struct perf_sample; | ||
32 | struct addr_location; | ||
33 | |||
34 | /* | ||
35 | * Call/Return flags. | ||
36 | * | ||
37 | * CALL_RETURN_NO_CALL: 'return' but no matching 'call' | ||
38 | * CALL_RETURN_NO_RETURN: 'call' but no matching 'return' | ||
39 | */ | ||
40 | enum { | ||
41 | CALL_RETURN_NO_CALL = 1 << 0, | ||
42 | CALL_RETURN_NO_RETURN = 1 << 1, | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * struct call_return - paired call/return information. | ||
47 | * @thread: thread in which call/return occurred | ||
48 | * @comm: comm in which call/return occurred | ||
49 | * @cp: call path | ||
50 | * @call_time: timestamp of call (if known) | ||
51 | * @return_time: timestamp of return (if known) | ||
52 | * @branch_count: number of branches seen between call and return | ||
53 | * @call_ref: external reference to 'call' sample (e.g. db_id) | ||
54 | * @return_ref: external reference to 'return' sample (e.g. db_id) | ||
55 | * @db_id: id used for db-export | ||
56 | * @flags: Call/Return flags | ||
57 | */ | ||
58 | struct call_return { | ||
59 | struct thread *thread; | ||
60 | struct comm *comm; | ||
61 | struct call_path *cp; | ||
62 | u64 call_time; | ||
63 | u64 return_time; | ||
64 | u64 branch_count; | ||
65 | u64 call_ref; | ||
66 | u64 return_ref; | ||
67 | u64 db_id; | ||
68 | u32 flags; | ||
69 | }; | ||
70 | |||
71 | /** | ||
72 | * struct call_path - node in list of calls leading to a function call. | ||
73 | * @parent: call path to the parent function call | ||
74 | * @sym: symbol of function called | ||
75 | * @ip: only if sym is null, the ip of the function | ||
76 | * @db_id: id used for db-export | ||
77 | * @in_kernel: whether function is a in the kernel | ||
78 | * @rb_node: node in parent's tree of called functions | ||
79 | * @children: tree of call paths of functions called | ||
80 | * | ||
81 | * In combination with the call_return structure, the call_path structure | ||
82 | * defines a context-sensitve call-graph. | ||
83 | */ | ||
84 | struct call_path { | ||
85 | struct call_path *parent; | ||
86 | struct symbol *sym; | ||
87 | u64 ip; | ||
88 | u64 db_id; | ||
89 | bool in_kernel; | ||
90 | struct rb_node rb_node; | ||
91 | struct rb_root children; | ||
92 | }; | ||
93 | |||
94 | int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip, | ||
95 | u64 to_ip, u16 insn_len, u64 trace_nr); | ||
96 | void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr); | ||
97 | void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, | ||
98 | size_t sz, u64 ip); | ||
99 | void thread_stack__free(struct thread *thread); | ||
100 | |||
101 | struct call_return_processor * | ||
102 | call_return_processor__new(int (*process)(struct call_return *cr, void *data), | ||
103 | void *data); | ||
104 | void call_return_processor__free(struct call_return_processor *crp); | ||
105 | int thread_stack__process(struct thread *thread, struct comm *comm, | ||
106 | struct perf_sample *sample, | ||
107 | struct addr_location *from_al, | ||
108 | struct addr_location *to_al, u64 ref, | ||
109 | struct call_return_processor *crp); | ||
110 | |||
111 | #endif | ||
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index c41411726c7a..9ebc8b1f9be5 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <string.h> | 4 | #include <string.h> |
5 | #include "session.h" | 5 | #include "session.h" |
6 | #include "thread.h" | 6 | #include "thread.h" |
7 | #include "thread-stack.h" | ||
7 | #include "util.h" | 8 | #include "util.h" |
8 | #include "debug.h" | 9 | #include "debug.h" |
9 | #include "comm.h" | 10 | #include "comm.h" |
@@ -15,7 +16,7 @@ int thread__init_map_groups(struct thread *thread, struct machine *machine) | |||
15 | pid_t pid = thread->pid_; | 16 | pid_t pid = thread->pid_; |
16 | 17 | ||
17 | if (pid == thread->tid || pid == -1) { | 18 | if (pid == thread->tid || pid == -1) { |
18 | thread->mg = map_groups__new(); | 19 | thread->mg = map_groups__new(machine); |
19 | } else { | 20 | } else { |
20 | leader = machine__findnew_thread(machine, pid, pid); | 21 | leader = machine__findnew_thread(machine, pid, pid); |
21 | if (leader) | 22 | if (leader) |
@@ -66,6 +67,8 @@ void thread__delete(struct thread *thread) | |||
66 | { | 67 | { |
67 | struct comm *comm, *tmp; | 68 | struct comm *comm, *tmp; |
68 | 69 | ||
70 | thread_stack__free(thread); | ||
71 | |||
69 | if (thread->mg) { | 72 | if (thread->mg) { |
70 | map_groups__put(thread->mg); | 73 | map_groups__put(thread->mg); |
71 | thread->mg = NULL; | 74 | thread->mg = NULL; |
@@ -100,15 +103,14 @@ struct comm *thread__exec_comm(const struct thread *thread) | |||
100 | return last; | 103 | return last; |
101 | } | 104 | } |
102 | 105 | ||
103 | /* CHECKME: time should always be 0 if event aren't ordered */ | ||
104 | int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, | 106 | int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, |
105 | bool exec) | 107 | bool exec) |
106 | { | 108 | { |
107 | struct comm *new, *curr = thread__comm(thread); | 109 | struct comm *new, *curr = thread__comm(thread); |
108 | int err; | 110 | int err; |
109 | 111 | ||
110 | /* Override latest entry if it had no specific time coverage */ | 112 | /* Override the default :tid entry */ |
111 | if (!curr->start && !curr->exec) { | 113 | if (!thread->comm_set) { |
112 | err = comm__override(curr, str, timestamp, exec); | 114 | err = comm__override(curr, str, timestamp, exec); |
113 | if (err) | 115 | if (err) |
114 | return err; | 116 | return err; |
@@ -198,7 +200,6 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) | |||
198 | } | 200 | } |
199 | 201 | ||
200 | void thread__find_cpumode_addr_location(struct thread *thread, | 202 | void thread__find_cpumode_addr_location(struct thread *thread, |
201 | struct machine *machine, | ||
202 | enum map_type type, u64 addr, | 203 | enum map_type type, u64 addr, |
203 | struct addr_location *al) | 204 | struct addr_location *al) |
204 | { | 205 | { |
@@ -211,8 +212,7 @@ void thread__find_cpumode_addr_location(struct thread *thread, | |||
211 | }; | 212 | }; |
212 | 213 | ||
213 | for (i = 0; i < ARRAY_SIZE(cpumodes); i++) { | 214 | for (i = 0; i < ARRAY_SIZE(cpumodes); i++) { |
214 | thread__find_addr_location(thread, machine, cpumodes[i], type, | 215 | thread__find_addr_location(thread, cpumodes[i], type, addr, al); |
215 | addr, al); | ||
216 | if (al->map) | 216 | if (al->map) |
217 | break; | 217 | break; |
218 | } | 218 | } |
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 8c75fa774706..160fd066a7d1 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
@@ -8,6 +8,8 @@ | |||
8 | #include "symbol.h" | 8 | #include "symbol.h" |
9 | #include <strlist.h> | 9 | #include <strlist.h> |
10 | 10 | ||
11 | struct thread_stack; | ||
12 | |||
11 | struct thread { | 13 | struct thread { |
12 | union { | 14 | union { |
13 | struct rb_node rb_node; | 15 | struct rb_node rb_node; |
@@ -23,8 +25,10 @@ struct thread { | |||
23 | bool dead; /* if set thread has exited */ | 25 | bool dead; /* if set thread has exited */ |
24 | struct list_head comm_list; | 26 | struct list_head comm_list; |
25 | int comm_len; | 27 | int comm_len; |
28 | u64 db_id; | ||
26 | 29 | ||
27 | void *priv; | 30 | void *priv; |
31 | struct thread_stack *ts; | ||
28 | }; | 32 | }; |
29 | 33 | ||
30 | struct machine; | 34 | struct machine; |
@@ -54,16 +58,15 @@ void thread__insert_map(struct thread *thread, struct map *map); | |||
54 | int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); | 58 | int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); |
55 | size_t thread__fprintf(struct thread *thread, FILE *fp); | 59 | size_t thread__fprintf(struct thread *thread, FILE *fp); |
56 | 60 | ||
57 | void thread__find_addr_map(struct thread *thread, struct machine *machine, | 61 | void thread__find_addr_map(struct thread *thread, |
58 | u8 cpumode, enum map_type type, u64 addr, | 62 | u8 cpumode, enum map_type type, u64 addr, |
59 | struct addr_location *al); | 63 | struct addr_location *al); |
60 | 64 | ||
61 | void thread__find_addr_location(struct thread *thread, struct machine *machine, | 65 | void thread__find_addr_location(struct thread *thread, |
62 | u8 cpumode, enum map_type type, u64 addr, | 66 | u8 cpumode, enum map_type type, u64 addr, |
63 | struct addr_location *al); | 67 | struct addr_location *al); |
64 | 68 | ||
65 | void thread__find_cpumode_addr_location(struct thread *thread, | 69 | void thread__find_cpumode_addr_location(struct thread *thread, |
66 | struct machine *machine, | ||
67 | enum map_type type, u64 addr, | 70 | enum map_type type, u64 addr, |
68 | struct addr_location *al); | 71 | struct addr_location *al); |
69 | 72 | ||
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index f11636966a0f..bb2708bbfaca 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h | |||
@@ -39,7 +39,8 @@ struct perf_tool { | |||
39 | event_attr_op attr; | 39 | event_attr_op attr; |
40 | event_op2 tracing_data; | 40 | event_op2 tracing_data; |
41 | event_op2 finished_round, | 41 | event_op2 finished_round, |
42 | build_id; | 42 | build_id, |
43 | id_index; | ||
43 | bool ordered_events; | 44 | bool ordered_events; |
44 | bool ordering_requires_timestamps; | 45 | bool ordering_requires_timestamps; |
45 | }; | 46 | }; |
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c index 7419768c38b1..2dcfe9a7c8d0 100644 --- a/tools/perf/util/unwind-libdw.c +++ b/tools/perf/util/unwind-libdw.c | |||
@@ -26,7 +26,7 @@ static int __report_module(struct addr_location *al, u64 ip, | |||
26 | Dwfl_Module *mod; | 26 | Dwfl_Module *mod; |
27 | struct dso *dso = NULL; | 27 | struct dso *dso = NULL; |
28 | 28 | ||
29 | thread__find_addr_location(ui->thread, ui->machine, | 29 | thread__find_addr_location(ui->thread, |
30 | PERF_RECORD_MISC_USER, | 30 | PERF_RECORD_MISC_USER, |
31 | MAP__FUNCTION, ip, al); | 31 | MAP__FUNCTION, ip, al); |
32 | 32 | ||
@@ -89,7 +89,7 @@ static int access_dso_mem(struct unwind_info *ui, Dwarf_Addr addr, | |||
89 | struct addr_location al; | 89 | struct addr_location al; |
90 | ssize_t size; | 90 | ssize_t size; |
91 | 91 | ||
92 | thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, | 92 | thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER, |
93 | MAP__FUNCTION, addr, &al); | 93 | MAP__FUNCTION, addr, &al); |
94 | if (!al.map) { | 94 | if (!al.map) { |
95 | pr_debug("unwind: no map for %lx\n", (unsigned long)addr); | 95 | pr_debug("unwind: no map for %lx\n", (unsigned long)addr); |
@@ -164,14 +164,14 @@ frame_callback(Dwfl_Frame *state, void *arg) | |||
164 | } | 164 | } |
165 | 165 | ||
166 | int unwind__get_entries(unwind_entry_cb_t cb, void *arg, | 166 | int unwind__get_entries(unwind_entry_cb_t cb, void *arg, |
167 | struct machine *machine, struct thread *thread, | 167 | struct thread *thread, |
168 | struct perf_sample *data, | 168 | struct perf_sample *data, |
169 | int max_stack) | 169 | int max_stack) |
170 | { | 170 | { |
171 | struct unwind_info ui = { | 171 | struct unwind_info ui = { |
172 | .sample = data, | 172 | .sample = data, |
173 | .thread = thread, | 173 | .thread = thread, |
174 | .machine = machine, | 174 | .machine = thread->mg->machine, |
175 | .cb = cb, | 175 | .cb = cb, |
176 | .arg = arg, | 176 | .arg = arg, |
177 | .max_stack = max_stack, | 177 | .max_stack = max_stack, |
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index 4d45c0dfe343..6edf535f65c2 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c | |||
@@ -185,6 +185,28 @@ static u64 elf_section_offset(int fd, const char *name) | |||
185 | return offset; | 185 | return offset; |
186 | } | 186 | } |
187 | 187 | ||
188 | #ifndef NO_LIBUNWIND_DEBUG_FRAME | ||
189 | static int elf_is_exec(int fd, const char *name) | ||
190 | { | ||
191 | Elf *elf; | ||
192 | GElf_Ehdr ehdr; | ||
193 | int retval = 0; | ||
194 | |||
195 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | ||
196 | if (elf == NULL) | ||
197 | return 0; | ||
198 | if (gelf_getehdr(elf, &ehdr) == NULL) | ||
199 | goto out; | ||
200 | |||
201 | retval = (ehdr.e_type == ET_EXEC); | ||
202 | |||
203 | out: | ||
204 | elf_end(elf); | ||
205 | pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval); | ||
206 | return retval; | ||
207 | } | ||
208 | #endif | ||
209 | |||
188 | struct table_entry { | 210 | struct table_entry { |
189 | u32 start_ip_offset; | 211 | u32 start_ip_offset; |
190 | u32 fde_offset; | 212 | u32 fde_offset; |
@@ -284,7 +306,7 @@ static struct map *find_map(unw_word_t ip, struct unwind_info *ui) | |||
284 | { | 306 | { |
285 | struct addr_location al; | 307 | struct addr_location al; |
286 | 308 | ||
287 | thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, | 309 | thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER, |
288 | MAP__FUNCTION, ip, &al); | 310 | MAP__FUNCTION, ip, &al); |
289 | return al.map; | 311 | return al.map; |
290 | } | 312 | } |
@@ -322,8 +344,12 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, | |||
322 | #ifndef NO_LIBUNWIND_DEBUG_FRAME | 344 | #ifndef NO_LIBUNWIND_DEBUG_FRAME |
323 | /* Check the .debug_frame section for unwinding info */ | 345 | /* Check the .debug_frame section for unwinding info */ |
324 | if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { | 346 | if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { |
347 | int fd = dso__data_fd(map->dso, ui->machine); | ||
348 | int is_exec = elf_is_exec(fd, map->dso->name); | ||
349 | unw_word_t base = is_exec ? 0 : map->start; | ||
350 | |||
325 | memset(&di, 0, sizeof(di)); | 351 | memset(&di, 0, sizeof(di)); |
326 | if (dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name, | 352 | if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name, |
327 | map->start, map->end)) | 353 | map->start, map->end)) |
328 | return dwarf_search_unwind_table(as, ip, &di, pi, | 354 | return dwarf_search_unwind_table(as, ip, &di, pi, |
329 | need_unwind_info, arg); | 355 | need_unwind_info, arg); |
@@ -374,7 +400,7 @@ static int access_dso_mem(struct unwind_info *ui, unw_word_t addr, | |||
374 | struct addr_location al; | 400 | struct addr_location al; |
375 | ssize_t size; | 401 | ssize_t size; |
376 | 402 | ||
377 | thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, | 403 | thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER, |
378 | MAP__FUNCTION, addr, &al); | 404 | MAP__FUNCTION, addr, &al); |
379 | if (!al.map) { | 405 | if (!al.map) { |
380 | pr_debug("unwind: no map for %lx\n", (unsigned long)addr); | 406 | pr_debug("unwind: no map for %lx\n", (unsigned long)addr); |
@@ -476,14 +502,13 @@ static void put_unwind_info(unw_addr_space_t __maybe_unused as, | |||
476 | pr_debug("unwind: put_unwind_info called\n"); | 502 | pr_debug("unwind: put_unwind_info called\n"); |
477 | } | 503 | } |
478 | 504 | ||
479 | static int entry(u64 ip, struct thread *thread, struct machine *machine, | 505 | static int entry(u64 ip, struct thread *thread, |
480 | unwind_entry_cb_t cb, void *arg) | 506 | unwind_entry_cb_t cb, void *arg) |
481 | { | 507 | { |
482 | struct unwind_entry e; | 508 | struct unwind_entry e; |
483 | struct addr_location al; | 509 | struct addr_location al; |
484 | 510 | ||
485 | thread__find_addr_location(thread, machine, | 511 | thread__find_addr_location(thread, PERF_RECORD_MISC_USER, |
486 | PERF_RECORD_MISC_USER, | ||
487 | MAP__FUNCTION, ip, &al); | 512 | MAP__FUNCTION, ip, &al); |
488 | 513 | ||
489 | e.ip = ip; | 514 | e.ip = ip; |
@@ -586,21 +611,21 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, | |||
586 | unw_word_t ip; | 611 | unw_word_t ip; |
587 | 612 | ||
588 | unw_get_reg(&c, UNW_REG_IP, &ip); | 613 | unw_get_reg(&c, UNW_REG_IP, &ip); |
589 | ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0; | 614 | ret = ip ? entry(ip, ui->thread, cb, arg) : 0; |
590 | } | 615 | } |
591 | 616 | ||
592 | return ret; | 617 | return ret; |
593 | } | 618 | } |
594 | 619 | ||
595 | int unwind__get_entries(unwind_entry_cb_t cb, void *arg, | 620 | int unwind__get_entries(unwind_entry_cb_t cb, void *arg, |
596 | struct machine *machine, struct thread *thread, | 621 | struct thread *thread, |
597 | struct perf_sample *data, int max_stack) | 622 | struct perf_sample *data, int max_stack) |
598 | { | 623 | { |
599 | u64 ip; | 624 | u64 ip; |
600 | struct unwind_info ui = { | 625 | struct unwind_info ui = { |
601 | .sample = data, | 626 | .sample = data, |
602 | .thread = thread, | 627 | .thread = thread, |
603 | .machine = machine, | 628 | .machine = thread->mg->machine, |
604 | }; | 629 | }; |
605 | int ret; | 630 | int ret; |
606 | 631 | ||
@@ -611,7 +636,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, | |||
611 | if (ret) | 636 | if (ret) |
612 | return ret; | 637 | return ret; |
613 | 638 | ||
614 | ret = entry(ip, thread, machine, cb, arg); | 639 | ret = entry(ip, thread, cb, arg); |
615 | if (ret) | 640 | if (ret) |
616 | return -ENOMEM; | 641 | return -ENOMEM; |
617 | 642 | ||
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h index f50b737235eb..12790cf94618 100644 --- a/tools/perf/util/unwind.h +++ b/tools/perf/util/unwind.h | |||
@@ -16,7 +16,6 @@ typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); | |||
16 | 16 | ||
17 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | 17 | #ifdef HAVE_DWARF_UNWIND_SUPPORT |
18 | int unwind__get_entries(unwind_entry_cb_t cb, void *arg, | 18 | int unwind__get_entries(unwind_entry_cb_t cb, void *arg, |
19 | struct machine *machine, | ||
20 | struct thread *thread, | 19 | struct thread *thread, |
21 | struct perf_sample *data, int max_stack); | 20 | struct perf_sample *data, int max_stack); |
22 | /* libunwind specific */ | 21 | /* libunwind specific */ |
@@ -38,7 +37,6 @@ static inline void unwind__finish_access(struct thread *thread __maybe_unused) { | |||
38 | static inline int | 37 | static inline int |
39 | unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, | 38 | unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, |
40 | void *arg __maybe_unused, | 39 | void *arg __maybe_unused, |
41 | struct machine *machine __maybe_unused, | ||
42 | struct thread *thread __maybe_unused, | 40 | struct thread *thread __maybe_unused, |
43 | struct perf_sample *data __maybe_unused, | 41 | struct perf_sample *data __maybe_unused, |
44 | int max_stack __maybe_unused) | 42 | int max_stack __maybe_unused) |
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index d5eab3f3323f..b86744f29eef 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c | |||
@@ -442,23 +442,6 @@ unsigned long parse_tag_value(const char *str, struct parse_tag *tags) | |||
442 | return (unsigned long) -1; | 442 | return (unsigned long) -1; |
443 | } | 443 | } |
444 | 444 | ||
445 | int filename__read_int(const char *filename, int *value) | ||
446 | { | ||
447 | char line[64]; | ||
448 | int fd = open(filename, O_RDONLY), err = -1; | ||
449 | |||
450 | if (fd < 0) | ||
451 | return -1; | ||
452 | |||
453 | if (read(fd, line, sizeof(line)) > 0) { | ||
454 | *value = atoi(line); | ||
455 | err = 0; | ||
456 | } | ||
457 | |||
458 | close(fd); | ||
459 | return err; | ||
460 | } | ||
461 | |||
462 | int filename__read_str(const char *filename, char **buf, size_t *sizep) | 445 | int filename__read_str(const char *filename, char **buf, size_t *sizep) |
463 | { | 446 | { |
464 | size_t size = 0, alloc_size = 0; | 447 | size_t size = 0, alloc_size = 0; |
@@ -523,16 +506,9 @@ const char *get_filename_for_perf_kvm(void) | |||
523 | 506 | ||
524 | int perf_event_paranoid(void) | 507 | int perf_event_paranoid(void) |
525 | { | 508 | { |
526 | char path[PATH_MAX]; | ||
527 | const char *procfs = procfs__mountpoint(); | ||
528 | int value; | 509 | int value; |
529 | 510 | ||
530 | if (!procfs) | 511 | if (sysctl__read_int("kernel/perf_event_paranoid", &value)) |
531 | return INT_MAX; | ||
532 | |||
533 | scnprintf(path, PATH_MAX, "%s/sys/kernel/perf_event_paranoid", procfs); | ||
534 | |||
535 | if (filename__read_int(path, &value)) | ||
536 | return INT_MAX; | 512 | return INT_MAX; |
537 | 513 | ||
538 | return value; | 514 | return value; |
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 80bfdaa0e2a4..027a5153495c 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -153,8 +153,7 @@ extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))) | |||
153 | extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); | 153 | extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); |
154 | 154 | ||
155 | extern int prefixcmp(const char *str, const char *prefix); | 155 | extern int prefixcmp(const char *str, const char *prefix); |
156 | extern void set_buildid_dir(void); | 156 | extern void set_buildid_dir(const char *dir); |
157 | extern void disable_buildid_cache(void); | ||
158 | 157 | ||
159 | static inline const char *skip_prefix(const char *str, const char *prefix) | 158 | static inline const char *skip_prefix(const char *str, const char *prefix) |
160 | { | 159 | { |
@@ -270,35 +269,6 @@ void event_attr_init(struct perf_event_attr *attr); | |||
270 | #define _STR(x) #x | 269 | #define _STR(x) #x |
271 | #define STR(x) _STR(x) | 270 | #define STR(x) _STR(x) |
272 | 271 | ||
273 | /* | ||
274 | * Determine whether some value is a power of two, where zero is | ||
275 | * *not* considered a power of two. | ||
276 | */ | ||
277 | |||
278 | static inline __attribute__((const)) | ||
279 | bool is_power_of_2(unsigned long n) | ||
280 | { | ||
281 | return (n != 0 && ((n & (n - 1)) == 0)); | ||
282 | } | ||
283 | |||
284 | static inline unsigned next_pow2(unsigned x) | ||
285 | { | ||
286 | if (!x) | ||
287 | return 1; | ||
288 | return 1ULL << (32 - __builtin_clz(x - 1)); | ||
289 | } | ||
290 | |||
291 | static inline unsigned long next_pow2_l(unsigned long x) | ||
292 | { | ||
293 | #if BITS_PER_LONG == 64 | ||
294 | if (x <= (1UL << 31)) | ||
295 | return next_pow2(x); | ||
296 | return (unsigned long)next_pow2(x >> 32) << 32; | ||
297 | #else | ||
298 | return next_pow2(x); | ||
299 | #endif | ||
300 | } | ||
301 | |||
302 | size_t hex_width(u64 v); | 272 | size_t hex_width(u64 v); |
303 | int hex2u64(const char *ptr, u64 *val); | 273 | int hex2u64(const char *ptr, u64 *val); |
304 | 274 | ||
@@ -338,11 +308,12 @@ static inline int path__join3(char *bf, size_t size, | |||
338 | } | 308 | } |
339 | 309 | ||
340 | struct dso; | 310 | struct dso; |
311 | struct symbol; | ||
341 | 312 | ||
342 | char *get_srcline(struct dso *dso, unsigned long addr); | 313 | char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, |
314 | bool show_sym); | ||
343 | void free_srcline(char *srcline); | 315 | void free_srcline(char *srcline); |
344 | 316 | ||
345 | int filename__read_int(const char *filename, int *value); | ||
346 | int filename__read_str(const char *filename, char **buf, size_t *sizep); | 317 | int filename__read_str(const char *filename, char **buf, size_t *sizep); |
347 | int perf_event_paranoid(void); | 318 | int perf_event_paranoid(void); |
348 | 319 | ||
@@ -351,4 +322,9 @@ void mem_bswap_32(void *src, int byte_size); | |||
351 | 322 | ||
352 | const char *get_filename_for_perf_kvm(void); | 323 | const char *get_filename_for_perf_kvm(void); |
353 | bool find_process(const char *name); | 324 | bool find_process(const char *name); |
325 | |||
326 | #ifdef HAVE_ZLIB_SUPPORT | ||
327 | int gzip_decompress_to_file(const char *input, int output_fd); | ||
328 | #endif | ||
329 | |||
354 | #endif /* GIT_COMPAT_UTIL_H */ | 330 | #endif /* GIT_COMPAT_UTIL_H */ |
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c index adca69384fcc..5c7dd796979d 100644 --- a/tools/perf/util/vdso.c +++ b/tools/perf/util/vdso.c | |||
@@ -12,9 +12,16 @@ | |||
12 | #include "util.h" | 12 | #include "util.h" |
13 | #include "symbol.h" | 13 | #include "symbol.h" |
14 | #include "machine.h" | 14 | #include "machine.h" |
15 | #include "thread.h" | ||
15 | #include "linux/string.h" | 16 | #include "linux/string.h" |
16 | #include "debug.h" | 17 | #include "debug.h" |
17 | 18 | ||
19 | /* | ||
20 | * Include definition of find_vdso_map() also used in perf-read-vdso.c for | ||
21 | * building perf-read-vdso32 and perf-read-vdsox32. | ||
22 | */ | ||
23 | #include "find-vdso-map.c" | ||
24 | |||
18 | #define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX" | 25 | #define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX" |
19 | 26 | ||
20 | struct vdso_file { | 27 | struct vdso_file { |
@@ -22,10 +29,15 @@ struct vdso_file { | |||
22 | bool error; | 29 | bool error; |
23 | char temp_file_name[sizeof(VDSO__TEMP_FILE_NAME)]; | 30 | char temp_file_name[sizeof(VDSO__TEMP_FILE_NAME)]; |
24 | const char *dso_name; | 31 | const char *dso_name; |
32 | const char *read_prog; | ||
25 | }; | 33 | }; |
26 | 34 | ||
27 | struct vdso_info { | 35 | struct vdso_info { |
28 | struct vdso_file vdso; | 36 | struct vdso_file vdso; |
37 | #if BITS_PER_LONG == 64 | ||
38 | struct vdso_file vdso32; | ||
39 | struct vdso_file vdsox32; | ||
40 | #endif | ||
29 | }; | 41 | }; |
30 | 42 | ||
31 | static struct vdso_info *vdso_info__new(void) | 43 | static struct vdso_info *vdso_info__new(void) |
@@ -35,42 +47,23 @@ static struct vdso_info *vdso_info__new(void) | |||
35 | .temp_file_name = VDSO__TEMP_FILE_NAME, | 47 | .temp_file_name = VDSO__TEMP_FILE_NAME, |
36 | .dso_name = DSO__NAME_VDSO, | 48 | .dso_name = DSO__NAME_VDSO, |
37 | }, | 49 | }, |
50 | #if BITS_PER_LONG == 64 | ||
51 | .vdso32 = { | ||
52 | .temp_file_name = VDSO__TEMP_FILE_NAME, | ||
53 | .dso_name = DSO__NAME_VDSO32, | ||
54 | .read_prog = "perf-read-vdso32", | ||
55 | }, | ||
56 | .vdsox32 = { | ||
57 | .temp_file_name = VDSO__TEMP_FILE_NAME, | ||
58 | .dso_name = DSO__NAME_VDSOX32, | ||
59 | .read_prog = "perf-read-vdsox32", | ||
60 | }, | ||
61 | #endif | ||
38 | }; | 62 | }; |
39 | 63 | ||
40 | return memdup(&vdso_info_init, sizeof(vdso_info_init)); | 64 | return memdup(&vdso_info_init, sizeof(vdso_info_init)); |
41 | } | 65 | } |
42 | 66 | ||
43 | static int find_vdso_map(void **start, void **end) | ||
44 | { | ||
45 | FILE *maps; | ||
46 | char line[128]; | ||
47 | int found = 0; | ||
48 | |||
49 | maps = fopen("/proc/self/maps", "r"); | ||
50 | if (!maps) { | ||
51 | pr_err("vdso: cannot open maps\n"); | ||
52 | return -1; | ||
53 | } | ||
54 | |||
55 | while (!found && fgets(line, sizeof(line), maps)) { | ||
56 | int m = -1; | ||
57 | |||
58 | /* We care only about private r-x mappings. */ | ||
59 | if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n", | ||
60 | start, end, &m)) | ||
61 | continue; | ||
62 | if (m < 0) | ||
63 | continue; | ||
64 | |||
65 | if (!strncmp(&line[m], VDSO__MAP_NAME, | ||
66 | sizeof(VDSO__MAP_NAME) - 1)) | ||
67 | found = 1; | ||
68 | } | ||
69 | |||
70 | fclose(maps); | ||
71 | return !found; | ||
72 | } | ||
73 | |||
74 | static char *get_file(struct vdso_file *vdso_file) | 67 | static char *get_file(struct vdso_file *vdso_file) |
75 | { | 68 | { |
76 | char *vdso = NULL; | 69 | char *vdso = NULL; |
@@ -117,6 +110,12 @@ void vdso__exit(struct machine *machine) | |||
117 | 110 | ||
118 | if (vdso_info->vdso.found) | 111 | if (vdso_info->vdso.found) |
119 | unlink(vdso_info->vdso.temp_file_name); | 112 | unlink(vdso_info->vdso.temp_file_name); |
113 | #if BITS_PER_LONG == 64 | ||
114 | if (vdso_info->vdso32.found) | ||
115 | unlink(vdso_info->vdso32.temp_file_name); | ||
116 | if (vdso_info->vdsox32.found) | ||
117 | unlink(vdso_info->vdsox32.temp_file_name); | ||
118 | #endif | ||
120 | 119 | ||
121 | zfree(&machine->vdso_info); | 120 | zfree(&machine->vdso_info); |
122 | } | 121 | } |
@@ -135,6 +134,153 @@ static struct dso *vdso__new(struct machine *machine, const char *short_name, | |||
135 | return dso; | 134 | return dso; |
136 | } | 135 | } |
137 | 136 | ||
137 | #if BITS_PER_LONG == 64 | ||
138 | |||
139 | static enum dso_type machine__thread_dso_type(struct machine *machine, | ||
140 | struct thread *thread) | ||
141 | { | ||
142 | enum dso_type dso_type = DSO__TYPE_UNKNOWN; | ||
143 | struct map *map; | ||
144 | struct dso *dso; | ||
145 | |||
146 | map = map_groups__first(thread->mg, MAP__FUNCTION); | ||
147 | for (; map ; map = map_groups__next(map)) { | ||
148 | dso = map->dso; | ||
149 | if (!dso || dso->long_name[0] != '/') | ||
150 | continue; | ||
151 | dso_type = dso__type(dso, machine); | ||
152 | if (dso_type != DSO__TYPE_UNKNOWN) | ||
153 | break; | ||
154 | } | ||
155 | |||
156 | return dso_type; | ||
157 | } | ||
158 | |||
159 | static int vdso__do_copy_compat(FILE *f, int fd) | ||
160 | { | ||
161 | char buf[4096]; | ||
162 | size_t count; | ||
163 | |||
164 | while (1) { | ||
165 | count = fread(buf, 1, sizeof(buf), f); | ||
166 | if (ferror(f)) | ||
167 | return -errno; | ||
168 | if (feof(f)) | ||
169 | break; | ||
170 | if (count && writen(fd, buf, count) != (ssize_t)count) | ||
171 | return -errno; | ||
172 | } | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static int vdso__copy_compat(const char *prog, int fd) | ||
178 | { | ||
179 | FILE *f; | ||
180 | int err; | ||
181 | |||
182 | f = popen(prog, "r"); | ||
183 | if (!f) | ||
184 | return -errno; | ||
185 | |||
186 | err = vdso__do_copy_compat(f, fd); | ||
187 | |||
188 | if (pclose(f) == -1) | ||
189 | return -errno; | ||
190 | |||
191 | return err; | ||
192 | } | ||
193 | |||
194 | static int vdso__create_compat_file(const char *prog, char *temp_name) | ||
195 | { | ||
196 | int fd, err; | ||
197 | |||
198 | fd = mkstemp(temp_name); | ||
199 | if (fd < 0) | ||
200 | return -errno; | ||
201 | |||
202 | err = vdso__copy_compat(prog, fd); | ||
203 | |||
204 | if (close(fd) == -1) | ||
205 | return -errno; | ||
206 | |||
207 | return err; | ||
208 | } | ||
209 | |||
210 | static const char *vdso__get_compat_file(struct vdso_file *vdso_file) | ||
211 | { | ||
212 | int err; | ||
213 | |||
214 | if (vdso_file->found) | ||
215 | return vdso_file->temp_file_name; | ||
216 | |||
217 | if (vdso_file->error) | ||
218 | return NULL; | ||
219 | |||
220 | err = vdso__create_compat_file(vdso_file->read_prog, | ||
221 | vdso_file->temp_file_name); | ||
222 | if (err) { | ||
223 | pr_err("%s failed, error %d\n", vdso_file->read_prog, err); | ||
224 | vdso_file->error = true; | ||
225 | return NULL; | ||
226 | } | ||
227 | |||
228 | vdso_file->found = true; | ||
229 | |||
230 | return vdso_file->temp_file_name; | ||
231 | } | ||
232 | |||
233 | static struct dso *vdso__findnew_compat(struct machine *machine, | ||
234 | struct vdso_file *vdso_file) | ||
235 | { | ||
236 | const char *file_name; | ||
237 | struct dso *dso; | ||
238 | |||
239 | dso = dsos__find(&machine->user_dsos, vdso_file->dso_name, true); | ||
240 | if (dso) | ||
241 | return dso; | ||
242 | |||
243 | file_name = vdso__get_compat_file(vdso_file); | ||
244 | if (!file_name) | ||
245 | return NULL; | ||
246 | |||
247 | return vdso__new(machine, vdso_file->dso_name, file_name); | ||
248 | } | ||
249 | |||
250 | static int vdso__dso_findnew_compat(struct machine *machine, | ||
251 | struct thread *thread, | ||
252 | struct vdso_info *vdso_info, | ||
253 | struct dso **dso) | ||
254 | { | ||
255 | enum dso_type dso_type; | ||
256 | |||
257 | dso_type = machine__thread_dso_type(machine, thread); | ||
258 | |||
259 | #ifndef HAVE_PERF_READ_VDSO32 | ||
260 | if (dso_type == DSO__TYPE_32BIT) | ||
261 | return 0; | ||
262 | #endif | ||
263 | #ifndef HAVE_PERF_READ_VDSOX32 | ||
264 | if (dso_type == DSO__TYPE_X32BIT) | ||
265 | return 0; | ||
266 | #endif | ||
267 | |||
268 | switch (dso_type) { | ||
269 | case DSO__TYPE_32BIT: | ||
270 | *dso = vdso__findnew_compat(machine, &vdso_info->vdso32); | ||
271 | return 1; | ||
272 | case DSO__TYPE_X32BIT: | ||
273 | *dso = vdso__findnew_compat(machine, &vdso_info->vdsox32); | ||
274 | return 1; | ||
275 | case DSO__TYPE_UNKNOWN: | ||
276 | case DSO__TYPE_64BIT: | ||
277 | default: | ||
278 | return 0; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | #endif | ||
283 | |||
138 | struct dso *vdso__dso_findnew(struct machine *machine, | 284 | struct dso *vdso__dso_findnew(struct machine *machine, |
139 | struct thread *thread __maybe_unused) | 285 | struct thread *thread __maybe_unused) |
140 | { | 286 | { |
@@ -148,6 +294,11 @@ struct dso *vdso__dso_findnew(struct machine *machine, | |||
148 | if (!vdso_info) | 294 | if (!vdso_info) |
149 | return NULL; | 295 | return NULL; |
150 | 296 | ||
297 | #if BITS_PER_LONG == 64 | ||
298 | if (vdso__dso_findnew_compat(machine, thread, vdso_info, &dso)) | ||
299 | return dso; | ||
300 | #endif | ||
301 | |||
151 | dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true); | 302 | dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true); |
152 | if (!dso) { | 303 | if (!dso) { |
153 | char *file; | 304 | char *file; |
@@ -164,5 +315,7 @@ struct dso *vdso__dso_findnew(struct machine *machine, | |||
164 | 315 | ||
165 | bool dso__is_vdso(struct dso *dso) | 316 | bool dso__is_vdso(struct dso *dso) |
166 | { | 317 | { |
167 | return !strcmp(dso->short_name, DSO__NAME_VDSO); | 318 | return !strcmp(dso->short_name, DSO__NAME_VDSO) || |
319 | !strcmp(dso->short_name, DSO__NAME_VDSO32) || | ||
320 | !strcmp(dso->short_name, DSO__NAME_VDSOX32); | ||
168 | } | 321 | } |
diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h index af9d6929a215..d97da1616f0c 100644 --- a/tools/perf/util/vdso.h +++ b/tools/perf/util/vdso.h | |||
@@ -7,7 +7,9 @@ | |||
7 | 7 | ||
8 | #define VDSO__MAP_NAME "[vdso]" | 8 | #define VDSO__MAP_NAME "[vdso]" |
9 | 9 | ||
10 | #define DSO__NAME_VDSO "[vdso]" | 10 | #define DSO__NAME_VDSO "[vdso]" |
11 | #define DSO__NAME_VDSO32 "[vdso32]" | ||
12 | #define DSO__NAME_VDSOX32 "[vdsox32]" | ||
11 | 13 | ||
12 | static inline bool is_vdso_map(const char *filename) | 14 | static inline bool is_vdso_map(const char *filename) |
13 | { | 15 | { |
diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c new file mode 100644 index 000000000000..495a449fc25c --- /dev/null +++ b/tools/perf/util/zlib.c | |||
@@ -0,0 +1,78 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <unistd.h> | ||
3 | #include <sys/stat.h> | ||
4 | #include <sys/mman.h> | ||
5 | #include <zlib.h> | ||
6 | |||
7 | #include "util/util.h" | ||
8 | #include "util/debug.h" | ||
9 | |||
10 | |||
11 | #define CHUNK_SIZE 16384 | ||
12 | |||
13 | int gzip_decompress_to_file(const char *input, int output_fd) | ||
14 | { | ||
15 | int ret = Z_STREAM_ERROR; | ||
16 | int input_fd; | ||
17 | void *ptr; | ||
18 | int len; | ||
19 | struct stat stbuf; | ||
20 | unsigned char buf[CHUNK_SIZE]; | ||
21 | z_stream zs = { | ||
22 | .zalloc = Z_NULL, | ||
23 | .zfree = Z_NULL, | ||
24 | .opaque = Z_NULL, | ||
25 | .avail_in = 0, | ||
26 | .next_in = Z_NULL, | ||
27 | }; | ||
28 | |||
29 | input_fd = open(input, O_RDONLY); | ||
30 | if (input_fd < 0) | ||
31 | return -1; | ||
32 | |||
33 | if (fstat(input_fd, &stbuf) < 0) | ||
34 | goto out_close; | ||
35 | |||
36 | ptr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0); | ||
37 | if (ptr == MAP_FAILED) | ||
38 | goto out_close; | ||
39 | |||
40 | if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK) | ||
41 | goto out_unmap; | ||
42 | |||
43 | zs.next_in = ptr; | ||
44 | zs.avail_in = stbuf.st_size; | ||
45 | |||
46 | do { | ||
47 | zs.next_out = buf; | ||
48 | zs.avail_out = CHUNK_SIZE; | ||
49 | |||
50 | ret = inflate(&zs, Z_NO_FLUSH); | ||
51 | switch (ret) { | ||
52 | case Z_NEED_DICT: | ||
53 | ret = Z_DATA_ERROR; | ||
54 | /* fall through */ | ||
55 | case Z_DATA_ERROR: | ||
56 | case Z_MEM_ERROR: | ||
57 | goto out; | ||
58 | default: | ||
59 | break; | ||
60 | } | ||
61 | |||
62 | len = CHUNK_SIZE - zs.avail_out; | ||
63 | if (writen(output_fd, buf, len) != len) { | ||
64 | ret = Z_DATA_ERROR; | ||
65 | goto out; | ||
66 | } | ||
67 | |||
68 | } while (ret != Z_STREAM_END); | ||
69 | |||
70 | out: | ||
71 | inflateEnd(&zs); | ||
72 | out_unmap: | ||
73 | munmap(ptr, stbuf.st_size); | ||
74 | out_close: | ||
75 | close(input_fd); | ||
76 | |||
77 | return ret == Z_STREAM_END ? 0 : -1; | ||
78 | } | ||
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c index 7cdcf88659c7..9ea914378985 100644 --- a/tools/power/cpupower/utils/cpupower.c +++ b/tools/power/cpupower/utils/cpupower.c | |||
@@ -199,7 +199,7 @@ int main(int argc, const char *argv[]) | |||
199 | } | 199 | } |
200 | 200 | ||
201 | get_cpu_info(0, &cpupower_cpu_info); | 201 | get_cpu_info(0, &cpupower_cpu_info); |
202 | run_as_root = !getuid(); | 202 | run_as_root = !geteuid(); |
203 | if (run_as_root) { | 203 | if (run_as_root) { |
204 | ret = uname(&uts); | 204 | ret = uname(&uts); |
205 | if (!ret && !strcmp(uts.machine, "x86_64") && | 205 | if (!ret && !strcmp(uts.machine, "x86_64") && |
diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c index 09afe5d87f2b..4e8fe2c7b054 100644 --- a/tools/power/cpupower/utils/helpers/sysfs.c +++ b/tools/power/cpupower/utils/helpers/sysfs.c | |||
@@ -361,7 +361,7 @@ unsigned int sysfs_get_idlestate_count(unsigned int cpu) | |||
361 | 361 | ||
362 | snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle"); | 362 | snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle"); |
363 | if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) | 363 | if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) |
364 | return -ENODEV; | 364 | return 0; |
365 | 365 | ||
366 | snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu); | 366 | snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu); |
367 | if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) | 367 | if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) |
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index bf1398180785..b9cd036f0442 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl | |||
@@ -684,11 +684,8 @@ sub set_value { | |||
684 | } | 684 | } |
685 | ${$overrides}{$lvalue} = $prvalue; | 685 | ${$overrides}{$lvalue} = $prvalue; |
686 | } | 686 | } |
687 | if ($rvalue =~ /^\s*$/) { | 687 | |
688 | delete $opt{$lvalue}; | 688 | $opt{$lvalue} = $prvalue; |
689 | } else { | ||
690 | $opt{$lvalue} = $prvalue; | ||
691 | } | ||
692 | } | 689 | } |
693 | 690 | ||
694 | sub set_eval { | 691 | sub set_eval { |
@@ -2005,7 +2002,7 @@ sub get_version { | |||
2005 | # get the release name | 2002 | # get the release name |
2006 | return if ($have_version); | 2003 | return if ($have_version); |
2007 | doprint "$make kernelrelease ... "; | 2004 | doprint "$make kernelrelease ... "; |
2008 | $version = `$make kernelrelease | tail -1`; | 2005 | $version = `$make -s kernelrelease | tail -1`; |
2009 | chomp($version); | 2006 | chomp($version); |
2010 | doprint "$version\n"; | 2007 | doprint "$version\n"; |
2011 | $have_version = 1; | 2008 | $have_version = 1; |
@@ -3571,7 +3568,9 @@ sub test_this_config { | |||
3571 | undef %configs; | 3568 | undef %configs; |
3572 | assign_configs \%configs, $output_config; | 3569 | assign_configs \%configs, $output_config; |
3573 | 3570 | ||
3574 | return $config if (!defined($configs{$config})); | 3571 | if (!defined($configs{$config}) || $configs{$config} =~ /^#/) { |
3572 | return $config; | ||
3573 | } | ||
3575 | 3574 | ||
3576 | doprint "disabling config $config did not change .config\n"; | 3575 | doprint "disabling config $config did not change .config\n"; |
3577 | 3576 | ||
@@ -3945,12 +3944,22 @@ for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { | |||
3945 | } | 3944 | } |
3946 | } | 3945 | } |
3947 | 3946 | ||
3947 | sub option_defined { | ||
3948 | my ($option) = @_; | ||
3949 | |||
3950 | if (defined($opt{$option}) && $opt{$option} !~ /^\s*$/) { | ||
3951 | return 1; | ||
3952 | } | ||
3953 | |||
3954 | return 0; | ||
3955 | } | ||
3956 | |||
3948 | sub __set_test_option { | 3957 | sub __set_test_option { |
3949 | my ($name, $i) = @_; | 3958 | my ($name, $i) = @_; |
3950 | 3959 | ||
3951 | my $option = "$name\[$i\]"; | 3960 | my $option = "$name\[$i\]"; |
3952 | 3961 | ||
3953 | if (defined($opt{$option})) { | 3962 | if (option_defined($option)) { |
3954 | return $opt{$option}; | 3963 | return $opt{$option}; |
3955 | } | 3964 | } |
3956 | 3965 | ||
@@ -3958,13 +3967,13 @@ sub __set_test_option { | |||
3958 | if ($i >= $test && | 3967 | if ($i >= $test && |
3959 | $i < $test + $repeat_tests{$test}) { | 3968 | $i < $test + $repeat_tests{$test}) { |
3960 | $option = "$name\[$test\]"; | 3969 | $option = "$name\[$test\]"; |
3961 | if (defined($opt{$option})) { | 3970 | if (option_defined($option)) { |
3962 | return $opt{$option}; | 3971 | return $opt{$option}; |
3963 | } | 3972 | } |
3964 | } | 3973 | } |
3965 | } | 3974 | } |
3966 | 3975 | ||
3967 | if (defined($opt{$name})) { | 3976 | if (option_defined($name)) { |
3968 | return $opt{$name}; | 3977 | return $opt{$name}; |
3969 | } | 3978 | } |
3970 | 3979 | ||
@@ -4077,8 +4086,14 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { | |||
4077 | my $installme = ""; | 4086 | my $installme = ""; |
4078 | $installme = " no_install" if ($no_install); | 4087 | $installme = " no_install" if ($no_install); |
4079 | 4088 | ||
4089 | my $name = ""; | ||
4090 | |||
4091 | if (defined($test_name)) { | ||
4092 | $name = " ($test_name)"; | ||
4093 | } | ||
4094 | |||
4080 | doprint "\n\n"; | 4095 | doprint "\n\n"; |
4081 | doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n"; | 4096 | doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n"; |
4082 | 4097 | ||
4083 | if (defined($pre_test)) { | 4098 | if (defined($pre_test)) { |
4084 | run_command $pre_test; | 4099 | run_command $pre_test; |
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 45f145c6f843..4e511221a0c1 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile | |||
@@ -1,20 +1,23 @@ | |||
1 | TARGETS = breakpoints | 1 | TARGETS = breakpoints |
2 | TARGETS += cpu-hotplug | 2 | TARGETS += cpu-hotplug |
3 | TARGETS += efivarfs | 3 | TARGETS += efivarfs |
4 | TARGETS += exec | ||
5 | TARGETS += firmware | ||
6 | TARGETS += ftrace | ||
4 | TARGETS += kcmp | 7 | TARGETS += kcmp |
5 | TARGETS += memfd | 8 | TARGETS += memfd |
6 | TARGETS += memory-hotplug | 9 | TARGETS += memory-hotplug |
7 | TARGETS += mqueue | ||
8 | TARGETS += mount | 10 | TARGETS += mount |
11 | TARGETS += mqueue | ||
9 | TARGETS += net | 12 | TARGETS += net |
13 | TARGETS += powerpc | ||
10 | TARGETS += ptrace | 14 | TARGETS += ptrace |
15 | TARGETS += size | ||
16 | TARGETS += sysctl | ||
11 | TARGETS += timers | 17 | TARGETS += timers |
12 | TARGETS += vm | ||
13 | TARGETS += powerpc | ||
14 | TARGETS += user | 18 | TARGETS += user |
15 | TARGETS += sysctl | 19 | TARGETS += vm |
16 | TARGETS += firmware | 20 | #Please keep the TARGETS list alphabetically sorted |
17 | TARGETS += ftrace | ||
18 | 21 | ||
19 | TARGETS_HOTPLUG = cpu-hotplug | 22 | TARGETS_HOTPLUG = cpu-hotplug |
20 | TARGETS_HOTPLUG += memory-hotplug | 23 | TARGETS_HOTPLUG += memory-hotplug |
diff --git a/tools/testing/selftests/README.txt b/tools/testing/selftests/README.txt deleted file mode 100644 index 2660d5ff9179..000000000000 --- a/tools/testing/selftests/README.txt +++ /dev/null | |||
@@ -1,61 +0,0 @@ | |||
1 | Linux Kernel Selftests | ||
2 | |||
3 | The kernel contains a set of "self tests" under the tools/testing/selftests/ | ||
4 | directory. These are intended to be small unit tests to exercise individual | ||
5 | code paths in the kernel. | ||
6 | |||
7 | On some systems, hot-plug tests could hang forever waiting for cpu and | ||
8 | memory to be ready to be offlined. A special hot-plug target is created | ||
9 | to run full range of hot-plug tests. In default mode, hot-plug tests run | ||
10 | in safe mode with a limited scope. In limited mode, cpu-hotplug test is | ||
11 | run on a single cpu as opposed to all hotplug capable cpus, and memory | ||
12 | hotplug test is run on 2% of hotplug capable memory instead of 10%. | ||
13 | |||
14 | Running the selftests (hotplug tests are run in limited mode) | ||
15 | ============================================================= | ||
16 | |||
17 | To build the tests: | ||
18 | |||
19 | $ make -C tools/testing/selftests | ||
20 | |||
21 | |||
22 | To run the tests: | ||
23 | |||
24 | $ make -C tools/testing/selftests run_tests | ||
25 | |||
26 | - note that some tests will require root privileges. | ||
27 | |||
28 | To run only tests targeted for a single subsystem: (including | ||
29 | hotplug targets in limited mode) | ||
30 | |||
31 | $ make -C tools/testing/selftests TARGETS=cpu-hotplug run_tests | ||
32 | |||
33 | See the top-level tools/testing/selftests/Makefile for the list of all possible | ||
34 | targets. | ||
35 | |||
36 | Running the full range hotplug selftests | ||
37 | ======================================== | ||
38 | |||
39 | To build the tests: | ||
40 | |||
41 | $ make -C tools/testing/selftests hotplug | ||
42 | |||
43 | To run the tests: | ||
44 | |||
45 | $ make -C tools/testing/selftests run_hotplug | ||
46 | |||
47 | - note that some tests will require root privileges. | ||
48 | |||
49 | Contributing new tests | ||
50 | ====================== | ||
51 | |||
52 | In general, the rules for for selftests are | ||
53 | |||
54 | * Do as much as you can if you're not root; | ||
55 | |||
56 | * Don't take too long; | ||
57 | |||
58 | * Don't break the build on any architecture, and | ||
59 | |||
60 | * Don't cause the top-level "make run_tests" to fail if your feature is | ||
61 | unconfigured. | ||
diff --git a/tools/testing/selftests/breakpoints/breakpoint_test.c b/tools/testing/selftests/breakpoints/breakpoint_test.c index a0743f3b2b57..120895ab5505 100644 --- a/tools/testing/selftests/breakpoints/breakpoint_test.c +++ b/tools/testing/selftests/breakpoints/breakpoint_test.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <sys/types.h> | 17 | #include <sys/types.h> |
18 | #include <sys/wait.h> | 18 | #include <sys/wait.h> |
19 | 19 | ||
20 | #include "../kselftest.h" | ||
21 | |||
20 | 22 | ||
21 | /* Breakpoint access modes */ | 23 | /* Breakpoint access modes */ |
22 | enum { | 24 | enum { |
@@ -42,7 +44,7 @@ static void set_breakpoint_addr(void *addr, int n) | |||
42 | offsetof(struct user, u_debugreg[n]), addr); | 44 | offsetof(struct user, u_debugreg[n]), addr); |
43 | if (ret) { | 45 | if (ret) { |
44 | perror("Can't set breakpoint addr\n"); | 46 | perror("Can't set breakpoint addr\n"); |
45 | exit(-1); | 47 | ksft_exit_fail(); |
46 | } | 48 | } |
47 | } | 49 | } |
48 | 50 | ||
@@ -105,7 +107,7 @@ static void toggle_breakpoint(int n, int type, int len, | |||
105 | offsetof(struct user, u_debugreg[7]), dr7); | 107 | offsetof(struct user, u_debugreg[7]), dr7); |
106 | if (ret) { | 108 | if (ret) { |
107 | perror("Can't set dr7"); | 109 | perror("Can't set dr7"); |
108 | exit(-1); | 110 | ksft_exit_fail(); |
109 | } | 111 | } |
110 | } | 112 | } |
111 | 113 | ||
@@ -275,7 +277,7 @@ static void check_success(const char *msg) | |||
275 | msg2 = "Ok"; | 277 | msg2 = "Ok"; |
276 | if (ptrace(PTRACE_POKEDATA, child_pid, &trapped, 1)) { | 278 | if (ptrace(PTRACE_POKEDATA, child_pid, &trapped, 1)) { |
277 | perror("Can't poke\n"); | 279 | perror("Can't poke\n"); |
278 | exit(-1); | 280 | ksft_exit_fail(); |
279 | } | 281 | } |
280 | } | 282 | } |
281 | 283 | ||
@@ -390,5 +392,5 @@ int main(int argc, char **argv) | |||
390 | 392 | ||
391 | wait(NULL); | 393 | wait(NULL); |
392 | 394 | ||
393 | return 0; | 395 | return ksft_exit_pass(); |
394 | } | 396 | } |
diff --git a/tools/testing/selftests/exec/.gitignore b/tools/testing/selftests/exec/.gitignore new file mode 100644 index 000000000000..64073e050c6a --- /dev/null +++ b/tools/testing/selftests/exec/.gitignore | |||
@@ -0,0 +1,9 @@ | |||
1 | subdir* | ||
2 | script* | ||
3 | execveat | ||
4 | execveat.symlink | ||
5 | execveat.moved | ||
6 | execveat.path.ephemeral | ||
7 | execveat.ephemeral | ||
8 | execveat.denatured | ||
9 | xxxxxxxx* \ No newline at end of file | ||
diff --git a/tools/testing/selftests/exec/Makefile b/tools/testing/selftests/exec/Makefile new file mode 100644 index 000000000000..66dfc2ce1788 --- /dev/null +++ b/tools/testing/selftests/exec/Makefile | |||
@@ -0,0 +1,25 @@ | |||
1 | CC = $(CROSS_COMPILE)gcc | ||
2 | CFLAGS = -Wall | ||
3 | BINARIES = execveat | ||
4 | DEPS = execveat.symlink execveat.denatured script subdir | ||
5 | all: $(BINARIES) $(DEPS) | ||
6 | |||
7 | subdir: | ||
8 | mkdir -p $@ | ||
9 | script: | ||
10 | echo '#!/bin/sh' > $@ | ||
11 | echo 'exit $$*' >> $@ | ||
12 | chmod +x $@ | ||
13 | execveat.symlink: execveat | ||
14 | ln -s -f $< $@ | ||
15 | execveat.denatured: execveat | ||
16 | cp $< $@ | ||
17 | chmod -x $@ | ||
18 | %: %.c | ||
19 | $(CC) $(CFLAGS) -o $@ $^ | ||
20 | |||
21 | run_tests: all | ||
22 | ./execveat | ||
23 | |||
24 | clean: | ||
25 | rm -rf $(BINARIES) $(DEPS) subdir.moved execveat.moved xxxxx* | ||
diff --git a/tools/testing/selftests/exec/execveat.c b/tools/testing/selftests/exec/execveat.c new file mode 100644 index 000000000000..e238c9559caf --- /dev/null +++ b/tools/testing/selftests/exec/execveat.c | |||
@@ -0,0 +1,404 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Google, Inc. | ||
3 | * | ||
4 | * Licensed under the terms of the GNU GPL License version 2 | ||
5 | * | ||
6 | * Selftests for execveat(2). | ||
7 | */ | ||
8 | |||
9 | #define _GNU_SOURCE /* to get O_PATH, AT_EMPTY_PATH */ | ||
10 | #include <sys/sendfile.h> | ||
11 | #include <sys/stat.h> | ||
12 | #include <sys/syscall.h> | ||
13 | #include <sys/types.h> | ||
14 | #include <sys/wait.h> | ||
15 | #include <errno.h> | ||
16 | #include <fcntl.h> | ||
17 | #include <limits.h> | ||
18 | #include <stdio.h> | ||
19 | #include <stdlib.h> | ||
20 | #include <string.h> | ||
21 | #include <unistd.h> | ||
22 | |||
23 | static char longpath[2 * PATH_MAX] = ""; | ||
24 | static char *envp[] = { "IN_TEST=yes", NULL, NULL }; | ||
25 | static char *argv[] = { "execveat", "99", NULL }; | ||
26 | |||
27 | static int execveat_(int fd, const char *path, char **argv, char **envp, | ||
28 | int flags) | ||
29 | { | ||
30 | #ifdef __NR_execveat | ||
31 | return syscall(__NR_execveat, fd, path, argv, envp, flags); | ||
32 | #else | ||
33 | errno = -ENOSYS; | ||
34 | return -1; | ||
35 | #endif | ||
36 | } | ||
37 | |||
38 | #define check_execveat_fail(fd, path, flags, errno) \ | ||
39 | _check_execveat_fail(fd, path, flags, errno, #errno) | ||
40 | static int _check_execveat_fail(int fd, const char *path, int flags, | ||
41 | int expected_errno, const char *errno_str) | ||
42 | { | ||
43 | int rc; | ||
44 | |||
45 | errno = 0; | ||
46 | printf("Check failure of execveat(%d, '%s', %d) with %s... ", | ||
47 | fd, path?:"(null)", flags, errno_str); | ||
48 | rc = execveat_(fd, path, argv, envp, flags); | ||
49 | |||
50 | if (rc > 0) { | ||
51 | printf("[FAIL] (unexpected success from execveat(2))\n"); | ||
52 | return 1; | ||
53 | } | ||
54 | if (errno != expected_errno) { | ||
55 | printf("[FAIL] (expected errno %d (%s) not %d (%s)\n", | ||
56 | expected_errno, strerror(expected_errno), | ||
57 | errno, strerror(errno)); | ||
58 | return 1; | ||
59 | } | ||
60 | printf("[OK]\n"); | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static int check_execveat_invoked_rc(int fd, const char *path, int flags, | ||
65 | int expected_rc, int expected_rc2) | ||
66 | { | ||
67 | int status; | ||
68 | int rc; | ||
69 | pid_t child; | ||
70 | int pathlen = path ? strlen(path) : 0; | ||
71 | |||
72 | if (pathlen > 40) | ||
73 | printf("Check success of execveat(%d, '%.20s...%s', %d)... ", | ||
74 | fd, path, (path + pathlen - 20), flags); | ||
75 | else | ||
76 | printf("Check success of execveat(%d, '%s', %d)... ", | ||
77 | fd, path?:"(null)", flags); | ||
78 | child = fork(); | ||
79 | if (child < 0) { | ||
80 | printf("[FAIL] (fork() failed)\n"); | ||
81 | return 1; | ||
82 | } | ||
83 | if (child == 0) { | ||
84 | /* Child: do execveat(). */ | ||
85 | rc = execveat_(fd, path, argv, envp, flags); | ||
86 | printf("[FAIL]: execveat() failed, rc=%d errno=%d (%s)\n", | ||
87 | rc, errno, strerror(errno)); | ||
88 | exit(1); /* should not reach here */ | ||
89 | } | ||
90 | /* Parent: wait for & check child's exit status. */ | ||
91 | rc = waitpid(child, &status, 0); | ||
92 | if (rc != child) { | ||
93 | printf("[FAIL] (waitpid(%d,...) returned %d)\n", child, rc); | ||
94 | return 1; | ||
95 | } | ||
96 | if (!WIFEXITED(status)) { | ||
97 | printf("[FAIL] (child %d did not exit cleanly, status=%08x)\n", | ||
98 | child, status); | ||
99 | return 1; | ||
100 | } | ||
101 | if ((WEXITSTATUS(status) != expected_rc) && | ||
102 | (WEXITSTATUS(status) != expected_rc2)) { | ||
103 | printf("[FAIL] (child %d exited with %d not %d nor %d)\n", | ||
104 | child, WEXITSTATUS(status), expected_rc, expected_rc2); | ||
105 | return 1; | ||
106 | } | ||
107 | printf("[OK]\n"); | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static int check_execveat(int fd, const char *path, int flags) | ||
112 | { | ||
113 | return check_execveat_invoked_rc(fd, path, flags, 99, 99); | ||
114 | } | ||
115 | |||
116 | static char *concat(const char *left, const char *right) | ||
117 | { | ||
118 | char *result = malloc(strlen(left) + strlen(right) + 1); | ||
119 | |||
120 | strcpy(result, left); | ||
121 | strcat(result, right); | ||
122 | return result; | ||
123 | } | ||
124 | |||
125 | static int open_or_die(const char *filename, int flags) | ||
126 | { | ||
127 | int fd = open(filename, flags); | ||
128 | |||
129 | if (fd < 0) { | ||
130 | printf("Failed to open '%s'; " | ||
131 | "check prerequisites are available\n", filename); | ||
132 | exit(1); | ||
133 | } | ||
134 | return fd; | ||
135 | } | ||
136 | |||
137 | static void exe_cp(const char *src, const char *dest) | ||
138 | { | ||
139 | int in_fd = open_or_die(src, O_RDONLY); | ||
140 | int out_fd = open(dest, O_RDWR|O_CREAT|O_TRUNC, 0755); | ||
141 | struct stat info; | ||
142 | |||
143 | fstat(in_fd, &info); | ||
144 | sendfile(out_fd, in_fd, NULL, info.st_size); | ||
145 | close(in_fd); | ||
146 | close(out_fd); | ||
147 | } | ||
148 | |||
149 | #define XX_DIR_LEN 200 | ||
150 | static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script) | ||
151 | { | ||
152 | int fail = 0; | ||
153 | int ii, count, len; | ||
154 | char longname[XX_DIR_LEN + 1]; | ||
155 | int fd; | ||
156 | |||
157 | if (*longpath == '\0') { | ||
158 | /* Create a filename close to PATH_MAX in length */ | ||
159 | memset(longname, 'x', XX_DIR_LEN - 1); | ||
160 | longname[XX_DIR_LEN - 1] = '/'; | ||
161 | longname[XX_DIR_LEN] = '\0'; | ||
162 | count = (PATH_MAX - 3) / XX_DIR_LEN; | ||
163 | for (ii = 0; ii < count; ii++) { | ||
164 | strcat(longpath, longname); | ||
165 | mkdir(longpath, 0755); | ||
166 | } | ||
167 | len = (PATH_MAX - 3) - (count * XX_DIR_LEN); | ||
168 | if (len <= 0) | ||
169 | len = 1; | ||
170 | memset(longname, 'y', len); | ||
171 | longname[len] = '\0'; | ||
172 | strcat(longpath, longname); | ||
173 | } | ||
174 | exe_cp(src, longpath); | ||
175 | |||
176 | /* | ||
177 | * Execute as a pre-opened file descriptor, which works whether this is | ||
178 | * a script or not (because the interpreter sees a filename like | ||
179 | * "/dev/fd/20"). | ||
180 | */ | ||
181 | fd = open(longpath, O_RDONLY); | ||
182 | if (fd > 0) { | ||
183 | printf("Invoke copy of '%s' via filename of length %zu:\n", | ||
184 | src, strlen(longpath)); | ||
185 | fail += check_execveat(fd, "", AT_EMPTY_PATH); | ||
186 | } else { | ||
187 | printf("Failed to open length %zu filename, errno=%d (%s)\n", | ||
188 | strlen(longpath), errno, strerror(errno)); | ||
189 | fail++; | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | * Execute as a long pathname relative to ".". If this is a script, | ||
194 | * the interpreter will launch but fail to open the script because its | ||
195 | * name ("/dev/fd/5/xxx....") is bigger than PATH_MAX. | ||
196 | * | ||
197 | * The failure code is usually 127 (POSIX: "If a command is not found, | ||
198 | * the exit status shall be 127."), but some systems give 126 (POSIX: | ||
199 | * "If the command name is found, but it is not an executable utility, | ||
200 | * the exit status shall be 126."), so allow either. | ||
201 | */ | ||
202 | if (is_script) | ||
203 | fail += check_execveat_invoked_rc(dot_dfd, longpath, 0, | ||
204 | 127, 126); | ||
205 | else | ||
206 | fail += check_execveat(dot_dfd, longpath, 0); | ||
207 | |||
208 | return fail; | ||
209 | } | ||
210 | |||
211 | static int run_tests(void) | ||
212 | { | ||
213 | int fail = 0; | ||
214 | char *fullname = realpath("execveat", NULL); | ||
215 | char *fullname_script = realpath("script", NULL); | ||
216 | char *fullname_symlink = concat(fullname, ".symlink"); | ||
217 | int subdir_dfd = open_or_die("subdir", O_DIRECTORY|O_RDONLY); | ||
218 | int subdir_dfd_ephemeral = open_or_die("subdir.ephemeral", | ||
219 | O_DIRECTORY|O_RDONLY); | ||
220 | int dot_dfd = open_or_die(".", O_DIRECTORY|O_RDONLY); | ||
221 | int dot_dfd_path = open_or_die(".", O_DIRECTORY|O_RDONLY|O_PATH); | ||
222 | int dot_dfd_cloexec = open_or_die(".", O_DIRECTORY|O_RDONLY|O_CLOEXEC); | ||
223 | int fd = open_or_die("execveat", O_RDONLY); | ||
224 | int fd_path = open_or_die("execveat", O_RDONLY|O_PATH); | ||
225 | int fd_symlink = open_or_die("execveat.symlink", O_RDONLY); | ||
226 | int fd_denatured = open_or_die("execveat.denatured", O_RDONLY); | ||
227 | int fd_denatured_path = open_or_die("execveat.denatured", | ||
228 | O_RDONLY|O_PATH); | ||
229 | int fd_script = open_or_die("script", O_RDONLY); | ||
230 | int fd_ephemeral = open_or_die("execveat.ephemeral", O_RDONLY); | ||
231 | int fd_ephemeral_path = open_or_die("execveat.path.ephemeral", | ||
232 | O_RDONLY|O_PATH); | ||
233 | int fd_script_ephemeral = open_or_die("script.ephemeral", O_RDONLY); | ||
234 | int fd_cloexec = open_or_die("execveat", O_RDONLY|O_CLOEXEC); | ||
235 | int fd_script_cloexec = open_or_die("script", O_RDONLY|O_CLOEXEC); | ||
236 | |||
237 | /* Change file position to confirm it doesn't affect anything */ | ||
238 | lseek(fd, 10, SEEK_SET); | ||
239 | |||
240 | /* Normal executable file: */ | ||
241 | /* dfd + path */ | ||
242 | fail += check_execveat(subdir_dfd, "../execveat", 0); | ||
243 | fail += check_execveat(dot_dfd, "execveat", 0); | ||
244 | fail += check_execveat(dot_dfd_path, "execveat", 0); | ||
245 | /* absolute path */ | ||
246 | fail += check_execveat(AT_FDCWD, fullname, 0); | ||
247 | /* absolute path with nonsense dfd */ | ||
248 | fail += check_execveat(99, fullname, 0); | ||
249 | /* fd + no path */ | ||
250 | fail += check_execveat(fd, "", AT_EMPTY_PATH); | ||
251 | /* O_CLOEXEC fd + no path */ | ||
252 | fail += check_execveat(fd_cloexec, "", AT_EMPTY_PATH); | ||
253 | /* O_PATH fd */ | ||
254 | fail += check_execveat(fd_path, "", AT_EMPTY_PATH); | ||
255 | |||
256 | /* Mess with executable file that's already open: */ | ||
257 | /* fd + no path to a file that's been renamed */ | ||
258 | rename("execveat.ephemeral", "execveat.moved"); | ||
259 | fail += check_execveat(fd_ephemeral, "", AT_EMPTY_PATH); | ||
260 | /* fd + no path to a file that's been deleted */ | ||
261 | unlink("execveat.moved"); /* remove the file now fd open */ | ||
262 | fail += check_execveat(fd_ephemeral, "", AT_EMPTY_PATH); | ||
263 | |||
264 | /* Mess with executable file that's already open with O_PATH */ | ||
265 | /* fd + no path to a file that's been deleted */ | ||
266 | unlink("execveat.path.ephemeral"); | ||
267 | fail += check_execveat(fd_ephemeral_path, "", AT_EMPTY_PATH); | ||
268 | |||
269 | /* Invalid argument failures */ | ||
270 | fail += check_execveat_fail(fd, "", 0, ENOENT); | ||
271 | fail += check_execveat_fail(fd, NULL, AT_EMPTY_PATH, EFAULT); | ||
272 | |||
273 | /* Symlink to executable file: */ | ||
274 | /* dfd + path */ | ||
275 | fail += check_execveat(dot_dfd, "execveat.symlink", 0); | ||
276 | fail += check_execveat(dot_dfd_path, "execveat.symlink", 0); | ||
277 | /* absolute path */ | ||
278 | fail += check_execveat(AT_FDCWD, fullname_symlink, 0); | ||
279 | /* fd + no path, even with AT_SYMLINK_NOFOLLOW (already followed) */ | ||
280 | fail += check_execveat(fd_symlink, "", AT_EMPTY_PATH); | ||
281 | fail += check_execveat(fd_symlink, "", | ||
282 | AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW); | ||
283 | |||
284 | /* Symlink fails when AT_SYMLINK_NOFOLLOW set: */ | ||
285 | /* dfd + path */ | ||
286 | fail += check_execveat_fail(dot_dfd, "execveat.symlink", | ||
287 | AT_SYMLINK_NOFOLLOW, ELOOP); | ||
288 | fail += check_execveat_fail(dot_dfd_path, "execveat.symlink", | ||
289 | AT_SYMLINK_NOFOLLOW, ELOOP); | ||
290 | /* absolute path */ | ||
291 | fail += check_execveat_fail(AT_FDCWD, fullname_symlink, | ||
292 | AT_SYMLINK_NOFOLLOW, ELOOP); | ||
293 | |||
294 | /* Shell script wrapping executable file: */ | ||
295 | /* dfd + path */ | ||
296 | fail += check_execveat(subdir_dfd, "../script", 0); | ||
297 | fail += check_execveat(dot_dfd, "script", 0); | ||
298 | fail += check_execveat(dot_dfd_path, "script", 0); | ||
299 | /* absolute path */ | ||
300 | fail += check_execveat(AT_FDCWD, fullname_script, 0); | ||
301 | /* fd + no path */ | ||
302 | fail += check_execveat(fd_script, "", AT_EMPTY_PATH); | ||
303 | fail += check_execveat(fd_script, "", | ||
304 | AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW); | ||
305 | /* O_CLOEXEC fd fails for a script (as script file inaccessible) */ | ||
306 | fail += check_execveat_fail(fd_script_cloexec, "", AT_EMPTY_PATH, | ||
307 | ENOENT); | ||
308 | fail += check_execveat_fail(dot_dfd_cloexec, "script", 0, ENOENT); | ||
309 | |||
310 | /* Mess with script file that's already open: */ | ||
311 | /* fd + no path to a file that's been renamed */ | ||
312 | rename("script.ephemeral", "script.moved"); | ||
313 | fail += check_execveat(fd_script_ephemeral, "", AT_EMPTY_PATH); | ||
314 | /* fd + no path to a file that's been deleted */ | ||
315 | unlink("script.moved"); /* remove the file while fd open */ | ||
316 | fail += check_execveat(fd_script_ephemeral, "", AT_EMPTY_PATH); | ||
317 | |||
318 | /* Rename a subdirectory in the path: */ | ||
319 | rename("subdir.ephemeral", "subdir.moved"); | ||
320 | fail += check_execveat(subdir_dfd_ephemeral, "../script", 0); | ||
321 | fail += check_execveat(subdir_dfd_ephemeral, "script", 0); | ||
322 | /* Remove the subdir and its contents */ | ||
323 | unlink("subdir.moved/script"); | ||
324 | unlink("subdir.moved"); | ||
325 | /* Shell loads via deleted subdir OK because name starts with .. */ | ||
326 | fail += check_execveat(subdir_dfd_ephemeral, "../script", 0); | ||
327 | fail += check_execveat_fail(subdir_dfd_ephemeral, "script", 0, ENOENT); | ||
328 | |||
329 | /* Flag values other than AT_SYMLINK_NOFOLLOW => EINVAL */ | ||
330 | fail += check_execveat_fail(dot_dfd, "execveat", 0xFFFF, EINVAL); | ||
331 | /* Invalid path => ENOENT */ | ||
332 | fail += check_execveat_fail(dot_dfd, "no-such-file", 0, ENOENT); | ||
333 | fail += check_execveat_fail(dot_dfd_path, "no-such-file", 0, ENOENT); | ||
334 | fail += check_execveat_fail(AT_FDCWD, "no-such-file", 0, ENOENT); | ||
335 | /* Attempt to execute directory => EACCES */ | ||
336 | fail += check_execveat_fail(dot_dfd, "", AT_EMPTY_PATH, EACCES); | ||
337 | /* Attempt to execute non-executable => EACCES */ | ||
338 | fail += check_execveat_fail(dot_dfd, "Makefile", 0, EACCES); | ||
339 | fail += check_execveat_fail(fd_denatured, "", AT_EMPTY_PATH, EACCES); | ||
340 | fail += check_execveat_fail(fd_denatured_path, "", AT_EMPTY_PATH, | ||
341 | EACCES); | ||
342 | /* Attempt to execute nonsense FD => EBADF */ | ||
343 | fail += check_execveat_fail(99, "", AT_EMPTY_PATH, EBADF); | ||
344 | fail += check_execveat_fail(99, "execveat", 0, EBADF); | ||
345 | /* Attempt to execute relative to non-directory => ENOTDIR */ | ||
346 | fail += check_execveat_fail(fd, "execveat", 0, ENOTDIR); | ||
347 | |||
348 | fail += check_execveat_pathmax(dot_dfd, "execveat", 0); | ||
349 | fail += check_execveat_pathmax(dot_dfd, "script", 1); | ||
350 | return fail; | ||
351 | } | ||
352 | |||
353 | static void prerequisites(void) | ||
354 | { | ||
355 | int fd; | ||
356 | const char *script = "#!/bin/sh\nexit $*\n"; | ||
357 | |||
358 | /* Create ephemeral copies of files */ | ||
359 | exe_cp("execveat", "execveat.ephemeral"); | ||
360 | exe_cp("execveat", "execveat.path.ephemeral"); | ||
361 | exe_cp("script", "script.ephemeral"); | ||
362 | mkdir("subdir.ephemeral", 0755); | ||
363 | |||
364 | fd = open("subdir.ephemeral/script", O_RDWR|O_CREAT|O_TRUNC, 0755); | ||
365 | write(fd, script, strlen(script)); | ||
366 | close(fd); | ||
367 | } | ||
368 | |||
369 | int main(int argc, char **argv) | ||
370 | { | ||
371 | int ii; | ||
372 | int rc; | ||
373 | const char *verbose = getenv("VERBOSE"); | ||
374 | |||
375 | if (argc >= 2) { | ||
376 | /* If we are invoked with an argument, don't run tests. */ | ||
377 | const char *in_test = getenv("IN_TEST"); | ||
378 | |||
379 | if (verbose) { | ||
380 | printf(" invoked with:"); | ||
381 | for (ii = 0; ii < argc; ii++) | ||
382 | printf(" [%d]='%s'", ii, argv[ii]); | ||
383 | printf("\n"); | ||
384 | } | ||
385 | |||
386 | /* Check expected environment transferred. */ | ||
387 | if (!in_test || strcmp(in_test, "yes") != 0) { | ||
388 | printf("[FAIL] (no IN_TEST=yes in env)\n"); | ||
389 | return 1; | ||
390 | } | ||
391 | |||
392 | /* Use the final argument as an exit code. */ | ||
393 | rc = atoi(argv[argc - 1]); | ||
394 | fflush(stdout); | ||
395 | } else { | ||
396 | prerequisites(); | ||
397 | if (verbose) | ||
398 | envp[1] = "VERBOSE=1"; | ||
399 | rc = run_tests(); | ||
400 | if (rc > 0) | ||
401 | printf("%d tests failed\n", rc); | ||
402 | } | ||
403 | return rc; | ||
404 | } | ||
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest index 515247601df4..da48812ab95e 100755 --- a/tools/testing/selftests/ftrace/ftracetest +++ b/tools/testing/selftests/ftrace/ftracetest | |||
@@ -13,6 +13,7 @@ echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]" | |||
13 | echo " Options:" | 13 | echo " Options:" |
14 | echo " -h|--help Show help message" | 14 | echo " -h|--help Show help message" |
15 | echo " -k|--keep Keep passed test logs" | 15 | echo " -k|--keep Keep passed test logs" |
16 | echo " -v|--verbose Show all stdout messages in testcases" | ||
16 | echo " -d|--debug Debug mode (trace all shell commands)" | 17 | echo " -d|--debug Debug mode (trace all shell commands)" |
17 | exit $1 | 18 | exit $1 |
18 | } | 19 | } |
@@ -37,7 +38,7 @@ abspath() { | |||
37 | } | 38 | } |
38 | 39 | ||
39 | find_testcases() { #directory | 40 | find_testcases() { #directory |
40 | echo `find $1 -name \*.tc` | 41 | echo `find $1 -name \*.tc | sort` |
41 | } | 42 | } |
42 | 43 | ||
43 | parse_opts() { # opts | 44 | parse_opts() { # opts |
@@ -53,6 +54,10 @@ parse_opts() { # opts | |||
53 | KEEP_LOG=1 | 54 | KEEP_LOG=1 |
54 | shift 1 | 55 | shift 1 |
55 | ;; | 56 | ;; |
57 | --verbose|-v) | ||
58 | VERBOSE=1 | ||
59 | shift 1 | ||
60 | ;; | ||
56 | --debug|-d) | 61 | --debug|-d) |
57 | DEBUG=1 | 62 | DEBUG=1 |
58 | shift 1 | 63 | shift 1 |
@@ -90,6 +95,7 @@ TEST_CASES=`find_testcases $TEST_DIR` | |||
90 | LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/ | 95 | LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/ |
91 | KEEP_LOG=0 | 96 | KEEP_LOG=0 |
92 | DEBUG=0 | 97 | DEBUG=0 |
98 | VERBOSE=0 | ||
93 | # Parse command-line options | 99 | # Parse command-line options |
94 | parse_opts $* | 100 | parse_opts $* |
95 | 101 | ||
@@ -135,15 +141,12 @@ TOTAL_RESULT=0 | |||
135 | CASENO=0 | 141 | CASENO=0 |
136 | testcase() { # testfile | 142 | testcase() { # testfile |
137 | CASENO=$((CASENO+1)) | 143 | CASENO=$((CASENO+1)) |
138 | prlog -n "[$CASENO]"`grep "^#[ \t]*description:" $1 | cut -f2 -d:` | 144 | desc=`grep "^#[ \t]*description:" $1 | cut -f2 -d:` |
145 | prlog -n "[$CASENO]$desc" | ||
139 | } | 146 | } |
140 | 147 | ||
141 | eval_result() { # retval sigval | 148 | eval_result() { # sigval |
142 | local retval=$2 | 149 | case $1 in |
143 | if [ $2 -eq 0 ]; then | ||
144 | test $1 -ne 0 && retval=$FAIL | ||
145 | fi | ||
146 | case $retval in | ||
147 | $PASS) | 150 | $PASS) |
148 | prlog " [PASS]" | 151 | prlog " [PASS]" |
149 | PASSED_CASES="$PASSED_CASES $CASENO" | 152 | PASSED_CASES="$PASSED_CASES $CASENO" |
@@ -187,6 +190,9 @@ SIG_RESULT= | |||
187 | SIG_BASE=36 # Use realtime signals | 190 | SIG_BASE=36 # Use realtime signals |
188 | SIG_PID=$$ | 191 | SIG_PID=$$ |
189 | 192 | ||
193 | SIG_FAIL=$((SIG_BASE + FAIL)) | ||
194 | trap 'SIG_RESULT=$FAIL' $SIG_FAIL | ||
195 | |||
190 | SIG_UNRESOLVED=$((SIG_BASE + UNRESOLVED)) | 196 | SIG_UNRESOLVED=$((SIG_BASE + UNRESOLVED)) |
191 | exit_unresolved () { | 197 | exit_unresolved () { |
192 | kill -s $SIG_UNRESOLVED $SIG_PID | 198 | kill -s $SIG_UNRESOLVED $SIG_PID |
@@ -215,17 +221,25 @@ exit_xfail () { | |||
215 | } | 221 | } |
216 | trap 'SIG_RESULT=$XFAIL' $SIG_XFAIL | 222 | trap 'SIG_RESULT=$XFAIL' $SIG_XFAIL |
217 | 223 | ||
224 | __run_test() { # testfile | ||
225 | # setup PID and PPID, $$ is not updated. | ||
226 | (cd $TRACING_DIR; read PID _ < /proc/self/stat ; set -e; set -x; . $1) | ||
227 | [ $? -ne 0 ] && kill -s $SIG_FAIL $SIG_PID | ||
228 | } | ||
229 | |||
218 | # Run one test case | 230 | # Run one test case |
219 | run_test() { # testfile | 231 | run_test() { # testfile |
220 | local testname=`basename $1` | 232 | local testname=`basename $1` |
221 | local testlog=`mktemp --tmpdir=$LOG_DIR ${testname}-XXXXXX.log` | 233 | local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX` |
222 | testcase $1 | 234 | testcase $1 |
223 | echo "execute: "$1 > $testlog | 235 | echo "execute: "$1 > $testlog |
224 | SIG_RESULT=0 | 236 | SIG_RESULT=0 |
225 | # setup PID and PPID, $$ is not updated. | 237 | if [ $VERBOSE -ne 0 ]; then |
226 | (cd $TRACING_DIR; read PID _ < /proc/self/stat ; | 238 | __run_test $1 2>> $testlog | tee -a $testlog |
227 | set -e; set -x; . $1) >> $testlog 2>&1 | 239 | else |
228 | eval_result $? $SIG_RESULT | 240 | __run_test $1 >> $testlog 2>&1 |
241 | fi | ||
242 | eval_result $SIG_RESULT | ||
229 | if [ $? -eq 0 ]; then | 243 | if [ $? -eq 0 ]; then |
230 | # Remove test log if the test was done as it was expected. | 244 | # Remove test log if the test was done as it was expected. |
231 | [ $KEEP_LOG -eq 0 ] && rm $testlog | 245 | [ $KEEP_LOG -eq 0 ] && rm $testlog |
@@ -235,6 +249,9 @@ run_test() { # testfile | |||
235 | fi | 249 | fi |
236 | } | 250 | } |
237 | 251 | ||
252 | # load in the helper functions | ||
253 | . $TEST_DIR/functions | ||
254 | |||
238 | # Main loop | 255 | # Main loop |
239 | for t in $TEST_CASES; do | 256 | for t in $TEST_CASES; do |
240 | run_test $t | 257 | run_test $t |
diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc new file mode 100644 index 000000000000..fd9c49a13612 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc | |||
@@ -0,0 +1,5 @@ | |||
1 | #!/bin/sh | ||
2 | # description: Basic event tracing check | ||
3 | test -f available_events -a -f set_event -a -d events | ||
4 | # check scheduler events are available | ||
5 | grep -q sched available_events && exit 0 || exit -1 \ No newline at end of file | ||
diff --git a/tools/testing/selftests/ftrace/test.d/event/event-enable.tc b/tools/testing/selftests/ftrace/test.d/event/event-enable.tc new file mode 100644 index 000000000000..668616d9bb03 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/event/event-enable.tc | |||
@@ -0,0 +1,53 @@ | |||
1 | #!/bin/sh | ||
2 | # description: event tracing - enable/disable with event level files | ||
3 | |||
4 | do_reset() { | ||
5 | echo > set_event | ||
6 | clear_trace | ||
7 | } | ||
8 | |||
9 | fail() { #msg | ||
10 | do_reset | ||
11 | echo $1 | ||
12 | exit -1 | ||
13 | } | ||
14 | |||
15 | if [ ! -f set_event -o ! -d events/sched ]; then | ||
16 | echo "event tracing is not supported" | ||
17 | exit_unsupported | ||
18 | fi | ||
19 | |||
20 | reset_tracer | ||
21 | do_reset | ||
22 | |||
23 | echo 'sched:sched_switch' > set_event | ||
24 | usleep 1 | ||
25 | |||
26 | count=`cat trace | grep sched_switch | wc -l` | ||
27 | if [ $count -eq 0 ]; then | ||
28 | fail "sched_switch events are not recorded" | ||
29 | fi | ||
30 | |||
31 | do_reset | ||
32 | |||
33 | echo 1 > events/sched/sched_switch/enable | ||
34 | usleep 1 | ||
35 | |||
36 | count=`cat trace | grep sched_switch | wc -l` | ||
37 | if [ $count -eq 0 ]; then | ||
38 | fail "sched_switch events are not recorded" | ||
39 | fi | ||
40 | |||
41 | do_reset | ||
42 | |||
43 | echo 0 > events/sched/sched_switch/enable | ||
44 | usleep 1 | ||
45 | |||
46 | count=`cat trace | grep sched_switch | wc -l` | ||
47 | if [ $count -ne 0 ]; then | ||
48 | fail "sched_switch events should not be recorded" | ||
49 | fi | ||
50 | |||
51 | do_reset | ||
52 | |||
53 | exit 0 | ||
diff --git a/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc b/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc new file mode 100644 index 000000000000..655c415b6e7f --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc | |||
@@ -0,0 +1,53 @@ | |||
1 | #!/bin/sh | ||
2 | # description: event tracing - enable/disable with subsystem level files | ||
3 | |||
4 | do_reset() { | ||
5 | echo > set_event | ||
6 | clear_trace | ||
7 | } | ||
8 | |||
9 | fail() { #msg | ||
10 | do_reset | ||
11 | echo $1 | ||
12 | exit -1 | ||
13 | } | ||
14 | |||
15 | if [ ! -f set_event -o ! -d events/sched ]; then | ||
16 | echo "event tracing is not supported" | ||
17 | exit_unsupported | ||
18 | fi | ||
19 | |||
20 | reset_tracer | ||
21 | do_reset | ||
22 | |||
23 | echo 'sched:*' > set_event | ||
24 | usleep 1 | ||
25 | |||
26 | count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` | ||
27 | if [ $count -lt 3 ]; then | ||
28 | fail "at least fork, exec and exit events should be recorded" | ||
29 | fi | ||
30 | |||
31 | do_reset | ||
32 | |||
33 | echo 1 > events/sched/enable | ||
34 | usleep 1 | ||
35 | |||
36 | count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` | ||
37 | if [ $count -lt 3 ]; then | ||
38 | fail "at least fork, exec and exit events should be recorded" | ||
39 | fi | ||
40 | |||
41 | do_reset | ||
42 | |||
43 | echo 0 > events/sched/enable | ||
44 | usleep 1 | ||
45 | |||
46 | count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` | ||
47 | if [ $count -ne 0 ]; then | ||
48 | fail "any of scheduler events should not be recorded" | ||
49 | fi | ||
50 | |||
51 | do_reset | ||
52 | |||
53 | exit 0 | ||
diff --git a/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc b/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc new file mode 100644 index 000000000000..480845774007 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc | |||
@@ -0,0 +1,47 @@ | |||
1 | #!/bin/sh | ||
2 | # description: event tracing - enable/disable with top level files | ||
3 | |||
4 | do_reset() { | ||
5 | echo > set_event | ||
6 | clear_trace | ||
7 | } | ||
8 | |||
9 | fail() { #msg | ||
10 | do_reset | ||
11 | echo $1 | ||
12 | exit -1 | ||
13 | } | ||
14 | |||
15 | if [ ! -f available_events -o ! -f set_event -o ! -d events ]; then | ||
16 | echo "event tracing is not supported" | ||
17 | exit_unsupported | ||
18 | fi | ||
19 | |||
20 | reset_tracer | ||
21 | do_reset | ||
22 | |||
23 | echo '*:*' > set_event | ||
24 | count=`cat trace | grep -v ^# | wc -l` | ||
25 | if [ $count -eq 0 ]; then | ||
26 | fail "none of events are recorded" | ||
27 | fi | ||
28 | |||
29 | do_reset | ||
30 | |||
31 | echo 1 > events/enable | ||
32 | count=`cat trace | grep -v ^# | wc -l` | ||
33 | if [ $count -eq 0 ]; then | ||
34 | fail "none of events are recorded" | ||
35 | fi | ||
36 | |||
37 | do_reset | ||
38 | |||
39 | echo 0 > events/enable | ||
40 | count=`cat trace | grep -v ^# | wc -l` | ||
41 | if [ $count -ne 0 ]; then | ||
42 | fail "any of events should not be recorded" | ||
43 | fi | ||
44 | |||
45 | do_reset | ||
46 | |||
47 | exit 0 | ||
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc new file mode 100644 index 000000000000..c15e018e0220 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc | |||
@@ -0,0 +1,89 @@ | |||
1 | #!/bin/sh | ||
2 | # description: ftrace - function graph filters with stack tracer | ||
3 | |||
4 | # Make sure that function graph filtering works, and is not | ||
5 | # affected by other tracers enabled (like stack tracer) | ||
6 | |||
7 | if ! grep -q function_graph available_tracers; then | ||
8 | echo "no function graph tracer configured" | ||
9 | exit_unsupported | ||
10 | fi | ||
11 | |||
12 | if [ ! -f set_ftrace_filter ]; then | ||
13 | echo "set_ftrace_filter not found? Is dynamic ftrace not set?" | ||
14 | exit_unsupported | ||
15 | fi | ||
16 | |||
17 | do_reset() { | ||
18 | reset_tracer | ||
19 | echo 0 > /proc/sys/kernel/stack_tracer_enabled | ||
20 | enable_tracing | ||
21 | clear_trace | ||
22 | echo > set_ftrace_filter | ||
23 | } | ||
24 | |||
25 | fail() { # msg | ||
26 | do_reset | ||
27 | echo $1 | ||
28 | exit -1 | ||
29 | } | ||
30 | |||
31 | disable_tracing | ||
32 | clear_trace; | ||
33 | |||
34 | # filter something, schedule is always good | ||
35 | if ! echo "schedule" > set_ftrace_filter; then | ||
36 | # test for powerpc 64 | ||
37 | if ! echo ".schedule" > set_ftrace_filter; then | ||
38 | fail "can not enable schedule filter" | ||
39 | fi | ||
40 | fi | ||
41 | |||
42 | echo function_graph > current_tracer | ||
43 | |||
44 | if [ ! -f stack_trace ]; then | ||
45 | echo "Stack tracer not configured" | ||
46 | do_reset | ||
47 | exit_unsupported; | ||
48 | fi | ||
49 | |||
50 | echo "Now testing with stack tracer" | ||
51 | |||
52 | echo 1 > /proc/sys/kernel/stack_tracer_enabled | ||
53 | |||
54 | disable_tracing | ||
55 | clear_trace | ||
56 | enable_tracing | ||
57 | sleep 1 | ||
58 | |||
59 | count=`cat trace | grep '()' | grep -v schedule | wc -l` | ||
60 | |||
61 | if [ $count -ne 0 ]; then | ||
62 | fail "Graph filtering not working with stack tracer?" | ||
63 | fi | ||
64 | |||
65 | # Make sure we did find something | ||
66 | count=`cat trace | grep 'schedule()' | wc -l` | ||
67 | if [ $count -eq 0 ]; then | ||
68 | fail "No schedule traces found?" | ||
69 | fi | ||
70 | |||
71 | echo 0 > /proc/sys/kernel/stack_tracer_enabled | ||
72 | clear_trace | ||
73 | sleep 1 | ||
74 | |||
75 | |||
76 | count=`cat trace | grep '()' | grep -v schedule | wc -l` | ||
77 | |||
78 | if [ $count -ne 0 ]; then | ||
79 | fail "Graph filtering not working after stack tracer disabled?" | ||
80 | fi | ||
81 | |||
82 | count=`cat trace | grep 'schedule()' | wc -l` | ||
83 | if [ $count -eq 0 ]; then | ||
84 | fail "No schedule traces found?" | ||
85 | fi | ||
86 | |||
87 | do_reset | ||
88 | |||
89 | exit 0 | ||
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc new file mode 100644 index 000000000000..6af5f6360b18 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc | |||
@@ -0,0 +1,52 @@ | |||
1 | #!/bin/sh | ||
2 | # description: ftrace - function graph filters | ||
3 | |||
4 | # Make sure that function graph filtering works | ||
5 | |||
6 | if ! grep -q function_graph available_tracers; then | ||
7 | echo "no function graph tracer configured" | ||
8 | exit_unsupported | ||
9 | fi | ||
10 | |||
11 | do_reset() { | ||
12 | reset_tracer | ||
13 | enable_tracing | ||
14 | clear_trace | ||
15 | } | ||
16 | |||
17 | fail() { # msg | ||
18 | do_reset | ||
19 | echo $1 | ||
20 | exit -1 | ||
21 | } | ||
22 | |||
23 | disable_tracing | ||
24 | clear_trace | ||
25 | |||
26 | # filter something, schedule is always good | ||
27 | if ! echo "schedule" > set_ftrace_filter; then | ||
28 | # test for powerpc 64 | ||
29 | if ! echo ".schedule" > set_ftrace_filter; then | ||
30 | fail "can not enable schedule filter" | ||
31 | fi | ||
32 | fi | ||
33 | |||
34 | echo function_graph > current_tracer | ||
35 | enable_tracing | ||
36 | sleep 1 | ||
37 | # search for functions (has "()" on the line), and make sure | ||
38 | # that only the schedule function was found | ||
39 | count=`cat trace | grep '()' | grep -v schedule | wc -l` | ||
40 | if [ $count -ne 0 ]; then | ||
41 | fail "Graph filtering not working by itself?" | ||
42 | fi | ||
43 | |||
44 | # Make sure we did find something | ||
45 | count=`cat trace | grep 'schedule()' | wc -l` | ||
46 | if [ $count -eq 0 ]; then | ||
47 | fail "No schedule traces found?" | ||
48 | fi | ||
49 | |||
50 | do_reset | ||
51 | |||
52 | exit 0 | ||
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc new file mode 100644 index 000000000000..2e719cb1fc4d --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc | |||
@@ -0,0 +1,80 @@ | |||
1 | #!/bin/sh | ||
2 | # description: ftrace - function profiler with function tracing | ||
3 | |||
4 | # There was a bug after a rewrite of the ftrace infrastructure that | ||
5 | # caused the function_profiler not to be able to run with the function | ||
6 | # tracer, because the function_profiler used the function_graph tracer | ||
7 | # and it was assumed the two could not run simultaneously. | ||
8 | # | ||
9 | # There was another related bug where the solution to the first bug | ||
10 | # broke the way filtering of the function tracer worked. | ||
11 | # | ||
12 | # This test triggers those bugs on those kernels. | ||
13 | # | ||
14 | # We need function_graph and profiling to to run this test | ||
15 | if ! grep -q function_graph available_tracers; then | ||
16 | echo "no function graph tracer configured" | ||
17 | exit_unsupported; | ||
18 | fi | ||
19 | |||
20 | if [ ! -f set_ftrace_filter ]; then | ||
21 | echo "set_ftrace_filter not found? Is dynamic ftrace not set?" | ||
22 | exit_unsupported | ||
23 | fi | ||
24 | |||
25 | if [ ! -f function_profile_enabled ]; then | ||
26 | echo "function_profile_enabled not found, function profiling enabled?" | ||
27 | exit_unsupported | ||
28 | fi | ||
29 | |||
30 | fail() { # mesg | ||
31 | reset_tracer | ||
32 | echo > set_ftrace_filter | ||
33 | echo $1 | ||
34 | exit -1 | ||
35 | } | ||
36 | |||
37 | echo "Testing function tracer with profiler:" | ||
38 | echo "enable function tracer" | ||
39 | echo function > current_tracer | ||
40 | echo "enable profiler" | ||
41 | echo 1 > function_profile_enabled | ||
42 | |||
43 | sleep 1 | ||
44 | |||
45 | echo "Now filter on just schedule" | ||
46 | echo '*schedule' > set_ftrace_filter | ||
47 | clear_trace | ||
48 | |||
49 | echo "Now disable function profiler" | ||
50 | echo 0 > function_profile_enabled | ||
51 | |||
52 | sleep 1 | ||
53 | |||
54 | # make sure only schedule functions exist | ||
55 | |||
56 | echo "testing if only schedule is being traced" | ||
57 | if grep -v -e '^#' -e 'schedule' trace; then | ||
58 | fail "more than schedule was found" | ||
59 | fi | ||
60 | |||
61 | echo "Make sure schedule was traced" | ||
62 | if ! grep -e 'schedule' trace > /dev/null; then | ||
63 | cat trace | ||
64 | fail "can not find schedule in trace" | ||
65 | fi | ||
66 | |||
67 | echo > set_ftrace_filter | ||
68 | clear_trace | ||
69 | |||
70 | sleep 1 | ||
71 | |||
72 | echo "make sure something other than scheduler is being traced" | ||
73 | if ! grep -v -e '^#' -e 'schedule' trace > /dev/null; then | ||
74 | cat trace | ||
75 | fail "no other functions besides schedule was found" | ||
76 | fi | ||
77 | |||
78 | reset_tracer | ||
79 | |||
80 | exit 0 | ||
diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions new file mode 100644 index 000000000000..5d8cd06d920f --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/functions | |||
@@ -0,0 +1,16 @@ | |||
1 | |||
2 | clear_trace() { # reset trace output | ||
3 | echo > trace | ||
4 | } | ||
5 | |||
6 | disable_tracing() { # stop trace recording | ||
7 | echo 0 > tracing_on | ||
8 | } | ||
9 | |||
10 | enable_tracing() { # start trace recording | ||
11 | echo 1 > tracing_on | ||
12 | } | ||
13 | |||
14 | reset_tracer() { # reset the current tracer | ||
15 | echo nop > current_tracer | ||
16 | } | ||
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc b/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc index 1b8b665ab2b3..a5a426211129 100644 --- a/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc +++ b/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc | |||
@@ -9,3 +9,4 @@ echo p:myevent do_fork > kprobe_events | |||
9 | grep myevent kprobe_events | 9 | grep myevent kprobe_events |
10 | test -d events/kprobes/myevent | 10 | test -d events/kprobes/myevent |
11 | echo > kprobe_events | 11 | echo > kprobe_events |
12 | clear_trace | ||
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc b/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc index b55c84003587..d8c7bb6581fe 100644 --- a/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc +++ b/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc | |||
@@ -11,3 +11,4 @@ echo 1 > events/kprobes/myevent/enable | |||
11 | echo > kprobe_events && exit 1 # this must fail | 11 | echo > kprobe_events && exit 1 # this must fail |
12 | echo 0 > events/kprobes/myevent/enable | 12 | echo 0 > events/kprobes/myevent/enable |
13 | echo > kprobe_events # this must succeed | 13 | echo > kprobe_events # this must succeed |
14 | clear_trace | ||
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc index a603d3f8db7b..c45ee2761354 100644 --- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc | |||
@@ -12,5 +12,6 @@ echo 1 > events/kprobes/testprobe/enable | |||
12 | ( echo "forked") | 12 | ( echo "forked") |
13 | echo 0 > events/kprobes/testprobe/enable | 13 | echo 0 > events/kprobes/testprobe/enable |
14 | echo "-:testprobe" >> kprobe_events | 14 | echo "-:testprobe" >> kprobe_events |
15 | clear_trace | ||
15 | test -d events/kprobes/testprobe && exit 1 || exit 0 | 16 | test -d events/kprobes/testprobe && exit 1 || exit 0 |
16 | 17 | ||
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc new file mode 100644 index 000000000000..ab41d2b29841 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc | |||
@@ -0,0 +1,55 @@ | |||
1 | #!/bin/sh | ||
2 | # description: Kprobe dynamic event with function tracer | ||
3 | |||
4 | [ -f kprobe_events ] || exit_unsupported # this is configurable | ||
5 | grep function available_tracers || exit_unsupported # this is configurable | ||
6 | |||
7 | # prepare | ||
8 | echo nop > current_tracer | ||
9 | echo do_fork > set_ftrace_filter | ||
10 | echo 0 > events/enable | ||
11 | echo > kprobe_events | ||
12 | echo 'p:testprobe do_fork' > kprobe_events | ||
13 | |||
14 | # kprobe on / ftrace off | ||
15 | echo 1 > events/kprobes/testprobe/enable | ||
16 | echo > trace | ||
17 | ( echo "forked") | ||
18 | grep testprobe trace | ||
19 | ! grep 'do_fork <-' trace | ||
20 | |||
21 | # kprobe on / ftrace on | ||
22 | echo function > current_tracer | ||
23 | echo > trace | ||
24 | ( echo "forked") | ||
25 | grep testprobe trace | ||
26 | grep 'do_fork <-' trace | ||
27 | |||
28 | # kprobe off / ftrace on | ||
29 | echo 0 > events/kprobes/testprobe/enable | ||
30 | echo > trace | ||
31 | ( echo "forked") | ||
32 | ! grep testprobe trace | ||
33 | grep 'do_fork <-' trace | ||
34 | |||
35 | # kprobe on / ftrace on | ||
36 | echo 1 > events/kprobes/testprobe/enable | ||
37 | echo function > current_tracer | ||
38 | echo > trace | ||
39 | ( echo "forked") | ||
40 | grep testprobe trace | ||
41 | grep 'do_fork <-' trace | ||
42 | |||
43 | # kprobe on / ftrace off | ||
44 | echo nop > current_tracer | ||
45 | echo > trace | ||
46 | ( echo "forked") | ||
47 | grep testprobe trace | ||
48 | ! grep 'do_fork <-' trace | ||
49 | |||
50 | # cleanup | ||
51 | echo nop > current_tracer | ||
52 | echo > set_ftrace_filter | ||
53 | echo 0 > events/kprobes/testprobe/enable | ||
54 | echo > kprobe_events | ||
55 | echo > trace | ||
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc index 283c29e7f7c4..31717985acc7 100644 --- a/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc | |||
@@ -12,4 +12,5 @@ echo 1 > events/kprobes/testprobe2/enable | |||
12 | ( echo "forked") | 12 | ( echo "forked") |
13 | echo 0 > events/kprobes/testprobe2/enable | 13 | echo 0 > events/kprobes/testprobe2/enable |
14 | echo '-:testprobe2' >> kprobe_events | 14 | echo '-:testprobe2' >> kprobe_events |
15 | clear_trace | ||
15 | test -d events/kprobes/testprobe2 && exit 1 || exit 0 | 16 | test -d events/kprobes/testprobe2 && exit 1 || exit 0 |
diff --git a/tools/testing/selftests/ipc/msgque.c b/tools/testing/selftests/ipc/msgque.c index 552f0810bffb..1b2ce334bb3f 100644 --- a/tools/testing/selftests/ipc/msgque.c +++ b/tools/testing/selftests/ipc/msgque.c | |||
@@ -5,6 +5,8 @@ | |||
5 | #include <linux/msg.h> | 5 | #include <linux/msg.h> |
6 | #include <fcntl.h> | 6 | #include <fcntl.h> |
7 | 7 | ||
8 | #include "../kselftest.h" | ||
9 | |||
8 | #define MAX_MSG_SIZE 32 | 10 | #define MAX_MSG_SIZE 32 |
9 | 11 | ||
10 | struct msg1 { | 12 | struct msg1 { |
@@ -195,58 +197,58 @@ int main(int argc, char **argv) | |||
195 | 197 | ||
196 | if (getuid() != 0) { | 198 | if (getuid() != 0) { |
197 | printf("Please run the test as root - Exiting.\n"); | 199 | printf("Please run the test as root - Exiting.\n"); |
198 | exit(1); | 200 | return ksft_exit_fail(); |
199 | } | 201 | } |
200 | 202 | ||
201 | msgque.key = ftok(argv[0], 822155650); | 203 | msgque.key = ftok(argv[0], 822155650); |
202 | if (msgque.key == -1) { | 204 | if (msgque.key == -1) { |
203 | printf("Can't make key\n"); | 205 | printf("Can't make key: %d\n", -errno); |
204 | return -errno; | 206 | return ksft_exit_fail(); |
205 | } | 207 | } |
206 | 208 | ||
207 | msgque.msq_id = msgget(msgque.key, IPC_CREAT | IPC_EXCL | 0666); | 209 | msgque.msq_id = msgget(msgque.key, IPC_CREAT | IPC_EXCL | 0666); |
208 | if (msgque.msq_id == -1) { | 210 | if (msgque.msq_id == -1) { |
209 | err = -errno; | 211 | err = -errno; |
210 | printf("Can't create queue\n"); | 212 | printf("Can't create queue: %d\n", err); |
211 | goto err_out; | 213 | goto err_out; |
212 | } | 214 | } |
213 | 215 | ||
214 | err = fill_msgque(&msgque); | 216 | err = fill_msgque(&msgque); |
215 | if (err) { | 217 | if (err) { |
216 | printf("Failed to fill queue\n"); | 218 | printf("Failed to fill queue: %d\n", err); |
217 | goto err_destroy; | 219 | goto err_destroy; |
218 | } | 220 | } |
219 | 221 | ||
220 | err = dump_queue(&msgque); | 222 | err = dump_queue(&msgque); |
221 | if (err) { | 223 | if (err) { |
222 | printf("Failed to dump queue\n"); | 224 | printf("Failed to dump queue: %d\n", err); |
223 | goto err_destroy; | 225 | goto err_destroy; |
224 | } | 226 | } |
225 | 227 | ||
226 | err = check_and_destroy_queue(&msgque); | 228 | err = check_and_destroy_queue(&msgque); |
227 | if (err) { | 229 | if (err) { |
228 | printf("Failed to check and destroy queue\n"); | 230 | printf("Failed to check and destroy queue: %d\n", err); |
229 | goto err_out; | 231 | goto err_out; |
230 | } | 232 | } |
231 | 233 | ||
232 | err = restore_queue(&msgque); | 234 | err = restore_queue(&msgque); |
233 | if (err) { | 235 | if (err) { |
234 | printf("Failed to restore queue\n"); | 236 | printf("Failed to restore queue: %d\n", err); |
235 | goto err_destroy; | 237 | goto err_destroy; |
236 | } | 238 | } |
237 | 239 | ||
238 | err = check_and_destroy_queue(&msgque); | 240 | err = check_and_destroy_queue(&msgque); |
239 | if (err) { | 241 | if (err) { |
240 | printf("Failed to test queue\n"); | 242 | printf("Failed to test queue: %d\n", err); |
241 | goto err_out; | 243 | goto err_out; |
242 | } | 244 | } |
243 | return 0; | 245 | return ksft_exit_pass(); |
244 | 246 | ||
245 | err_destroy: | 247 | err_destroy: |
246 | if (msgctl(msgque.msq_id, IPC_RMID, 0)) { | 248 | if (msgctl(msgque.msq_id, IPC_RMID, 0)) { |
247 | printf("Failed to destroy queue: %d\n", -errno); | 249 | printf("Failed to destroy queue: %d\n", -errno); |
248 | return -errno; | 250 | return ksft_exit_fail(); |
249 | } | 251 | } |
250 | err_out: | 252 | err_out: |
251 | return err; | 253 | return ksft_exit_fail(); |
252 | } | 254 | } |
diff --git a/tools/testing/selftests/kcmp/Makefile b/tools/testing/selftests/kcmp/Makefile index 8aabd82db9e4..ff0eefdc6ceb 100644 --- a/tools/testing/selftests/kcmp/Makefile +++ b/tools/testing/selftests/kcmp/Makefile | |||
@@ -1,25 +1,7 @@ | |||
1 | uname_M := $(shell uname -m 2>/dev/null || echo not) | 1 | CC := $(CROSS_COMPILE)$(CC) |
2 | ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/) | ||
3 | ifeq ($(ARCH),i386) | ||
4 | ARCH := x86 | ||
5 | CFLAGS := -DCONFIG_X86_32 -D__i386__ | ||
6 | endif | ||
7 | ifeq ($(ARCH),x86_64) | ||
8 | ARCH := x86 | ||
9 | CFLAGS := -DCONFIG_X86_64 -D__x86_64__ | ||
10 | endif | ||
11 | |||
12 | CFLAGS += -I../../../../arch/x86/include/generated/ | ||
13 | CFLAGS += -I../../../../include/ | ||
14 | CFLAGS += -I../../../../usr/include/ | 2 | CFLAGS += -I../../../../usr/include/ |
15 | CFLAGS += -I../../../../arch/x86/include/ | ||
16 | 3 | ||
17 | all: | 4 | all: kcmp_test |
18 | ifeq ($(ARCH),x86) | ||
19 | gcc $(CFLAGS) kcmp_test.c -o kcmp_test | ||
20 | else | ||
21 | echo "Not an x86 target, can't build kcmp selftest" | ||
22 | endif | ||
23 | 5 | ||
24 | run_tests: all | 6 | run_tests: all |
25 | @./kcmp_test || echo "kcmp_test: [FAIL]" | 7 | @./kcmp_test || echo "kcmp_test: [FAIL]" |
diff --git a/tools/testing/selftests/kcmp/kcmp_test.c b/tools/testing/selftests/kcmp/kcmp_test.c index dbba4084869c..a5a4da856dfe 100644 --- a/tools/testing/selftests/kcmp/kcmp_test.c +++ b/tools/testing/selftests/kcmp/kcmp_test.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <sys/stat.h> | 17 | #include <sys/stat.h> |
18 | #include <sys/wait.h> | 18 | #include <sys/wait.h> |
19 | 19 | ||
20 | #include "../kselftest.h" | ||
21 | |||
20 | static long sys_kcmp(int pid1, int pid2, int type, int fd1, int fd2) | 22 | static long sys_kcmp(int pid1, int pid2, int type, int fd1, int fd2) |
21 | { | 23 | { |
22 | return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2); | 24 | return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2); |
@@ -34,13 +36,13 @@ int main(int argc, char **argv) | |||
34 | 36 | ||
35 | if (fd1 < 0) { | 37 | if (fd1 < 0) { |
36 | perror("Can't create file"); | 38 | perror("Can't create file"); |
37 | exit(1); | 39 | ksft_exit_fail(); |
38 | } | 40 | } |
39 | 41 | ||
40 | pid2 = fork(); | 42 | pid2 = fork(); |
41 | if (pid2 < 0) { | 43 | if (pid2 < 0) { |
42 | perror("fork failed"); | 44 | perror("fork failed"); |
43 | exit(1); | 45 | ksft_exit_fail(); |
44 | } | 46 | } |
45 | 47 | ||
46 | if (!pid2) { | 48 | if (!pid2) { |
@@ -50,7 +52,7 @@ int main(int argc, char **argv) | |||
50 | fd2 = open(kpath, O_RDWR, 0644); | 52 | fd2 = open(kpath, O_RDWR, 0644); |
51 | if (fd2 < 0) { | 53 | if (fd2 < 0) { |
52 | perror("Can't open file"); | 54 | perror("Can't open file"); |
53 | exit(1); | 55 | ksft_exit_fail(); |
54 | } | 56 | } |
55 | 57 | ||
56 | /* An example of output and arguments */ | 58 | /* An example of output and arguments */ |
@@ -74,23 +76,34 @@ int main(int argc, char **argv) | |||
74 | if (ret) { | 76 | if (ret) { |
75 | printf("FAIL: 0 expected but %d returned (%s)\n", | 77 | printf("FAIL: 0 expected but %d returned (%s)\n", |
76 | ret, strerror(errno)); | 78 | ret, strerror(errno)); |
79 | ksft_inc_fail_cnt(); | ||
77 | ret = -1; | 80 | ret = -1; |
78 | } else | 81 | } else { |
79 | printf("PASS: 0 returned as expected\n"); | 82 | printf("PASS: 0 returned as expected\n"); |
83 | ksft_inc_pass_cnt(); | ||
84 | } | ||
80 | 85 | ||
81 | /* Compare with self */ | 86 | /* Compare with self */ |
82 | ret = sys_kcmp(pid1, pid1, KCMP_VM, 0, 0); | 87 | ret = sys_kcmp(pid1, pid1, KCMP_VM, 0, 0); |
83 | if (ret) { | 88 | if (ret) { |
84 | printf("FAIL: 0 expected but %d returned (%s)\n", | 89 | printf("FAIL: 0 expected but %d returned (%s)\n", |
85 | ret, strerror(errno)); | 90 | ret, strerror(errno)); |
91 | ksft_inc_fail_cnt(); | ||
86 | ret = -1; | 92 | ret = -1; |
87 | } else | 93 | } else { |
88 | printf("PASS: 0 returned as expected\n"); | 94 | printf("PASS: 0 returned as expected\n"); |
95 | ksft_inc_pass_cnt(); | ||
96 | } | ||
97 | |||
98 | ksft_print_cnts(); | ||
89 | 99 | ||
90 | exit(ret); | 100 | if (ret) |
101 | ksft_exit_fail(); | ||
102 | else | ||
103 | ksft_exit_pass(); | ||
91 | } | 104 | } |
92 | 105 | ||
93 | waitpid(pid2, &status, P_ALL); | 106 | waitpid(pid2, &status, P_ALL); |
94 | 107 | ||
95 | return 0; | 108 | return ksft_exit_pass(); |
96 | } | 109 | } |
diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h new file mode 100644 index 000000000000..572c8888167a --- /dev/null +++ b/tools/testing/selftests/kselftest.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * kselftest.h: kselftest framework return codes to include from | ||
3 | * selftests. | ||
4 | * | ||
5 | * Copyright (c) 2014 Shuah Khan <shuahkh@osg.samsung.com> | ||
6 | * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||
7 | * | ||
8 | * This file is released under the GPLv2. | ||
9 | */ | ||
10 | #ifndef __KSELFTEST_H | ||
11 | #define __KSELFTEST_H | ||
12 | |||
13 | #include <stdlib.h> | ||
14 | #include <unistd.h> | ||
15 | |||
16 | /* counters */ | ||
17 | struct ksft_count { | ||
18 | unsigned int ksft_pass; | ||
19 | unsigned int ksft_fail; | ||
20 | unsigned int ksft_xfail; | ||
21 | unsigned int ksft_xpass; | ||
22 | unsigned int ksft_xskip; | ||
23 | }; | ||
24 | |||
25 | static struct ksft_count ksft_cnt; | ||
26 | |||
27 | static inline void ksft_inc_pass_cnt(void) { ksft_cnt.ksft_pass++; } | ||
28 | static inline void ksft_inc_fail_cnt(void) { ksft_cnt.ksft_fail++; } | ||
29 | static inline void ksft_inc_xfail_cnt(void) { ksft_cnt.ksft_xfail++; } | ||
30 | static inline void ksft_inc_xpass_cnt(void) { ksft_cnt.ksft_xpass++; } | ||
31 | static inline void ksft_inc_xskip_cnt(void) { ksft_cnt.ksft_xskip++; } | ||
32 | |||
33 | static inline void ksft_print_cnts(void) | ||
34 | { | ||
35 | printf("Pass: %d Fail: %d Xfail: %d Xpass: %d, Xskip: %d\n", | ||
36 | ksft_cnt.ksft_pass, ksft_cnt.ksft_fail, | ||
37 | ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass, | ||
38 | ksft_cnt.ksft_xskip); | ||
39 | } | ||
40 | |||
41 | static inline int ksft_exit_pass(void) | ||
42 | { | ||
43 | exit(0); | ||
44 | } | ||
45 | static inline int ksft_exit_fail(void) | ||
46 | { | ||
47 | exit(1); | ||
48 | } | ||
49 | static inline int ksft_exit_xfail(void) | ||
50 | { | ||
51 | exit(2); | ||
52 | } | ||
53 | static inline int ksft_exit_xpass(void) | ||
54 | { | ||
55 | exit(3); | ||
56 | } | ||
57 | static inline int ksft_exit_skip(void) | ||
58 | { | ||
59 | exit(4); | ||
60 | } | ||
61 | |||
62 | #endif /* __KSELFTEST_H */ | ||
diff --git a/tools/testing/selftests/mount/unprivileged-remount-test.c b/tools/testing/selftests/mount/unprivileged-remount-test.c index 1b3ff2fda4d0..517785052f1c 100644 --- a/tools/testing/selftests/mount/unprivileged-remount-test.c +++ b/tools/testing/selftests/mount/unprivileged-remount-test.c | |||
@@ -6,6 +6,8 @@ | |||
6 | #include <sys/types.h> | 6 | #include <sys/types.h> |
7 | #include <sys/mount.h> | 7 | #include <sys/mount.h> |
8 | #include <sys/wait.h> | 8 | #include <sys/wait.h> |
9 | #include <sys/vfs.h> | ||
10 | #include <sys/statvfs.h> | ||
9 | #include <stdlib.h> | 11 | #include <stdlib.h> |
10 | #include <unistd.h> | 12 | #include <unistd.h> |
11 | #include <fcntl.h> | 13 | #include <fcntl.h> |
@@ -32,11 +34,14 @@ | |||
32 | # define CLONE_NEWPID 0x20000000 | 34 | # define CLONE_NEWPID 0x20000000 |
33 | #endif | 35 | #endif |
34 | 36 | ||
37 | #ifndef MS_REC | ||
38 | # define MS_REC 16384 | ||
39 | #endif | ||
35 | #ifndef MS_RELATIME | 40 | #ifndef MS_RELATIME |
36 | #define MS_RELATIME (1 << 21) | 41 | # define MS_RELATIME (1 << 21) |
37 | #endif | 42 | #endif |
38 | #ifndef MS_STRICTATIME | 43 | #ifndef MS_STRICTATIME |
39 | #define MS_STRICTATIME (1 << 24) | 44 | # define MS_STRICTATIME (1 << 24) |
40 | #endif | 45 | #endif |
41 | 46 | ||
42 | static void die(char *fmt, ...) | 47 | static void die(char *fmt, ...) |
@@ -48,17 +53,14 @@ static void die(char *fmt, ...) | |||
48 | exit(EXIT_FAILURE); | 53 | exit(EXIT_FAILURE); |
49 | } | 54 | } |
50 | 55 | ||
51 | static void write_file(char *filename, char *fmt, ...) | 56 | static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list ap) |
52 | { | 57 | { |
53 | char buf[4096]; | 58 | char buf[4096]; |
54 | int fd; | 59 | int fd; |
55 | ssize_t written; | 60 | ssize_t written; |
56 | int buf_len; | 61 | int buf_len; |
57 | va_list ap; | ||
58 | 62 | ||
59 | va_start(ap, fmt); | ||
60 | buf_len = vsnprintf(buf, sizeof(buf), fmt, ap); | 63 | buf_len = vsnprintf(buf, sizeof(buf), fmt, ap); |
61 | va_end(ap); | ||
62 | if (buf_len < 0) { | 64 | if (buf_len < 0) { |
63 | die("vsnprintf failed: %s\n", | 65 | die("vsnprintf failed: %s\n", |
64 | strerror(errno)); | 66 | strerror(errno)); |
@@ -69,6 +71,8 @@ static void write_file(char *filename, char *fmt, ...) | |||
69 | 71 | ||
70 | fd = open(filename, O_WRONLY); | 72 | fd = open(filename, O_WRONLY); |
71 | if (fd < 0) { | 73 | if (fd < 0) { |
74 | if ((errno == ENOENT) && enoent_ok) | ||
75 | return; | ||
72 | die("open of %s failed: %s\n", | 76 | die("open of %s failed: %s\n", |
73 | filename, strerror(errno)); | 77 | filename, strerror(errno)); |
74 | } | 78 | } |
@@ -87,6 +91,65 @@ static void write_file(char *filename, char *fmt, ...) | |||
87 | } | 91 | } |
88 | } | 92 | } |
89 | 93 | ||
94 | static void maybe_write_file(char *filename, char *fmt, ...) | ||
95 | { | ||
96 | va_list ap; | ||
97 | |||
98 | va_start(ap, fmt); | ||
99 | vmaybe_write_file(true, filename, fmt, ap); | ||
100 | va_end(ap); | ||
101 | |||
102 | } | ||
103 | |||
104 | static void write_file(char *filename, char *fmt, ...) | ||
105 | { | ||
106 | va_list ap; | ||
107 | |||
108 | va_start(ap, fmt); | ||
109 | vmaybe_write_file(false, filename, fmt, ap); | ||
110 | va_end(ap); | ||
111 | |||
112 | } | ||
113 | |||
114 | static int read_mnt_flags(const char *path) | ||
115 | { | ||
116 | int ret; | ||
117 | struct statvfs stat; | ||
118 | int mnt_flags; | ||
119 | |||
120 | ret = statvfs(path, &stat); | ||
121 | if (ret != 0) { | ||
122 | die("statvfs of %s failed: %s\n", | ||
123 | path, strerror(errno)); | ||
124 | } | ||
125 | if (stat.f_flag & ~(ST_RDONLY | ST_NOSUID | ST_NODEV | \ | ||
126 | ST_NOEXEC | ST_NOATIME | ST_NODIRATIME | ST_RELATIME | \ | ||
127 | ST_SYNCHRONOUS | ST_MANDLOCK)) { | ||
128 | die("Unrecognized mount flags\n"); | ||
129 | } | ||
130 | mnt_flags = 0; | ||
131 | if (stat.f_flag & ST_RDONLY) | ||
132 | mnt_flags |= MS_RDONLY; | ||
133 | if (stat.f_flag & ST_NOSUID) | ||
134 | mnt_flags |= MS_NOSUID; | ||
135 | if (stat.f_flag & ST_NODEV) | ||
136 | mnt_flags |= MS_NODEV; | ||
137 | if (stat.f_flag & ST_NOEXEC) | ||
138 | mnt_flags |= MS_NOEXEC; | ||
139 | if (stat.f_flag & ST_NOATIME) | ||
140 | mnt_flags |= MS_NOATIME; | ||
141 | if (stat.f_flag & ST_NODIRATIME) | ||
142 | mnt_flags |= MS_NODIRATIME; | ||
143 | if (stat.f_flag & ST_RELATIME) | ||
144 | mnt_flags |= MS_RELATIME; | ||
145 | if (stat.f_flag & ST_SYNCHRONOUS) | ||
146 | mnt_flags |= MS_SYNCHRONOUS; | ||
147 | if (stat.f_flag & ST_MANDLOCK) | ||
148 | mnt_flags |= ST_MANDLOCK; | ||
149 | |||
150 | return mnt_flags; | ||
151 | } | ||
152 | |||
90 | static void create_and_enter_userns(void) | 153 | static void create_and_enter_userns(void) |
91 | { | 154 | { |
92 | uid_t uid; | 155 | uid_t uid; |
@@ -100,13 +163,10 @@ static void create_and_enter_userns(void) | |||
100 | strerror(errno)); | 163 | strerror(errno)); |
101 | } | 164 | } |
102 | 165 | ||
166 | maybe_write_file("/proc/self/setgroups", "deny"); | ||
103 | write_file("/proc/self/uid_map", "0 %d 1", uid); | 167 | write_file("/proc/self/uid_map", "0 %d 1", uid); |
104 | write_file("/proc/self/gid_map", "0 %d 1", gid); | 168 | write_file("/proc/self/gid_map", "0 %d 1", gid); |
105 | 169 | ||
106 | if (setgroups(0, NULL) != 0) { | ||
107 | die("setgroups failed: %s\n", | ||
108 | strerror(errno)); | ||
109 | } | ||
110 | if (setgid(0) != 0) { | 170 | if (setgid(0) != 0) { |
111 | die ("setgid(0) failed %s\n", | 171 | die ("setgid(0) failed %s\n", |
112 | strerror(errno)); | 172 | strerror(errno)); |
@@ -118,7 +178,8 @@ static void create_and_enter_userns(void) | |||
118 | } | 178 | } |
119 | 179 | ||
120 | static | 180 | static |
121 | bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags) | 181 | bool test_unpriv_remount(const char *fstype, const char *mount_options, |
182 | int mount_flags, int remount_flags, int invalid_flags) | ||
122 | { | 183 | { |
123 | pid_t child; | 184 | pid_t child; |
124 | 185 | ||
@@ -151,9 +212,11 @@ bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags) | |||
151 | strerror(errno)); | 212 | strerror(errno)); |
152 | } | 213 | } |
153 | 214 | ||
154 | if (mount("testing", "/tmp", "ramfs", mount_flags, NULL) != 0) { | 215 | if (mount("testing", "/tmp", fstype, mount_flags, mount_options) != 0) { |
155 | die("mount of /tmp failed: %s\n", | 216 | die("mount of %s with options '%s' on /tmp failed: %s\n", |
156 | strerror(errno)); | 217 | fstype, |
218 | mount_options? mount_options : "", | ||
219 | strerror(errno)); | ||
157 | } | 220 | } |
158 | 221 | ||
159 | create_and_enter_userns(); | 222 | create_and_enter_userns(); |
@@ -181,62 +244,127 @@ bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags) | |||
181 | 244 | ||
182 | static bool test_unpriv_remount_simple(int mount_flags) | 245 | static bool test_unpriv_remount_simple(int mount_flags) |
183 | { | 246 | { |
184 | return test_unpriv_remount(mount_flags, mount_flags, 0); | 247 | return test_unpriv_remount("ramfs", NULL, mount_flags, mount_flags, 0); |
185 | } | 248 | } |
186 | 249 | ||
187 | static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags) | 250 | static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags) |
188 | { | 251 | { |
189 | return test_unpriv_remount(mount_flags, mount_flags, invalid_flags); | 252 | return test_unpriv_remount("ramfs", NULL, mount_flags, mount_flags, |
253 | invalid_flags); | ||
254 | } | ||
255 | |||
256 | static bool test_priv_mount_unpriv_remount(void) | ||
257 | { | ||
258 | pid_t child; | ||
259 | int ret; | ||
260 | const char *orig_path = "/dev"; | ||
261 | const char *dest_path = "/tmp"; | ||
262 | int orig_mnt_flags, remount_mnt_flags; | ||
263 | |||
264 | child = fork(); | ||
265 | if (child == -1) { | ||
266 | die("fork failed: %s\n", | ||
267 | strerror(errno)); | ||
268 | } | ||
269 | if (child != 0) { /* parent */ | ||
270 | pid_t pid; | ||
271 | int status; | ||
272 | pid = waitpid(child, &status, 0); | ||
273 | if (pid == -1) { | ||
274 | die("waitpid failed: %s\n", | ||
275 | strerror(errno)); | ||
276 | } | ||
277 | if (pid != child) { | ||
278 | die("waited for %d got %d\n", | ||
279 | child, pid); | ||
280 | } | ||
281 | if (!WIFEXITED(status)) { | ||
282 | die("child did not terminate cleanly\n"); | ||
283 | } | ||
284 | return WEXITSTATUS(status) == EXIT_SUCCESS ? true : false; | ||
285 | } | ||
286 | |||
287 | orig_mnt_flags = read_mnt_flags(orig_path); | ||
288 | |||
289 | create_and_enter_userns(); | ||
290 | ret = unshare(CLONE_NEWNS); | ||
291 | if (ret != 0) { | ||
292 | die("unshare(CLONE_NEWNS) failed: %s\n", | ||
293 | strerror(errno)); | ||
294 | } | ||
295 | |||
296 | ret = mount(orig_path, dest_path, "bind", MS_BIND | MS_REC, NULL); | ||
297 | if (ret != 0) { | ||
298 | die("recursive bind mount of %s onto %s failed: %s\n", | ||
299 | orig_path, dest_path, strerror(errno)); | ||
300 | } | ||
301 | |||
302 | ret = mount(dest_path, dest_path, "none", | ||
303 | MS_REMOUNT | MS_BIND | orig_mnt_flags , NULL); | ||
304 | if (ret != 0) { | ||
305 | /* system("cat /proc/self/mounts"); */ | ||
306 | die("remount of /tmp failed: %s\n", | ||
307 | strerror(errno)); | ||
308 | } | ||
309 | |||
310 | remount_mnt_flags = read_mnt_flags(dest_path); | ||
311 | if (orig_mnt_flags != remount_mnt_flags) { | ||
312 | die("Mount flags unexpectedly changed during remount of %s originally mounted on %s\n", | ||
313 | dest_path, orig_path); | ||
314 | } | ||
315 | exit(EXIT_SUCCESS); | ||
190 | } | 316 | } |
191 | 317 | ||
192 | int main(int argc, char **argv) | 318 | int main(int argc, char **argv) |
193 | { | 319 | { |
194 | if (!test_unpriv_remount_simple(MS_RDONLY|MS_NODEV)) { | 320 | if (!test_unpriv_remount_simple(MS_RDONLY)) { |
195 | die("MS_RDONLY malfunctions\n"); | 321 | die("MS_RDONLY malfunctions\n"); |
196 | } | 322 | } |
197 | if (!test_unpriv_remount_simple(MS_NODEV)) { | 323 | if (!test_unpriv_remount("devpts", "newinstance", MS_NODEV, MS_NODEV, 0)) { |
198 | die("MS_NODEV malfunctions\n"); | 324 | die("MS_NODEV malfunctions\n"); |
199 | } | 325 | } |
200 | if (!test_unpriv_remount_simple(MS_NOSUID|MS_NODEV)) { | 326 | if (!test_unpriv_remount_simple(MS_NOSUID)) { |
201 | die("MS_NOSUID malfunctions\n"); | 327 | die("MS_NOSUID malfunctions\n"); |
202 | } | 328 | } |
203 | if (!test_unpriv_remount_simple(MS_NOEXEC|MS_NODEV)) { | 329 | if (!test_unpriv_remount_simple(MS_NOEXEC)) { |
204 | die("MS_NOEXEC malfunctions\n"); | 330 | die("MS_NOEXEC malfunctions\n"); |
205 | } | 331 | } |
206 | if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODEV, | 332 | if (!test_unpriv_remount_atime(MS_RELATIME, |
207 | MS_NOATIME|MS_NODEV)) | 333 | MS_NOATIME)) |
208 | { | 334 | { |
209 | die("MS_RELATIME malfunctions\n"); | 335 | die("MS_RELATIME malfunctions\n"); |
210 | } | 336 | } |
211 | if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODEV, | 337 | if (!test_unpriv_remount_atime(MS_STRICTATIME, |
212 | MS_NOATIME|MS_NODEV)) | 338 | MS_NOATIME)) |
213 | { | 339 | { |
214 | die("MS_STRICTATIME malfunctions\n"); | 340 | die("MS_STRICTATIME malfunctions\n"); |
215 | } | 341 | } |
216 | if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODEV, | 342 | if (!test_unpriv_remount_atime(MS_NOATIME, |
217 | MS_STRICTATIME|MS_NODEV)) | 343 | MS_STRICTATIME)) |
218 | { | 344 | { |
219 | die("MS_RELATIME malfunctions\n"); | 345 | die("MS_NOATIME malfunctions\n"); |
220 | } | 346 | } |
221 | if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME|MS_NODEV, | 347 | if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME, |
222 | MS_NOATIME|MS_NODEV)) | 348 | MS_NOATIME)) |
223 | { | 349 | { |
224 | die("MS_RELATIME malfunctions\n"); | 350 | die("MS_RELATIME|MS_NODIRATIME malfunctions\n"); |
225 | } | 351 | } |
226 | if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME|MS_NODEV, | 352 | if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME, |
227 | MS_NOATIME|MS_NODEV)) | 353 | MS_NOATIME)) |
228 | { | 354 | { |
229 | die("MS_RELATIME malfunctions\n"); | 355 | die("MS_STRICTATIME|MS_NODIRATIME malfunctions\n"); |
230 | } | 356 | } |
231 | if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME|MS_NODEV, | 357 | if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME, |
232 | MS_STRICTATIME|MS_NODEV)) | 358 | MS_STRICTATIME)) |
233 | { | 359 | { |
234 | die("MS_RELATIME malfunctions\n"); | 360 | die("MS_NOATIME|MS_DIRATIME malfunctions\n"); |
235 | } | 361 | } |
236 | if (!test_unpriv_remount(MS_STRICTATIME|MS_NODEV, MS_NODEV, | 362 | if (!test_unpriv_remount("ramfs", NULL, MS_STRICTATIME, 0, MS_NOATIME)) |
237 | MS_NOATIME|MS_NODEV)) | ||
238 | { | 363 | { |
239 | die("Default atime malfunctions\n"); | 364 | die("Default atime malfunctions\n"); |
240 | } | 365 | } |
366 | if (!test_priv_mount_unpriv_remount()) { | ||
367 | die("Mount flags unexpectedly changed after remount\n"); | ||
368 | } | ||
241 | return EXIT_SUCCESS; | 369 | return EXIT_SUCCESS; |
242 | } | 370 | } |
diff --git a/tools/testing/selftests/mqueue/mq_perf_tests.c b/tools/testing/selftests/mqueue/mq_perf_tests.c index 94dae65eea41..8519e9ee97e3 100644 --- a/tools/testing/selftests/mqueue/mq_perf_tests.c +++ b/tools/testing/selftests/mqueue/mq_perf_tests.c | |||
@@ -536,10 +536,9 @@ int main(int argc, char *argv[]) | |||
536 | { | 536 | { |
537 | struct mq_attr attr; | 537 | struct mq_attr attr; |
538 | char *option, *next_option; | 538 | char *option, *next_option; |
539 | int i, cpu; | 539 | int i, cpu, rc; |
540 | struct sigaction sa; | 540 | struct sigaction sa; |
541 | poptContext popt_context; | 541 | poptContext popt_context; |
542 | char rc; | ||
543 | void *retval; | 542 | void *retval; |
544 | 543 | ||
545 | main_thread = pthread_self(); | 544 | main_thread = pthread_self(); |
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index c7493b8f9b0e..62f22cc9941c 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile | |||
@@ -14,12 +14,6 @@ all: $(NET_PROGS) | |||
14 | run_tests: all | 14 | run_tests: all |
15 | @/bin/sh ./run_netsocktests || echo "sockettests: [FAIL]" | 15 | @/bin/sh ./run_netsocktests || echo "sockettests: [FAIL]" |
16 | @/bin/sh ./run_afpackettests || echo "afpackettests: [FAIL]" | 16 | @/bin/sh ./run_afpackettests || echo "afpackettests: [FAIL]" |
17 | @if /sbin/modprobe test_bpf ; then \ | 17 | ./test_bpf.sh |
18 | /sbin/rmmod test_bpf; \ | ||
19 | echo "test_bpf: ok"; \ | ||
20 | else \ | ||
21 | echo "test_bpf: [FAIL]"; \ | ||
22 | exit 1; \ | ||
23 | fi | ||
24 | clean: | 18 | clean: |
25 | $(RM) $(NET_PROGS) | 19 | $(RM) $(NET_PROGS) |
diff --git a/tools/testing/selftests/net/test_bpf.sh b/tools/testing/selftests/net/test_bpf.sh new file mode 100755 index 000000000000..8b29796d46aa --- /dev/null +++ b/tools/testing/selftests/net/test_bpf.sh | |||
@@ -0,0 +1,10 @@ | |||
1 | #!/bin/sh | ||
2 | # Runs bpf test using test_bpf kernel module | ||
3 | |||
4 | if /sbin/modprobe -q test_bpf ; then | ||
5 | /sbin/modprobe -q -r test_bpf; | ||
6 | echo "test_bpf: ok"; | ||
7 | else | ||
8 | echo "test_bpf: [FAIL]"; | ||
9 | exit 1; | ||
10 | fi | ||
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh index f6b2b4771b78..8ca9f21f2efc 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh | |||
@@ -45,7 +45,7 @@ trap 'rm -rf $T' 0 | |||
45 | touch $T | 45 | touch $T |
46 | 46 | ||
47 | . $KVM/bin/functions.sh | 47 | . $KVM/bin/functions.sh |
48 | . $KVPATH/ver_functions.sh | 48 | . $CONFIGFRAG/ver_functions.sh |
49 | 49 | ||
50 | config_template=${1} | 50 | config_template=${1} |
51 | config_dir=`echo $config_template | sed -e 's,/[^/]*$,,'` | 51 | config_dir=`echo $config_template | sed -e 's,/[^/]*$,,'` |
@@ -168,8 +168,8 @@ then | |||
168 | touch $resdir/buildonly | 168 | touch $resdir/buildonly |
169 | exit 0 | 169 | exit 0 |
170 | fi | 170 | fi |
171 | echo $QEMU $qemu_args -m 512 -kernel $builddir/$BOOT_IMAGE -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd | 171 | echo $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd |
172 | ( $QEMU $qemu_args -m 512 -kernel $builddir/$BOOT_IMAGE -append "$qemu_append $boot_args"; echo $? > $resdir/qemu-retval ) & | 172 | ( $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append "$qemu_append $boot_args"; echo $? > $resdir/qemu-retval ) & |
173 | qemu_pid=$! | 173 | qemu_pid=$! |
174 | commandcompleted=0 | 174 | commandcompleted=0 |
175 | echo Monitoring qemu job at pid $qemu_pid | 175 | echo Monitoring qemu job at pid $qemu_pid |
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh index e527dc952eb0..368d64ac779e 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm.sh | |||
@@ -47,7 +47,6 @@ resdir="" | |||
47 | configs="" | 47 | configs="" |
48 | cpus=0 | 48 | cpus=0 |
49 | ds=`date +%Y.%m.%d-%H:%M:%S` | 49 | ds=`date +%Y.%m.%d-%H:%M:%S` |
50 | kversion="" | ||
51 | 50 | ||
52 | . functions.sh | 51 | . functions.sh |
53 | 52 | ||
@@ -64,7 +63,6 @@ usage () { | |||
64 | echo " --duration minutes" | 63 | echo " --duration minutes" |
65 | echo " --interactive" | 64 | echo " --interactive" |
66 | echo " --kmake-arg kernel-make-arguments" | 65 | echo " --kmake-arg kernel-make-arguments" |
67 | echo " --kversion vN.NN" | ||
68 | echo " --mac nn:nn:nn:nn:nn:nn" | 66 | echo " --mac nn:nn:nn:nn:nn:nn" |
69 | echo " --no-initrd" | 67 | echo " --no-initrd" |
70 | echo " --qemu-args qemu-system-..." | 68 | echo " --qemu-args qemu-system-..." |
@@ -128,11 +126,6 @@ do | |||
128 | TORTURE_KMAKE_ARG="$2" | 126 | TORTURE_KMAKE_ARG="$2" |
129 | shift | 127 | shift |
130 | ;; | 128 | ;; |
131 | --kversion) | ||
132 | checkarg --kversion "(kernel version)" $# "$2" '^v[0-9.]*$' '^error' | ||
133 | kversion=$2 | ||
134 | shift | ||
135 | ;; | ||
136 | --mac) | 129 | --mac) |
137 | checkarg --mac "(MAC address)" $# "$2" '^\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}$' error | 130 | checkarg --mac "(MAC address)" $# "$2" '^\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}$' error |
138 | TORTURE_QEMU_MAC=$2 | 131 | TORTURE_QEMU_MAC=$2 |
@@ -170,11 +163,10 @@ do | |||
170 | done | 163 | done |
171 | 164 | ||
172 | CONFIGFRAG=${KVM}/configs/${TORTURE_SUITE}; export CONFIGFRAG | 165 | CONFIGFRAG=${KVM}/configs/${TORTURE_SUITE}; export CONFIGFRAG |
173 | KVPATH=${CONFIGFRAG}/$kversion; export KVPATH | ||
174 | 166 | ||
175 | if test -z "$configs" | 167 | if test -z "$configs" |
176 | then | 168 | then |
177 | configs="`cat $CONFIGFRAG/$kversion/CFLIST`" | 169 | configs="`cat $CONFIGFRAG/CFLIST`" |
178 | fi | 170 | fi |
179 | 171 | ||
180 | if test -z "$resdir" | 172 | if test -z "$resdir" |
@@ -186,10 +178,10 @@ fi | |||
186 | touch $T/cfgcpu | 178 | touch $T/cfgcpu |
187 | for CF in $configs | 179 | for CF in $configs |
188 | do | 180 | do |
189 | if test -f "$CONFIGFRAG/$kversion/$CF" | 181 | if test -f "$CONFIGFRAG/$CF" |
190 | then | 182 | then |
191 | cpu_count=`configNR_CPUS.sh $CONFIGFRAG/$kversion/$CF` | 183 | cpu_count=`configNR_CPUS.sh $CONFIGFRAG/$CF` |
192 | cpu_count=`configfrag_boot_cpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$kversion/$CF" "$cpu_count"` | 184 | cpu_count=`configfrag_boot_cpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$CF" "$cpu_count"` |
193 | echo $CF $cpu_count >> $T/cfgcpu | 185 | echo $CF $cpu_count >> $T/cfgcpu |
194 | else | 186 | else |
195 | echo "The --configs file $CF does not exist, terminating." | 187 | echo "The --configs file $CF does not exist, terminating." |
@@ -252,7 +244,6 @@ END { | |||
252 | cat << ___EOF___ > $T/script | 244 | cat << ___EOF___ > $T/script |
253 | CONFIGFRAG="$CONFIGFRAG"; export CONFIGFRAG | 245 | CONFIGFRAG="$CONFIGFRAG"; export CONFIGFRAG |
254 | KVM="$KVM"; export KVM | 246 | KVM="$KVM"; export KVM |
255 | KVPATH="$KVPATH"; export KVPATH | ||
256 | PATH="$PATH"; export PATH | 247 | PATH="$PATH"; export PATH |
257 | TORTURE_BOOT_IMAGE="$TORTURE_BOOT_IMAGE"; export TORTURE_BOOT_IMAGE | 248 | TORTURE_BOOT_IMAGE="$TORTURE_BOOT_IMAGE"; export TORTURE_BOOT_IMAGE |
258 | TORTURE_BUILDONLY="$TORTURE_BUILDONLY"; export TORTURE_BUILDONLY | 249 | TORTURE_BUILDONLY="$TORTURE_BUILDONLY"; export TORTURE_BUILDONLY |
@@ -285,7 +276,7 @@ then | |||
285 | fi | 276 | fi |
286 | ___EOF___ | 277 | ___EOF___ |
287 | awk < $T/cfgcpu.pack \ | 278 | awk < $T/cfgcpu.pack \ |
288 | -v CONFIGDIR="$CONFIGFRAG/$kversion/" \ | 279 | -v CONFIGDIR="$CONFIGFRAG/" \ |
289 | -v KVM="$KVM" \ | 280 | -v KVM="$KVM" \ |
290 | -v ncpus=$cpus \ | 281 | -v ncpus=$cpus \ |
291 | -v rd=$resdir/$ds/ \ | 282 | -v rd=$resdir/$ds/ \ |
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TINY02 b/tools/testing/selftests/rcutorture/configs/rcu/TINY02 index f4feaee40776..36e41df3d27a 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TINY02 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY02 | |||
@@ -7,6 +7,8 @@ CONFIG_HZ_PERIODIC=y | |||
7 | CONFIG_NO_HZ_IDLE=n | 7 | CONFIG_NO_HZ_IDLE=n |
8 | CONFIG_NO_HZ_FULL=n | 8 | CONFIG_NO_HZ_FULL=n |
9 | CONFIG_RCU_TRACE=y | 9 | CONFIG_RCU_TRACE=y |
10 | CONFIG_PROVE_LOCKING=y | ||
11 | CONFIG_PROVE_RCU=y | ||
10 | CONFIG_DEBUG_LOCK_ALLOC=y | 12 | CONFIG_DEBUG_LOCK_ALLOC=y |
11 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | 13 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n |
12 | CONFIG_PREEMPT_COUNT=y | 14 | CONFIG_PREEMPT_COUNT=y |
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TINY02.boot b/tools/testing/selftests/rcutorture/configs/rcu/TINY02.boot new file mode 100644 index 000000000000..0f0802730014 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY02.boot | |||
@@ -0,0 +1,2 @@ | |||
1 | rcupdate.rcu_self_test=1 | ||
2 | rcupdate.rcu_self_test_bh=1 | ||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01 b/tools/testing/selftests/rcutorture/configs/rcu/TREE01 index 38e3895759dd..f8a10a7500c6 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE01 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01 | |||
@@ -2,7 +2,7 @@ CONFIG_SMP=y | |||
2 | CONFIG_PREEMPT_NONE=n | 2 | CONFIG_PREEMPT_NONE=n |
3 | CONFIG_PREEMPT_VOLUNTARY=n | 3 | CONFIG_PREEMPT_VOLUNTARY=n |
4 | CONFIG_PREEMPT=y | 4 | CONFIG_PREEMPT=y |
5 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | 5 | #CHECK#CONFIG_PREEMPT_RCU=y |
6 | CONFIG_HZ_PERIODIC=n | 6 | CONFIG_HZ_PERIODIC=n |
7 | CONFIG_NO_HZ_IDLE=y | 7 | CONFIG_NO_HZ_IDLE=y |
8 | CONFIG_NO_HZ_FULL=n | 8 | CONFIG_NO_HZ_FULL=n |
@@ -14,6 +14,5 @@ CONFIG_RCU_NOCB_CPU=y | |||
14 | CONFIG_RCU_NOCB_CPU_ZERO=y | 14 | CONFIG_RCU_NOCB_CPU_ZERO=y |
15 | CONFIG_DEBUG_LOCK_ALLOC=n | 15 | CONFIG_DEBUG_LOCK_ALLOC=n |
16 | CONFIG_RCU_CPU_STALL_INFO=n | 16 | CONFIG_RCU_CPU_STALL_INFO=n |
17 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
18 | CONFIG_RCU_BOOST=n | 17 | CONFIG_RCU_BOOST=n |
19 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | 18 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n |
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE02 b/tools/testing/selftests/rcutorture/configs/rcu/TREE02 index ea119ba2f7d4..629122fb8b4a 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE02 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE02 | |||
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=8 | |||
3 | CONFIG_PREEMPT_NONE=n | 3 | CONFIG_PREEMPT_NONE=n |
4 | CONFIG_PREEMPT_VOLUNTARY=n | 4 | CONFIG_PREEMPT_VOLUNTARY=n |
5 | CONFIG_PREEMPT=y | 5 | CONFIG_PREEMPT=y |
6 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | 6 | #CHECK#CONFIG_PREEMPT_RCU=y |
7 | CONFIG_HZ_PERIODIC=n | 7 | CONFIG_HZ_PERIODIC=n |
8 | CONFIG_NO_HZ_IDLE=y | 8 | CONFIG_NO_HZ_IDLE=y |
9 | CONFIG_NO_HZ_FULL=n | 9 | CONFIG_NO_HZ_FULL=n |
@@ -19,6 +19,5 @@ CONFIG_RCU_NOCB_CPU=n | |||
19 | CONFIG_DEBUG_LOCK_ALLOC=y | 19 | CONFIG_DEBUG_LOCK_ALLOC=y |
20 | CONFIG_PROVE_LOCKING=n | 20 | CONFIG_PROVE_LOCKING=n |
21 | CONFIG_RCU_CPU_STALL_INFO=n | 21 | CONFIG_RCU_CPU_STALL_INFO=n |
22 | CONFIG_RCU_CPU_STALL_VERBOSE=y | ||
23 | CONFIG_RCU_BOOST=n | 22 | CONFIG_RCU_BOOST=n |
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | 23 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n |
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE02-T b/tools/testing/selftests/rcutorture/configs/rcu/TREE02-T index 19cf9485f48a..a25de47888a4 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE02-T +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE02-T | |||
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=8 | |||
3 | CONFIG_PREEMPT_NONE=n | 3 | CONFIG_PREEMPT_NONE=n |
4 | CONFIG_PREEMPT_VOLUNTARY=n | 4 | CONFIG_PREEMPT_VOLUNTARY=n |
5 | CONFIG_PREEMPT=y | 5 | CONFIG_PREEMPT=y |
6 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | 6 | #CHECK#CONFIG_PREEMPT_RCU=y |
7 | CONFIG_HZ_PERIODIC=n | 7 | CONFIG_HZ_PERIODIC=n |
8 | CONFIG_NO_HZ_IDLE=y | 8 | CONFIG_NO_HZ_IDLE=y |
9 | CONFIG_NO_HZ_FULL=n | 9 | CONFIG_NO_HZ_FULL=n |
@@ -19,6 +19,5 @@ CONFIG_RCU_NOCB_CPU=n | |||
19 | CONFIG_DEBUG_LOCK_ALLOC=y | 19 | CONFIG_DEBUG_LOCK_ALLOC=y |
20 | CONFIG_PROVE_LOCKING=n | 20 | CONFIG_PROVE_LOCKING=n |
21 | CONFIG_RCU_CPU_STALL_INFO=n | 21 | CONFIG_RCU_CPU_STALL_INFO=n |
22 | CONFIG_RCU_CPU_STALL_VERBOSE=y | ||
23 | CONFIG_RCU_BOOST=n | 22 | CONFIG_RCU_BOOST=n |
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | 23 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n |
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE03 b/tools/testing/selftests/rcutorture/configs/rcu/TREE03 index f4567fb3e332..53f24e0a0ab6 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE03 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE03 | |||
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=8 | |||
3 | CONFIG_PREEMPT_NONE=n | 3 | CONFIG_PREEMPT_NONE=n |
4 | CONFIG_PREEMPT_VOLUNTARY=n | 4 | CONFIG_PREEMPT_VOLUNTARY=n |
5 | CONFIG_PREEMPT=y | 5 | CONFIG_PREEMPT=y |
6 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | 6 | #CHECK#CONFIG_PREEMPT_RCU=y |
7 | CONFIG_HZ_PERIODIC=y | 7 | CONFIG_HZ_PERIODIC=y |
8 | CONFIG_NO_HZ_IDLE=n | 8 | CONFIG_NO_HZ_IDLE=n |
9 | CONFIG_NO_HZ_FULL=n | 9 | CONFIG_NO_HZ_FULL=n |
@@ -15,7 +15,6 @@ CONFIG_RCU_FANOUT_EXACT=n | |||
15 | CONFIG_RCU_NOCB_CPU=n | 15 | CONFIG_RCU_NOCB_CPU=n |
16 | CONFIG_DEBUG_LOCK_ALLOC=n | 16 | CONFIG_DEBUG_LOCK_ALLOC=n |
17 | CONFIG_RCU_CPU_STALL_INFO=n | 17 | CONFIG_RCU_CPU_STALL_INFO=n |
18 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
19 | CONFIG_RCU_BOOST=y | 18 | CONFIG_RCU_BOOST=y |
20 | CONFIG_RCU_BOOST_PRIO=2 | 19 | CONFIG_RCU_KTHREAD_PRIO=2 |
21 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | 20 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n |
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 b/tools/testing/selftests/rcutorture/configs/rcu/TREE04 index 0a262fbb0c12..0f84db35b36d 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04 | |||
@@ -19,5 +19,4 @@ CONFIG_RCU_FANOUT_EXACT=n | |||
19 | CONFIG_RCU_NOCB_CPU=n | 19 | CONFIG_RCU_NOCB_CPU=n |
20 | CONFIG_DEBUG_LOCK_ALLOC=n | 20 | CONFIG_DEBUG_LOCK_ALLOC=n |
21 | CONFIG_RCU_CPU_STALL_INFO=y | 21 | CONFIG_RCU_CPU_STALL_INFO=y |
22 | CONFIG_RCU_CPU_STALL_VERBOSE=y | ||
23 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | 22 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n |
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE05 b/tools/testing/selftests/rcutorture/configs/rcu/TREE05 index 3a06b97e9a73..212e3bfd2b2a 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE05 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE05 | |||
@@ -19,5 +19,4 @@ CONFIG_DEBUG_LOCK_ALLOC=y | |||
19 | CONFIG_PROVE_LOCKING=y | 19 | CONFIG_PROVE_LOCKING=y |
20 | CONFIG_PROVE_RCU=y | 20 | CONFIG_PROVE_RCU=y |
21 | CONFIG_RCU_CPU_STALL_INFO=n | 21 | CONFIG_RCU_CPU_STALL_INFO=n |
22 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
23 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | 22 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n |
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot index 3b42b8b033cd..15b3e1a86f74 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot | |||
@@ -1 +1,2 @@ | |||
1 | rcutorture.torture_type=sched | 1 | rcutorture.torture_type=sched |
2 | rcupdate.rcu_self_test_sched=1 | ||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE06 b/tools/testing/selftests/rcutorture/configs/rcu/TREE06 index 8f084cca91bf..7eee63b44218 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE06 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE06 | |||
@@ -20,5 +20,4 @@ CONFIG_DEBUG_LOCK_ALLOC=y | |||
20 | CONFIG_PROVE_LOCKING=y | 20 | CONFIG_PROVE_LOCKING=y |
21 | CONFIG_PROVE_RCU=y | 21 | CONFIG_PROVE_RCU=y |
22 | CONFIG_RCU_CPU_STALL_INFO=n | 22 | CONFIG_RCU_CPU_STALL_INFO=n |
23 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | 23 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y |
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot new file mode 100644 index 000000000000..da9a03a398db --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot | |||
@@ -0,0 +1,3 @@ | |||
1 | rcupdate.rcu_self_test=1 | ||
2 | rcupdate.rcu_self_test_bh=1 | ||
3 | rcupdate.rcu_self_test_sched=1 | ||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE07 b/tools/testing/selftests/rcutorture/configs/rcu/TREE07 index 8f1017666aa7..92a97fa97dec 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE07 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE07 | |||
@@ -19,5 +19,4 @@ CONFIG_RCU_FANOUT_EXACT=n | |||
19 | CONFIG_RCU_NOCB_CPU=n | 19 | CONFIG_RCU_NOCB_CPU=n |
20 | CONFIG_DEBUG_LOCK_ALLOC=n | 20 | CONFIG_DEBUG_LOCK_ALLOC=n |
21 | CONFIG_RCU_CPU_STALL_INFO=y | 21 | CONFIG_RCU_CPU_STALL_INFO=y |
22 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
23 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | 22 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n |
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08 b/tools/testing/selftests/rcutorture/configs/rcu/TREE08 index 69a2e255bf98..5812027d6f9f 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE08 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08 | |||
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=16 | |||
3 | CONFIG_PREEMPT_NONE=n | 3 | CONFIG_PREEMPT_NONE=n |
4 | CONFIG_PREEMPT_VOLUNTARY=n | 4 | CONFIG_PREEMPT_VOLUNTARY=n |
5 | CONFIG_PREEMPT=y | 5 | CONFIG_PREEMPT=y |
6 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | 6 | #CHECK#CONFIG_PREEMPT_RCU=y |
7 | CONFIG_HZ_PERIODIC=n | 7 | CONFIG_HZ_PERIODIC=n |
8 | CONFIG_NO_HZ_IDLE=y | 8 | CONFIG_NO_HZ_IDLE=y |
9 | CONFIG_NO_HZ_FULL=n | 9 | CONFIG_NO_HZ_FULL=n |
@@ -18,7 +18,8 @@ CONFIG_RCU_FANOUT_LEAF=2 | |||
18 | CONFIG_RCU_NOCB_CPU=y | 18 | CONFIG_RCU_NOCB_CPU=y |
19 | CONFIG_RCU_NOCB_CPU_ALL=y | 19 | CONFIG_RCU_NOCB_CPU_ALL=y |
20 | CONFIG_DEBUG_LOCK_ALLOC=n | 20 | CONFIG_DEBUG_LOCK_ALLOC=n |
21 | CONFIG_PROVE_LOCKING=y | ||
22 | CONFIG_PROVE_RCU=y | ||
21 | CONFIG_RCU_CPU_STALL_INFO=n | 23 | CONFIG_RCU_CPU_STALL_INFO=n |
22 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
23 | CONFIG_RCU_BOOST=n | 24 | CONFIG_RCU_BOOST=n |
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | 25 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n |
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T b/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T index a0f32fb8f17e..3eaeccacb083 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T | |||
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=16 | |||
3 | CONFIG_PREEMPT_NONE=n | 3 | CONFIG_PREEMPT_NONE=n |
4 | CONFIG_PREEMPT_VOLUNTARY=n | 4 | CONFIG_PREEMPT_VOLUNTARY=n |
5 | CONFIG_PREEMPT=y | 5 | CONFIG_PREEMPT=y |
6 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | 6 | #CHECK#CONFIG_PREEMPT_RCU=y |
7 | CONFIG_HZ_PERIODIC=n | 7 | CONFIG_HZ_PERIODIC=n |
8 | CONFIG_NO_HZ_IDLE=y | 8 | CONFIG_NO_HZ_IDLE=y |
9 | CONFIG_NO_HZ_FULL=n | 9 | CONFIG_NO_HZ_FULL=n |
@@ -19,6 +19,5 @@ CONFIG_RCU_NOCB_CPU=y | |||
19 | CONFIG_RCU_NOCB_CPU_ALL=y | 19 | CONFIG_RCU_NOCB_CPU_ALL=y |
20 | CONFIG_DEBUG_LOCK_ALLOC=n | 20 | CONFIG_DEBUG_LOCK_ALLOC=n |
21 | CONFIG_RCU_CPU_STALL_INFO=n | 21 | CONFIG_RCU_CPU_STALL_INFO=n |
22 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
23 | CONFIG_RCU_BOOST=n | 22 | CONFIG_RCU_BOOST=n |
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | 23 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n |
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot index 3b42b8b033cd..2561daf605ad 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot | |||
@@ -1 +1,3 @@ | |||
1 | rcutorture.torture_type=sched | 1 | rcutorture.torture_type=sched |
2 | rcupdate.rcu_self_test=1 | ||
3 | rcupdate.rcu_self_test_sched=1 | ||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE09 b/tools/testing/selftests/rcutorture/configs/rcu/TREE09 index b7a62a540ad1..6076b36f6c0b 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE09 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE09 | |||
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=1 | |||
3 | CONFIG_PREEMPT_NONE=n | 3 | CONFIG_PREEMPT_NONE=n |
4 | CONFIG_PREEMPT_VOLUNTARY=n | 4 | CONFIG_PREEMPT_VOLUNTARY=n |
5 | CONFIG_PREEMPT=y | 5 | CONFIG_PREEMPT=y |
6 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | 6 | #CHECK#CONFIG_PREEMPT_RCU=y |
7 | CONFIG_HZ_PERIODIC=n | 7 | CONFIG_HZ_PERIODIC=n |
8 | CONFIG_NO_HZ_IDLE=y | 8 | CONFIG_NO_HZ_IDLE=y |
9 | CONFIG_NO_HZ_FULL=n | 9 | CONFIG_NO_HZ_FULL=n |
@@ -14,6 +14,5 @@ CONFIG_HIBERNATION=n | |||
14 | CONFIG_RCU_NOCB_CPU=n | 14 | CONFIG_RCU_NOCB_CPU=n |
15 | CONFIG_DEBUG_LOCK_ALLOC=n | 15 | CONFIG_DEBUG_LOCK_ALLOC=n |
16 | CONFIG_RCU_CPU_STALL_INFO=n | 16 | CONFIG_RCU_CPU_STALL_INFO=n |
17 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
18 | CONFIG_RCU_BOOST=n | 17 | CONFIG_RCU_BOOST=n |
19 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | 18 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n |
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST deleted file mode 100644 index 18223947bbcb..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | P1-S-T-NH-SD-SMP-HP | ||
2 | P2-2-t-nh-sd-SMP-hp | ||
3 | P3-3-T-nh-SD-SMP-hp | ||
4 | P4-A-t-NH-sd-SMP-HP | ||
5 | P5-U-T-NH-sd-SMP-hp | ||
6 | N1-S-T-NH-SD-SMP-HP | ||
7 | N2-2-t-nh-sd-SMP-hp | ||
8 | N3-3-T-nh-SD-SMP-hp | ||
9 | N4-A-t-NH-sd-SMP-HP | ||
10 | N5-U-T-NH-sd-SMP-hp | ||
11 | PT1-nh | ||
12 | PT2-NH | ||
13 | NT1-nh | ||
14 | NT3-NH | ||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP deleted file mode 100644 index d3ef873eb6e7..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=8 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=y | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=n | ||
11 | #CHECK#CONFIG_TREE_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
15 | CONFIG_IKCONFIG=y | ||
16 | CONFIG_IKCONFIG_PROC=y | ||
17 | CONFIG_PRINTK_TIME=y | ||
18 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp deleted file mode 100644 index 02e418572b1b..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp deleted file mode 100644 index b3100f69c8cf..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP deleted file mode 100644 index c56b44530725..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=y | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=n | ||
11 | #CHECK#CONFIG_TREE_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
15 | CONFIG_IKCONFIG=y | ||
16 | CONFIG_IKCONFIG_PROC=y | ||
17 | CONFIG_PRINTK_TIME=y | ||
18 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp deleted file mode 100644 index 90d924fea9e9..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_DEBUG_KERNEL=y | ||
3 | CONFIG_RCU_CPU_STALL_INFO=y | ||
4 | CONFIG_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=6 | ||
7 | CONFIG_NR_CPUS=8 | ||
8 | CONFIG_RCU_FANOUT_EXACT=y | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | CONFIG_SUSPEND=n | ||
11 | CONFIG_HIBERNATION=n | ||
12 | CONFIG_PREEMPT_NONE=y | ||
13 | CONFIG_PREEMPT_VOLUNTARY=n | ||
14 | CONFIG_PREEMPT=n | ||
15 | #CHECK#CONFIG_TREE_RCU=y | ||
16 | CONFIG_RCU_TORTURE_TEST=m | ||
17 | CONFIG_MODULE_UNLOAD=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh deleted file mode 100644 index 023f312a931c..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TRACE=y | ||
3 | CONFIG_RCU_TORTURE_TEST=m | ||
4 | CONFIG_MODULE_UNLOAD=y | ||
5 | CONFIG_SUSPEND=n | ||
6 | CONFIG_HIBERNATION=n | ||
7 | # | ||
8 | CONFIG_SMP=n | ||
9 | # | ||
10 | CONFIG_HOTPLUG_CPU=n | ||
11 | # | ||
12 | CONFIG_NO_HZ=n | ||
13 | # | ||
14 | CONFIG_PREEMPT_NONE=y | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=n | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH deleted file mode 100644 index 6fd0235dae73..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=y | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=n | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP deleted file mode 100644 index f72402d7c13d..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=8 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=n | ||
8 | CONFIG_HOTPLUG_CPU=y | ||
9 | CONFIG_PREEMPT_NONE=n | ||
10 | CONFIG_PREEMPT_VOLUNTARY=n | ||
11 | CONFIG_PREEMPT=y | ||
12 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
13 | CONFIG_RCU_TORTURE_TEST=m | ||
14 | CONFIG_MODULE_UNLOAD=y | ||
15 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
16 | CONFIG_IKCONFIG=y | ||
17 | CONFIG_IKCONFIG_PROC=y | ||
18 | CONFIG_PRINTK_TIME=y | ||
19 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp deleted file mode 100644 index 0f3b667d2a9f..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp deleted file mode 100644 index b035e141bf2a..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP deleted file mode 100644 index 3ccf6a9447f5..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=n | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=y | ||
11 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_RT_MUTEXES=y | ||
15 | CONFIG_RCU_BOOST=y | ||
16 | CONFIG_RCU_BOOST_PRIO=2 | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp deleted file mode 100644 index a55c00877fe4..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=6 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=y | ||
8 | CONFIG_HOTPLUG_CPU=n | ||
9 | CONFIG_SUSPEND=n | ||
10 | CONFIG_HIBERNATION=n | ||
11 | CONFIG_PREEMPT_NONE=n | ||
12 | CONFIG_PREEMPT_VOLUNTARY=n | ||
13 | CONFIG_PREEMPT=y | ||
14 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
15 | CONFIG_DEBUG_KERNEL=y | ||
16 | CONFIG_DEBUG_OBJECTS=y | ||
17 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
18 | CONFIG_RT_MUTEXES=y | ||
19 | CONFIG_RCU_BOOST=y | ||
20 | CONFIG_RCU_BOOST_PRIO=2 | ||
21 | CONFIG_RCU_TORTURE_TEST=m | ||
22 | CONFIG_MODULE_UNLOAD=y | ||
23 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
24 | CONFIG_IKCONFIG=y | ||
25 | CONFIG_IKCONFIG_PROC=y | ||
26 | CONFIG_PRINTK_TIME=y | ||
27 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh deleted file mode 100644 index e3361c3894a1..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_BOOST=y | ||
3 | CONFIG_RCU_BOOST_PRIO=2 | ||
4 | CONFIG_RCU_TRACE=y | ||
5 | CONFIG_RCU_TORTURE_TEST=m | ||
6 | CONFIG_MODULE_UNLOAD=y | ||
7 | CONFIG_SUSPEND=n | ||
8 | CONFIG_HIBERNATION=n | ||
9 | # | ||
10 | CONFIG_SMP=n | ||
11 | # | ||
12 | CONFIG_HOTPLUG_CPU=n | ||
13 | # | ||
14 | CONFIG_NO_HZ=n | ||
15 | # | ||
16 | CONFIG_PREEMPT_NONE=n | ||
17 | CONFIG_PREEMPT_VOLUNTARY=n | ||
18 | CONFIG_PREEMPT=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH deleted file mode 100644 index 64abfc3b4d94..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=n | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh deleted file mode 100644 index 5ace37a89780..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Kernel-version-dependent shell functions for the rest of the scripts. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify | ||
6 | # it under the terms of the GNU General Public License as published by | ||
7 | # the Free Software Foundation; either version 2 of the License, or | ||
8 | # (at your option) any later version. | ||
9 | # | ||
10 | # This program is distributed in the hope that it will be useful, | ||
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | # GNU General Public License for more details. | ||
14 | # | ||
15 | # You should have received a copy of the GNU General Public License | ||
16 | # along with this program; if not, you can access it online at | ||
17 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
18 | # | ||
19 | # Copyright (C) IBM Corporation, 2013 | ||
20 | # | ||
21 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
22 | |||
23 | # per_version_boot_params bootparam-string config-file seconds | ||
24 | # | ||
25 | # Adds per-version torture-module parameters to kernels supporting them. | ||
26 | # Which old kernels do not. | ||
27 | per_version_boot_params () { | ||
28 | echo rcutorture.stat_interval=15 \ | ||
29 | rcutorture.shutdown_secs=$3 \ | ||
30 | rcutorture.rcutorture_runnable=1 \ | ||
31 | rcutorture.test_no_idle_hz=1 \ | ||
32 | rcutorture.verbose=1 | ||
33 | } | ||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST deleted file mode 100644 index da4cbc668f2a..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | sysidleY.2013.06.19a | ||
2 | sysidleN.2013.06.19a | ||
3 | P1-S-T-NH-SD-SMP-HP | ||
4 | P2-2-t-nh-sd-SMP-hp | ||
5 | P3-3-T-nh-SD-SMP-hp | ||
6 | P4-A-t-NH-sd-SMP-HP | ||
7 | P5-U-T-NH-sd-SMP-hp | ||
8 | P6---t-nh-SD-smp-hp | ||
9 | N1-S-T-NH-SD-SMP-HP | ||
10 | N2-2-t-nh-sd-SMP-hp | ||
11 | N3-3-T-nh-SD-SMP-hp | ||
12 | N4-A-t-NH-sd-SMP-HP | ||
13 | N5-U-T-NH-sd-SMP-hp | ||
14 | PT1-nh | ||
15 | PT2-NH | ||
16 | NT1-nh | ||
17 | NT3-NH | ||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP deleted file mode 100644 index d81e11d280aa..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_FAST_NO_HZ=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=8 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=n | ||
8 | CONFIG_HOTPLUG_CPU=y | ||
9 | CONFIG_PREEMPT_NONE=y | ||
10 | CONFIG_PREEMPT_VOLUNTARY=n | ||
11 | CONFIG_PREEMPT=n | ||
12 | #CHECK#CONFIG_TREE_RCU=y | ||
13 | CONFIG_RCU_TORTURE_TEST=m | ||
14 | CONFIG_MODULE_UNLOAD=y | ||
15 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
16 | CONFIG_IKCONFIG=y | ||
17 | CONFIG_IKCONFIG_PROC=y | ||
18 | CONFIG_PRINTK_TIME=y | ||
19 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp deleted file mode 100644 index 02e418572b1b..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp deleted file mode 100644 index b3100f69c8cf..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP deleted file mode 100644 index c56b44530725..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=y | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=n | ||
11 | #CHECK#CONFIG_TREE_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
15 | CONFIG_IKCONFIG=y | ||
16 | CONFIG_IKCONFIG_PROC=y | ||
17 | CONFIG_PRINTK_TIME=y | ||
18 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp deleted file mode 100644 index 90d924fea9e9..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_DEBUG_KERNEL=y | ||
3 | CONFIG_RCU_CPU_STALL_INFO=y | ||
4 | CONFIG_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=6 | ||
7 | CONFIG_NR_CPUS=8 | ||
8 | CONFIG_RCU_FANOUT_EXACT=y | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | CONFIG_SUSPEND=n | ||
11 | CONFIG_HIBERNATION=n | ||
12 | CONFIG_PREEMPT_NONE=y | ||
13 | CONFIG_PREEMPT_VOLUNTARY=n | ||
14 | CONFIG_PREEMPT=n | ||
15 | #CHECK#CONFIG_TREE_RCU=y | ||
16 | CONFIG_RCU_TORTURE_TEST=m | ||
17 | CONFIG_MODULE_UNLOAD=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp deleted file mode 100644 index 0ccc36d72738..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_NR_CPUS=1 | ||
5 | CONFIG_RCU_FANOUT_EXACT=n | ||
6 | CONFIG_HOTPLUG_CPU=n | ||
7 | CONFIG_SUSPEND=n | ||
8 | CONFIG_HIBERNATION=n | ||
9 | CONFIG_PREEMPT_NONE=y | ||
10 | CONFIG_PREEMPT_VOLUNTARY=n | ||
11 | CONFIG_PREEMPT=n | ||
12 | #CHECK#CONFIG_TREE_RCU=y | ||
13 | CONFIG_RCU_TORTURE_TEST=m | ||
14 | CONFIG_MODULE_UNLOAD=y | ||
15 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
16 | CONFIG_IKCONFIG=y | ||
17 | CONFIG_IKCONFIG_PROC=y | ||
18 | CONFIG_PRINTK_TIME=y | ||
19 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP deleted file mode 100644 index 3f640cf84973..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_DEBUG_KERNEL=y | ||
3 | CONFIG_RCU_CPU_STALL_INFO=y | ||
4 | CONFIG_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=2 | ||
7 | CONFIG_NR_CPUS=16 | ||
8 | CONFIG_RCU_FANOUT_EXACT=n | ||
9 | CONFIG_HOTPLUG_CPU=y | ||
10 | CONFIG_RCU_NOCB_CPU=y | ||
11 | CONFIG_RCU_NOCB_CPU_NONE=y | ||
12 | CONFIG_RCU_NOCB_CPU_ZERO=n | ||
13 | CONFIG_RCU_NOCB_CPU_ALL=n | ||
14 | CONFIG_SUSPEND=n | ||
15 | CONFIG_HIBERNATION=n | ||
16 | CONFIG_PREEMPT_NONE=y | ||
17 | CONFIG_PREEMPT_VOLUNTARY=n | ||
18 | CONFIG_PREEMPT=n | ||
19 | #CHECK#CONFIG_TREE_RCU=y | ||
20 | CONFIG_RCU_TORTURE_TEST=m | ||
21 | CONFIG_MODULE_UNLOAD=y | ||
22 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
23 | CONFIG_IKCONFIG=y | ||
24 | CONFIG_IKCONFIG_PROC=y | ||
25 | CONFIG_PRINTK_TIME=y | ||
26 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP deleted file mode 100644 index 285da2dd8ac3..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_DEBUG_KERNEL=y | ||
3 | CONFIG_RCU_CPU_STALL_INFO=y | ||
4 | CONFIG_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=14 | ||
7 | CONFIG_NR_CPUS=16 | ||
8 | CONFIG_RCU_FANOUT_EXACT=y | ||
9 | CONFIG_HOTPLUG_CPU=y | ||
10 | CONFIG_SUSPEND=n | ||
11 | CONFIG_HIBERNATION=n | ||
12 | CONFIG_PREEMPT_NONE=y | ||
13 | CONFIG_PREEMPT_VOLUNTARY=n | ||
14 | CONFIG_PREEMPT=n | ||
15 | #CHECK#CONFIG_TREE_RCU=y | ||
16 | CONFIG_RCU_TORTURE_TEST=m | ||
17 | CONFIG_MODULE_UNLOAD=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh deleted file mode 100644 index 023f312a931c..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TRACE=y | ||
3 | CONFIG_RCU_TORTURE_TEST=m | ||
4 | CONFIG_MODULE_UNLOAD=y | ||
5 | CONFIG_SUSPEND=n | ||
6 | CONFIG_HIBERNATION=n | ||
7 | # | ||
8 | CONFIG_SMP=n | ||
9 | # | ||
10 | CONFIG_HOTPLUG_CPU=n | ||
11 | # | ||
12 | CONFIG_NO_HZ=n | ||
13 | # | ||
14 | CONFIG_PREEMPT_NONE=y | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=n | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH deleted file mode 100644 index 6fd0235dae73..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=y | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=n | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP deleted file mode 100644 index 9647c44cf4b7..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_RCU_FAST_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=8 | ||
7 | CONFIG_NR_CPUS=8 | ||
8 | CONFIG_RCU_FANOUT_EXACT=n | ||
9 | CONFIG_HOTPLUG_CPU=y | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp deleted file mode 100644 index 0f3b667d2a9f..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp deleted file mode 100644 index b035e141bf2a..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP deleted file mode 100644 index 3ccf6a9447f5..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=n | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=y | ||
11 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_RT_MUTEXES=y | ||
15 | CONFIG_RCU_BOOST=y | ||
16 | CONFIG_RCU_BOOST_PRIO=2 | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp deleted file mode 100644 index a55c00877fe4..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=6 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=y | ||
8 | CONFIG_HOTPLUG_CPU=n | ||
9 | CONFIG_SUSPEND=n | ||
10 | CONFIG_HIBERNATION=n | ||
11 | CONFIG_PREEMPT_NONE=n | ||
12 | CONFIG_PREEMPT_VOLUNTARY=n | ||
13 | CONFIG_PREEMPT=y | ||
14 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
15 | CONFIG_DEBUG_KERNEL=y | ||
16 | CONFIG_DEBUG_OBJECTS=y | ||
17 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
18 | CONFIG_RT_MUTEXES=y | ||
19 | CONFIG_RCU_BOOST=y | ||
20 | CONFIG_RCU_BOOST_PRIO=2 | ||
21 | CONFIG_RCU_TORTURE_TEST=m | ||
22 | CONFIG_MODULE_UNLOAD=y | ||
23 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
24 | CONFIG_IKCONFIG=y | ||
25 | CONFIG_IKCONFIG_PROC=y | ||
26 | CONFIG_PRINTK_TIME=y | ||
27 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp deleted file mode 100644 index f4c9175828bf..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=n | ||
4 | CONFIG_RCU_FANOUT_EXACT=n | ||
5 | CONFIG_HOTPLUG_CPU=n | ||
6 | CONFIG_SUSPEND=n | ||
7 | CONFIG_HIBERNATION=n | ||
8 | CONFIG_PREEMPT_NONE=n | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=y | ||
11 | CONFIG_TREE_PREEMPT_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
15 | CONFIG_IKCONFIG=y | ||
16 | CONFIG_IKCONFIG_PROC=y | ||
17 | CONFIG_PRINTK_TIME=y | ||
18 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP deleted file mode 100644 index 77a8c5b75763..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=16 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_RCU_NOCB_CPU=y | ||
9 | CONFIG_RCU_NOCB_CPU_NONE=n | ||
10 | CONFIG_RCU_NOCB_CPU_ZERO=n | ||
11 | CONFIG_RCU_NOCB_CPU_ALL=y | ||
12 | CONFIG_SUSPEND=n | ||
13 | CONFIG_HIBERNATION=n | ||
14 | CONFIG_PREEMPT_NONE=n | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=y | ||
17 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
18 | CONFIG_RCU_TORTURE_TEST=m | ||
19 | CONFIG_MODULE_UNLOAD=y | ||
20 | CONFIG_PROVE_LOCKING=y | ||
21 | CONFIG_PROVE_RCU=y | ||
22 | CONFIG_DEBUG_KERNEL=y | ||
23 | CONFIG_DEBUG_OBJECTS=y | ||
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
25 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
26 | CONFIG_SLUB=y | ||
27 | CONFIG_IKCONFIG=y | ||
28 | CONFIG_IKCONFIG_PROC=y | ||
29 | CONFIG_PRINTK_TIME=y | ||
30 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all deleted file mode 100644 index 0eecebc6e95f..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=16 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_RCU_NOCB_CPU=y | ||
9 | CONFIG_RCU_NOCB_CPU_NONE=y | ||
10 | CONFIG_RCU_NOCB_CPU_ZERO=n | ||
11 | CONFIG_RCU_NOCB_CPU_ALL=n | ||
12 | CONFIG_SUSPEND=n | ||
13 | CONFIG_HIBERNATION=n | ||
14 | CONFIG_PREEMPT_NONE=n | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=y | ||
17 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
18 | CONFIG_RCU_TORTURE_TEST=m | ||
19 | CONFIG_MODULE_UNLOAD=y | ||
20 | CONFIG_PROVE_LOCKING=y | ||
21 | CONFIG_PROVE_RCU=y | ||
22 | CONFIG_DEBUG_KERNEL=y | ||
23 | CONFIG_DEBUG_OBJECTS=y | ||
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
25 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
26 | CONFIG_SLUB=y | ||
27 | CONFIG_IKCONFIG=y | ||
28 | CONFIG_IKCONFIG_PROC=y | ||
29 | CONFIG_PRINTK_TIME=y | ||
30 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none deleted file mode 100644 index 0eecebc6e95f..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=16 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_RCU_NOCB_CPU=y | ||
9 | CONFIG_RCU_NOCB_CPU_NONE=y | ||
10 | CONFIG_RCU_NOCB_CPU_ZERO=n | ||
11 | CONFIG_RCU_NOCB_CPU_ALL=n | ||
12 | CONFIG_SUSPEND=n | ||
13 | CONFIG_HIBERNATION=n | ||
14 | CONFIG_PREEMPT_NONE=n | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=y | ||
17 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
18 | CONFIG_RCU_TORTURE_TEST=m | ||
19 | CONFIG_MODULE_UNLOAD=y | ||
20 | CONFIG_PROVE_LOCKING=y | ||
21 | CONFIG_PROVE_RCU=y | ||
22 | CONFIG_DEBUG_KERNEL=y | ||
23 | CONFIG_DEBUG_OBJECTS=y | ||
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
25 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
26 | CONFIG_SLUB=y | ||
27 | CONFIG_IKCONFIG=y | ||
28 | CONFIG_IKCONFIG_PROC=y | ||
29 | CONFIG_PRINTK_TIME=y | ||
30 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp deleted file mode 100644 index 588bc70420cd..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=16 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_RCU_NOCB_CPU=y | ||
9 | CONFIG_RCU_NOCB_CPU_NONE=n | ||
10 | CONFIG_RCU_NOCB_CPU_ZERO=y | ||
11 | CONFIG_RCU_NOCB_CPU_ALL=n | ||
12 | CONFIG_SUSPEND=n | ||
13 | CONFIG_HIBERNATION=n | ||
14 | CONFIG_PREEMPT_NONE=n | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=y | ||
17 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
18 | CONFIG_RCU_TORTURE_TEST=m | ||
19 | CONFIG_MODULE_UNLOAD=y | ||
20 | CONFIG_PROVE_LOCKING=y | ||
21 | CONFIG_PROVE_RCU=y | ||
22 | CONFIG_DEBUG_KERNEL=y | ||
23 | CONFIG_DEBUG_OBJECTS=y | ||
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
25 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
26 | CONFIG_SLUB=y | ||
27 | CONFIG_IKCONFIG=y | ||
28 | CONFIG_IKCONFIG_PROC=y | ||
29 | CONFIG_PRINTK_TIME=y | ||
30 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh deleted file mode 100644 index e3361c3894a1..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_BOOST=y | ||
3 | CONFIG_RCU_BOOST_PRIO=2 | ||
4 | CONFIG_RCU_TRACE=y | ||
5 | CONFIG_RCU_TORTURE_TEST=m | ||
6 | CONFIG_MODULE_UNLOAD=y | ||
7 | CONFIG_SUSPEND=n | ||
8 | CONFIG_HIBERNATION=n | ||
9 | # | ||
10 | CONFIG_SMP=n | ||
11 | # | ||
12 | CONFIG_HOTPLUG_CPU=n | ||
13 | # | ||
14 | CONFIG_NO_HZ=n | ||
15 | # | ||
16 | CONFIG_PREEMPT_NONE=n | ||
17 | CONFIG_PREEMPT_VOLUNTARY=n | ||
18 | CONFIG_PREEMPT=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH deleted file mode 100644 index 64abfc3b4d94..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=n | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST deleted file mode 100644 index 18223947bbcb..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | P1-S-T-NH-SD-SMP-HP | ||
2 | P2-2-t-nh-sd-SMP-hp | ||
3 | P3-3-T-nh-SD-SMP-hp | ||
4 | P4-A-t-NH-sd-SMP-HP | ||
5 | P5-U-T-NH-sd-SMP-hp | ||
6 | N1-S-T-NH-SD-SMP-HP | ||
7 | N2-2-t-nh-sd-SMP-hp | ||
8 | N3-3-T-nh-SD-SMP-hp | ||
9 | N4-A-t-NH-sd-SMP-HP | ||
10 | N5-U-T-NH-sd-SMP-hp | ||
11 | PT1-nh | ||
12 | PT2-NH | ||
13 | NT1-nh | ||
14 | NT3-NH | ||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP deleted file mode 100644 index d81e11d280aa..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_FAST_NO_HZ=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=8 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=n | ||
8 | CONFIG_HOTPLUG_CPU=y | ||
9 | CONFIG_PREEMPT_NONE=y | ||
10 | CONFIG_PREEMPT_VOLUNTARY=n | ||
11 | CONFIG_PREEMPT=n | ||
12 | #CHECK#CONFIG_TREE_RCU=y | ||
13 | CONFIG_RCU_TORTURE_TEST=m | ||
14 | CONFIG_MODULE_UNLOAD=y | ||
15 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
16 | CONFIG_IKCONFIG=y | ||
17 | CONFIG_IKCONFIG_PROC=y | ||
18 | CONFIG_PRINTK_TIME=y | ||
19 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp deleted file mode 100644 index 02e418572b1b..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp deleted file mode 100644 index b3100f69c8cf..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP deleted file mode 100644 index c56b44530725..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=y | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=n | ||
11 | #CHECK#CONFIG_TREE_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
15 | CONFIG_IKCONFIG=y | ||
16 | CONFIG_IKCONFIG_PROC=y | ||
17 | CONFIG_PRINTK_TIME=y | ||
18 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp deleted file mode 100644 index 90d924fea9e9..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_DEBUG_KERNEL=y | ||
3 | CONFIG_RCU_CPU_STALL_INFO=y | ||
4 | CONFIG_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=6 | ||
7 | CONFIG_NR_CPUS=8 | ||
8 | CONFIG_RCU_FANOUT_EXACT=y | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | CONFIG_SUSPEND=n | ||
11 | CONFIG_HIBERNATION=n | ||
12 | CONFIG_PREEMPT_NONE=y | ||
13 | CONFIG_PREEMPT_VOLUNTARY=n | ||
14 | CONFIG_PREEMPT=n | ||
15 | #CHECK#CONFIG_TREE_RCU=y | ||
16 | CONFIG_RCU_TORTURE_TEST=m | ||
17 | CONFIG_MODULE_UNLOAD=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh deleted file mode 100644 index 023f312a931c..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TRACE=y | ||
3 | CONFIG_RCU_TORTURE_TEST=m | ||
4 | CONFIG_MODULE_UNLOAD=y | ||
5 | CONFIG_SUSPEND=n | ||
6 | CONFIG_HIBERNATION=n | ||
7 | # | ||
8 | CONFIG_SMP=n | ||
9 | # | ||
10 | CONFIG_HOTPLUG_CPU=n | ||
11 | # | ||
12 | CONFIG_NO_HZ=n | ||
13 | # | ||
14 | CONFIG_PREEMPT_NONE=y | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=n | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH deleted file mode 100644 index 6fd0235dae73..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=y | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=n | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP deleted file mode 100644 index 9647c44cf4b7..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_RCU_FAST_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=8 | ||
7 | CONFIG_NR_CPUS=8 | ||
8 | CONFIG_RCU_FANOUT_EXACT=n | ||
9 | CONFIG_HOTPLUG_CPU=y | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp deleted file mode 100644 index 0f3b667d2a9f..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp deleted file mode 100644 index b035e141bf2a..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP deleted file mode 100644 index 3ccf6a9447f5..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=n | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=y | ||
11 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_RT_MUTEXES=y | ||
15 | CONFIG_RCU_BOOST=y | ||
16 | CONFIG_RCU_BOOST_PRIO=2 | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp deleted file mode 100644 index a55c00877fe4..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=6 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=y | ||
8 | CONFIG_HOTPLUG_CPU=n | ||
9 | CONFIG_SUSPEND=n | ||
10 | CONFIG_HIBERNATION=n | ||
11 | CONFIG_PREEMPT_NONE=n | ||
12 | CONFIG_PREEMPT_VOLUNTARY=n | ||
13 | CONFIG_PREEMPT=y | ||
14 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
15 | CONFIG_DEBUG_KERNEL=y | ||
16 | CONFIG_DEBUG_OBJECTS=y | ||
17 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
18 | CONFIG_RT_MUTEXES=y | ||
19 | CONFIG_RCU_BOOST=y | ||
20 | CONFIG_RCU_BOOST_PRIO=2 | ||
21 | CONFIG_RCU_TORTURE_TEST=m | ||
22 | CONFIG_MODULE_UNLOAD=y | ||
23 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
24 | CONFIG_IKCONFIG=y | ||
25 | CONFIG_IKCONFIG_PROC=y | ||
26 | CONFIG_PRINTK_TIME=y | ||
27 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh deleted file mode 100644 index e3361c3894a1..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_BOOST=y | ||
3 | CONFIG_RCU_BOOST_PRIO=2 | ||
4 | CONFIG_RCU_TRACE=y | ||
5 | CONFIG_RCU_TORTURE_TEST=m | ||
6 | CONFIG_MODULE_UNLOAD=y | ||
7 | CONFIG_SUSPEND=n | ||
8 | CONFIG_HIBERNATION=n | ||
9 | # | ||
10 | CONFIG_SMP=n | ||
11 | # | ||
12 | CONFIG_HOTPLUG_CPU=n | ||
13 | # | ||
14 | CONFIG_NO_HZ=n | ||
15 | # | ||
16 | CONFIG_PREEMPT_NONE=n | ||
17 | CONFIG_PREEMPT_VOLUNTARY=n | ||
18 | CONFIG_PREEMPT=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH deleted file mode 100644 index 64abfc3b4d94..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=n | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh deleted file mode 100644 index bae55692ce6e..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Kernel-version-dependent shell functions for the rest of the scripts. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify | ||
6 | # it under the terms of the GNU General Public License as published by | ||
7 | # the Free Software Foundation; either version 2 of the License, or | ||
8 | # (at your option) any later version. | ||
9 | # | ||
10 | # This program is distributed in the hope that it will be useful, | ||
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | # GNU General Public License for more details. | ||
14 | # | ||
15 | # You should have received a copy of the GNU General Public License | ||
16 | # along with this program; if not, you can access it online at | ||
17 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
18 | # | ||
19 | # Copyright (C) IBM Corporation, 2013 | ||
20 | # | ||
21 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
22 | |||
23 | # rcutorture_param_onoff bootparam-string config-file | ||
24 | # | ||
25 | # Adds onoff rcutorture module parameters to kernels having it. | ||
26 | rcutorture_param_onoff () { | ||
27 | if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" | ||
28 | then | ||
29 | echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2 | ||
30 | echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30 | ||
31 | fi | ||
32 | } | ||
33 | |||
34 | # per_version_boot_params bootparam-string config-file seconds | ||
35 | # | ||
36 | # Adds per-version torture-module parameters to kernels supporting them. | ||
37 | per_version_boot_params () { | ||
38 | echo $1 `rcutorture_param_onoff "$1" "$2"` \ | ||
39 | rcutorture.stat_interval=15 \ | ||
40 | rcutorture.shutdown_secs=$3 \ | ||
41 | rcutorture.rcutorture_runnable=1 \ | ||
42 | rcutorture.test_no_idle_hz=1 \ | ||
43 | rcutorture.verbose=1 | ||
44 | } | ||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST deleted file mode 100644 index 18223947bbcb..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | P1-S-T-NH-SD-SMP-HP | ||
2 | P2-2-t-nh-sd-SMP-hp | ||
3 | P3-3-T-nh-SD-SMP-hp | ||
4 | P4-A-t-NH-sd-SMP-HP | ||
5 | P5-U-T-NH-sd-SMP-hp | ||
6 | N1-S-T-NH-SD-SMP-HP | ||
7 | N2-2-t-nh-sd-SMP-hp | ||
8 | N3-3-T-nh-SD-SMP-hp | ||
9 | N4-A-t-NH-sd-SMP-HP | ||
10 | N5-U-T-NH-sd-SMP-hp | ||
11 | PT1-nh | ||
12 | PT2-NH | ||
13 | NT1-nh | ||
14 | NT3-NH | ||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP deleted file mode 100644 index d81e11d280aa..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_FAST_NO_HZ=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=8 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=n | ||
8 | CONFIG_HOTPLUG_CPU=y | ||
9 | CONFIG_PREEMPT_NONE=y | ||
10 | CONFIG_PREEMPT_VOLUNTARY=n | ||
11 | CONFIG_PREEMPT=n | ||
12 | #CHECK#CONFIG_TREE_RCU=y | ||
13 | CONFIG_RCU_TORTURE_TEST=m | ||
14 | CONFIG_MODULE_UNLOAD=y | ||
15 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
16 | CONFIG_IKCONFIG=y | ||
17 | CONFIG_IKCONFIG_PROC=y | ||
18 | CONFIG_PRINTK_TIME=y | ||
19 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp deleted file mode 100644 index 02e418572b1b..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp deleted file mode 100644 index b3100f69c8cf..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP deleted file mode 100644 index c56b44530725..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=y | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=n | ||
11 | #CHECK#CONFIG_TREE_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
15 | CONFIG_IKCONFIG=y | ||
16 | CONFIG_IKCONFIG_PROC=y | ||
17 | CONFIG_PRINTK_TIME=y | ||
18 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp deleted file mode 100644 index 90d924fea9e9..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_DEBUG_KERNEL=y | ||
3 | CONFIG_RCU_CPU_STALL_INFO=y | ||
4 | CONFIG_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=6 | ||
7 | CONFIG_NR_CPUS=8 | ||
8 | CONFIG_RCU_FANOUT_EXACT=y | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | CONFIG_SUSPEND=n | ||
11 | CONFIG_HIBERNATION=n | ||
12 | CONFIG_PREEMPT_NONE=y | ||
13 | CONFIG_PREEMPT_VOLUNTARY=n | ||
14 | CONFIG_PREEMPT=n | ||
15 | #CHECK#CONFIG_TREE_RCU=y | ||
16 | CONFIG_RCU_TORTURE_TEST=m | ||
17 | CONFIG_MODULE_UNLOAD=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh deleted file mode 100644 index 023f312a931c..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TRACE=y | ||
3 | CONFIG_RCU_TORTURE_TEST=m | ||
4 | CONFIG_MODULE_UNLOAD=y | ||
5 | CONFIG_SUSPEND=n | ||
6 | CONFIG_HIBERNATION=n | ||
7 | # | ||
8 | CONFIG_SMP=n | ||
9 | # | ||
10 | CONFIG_HOTPLUG_CPU=n | ||
11 | # | ||
12 | CONFIG_NO_HZ=n | ||
13 | # | ||
14 | CONFIG_PREEMPT_NONE=y | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=n | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH deleted file mode 100644 index 6fd0235dae73..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=y | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=n | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP deleted file mode 100644 index 9647c44cf4b7..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_RCU_FAST_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=8 | ||
7 | CONFIG_NR_CPUS=8 | ||
8 | CONFIG_RCU_FANOUT_EXACT=n | ||
9 | CONFIG_HOTPLUG_CPU=y | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp deleted file mode 100644 index 0f3b667d2a9f..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp deleted file mode 100644 index b035e141bf2a..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP deleted file mode 100644 index 3ccf6a9447f5..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=n | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=y | ||
11 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_RT_MUTEXES=y | ||
15 | CONFIG_RCU_BOOST=y | ||
16 | CONFIG_RCU_BOOST_PRIO=2 | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp deleted file mode 100644 index a55c00877fe4..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=6 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=y | ||
8 | CONFIG_HOTPLUG_CPU=n | ||
9 | CONFIG_SUSPEND=n | ||
10 | CONFIG_HIBERNATION=n | ||
11 | CONFIG_PREEMPT_NONE=n | ||
12 | CONFIG_PREEMPT_VOLUNTARY=n | ||
13 | CONFIG_PREEMPT=y | ||
14 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
15 | CONFIG_DEBUG_KERNEL=y | ||
16 | CONFIG_DEBUG_OBJECTS=y | ||
17 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
18 | CONFIG_RT_MUTEXES=y | ||
19 | CONFIG_RCU_BOOST=y | ||
20 | CONFIG_RCU_BOOST_PRIO=2 | ||
21 | CONFIG_RCU_TORTURE_TEST=m | ||
22 | CONFIG_MODULE_UNLOAD=y | ||
23 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
24 | CONFIG_IKCONFIG=y | ||
25 | CONFIG_IKCONFIG_PROC=y | ||
26 | CONFIG_PRINTK_TIME=y | ||
27 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh deleted file mode 100644 index e3361c3894a1..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_BOOST=y | ||
3 | CONFIG_RCU_BOOST_PRIO=2 | ||
4 | CONFIG_RCU_TRACE=y | ||
5 | CONFIG_RCU_TORTURE_TEST=m | ||
6 | CONFIG_MODULE_UNLOAD=y | ||
7 | CONFIG_SUSPEND=n | ||
8 | CONFIG_HIBERNATION=n | ||
9 | # | ||
10 | CONFIG_SMP=n | ||
11 | # | ||
12 | CONFIG_HOTPLUG_CPU=n | ||
13 | # | ||
14 | CONFIG_NO_HZ=n | ||
15 | # | ||
16 | CONFIG_PREEMPT_NONE=n | ||
17 | CONFIG_PREEMPT_VOLUNTARY=n | ||
18 | CONFIG_PREEMPT=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH deleted file mode 100644 index 64abfc3b4d94..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=n | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh deleted file mode 100644 index 8977d8d31b19..000000000000 --- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh +++ /dev/null | |||
@@ -1,57 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Kernel-version-dependent shell functions for the rest of the scripts. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify | ||
6 | # it under the terms of the GNU General Public License as published by | ||
7 | # the Free Software Foundation; either version 2 of the License, or | ||
8 | # (at your option) any later version. | ||
9 | # | ||
10 | # This program is distributed in the hope that it will be useful, | ||
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | # GNU General Public License for more details. | ||
14 | # | ||
15 | # You should have received a copy of the GNU General Public License | ||
16 | # along with this program; if not, you can access it online at | ||
17 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
18 | # | ||
19 | # Copyright (C) IBM Corporation, 2013 | ||
20 | # | ||
21 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
22 | |||
23 | # rcutorture_param_n_barrier_cbs bootparam-string | ||
24 | # | ||
25 | # Adds n_barrier_cbs rcutorture module parameter to kernels having it. | ||
26 | rcutorture_param_n_barrier_cbs () { | ||
27 | if echo $1 | grep -q "rcutorture\.n_barrier_cbs" | ||
28 | then | ||
29 | : | ||
30 | else | ||
31 | echo rcutorture.n_barrier_cbs=4 | ||
32 | fi | ||
33 | } | ||
34 | |||
35 | # rcutorture_param_onoff bootparam-string config-file | ||
36 | # | ||
37 | # Adds onoff rcutorture module parameters to kernels having it. | ||
38 | rcutorture_param_onoff () { | ||
39 | if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" | ||
40 | then | ||
41 | echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2 | ||
42 | echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30 | ||
43 | fi | ||
44 | } | ||
45 | |||
46 | # per_version_boot_params bootparam-string config-file seconds | ||
47 | # | ||
48 | # Adds per-version torture-module parameters to kernels supporting them. | ||
49 | per_version_boot_params () { | ||
50 | echo $1 `rcutorture_param_onoff "$1" "$2"` \ | ||
51 | `rcutorture_param_n_barrier_cbs "$1"` \ | ||
52 | rcutorture.stat_interval=15 \ | ||
53 | rcutorture.shutdown_secs=$3 \ | ||
54 | rcutorture.rcutorture_runnable=1 \ | ||
55 | rcutorture.test_no_idle_hz=1 \ | ||
56 | rcutorture.verbose=1 | ||
57 | } | ||
diff --git a/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt b/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt index 28db67b54e55..9ef33a743b73 100644 --- a/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt +++ b/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt | |||
@@ -34,7 +34,7 @@ CONFIG_PREEMPT | |||
34 | CONFIG_PREEMPT_RCU | 34 | CONFIG_PREEMPT_RCU |
35 | CONFIG_SMP | 35 | CONFIG_SMP |
36 | CONFIG_TINY_RCU | 36 | CONFIG_TINY_RCU |
37 | CONFIG_TREE_PREEMPT_RCU | 37 | CONFIG_PREEMPT_RCU |
38 | CONFIG_TREE_RCU | 38 | CONFIG_TREE_RCU |
39 | 39 | ||
40 | All forced by CONFIG_TINY_RCU. | 40 | All forced by CONFIG_TINY_RCU. |
diff --git a/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt index 3e588db86a17..ec03c883db00 100644 --- a/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt +++ b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt | |||
@@ -1,5 +1,5 @@ | |||
1 | This document gives a brief rationale for the TREE_RCU-related test | 1 | This document gives a brief rationale for the TREE_RCU-related test |
2 | cases, a group that includes TREE_PREEMPT_RCU. | 2 | cases, a group that includes PREEMPT_RCU. |
3 | 3 | ||
4 | 4 | ||
5 | Kconfig Parameters: | 5 | Kconfig Parameters: |
@@ -14,10 +14,9 @@ CONFIG_NO_HZ_FULL_SYSIDLE -- Do one. | |||
14 | CONFIG_PREEMPT -- Do half. (First three and #8.) | 14 | CONFIG_PREEMPT -- Do half. (First three and #8.) |
15 | CONFIG_PROVE_LOCKING -- Do all but two, covering CONFIG_PROVE_RCU and not. | 15 | CONFIG_PROVE_LOCKING -- Do all but two, covering CONFIG_PROVE_RCU and not. |
16 | CONFIG_PROVE_RCU -- Do all but one under CONFIG_PROVE_LOCKING. | 16 | CONFIG_PROVE_RCU -- Do all but one under CONFIG_PROVE_LOCKING. |
17 | CONFIG_RCU_BOOST -- one of TREE_PREEMPT_RCU. | 17 | CONFIG_RCU_BOOST -- one of PREEMPT_RCU. |
18 | CONFIG_RCU_BOOST_PRIO -- set to 2 for _BOOST testing. | 18 | CONFIG_RCU_KTHREAD_PRIO -- set to 2 for _BOOST testing. |
19 | CONFIG_RCU_CPU_STALL_INFO -- do one with and without _VERBOSE. | 19 | CONFIG_RCU_CPU_STALL_INFO -- Do one. |
20 | CONFIG_RCU_CPU_STALL_VERBOSE -- do one with and without _INFO. | ||
21 | CONFIG_RCU_FANOUT -- Cover hierarchy as currently, but overlap with others. | 20 | CONFIG_RCU_FANOUT -- Cover hierarchy as currently, but overlap with others. |
22 | CONFIG_RCU_FANOUT_EXACT -- Do one. | 21 | CONFIG_RCU_FANOUT_EXACT -- Do one. |
23 | CONFIG_RCU_FANOUT_LEAF -- Do one non-default. | 22 | CONFIG_RCU_FANOUT_LEAF -- Do one non-default. |
@@ -27,7 +26,7 @@ CONFIG_RCU_NOCB_CPU_ALL -- Do one. | |||
27 | CONFIG_RCU_NOCB_CPU_NONE -- Do one. | 26 | CONFIG_RCU_NOCB_CPU_NONE -- Do one. |
28 | CONFIG_RCU_NOCB_CPU_ZERO -- Do one. | 27 | CONFIG_RCU_NOCB_CPU_ZERO -- Do one. |
29 | CONFIG_RCU_TRACE -- Do half. | 28 | CONFIG_RCU_TRACE -- Do half. |
30 | CONFIG_SMP -- Need one !SMP for TREE_PREEMPT_RCU. | 29 | CONFIG_SMP -- Need one !SMP for PREEMPT_RCU. |
31 | RCU-bh: Do one with PREEMPT and one with !PREEMPT. | 30 | RCU-bh: Do one with PREEMPT and one with !PREEMPT. |
32 | RCU-sched: Do one with PREEMPT but not BOOST. | 31 | RCU-sched: Do one with PREEMPT but not BOOST. |
33 | 32 | ||
@@ -77,7 +76,7 @@ CONFIG_RCU_CPU_STALL_TIMEOUT | |||
77 | 76 | ||
78 | CONFIG_RCU_STALL_COMMON | 77 | CONFIG_RCU_STALL_COMMON |
79 | 78 | ||
80 | Implied by TREE_RCU and TREE_PREEMPT_RCU. | 79 | Implied by TREE_RCU and PREEMPT_RCU. |
81 | 80 | ||
82 | CONFIG_RCU_TORTURE_TEST | 81 | CONFIG_RCU_TORTURE_TEST |
83 | CONFIG_RCU_TORTURE_TEST_RUNNABLE | 82 | CONFIG_RCU_TORTURE_TEST_RUNNABLE |
@@ -88,7 +87,7 @@ CONFIG_RCU_USER_QS | |||
88 | 87 | ||
89 | Redundant with CONFIG_NO_HZ_FULL. | 88 | Redundant with CONFIG_NO_HZ_FULL. |
90 | 89 | ||
91 | CONFIG_TREE_PREEMPT_RCU | 90 | CONFIG_PREEMPT_RCU |
92 | CONFIG_TREE_RCU | 91 | CONFIG_TREE_RCU |
93 | 92 | ||
94 | These are controlled by CONFIG_PREEMPT. | 93 | These are controlled by CONFIG_PREEMPT. |
diff --git a/tools/testing/selftests/size/.gitignore b/tools/testing/selftests/size/.gitignore new file mode 100644 index 000000000000..189b7818de34 --- /dev/null +++ b/tools/testing/selftests/size/.gitignore | |||
@@ -0,0 +1 @@ | |||
get_size | |||
diff --git a/tools/testing/selftests/size/Makefile b/tools/testing/selftests/size/Makefile new file mode 100644 index 000000000000..04dc25e4fa92 --- /dev/null +++ b/tools/testing/selftests/size/Makefile | |||
@@ -0,0 +1,12 @@ | |||
1 | CC = $(CROSS_COMPILE)gcc | ||
2 | |||
3 | all: get_size | ||
4 | |||
5 | get_size: get_size.c | ||
6 | $(CC) -static -ffreestanding -nostartfiles -s $< -o $@ | ||
7 | |||
8 | run_tests: all | ||
9 | ./get_size | ||
10 | |||
11 | clean: | ||
12 | $(RM) get_size | ||
diff --git a/tools/testing/selftests/size/get_size.c b/tools/testing/selftests/size/get_size.c new file mode 100644 index 000000000000..2d1af7cca463 --- /dev/null +++ b/tools/testing/selftests/size/get_size.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * Copyright 2014 Sony Mobile Communications Inc. | ||
3 | * | ||
4 | * Licensed under the terms of the GNU GPL License version 2 | ||
5 | * | ||
6 | * Selftest for runtime system size | ||
7 | * | ||
8 | * Prints the amount of RAM that the currently running system is using. | ||
9 | * | ||
10 | * This program tries to be as small as possible itself, to | ||
11 | * avoid perturbing the system memory utilization with its | ||
12 | * own execution. It also attempts to have as few dependencies | ||
13 | * on kernel features as possible. | ||
14 | * | ||
15 | * It should be statically linked, with startup libs avoided. | ||
16 | * It uses no library calls, and only the following 3 syscalls: | ||
17 | * sysinfo(), write(), and _exit() | ||
18 | * | ||
19 | * For output, it avoids printf (which in some C libraries | ||
20 | * has large external dependencies) by implementing it's own | ||
21 | * number output and print routines, and using __builtin_strlen() | ||
22 | */ | ||
23 | |||
24 | #include <sys/sysinfo.h> | ||
25 | #include <unistd.h> | ||
26 | |||
27 | #define STDOUT_FILENO 1 | ||
28 | |||
29 | static int print(const char *s) | ||
30 | { | ||
31 | return write(STDOUT_FILENO, s, __builtin_strlen(s)); | ||
32 | } | ||
33 | |||
34 | static inline char *num_to_str(unsigned long num, char *buf, int len) | ||
35 | { | ||
36 | unsigned int digit; | ||
37 | |||
38 | /* put digits in buffer from back to front */ | ||
39 | buf += len - 1; | ||
40 | *buf = 0; | ||
41 | do { | ||
42 | digit = num % 10; | ||
43 | *(--buf) = digit + '0'; | ||
44 | num /= 10; | ||
45 | } while (num > 0); | ||
46 | |||
47 | return buf; | ||
48 | } | ||
49 | |||
50 | static int print_num(unsigned long num) | ||
51 | { | ||
52 | char num_buf[30]; | ||
53 | |||
54 | return print(num_to_str(num, num_buf, sizeof(num_buf))); | ||
55 | } | ||
56 | |||
57 | static int print_k_value(const char *s, unsigned long num, unsigned long units) | ||
58 | { | ||
59 | unsigned long long temp; | ||
60 | int ccode; | ||
61 | |||
62 | print(s); | ||
63 | |||
64 | temp = num; | ||
65 | temp = (temp * units)/1024; | ||
66 | num = temp; | ||
67 | ccode = print_num(num); | ||
68 | print("\n"); | ||
69 | return ccode; | ||
70 | } | ||
71 | |||
72 | /* this program has no main(), as startup libraries are not used */ | ||
73 | void _start(void) | ||
74 | { | ||
75 | int ccode; | ||
76 | struct sysinfo info; | ||
77 | unsigned long used; | ||
78 | |||
79 | print("Testing system size.\n"); | ||
80 | print("1..1\n"); | ||
81 | |||
82 | ccode = sysinfo(&info); | ||
83 | if (ccode < 0) { | ||
84 | print("not ok 1 get runtime memory use\n"); | ||
85 | print("# could not get sysinfo\n"); | ||
86 | _exit(ccode); | ||
87 | } | ||
88 | /* ignore cache complexities for now */ | ||
89 | used = info.totalram - info.freeram - info.bufferram; | ||
90 | print_k_value("ok 1 get runtime memory use # size = ", used, | ||
91 | info.mem_unit); | ||
92 | |||
93 | print("# System runtime memory report (units in Kilobytes):\n"); | ||
94 | print_k_value("# Total: ", info.totalram, info.mem_unit); | ||
95 | print_k_value("# Free: ", info.freeram, info.mem_unit); | ||
96 | print_k_value("# Buffer: ", info.bufferram, info.mem_unit); | ||
97 | print_k_value("# In use: ", used, info.mem_unit); | ||
98 | |||
99 | _exit(0); | ||
100 | } | ||
diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c index 41bd85559d4b..f87d970a485c 100644 --- a/tools/testing/selftests/timers/posix_timers.c +++ b/tools/testing/selftests/timers/posix_timers.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <time.h> | 15 | #include <time.h> |
16 | #include <pthread.h> | 16 | #include <pthread.h> |
17 | 17 | ||
18 | #include "../kselftest.h" | ||
19 | |||
18 | #define DELAY 2 | 20 | #define DELAY 2 |
19 | #define USECS_PER_SEC 1000000 | 21 | #define USECS_PER_SEC 1000000 |
20 | 22 | ||
@@ -194,16 +196,16 @@ int main(int argc, char **argv) | |||
194 | printf("based timers if other threads run on the CPU...\n"); | 196 | printf("based timers if other threads run on the CPU...\n"); |
195 | 197 | ||
196 | if (check_itimer(ITIMER_VIRTUAL) < 0) | 198 | if (check_itimer(ITIMER_VIRTUAL) < 0) |
197 | return -1; | 199 | return ksft_exit_fail(); |
198 | 200 | ||
199 | if (check_itimer(ITIMER_PROF) < 0) | 201 | if (check_itimer(ITIMER_PROF) < 0) |
200 | return -1; | 202 | return ksft_exit_fail(); |
201 | 203 | ||
202 | if (check_itimer(ITIMER_REAL) < 0) | 204 | if (check_itimer(ITIMER_REAL) < 0) |
203 | return -1; | 205 | return ksft_exit_fail(); |
204 | 206 | ||
205 | if (check_timer_create(CLOCK_THREAD_CPUTIME_ID) < 0) | 207 | if (check_timer_create(CLOCK_THREAD_CPUTIME_ID) < 0) |
206 | return -1; | 208 | return ksft_exit_fail(); |
207 | 209 | ||
208 | /* | 210 | /* |
209 | * It's unfortunately hard to reliably test a timer expiration | 211 | * It's unfortunately hard to reliably test a timer expiration |
@@ -215,7 +217,7 @@ int main(int argc, char **argv) | |||
215 | * find a better solution. | 217 | * find a better solution. |
216 | */ | 218 | */ |
217 | if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0) | 219 | if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0) |
218 | return -1; | 220 | return ksft_exit_fail(); |
219 | 221 | ||
220 | return 0; | 222 | return ksft_exit_pass(); |
221 | } | 223 | } |
diff --git a/tools/testing/selftests/user/Makefile b/tools/testing/selftests/user/Makefile index 396255bd720e..12c9d15bab07 100644 --- a/tools/testing/selftests/user/Makefile +++ b/tools/testing/selftests/user/Makefile | |||
@@ -4,10 +4,4 @@ | |||
4 | all: | 4 | all: |
5 | 5 | ||
6 | run_tests: all | 6 | run_tests: all |
7 | @if /sbin/modprobe test_user_copy ; then \ | 7 | ./test_user_copy.sh |
8 | rmmod test_user_copy; \ | ||
9 | echo "user_copy: ok"; \ | ||
10 | else \ | ||
11 | echo "user_copy: [FAIL]"; \ | ||
12 | exit 1; \ | ||
13 | fi | ||
diff --git a/tools/testing/selftests/user/test_user_copy.sh b/tools/testing/selftests/user/test_user_copy.sh new file mode 100755 index 000000000000..350107f40c1d --- /dev/null +++ b/tools/testing/selftests/user/test_user_copy.sh | |||
@@ -0,0 +1,10 @@ | |||
1 | #!/bin/sh | ||
2 | # Runs copy_to/from_user infrastructure using test_user_copy kernel module | ||
3 | |||
4 | if /sbin/modprobe -q test_user_copy; then | ||
5 | /sbin/modprobe -q -r test_user_copy | ||
6 | echo "user_copy: ok" | ||
7 | else | ||
8 | echo "user_copy: [FAIL]" | ||
9 | exit 1 | ||
10 | fi | ||
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile index 4c4b1f631ecf..077828c889f1 100644 --- a/tools/testing/selftests/vm/Makefile +++ b/tools/testing/selftests/vm/Makefile | |||
@@ -7,7 +7,7 @@ BINARIES += transhuge-stress | |||
7 | 7 | ||
8 | all: $(BINARIES) | 8 | all: $(BINARIES) |
9 | %: %.c | 9 | %: %.c |
10 | $(CC) $(CFLAGS) -o $@ $^ | 10 | $(CC) $(CFLAGS) -o $@ $^ -lrt |
11 | 11 | ||
12 | run_tests: all | 12 | run_tests: all |
13 | @/bin/sh ./run_vmtests || (echo "vmtests: [FAIL]"; exit 1) | 13 | @/bin/sh ./run_vmtests || (echo "vmtests: [FAIL]"; exit 1) |
diff --git a/tools/thermal/tmon/sysfs.c b/tools/thermal/tmon/sysfs.c index dfe454855cd2..1c12536f2081 100644 --- a/tools/thermal/tmon/sysfs.c +++ b/tools/thermal/tmon/sysfs.c | |||
@@ -446,7 +446,7 @@ int probe_thermal_sysfs(void) | |||
446 | return -1; | 446 | return -1; |
447 | } | 447 | } |
448 | 448 | ||
449 | ptdata.tzi = calloc(sizeof(struct tz_info), ptdata.max_tz_instance+1); | 449 | ptdata.tzi = calloc(ptdata.max_tz_instance+1, sizeof(struct tz_info)); |
450 | if (!ptdata.tzi) { | 450 | if (!ptdata.tzi) { |
451 | fprintf(stderr, "Err: allocate tz_info\n"); | 451 | fprintf(stderr, "Err: allocate tz_info\n"); |
452 | return -1; | 452 | return -1; |
@@ -454,8 +454,8 @@ int probe_thermal_sysfs(void) | |||
454 | 454 | ||
455 | /* we still show thermal zone information if there is no cdev */ | 455 | /* we still show thermal zone information if there is no cdev */ |
456 | if (ptdata.nr_cooling_dev) { | 456 | if (ptdata.nr_cooling_dev) { |
457 | ptdata.cdi = calloc(sizeof(struct cdev_info), | 457 | ptdata.cdi = calloc(ptdata.max_cdev_instance + 1, |
458 | ptdata.max_cdev_instance + 1); | 458 | sizeof(struct cdev_info)); |
459 | if (!ptdata.cdi) { | 459 | if (!ptdata.cdi) { |
460 | free(ptdata.tzi); | 460 | free(ptdata.tzi); |
461 | fprintf(stderr, "Err: allocate cdev_info\n"); | 461 | fprintf(stderr, "Err: allocate cdev_info\n"); |
diff --git a/tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c b/tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c index af4b0508be77..aaca1f44e788 100644 --- a/tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c +++ b/tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c | |||
@@ -342,7 +342,7 @@ int main(int argc, char *argv[]) | |||
342 | iobuf[i].requested = ret; | 342 | iobuf[i].requested = ret; |
343 | printf("submit: %d requests buf: %d\n", ret, i); | 343 | printf("submit: %d requests buf: %d\n", ret, i); |
344 | } else | 344 | } else |
345 | perror("unable to submit reqests"); | 345 | perror("unable to submit requests"); |
346 | } | 346 | } |
347 | 347 | ||
348 | /* if event is ready to read */ | 348 | /* if event is ready to read */ |
diff --git a/tools/usb/usbip/libsrc/list.h b/tools/usb/usbip/libsrc/list.h index 8d0c936e184f..5eaaa78e2c6a 100644 --- a/tools/usb/usbip/libsrc/list.h +++ b/tools/usb/usbip/libsrc/list.h | |||
@@ -98,7 +98,7 @@ static inline void list_del(struct list_head *entry) | |||
98 | * list_entry - get the struct for this entry | 98 | * list_entry - get the struct for this entry |
99 | * @ptr: the &struct list_head pointer. | 99 | * @ptr: the &struct list_head pointer. |
100 | * @type: the type of the struct this is embedded in. | 100 | * @type: the type of the struct this is embedded in. |
101 | * @member: the name of the list_struct within the struct. | 101 | * @member: the name of the list_head within the struct. |
102 | */ | 102 | */ |
103 | #define list_entry(ptr, type, member) \ | 103 | #define list_entry(ptr, type, member) \ |
104 | container_of(ptr, type, member) | 104 | container_of(ptr, type, member) |
diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c index 2f87f2d348ba..2a7cd2b8d966 100644 --- a/tools/usb/usbip/src/usbipd.c +++ b/tools/usb/usbip/src/usbipd.c | |||
@@ -91,7 +91,6 @@ static void usbipd_help(void) | |||
91 | static int recv_request_import(int sockfd) | 91 | static int recv_request_import(int sockfd) |
92 | { | 92 | { |
93 | struct op_import_request req; | 93 | struct op_import_request req; |
94 | struct op_common reply; | ||
95 | struct usbip_exported_device *edev; | 94 | struct usbip_exported_device *edev; |
96 | struct usbip_usb_device pdu_udev; | 95 | struct usbip_usb_device pdu_udev; |
97 | struct list_head *i; | 96 | struct list_head *i; |
@@ -100,7 +99,6 @@ static int recv_request_import(int sockfd) | |||
100 | int rc; | 99 | int rc; |
101 | 100 | ||
102 | memset(&req, 0, sizeof(req)); | 101 | memset(&req, 0, sizeof(req)); |
103 | memset(&reply, 0, sizeof(reply)); | ||
104 | 102 | ||
105 | rc = usbip_net_recv(sockfd, &req, sizeof(req)); | 103 | rc = usbip_net_recv(sockfd, &req, sizeof(req)); |
106 | if (rc < 0) { | 104 | if (rc < 0) { |
diff --git a/tools/virtio/Makefile b/tools/virtio/Makefile index 9325f4693821..505ad51b3b51 100644 --- a/tools/virtio/Makefile +++ b/tools/virtio/Makefile | |||
@@ -3,7 +3,7 @@ test: virtio_test vringh_test | |||
3 | virtio_test: virtio_ring.o virtio_test.o | 3 | virtio_test: virtio_ring.o virtio_test.o |
4 | vringh_test: vringh_test.o vringh.o virtio_ring.o | 4 | vringh_test: vringh_test.o vringh.o virtio_ring.o |
5 | 5 | ||
6 | CFLAGS += -g -O2 -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE | 6 | CFLAGS += -g -O2 -Werror -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE |
7 | vpath %.c ../../drivers/virtio ../../drivers/vhost | 7 | vpath %.c ../../drivers/virtio ../../drivers/vhost |
8 | mod: | 8 | mod: |
9 | ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test | 9 | ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test |
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h index 5a2d1f0f6bc7..a3e07016a440 100644 --- a/tools/virtio/linux/virtio.h +++ b/tools/virtio/linux/virtio.h | |||
@@ -6,31 +6,12 @@ | |||
6 | /* TODO: empty stubs for now. Broken but enough for virtio_ring.c */ | 6 | /* TODO: empty stubs for now. Broken but enough for virtio_ring.c */ |
7 | #define list_add_tail(a, b) do {} while (0) | 7 | #define list_add_tail(a, b) do {} while (0) |
8 | #define list_del(a) do {} while (0) | 8 | #define list_del(a) do {} while (0) |
9 | 9 | #define list_for_each_entry(a, b, c) while (0) | |
10 | #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) | ||
11 | #define BITS_PER_BYTE 8 | ||
12 | #define BITS_PER_LONG (sizeof(long) * BITS_PER_BYTE) | ||
13 | #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) | ||
14 | |||
15 | /* TODO: Not atomic as it should be: | ||
16 | * we don't use this for anything important. */ | ||
17 | static inline void clear_bit(int nr, volatile unsigned long *addr) | ||
18 | { | ||
19 | unsigned long mask = BIT_MASK(nr); | ||
20 | unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); | ||
21 | |||
22 | *p &= ~mask; | ||
23 | } | ||
24 | |||
25 | static inline int test_bit(int nr, const volatile unsigned long *addr) | ||
26 | { | ||
27 | return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); | ||
28 | } | ||
29 | /* end of stubs */ | 10 | /* end of stubs */ |
30 | 11 | ||
31 | struct virtio_device { | 12 | struct virtio_device { |
32 | void *dev; | 13 | void *dev; |
33 | unsigned long features[1]; | 14 | u64 features; |
34 | }; | 15 | }; |
35 | 16 | ||
36 | struct virtqueue { | 17 | struct virtqueue { |
diff --git a/tools/virtio/linux/virtio_byteorder.h b/tools/virtio/linux/virtio_byteorder.h new file mode 100644 index 000000000000..9de9e6ac1d10 --- /dev/null +++ b/tools/virtio/linux/virtio_byteorder.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _LINUX_VIRTIO_BYTEORDER_STUB_H | ||
2 | #define _LINUX_VIRTIO_BYTEORDER_STUB_H | ||
3 | |||
4 | #include <asm/byteorder.h> | ||
5 | #include "../../include/linux/byteorder/generic.h" | ||
6 | #include "../../include/linux/virtio_byteorder.h" | ||
7 | |||
8 | #endif | ||
diff --git a/tools/virtio/linux/virtio_config.h b/tools/virtio/linux/virtio_config.h index 5049967f99f7..806d683ab107 100644 --- a/tools/virtio/linux/virtio_config.h +++ b/tools/virtio/linux/virtio_config.h | |||
@@ -1,6 +1,72 @@ | |||
1 | #define VIRTIO_TRANSPORT_F_START 28 | 1 | #include <linux/virtio_byteorder.h> |
2 | #define VIRTIO_TRANSPORT_F_END 32 | 2 | #include <linux/virtio.h> |
3 | #include <uapi/linux/virtio_config.h> | ||
4 | |||
5 | /* | ||
6 | * __virtio_test_bit - helper to test feature bits. For use by transports. | ||
7 | * Devices should normally use virtio_has_feature, | ||
8 | * which includes more checks. | ||
9 | * @vdev: the device | ||
10 | * @fbit: the feature bit | ||
11 | */ | ||
12 | static inline bool __virtio_test_bit(const struct virtio_device *vdev, | ||
13 | unsigned int fbit) | ||
14 | { | ||
15 | return vdev->features & (1ULL << fbit); | ||
16 | } | ||
17 | |||
18 | /** | ||
19 | * __virtio_set_bit - helper to set feature bits. For use by transports. | ||
20 | * @vdev: the device | ||
21 | * @fbit: the feature bit | ||
22 | */ | ||
23 | static inline void __virtio_set_bit(struct virtio_device *vdev, | ||
24 | unsigned int fbit) | ||
25 | { | ||
26 | vdev->features |= (1ULL << fbit); | ||
27 | } | ||
28 | |||
29 | /** | ||
30 | * __virtio_clear_bit - helper to clear feature bits. For use by transports. | ||
31 | * @vdev: the device | ||
32 | * @fbit: the feature bit | ||
33 | */ | ||
34 | static inline void __virtio_clear_bit(struct virtio_device *vdev, | ||
35 | unsigned int fbit) | ||
36 | { | ||
37 | vdev->features &= ~(1ULL << fbit); | ||
38 | } | ||
3 | 39 | ||
4 | #define virtio_has_feature(dev, feature) \ | 40 | #define virtio_has_feature(dev, feature) \ |
5 | test_bit((feature), (dev)->features) | 41 | (__virtio_test_bit((dev), feature)) |
42 | |||
43 | static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val) | ||
44 | { | ||
45 | return __virtio16_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | ||
46 | } | ||
47 | |||
48 | static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val) | ||
49 | { | ||
50 | return __cpu_to_virtio16(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | ||
51 | } | ||
52 | |||
53 | static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val) | ||
54 | { | ||
55 | return __virtio32_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | ||
56 | } | ||
57 | |||
58 | static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val) | ||
59 | { | ||
60 | return __cpu_to_virtio32(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | ||
61 | } | ||
62 | |||
63 | static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val) | ||
64 | { | ||
65 | return __virtio64_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | ||
66 | } | ||
67 | |||
68 | static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val) | ||
69 | { | ||
70 | return __cpu_to_virtio64(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | ||
71 | } | ||
6 | 72 | ||
diff --git a/tools/virtio/uapi/linux/virtio_types.h b/tools/virtio/uapi/linux/virtio_types.h new file mode 100644 index 000000000000..e7a1096e7c97 --- /dev/null +++ b/tools/virtio/uapi/linux/virtio_types.h | |||
@@ -0,0 +1 @@ | |||
#include "../../include/uapi/linux/virtio_types.h" | |||
diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c index 00ea679b3826..e0445898f08f 100644 --- a/tools/virtio/virtio_test.c +++ b/tools/virtio/virtio_test.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <sys/types.h> | 11 | #include <sys/types.h> |
12 | #include <fcntl.h> | 12 | #include <fcntl.h> |
13 | #include <stdbool.h> | 13 | #include <stdbool.h> |
14 | #include <linux/virtio_types.h> | ||
14 | #include <linux/vhost.h> | 15 | #include <linux/vhost.h> |
15 | #include <linux/virtio.h> | 16 | #include <linux/virtio.h> |
16 | #include <linux/virtio_ring.h> | 17 | #include <linux/virtio_ring.h> |
@@ -60,7 +61,7 @@ void vhost_vq_setup(struct vdev_info *dev, struct vq_info *info) | |||
60 | { | 61 | { |
61 | struct vhost_vring_state state = { .index = info->idx }; | 62 | struct vhost_vring_state state = { .index = info->idx }; |
62 | struct vhost_vring_file file = { .index = info->idx }; | 63 | struct vhost_vring_file file = { .index = info->idx }; |
63 | unsigned long long features = dev->vdev.features[0]; | 64 | unsigned long long features = dev->vdev.features; |
64 | struct vhost_vring_addr addr = { | 65 | struct vhost_vring_addr addr = { |
65 | .index = info->idx, | 66 | .index = info->idx, |
66 | .desc_user_addr = (uint64_t)(unsigned long)info->vring.desc, | 67 | .desc_user_addr = (uint64_t)(unsigned long)info->vring.desc, |
@@ -113,8 +114,7 @@ static void vdev_info_init(struct vdev_info* dev, unsigned long long features) | |||
113 | { | 114 | { |
114 | int r; | 115 | int r; |
115 | memset(dev, 0, sizeof *dev); | 116 | memset(dev, 0, sizeof *dev); |
116 | dev->vdev.features[0] = features; | 117 | dev->vdev.features = features; |
117 | dev->vdev.features[1] = features >> 32; | ||
118 | dev->buf_size = 1024; | 118 | dev->buf_size = 1024; |
119 | dev->buf = malloc(dev->buf_size); | 119 | dev->buf = malloc(dev->buf_size); |
120 | assert(dev->buf); | 120 | assert(dev->buf); |
@@ -228,6 +228,14 @@ const struct option longopts[] = { | |||
228 | .val = 'i', | 228 | .val = 'i', |
229 | }, | 229 | }, |
230 | { | 230 | { |
231 | .name = "virtio-1", | ||
232 | .val = '1', | ||
233 | }, | ||
234 | { | ||
235 | .name = "no-virtio-1", | ||
236 | .val = '0', | ||
237 | }, | ||
238 | { | ||
231 | .name = "delayed-interrupt", | 239 | .name = "delayed-interrupt", |
232 | .val = 'D', | 240 | .val = 'D', |
233 | }, | 241 | }, |
@@ -244,6 +252,7 @@ static void help(void) | |||
244 | fprintf(stderr, "Usage: virtio_test [--help]" | 252 | fprintf(stderr, "Usage: virtio_test [--help]" |
245 | " [--no-indirect]" | 253 | " [--no-indirect]" |
246 | " [--no-event-idx]" | 254 | " [--no-event-idx]" |
255 | " [--no-virtio-1]" | ||
247 | " [--delayed-interrupt]" | 256 | " [--delayed-interrupt]" |
248 | "\n"); | 257 | "\n"); |
249 | } | 258 | } |
@@ -252,7 +261,7 @@ int main(int argc, char **argv) | |||
252 | { | 261 | { |
253 | struct vdev_info dev; | 262 | struct vdev_info dev; |
254 | unsigned long long features = (1ULL << VIRTIO_RING_F_INDIRECT_DESC) | | 263 | unsigned long long features = (1ULL << VIRTIO_RING_F_INDIRECT_DESC) | |
255 | (1ULL << VIRTIO_RING_F_EVENT_IDX); | 264 | (1ULL << VIRTIO_RING_F_EVENT_IDX) | (1ULL << VIRTIO_F_VERSION_1); |
256 | int o; | 265 | int o; |
257 | bool delayed = false; | 266 | bool delayed = false; |
258 | 267 | ||
@@ -273,6 +282,9 @@ int main(int argc, char **argv) | |||
273 | case 'i': | 282 | case 'i': |
274 | features &= ~(1ULL << VIRTIO_RING_F_INDIRECT_DESC); | 283 | features &= ~(1ULL << VIRTIO_RING_F_INDIRECT_DESC); |
275 | break; | 284 | break; |
285 | case '0': | ||
286 | features &= ~(1ULL << VIRTIO_F_VERSION_1); | ||
287 | break; | ||
276 | case 'D': | 288 | case 'D': |
277 | delayed = true; | 289 | delayed = true; |
278 | break; | 290 | break; |
diff --git a/tools/virtio/vringh_test.c b/tools/virtio/vringh_test.c index 14a4f4cab5b9..5f94f5105678 100644 --- a/tools/virtio/vringh_test.c +++ b/tools/virtio/vringh_test.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/virtio.h> | 7 | #include <linux/virtio.h> |
8 | #include <linux/vringh.h> | 8 | #include <linux/vringh.h> |
9 | #include <linux/virtio_ring.h> | 9 | #include <linux/virtio_ring.h> |
10 | #include <linux/virtio_config.h> | ||
10 | #include <linux/uaccess.h> | 11 | #include <linux/uaccess.h> |
11 | #include <sys/types.h> | 12 | #include <sys/types.h> |
12 | #include <sys/stat.h> | 13 | #include <sys/stat.h> |
@@ -131,7 +132,7 @@ static inline int vringh_get_head(struct vringh *vrh, u16 *head) | |||
131 | return 1; | 132 | return 1; |
132 | } | 133 | } |
133 | 134 | ||
134 | static int parallel_test(unsigned long features, | 135 | static int parallel_test(u64 features, |
135 | bool (*getrange)(struct vringh *vrh, | 136 | bool (*getrange)(struct vringh *vrh, |
136 | u64 addr, struct vringh_range *r), | 137 | u64 addr, struct vringh_range *r), |
137 | bool fast_vringh) | 138 | bool fast_vringh) |
@@ -304,7 +305,7 @@ static int parallel_test(unsigned long features, | |||
304 | close(to_guest[1]); | 305 | close(to_guest[1]); |
305 | close(to_host[0]); | 306 | close(to_host[0]); |
306 | 307 | ||
307 | gvdev.vdev.features[0] = features; | 308 | gvdev.vdev.features = features; |
308 | gvdev.to_host_fd = to_host[1]; | 309 | gvdev.to_host_fd = to_host[1]; |
309 | gvdev.notifies = 0; | 310 | gvdev.notifies = 0; |
310 | 311 | ||
@@ -449,13 +450,15 @@ int main(int argc, char *argv[]) | |||
449 | bool fast_vringh = false, parallel = false; | 450 | bool fast_vringh = false, parallel = false; |
450 | 451 | ||
451 | getrange = getrange_iov; | 452 | getrange = getrange_iov; |
452 | vdev.features[0] = 0; | 453 | vdev.features = 0; |
453 | 454 | ||
454 | while (argv[1]) { | 455 | while (argv[1]) { |
455 | if (strcmp(argv[1], "--indirect") == 0) | 456 | if (strcmp(argv[1], "--indirect") == 0) |
456 | vdev.features[0] |= (1 << VIRTIO_RING_F_INDIRECT_DESC); | 457 | __virtio_set_bit(&vdev, VIRTIO_RING_F_INDIRECT_DESC); |
457 | else if (strcmp(argv[1], "--eventidx") == 0) | 458 | else if (strcmp(argv[1], "--eventidx") == 0) |
458 | vdev.features[0] |= (1 << VIRTIO_RING_F_EVENT_IDX); | 459 | __virtio_set_bit(&vdev, VIRTIO_RING_F_EVENT_IDX); |
460 | else if (strcmp(argv[1], "--virtio-1") == 0) | ||
461 | __virtio_set_bit(&vdev, VIRTIO_F_VERSION_1); | ||
459 | else if (strcmp(argv[1], "--slow-range") == 0) | 462 | else if (strcmp(argv[1], "--slow-range") == 0) |
460 | getrange = getrange_slow; | 463 | getrange = getrange_slow; |
461 | else if (strcmp(argv[1], "--fast-vringh") == 0) | 464 | else if (strcmp(argv[1], "--fast-vringh") == 0) |
@@ -468,7 +471,7 @@ int main(int argc, char *argv[]) | |||
468 | } | 471 | } |
469 | 472 | ||
470 | if (parallel) | 473 | if (parallel) |
471 | return parallel_test(vdev.features[0], getrange, fast_vringh); | 474 | return parallel_test(vdev.features, getrange, fast_vringh); |
472 | 475 | ||
473 | if (posix_memalign(&__user_addr_min, PAGE_SIZE, USER_MEM) != 0) | 476 | if (posix_memalign(&__user_addr_min, PAGE_SIZE, USER_MEM) != 0) |
474 | abort(); | 477 | abort(); |
@@ -483,7 +486,7 @@ int main(int argc, char *argv[]) | |||
483 | 486 | ||
484 | /* Set up host side. */ | 487 | /* Set up host side. */ |
485 | vring_init(&vrh.vring, RINGSIZE, __user_addr_min, ALIGN); | 488 | vring_init(&vrh.vring, RINGSIZE, __user_addr_min, ALIGN); |
486 | vringh_init_user(&vrh, vdev.features[0], RINGSIZE, true, | 489 | vringh_init_user(&vrh, vdev.features, RINGSIZE, true, |
487 | vrh.vring.desc, vrh.vring.avail, vrh.vring.used); | 490 | vrh.vring.desc, vrh.vring.avail, vrh.vring.used); |
488 | 491 | ||
489 | /* No descriptor to get yet... */ | 492 | /* No descriptor to get yet... */ |
@@ -652,13 +655,13 @@ int main(int argc, char *argv[]) | |||
652 | } | 655 | } |
653 | 656 | ||
654 | /* Test weird (but legal!) indirect. */ | 657 | /* Test weird (but legal!) indirect. */ |
655 | if (vdev.features[0] & (1 << VIRTIO_RING_F_INDIRECT_DESC)) { | 658 | if (__virtio_test_bit(&vdev, VIRTIO_RING_F_INDIRECT_DESC)) { |
656 | char *data = __user_addr_max - USER_MEM/4; | 659 | char *data = __user_addr_max - USER_MEM/4; |
657 | struct vring_desc *d = __user_addr_max - USER_MEM/2; | 660 | struct vring_desc *d = __user_addr_max - USER_MEM/2; |
658 | struct vring vring; | 661 | struct vring vring; |
659 | 662 | ||
660 | /* Force creation of direct, which we modify. */ | 663 | /* Force creation of direct, which we modify. */ |
661 | vdev.features[0] &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC); | 664 | __virtio_clear_bit(&vdev, VIRTIO_RING_F_INDIRECT_DESC); |
662 | vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &vdev, true, | 665 | vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &vdev, true, |
663 | __user_addr_min, | 666 | __user_addr_min, |
664 | never_notify_host, | 667 | never_notify_host, |
diff --git a/tools/vm/Makefile b/tools/vm/Makefile index 3d907dacf2ac..ac884b65a072 100644 --- a/tools/vm/Makefile +++ b/tools/vm/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # Makefile for vm tools | 1 | # Makefile for vm tools |
2 | # | 2 | # |
3 | TARGETS=page-types slabinfo | 3 | TARGETS=page-types slabinfo page_owner_sort |
4 | 4 | ||
5 | LIB_DIR = ../lib/api | 5 | LIB_DIR = ../lib/api |
6 | LIBS = $(LIB_DIR)/libapikfs.a | 6 | LIBS = $(LIB_DIR)/libapikfs.a |
@@ -18,5 +18,5 @@ $(LIBS): | |||
18 | $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) | 18 | $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) |
19 | 19 | ||
20 | clean: | 20 | clean: |
21 | $(RM) page-types slabinfo | 21 | $(RM) page-types slabinfo page_owner_sort |
22 | make -C $(LIB_DIR) clean | 22 | make -C $(LIB_DIR) clean |
diff --git a/tools/vm/page_owner_sort.c b/tools/vm/page_owner_sort.c new file mode 100644 index 000000000000..77147b42d598 --- /dev/null +++ b/tools/vm/page_owner_sort.c | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * User-space helper to sort the output of /sys/kernel/debug/page_owner | ||
3 | * | ||
4 | * Example use: | ||
5 | * cat /sys/kernel/debug/page_owner > page_owner_full.txt | ||
6 | * grep -v ^PFN page_owner_full.txt > page_owner.txt | ||
7 | * ./sort page_owner.txt sorted_page_owner.txt | ||
8 | */ | ||
9 | |||
10 | #include <stdio.h> | ||
11 | #include <stdlib.h> | ||
12 | #include <sys/types.h> | ||
13 | #include <sys/stat.h> | ||
14 | #include <fcntl.h> | ||
15 | #include <unistd.h> | ||
16 | #include <string.h> | ||
17 | |||
18 | struct block_list { | ||
19 | char *txt; | ||
20 | int len; | ||
21 | int num; | ||
22 | }; | ||
23 | |||
24 | |||
25 | static struct block_list *list; | ||
26 | static int list_size; | ||
27 | static int max_size; | ||
28 | |||
29 | struct block_list *block_head; | ||
30 | |||
31 | int read_block(char *buf, int buf_size, FILE *fin) | ||
32 | { | ||
33 | char *curr = buf, *const buf_end = buf + buf_size; | ||
34 | |||
35 | while (buf_end - curr > 1 && fgets(curr, buf_end - curr, fin)) { | ||
36 | if (*curr == '\n') /* empty line */ | ||
37 | return curr - buf; | ||
38 | curr += strlen(curr); | ||
39 | } | ||
40 | |||
41 | return -1; /* EOF or no space left in buf. */ | ||
42 | } | ||
43 | |||
44 | static int compare_txt(const void *p1, const void *p2) | ||
45 | { | ||
46 | const struct block_list *l1 = p1, *l2 = p2; | ||
47 | |||
48 | return strcmp(l1->txt, l2->txt); | ||
49 | } | ||
50 | |||
51 | static int compare_num(const void *p1, const void *p2) | ||
52 | { | ||
53 | const struct block_list *l1 = p1, *l2 = p2; | ||
54 | |||
55 | return l2->num - l1->num; | ||
56 | } | ||
57 | |||
58 | static void add_list(char *buf, int len) | ||
59 | { | ||
60 | if (list_size != 0 && | ||
61 | len == list[list_size-1].len && | ||
62 | memcmp(buf, list[list_size-1].txt, len) == 0) { | ||
63 | list[list_size-1].num++; | ||
64 | return; | ||
65 | } | ||
66 | if (list_size == max_size) { | ||
67 | printf("max_size too small??\n"); | ||
68 | exit(1); | ||
69 | } | ||
70 | list[list_size].txt = malloc(len+1); | ||
71 | list[list_size].len = len; | ||
72 | list[list_size].num = 1; | ||
73 | memcpy(list[list_size].txt, buf, len); | ||
74 | list[list_size].txt[len] = 0; | ||
75 | list_size++; | ||
76 | if (list_size % 1000 == 0) { | ||
77 | printf("loaded %d\r", list_size); | ||
78 | fflush(stdout); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | #define BUF_SIZE 1024 | ||
83 | |||
84 | int main(int argc, char **argv) | ||
85 | { | ||
86 | FILE *fin, *fout; | ||
87 | char buf[BUF_SIZE]; | ||
88 | int ret, i, count; | ||
89 | struct block_list *list2; | ||
90 | struct stat st; | ||
91 | |||
92 | if (argc < 3) { | ||
93 | printf("Usage: ./program <input> <output>\n"); | ||
94 | perror("open: "); | ||
95 | exit(1); | ||
96 | } | ||
97 | |||
98 | fin = fopen(argv[1], "r"); | ||
99 | fout = fopen(argv[2], "w"); | ||
100 | if (!fin || !fout) { | ||
101 | printf("Usage: ./program <input> <output>\n"); | ||
102 | perror("open: "); | ||
103 | exit(1); | ||
104 | } | ||
105 | |||
106 | fstat(fileno(fin), &st); | ||
107 | max_size = st.st_size / 100; /* hack ... */ | ||
108 | |||
109 | list = malloc(max_size * sizeof(*list)); | ||
110 | |||
111 | for ( ; ; ) { | ||
112 | ret = read_block(buf, BUF_SIZE, fin); | ||
113 | if (ret < 0) | ||
114 | break; | ||
115 | |||
116 | add_list(buf, ret); | ||
117 | } | ||
118 | |||
119 | printf("loaded %d\n", list_size); | ||
120 | |||
121 | printf("sorting ....\n"); | ||
122 | |||
123 | qsort(list, list_size, sizeof(list[0]), compare_txt); | ||
124 | |||
125 | list2 = malloc(sizeof(*list) * list_size); | ||
126 | |||
127 | printf("culling\n"); | ||
128 | |||
129 | for (i = count = 0; i < list_size; i++) { | ||
130 | if (count == 0 || | ||
131 | strcmp(list2[count-1].txt, list[i].txt) != 0) { | ||
132 | list2[count++] = list[i]; | ||
133 | } else { | ||
134 | list2[count-1].num += list[i].num; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | qsort(list2, count, sizeof(list[0]), compare_num); | ||
139 | |||
140 | for (i = 0; i < count; i++) | ||
141 | fprintf(fout, "%d times:\n%s\n", list2[i].num, list2[i].txt); | ||
142 | |||
143 | return 0; | ||
144 | } | ||