diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-19 16:15:24 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-19 16:15:24 -0500 |
| commit | 88a57667f2990f00b019d46c8426441c9e516d51 (patch) | |
| tree | 392f5dcb9724e688aa307e2ed2cc8ee13e66f570 /tools/perf/util | |
| parent | 34b85e3574424beb30e4cd163e6da2e2282d2683 (diff) | |
| parent | ac931f87a647ca156f65a4c00e7297165e4fa2d8 (diff) | |
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes and cleanups from Ingo Molnar:
"A kernel fix plus mostly tooling fixes, but also some tooling
restructuring and cleanups"
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (39 commits)
perf: Fix building warning on ARM 32
perf symbols: Fix use after free in filename__read_build_id
perf evlist: Use roundup_pow_of_two
tools: Adopt roundup_pow_of_two
perf tools: Make the mmap length autotuning more robust
tools: Adopt rounddown_pow_of_two and deps
tools: Adopt fls_long and deps
tools: Move bitops.h from tools/perf/util to tools/
tools: Introduce asm-generic/bitops.h
tools lib: Move asm-generic/bitops/find.h code to tools/include and tools/lib
tools: Whitespace prep patches for moving bitops.h
tools: Move code originally from asm-generic/atomic.h into tools/include/asm-generic/
tools: Move code originally from linux/log2.h to tools/include/linux/
tools: Move __ffs implementation to tools/include/asm-generic/bitops/__ffs.h
perf evlist: Do not use hard coded value for a mmap_pages default
perf trace: Let the perf_evlist__mmap autosize the number of pages to use
perf evlist: Improve the strerror_mmap method
perf evlist: Clarify sterror_mmap variable names
perf evlist: Fixup brown paper bag on "hint" for --mmap-pages cmdline arg
perf trace: Provide a better explanation when mmap fails
...
Diffstat (limited to 'tools/perf/util')
| -rw-r--r-- | tools/perf/util/build-id.c | 9 | ||||
| -rw-r--r-- | tools/perf/util/callchain.c | 2 | ||||
| -rw-r--r-- | tools/perf/util/config.c | 10 | ||||
| -rw-r--r-- | tools/perf/util/evlist.c | 57 | ||||
| -rw-r--r-- | tools/perf/util/evlist.h | 1 | ||||
| -rw-r--r-- | tools/perf/util/include/linux/bitops.h | 162 | ||||
| -rw-r--r-- | tools/perf/util/machine.c | 72 | ||||
| -rw-r--r-- | tools/perf/util/record.c | 11 | ||||
| -rw-r--r-- | tools/perf/util/srcline.c | 12 | ||||
| -rw-r--r-- | tools/perf/util/symbol-minimal.c | 8 | ||||
| -rw-r--r-- | tools/perf/util/util.c | 26 | ||||
| -rw-r--r-- | tools/perf/util/util.h | 34 |
12 files changed, 114 insertions, 290 deletions
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/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 | ||
