diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2015-01-12 04:51:13 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2015-01-12 04:51:13 -0500 |
commit | 2f5eaf66e580f64032b365a00157b6b58c266b37 (patch) | |
tree | 7852017c864f0eb3833782e2a017952bd8531458 /tools | |
parent | c291ee622165cb2c8d4e7af63fffd499354a23be (diff) | |
parent | 91d1179212161f220938198b742c328ad38fd0a3 (diff) |
Merge tag 'irqchip-urgent-3.19' of git://git.infradead.org/users/jcooper/linux into irq/urgent
irqchip urgent fixes for v3.19 from Jason Cooper
- mtk-sysirq: Fix error handling
- hip04: Fix cpu map for 16bit value
- gic-v3-its: Clear a warning regarding decimal constants
- omap-intc: Fix legacy DMA regression
- atmel-aic-common: Retain priority when changing type
Diffstat (limited to 'tools')
88 files changed, 2653 insertions, 966 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..6eedba1f7732 --- /dev/null +++ b/tools/include/asm-generic/bitops.h | |||
@@ -0,0 +1,27 @@ | |||
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/atomic.h> | ||
26 | |||
27 | #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/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/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/linux/bitops.h b/tools/include/linux/bitops.h new file mode 100644 index 000000000000..26005a15e7e2 --- /dev/null +++ b/tools/include/linux/bitops.h | |||
@@ -0,0 +1,53 @@ | |||
1 | #ifndef _TOOLS_LINUX_BITOPS_H_ | ||
2 | #define _TOOLS_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 | |||
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 | /* | ||
23 | * Include this here because some architectures need generic_ffs/fls in | ||
24 | * scope | ||
25 | * | ||
26 | * XXX: this needs to be asm/bitops.h, when we get to per arch optimizations | ||
27 | */ | ||
28 | #include <asm-generic/bitops.h> | ||
29 | |||
30 | #define for_each_set_bit(bit, addr, size) \ | ||
31 | for ((bit) = find_first_bit((addr), (size)); \ | ||
32 | (bit) < (size); \ | ||
33 | (bit) = find_next_bit((addr), (size), (bit) + 1)) | ||
34 | |||
35 | /* same as for_each_set_bit() but use bit as value to start with */ | ||
36 | #define for_each_set_bit_from(bit, addr, size) \ | ||
37 | for ((bit) = find_next_bit((addr), (size), (bit)); \ | ||
38 | (bit) < (size); \ | ||
39 | (bit) = find_next_bit((addr), (size), (bit) + 1)) | ||
40 | |||
41 | static inline unsigned long hweight_long(unsigned long w) | ||
42 | { | ||
43 | return sizeof(w) == 4 ? hweight32(w) : hweight64(w); | ||
44 | } | ||
45 | |||
46 | static inline unsigned fls_long(unsigned long l) | ||
47 | { | ||
48 | if (sizeof(l) == 4) | ||
49 | return fls(l); | ||
50 | return fls64(l); | ||
51 | } | ||
52 | |||
53 | #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/fs.c b/tools/lib/api/fs/fs.c index c1b49c36a951..65d9be3f9887 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" |
@@ -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/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/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..83e2887f91a3 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST | |||
@@ -4,17 +4,31 @@ 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/atomic.h | ||
10 | tools/include/asm-generic/bitops/__ffs.h | ||
11 | tools/include/asm-generic/bitops/__fls.h | ||
12 | tools/include/asm-generic/bitops/find.h | ||
13 | tools/include/asm-generic/bitops/fls64.h | ||
14 | tools/include/asm-generic/bitops/fls.h | ||
15 | tools/include/asm-generic/bitops.h | ||
16 | tools/include/linux/bitops.h | ||
8 | tools/include/linux/compiler.h | 17 | tools/include/linux/compiler.h |
9 | tools/include/linux/hash.h | ||
10 | tools/include/linux/export.h | 18 | tools/include/linux/export.h |
19 | tools/include/linux/hash.h | ||
20 | tools/include/linux/log2.h | ||
11 | tools/include/linux/types.h | 21 | tools/include/linux/types.h |
22 | include/asm-generic/bitops/fls64.h | ||
23 | include/asm-generic/bitops/__fls.h | ||
24 | include/asm-generic/bitops/fls.h | ||
12 | include/linux/const.h | 25 | include/linux/const.h |
13 | include/linux/perf_event.h | 26 | include/linux/perf_event.h |
14 | include/linux/rbtree.h | 27 | include/linux/rbtree.h |
15 | include/linux/list.h | 28 | include/linux/list.h |
16 | include/linux/hash.h | 29 | include/linux/hash.h |
17 | include/linux/stringify.h | 30 | include/linux/stringify.h |
31 | lib/find_next_bit.c | ||
18 | lib/rbtree.c | 32 | lib/rbtree.c |
19 | include/linux/swab.h | 33 | include/linux/swab.h |
20 | arch/*/include/asm/unistd*.h | 34 | arch/*/include/asm/unistd*.h |
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 478efa9b2364..67a03a825b3c 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
@@ -231,8 +231,16 @@ LIB_H += ../../include/uapi/linux/const.h | |||
231 | LIB_H += ../include/linux/hash.h | 231 | LIB_H += ../include/linux/hash.h |
232 | LIB_H += ../../include/linux/stringify.h | 232 | LIB_H += ../../include/linux/stringify.h |
233 | LIB_H += util/include/linux/bitmap.h | 233 | LIB_H += util/include/linux/bitmap.h |
234 | LIB_H += util/include/linux/bitops.h | 234 | LIB_H += ../include/linux/bitops.h |
235 | LIB_H += ../include/asm-generic/bitops/atomic.h | ||
236 | LIB_H += ../include/asm-generic/bitops/find.h | ||
237 | LIB_H += ../include/asm-generic/bitops/fls64.h | ||
238 | LIB_H += ../include/asm-generic/bitops/fls.h | ||
239 | LIB_H += ../include/asm-generic/bitops/__ffs.h | ||
240 | LIB_H += ../include/asm-generic/bitops/__fls.h | ||
241 | LIB_H += ../include/asm-generic/bitops.h | ||
235 | LIB_H += ../include/linux/compiler.h | 242 | LIB_H += ../include/linux/compiler.h |
243 | LIB_H += ../include/linux/log2.h | ||
236 | LIB_H += util/include/linux/const.h | 244 | LIB_H += util/include/linux/const.h |
237 | LIB_H += util/include/linux/ctype.h | 245 | LIB_H += util/include/linux/ctype.h |
238 | LIB_H += util/include/linux/kernel.h | 246 | LIB_H += util/include/linux/kernel.h |
@@ -335,6 +343,7 @@ LIB_OBJS += $(OUTPUT)util/event.o | |||
335 | LIB_OBJS += $(OUTPUT)util/evlist.o | 343 | LIB_OBJS += $(OUTPUT)util/evlist.o |
336 | LIB_OBJS += $(OUTPUT)util/evsel.o | 344 | LIB_OBJS += $(OUTPUT)util/evsel.o |
337 | LIB_OBJS += $(OUTPUT)util/exec_cmd.o | 345 | LIB_OBJS += $(OUTPUT)util/exec_cmd.o |
346 | LIB_OBJS += $(OUTPUT)util/find_next_bit.o | ||
338 | LIB_OBJS += $(OUTPUT)util/help.o | 347 | LIB_OBJS += $(OUTPUT)util/help.o |
339 | LIB_OBJS += $(OUTPUT)util/kallsyms.o | 348 | LIB_OBJS += $(OUTPUT)util/kallsyms.o |
340 | LIB_OBJS += $(OUTPUT)util/levenshtein.o | 349 | LIB_OBJS += $(OUTPUT)util/levenshtein.o |
@@ -458,7 +467,6 @@ BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o | |||
458 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o | 467 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o |
459 | endif | 468 | endif |
460 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o | 469 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o |
461 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o | ||
462 | BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o | 470 | BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o |
463 | BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o | 471 | BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o |
464 | BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o | 472 | BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o |
@@ -735,6 +743,9 @@ $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS | |||
735 | $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS | 743 | $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS |
736 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< | 744 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< |
737 | 745 | ||
746 | $(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c $(OUTPUT)PERF-CFLAGS | ||
747 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< | ||
748 | |||
738 | $(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS | 749 | $(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS |
739 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $< | 750 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $< |
740 | 751 | ||
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/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-kvm.c b/tools/perf/builtin-kvm.c index 3c0f3d4fb021..0894a817f67e 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -1293,7 +1293,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, | |||
1293 | OPT_UINTEGER('d', "display", &kvm->display_time, | 1293 | OPT_UINTEGER('d', "display", &kvm->display_time, |
1294 | "time in seconds between display updates"), | 1294 | "time in seconds between display updates"), |
1295 | OPT_STRING(0, "event", &kvm->report_event, "report event", | 1295 | OPT_STRING(0, "event", &kvm->report_event, "report event", |
1296 | "event for reporting: vmexit, mmio, ioport"), | 1296 | "event for reporting: " |
1297 | "vmexit, mmio (x86 only), ioport (x86 only)"), | ||
1297 | OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu, | 1298 | OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu, |
1298 | "vcpu id to report"), | 1299 | "vcpu id to report"), |
1299 | 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-trace.c b/tools/perf/builtin-trace.c index 83a4835c8118..badfabc6a01f 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -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/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/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/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 502daff76ceb..e6bb04b5b09b 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -1252,7 +1252,7 @@ static int hists__browser_title(struct hists *hists, | |||
1252 | 1252 | ||
1253 | nr_samples = convert_unit(nr_samples, &unit); | 1253 | nr_samples = convert_unit(nr_samples, &unit); |
1254 | printed = scnprintf(bf, size, | 1254 | printed = scnprintf(bf, size, |
1255 | "Samples: %lu%c of event '%s', Event count (approx.): %lu", | 1255 | "Samples: %lu%c of event '%s', Event count (approx.): %" PRIu64, |
1256 | nr_samples, unit, ev_name, nr_events); | 1256 | nr_samples, unit, ev_name, nr_events); |
1257 | 1257 | ||
1258 | 1258 | ||
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 2af18376b077..dc0d095f318c 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; |
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index e8d79e5bfaf7..0c72680a977f 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -410,21 +410,18 @@ int perf_session__cache_build_ids(struct perf_session *session) | |||
410 | { | 410 | { |
411 | struct rb_node *nd; | 411 | struct rb_node *nd; |
412 | int ret; | 412 | int ret; |
413 | char debugdir[PATH_MAX]; | ||
414 | 413 | ||
415 | if (no_buildid_cache) | 414 | if (no_buildid_cache) |
416 | return 0; | 415 | return 0; |
417 | 416 | ||
418 | snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir); | 417 | if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST) |
419 | |||
420 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) | ||
421 | return -1; | 418 | return -1; |
422 | 419 | ||
423 | ret = machine__cache_build_ids(&session->machines.host, debugdir); | 420 | ret = machine__cache_build_ids(&session->machines.host, buildid_dir); |
424 | 421 | ||
425 | for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { | 422 | for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { |
426 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | 423 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
427 | ret |= machine__cache_build_ids(pos, debugdir); | 424 | ret |= machine__cache_build_ids(pos, buildid_dir); |
428 | } | 425 | } |
429 | return ret ? -1 : 0; | 426 | return ret ? -1 : 0; |
430 | } | 427 | } |
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index cf524a35cc84..64b377e591e4 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 |
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/evlist.c b/tools/perf/util/evlist.c index cfbe2b99b9aa..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); |
@@ -892,10 +894,24 @@ out_unmap: | |||
892 | 894 | ||
893 | static size_t perf_evlist__mmap_size(unsigned long pages) | 895 | static size_t perf_evlist__mmap_size(unsigned long pages) |
894 | { | 896 | { |
895 | /* 512 kiB: default amount of unprivileged mlocked memory */ | 897 | if (pages == UINT_MAX) { |
896 | if (pages == UINT_MAX) | 898 | int max; |
897 | pages = (512 * 1024) / page_size; | 899 | |
898 | 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)) | ||
899 | return 0; | 915 | return 0; |
900 | 916 | ||
901 | return (pages + 1) * page_size; | 917 | return (pages + 1) * page_size; |
@@ -932,7 +948,7 @@ static long parse_pages_arg(const char *str, unsigned long min, | |||
932 | /* leave number of pages at 0 */ | 948 | /* leave number of pages at 0 */ |
933 | } else if (!is_power_of_2(pages)) { | 949 | } else if (!is_power_of_2(pages)) { |
934 | /* round pages up to next power of 2 */ | 950 | /* round pages up to next power of 2 */ |
935 | pages = next_pow2_l(pages); | 951 | pages = roundup_pow_of_two(pages); |
936 | if (!pages) | 952 | if (!pages) |
937 | return -EINVAL; | 953 | return -EINVAL; |
938 | 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", |
@@ -1483,6 +1499,37 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused, | |||
1483 | return 0; | 1499 | return 0; |
1484 | } | 1500 | } |
1485 | 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 | |||
1486 | void perf_evlist__to_front(struct perf_evlist *evlist, | 1533 | void perf_evlist__to_front(struct perf_evlist *evlist, |
1487 | struct perf_evsel *move_evsel) | 1534 | struct perf_evsel *move_evsel) |
1488 | { | 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/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/linux/bitops.h b/tools/perf/util/include/linux/bitops.h deleted file mode 100644 index c3294163de17..000000000000 --- a/tools/perf/util/include/linux/bitops.h +++ /dev/null | |||
@@ -1,162 +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 | #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) | ||
19 | #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) | ||
20 | |||
21 | #define for_each_set_bit(bit, addr, size) \ | ||
22 | for ((bit) = find_first_bit((addr), (size)); \ | ||
23 | (bit) < (size); \ | ||
24 | (bit) = find_next_bit((addr), (size), (bit) + 1)) | ||
25 | |||
26 | /* same as for_each_set_bit() but use bit as value to start with */ | ||
27 | #define for_each_set_bit_from(bit, addr, size) \ | ||
28 | for ((bit) = find_next_bit((addr), (size), (bit)); \ | ||
29 | (bit) < (size); \ | ||
30 | (bit) = find_next_bit((addr), (size), (bit) + 1)) | ||
31 | |||
32 | static inline void set_bit(int nr, unsigned long *addr) | ||
33 | { | ||
34 | addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG); | ||
35 | } | ||
36 | |||
37 | static inline void clear_bit(int nr, unsigned long *addr) | ||
38 | { | ||
39 | addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG)); | ||
40 | } | ||
41 | |||
42 | static __always_inline int test_bit(unsigned int nr, const unsigned long *addr) | ||
43 | { | ||
44 | return ((1UL << (nr % BITS_PER_LONG)) & | ||
45 | (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0; | ||
46 | } | ||
47 | |||
48 | static inline unsigned long hweight_long(unsigned long w) | ||
49 | { | ||
50 | return sizeof(w) == 4 ? hweight32(w) : hweight64(w); | ||
51 | } | ||
52 | |||
53 | #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) | ||
54 | |||
55 | /** | ||
56 | * __ffs - find first bit in word. | ||
57 | * @word: The word to search | ||
58 | * | ||
59 | * Undefined if no bit exists, so code should check against 0 first. | ||
60 | */ | ||
61 | static __always_inline unsigned long __ffs(unsigned long word) | ||
62 | { | ||
63 | int num = 0; | ||
64 | |||
65 | #if BITS_PER_LONG == 64 | ||
66 | if ((word & 0xffffffff) == 0) { | ||
67 | num += 32; | ||
68 | word >>= 32; | ||
69 | } | ||
70 | #endif | ||
71 | if ((word & 0xffff) == 0) { | ||
72 | num += 16; | ||
73 | word >>= 16; | ||
74 | } | ||
75 | if ((word & 0xff) == 0) { | ||
76 | num += 8; | ||
77 | word >>= 8; | ||
78 | } | ||
79 | if ((word & 0xf) == 0) { | ||
80 | num += 4; | ||
81 | word >>= 4; | ||
82 | } | ||
83 | if ((word & 0x3) == 0) { | ||
84 | num += 2; | ||
85 | word >>= 2; | ||
86 | } | ||
87 | if ((word & 0x1) == 0) | ||
88 | num += 1; | ||
89 | return num; | ||
90 | } | ||
91 | |||
92 | typedef const unsigned long __attribute__((__may_alias__)) long_alias_t; | ||
93 | |||
94 | /* | ||
95 | * Find the first set bit in a memory region. | ||
96 | */ | ||
97 | static inline unsigned long | ||
98 | find_first_bit(const unsigned long *addr, unsigned long size) | ||
99 | { | ||
100 | long_alias_t *p = (long_alias_t *) addr; | ||
101 | unsigned long result = 0; | ||
102 | unsigned long tmp; | ||
103 | |||
104 | while (size & ~(BITS_PER_LONG-1)) { | ||
105 | if ((tmp = *(p++))) | ||
106 | goto found; | ||
107 | result += BITS_PER_LONG; | ||
108 | size -= BITS_PER_LONG; | ||
109 | } | ||
110 | if (!size) | ||
111 | return result; | ||
112 | |||
113 | tmp = (*p) & (~0UL >> (BITS_PER_LONG - size)); | ||
114 | if (tmp == 0UL) /* Are any bits set? */ | ||
115 | return result + size; /* Nope. */ | ||
116 | found: | ||
117 | return result + __ffs(tmp); | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | * Find the next set bit in a memory region. | ||
122 | */ | ||
123 | static inline unsigned long | ||
124 | find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset) | ||
125 | { | ||
126 | const unsigned long *p = addr + BITOP_WORD(offset); | ||
127 | unsigned long result = offset & ~(BITS_PER_LONG-1); | ||
128 | unsigned long tmp; | ||
129 | |||
130 | if (offset >= size) | ||
131 | return size; | ||
132 | size -= result; | ||
133 | offset %= BITS_PER_LONG; | ||
134 | if (offset) { | ||
135 | tmp = *(p++); | ||
136 | tmp &= (~0UL << offset); | ||
137 | if (size < BITS_PER_LONG) | ||
138 | goto found_first; | ||
139 | if (tmp) | ||
140 | goto found_middle; | ||
141 | size -= BITS_PER_LONG; | ||
142 | result += BITS_PER_LONG; | ||
143 | } | ||
144 | while (size & ~(BITS_PER_LONG-1)) { | ||
145 | if ((tmp = *(p++))) | ||
146 | goto found_middle; | ||
147 | result += BITS_PER_LONG; | ||
148 | size -= BITS_PER_LONG; | ||
149 | } | ||
150 | if (!size) | ||
151 | return result; | ||
152 | tmp = *p; | ||
153 | |||
154 | found_first: | ||
155 | tmp &= (~0UL >> (BITS_PER_LONG - size)); | ||
156 | if (tmp == 0UL) /* Are any bits set? */ | ||
157 | return result + size; /* Nope. */ | ||
158 | found_middle: | ||
159 | return result + __ffs(tmp); | ||
160 | } | ||
161 | |||
162 | #endif | ||
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 15dd0a9691ce..94de3e48b490 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -1385,19 +1385,46 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample, | |||
1385 | static int add_callchain_ip(struct thread *thread, | 1385 | static int add_callchain_ip(struct thread *thread, |
1386 | struct symbol **parent, | 1386 | struct symbol **parent, |
1387 | struct addr_location *root_al, | 1387 | struct addr_location *root_al, |
1388 | int cpumode, | 1388 | bool branch_history, |
1389 | u64 ip) | 1389 | u64 ip) |
1390 | { | 1390 | { |
1391 | struct addr_location al; | 1391 | struct addr_location al; |
1392 | 1392 | ||
1393 | al.filtered = 0; | 1393 | al.filtered = 0; |
1394 | al.sym = NULL; | 1394 | al.sym = NULL; |
1395 | if (cpumode == -1) | 1395 | if (branch_history) |
1396 | thread__find_cpumode_addr_location(thread, MAP__FUNCTION, | 1396 | thread__find_cpumode_addr_location(thread, MAP__FUNCTION, |
1397 | ip, &al); | 1397 | ip, &al); |
1398 | else | 1398 | else { |
1399 | u8 cpumode = PERF_RECORD_MISC_USER; | ||
1400 | |||
1401 | if (ip >= PERF_CONTEXT_MAX) { | ||
1402 | switch (ip) { | ||
1403 | case PERF_CONTEXT_HV: | ||
1404 | cpumode = PERF_RECORD_MISC_HYPERVISOR; | ||
1405 | break; | ||
1406 | case PERF_CONTEXT_KERNEL: | ||
1407 | cpumode = PERF_RECORD_MISC_KERNEL; | ||
1408 | break; | ||
1409 | case PERF_CONTEXT_USER: | ||
1410 | cpumode = PERF_RECORD_MISC_USER; | ||
1411 | break; | ||
1412 | default: | ||
1413 | pr_debug("invalid callchain context: " | ||
1414 | "%"PRId64"\n", (s64) ip); | ||
1415 | /* | ||
1416 | * It seems the callchain is corrupted. | ||
1417 | * Discard all. | ||
1418 | */ | ||
1419 | callchain_cursor_reset(&callchain_cursor); | ||
1420 | return 1; | ||
1421 | } | ||
1422 | return 0; | ||
1423 | } | ||
1399 | thread__find_addr_location(thread, cpumode, MAP__FUNCTION, | 1424 | thread__find_addr_location(thread, cpumode, MAP__FUNCTION, |
1400 | ip, &al); | 1425 | ip, &al); |
1426 | } | ||
1427 | |||
1401 | if (al.sym != NULL) { | 1428 | if (al.sym != NULL) { |
1402 | if (sort__has_parent && !*parent && | 1429 | if (sort__has_parent && !*parent && |
1403 | symbol__match_regex(al.sym, &parent_regex)) | 1430 | symbol__match_regex(al.sym, &parent_regex)) |
@@ -1480,11 +1507,8 @@ static int thread__resolve_callchain_sample(struct thread *thread, | |||
1480 | struct addr_location *root_al, | 1507 | struct addr_location *root_al, |
1481 | int max_stack) | 1508 | int max_stack) |
1482 | { | 1509 | { |
1483 | u8 cpumode = PERF_RECORD_MISC_USER; | ||
1484 | int chain_nr = min(max_stack, (int)chain->nr); | 1510 | int chain_nr = min(max_stack, (int)chain->nr); |
1485 | int i; | 1511 | int i, j, err; |
1486 | int j; | ||
1487 | int err; | ||
1488 | int skip_idx = -1; | 1512 | int skip_idx = -1; |
1489 | int first_call = 0; | 1513 | int first_call = 0; |
1490 | 1514 | ||
@@ -1542,10 +1566,10 @@ static int thread__resolve_callchain_sample(struct thread *thread, | |||
1542 | 1566 | ||
1543 | for (i = 0; i < nr; i++) { | 1567 | for (i = 0; i < nr; i++) { |
1544 | err = add_callchain_ip(thread, parent, root_al, | 1568 | err = add_callchain_ip(thread, parent, root_al, |
1545 | -1, be[i].to); | 1569 | true, be[i].to); |
1546 | if (!err) | 1570 | if (!err) |
1547 | err = add_callchain_ip(thread, parent, root_al, | 1571 | err = add_callchain_ip(thread, parent, root_al, |
1548 | -1, be[i].from); | 1572 | true, be[i].from); |
1549 | if (err == -EINVAL) | 1573 | if (err == -EINVAL) |
1550 | break; | 1574 | break; |
1551 | if (err) | 1575 | if (err) |
@@ -1574,36 +1598,10 @@ check_calls: | |||
1574 | #endif | 1598 | #endif |
1575 | ip = chain->ips[j]; | 1599 | ip = chain->ips[j]; |
1576 | 1600 | ||
1577 | if (ip >= PERF_CONTEXT_MAX) { | 1601 | err = add_callchain_ip(thread, parent, root_al, false, ip); |
1578 | switch (ip) { | ||
1579 | case PERF_CONTEXT_HV: | ||
1580 | cpumode = PERF_RECORD_MISC_HYPERVISOR; | ||
1581 | break; | ||
1582 | case PERF_CONTEXT_KERNEL: | ||
1583 | cpumode = PERF_RECORD_MISC_KERNEL; | ||
1584 | break; | ||
1585 | case PERF_CONTEXT_USER: | ||
1586 | cpumode = PERF_RECORD_MISC_USER; | ||
1587 | break; | ||
1588 | default: | ||
1589 | pr_debug("invalid callchain context: " | ||
1590 | "%"PRId64"\n", (s64) ip); | ||
1591 | /* | ||
1592 | * It seems the callchain is corrupted. | ||
1593 | * Discard all. | ||
1594 | */ | ||
1595 | callchain_cursor_reset(&callchain_cursor); | ||
1596 | return 0; | ||
1597 | } | ||
1598 | continue; | ||
1599 | } | ||
1600 | 1602 | ||
1601 | err = add_callchain_ip(thread, parent, root_al, | ||
1602 | cpumode, ip); | ||
1603 | if (err == -EINVAL) | ||
1604 | break; | ||
1605 | if (err) | 1603 | if (err) |
1606 | return err; | 1604 | return (err < 0) ? err : 0; |
1607 | } | 1605 | } |
1608 | 1606 | ||
1609 | return 0; | 1607 | return 0; |
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/srcline.c b/tools/perf/util/srcline.c index e73b6a5c9e0f..c93fb0c5bd0b 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c | |||
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | struct a2l_data { | 21 | struct a2l_data { |
22 | const char *input; | 22 | const char *input; |
23 | unsigned long addr; | 23 | u64 addr; |
24 | 24 | ||
25 | bool found; | 25 | bool found; |
26 | const char *filename; | 26 | const char *filename; |
@@ -147,7 +147,7 @@ static void addr2line_cleanup(struct a2l_data *a2l) | |||
147 | free(a2l); | 147 | free(a2l); |
148 | } | 148 | } |
149 | 149 | ||
150 | static int addr2line(const char *dso_name, unsigned long addr, | 150 | static int addr2line(const char *dso_name, u64 addr, |
151 | char **file, unsigned int *line, struct dso *dso) | 151 | char **file, unsigned int *line, struct dso *dso) |
152 | { | 152 | { |
153 | int ret = 0; | 153 | int ret = 0; |
@@ -193,7 +193,7 @@ void dso__free_a2l(struct dso *dso) | |||
193 | 193 | ||
194 | #else /* HAVE_LIBBFD_SUPPORT */ | 194 | #else /* HAVE_LIBBFD_SUPPORT */ |
195 | 195 | ||
196 | static int addr2line(const char *dso_name, unsigned long addr, | 196 | static int addr2line(const char *dso_name, u64 addr, |
197 | char **file, unsigned int *line_nr, | 197 | char **file, unsigned int *line_nr, |
198 | struct dso *dso __maybe_unused) | 198 | struct dso *dso __maybe_unused) |
199 | { | 199 | { |
@@ -252,7 +252,7 @@ void dso__free_a2l(struct dso *dso __maybe_unused) | |||
252 | */ | 252 | */ |
253 | #define A2L_FAIL_LIMIT 123 | 253 | #define A2L_FAIL_LIMIT 123 |
254 | 254 | ||
255 | char *get_srcline(struct dso *dso, unsigned long addr, struct symbol *sym, | 255 | char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, |
256 | bool show_sym) | 256 | bool show_sym) |
257 | { | 257 | { |
258 | char *file = NULL; | 258 | char *file = NULL; |
@@ -293,10 +293,10 @@ out: | |||
293 | dso__free_a2l(dso); | 293 | dso__free_a2l(dso); |
294 | } | 294 | } |
295 | if (sym) { | 295 | if (sym) { |
296 | if (asprintf(&srcline, "%s+%ld", show_sym ? sym->name : "", | 296 | if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "", |
297 | addr - sym->start) < 0) | 297 | addr - sym->start) < 0) |
298 | return SRCLINE_UNKNOWN; | 298 | return SRCLINE_UNKNOWN; |
299 | } else if (asprintf(&srcline, "%s[%lx]", dso->short_name, addr) < 0) | 299 | } else if (asprintf(&srcline, "%s[%" PRIx64 "]", dso->short_name, addr) < 0) |
300 | return SRCLINE_UNKNOWN; | 300 | return SRCLINE_UNKNOWN; |
301 | return srcline; | 301 | return srcline; |
302 | } | 302 | } |
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index fa585c63f56a..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 | ||
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 419bee030f83..027a5153495c 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -153,7 +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 | 157 | ||
158 | 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) |
159 | { | 159 | { |
@@ -269,35 +269,6 @@ void event_attr_init(struct perf_event_attr *attr); | |||
269 | #define _STR(x) #x | 269 | #define _STR(x) #x |
270 | #define STR(x) _STR(x) | 270 | #define STR(x) _STR(x) |
271 | 271 | ||
272 | /* | ||
273 | * Determine whether some value is a power of two, where zero is | ||
274 | * *not* considered a power of two. | ||
275 | */ | ||
276 | |||
277 | static inline __attribute__((const)) | ||
278 | bool is_power_of_2(unsigned long n) | ||
279 | { | ||
280 | return (n != 0 && ((n & (n - 1)) == 0)); | ||
281 | } | ||
282 | |||
283 | static inline unsigned next_pow2(unsigned x) | ||
284 | { | ||
285 | if (!x) | ||
286 | return 1; | ||
287 | return 1ULL << (32 - __builtin_clz(x - 1)); | ||
288 | } | ||
289 | |||
290 | static inline unsigned long next_pow2_l(unsigned long x) | ||
291 | { | ||
292 | #if BITS_PER_LONG == 64 | ||
293 | if (x <= (1UL << 31)) | ||
294 | return next_pow2(x); | ||
295 | return (unsigned long)next_pow2(x >> 32) << 32; | ||
296 | #else | ||
297 | return next_pow2(x); | ||
298 | #endif | ||
299 | } | ||
300 | |||
301 | size_t hex_width(u64 v); | 272 | size_t hex_width(u64 v); |
302 | int hex2u64(const char *ptr, u64 *val); | 273 | int hex2u64(const char *ptr, u64 *val); |
303 | 274 | ||
@@ -339,11 +310,10 @@ static inline int path__join3(char *bf, size_t size, | |||
339 | struct dso; | 310 | struct dso; |
340 | struct symbol; | 311 | struct symbol; |
341 | 312 | ||
342 | char *get_srcline(struct dso *dso, unsigned long addr, struct symbol *sym, | 313 | char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, |
343 | bool show_sym); | 314 | bool show_sym); |
344 | void free_srcline(char *srcline); | 315 | void free_srcline(char *srcline); |
345 | 316 | ||
346 | int filename__read_int(const char *filename, int *value); | ||
347 | 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); |
348 | int perf_event_paranoid(void); | 318 | int perf_event_paranoid(void); |
349 | 319 | ||
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..33a5c06d95ca --- /dev/null +++ b/tools/testing/selftests/exec/execveat.c | |||
@@ -0,0 +1,397 @@ | |||
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) | ||
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 | printf("[FAIL] (child %d exited with %d not %d)\n", | ||
103 | child, WEXITSTATUS(status), expected_rc); | ||
104 | return 1; | ||
105 | } | ||
106 | printf("[OK]\n"); | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int check_execveat(int fd, const char *path, int flags) | ||
111 | { | ||
112 | return check_execveat_invoked_rc(fd, path, flags, 99); | ||
113 | } | ||
114 | |||
115 | static char *concat(const char *left, const char *right) | ||
116 | { | ||
117 | char *result = malloc(strlen(left) + strlen(right) + 1); | ||
118 | |||
119 | strcpy(result, left); | ||
120 | strcat(result, right); | ||
121 | return result; | ||
122 | } | ||
123 | |||
124 | static int open_or_die(const char *filename, int flags) | ||
125 | { | ||
126 | int fd = open(filename, flags); | ||
127 | |||
128 | if (fd < 0) { | ||
129 | printf("Failed to open '%s'; " | ||
130 | "check prerequisites are available\n", filename); | ||
131 | exit(1); | ||
132 | } | ||
133 | return fd; | ||
134 | } | ||
135 | |||
136 | static void exe_cp(const char *src, const char *dest) | ||
137 | { | ||
138 | int in_fd = open_or_die(src, O_RDONLY); | ||
139 | int out_fd = open(dest, O_RDWR|O_CREAT|O_TRUNC, 0755); | ||
140 | struct stat info; | ||
141 | |||
142 | fstat(in_fd, &info); | ||
143 | sendfile(out_fd, in_fd, NULL, info.st_size); | ||
144 | close(in_fd); | ||
145 | close(out_fd); | ||
146 | } | ||
147 | |||
148 | #define XX_DIR_LEN 200 | ||
149 | static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script) | ||
150 | { | ||
151 | int fail = 0; | ||
152 | int ii, count, len; | ||
153 | char longname[XX_DIR_LEN + 1]; | ||
154 | int fd; | ||
155 | |||
156 | if (*longpath == '\0') { | ||
157 | /* Create a filename close to PATH_MAX in length */ | ||
158 | memset(longname, 'x', XX_DIR_LEN - 1); | ||
159 | longname[XX_DIR_LEN - 1] = '/'; | ||
160 | longname[XX_DIR_LEN] = '\0'; | ||
161 | count = (PATH_MAX - 3) / XX_DIR_LEN; | ||
162 | for (ii = 0; ii < count; ii++) { | ||
163 | strcat(longpath, longname); | ||
164 | mkdir(longpath, 0755); | ||
165 | } | ||
166 | len = (PATH_MAX - 3) - (count * XX_DIR_LEN); | ||
167 | if (len <= 0) | ||
168 | len = 1; | ||
169 | memset(longname, 'y', len); | ||
170 | longname[len] = '\0'; | ||
171 | strcat(longpath, longname); | ||
172 | } | ||
173 | exe_cp(src, longpath); | ||
174 | |||
175 | /* | ||
176 | * Execute as a pre-opened file descriptor, which works whether this is | ||
177 | * a script or not (because the interpreter sees a filename like | ||
178 | * "/dev/fd/20"). | ||
179 | */ | ||
180 | fd = open(longpath, O_RDONLY); | ||
181 | if (fd > 0) { | ||
182 | printf("Invoke copy of '%s' via filename of length %lu:\n", | ||
183 | src, strlen(longpath)); | ||
184 | fail += check_execveat(fd, "", AT_EMPTY_PATH); | ||
185 | } else { | ||
186 | printf("Failed to open length %lu filename, errno=%d (%s)\n", | ||
187 | strlen(longpath), errno, strerror(errno)); | ||
188 | fail++; | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | * Execute as a long pathname relative to ".". If this is a script, | ||
193 | * the interpreter will launch but fail to open the script because its | ||
194 | * name ("/dev/fd/5/xxx....") is bigger than PATH_MAX. | ||
195 | */ | ||
196 | if (is_script) | ||
197 | fail += check_execveat_invoked_rc(dot_dfd, longpath, 0, 127); | ||
198 | else | ||
199 | fail += check_execveat(dot_dfd, longpath, 0); | ||
200 | |||
201 | return fail; | ||
202 | } | ||
203 | |||
204 | static int run_tests(void) | ||
205 | { | ||
206 | int fail = 0; | ||
207 | char *fullname = realpath("execveat", NULL); | ||
208 | char *fullname_script = realpath("script", NULL); | ||
209 | char *fullname_symlink = concat(fullname, ".symlink"); | ||
210 | int subdir_dfd = open_or_die("subdir", O_DIRECTORY|O_RDONLY); | ||
211 | int subdir_dfd_ephemeral = open_or_die("subdir.ephemeral", | ||
212 | O_DIRECTORY|O_RDONLY); | ||
213 | int dot_dfd = open_or_die(".", O_DIRECTORY|O_RDONLY); | ||
214 | int dot_dfd_path = open_or_die(".", O_DIRECTORY|O_RDONLY|O_PATH); | ||
215 | int dot_dfd_cloexec = open_or_die(".", O_DIRECTORY|O_RDONLY|O_CLOEXEC); | ||
216 | int fd = open_or_die("execveat", O_RDONLY); | ||
217 | int fd_path = open_or_die("execveat", O_RDONLY|O_PATH); | ||
218 | int fd_symlink = open_or_die("execveat.symlink", O_RDONLY); | ||
219 | int fd_denatured = open_or_die("execveat.denatured", O_RDONLY); | ||
220 | int fd_denatured_path = open_or_die("execveat.denatured", | ||
221 | O_RDONLY|O_PATH); | ||
222 | int fd_script = open_or_die("script", O_RDONLY); | ||
223 | int fd_ephemeral = open_or_die("execveat.ephemeral", O_RDONLY); | ||
224 | int fd_ephemeral_path = open_or_die("execveat.path.ephemeral", | ||
225 | O_RDONLY|O_PATH); | ||
226 | int fd_script_ephemeral = open_or_die("script.ephemeral", O_RDONLY); | ||
227 | int fd_cloexec = open_or_die("execveat", O_RDONLY|O_CLOEXEC); | ||
228 | int fd_script_cloexec = open_or_die("script", O_RDONLY|O_CLOEXEC); | ||
229 | |||
230 | /* Change file position to confirm it doesn't affect anything */ | ||
231 | lseek(fd, 10, SEEK_SET); | ||
232 | |||
233 | /* Normal executable file: */ | ||
234 | /* dfd + path */ | ||
235 | fail += check_execveat(subdir_dfd, "../execveat", 0); | ||
236 | fail += check_execveat(dot_dfd, "execveat", 0); | ||
237 | fail += check_execveat(dot_dfd_path, "execveat", 0); | ||
238 | /* absolute path */ | ||
239 | fail += check_execveat(AT_FDCWD, fullname, 0); | ||
240 | /* absolute path with nonsense dfd */ | ||
241 | fail += check_execveat(99, fullname, 0); | ||
242 | /* fd + no path */ | ||
243 | fail += check_execveat(fd, "", AT_EMPTY_PATH); | ||
244 | /* O_CLOEXEC fd + no path */ | ||
245 | fail += check_execveat(fd_cloexec, "", AT_EMPTY_PATH); | ||
246 | /* O_PATH fd */ | ||
247 | fail += check_execveat(fd_path, "", AT_EMPTY_PATH); | ||
248 | |||
249 | /* Mess with executable file that's already open: */ | ||
250 | /* fd + no path to a file that's been renamed */ | ||
251 | rename("execveat.ephemeral", "execveat.moved"); | ||
252 | fail += check_execveat(fd_ephemeral, "", AT_EMPTY_PATH); | ||
253 | /* fd + no path to a file that's been deleted */ | ||
254 | unlink("execveat.moved"); /* remove the file now fd open */ | ||
255 | fail += check_execveat(fd_ephemeral, "", AT_EMPTY_PATH); | ||
256 | |||
257 | /* Mess with executable file that's already open with O_PATH */ | ||
258 | /* fd + no path to a file that's been deleted */ | ||
259 | unlink("execveat.path.ephemeral"); | ||
260 | fail += check_execveat(fd_ephemeral_path, "", AT_EMPTY_PATH); | ||
261 | |||
262 | /* Invalid argument failures */ | ||
263 | fail += check_execveat_fail(fd, "", 0, ENOENT); | ||
264 | fail += check_execveat_fail(fd, NULL, AT_EMPTY_PATH, EFAULT); | ||
265 | |||
266 | /* Symlink to executable file: */ | ||
267 | /* dfd + path */ | ||
268 | fail += check_execveat(dot_dfd, "execveat.symlink", 0); | ||
269 | fail += check_execveat(dot_dfd_path, "execveat.symlink", 0); | ||
270 | /* absolute path */ | ||
271 | fail += check_execveat(AT_FDCWD, fullname_symlink, 0); | ||
272 | /* fd + no path, even with AT_SYMLINK_NOFOLLOW (already followed) */ | ||
273 | fail += check_execveat(fd_symlink, "", AT_EMPTY_PATH); | ||
274 | fail += check_execveat(fd_symlink, "", | ||
275 | AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW); | ||
276 | |||
277 | /* Symlink fails when AT_SYMLINK_NOFOLLOW set: */ | ||
278 | /* dfd + path */ | ||
279 | fail += check_execveat_fail(dot_dfd, "execveat.symlink", | ||
280 | AT_SYMLINK_NOFOLLOW, ELOOP); | ||
281 | fail += check_execveat_fail(dot_dfd_path, "execveat.symlink", | ||
282 | AT_SYMLINK_NOFOLLOW, ELOOP); | ||
283 | /* absolute path */ | ||
284 | fail += check_execveat_fail(AT_FDCWD, fullname_symlink, | ||
285 | AT_SYMLINK_NOFOLLOW, ELOOP); | ||
286 | |||
287 | /* Shell script wrapping executable file: */ | ||
288 | /* dfd + path */ | ||
289 | fail += check_execveat(subdir_dfd, "../script", 0); | ||
290 | fail += check_execveat(dot_dfd, "script", 0); | ||
291 | fail += check_execveat(dot_dfd_path, "script", 0); | ||
292 | /* absolute path */ | ||
293 | fail += check_execveat(AT_FDCWD, fullname_script, 0); | ||
294 | /* fd + no path */ | ||
295 | fail += check_execveat(fd_script, "", AT_EMPTY_PATH); | ||
296 | fail += check_execveat(fd_script, "", | ||
297 | AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW); | ||
298 | /* O_CLOEXEC fd fails for a script (as script file inaccessible) */ | ||
299 | fail += check_execveat_fail(fd_script_cloexec, "", AT_EMPTY_PATH, | ||
300 | ENOENT); | ||
301 | fail += check_execveat_fail(dot_dfd_cloexec, "script", 0, ENOENT); | ||
302 | |||
303 | /* Mess with script file that's already open: */ | ||
304 | /* fd + no path to a file that's been renamed */ | ||
305 | rename("script.ephemeral", "script.moved"); | ||
306 | fail += check_execveat(fd_script_ephemeral, "", AT_EMPTY_PATH); | ||
307 | /* fd + no path to a file that's been deleted */ | ||
308 | unlink("script.moved"); /* remove the file while fd open */ | ||
309 | fail += check_execveat(fd_script_ephemeral, "", AT_EMPTY_PATH); | ||
310 | |||
311 | /* Rename a subdirectory in the path: */ | ||
312 | rename("subdir.ephemeral", "subdir.moved"); | ||
313 | fail += check_execveat(subdir_dfd_ephemeral, "../script", 0); | ||
314 | fail += check_execveat(subdir_dfd_ephemeral, "script", 0); | ||
315 | /* Remove the subdir and its contents */ | ||
316 | unlink("subdir.moved/script"); | ||
317 | unlink("subdir.moved"); | ||
318 | /* Shell loads via deleted subdir OK because name starts with .. */ | ||
319 | fail += check_execveat(subdir_dfd_ephemeral, "../script", 0); | ||
320 | fail += check_execveat_fail(subdir_dfd_ephemeral, "script", 0, ENOENT); | ||
321 | |||
322 | /* Flag values other than AT_SYMLINK_NOFOLLOW => EINVAL */ | ||
323 | fail += check_execveat_fail(dot_dfd, "execveat", 0xFFFF, EINVAL); | ||
324 | /* Invalid path => ENOENT */ | ||
325 | fail += check_execveat_fail(dot_dfd, "no-such-file", 0, ENOENT); | ||
326 | fail += check_execveat_fail(dot_dfd_path, "no-such-file", 0, ENOENT); | ||
327 | fail += check_execveat_fail(AT_FDCWD, "no-such-file", 0, ENOENT); | ||
328 | /* Attempt to execute directory => EACCES */ | ||
329 | fail += check_execveat_fail(dot_dfd, "", AT_EMPTY_PATH, EACCES); | ||
330 | /* Attempt to execute non-executable => EACCES */ | ||
331 | fail += check_execveat_fail(dot_dfd, "Makefile", 0, EACCES); | ||
332 | fail += check_execveat_fail(fd_denatured, "", AT_EMPTY_PATH, EACCES); | ||
333 | fail += check_execveat_fail(fd_denatured_path, "", AT_EMPTY_PATH, | ||
334 | EACCES); | ||
335 | /* Attempt to execute nonsense FD => EBADF */ | ||
336 | fail += check_execveat_fail(99, "", AT_EMPTY_PATH, EBADF); | ||
337 | fail += check_execveat_fail(99, "execveat", 0, EBADF); | ||
338 | /* Attempt to execute relative to non-directory => ENOTDIR */ | ||
339 | fail += check_execveat_fail(fd, "execveat", 0, ENOTDIR); | ||
340 | |||
341 | fail += check_execveat_pathmax(dot_dfd, "execveat", 0); | ||
342 | fail += check_execveat_pathmax(dot_dfd, "script", 1); | ||
343 | return fail; | ||
344 | } | ||
345 | |||
346 | static void prerequisites(void) | ||
347 | { | ||
348 | int fd; | ||
349 | const char *script = "#!/bin/sh\nexit $*\n"; | ||
350 | |||
351 | /* Create ephemeral copies of files */ | ||
352 | exe_cp("execveat", "execveat.ephemeral"); | ||
353 | exe_cp("execveat", "execveat.path.ephemeral"); | ||
354 | exe_cp("script", "script.ephemeral"); | ||
355 | mkdir("subdir.ephemeral", 0755); | ||
356 | |||
357 | fd = open("subdir.ephemeral/script", O_RDWR|O_CREAT|O_TRUNC, 0755); | ||
358 | write(fd, script, strlen(script)); | ||
359 | close(fd); | ||
360 | } | ||
361 | |||
362 | int main(int argc, char **argv) | ||
363 | { | ||
364 | int ii; | ||
365 | int rc; | ||
366 | const char *verbose = getenv("VERBOSE"); | ||
367 | |||
368 | if (argc >= 2) { | ||
369 | /* If we are invoked with an argument, don't run tests. */ | ||
370 | const char *in_test = getenv("IN_TEST"); | ||
371 | |||
372 | if (verbose) { | ||
373 | printf(" invoked with:"); | ||
374 | for (ii = 0; ii < argc; ii++) | ||
375 | printf(" [%d]='%s'", ii, argv[ii]); | ||
376 | printf("\n"); | ||
377 | } | ||
378 | |||
379 | /* Check expected environment transferred. */ | ||
380 | if (!in_test || strcmp(in_test, "yes") != 0) { | ||
381 | printf("[FAIL] (no IN_TEST=yes in env)\n"); | ||
382 | return 1; | ||
383 | } | ||
384 | |||
385 | /* Use the final argument as an exit code. */ | ||
386 | rc = atoi(argv[argc - 1]); | ||
387 | fflush(stdout); | ||
388 | } else { | ||
389 | prerequisites(); | ||
390 | if (verbose) | ||
391 | envp[1] = "VERBOSE=1"; | ||
392 | rc = run_tests(); | ||
393 | if (rc > 0) | ||
394 | printf("%d tests failed\n", rc); | ||
395 | } | ||
396 | return rc; | ||
397 | } | ||
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/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/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/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 | } | ||