aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-12-18 01:23:55 -0500
committerIngo Molnar <mingo@kernel.org>2014-12-18 01:23:55 -0500
commit6aaba7c9011e0d34cf520808467bd7eb36e51b4c (patch)
treed8e8763a585680ce52245c93c764f3eff124f3df /tools/perf
parent41e950c033b7df997d4b38653efe6554be9b96a7 (diff)
parent7ad74b41e56e4f7f42c6b765bc44428cd09310d7 (diff)
Merge tag 'perf-core-for-mingo-2' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: - The mmap address range for the ring buffer now is calculated using the contents of /proc/sys/kernel/perf_event_mlock_kb. This fixes an -EPERM case where 'trace' was trying to use more than what is configured on perf_event_mlock_kb. (Arnaldo Carvalho de Melo) Infrastructure changes: - Move bitops definitions so that they match the header file hierarchy in the kernel sources where that code came from. (Arnaldo Carvalho de Melo) - Adopt round{down,up}_pow_of_two from the kernel and use it instead of equivalent code, so that we reuse more kernel code and make tools/ look more like kernel source code, to encourage further contributions from kernel hackers (Arnaldo Carvalho de Melo) - Fix use after free in filename__read_build_id (Mitchell Krome) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/MANIFEST16
-rw-r--r--tools/perf/Makefile.perf14
-rw-r--r--tools/perf/builtin-trace.c2
-rw-r--r--tools/perf/util/evlist.c46
-rw-r--r--tools/perf/util/include/linux/bitops.h162
-rw-r--r--tools/perf/util/symbol-minimal.c8
-rw-r--r--tools/perf/util/util.h29
7 files changed, 70 insertions, 207 deletions
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
4tools/lib/api 4tools/lib/api
5tools/lib/symbol/kallsyms.c 5tools/lib/symbol/kallsyms.c
6tools/lib/symbol/kallsyms.h 6tools/lib/symbol/kallsyms.h
7tools/lib/util/find_next_bit.c
7tools/include/asm/bug.h 8tools/include/asm/bug.h
9tools/include/asm-generic/bitops/atomic.h
10tools/include/asm-generic/bitops/__ffs.h
11tools/include/asm-generic/bitops/__fls.h
12tools/include/asm-generic/bitops/find.h
13tools/include/asm-generic/bitops/fls64.h
14tools/include/asm-generic/bitops/fls.h
15tools/include/asm-generic/bitops.h
16tools/include/linux/bitops.h
8tools/include/linux/compiler.h 17tools/include/linux/compiler.h
9tools/include/linux/hash.h
10tools/include/linux/export.h 18tools/include/linux/export.h
19tools/include/linux/hash.h
20tools/include/linux/log2.h
11tools/include/linux/types.h 21tools/include/linux/types.h
22include/asm-generic/bitops/fls64.h
23include/asm-generic/bitops/__fls.h
24include/asm-generic/bitops/fls.h
12include/linux/const.h 25include/linux/const.h
13include/linux/perf_event.h 26include/linux/perf_event.h
14include/linux/rbtree.h 27include/linux/rbtree.h
15include/linux/list.h 28include/linux/list.h
16include/linux/hash.h 29include/linux/hash.h
17include/linux/stringify.h 30include/linux/stringify.h
31lib/find_next_bit.c
18lib/rbtree.c 32lib/rbtree.c
19include/linux/swab.h 33include/linux/swab.h
20arch/*/include/asm/unistd*.h 34arch/*/include/asm/unistd*.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 763e68fb5767..67a03a825b3c 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -231,8 +231,16 @@ LIB_H += ../../include/uapi/linux/const.h
231LIB_H += ../include/linux/hash.h 231LIB_H += ../include/linux/hash.h
232LIB_H += ../../include/linux/stringify.h 232LIB_H += ../../include/linux/stringify.h
233LIB_H += util/include/linux/bitmap.h 233LIB_H += util/include/linux/bitmap.h
234LIB_H += util/include/linux/bitops.h 234LIB_H += ../include/linux/bitops.h
235LIB_H += ../include/asm-generic/bitops/atomic.h
236LIB_H += ../include/asm-generic/bitops/find.h
237LIB_H += ../include/asm-generic/bitops/fls64.h
238LIB_H += ../include/asm-generic/bitops/fls.h
239LIB_H += ../include/asm-generic/bitops/__ffs.h
240LIB_H += ../include/asm-generic/bitops/__fls.h
241LIB_H += ../include/asm-generic/bitops.h
235LIB_H += ../include/linux/compiler.h 242LIB_H += ../include/linux/compiler.h
243LIB_H += ../include/linux/log2.h
236LIB_H += util/include/linux/const.h 244LIB_H += util/include/linux/const.h
237LIB_H += util/include/linux/ctype.h 245LIB_H += util/include/linux/ctype.h
238LIB_H += util/include/linux/kernel.h 246LIB_H += util/include/linux/kernel.h
@@ -335,6 +343,7 @@ LIB_OBJS += $(OUTPUT)util/event.o
335LIB_OBJS += $(OUTPUT)util/evlist.o 343LIB_OBJS += $(OUTPUT)util/evlist.o
336LIB_OBJS += $(OUTPUT)util/evsel.o 344LIB_OBJS += $(OUTPUT)util/evsel.o
337LIB_OBJS += $(OUTPUT)util/exec_cmd.o 345LIB_OBJS += $(OUTPUT)util/exec_cmd.o
346LIB_OBJS += $(OUTPUT)util/find_next_bit.o
338LIB_OBJS += $(OUTPUT)util/help.o 347LIB_OBJS += $(OUTPUT)util/help.o
339LIB_OBJS += $(OUTPUT)util/kallsyms.o 348LIB_OBJS += $(OUTPUT)util/kallsyms.o
340LIB_OBJS += $(OUTPUT)util/levenshtein.o 349LIB_OBJS += $(OUTPUT)util/levenshtein.o
@@ -734,6 +743,9 @@ $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS
734$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 743$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
735 $(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)"' $<
736 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
737$(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
738 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $< 750 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
739 751
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 327541e43c7f..badfabc6a01f 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -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/util/evlist.c b/tools/perf/util/evlist.c
index bb5dfc5d1e75..cbab1fb77b1d 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -25,6 +25,7 @@
25 25
26#include <linux/bitops.h> 26#include <linux/bitops.h>
27#include <linux/hash.h> 27#include <linux/hash.h>
28#include <linux/log2.h>
28 29
29static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx); 30static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
30static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx); 31static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
@@ -893,10 +894,24 @@ out_unmap:
893 894
894static size_t perf_evlist__mmap_size(unsigned long pages) 895static size_t perf_evlist__mmap_size(unsigned long pages)
895{ 896{
896 /* 512 kiB: default amount of unprivileged mlocked memory */ 897 if (pages == UINT_MAX) {
897 if (pages == UINT_MAX) 898 int max;
898 pages = (512 * 1024) / page_size; 899
899 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))
900 return 0; 915 return 0;
901 916
902 return (pages + 1) * page_size; 917 return (pages + 1) * page_size;
@@ -933,7 +948,7 @@ static long parse_pages_arg(const char *str, unsigned long min,
933 /* leave number of pages at 0 */ 948 /* leave number of pages at 0 */
934 } else if (!is_power_of_2(pages)) { 949 } else if (!is_power_of_2(pages)) {
935 /* round pages up to next power of 2 */ 950 /* round pages up to next power of 2 */
936 pages = next_pow2_l(pages); 951 pages = roundup_pow_of_two(pages);
937 if (!pages) 952 if (!pages)
938 return -EINVAL; 953 return -EINVAL;
939 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",
@@ -1487,16 +1502,25 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1487int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size) 1502int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size)
1488{ 1503{
1489 char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); 1504 char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
1490 int value; 1505 int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0;
1491 1506
1492 switch (err) { 1507 switch (err) {
1493 case EPERM: 1508 case EPERM:
1494 sysctl__read_int("kernel/perf_event_mlock_kb", &value); 1509 sysctl__read_int("kernel/perf_event_mlock_kb", &pages_max_per_user);
1495 scnprintf(buf, size, "Error:\t%s.\n" 1510 printed += scnprintf(buf + printed, size - printed,
1511 "Error:\t%s.\n"
1496 "Hint:\tCheck /proc/sys/kernel/perf_event_mlock_kb (%d kB) setting.\n" 1512 "Hint:\tCheck /proc/sys/kernel/perf_event_mlock_kb (%d kB) setting.\n"
1497 "Hint:\tTried using %zd kB.\n" 1513 "Hint:\tTried using %zd kB.\n",
1498 "Hint:\tTry using a bigger -m/--mmap-pages value.", 1514 emsg, pages_max_per_user, pages_attempted);
1499 emsg, value, evlist->mmap_len / 1024); 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.");
1500 break; 1524 break;
1501 default: 1525 default:
1502 scnprintf(buf, size, "%s", emsg); 1526 scnprintf(buf, size, "%s", emsg);
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
32static inline void set_bit(int nr, unsigned long *addr)
33{
34 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
35}
36
37static inline void clear_bit(int nr, unsigned long *addr)
38{
39 addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG));
40}
41
42static __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
48static 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 */
61static __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
92typedef const unsigned long __attribute__((__may_alias__)) long_alias_t;
93
94/*
95 * Find the first set bit in a memory region.
96 */
97static inline unsigned long
98find_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. */
116found:
117 return result + __ffs(tmp);
118}
119
120/*
121 * Find the next set bit in a memory region.
122 */
123static inline unsigned long
124find_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
154found_first:
155 tmp &= (~0UL >> (BITS_PER_LONG - size));
156 if (tmp == 0UL) /* Are any bits set? */
157 return result + size; /* Nope. */
158found_middle:
159 return result + __ffs(tmp);
160}
161
162#endif
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.h b/tools/perf/util/util.h
index 008b361b1758..be198ac27031 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -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
277static inline __attribute__((const))
278bool is_power_of_2(unsigned long n)
279{
280 return (n != 0 && ((n & (n - 1)) == 0));
281}
282
283static inline unsigned next_pow2(unsigned x)
284{
285 if (!x)
286 return 1;
287 return 1ULL << (32 - __builtin_clz(x - 1));
288}
289
290static 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
301size_t hex_width(u64 v); 272size_t hex_width(u64 v);
302int hex2u64(const char *ptr, u64 *val); 273int hex2u64(const char *ptr, u64 *val);
303 274