diff options
| author | Ingo Molnar <mingo@kernel.org> | 2012-07-06 04:17:40 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2012-07-06 04:22:46 -0400 |
| commit | 387ef4e24af4ae43a7961ba6eec749488da99535 (patch) | |
| tree | bdd6995a544bce7401562afbd70ffd27e2b5a083 /tools/perf | |
| parent | 6a67943a18c264d5f3df436da38edb3e59adc905 (diff) | |
| parent | 81e9b994bb20716d1f6c47e048e4ae4a43de2f83 (diff) | |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
perf/core improvements and fixes:
- Preparatory patches to use hw events in PMU syntax, from Jiri Olsa
- Remaining backport of trace-cmd's libparseevent, from Namhyung Kim
- Fix libtraceevent 'clean' make target, from Namhyung Kim
- Teach ctags about libtraceevent error codes, from Namhyung Kim
- Fix libtraceevent dependency files usage, from Namhyung Kim
- Support hex number pretty printing in libtraceevent, fixing
kvm output, from Namhyung Kim
- Kill some die() usage in libtraceevent, from Namhyung Kim
- Improve support for hw breakpoints parsing/pretty printing/testing,
from Jiri Olsa
- Clarify perf bench option naming, from Hitoshi Mitake
- Look for ".note" ELF notes too, used in the kernel vdso, from Jiri Olsa
- Fix internal PMU list usage, removing leak, from Robert Richter
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/Documentation/perf-bench.txt | 4 | ||||
| -rw-r--r-- | tools/perf/bench/mem-memcpy.c | 80 | ||||
| -rw-r--r-- | tools/perf/bench/mem-memset.c | 80 | ||||
| -rw-r--r-- | tools/perf/util/evsel.c | 30 | ||||
| -rw-r--r-- | tools/perf/util/include/linux/kernel.h | 10 | ||||
| -rw-r--r-- | tools/perf/util/parse-events-test.c | 76 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.c | 194 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.l | 5 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.y | 15 | ||||
| -rw-r--r-- | tools/perf/util/pmu.c | 3 | ||||
| -rw-r--r-- | tools/perf/util/scripting-engines/trace-event-perl.c | 4 | ||||
| -rw-r--r-- | tools/perf/util/scripting-engines/trace-event-python.c | 4 | ||||
| -rw-r--r-- | tools/perf/util/symbol.c | 29 |
13 files changed, 357 insertions, 177 deletions
diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt index f3c716a4cad..7065cd6fbdf 100644 --- a/tools/perf/Documentation/perf-bench.txt +++ b/tools/perf/Documentation/perf-bench.txt | |||
| @@ -144,7 +144,7 @@ On x86-64, x86-64-unrolled, x86-64-movsq and x86-64-movsb are supported. | |||
| 144 | Repeat memcpy invocation this number of times. | 144 | Repeat memcpy invocation this number of times. |
| 145 | 145 | ||
| 146 | -c:: | 146 | -c:: |
| 147 | --clock:: | 147 | --cycle:: |
| 148 | Use perf's cpu-cycles event instead of gettimeofday syscall. | 148 | Use perf's cpu-cycles event instead of gettimeofday syscall. |
| 149 | 149 | ||
| 150 | -o:: | 150 | -o:: |
| @@ -176,7 +176,7 @@ On x86-64, x86-64-unrolled, x86-64-stosq and x86-64-stosb are supported. | |||
| 176 | Repeat memset invocation this number of times. | 176 | Repeat memset invocation this number of times. |
| 177 | 177 | ||
| 178 | -c:: | 178 | -c:: |
| 179 | --clock:: | 179 | --cycle:: |
| 180 | Use perf's cpu-cycles event instead of gettimeofday syscall. | 180 | Use perf's cpu-cycles event instead of gettimeofday syscall. |
| 181 | 181 | ||
| 182 | -o:: | 182 | -o:: |
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c index d990365cafa..02dad5d3359 100644 --- a/tools/perf/bench/mem-memcpy.c +++ b/tools/perf/bench/mem-memcpy.c | |||
| @@ -24,8 +24,8 @@ | |||
| 24 | static const char *length_str = "1MB"; | 24 | static const char *length_str = "1MB"; |
| 25 | static const char *routine = "default"; | 25 | static const char *routine = "default"; |
| 26 | static int iterations = 1; | 26 | static int iterations = 1; |
| 27 | static bool use_clock; | 27 | static bool use_cycle; |
| 28 | static int clock_fd; | 28 | static int cycle_fd; |
| 29 | static bool only_prefault; | 29 | static bool only_prefault; |
| 30 | static bool no_prefault; | 30 | static bool no_prefault; |
| 31 | 31 | ||
| @@ -37,7 +37,7 @@ static const struct option options[] = { | |||
| 37 | "Specify routine to copy"), | 37 | "Specify routine to copy"), |
| 38 | OPT_INTEGER('i', "iterations", &iterations, | 38 | OPT_INTEGER('i', "iterations", &iterations, |
| 39 | "repeat memcpy() invocation this number of times"), | 39 | "repeat memcpy() invocation this number of times"), |
| 40 | OPT_BOOLEAN('c', "clock", &use_clock, | 40 | OPT_BOOLEAN('c', "cycle", &use_cycle, |
| 41 | "Use cycles event instead of gettimeofday() for measuring"), | 41 | "Use cycles event instead of gettimeofday() for measuring"), |
| 42 | OPT_BOOLEAN('o', "only-prefault", &only_prefault, | 42 | OPT_BOOLEAN('o', "only-prefault", &only_prefault, |
| 43 | "Show only the result with page faults before memcpy()"), | 43 | "Show only the result with page faults before memcpy()"), |
| @@ -76,27 +76,27 @@ static const char * const bench_mem_memcpy_usage[] = { | |||
| 76 | NULL | 76 | NULL |
| 77 | }; | 77 | }; |
| 78 | 78 | ||
| 79 | static struct perf_event_attr clock_attr = { | 79 | static struct perf_event_attr cycle_attr = { |
| 80 | .type = PERF_TYPE_HARDWARE, | 80 | .type = PERF_TYPE_HARDWARE, |
| 81 | .config = PERF_COUNT_HW_CPU_CYCLES | 81 | .config = PERF_COUNT_HW_CPU_CYCLES |
| 82 | }; | 82 | }; |
| 83 | 83 | ||
| 84 | static void init_clock(void) | 84 | static void init_cycle(void) |
| 85 | { | 85 | { |
| 86 | clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0); | 86 | cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0); |
| 87 | 87 | ||
| 88 | if (clock_fd < 0 && errno == ENOSYS) | 88 | if (cycle_fd < 0 && errno == ENOSYS) |
| 89 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); | 89 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); |
| 90 | else | 90 | else |
| 91 | BUG_ON(clock_fd < 0); | 91 | BUG_ON(cycle_fd < 0); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | static u64 get_clock(void) | 94 | static u64 get_cycle(void) |
| 95 | { | 95 | { |
| 96 | int ret; | 96 | int ret; |
| 97 | u64 clk; | 97 | u64 clk; |
| 98 | 98 | ||
| 99 | ret = read(clock_fd, &clk, sizeof(u64)); | 99 | ret = read(cycle_fd, &clk, sizeof(u64)); |
| 100 | BUG_ON(ret != sizeof(u64)); | 100 | BUG_ON(ret != sizeof(u64)); |
| 101 | 101 | ||
| 102 | return clk; | 102 | return clk; |
| @@ -119,9 +119,9 @@ static void alloc_mem(void **dst, void **src, size_t length) | |||
| 119 | die("memory allocation failed - maybe length is too large?\n"); | 119 | die("memory allocation failed - maybe length is too large?\n"); |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault) | 122 | static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault) |
| 123 | { | 123 | { |
| 124 | u64 clock_start = 0ULL, clock_end = 0ULL; | 124 | u64 cycle_start = 0ULL, cycle_end = 0ULL; |
| 125 | void *src = NULL, *dst = NULL; | 125 | void *src = NULL, *dst = NULL; |
| 126 | int i; | 126 | int i; |
| 127 | 127 | ||
| @@ -130,14 +130,14 @@ static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault) | |||
| 130 | if (prefault) | 130 | if (prefault) |
| 131 | fn(dst, src, len); | 131 | fn(dst, src, len); |
| 132 | 132 | ||
| 133 | clock_start = get_clock(); | 133 | cycle_start = get_cycle(); |
| 134 | for (i = 0; i < iterations; ++i) | 134 | for (i = 0; i < iterations; ++i) |
| 135 | fn(dst, src, len); | 135 | fn(dst, src, len); |
| 136 | clock_end = get_clock(); | 136 | cycle_end = get_cycle(); |
| 137 | 137 | ||
| 138 | free(src); | 138 | free(src); |
| 139 | free(dst); | 139 | free(dst); |
| 140 | return clock_end - clock_start; | 140 | return cycle_end - cycle_start; |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault) | 143 | static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault) |
| @@ -182,17 +182,17 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
| 182 | int i; | 182 | int i; |
| 183 | size_t len; | 183 | size_t len; |
| 184 | double result_bps[2]; | 184 | double result_bps[2]; |
| 185 | u64 result_clock[2]; | 185 | u64 result_cycle[2]; |
| 186 | 186 | ||
| 187 | argc = parse_options(argc, argv, options, | 187 | argc = parse_options(argc, argv, options, |
| 188 | bench_mem_memcpy_usage, 0); | 188 | bench_mem_memcpy_usage, 0); |
| 189 | 189 | ||
| 190 | if (use_clock) | 190 | if (use_cycle) |
| 191 | init_clock(); | 191 | init_cycle(); |
| 192 | 192 | ||
| 193 | len = (size_t)perf_atoll((char *)length_str); | 193 | len = (size_t)perf_atoll((char *)length_str); |
| 194 | 194 | ||
| 195 | result_clock[0] = result_clock[1] = 0ULL; | 195 | result_cycle[0] = result_cycle[1] = 0ULL; |
| 196 | result_bps[0] = result_bps[1] = 0.0; | 196 | result_bps[0] = result_bps[1] = 0.0; |
| 197 | 197 | ||
| 198 | if ((s64)len <= 0) { | 198 | if ((s64)len <= 0) { |
| @@ -223,11 +223,11 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
| 223 | 223 | ||
| 224 | if (!only_prefault && !no_prefault) { | 224 | if (!only_prefault && !no_prefault) { |
| 225 | /* show both of results */ | 225 | /* show both of results */ |
| 226 | if (use_clock) { | 226 | if (use_cycle) { |
| 227 | result_clock[0] = | 227 | result_cycle[0] = |
| 228 | do_memcpy_clock(routines[i].fn, len, false); | 228 | do_memcpy_cycle(routines[i].fn, len, false); |
| 229 | result_clock[1] = | 229 | result_cycle[1] = |
| 230 | do_memcpy_clock(routines[i].fn, len, true); | 230 | do_memcpy_cycle(routines[i].fn, len, true); |
| 231 | } else { | 231 | } else { |
| 232 | result_bps[0] = | 232 | result_bps[0] = |
| 233 | do_memcpy_gettimeofday(routines[i].fn, | 233 | do_memcpy_gettimeofday(routines[i].fn, |
| @@ -237,9 +237,9 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
| 237 | len, true); | 237 | len, true); |
| 238 | } | 238 | } |
| 239 | } else { | 239 | } else { |
| 240 | if (use_clock) { | 240 | if (use_cycle) { |
| 241 | result_clock[pf] = | 241 | result_cycle[pf] = |
| 242 | do_memcpy_clock(routines[i].fn, | 242 | do_memcpy_cycle(routines[i].fn, |
| 243 | len, only_prefault); | 243 | len, only_prefault); |
| 244 | } else { | 244 | } else { |
| 245 | result_bps[pf] = | 245 | result_bps[pf] = |
| @@ -251,12 +251,12 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
| 251 | switch (bench_format) { | 251 | switch (bench_format) { |
| 252 | case BENCH_FORMAT_DEFAULT: | 252 | case BENCH_FORMAT_DEFAULT: |
| 253 | if (!only_prefault && !no_prefault) { | 253 | if (!only_prefault && !no_prefault) { |
| 254 | if (use_clock) { | 254 | if (use_cycle) { |
| 255 | printf(" %14lf Clock/Byte\n", | 255 | printf(" %14lf Cycle/Byte\n", |
| 256 | (double)result_clock[0] | 256 | (double)result_cycle[0] |
| 257 | / (double)len); | 257 | / (double)len); |
| 258 | printf(" %14lf Clock/Byte (with prefault)\n", | 258 | printf(" %14lf Cycle/Byte (with prefault)\n", |
| 259 | (double)result_clock[1] | 259 | (double)result_cycle[1] |
| 260 | / (double)len); | 260 | / (double)len); |
| 261 | } else { | 261 | } else { |
| 262 | print_bps(result_bps[0]); | 262 | print_bps(result_bps[0]); |
| @@ -265,9 +265,9 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
| 265 | printf(" (with prefault)\n"); | 265 | printf(" (with prefault)\n"); |
| 266 | } | 266 | } |
| 267 | } else { | 267 | } else { |
| 268 | if (use_clock) { | 268 | if (use_cycle) { |
| 269 | printf(" %14lf Clock/Byte", | 269 | printf(" %14lf Cycle/Byte", |
| 270 | (double)result_clock[pf] | 270 | (double)result_cycle[pf] |
| 271 | / (double)len); | 271 | / (double)len); |
| 272 | } else | 272 | } else |
| 273 | print_bps(result_bps[pf]); | 273 | print_bps(result_bps[pf]); |
| @@ -277,17 +277,17 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
| 277 | break; | 277 | break; |
| 278 | case BENCH_FORMAT_SIMPLE: | 278 | case BENCH_FORMAT_SIMPLE: |
| 279 | if (!only_prefault && !no_prefault) { | 279 | if (!only_prefault && !no_prefault) { |
| 280 | if (use_clock) { | 280 | if (use_cycle) { |
| 281 | printf("%lf %lf\n", | 281 | printf("%lf %lf\n", |
| 282 | (double)result_clock[0] / (double)len, | 282 | (double)result_cycle[0] / (double)len, |
| 283 | (double)result_clock[1] / (double)len); | 283 | (double)result_cycle[1] / (double)len); |
| 284 | } else { | 284 | } else { |
| 285 | printf("%lf %lf\n", | 285 | printf("%lf %lf\n", |
| 286 | result_bps[0], result_bps[1]); | 286 | result_bps[0], result_bps[1]); |
| 287 | } | 287 | } |
| 288 | } else { | 288 | } else { |
| 289 | if (use_clock) { | 289 | if (use_cycle) { |
| 290 | printf("%lf\n", (double)result_clock[pf] | 290 | printf("%lf\n", (double)result_cycle[pf] |
| 291 | / (double)len); | 291 | / (double)len); |
| 292 | } else | 292 | } else |
| 293 | printf("%lf\n", result_bps[pf]); | 293 | printf("%lf\n", result_bps[pf]); |
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c index bf0d5f55201..350cc955726 100644 --- a/tools/perf/bench/mem-memset.c +++ b/tools/perf/bench/mem-memset.c | |||
| @@ -24,8 +24,8 @@ | |||
| 24 | static const char *length_str = "1MB"; | 24 | static const char *length_str = "1MB"; |
| 25 | static const char *routine = "default"; | 25 | static const char *routine = "default"; |
| 26 | static int iterations = 1; | 26 | static int iterations = 1; |
| 27 | static bool use_clock; | 27 | static bool use_cycle; |
| 28 | static int clock_fd; | 28 | static int cycle_fd; |
| 29 | static bool only_prefault; | 29 | static bool only_prefault; |
| 30 | static bool no_prefault; | 30 | static bool no_prefault; |
| 31 | 31 | ||
| @@ -37,7 +37,7 @@ static const struct option options[] = { | |||
| 37 | "Specify routine to set"), | 37 | "Specify routine to set"), |
| 38 | OPT_INTEGER('i', "iterations", &iterations, | 38 | OPT_INTEGER('i', "iterations", &iterations, |
| 39 | "repeat memset() invocation this number of times"), | 39 | "repeat memset() invocation this number of times"), |
| 40 | OPT_BOOLEAN('c', "clock", &use_clock, | 40 | OPT_BOOLEAN('c', "cycle", &use_cycle, |
| 41 | "Use cycles event instead of gettimeofday() for measuring"), | 41 | "Use cycles event instead of gettimeofday() for measuring"), |
| 42 | OPT_BOOLEAN('o', "only-prefault", &only_prefault, | 42 | OPT_BOOLEAN('o', "only-prefault", &only_prefault, |
| 43 | "Show only the result with page faults before memset()"), | 43 | "Show only the result with page faults before memset()"), |
| @@ -76,27 +76,27 @@ static const char * const bench_mem_memset_usage[] = { | |||
| 76 | NULL | 76 | NULL |
| 77 | }; | 77 | }; |
| 78 | 78 | ||
| 79 | static struct perf_event_attr clock_attr = { | 79 | static struct perf_event_attr cycle_attr = { |
| 80 | .type = PERF_TYPE_HARDWARE, | 80 | .type = PERF_TYPE_HARDWARE, |
| 81 | .config = PERF_COUNT_HW_CPU_CYCLES | 81 | .config = PERF_COUNT_HW_CPU_CYCLES |
| 82 | }; | 82 | }; |
| 83 | 83 | ||
| 84 | static void init_clock(void) | 84 | static void init_cycle(void) |
| 85 | { | 85 | { |
| 86 | clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0); | 86 | cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0); |
| 87 | 87 | ||
| 88 | if (clock_fd < 0 && errno == ENOSYS) | 88 | if (cycle_fd < 0 && errno == ENOSYS) |
| 89 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); | 89 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); |
| 90 | else | 90 | else |
| 91 | BUG_ON(clock_fd < 0); | 91 | BUG_ON(cycle_fd < 0); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | static u64 get_clock(void) | 94 | static u64 get_cycle(void) |
| 95 | { | 95 | { |
| 96 | int ret; | 96 | int ret; |
| 97 | u64 clk; | 97 | u64 clk; |
| 98 | 98 | ||
| 99 | ret = read(clock_fd, &clk, sizeof(u64)); | 99 | ret = read(cycle_fd, &clk, sizeof(u64)); |
| 100 | BUG_ON(ret != sizeof(u64)); | 100 | BUG_ON(ret != sizeof(u64)); |
| 101 | 101 | ||
| 102 | return clk; | 102 | return clk; |
| @@ -115,9 +115,9 @@ static void alloc_mem(void **dst, size_t length) | |||
| 115 | die("memory allocation failed - maybe length is too large?\n"); | 115 | die("memory allocation failed - maybe length is too large?\n"); |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | static u64 do_memset_clock(memset_t fn, size_t len, bool prefault) | 118 | static u64 do_memset_cycle(memset_t fn, size_t len, bool prefault) |
| 119 | { | 119 | { |
| 120 | u64 clock_start = 0ULL, clock_end = 0ULL; | 120 | u64 cycle_start = 0ULL, cycle_end = 0ULL; |
| 121 | void *dst = NULL; | 121 | void *dst = NULL; |
| 122 | int i; | 122 | int i; |
| 123 | 123 | ||
| @@ -126,13 +126,13 @@ static u64 do_memset_clock(memset_t fn, size_t len, bool prefault) | |||
| 126 | if (prefault) | 126 | if (prefault) |
| 127 | fn(dst, -1, len); | 127 | fn(dst, -1, len); |
| 128 | 128 | ||
| 129 | clock_start = get_clock(); | 129 | cycle_start = get_cycle(); |
| 130 | for (i = 0; i < iterations; ++i) | 130 | for (i = 0; i < iterations; ++i) |
| 131 | fn(dst, i, len); | 131 | fn(dst, i, len); |
| 132 | clock_end = get_clock(); | 132 | cycle_end = get_cycle(); |
| 133 | 133 | ||
| 134 | free(dst); | 134 | free(dst); |
| 135 | return clock_end - clock_start; | 135 | return cycle_end - cycle_start; |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault) | 138 | static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault) |
| @@ -176,17 +176,17 @@ int bench_mem_memset(int argc, const char **argv, | |||
| 176 | int i; | 176 | int i; |
| 177 | size_t len; | 177 | size_t len; |
| 178 | double result_bps[2]; | 178 | double result_bps[2]; |
| 179 | u64 result_clock[2]; | 179 | u64 result_cycle[2]; |
| 180 | 180 | ||
| 181 | argc = parse_options(argc, argv, options, | 181 | argc = parse_options(argc, argv, options, |
| 182 | bench_mem_memset_usage, 0); | 182 | bench_mem_memset_usage, 0); |
| 183 | 183 | ||
| 184 | if (use_clock) | 184 | if (use_cycle) |
| 185 | init_clock(); | 185 | init_cycle(); |
| 186 | 186 | ||
| 187 | len = (size_t)perf_atoll((char *)length_str); | 187 | len = (size_t)perf_atoll((char *)length_str); |
| 188 | 188 | ||
| 189 | result_clock[0] = result_clock[1] = 0ULL; | 189 | result_cycle[0] = result_cycle[1] = 0ULL; |
| 190 | result_bps[0] = result_bps[1] = 0.0; | 190 | result_bps[0] = result_bps[1] = 0.0; |
| 191 | 191 | ||
| 192 | if ((s64)len <= 0) { | 192 | if ((s64)len <= 0) { |
| @@ -217,11 +217,11 @@ int bench_mem_memset(int argc, const char **argv, | |||
| 217 | 217 | ||
| 218 | if (!only_prefault && !no_prefault) { | 218 | if (!only_prefault && !no_prefault) { |
| 219 | /* show both of results */ | 219 | /* show both of results */ |
| 220 | if (use_clock) { | 220 | if (use_cycle) { |
| 221 | result_clock[0] = | 221 | result_cycle[0] = |
| 222 | do_memset_clock(routines[i].fn, len, false); | 222 | do_memset_cycle(routines[i].fn, len, false); |
| 223 | result_clock[1] = | 223 | result_cycle[1] = |
| 224 | do_memset_clock(routines[i].fn, len, true); | 224 | do_memset_cycle(routines[i].fn, len, true); |
| 225 | } else { | 225 | } else { |
| 226 | result_bps[0] = | 226 | result_bps[0] = |
| 227 | do_memset_gettimeofday(routines[i].fn, | 227 | do_memset_gettimeofday(routines[i].fn, |
| @@ -231,9 +231,9 @@ int bench_mem_memset(int argc, const char **argv, | |||
| 231 | len, true); | 231 | len, true); |
| 232 | } | 232 | } |
| 233 | } else { | 233 | } else { |
| 234 | if (use_clock) { | 234 | if (use_cycle) { |
| 235 | result_clock[pf] = | 235 | result_cycle[pf] = |
| 236 | do_memset_clock(routines[i].fn, | 236 | do_memset_cycle(routines[i].fn, |
| 237 | len, only_prefault); | 237 | len, only_prefault); |
| 238 | } else { | 238 | } else { |
| 239 | result_bps[pf] = | 239 | result_bps[pf] = |
| @@ -245,12 +245,12 @@ int bench_mem_memset(int argc, const char **argv, | |||
| 245 | switch (bench_format) { | 245 | switch (bench_format) { |
| 246 | case BENCH_FORMAT_DEFAULT: | 246 | case BENCH_FORMAT_DEFAULT: |
| 247 | if (!only_prefault && !no_prefault) { | 247 | if (!only_prefault && !no_prefault) { |
| 248 | if (use_clock) { | 248 | if (use_cycle) { |
| 249 | printf(" %14lf Clock/Byte\n", | 249 | printf(" %14lf Cycle/Byte\n", |
| 250 | (double)result_clock[0] | 250 | (double)result_cycle[0] |
| 251 | / (double)len); | 251 | / (double)len); |
| 252 | printf(" %14lf Clock/Byte (with prefault)\n ", | 252 | printf(" %14lf Cycle/Byte (with prefault)\n ", |
| 253 | (double)result_clock[1] | 253 | (double)result_cycle[1] |
| 254 | / (double)len); | 254 | / (double)len); |
| 255 | } else { | 255 | } else { |
| 256 | print_bps(result_bps[0]); | 256 | print_bps(result_bps[0]); |
| @@ -259,9 +259,9 @@ int bench_mem_memset(int argc, const char **argv, | |||
| 259 | printf(" (with prefault)\n"); | 259 | printf(" (with prefault)\n"); |
| 260 | } | 260 | } |
| 261 | } else { | 261 | } else { |
| 262 | if (use_clock) { | 262 | if (use_cycle) { |
| 263 | printf(" %14lf Clock/Byte", | 263 | printf(" %14lf Cycle/Byte", |
| 264 | (double)result_clock[pf] | 264 | (double)result_cycle[pf] |
| 265 | / (double)len); | 265 | / (double)len); |
| 266 | } else | 266 | } else |
| 267 | print_bps(result_bps[pf]); | 267 | print_bps(result_bps[pf]); |
| @@ -271,17 +271,17 @@ int bench_mem_memset(int argc, const char **argv, | |||
| 271 | break; | 271 | break; |
| 272 | case BENCH_FORMAT_SIMPLE: | 272 | case BENCH_FORMAT_SIMPLE: |
| 273 | if (!only_prefault && !no_prefault) { | 273 | if (!only_prefault && !no_prefault) { |
| 274 | if (use_clock) { | 274 | if (use_cycle) { |
| 275 | printf("%lf %lf\n", | 275 | printf("%lf %lf\n", |
| 276 | (double)result_clock[0] / (double)len, | 276 | (double)result_cycle[0] / (double)len, |
| 277 | (double)result_clock[1] / (double)len); | 277 | (double)result_cycle[1] / (double)len); |
| 278 | } else { | 278 | } else { |
| 279 | printf("%lf %lf\n", | 279 | printf("%lf %lf\n", |
| 280 | result_bps[0], result_bps[1]); | 280 | result_bps[0], result_bps[1]); |
| 281 | } | 281 | } |
| 282 | } else { | 282 | } else { |
| 283 | if (use_clock) { | 283 | if (use_cycle) { |
| 284 | printf("%lf\n", (double)result_clock[pf] | 284 | printf("%lf\n", (double)result_cycle[pf] |
| 285 | / (double)len); | 285 | / (double)len); |
| 286 | } else | 286 | } else |
| 287 | printf("%lf\n", result_bps[pf]); | 287 | printf("%lf\n", result_bps[pf]); |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 3d1f6968f17..e8177136486 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "cpumap.h" | 15 | #include "cpumap.h" |
| 16 | #include "thread_map.h" | 16 | #include "thread_map.h" |
| 17 | #include "target.h" | 17 | #include "target.h" |
| 18 | #include "../../../include/linux/hw_breakpoint.h" | ||
| 18 | 19 | ||
| 19 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | 20 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) |
| 20 | #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) | 21 | #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) |
| @@ -152,6 +153,31 @@ static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size) | |||
| 152 | return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); | 153 | return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); |
| 153 | } | 154 | } |
| 154 | 155 | ||
| 156 | static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type) | ||
| 157 | { | ||
| 158 | int r; | ||
| 159 | |||
| 160 | r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr); | ||
| 161 | |||
| 162 | if (type & HW_BREAKPOINT_R) | ||
| 163 | r += scnprintf(bf + r, size - r, "r"); | ||
| 164 | |||
| 165 | if (type & HW_BREAKPOINT_W) | ||
| 166 | r += scnprintf(bf + r, size - r, "w"); | ||
| 167 | |||
| 168 | if (type & HW_BREAKPOINT_X) | ||
| 169 | r += scnprintf(bf + r, size - r, "x"); | ||
| 170 | |||
| 171 | return r; | ||
| 172 | } | ||
| 173 | |||
| 174 | static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size) | ||
| 175 | { | ||
| 176 | struct perf_event_attr *attr = &evsel->attr; | ||
| 177 | int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type); | ||
| 178 | return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); | ||
| 179 | } | ||
| 180 | |||
| 155 | const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] | 181 | const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] |
| 156 | [PERF_EVSEL__MAX_ALIASES] = { | 182 | [PERF_EVSEL__MAX_ALIASES] = { |
| 157 | { "L1-dcache", "l1-d", "l1d", "L1-data", }, | 183 | { "L1-dcache", "l1-d", "l1d", "L1-data", }, |
| @@ -285,6 +311,10 @@ const char *perf_evsel__name(struct perf_evsel *evsel) | |||
| 285 | scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint"); | 311 | scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint"); |
| 286 | break; | 312 | break; |
| 287 | 313 | ||
| 314 | case PERF_TYPE_BREAKPOINT: | ||
| 315 | perf_evsel__bp_name(evsel, bf, sizeof(bf)); | ||
| 316 | break; | ||
| 317 | |||
| 288 | default: | 318 | default: |
| 289 | scnprintf(bf, sizeof(bf), "%s", "unknown attr type"); | 319 | scnprintf(bf, sizeof(bf), "%s", "unknown attr type"); |
| 290 | break; | 320 | break; |
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h index 1eb804fd3fb..b6842c1d02a 100644 --- a/tools/perf/util/include/linux/kernel.h +++ b/tools/perf/util/include/linux/kernel.h | |||
| @@ -108,4 +108,14 @@ int eprintf(int level, | |||
| 108 | #define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) | 108 | #define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) |
| 109 | #define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) | 109 | #define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) |
| 110 | 110 | ||
| 111 | /* | ||
| 112 | * This looks more complex than it should be. But we need to | ||
| 113 | * get the type for the ~ right in round_down (it needs to be | ||
| 114 | * as wide as the result!), and we want to evaluate the macro | ||
| 115 | * arguments just once each. | ||
| 116 | */ | ||
| 117 | #define __round_mask(x, y) ((__typeof__(x))((y)-1)) | ||
| 118 | #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) | ||
| 119 | #define round_down(x, y) ((x) & ~__round_mask(x, y)) | ||
| 120 | |||
| 111 | #endif | 121 | #endif |
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c index a0f61a2a683..1b997d2b89c 100644 --- a/tools/perf/util/parse-events-test.c +++ b/tools/perf/util/parse-events-test.c | |||
| @@ -181,6 +181,22 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist) | |||
| 181 | return 0; | 181 | return 0; |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist) | ||
| 185 | { | ||
| 186 | struct perf_evsel *evsel = list_entry(evlist->entries.next, | ||
| 187 | struct perf_evsel, node); | ||
| 188 | |||
| 189 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
| 190 | TEST_ASSERT_VAL("wrong type", | ||
| 191 | PERF_TYPE_BREAKPOINT == evsel->attr.type); | ||
| 192 | TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); | ||
| 193 | TEST_ASSERT_VAL("wrong bp_type", | ||
| 194 | (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->attr.bp_type); | ||
| 195 | TEST_ASSERT_VAL("wrong bp_len", | ||
| 196 | HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len); | ||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | |||
| 184 | static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) | 200 | static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) |
| 185 | { | 201 | { |
| 186 | struct perf_evsel *evsel = list_entry(evlist->entries.next, | 202 | struct perf_evsel *evsel = list_entry(evlist->entries.next, |
| @@ -309,6 +325,8 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) | |||
| 309 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | 325 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); |
| 310 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | 326 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); |
| 311 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | 327 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); |
| 328 | TEST_ASSERT_VAL("wrong name", | ||
| 329 | !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u")); | ||
| 312 | 330 | ||
| 313 | return test__checkevent_breakpoint(evlist); | 331 | return test__checkevent_breakpoint(evlist); |
| 314 | } | 332 | } |
| @@ -322,6 +340,8 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist) | |||
| 322 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | 340 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); |
| 323 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | 341 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); |
| 324 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | 342 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); |
| 343 | TEST_ASSERT_VAL("wrong name", | ||
| 344 | !strcmp(perf_evsel__name(evsel), "mem:0x0:x:k")); | ||
| 325 | 345 | ||
| 326 | return test__checkevent_breakpoint_x(evlist); | 346 | return test__checkevent_breakpoint_x(evlist); |
| 327 | } | 347 | } |
| @@ -335,6 +355,8 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist) | |||
| 335 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | 355 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); |
| 336 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | 356 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); |
| 337 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); | 357 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); |
| 358 | TEST_ASSERT_VAL("wrong name", | ||
| 359 | !strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp")); | ||
| 338 | 360 | ||
| 339 | return test__checkevent_breakpoint_r(evlist); | 361 | return test__checkevent_breakpoint_r(evlist); |
| 340 | } | 362 | } |
| @@ -348,10 +370,27 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist) | |||
| 348 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | 370 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); |
| 349 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | 371 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); |
| 350 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); | 372 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); |
| 373 | TEST_ASSERT_VAL("wrong name", | ||
| 374 | !strcmp(perf_evsel__name(evsel), "mem:0x0:w:up")); | ||
| 351 | 375 | ||
| 352 | return test__checkevent_breakpoint_w(evlist); | 376 | return test__checkevent_breakpoint_w(evlist); |
| 353 | } | 377 | } |
| 354 | 378 | ||
| 379 | static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist) | ||
| 380 | { | ||
| 381 | struct perf_evsel *evsel = list_entry(evlist->entries.next, | ||
| 382 | struct perf_evsel, node); | ||
| 383 | |||
| 384 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
| 385 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
| 386 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
| 387 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); | ||
| 388 | TEST_ASSERT_VAL("wrong name", | ||
| 389 | !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp")); | ||
| 390 | |||
| 391 | return test__checkevent_breakpoint_rw(evlist); | ||
| 392 | } | ||
| 393 | |||
| 355 | static int test__checkevent_pmu(struct perf_evlist *evlist) | 394 | static int test__checkevent_pmu(struct perf_evlist *evlist) |
| 356 | { | 395 | { |
| 357 | 396 | ||
| @@ -585,10 +624,16 @@ static struct test__event_st test__events[] = { | |||
| 585 | .name = "instructions:H", | 624 | .name = "instructions:H", |
| 586 | .check = test__checkevent_exclude_guest_modifier, | 625 | .check = test__checkevent_exclude_guest_modifier, |
| 587 | }, | 626 | }, |
| 627 | [26] = { | ||
| 628 | .name = "mem:0:rw", | ||
| 629 | .check = test__checkevent_breakpoint_rw, | ||
| 630 | }, | ||
| 631 | [27] = { | ||
| 632 | .name = "mem:0:rw:kp", | ||
| 633 | .check = test__checkevent_breakpoint_rw_modifier, | ||
| 634 | }, | ||
| 588 | }; | 635 | }; |
| 589 | 636 | ||
| 590 | #define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st)) | ||
| 591 | |||
| 592 | static struct test__event_st test__events_pmu[] = { | 637 | static struct test__event_st test__events_pmu[] = { |
| 593 | [0] = { | 638 | [0] = { |
| 594 | .name = "cpu/config=10,config1,config2=3,period=1000/u", | 639 | .name = "cpu/config=10,config1,config2=3,period=1000/u", |
| @@ -600,9 +645,6 @@ static struct test__event_st test__events_pmu[] = { | |||
| 600 | }, | 645 | }, |
| 601 | }; | 646 | }; |
| 602 | 647 | ||
| 603 | #define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \ | ||
| 604 | sizeof(struct test__event_st)) | ||
| 605 | |||
| 606 | struct test__term { | 648 | struct test__term { |
| 607 | const char *str; | 649 | const char *str; |
| 608 | __u32 type; | 650 | __u32 type; |
| @@ -718,21 +760,17 @@ int parse_events__test(void) | |||
| 718 | { | 760 | { |
| 719 | int ret; | 761 | int ret; |
| 720 | 762 | ||
| 721 | do { | 763 | #define TEST_EVENTS(tests) \ |
| 722 | ret = test_events(test__events, TEST__EVENTS_CNT); | 764 | do { \ |
| 723 | if (ret) | 765 | ret = test_events(tests, ARRAY_SIZE(tests)); \ |
| 724 | break; | 766 | if (ret) \ |
| 725 | 767 | return ret; \ | |
| 726 | if (test_pmu()) { | 768 | } while (0) |
| 727 | ret = test_events(test__events_pmu, | ||
| 728 | TEST__EVENTS_PMU_CNT); | ||
| 729 | if (ret) | ||
| 730 | break; | ||
| 731 | } | ||
| 732 | 769 | ||
| 733 | ret = test_terms(test__terms, TEST__TERMS_CNT); | 770 | TEST_EVENTS(test__events); |
| 734 | 771 | ||
| 735 | } while (0); | 772 | if (test_pmu()) |
| 773 | TEST_EVENTS(test__events_pmu); | ||
| 736 | 774 | ||
| 737 | return ret; | 775 | return test_terms(test__terms, ARRAY_SIZE(test__terms)); |
| 738 | } | 776 | } |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 0cc27da30dd..1aa721d7c10 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
| @@ -19,8 +19,6 @@ | |||
| 19 | #define MAX_NAME_LEN 100 | 19 | #define MAX_NAME_LEN 100 |
| 20 | 20 | ||
| 21 | struct event_symbol { | 21 | struct event_symbol { |
| 22 | u8 type; | ||
| 23 | u64 config; | ||
| 24 | const char *symbol; | 22 | const char *symbol; |
| 25 | const char *alias; | 23 | const char *alias; |
| 26 | }; | 24 | }; |
| @@ -30,30 +28,86 @@ extern int parse_events_debug; | |||
| 30 | #endif | 28 | #endif |
| 31 | int parse_events_parse(void *data, void *scanner); | 29 | int parse_events_parse(void *data, void *scanner); |
| 32 | 30 | ||
| 33 | #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x | 31 | static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { |
| 34 | #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x | 32 | [PERF_COUNT_HW_CPU_CYCLES] = { |
| 35 | 33 | .symbol = "cpu-cycles", | |
| 36 | static struct event_symbol event_symbols[] = { | 34 | .alias = "cycles", |
| 37 | { CHW(CPU_CYCLES), "cpu-cycles", "cycles" }, | 35 | }, |
| 38 | { CHW(STALLED_CYCLES_FRONTEND), "stalled-cycles-frontend", "idle-cycles-frontend" }, | 36 | [PERF_COUNT_HW_INSTRUCTIONS] = { |
| 39 | { CHW(STALLED_CYCLES_BACKEND), "stalled-cycles-backend", "idle-cycles-backend" }, | 37 | .symbol = "instructions", |
| 40 | { CHW(INSTRUCTIONS), "instructions", "" }, | 38 | .alias = "", |
| 41 | { CHW(CACHE_REFERENCES), "cache-references", "" }, | 39 | }, |
| 42 | { CHW(CACHE_MISSES), "cache-misses", "" }, | 40 | [PERF_COUNT_HW_CACHE_REFERENCES] = { |
| 43 | { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, | 41 | .symbol = "cache-references", |
| 44 | { CHW(BRANCH_MISSES), "branch-misses", "" }, | 42 | .alias = "", |
| 45 | { CHW(BUS_CYCLES), "bus-cycles", "" }, | 43 | }, |
| 46 | { CHW(REF_CPU_CYCLES), "ref-cycles", "" }, | 44 | [PERF_COUNT_HW_CACHE_MISSES] = { |
| 47 | 45 | .symbol = "cache-misses", | |
| 48 | { CSW(CPU_CLOCK), "cpu-clock", "" }, | 46 | .alias = "", |
| 49 | { CSW(TASK_CLOCK), "task-clock", "" }, | 47 | }, |
| 50 | { CSW(PAGE_FAULTS), "page-faults", "faults" }, | 48 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { |
| 51 | { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, | 49 | .symbol = "branch-instructions", |
| 52 | { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, | 50 | .alias = "branches", |
| 53 | { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, | 51 | }, |
| 54 | { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, | 52 | [PERF_COUNT_HW_BRANCH_MISSES] = { |
| 55 | { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" }, | 53 | .symbol = "branch-misses", |
| 56 | { CSW(EMULATION_FAULTS), "emulation-faults", "" }, | 54 | .alias = "", |
| 55 | }, | ||
| 56 | [PERF_COUNT_HW_BUS_CYCLES] = { | ||
| 57 | .symbol = "bus-cycles", | ||
| 58 | .alias = "", | ||
| 59 | }, | ||
| 60 | [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = { | ||
| 61 | .symbol = "stalled-cycles-frontend", | ||
| 62 | .alias = "idle-cycles-frontend", | ||
| 63 | }, | ||
| 64 | [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = { | ||
| 65 | .symbol = "stalled-cycles-backend", | ||
| 66 | .alias = "idle-cycles-backend", | ||
| 67 | }, | ||
| 68 | [PERF_COUNT_HW_REF_CPU_CYCLES] = { | ||
| 69 | .symbol = "ref-cycles", | ||
| 70 | .alias = "", | ||
| 71 | }, | ||
| 72 | }; | ||
| 73 | |||
| 74 | static struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { | ||
| 75 | [PERF_COUNT_SW_CPU_CLOCK] = { | ||
| 76 | .symbol = "cpu-clock", | ||
| 77 | .alias = "", | ||
| 78 | }, | ||
| 79 | [PERF_COUNT_SW_TASK_CLOCK] = { | ||
| 80 | .symbol = "task-clock", | ||
| 81 | .alias = "", | ||
| 82 | }, | ||
| 83 | [PERF_COUNT_SW_PAGE_FAULTS] = { | ||
| 84 | .symbol = "page-faults", | ||
| 85 | .alias = "faults", | ||
| 86 | }, | ||
| 87 | [PERF_COUNT_SW_CONTEXT_SWITCHES] = { | ||
| 88 | .symbol = "context-switches", | ||
| 89 | .alias = "cs", | ||
| 90 | }, | ||
| 91 | [PERF_COUNT_SW_CPU_MIGRATIONS] = { | ||
| 92 | .symbol = "cpu-migrations", | ||
| 93 | .alias = "migrations", | ||
| 94 | }, | ||
| 95 | [PERF_COUNT_SW_PAGE_FAULTS_MIN] = { | ||
| 96 | .symbol = "minor-faults", | ||
| 97 | .alias = "", | ||
| 98 | }, | ||
| 99 | [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = { | ||
| 100 | .symbol = "major-faults", | ||
| 101 | .alias = "", | ||
| 102 | }, | ||
| 103 | [PERF_COUNT_SW_ALIGNMENT_FAULTS] = { | ||
| 104 | .symbol = "alignment-faults", | ||
| 105 | .alias = "", | ||
| 106 | }, | ||
| 107 | [PERF_COUNT_SW_EMULATION_FAULTS] = { | ||
| 108 | .symbol = "emulation-faults", | ||
| 109 | .alias = "", | ||
| 110 | }, | ||
| 57 | }; | 111 | }; |
| 58 | 112 | ||
| 59 | #define __PERF_EVENT_FIELD(config, name) \ | 113 | #define __PERF_EVENT_FIELD(config, name) \ |
| @@ -383,21 +437,31 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr) | |||
| 383 | if (!type || !type[i]) | 437 | if (!type || !type[i]) |
| 384 | break; | 438 | break; |
| 385 | 439 | ||
| 440 | #define CHECK_SET_TYPE(bit) \ | ||
| 441 | do { \ | ||
| 442 | if (attr->bp_type & bit) \ | ||
| 443 | return -EINVAL; \ | ||
| 444 | else \ | ||
| 445 | attr->bp_type |= bit; \ | ||
| 446 | } while (0) | ||
| 447 | |||
| 386 | switch (type[i]) { | 448 | switch (type[i]) { |
| 387 | case 'r': | 449 | case 'r': |
| 388 | attr->bp_type |= HW_BREAKPOINT_R; | 450 | CHECK_SET_TYPE(HW_BREAKPOINT_R); |
| 389 | break; | 451 | break; |
| 390 | case 'w': | 452 | case 'w': |
| 391 | attr->bp_type |= HW_BREAKPOINT_W; | 453 | CHECK_SET_TYPE(HW_BREAKPOINT_W); |
| 392 | break; | 454 | break; |
| 393 | case 'x': | 455 | case 'x': |
| 394 | attr->bp_type |= HW_BREAKPOINT_X; | 456 | CHECK_SET_TYPE(HW_BREAKPOINT_X); |
| 395 | break; | 457 | break; |
| 396 | default: | 458 | default: |
| 397 | return -EINVAL; | 459 | return -EINVAL; |
| 398 | } | 460 | } |
| 399 | } | 461 | } |
| 400 | 462 | ||
| 463 | #undef CHECK_SET_TYPE | ||
| 464 | |||
| 401 | if (!attr->bp_type) /* Default */ | 465 | if (!attr->bp_type) /* Default */ |
| 402 | attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; | 466 | attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; |
| 403 | 467 | ||
| @@ -408,7 +472,6 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx, | |||
| 408 | void *ptr, char *type) | 472 | void *ptr, char *type) |
| 409 | { | 473 | { |
| 410 | struct perf_event_attr attr; | 474 | struct perf_event_attr attr; |
| 411 | char name[MAX_NAME_LEN]; | ||
| 412 | 475 | ||
| 413 | memset(&attr, 0, sizeof(attr)); | 476 | memset(&attr, 0, sizeof(attr)); |
| 414 | attr.bp_addr = (unsigned long) ptr; | 477 | attr.bp_addr = (unsigned long) ptr; |
| @@ -427,8 +490,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx, | |||
| 427 | 490 | ||
| 428 | attr.type = PERF_TYPE_BREAKPOINT; | 491 | attr.type = PERF_TYPE_BREAKPOINT; |
| 429 | 492 | ||
| 430 | snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw"); | 493 | return add_event(list, idx, &attr, NULL); |
| 431 | return add_event(list, idx, &attr, name); | ||
| 432 | } | 494 | } |
| 433 | 495 | ||
| 434 | static int config_term(struct perf_event_attr *attr, | 496 | static int config_term(struct perf_event_attr *attr, |
| @@ -816,16 +878,13 @@ int is_valid_tracepoint(const char *event_string) | |||
| 816 | return 0; | 878 | return 0; |
| 817 | } | 879 | } |
| 818 | 880 | ||
| 819 | void print_events_type(u8 type) | 881 | static void __print_events_type(u8 type, struct event_symbol *syms, |
| 882 | unsigned max) | ||
| 820 | { | 883 | { |
| 821 | struct event_symbol *syms = event_symbols; | ||
| 822 | unsigned int i; | ||
| 823 | char name[64]; | 884 | char name[64]; |
| 885 | unsigned i; | ||
| 824 | 886 | ||
| 825 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { | 887 | for (i = 0; i < max ; i++, syms++) { |
| 826 | if (type != syms->type) | ||
| 827 | continue; | ||
| 828 | |||
| 829 | if (strlen(syms->alias)) | 888 | if (strlen(syms->alias)) |
| 830 | snprintf(name, sizeof(name), "%s OR %s", | 889 | snprintf(name, sizeof(name), "%s OR %s", |
| 831 | syms->symbol, syms->alias); | 890 | syms->symbol, syms->alias); |
| @@ -837,6 +896,14 @@ void print_events_type(u8 type) | |||
| 837 | } | 896 | } |
| 838 | } | 897 | } |
| 839 | 898 | ||
| 899 | void print_events_type(u8 type) | ||
| 900 | { | ||
| 901 | if (type == PERF_TYPE_SOFTWARE) | ||
| 902 | __print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX); | ||
| 903 | else | ||
| 904 | __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX); | ||
| 905 | } | ||
| 906 | |||
| 840 | int print_hwcache_events(const char *event_glob) | 907 | int print_hwcache_events(const char *event_glob) |
| 841 | { | 908 | { |
| 842 | unsigned int type, op, i, printed = 0; | 909 | unsigned int type, op, i, printed = 0; |
| @@ -864,26 +931,13 @@ int print_hwcache_events(const char *event_glob) | |||
| 864 | return printed; | 931 | return printed; |
| 865 | } | 932 | } |
| 866 | 933 | ||
| 867 | /* | 934 | static void print_symbol_events(const char *event_glob, unsigned type, |
| 868 | * Print the help text for the event symbols: | 935 | struct event_symbol *syms, unsigned max) |
| 869 | */ | ||
| 870 | void print_events(const char *event_glob) | ||
| 871 | { | 936 | { |
| 872 | unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0; | 937 | unsigned i, printed = 0; |
| 873 | struct event_symbol *syms = event_symbols; | ||
| 874 | char name[MAX_NAME_LEN]; | 938 | char name[MAX_NAME_LEN]; |
| 875 | 939 | ||
| 876 | printf("\n"); | 940 | for (i = 0; i < max; i++, syms++) { |
| 877 | printf("List of pre-defined events (to be used in -e):\n"); | ||
| 878 | |||
| 879 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { | ||
| 880 | type = syms->type; | ||
| 881 | |||
| 882 | if (type != prev_type && printed) { | ||
| 883 | printf("\n"); | ||
| 884 | printed = 0; | ||
| 885 | ntypes_printed++; | ||
| 886 | } | ||
| 887 | 941 | ||
| 888 | if (event_glob != NULL && | 942 | if (event_glob != NULL && |
| 889 | !(strglobmatch(syms->symbol, event_glob) || | 943 | !(strglobmatch(syms->symbol, event_glob) || |
| @@ -894,17 +948,31 @@ void print_events(const char *event_glob) | |||
| 894 | snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); | 948 | snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); |
| 895 | else | 949 | else |
| 896 | strncpy(name, syms->symbol, MAX_NAME_LEN); | 950 | strncpy(name, syms->symbol, MAX_NAME_LEN); |
| 897 | printf(" %-50s [%s]\n", name, | ||
| 898 | event_type_descriptors[type]); | ||
| 899 | 951 | ||
| 900 | prev_type = type; | 952 | printf(" %-50s [%s]\n", name, event_type_descriptors[type]); |
| 901 | ++printed; | 953 | |
| 954 | printed++; | ||
| 902 | } | 955 | } |
| 903 | 956 | ||
| 904 | if (ntypes_printed) { | 957 | if (printed) |
| 905 | printed = 0; | ||
| 906 | printf("\n"); | 958 | printf("\n"); |
| 907 | } | 959 | } |
| 960 | |||
| 961 | /* | ||
| 962 | * Print the help text for the event symbols: | ||
| 963 | */ | ||
| 964 | void print_events(const char *event_glob) | ||
| 965 | { | ||
| 966 | |||
| 967 | printf("\n"); | ||
| 968 | printf("List of pre-defined events (to be used in -e):\n"); | ||
| 969 | |||
| 970 | print_symbol_events(event_glob, PERF_TYPE_HARDWARE, | ||
| 971 | event_symbols_hw, PERF_COUNT_HW_MAX); | ||
| 972 | |||
| 973 | print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, | ||
| 974 | event_symbols_sw, PERF_COUNT_SW_MAX); | ||
| 975 | |||
| 908 | print_hwcache_events(event_glob); | 976 | print_hwcache_events(event_glob); |
| 909 | 977 | ||
| 910 | if (event_glob != NULL) | 978 | if (event_glob != NULL) |
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 488362e1413..384ca74c6b2 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l | |||
| @@ -56,7 +56,7 @@ static int sym(yyscan_t scanner, int type, int config) | |||
| 56 | YYSTYPE *yylval = parse_events_get_lval(scanner); | 56 | YYSTYPE *yylval = parse_events_get_lval(scanner); |
| 57 | 57 | ||
| 58 | yylval->num = (type << 16) + config; | 58 | yylval->num = (type << 16) + config; |
| 59 | return PE_VALUE_SYM; | 59 | return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | static int term(yyscan_t scanner, int type) | 62 | static int term(yyscan_t scanner, int type) |
| @@ -76,7 +76,7 @@ num_hex 0x[a-fA-F0-9]+ | |||
| 76 | num_raw_hex [a-fA-F0-9]+ | 76 | num_raw_hex [a-fA-F0-9]+ |
| 77 | name [a-zA-Z_*?][a-zA-Z0-9_*?]* | 77 | name [a-zA-Z_*?][a-zA-Z0-9_*?]* |
| 78 | modifier_event [ukhpGH]{1,8} | 78 | modifier_event [ukhpGH]{1,8} |
| 79 | modifier_bp [rwx] | 79 | modifier_bp [rwx]{1,3} |
| 80 | 80 | ||
| 81 | %% | 81 | %% |
| 82 | 82 | ||
| @@ -152,6 +152,7 @@ r{num_raw_hex} { return raw(yyscanner); } | |||
| 152 | , { return ','; } | 152 | , { return ','; } |
| 153 | : { return ':'; } | 153 | : { return ':'; } |
| 154 | = { return '='; } | 154 | = { return '='; } |
| 155 | \n { } | ||
| 155 | 156 | ||
| 156 | <mem>{ | 157 | <mem>{ |
| 157 | {modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); } | 158 | {modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); } |
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 9525c455d27..2bc5fbff2b5 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y | |||
| @@ -26,14 +26,15 @@ do { \ | |||
| 26 | %} | 26 | %} |
| 27 | 27 | ||
| 28 | %token PE_START_EVENTS PE_START_TERMS | 28 | %token PE_START_EVENTS PE_START_TERMS |
| 29 | %token PE_VALUE PE_VALUE_SYM PE_RAW PE_TERM | 29 | %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM |
| 30 | %token PE_NAME | 30 | %token PE_NAME |
| 31 | %token PE_MODIFIER_EVENT PE_MODIFIER_BP | 31 | %token PE_MODIFIER_EVENT PE_MODIFIER_BP |
| 32 | %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT | 32 | %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT |
| 33 | %token PE_PREFIX_MEM PE_PREFIX_RAW | 33 | %token PE_PREFIX_MEM PE_PREFIX_RAW |
| 34 | %token PE_ERROR | 34 | %token PE_ERROR |
| 35 | %type <num> PE_VALUE | 35 | %type <num> PE_VALUE |
| 36 | %type <num> PE_VALUE_SYM | 36 | %type <num> PE_VALUE_SYM_HW |
| 37 | %type <num> PE_VALUE_SYM_SW | ||
| 37 | %type <num> PE_RAW | 38 | %type <num> PE_RAW |
| 38 | %type <num> PE_TERM | 39 | %type <num> PE_TERM |
| 39 | %type <str> PE_NAME | 40 | %type <str> PE_NAME |
| @@ -41,6 +42,7 @@ do { \ | |||
| 41 | %type <str> PE_NAME_CACHE_OP_RESULT | 42 | %type <str> PE_NAME_CACHE_OP_RESULT |
| 42 | %type <str> PE_MODIFIER_EVENT | 43 | %type <str> PE_MODIFIER_EVENT |
| 43 | %type <str> PE_MODIFIER_BP | 44 | %type <str> PE_MODIFIER_BP |
| 45 | %type <num> value_sym | ||
| 44 | %type <head> event_config | 46 | %type <head> event_config |
| 45 | %type <term> event_term | 47 | %type <term> event_term |
| 46 | %type <head> event_pmu | 48 | %type <head> event_pmu |
| @@ -109,8 +111,13 @@ PE_NAME '/' event_config '/' | |||
| 109 | $$ = list; | 111 | $$ = list; |
| 110 | } | 112 | } |
| 111 | 113 | ||
| 114 | value_sym: | ||
| 115 | PE_VALUE_SYM_HW | ||
| 116 | | | ||
| 117 | PE_VALUE_SYM_SW | ||
| 118 | |||
| 112 | event_legacy_symbol: | 119 | event_legacy_symbol: |
| 113 | PE_VALUE_SYM '/' event_config '/' | 120 | value_sym '/' event_config '/' |
| 114 | { | 121 | { |
| 115 | struct parse_events_data__events *data = _data; | 122 | struct parse_events_data__events *data = _data; |
| 116 | struct list_head *list = NULL; | 123 | struct list_head *list = NULL; |
| @@ -123,7 +130,7 @@ PE_VALUE_SYM '/' event_config '/' | |||
| 123 | $$ = list; | 130 | $$ = list; |
| 124 | } | 131 | } |
| 125 | | | 132 | | |
| 126 | PE_VALUE_SYM sep_slash_dc | 133 | value_sym sep_slash_dc |
| 127 | { | 134 | { |
| 128 | struct parse_events_data__events *data = _data; | 135 | struct parse_events_data__events *data = _data; |
| 129 | struct list_head *list = NULL; | 136 | struct list_head *list = NULL; |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 74d0948ec36..67715a42cd6 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
| @@ -72,7 +72,7 @@ static int pmu_format(char *name, struct list_head *format) | |||
| 72 | "%s/bus/event_source/devices/%s/format", sysfs, name); | 72 | "%s/bus/event_source/devices/%s/format", sysfs, name); |
| 73 | 73 | ||
| 74 | if (stat(path, &st) < 0) | 74 | if (stat(path, &st) < 0) |
| 75 | return -1; | 75 | return 0; /* no error if format does not exist */ |
| 76 | 76 | ||
| 77 | if (pmu_format_parse(path, format)) | 77 | if (pmu_format_parse(path, format)) |
| 78 | return -1; | 78 | return -1; |
| @@ -252,6 +252,7 @@ static struct perf_pmu *pmu_lookup(char *name) | |||
| 252 | list_splice(&aliases, &pmu->aliases); | 252 | list_splice(&aliases, &pmu->aliases); |
| 253 | pmu->name = strdup(name); | 253 | pmu->name = strdup(name); |
| 254 | pmu->type = type; | 254 | pmu->type = type; |
| 255 | list_add_tail(&pmu->list, &pmus); | ||
| 255 | return pmu; | 256 | return pmu; |
| 256 | } | 257 | } |
| 257 | 258 | ||
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index b3620fe1276..02dfa19a467 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c | |||
| @@ -209,6 +209,10 @@ static void define_event_symbols(struct event_format *event, | |||
| 209 | define_symbolic_values(args->symbol.symbols, ev_name, | 209 | define_symbolic_values(args->symbol.symbols, ev_name, |
| 210 | cur_field_name); | 210 | cur_field_name); |
| 211 | break; | 211 | break; |
| 212 | case PRINT_HEX: | ||
| 213 | define_event_symbols(event, ev_name, args->hex.field); | ||
| 214 | define_event_symbols(event, ev_name, args->hex.size); | ||
| 215 | break; | ||
| 212 | case PRINT_BSTRING: | 216 | case PRINT_BSTRING: |
| 213 | case PRINT_DYNAMIC_ARRAY: | 217 | case PRINT_DYNAMIC_ARRAY: |
| 214 | case PRINT_STRING: | 218 | case PRINT_STRING: |
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index a8ca2f8179a..ce4d1b0c386 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
| @@ -166,6 +166,10 @@ static void define_event_symbols(struct event_format *event, | |||
| 166 | define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name, | 166 | define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name, |
| 167 | cur_field_name); | 167 | cur_field_name); |
| 168 | break; | 168 | break; |
| 169 | case PRINT_HEX: | ||
| 170 | define_event_symbols(event, ev_name, args->hex.field); | ||
| 171 | define_event_symbols(event, ev_name, args->hex.size); | ||
| 172 | break; | ||
| 169 | case PRINT_STRING: | 173 | case PRINT_STRING: |
| 170 | break; | 174 | break; |
| 171 | case PRINT_TYPE: | 175 | case PRINT_TYPE: |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 994f4ffdcd0..50958bbeb26 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -1478,14 +1478,31 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size) | |||
| 1478 | goto out; | 1478 | goto out; |
| 1479 | } | 1479 | } |
| 1480 | 1480 | ||
| 1481 | sec = elf_section_by_name(elf, &ehdr, &shdr, | 1481 | /* |
| 1482 | ".note.gnu.build-id", NULL); | 1482 | * Check following sections for notes: |
| 1483 | if (sec == NULL) { | 1483 | * '.note.gnu.build-id' |
| 1484 | * '.notes' | ||
| 1485 | * '.note' (VDSO specific) | ||
| 1486 | */ | ||
| 1487 | do { | ||
| 1488 | sec = elf_section_by_name(elf, &ehdr, &shdr, | ||
| 1489 | ".note.gnu.build-id", NULL); | ||
| 1490 | if (sec) | ||
| 1491 | break; | ||
| 1492 | |||
| 1484 | sec = elf_section_by_name(elf, &ehdr, &shdr, | 1493 | sec = elf_section_by_name(elf, &ehdr, &shdr, |
| 1485 | ".notes", NULL); | 1494 | ".notes", NULL); |
| 1486 | if (sec == NULL) | 1495 | if (sec) |
| 1487 | goto out; | 1496 | break; |
| 1488 | } | 1497 | |
| 1498 | sec = elf_section_by_name(elf, &ehdr, &shdr, | ||
| 1499 | ".note", NULL); | ||
| 1500 | if (sec) | ||
| 1501 | break; | ||
| 1502 | |||
| 1503 | return err; | ||
| 1504 | |||
| 1505 | } while (0); | ||
| 1489 | 1506 | ||
| 1490 | data = elf_getdata(sec, NULL); | 1507 | data = elf_getdata(sec, NULL); |
| 1491 | if (data == NULL) | 1508 | if (data == NULL) |
