From e080e6f1c863242ff709046d0486d09c46dc484a Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 27 Jun 2012 09:41:41 +0900 Subject: tools lib traceevent: Add support for __print_hex() Since the __print_hex() function is used in print fmt now, add corresponding parser routines. This makes the output of perf script on the kvm_emulate_insn event not to fail any more. before: kvm_emulate_insn: [FAILED TO PARSE] rip=3238197797 ... after: kvm_emulate_insn: 0:c102fa25:89 10 (prot32) Signed-off-by: Namhyung Kim Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1340757701-10711-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/scripting-engines/trace-event-perl.c | 4 ++++ tools/perf/util/scripting-engines/trace-event-python.c | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'tools/perf') diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index b3620fe12763..02dfa19a467f 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, define_symbolic_values(args->symbol.symbols, ev_name, cur_field_name); break; + case PRINT_HEX: + define_event_symbols(event, ev_name, args->hex.field); + define_event_symbols(event, ev_name, args->hex.size); + break; case PRINT_BSTRING: case PRINT_DYNAMIC_ARRAY: 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 a8ca2f8179a9..ce4d1b0c3862 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, define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name, cur_field_name); break; + case PRINT_HEX: + define_event_symbols(event, ev_name, args->hex.field); + define_event_symbols(event, ev_name, args->hex.size); + break; case PRINT_STRING: break; case PRINT_TYPE: -- cgit v1.2.3 From 7582732f57e547929d4c65ad8e38f3446e0538d8 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 29 Jun 2012 09:22:54 +0200 Subject: perf tools: Fix hw breakpoint's type modifier parsing Fixing the hw breakpoint's type modifier parsing to allow all possible combinations of 'rwx' characters. Adding automated tests to the parsing test suite. Reported-by: Jovi Zhang Original-patch-by: Namhyung Kim Signed-off-by: Jiri Olsa Cc: Jovi Zhang Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20120629072254.GA940@krava.brq.redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events-test.c | 37 +++++++++++++++++++++++++++++++++++++ tools/perf/util/parse-events.c | 16 +++++++++++++--- tools/perf/util/parse-events.l | 2 +- 3 files changed, 51 insertions(+), 4 deletions(-) (limited to 'tools/perf') diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c index a0f61a2a6835..de81fe1f9329 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) return 0; } +static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); + + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", + PERF_TYPE_BREAKPOINT == evsel->attr.type); + TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); + TEST_ASSERT_VAL("wrong bp_type", + (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->attr.bp_type); + TEST_ASSERT_VAL("wrong bp_len", + HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len); + return 0; +} + static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) { struct perf_evsel *evsel = list_entry(evlist->entries.next, @@ -352,6 +368,19 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist) return test__checkevent_breakpoint_w(evlist); } +static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); + + TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); + + return test__checkevent_breakpoint_rw(evlist); +} + static int test__checkevent_pmu(struct perf_evlist *evlist) { @@ -585,6 +614,14 @@ static struct test__event_st test__events[] = { .name = "instructions:H", .check = test__checkevent_exclude_guest_modifier, }, + [26] = { + .name = "mem:0:rw", + .check = test__checkevent_breakpoint_rw, + }, + [27] = { + .name = "mem:0:rw:kp", + .check = test__checkevent_breakpoint_rw_modifier, + }, }; #define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st)) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 0cc27da30ddb..7ae76af709f1 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -383,21 +383,31 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr) if (!type || !type[i]) break; +#define CHECK_SET_TYPE(bit) \ +do { \ + if (attr->bp_type & bit) \ + return -EINVAL; \ + else \ + attr->bp_type |= bit; \ +} while (0) + switch (type[i]) { case 'r': - attr->bp_type |= HW_BREAKPOINT_R; + CHECK_SET_TYPE(HW_BREAKPOINT_R); break; case 'w': - attr->bp_type |= HW_BREAKPOINT_W; + CHECK_SET_TYPE(HW_BREAKPOINT_W); break; case 'x': - attr->bp_type |= HW_BREAKPOINT_X; + CHECK_SET_TYPE(HW_BREAKPOINT_X); break; default: return -EINVAL; } } +#undef CHECK_SET_TYPE + if (!attr->bp_type) /* Default */ attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 488362e14133..a06689474210 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -76,7 +76,7 @@ num_hex 0x[a-fA-F0-9]+ num_raw_hex [a-fA-F0-9]+ name [a-zA-Z_*?][a-zA-Z0-9_*?]* modifier_event [ukhpGH]{1,8} -modifier_bp [rwx] +modifier_bp [rwx]{1,3} %% -- cgit v1.2.3 From 287e74aa3db097469bdca401f33f00ef20dc710d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 28 Jun 2012 23:18:49 +0200 Subject: perf evsel: Handle hw breakpoints event names in perf_evsel__name() Adding hw breakpoint events hook in the perf_evsel__name function, to display event names properly all over the perf tools. Updated hw breakpoints events tests. Signed-off-by: Jiri Olsa Cc: Jovi Zhang Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1340918329-3012-3-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 30 ++++++++++++++++++++++++++++++ tools/perf/util/parse-events-test.c | 10 ++++++++++ tools/perf/util/parse-events.c | 4 +--- 3 files changed, 41 insertions(+), 3 deletions(-) (limited to 'tools/perf') diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 3d1f6968f175..e81771364867 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -15,6 +15,7 @@ #include "cpumap.h" #include "thread_map.h" #include "target.h" +#include "../../../include/linux/hw_breakpoint.h" #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) #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) return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); } +static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type) +{ + int r; + + r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr); + + if (type & HW_BREAKPOINT_R) + r += scnprintf(bf + r, size - r, "r"); + + if (type & HW_BREAKPOINT_W) + r += scnprintf(bf + r, size - r, "w"); + + if (type & HW_BREAKPOINT_X) + r += scnprintf(bf + r, size - r, "x"); + + return r; +} + +static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size) +{ + struct perf_event_attr *attr = &evsel->attr; + int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type); + return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); +} + const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] [PERF_EVSEL__MAX_ALIASES] = { { "L1-dcache", "l1-d", "l1d", "L1-data", }, @@ -285,6 +311,10 @@ const char *perf_evsel__name(struct perf_evsel *evsel) scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint"); break; + case PERF_TYPE_BREAKPOINT: + perf_evsel__bp_name(evsel, bf, sizeof(bf)); + break; + default: scnprintf(bf, sizeof(bf), "%s", "unknown attr type"); break; diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c index de81fe1f9329..dd0c306a0698 100644 --- a/tools/perf/util/parse-events-test.c +++ b/tools/perf/util/parse-events-test.c @@ -325,6 +325,8 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong name", + !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u")); return test__checkevent_breakpoint(evlist); } @@ -338,6 +340,8 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong name", + !strcmp(perf_evsel__name(evsel), "mem:0x0:x:k")); return test__checkevent_breakpoint_x(evlist); } @@ -351,6 +355,8 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong name", + !strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp")); return test__checkevent_breakpoint_r(evlist); } @@ -364,6 +370,8 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong name", + !strcmp(perf_evsel__name(evsel), "mem:0x0:w:up")); return test__checkevent_breakpoint_w(evlist); } @@ -377,6 +385,8 @@ static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong name", + !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp")); return test__checkevent_breakpoint_rw(evlist); } diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 7ae76af709f1..1dc44dc69133 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -418,7 +418,6 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx, void *ptr, char *type) { struct perf_event_attr attr; - char name[MAX_NAME_LEN]; memset(&attr, 0, sizeof(attr)); attr.bp_addr = (unsigned long) ptr; @@ -437,8 +436,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx, attr.type = PERF_TYPE_BREAKPOINT; - snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw"); - return add_event(list, idx, &attr, name); + return add_event(list, idx, &attr, NULL); } static int config_term(struct perf_event_attr *attr, -- cgit v1.2.3 From 9bc8f9fe2c6e3778202c76ef85ef291567c00cb8 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 14 Jun 2012 22:38:37 +0200 Subject: perf tools: Fix generation of pmu list The internal pmu list was never used. With each perf_pmu__find() call the pmu structure was created new by parsing sysfs. Beside this it caused memory leaks. We now keep all pmus by adding them to the list. Also, pmu_lookup() should return pmus that do not expose the format specifier in sysfs. We need a valid internal pmu list in a later patch to iterate over all pmus that exist in the system. Signed-off-by: Robert Richter Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1339706321-8802-3-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools/perf') diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 74d0948ec368..67715a42cd6d 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) "%s/bus/event_source/devices/%s/format", sysfs, name); if (stat(path, &st) < 0) - return -1; + return 0; /* no error if format does not exist */ if (pmu_format_parse(path, format)) return -1; @@ -252,6 +252,7 @@ static struct perf_pmu *pmu_lookup(char *name) list_splice(&aliases, &pmu->aliases); pmu->name = strdup(name); pmu->type = type; + list_add_tail(&pmu->list, &pmus); return pmu; } -- cgit v1.2.3 From 1388d715dd7d0f494c93dfdef6ab26719218b868 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 19 Jun 2012 17:48:05 +0200 Subject: perf symbols: Add '.note' check into search for NOTE section Adding '.note' section name to be check when looking for notes section. The '.note' name is used by kernel VDSO. Signed-off-by: Jiri Olsa Cc: Arun Sharma Cc: Benjamin Redelings Cc: Corey Ashford Cc: Cyrill Gorcunov Cc: Frank Ch. Eigler Cc: Frederic Weisbecker Cc: Masami Hiramatsu Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Robert Richter Cc: Stephane Eranian Cc: Tom Zanussi Cc: Ulrich Drepper Link: http://lkml.kernel.org/r/1340120894-9465-15-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'tools/perf') diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 994f4ffdcd05..50958bbeb26a 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) goto out; } - sec = elf_section_by_name(elf, &ehdr, &shdr, - ".note.gnu.build-id", NULL); - if (sec == NULL) { + /* + * Check following sections for notes: + * '.note.gnu.build-id' + * '.notes' + * '.note' (VDSO specific) + */ + do { + sec = elf_section_by_name(elf, &ehdr, &shdr, + ".note.gnu.build-id", NULL); + if (sec) + break; + sec = elf_section_by_name(elf, &ehdr, &shdr, ".notes", NULL); - if (sec == NULL) - goto out; - } + if (sec) + break; + + sec = elf_section_by_name(elf, &ehdr, &shdr, + ".note", NULL); + if (sec) + break; + + return err; + + } while (0); data = elf_getdata(sec, NULL); if (data == NULL) -- cgit v1.2.3 From 339ce005091b156c2af4c016c6ba9c1f87cd826a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 19 Jun 2012 17:48:11 +0200 Subject: perf tools: Adding round_up/round_down macros Adding round_up and round_down macros. They will be used in upcoming patches. Signed-off-by: Jiri Olsa Cc: Arun Sharma Cc: Benjamin Redelings Cc: Corey Ashford Cc: Cyrill Gorcunov Cc: Frank Ch. Eigler Cc: Frederic Weisbecker Cc: Masami Hiramatsu Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Robert Richter Cc: Stephane Eranian Cc: Tom Zanussi Cc: Ulrich Drepper Link: http://lkml.kernel.org/r/1340120894-9465-21-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/include/linux/kernel.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'tools/perf') diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h index 1eb804fd3fbf..b6842c1d02a8 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, #define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) #define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) +/* + * This looks more complex than it should be. But we need to + * get the type for the ~ right in round_down (it needs to be + * as wide as the result!), and we want to evaluate the macro + * arguments just once each. + */ +#define __round_mask(x, y) ((__typeof__(x))((y)-1)) +#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) +#define round_down(x, y) ((x) & ~__round_mask(x, y)) + #endif -- cgit v1.2.3 From 17d7a1123f0f6d532830152564cc812cc73db2f3 Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Mon, 2 Jul 2012 22:46:17 +0900 Subject: perf bench: Fix confused variable namings and descriptions in mem subsystem As Namhyung Kim pointed, there are confused namings and descriptions of words "cycle" and "clock" in mem-memset.c and mem-memcpy.c. With the option "-c" (or "--clock", now renamed as "--cycle"), mem subsystem measures cost of memset() and memcpy() with cpu-cycles event. But current mem subsystem source code contains lots of confused variable namings and descriptions with "clock" (e.g. the variable use_clock). This is a very bad style because there is another software event named "cpu-clock". This patch replaces wrong usage of "clock" to "cycle". v2: modified Documentation/perf-bench.txt for the descriptions of --cycle option Signed-off-by: Hitoshi Mitake Cc: Ingo Molnar Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1341236777-18457-1-git-send-email-h.mitake@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-bench.txt | 4 +- tools/perf/bench/mem-memcpy.c | 80 ++++++++++++++++----------------- tools/perf/bench/mem-memset.c | 80 ++++++++++++++++----------------- 3 files changed, 82 insertions(+), 82 deletions(-) (limited to 'tools/perf') diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt index f3c716a4cad3..7065cd6fbdfc 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. Repeat memcpy invocation this number of times. -c:: ---clock:: +--cycle:: Use perf's cpu-cycles event instead of gettimeofday syscall. -o:: @@ -176,7 +176,7 @@ On x86-64, x86-64-unrolled, x86-64-stosq and x86-64-stosb are supported. Repeat memset invocation this number of times. -c:: ---clock:: +--cycle:: Use perf's cpu-cycles event instead of gettimeofday syscall. -o:: diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c index d990365cafa0..02dad5d3359b 100644 --- a/tools/perf/bench/mem-memcpy.c +++ b/tools/perf/bench/mem-memcpy.c @@ -24,8 +24,8 @@ static const char *length_str = "1MB"; static const char *routine = "default"; static int iterations = 1; -static bool use_clock; -static int clock_fd; +static bool use_cycle; +static int cycle_fd; static bool only_prefault; static bool no_prefault; @@ -37,7 +37,7 @@ static const struct option options[] = { "Specify routine to copy"), OPT_INTEGER('i', "iterations", &iterations, "repeat memcpy() invocation this number of times"), - OPT_BOOLEAN('c', "clock", &use_clock, + OPT_BOOLEAN('c', "cycle", &use_cycle, "Use cycles event instead of gettimeofday() for measuring"), OPT_BOOLEAN('o', "only-prefault", &only_prefault, "Show only the result with page faults before memcpy()"), @@ -76,27 +76,27 @@ static const char * const bench_mem_memcpy_usage[] = { NULL }; -static struct perf_event_attr clock_attr = { +static struct perf_event_attr cycle_attr = { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES }; -static void init_clock(void) +static void init_cycle(void) { - clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0); + cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0); - if (clock_fd < 0 && errno == ENOSYS) + if (cycle_fd < 0 && errno == ENOSYS) die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); else - BUG_ON(clock_fd < 0); + BUG_ON(cycle_fd < 0); } -static u64 get_clock(void) +static u64 get_cycle(void) { int ret; u64 clk; - ret = read(clock_fd, &clk, sizeof(u64)); + ret = read(cycle_fd, &clk, sizeof(u64)); BUG_ON(ret != sizeof(u64)); return clk; @@ -119,9 +119,9 @@ static void alloc_mem(void **dst, void **src, size_t length) die("memory allocation failed - maybe length is too large?\n"); } -static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault) +static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault) { - u64 clock_start = 0ULL, clock_end = 0ULL; + u64 cycle_start = 0ULL, cycle_end = 0ULL; void *src = NULL, *dst = NULL; int i; @@ -130,14 +130,14 @@ static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault) if (prefault) fn(dst, src, len); - clock_start = get_clock(); + cycle_start = get_cycle(); for (i = 0; i < iterations; ++i) fn(dst, src, len); - clock_end = get_clock(); + cycle_end = get_cycle(); free(src); free(dst); - return clock_end - clock_start; + return cycle_end - cycle_start; } 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, int i; size_t len; double result_bps[2]; - u64 result_clock[2]; + u64 result_cycle[2]; argc = parse_options(argc, argv, options, bench_mem_memcpy_usage, 0); - if (use_clock) - init_clock(); + if (use_cycle) + init_cycle(); len = (size_t)perf_atoll((char *)length_str); - result_clock[0] = result_clock[1] = 0ULL; + result_cycle[0] = result_cycle[1] = 0ULL; result_bps[0] = result_bps[1] = 0.0; if ((s64)len <= 0) { @@ -223,11 +223,11 @@ int bench_mem_memcpy(int argc, const char **argv, if (!only_prefault && !no_prefault) { /* show both of results */ - if (use_clock) { - result_clock[0] = - do_memcpy_clock(routines[i].fn, len, false); - result_clock[1] = - do_memcpy_clock(routines[i].fn, len, true); + if (use_cycle) { + result_cycle[0] = + do_memcpy_cycle(routines[i].fn, len, false); + result_cycle[1] = + do_memcpy_cycle(routines[i].fn, len, true); } else { result_bps[0] = do_memcpy_gettimeofday(routines[i].fn, @@ -237,9 +237,9 @@ int bench_mem_memcpy(int argc, const char **argv, len, true); } } else { - if (use_clock) { - result_clock[pf] = - do_memcpy_clock(routines[i].fn, + if (use_cycle) { + result_cycle[pf] = + do_memcpy_cycle(routines[i].fn, len, only_prefault); } else { result_bps[pf] = @@ -251,12 +251,12 @@ int bench_mem_memcpy(int argc, const char **argv, switch (bench_format) { case BENCH_FORMAT_DEFAULT: if (!only_prefault && !no_prefault) { - if (use_clock) { - printf(" %14lf Clock/Byte\n", - (double)result_clock[0] + if (use_cycle) { + printf(" %14lf Cycle/Byte\n", + (double)result_cycle[0] / (double)len); - printf(" %14lf Clock/Byte (with prefault)\n", - (double)result_clock[1] + printf(" %14lf Cycle/Byte (with prefault)\n", + (double)result_cycle[1] / (double)len); } else { print_bps(result_bps[0]); @@ -265,9 +265,9 @@ int bench_mem_memcpy(int argc, const char **argv, printf(" (with prefault)\n"); } } else { - if (use_clock) { - printf(" %14lf Clock/Byte", - (double)result_clock[pf] + if (use_cycle) { + printf(" %14lf Cycle/Byte", + (double)result_cycle[pf] / (double)len); } else print_bps(result_bps[pf]); @@ -277,17 +277,17 @@ int bench_mem_memcpy(int argc, const char **argv, break; case BENCH_FORMAT_SIMPLE: if (!only_prefault && !no_prefault) { - if (use_clock) { + if (use_cycle) { printf("%lf %lf\n", - (double)result_clock[0] / (double)len, - (double)result_clock[1] / (double)len); + (double)result_cycle[0] / (double)len, + (double)result_cycle[1] / (double)len); } else { printf("%lf %lf\n", result_bps[0], result_bps[1]); } } else { - if (use_clock) { - printf("%lf\n", (double)result_clock[pf] + if (use_cycle) { + printf("%lf\n", (double)result_cycle[pf] / (double)len); } else printf("%lf\n", result_bps[pf]); diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c index bf0d5f552017..350cc9557265 100644 --- a/tools/perf/bench/mem-memset.c +++ b/tools/perf/bench/mem-memset.c @@ -24,8 +24,8 @@ static const char *length_str = "1MB"; static const char *routine = "default"; static int iterations = 1; -static bool use_clock; -static int clock_fd; +static bool use_cycle; +static int cycle_fd; static bool only_prefault; static bool no_prefault; @@ -37,7 +37,7 @@ static const struct option options[] = { "Specify routine to set"), OPT_INTEGER('i', "iterations", &iterations, "repeat memset() invocation this number of times"), - OPT_BOOLEAN('c', "clock", &use_clock, + OPT_BOOLEAN('c', "cycle", &use_cycle, "Use cycles event instead of gettimeofday() for measuring"), OPT_BOOLEAN('o', "only-prefault", &only_prefault, "Show only the result with page faults before memset()"), @@ -76,27 +76,27 @@ static const char * const bench_mem_memset_usage[] = { NULL }; -static struct perf_event_attr clock_attr = { +static struct perf_event_attr cycle_attr = { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES }; -static void init_clock(void) +static void init_cycle(void) { - clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0); + cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0); - if (clock_fd < 0 && errno == ENOSYS) + if (cycle_fd < 0 && errno == ENOSYS) die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); else - BUG_ON(clock_fd < 0); + BUG_ON(cycle_fd < 0); } -static u64 get_clock(void) +static u64 get_cycle(void) { int ret; u64 clk; - ret = read(clock_fd, &clk, sizeof(u64)); + ret = read(cycle_fd, &clk, sizeof(u64)); BUG_ON(ret != sizeof(u64)); return clk; @@ -115,9 +115,9 @@ static void alloc_mem(void **dst, size_t length) die("memory allocation failed - maybe length is too large?\n"); } -static u64 do_memset_clock(memset_t fn, size_t len, bool prefault) +static u64 do_memset_cycle(memset_t fn, size_t len, bool prefault) { - u64 clock_start = 0ULL, clock_end = 0ULL; + u64 cycle_start = 0ULL, cycle_end = 0ULL; void *dst = NULL; int i; @@ -126,13 +126,13 @@ static u64 do_memset_clock(memset_t fn, size_t len, bool prefault) if (prefault) fn(dst, -1, len); - clock_start = get_clock(); + cycle_start = get_cycle(); for (i = 0; i < iterations; ++i) fn(dst, i, len); - clock_end = get_clock(); + cycle_end = get_cycle(); free(dst); - return clock_end - clock_start; + return cycle_end - cycle_start; } 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, int i; size_t len; double result_bps[2]; - u64 result_clock[2]; + u64 result_cycle[2]; argc = parse_options(argc, argv, options, bench_mem_memset_usage, 0); - if (use_clock) - init_clock(); + if (use_cycle) + init_cycle(); len = (size_t)perf_atoll((char *)length_str); - result_clock[0] = result_clock[1] = 0ULL; + result_cycle[0] = result_cycle[1] = 0ULL; result_bps[0] = result_bps[1] = 0.0; if ((s64)len <= 0) { @@ -217,11 +217,11 @@ int bench_mem_memset(int argc, const char **argv, if (!only_prefault && !no_prefault) { /* show both of results */ - if (use_clock) { - result_clock[0] = - do_memset_clock(routines[i].fn, len, false); - result_clock[1] = - do_memset_clock(routines[i].fn, len, true); + if (use_cycle) { + result_cycle[0] = + do_memset_cycle(routines[i].fn, len, false); + result_cycle[1] = + do_memset_cycle(routines[i].fn, len, true); } else { result_bps[0] = do_memset_gettimeofday(routines[i].fn, @@ -231,9 +231,9 @@ int bench_mem_memset(int argc, const char **argv, len, true); } } else { - if (use_clock) { - result_clock[pf] = - do_memset_clock(routines[i].fn, + if (use_cycle) { + result_cycle[pf] = + do_memset_cycle(routines[i].fn, len, only_prefault); } else { result_bps[pf] = @@ -245,12 +245,12 @@ int bench_mem_memset(int argc, const char **argv, switch (bench_format) { case BENCH_FORMAT_DEFAULT: if (!only_prefault && !no_prefault) { - if (use_clock) { - printf(" %14lf Clock/Byte\n", - (double)result_clock[0] + if (use_cycle) { + printf(" %14lf Cycle/Byte\n", + (double)result_cycle[0] / (double)len); - printf(" %14lf Clock/Byte (with prefault)\n ", - (double)result_clock[1] + printf(" %14lf Cycle/Byte (with prefault)\n ", + (double)result_cycle[1] / (double)len); } else { print_bps(result_bps[0]); @@ -259,9 +259,9 @@ int bench_mem_memset(int argc, const char **argv, printf(" (with prefault)\n"); } } else { - if (use_clock) { - printf(" %14lf Clock/Byte", - (double)result_clock[pf] + if (use_cycle) { + printf(" %14lf Cycle/Byte", + (double)result_cycle[pf] / (double)len); } else print_bps(result_bps[pf]); @@ -271,17 +271,17 @@ int bench_mem_memset(int argc, const char **argv, break; case BENCH_FORMAT_SIMPLE: if (!only_prefault && !no_prefault) { - if (use_clock) { + if (use_cycle) { printf("%lf %lf\n", - (double)result_clock[0] / (double)len, - (double)result_clock[1] / (double)len); + (double)result_cycle[0] / (double)len, + (double)result_cycle[1] / (double)len); } else { printf("%lf %lf\n", result_bps[0], result_bps[1]); } } else { - if (use_clock) { - printf("%lf\n", (double)result_clock[pf] + if (use_cycle) { + printf("%lf\n", (double)result_cycle[pf] / (double)len); } else printf("%lf\n", result_bps[pf]); -- cgit v1.2.3 From ebf124ffab59e9e1c6179347fe95fe5baf32dcd7 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 4 Jul 2012 00:00:47 +0200 Subject: perf test: Use ARRAY_SIZE in parse events tests Use ARRAY_SIZE instead of defining the sizes separately for each test arrays. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1341352848-11833-10-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events-test.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) (limited to 'tools/perf') diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c index dd0c306a0698..1b997d2b89ce 100644 --- a/tools/perf/util/parse-events-test.c +++ b/tools/perf/util/parse-events-test.c @@ -634,8 +634,6 @@ static struct test__event_st test__events[] = { }, }; -#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st)) - static struct test__event_st test__events_pmu[] = { [0] = { .name = "cpu/config=10,config1,config2=3,period=1000/u", @@ -647,9 +645,6 @@ static struct test__event_st test__events_pmu[] = { }, }; -#define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \ - sizeof(struct test__event_st)) - struct test__term { const char *str; __u32 type; @@ -765,21 +760,17 @@ int parse_events__test(void) { int ret; - do { - ret = test_events(test__events, TEST__EVENTS_CNT); - if (ret) - break; - - if (test_pmu()) { - ret = test_events(test__events_pmu, - TEST__EVENTS_PMU_CNT); - if (ret) - break; - } +#define TEST_EVENTS(tests) \ +do { \ + ret = test_events(tests, ARRAY_SIZE(tests)); \ + if (ret) \ + return ret; \ +} while (0) - ret = test_terms(test__terms, TEST__TERMS_CNT); + TEST_EVENTS(test__events); - } while (0); + if (test_pmu()) + TEST_EVENTS(test__events_pmu); - return ret; + return test_terms(test__terms, ARRAY_SIZE(test__terms)); } -- cgit v1.2.3 From 8c5f0a84c6b16e04195001bfd78281909519cf09 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 4 Jul 2012 00:00:39 +0200 Subject: perf tools: Add empty rule for new line in event syntax parsing The flex generator prints out each input character that is ignored by lex rules. Since the alias processing, we can have '\n' characters on input. We need to assign empty rule to it, so it's not printed out. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1341352848-11833-2-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.l | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/perf') diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index a06689474210..6cbe092e6c3b 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -152,6 +152,7 @@ r{num_raw_hex} { return raw(yyscanner); } , { return ','; } : { return ':'; } = { return '='; } +\n { } { {modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); } -- cgit v1.2.3 From cf3506dcc4a855d11af20bcb271ac921033ba0de Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 4 Jul 2012 00:00:43 +0200 Subject: perf tools: Split out PE_VALUE_SYM parsing token to SW and HW tokens Spliting PE_VALUE_SYM token to PE_VALUE_SYM_HW and PE_VALUE_SYM_SW tokens to separate hardware and software symbols. This will be useful in upcomming patch where we want to be able to parse out only hardware events. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1341352848-11833-6-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.l | 2 +- tools/perf/util/parse-events.y | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'tools/perf') diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 6cbe092e6c3b..384ca74c6b22 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) YYSTYPE *yylval = parse_events_get_lval(scanner); yylval->num = (type << 16) + config; - return PE_VALUE_SYM; + return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW; } static int term(yyscan_t scanner, int type) diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 9525c455d27f..2bc5fbff2b5d 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -26,14 +26,15 @@ do { \ %} %token PE_START_EVENTS PE_START_TERMS -%token PE_VALUE PE_VALUE_SYM PE_RAW PE_TERM +%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM %token PE_NAME %token PE_MODIFIER_EVENT PE_MODIFIER_BP %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT %token PE_PREFIX_MEM PE_PREFIX_RAW %token PE_ERROR %type PE_VALUE -%type PE_VALUE_SYM +%type PE_VALUE_SYM_HW +%type PE_VALUE_SYM_SW %type PE_RAW %type PE_TERM %type PE_NAME @@ -41,6 +42,7 @@ do { \ %type PE_NAME_CACHE_OP_RESULT %type PE_MODIFIER_EVENT %type PE_MODIFIER_BP +%type value_sym %type event_config %type event_term %type event_pmu @@ -109,8 +111,13 @@ PE_NAME '/' event_config '/' $$ = list; } +value_sym: +PE_VALUE_SYM_HW +| +PE_VALUE_SYM_SW + event_legacy_symbol: -PE_VALUE_SYM '/' event_config '/' +value_sym '/' event_config '/' { struct parse_events_data__events *data = _data; struct list_head *list = NULL; @@ -123,7 +130,7 @@ PE_VALUE_SYM '/' event_config '/' $$ = list; } | -PE_VALUE_SYM sep_slash_dc +value_sym sep_slash_dc { struct parse_events_data__events *data = _data; struct list_head *list = NULL; -- cgit v1.2.3 From 1dc12760854a670d0366dcfd8ad179e3574c1712 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 4 Jul 2012 00:00:44 +0200 Subject: perf tools: Split event symbols arrays to hw and sw parts It'll be convenient in upcoming patch to access hw event symbols strings via enum perf_hw_id indexes. In order not to duplicate the data, creating two separate arrays: event_symbols_hw for enum perf_hw_id events event_symbols_sw for enum perf_sw_ids events Changing the current event list code to follow the change. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1341352848-11833-7-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 174 +++++++++++++++++++++++++++-------------- 1 file changed, 117 insertions(+), 57 deletions(-) (limited to 'tools/perf') diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 1dc44dc69133..1aa721d7c10f 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -19,8 +19,6 @@ #define MAX_NAME_LEN 100 struct event_symbol { - u8 type; - u64 config; const char *symbol; const char *alias; }; @@ -30,30 +28,86 @@ extern int parse_events_debug; #endif int parse_events_parse(void *data, void *scanner); -#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x -#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x - -static struct event_symbol event_symbols[] = { - { CHW(CPU_CYCLES), "cpu-cycles", "cycles" }, - { CHW(STALLED_CYCLES_FRONTEND), "stalled-cycles-frontend", "idle-cycles-frontend" }, - { CHW(STALLED_CYCLES_BACKEND), "stalled-cycles-backend", "idle-cycles-backend" }, - { CHW(INSTRUCTIONS), "instructions", "" }, - { CHW(CACHE_REFERENCES), "cache-references", "" }, - { CHW(CACHE_MISSES), "cache-misses", "" }, - { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, - { CHW(BRANCH_MISSES), "branch-misses", "" }, - { CHW(BUS_CYCLES), "bus-cycles", "" }, - { CHW(REF_CPU_CYCLES), "ref-cycles", "" }, - - { CSW(CPU_CLOCK), "cpu-clock", "" }, - { CSW(TASK_CLOCK), "task-clock", "" }, - { CSW(PAGE_FAULTS), "page-faults", "faults" }, - { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, - { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, - { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, - { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, - { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" }, - { CSW(EMULATION_FAULTS), "emulation-faults", "" }, +static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { + [PERF_COUNT_HW_CPU_CYCLES] = { + .symbol = "cpu-cycles", + .alias = "cycles", + }, + [PERF_COUNT_HW_INSTRUCTIONS] = { + .symbol = "instructions", + .alias = "", + }, + [PERF_COUNT_HW_CACHE_REFERENCES] = { + .symbol = "cache-references", + .alias = "", + }, + [PERF_COUNT_HW_CACHE_MISSES] = { + .symbol = "cache-misses", + .alias = "", + }, + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { + .symbol = "branch-instructions", + .alias = "branches", + }, + [PERF_COUNT_HW_BRANCH_MISSES] = { + .symbol = "branch-misses", + .alias = "", + }, + [PERF_COUNT_HW_BUS_CYCLES] = { + .symbol = "bus-cycles", + .alias = "", + }, + [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = { + .symbol = "stalled-cycles-frontend", + .alias = "idle-cycles-frontend", + }, + [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = { + .symbol = "stalled-cycles-backend", + .alias = "idle-cycles-backend", + }, + [PERF_COUNT_HW_REF_CPU_CYCLES] = { + .symbol = "ref-cycles", + .alias = "", + }, +}; + +static struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { + [PERF_COUNT_SW_CPU_CLOCK] = { + .symbol = "cpu-clock", + .alias = "", + }, + [PERF_COUNT_SW_TASK_CLOCK] = { + .symbol = "task-clock", + .alias = "", + }, + [PERF_COUNT_SW_PAGE_FAULTS] = { + .symbol = "page-faults", + .alias = "faults", + }, + [PERF_COUNT_SW_CONTEXT_SWITCHES] = { + .symbol = "context-switches", + .alias = "cs", + }, + [PERF_COUNT_SW_CPU_MIGRATIONS] = { + .symbol = "cpu-migrations", + .alias = "migrations", + }, + [PERF_COUNT_SW_PAGE_FAULTS_MIN] = { + .symbol = "minor-faults", + .alias = "", + }, + [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = { + .symbol = "major-faults", + .alias = "", + }, + [PERF_COUNT_SW_ALIGNMENT_FAULTS] = { + .symbol = "alignment-faults", + .alias = "", + }, + [PERF_COUNT_SW_EMULATION_FAULTS] = { + .symbol = "emulation-faults", + .alias = "", + }, }; #define __PERF_EVENT_FIELD(config, name) \ @@ -824,16 +878,13 @@ int is_valid_tracepoint(const char *event_string) return 0; } -void print_events_type(u8 type) +static void __print_events_type(u8 type, struct event_symbol *syms, + unsigned max) { - struct event_symbol *syms = event_symbols; - unsigned int i; char name[64]; + unsigned i; - for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { - if (type != syms->type) - continue; - + for (i = 0; i < max ; i++, syms++) { if (strlen(syms->alias)) snprintf(name, sizeof(name), "%s OR %s", syms->symbol, syms->alias); @@ -845,6 +896,14 @@ void print_events_type(u8 type) } } +void print_events_type(u8 type) +{ + if (type == PERF_TYPE_SOFTWARE) + __print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX); + else + __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX); +} + int print_hwcache_events(const char *event_glob) { unsigned int type, op, i, printed = 0; @@ -872,26 +931,13 @@ int print_hwcache_events(const char *event_glob) return printed; } -/* - * Print the help text for the event symbols: - */ -void print_events(const char *event_glob) +static void print_symbol_events(const char *event_glob, unsigned type, + struct event_symbol *syms, unsigned max) { - unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0; - struct event_symbol *syms = event_symbols; + unsigned i, printed = 0; char name[MAX_NAME_LEN]; - printf("\n"); - printf("List of pre-defined events (to be used in -e):\n"); - - for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { - type = syms->type; - - if (type != prev_type && printed) { - printf("\n"); - printed = 0; - ntypes_printed++; - } + for (i = 0; i < max; i++, syms++) { if (event_glob != NULL && !(strglobmatch(syms->symbol, event_glob) || @@ -902,17 +948,31 @@ void print_events(const char *event_glob) snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); else strncpy(name, syms->symbol, MAX_NAME_LEN); - printf(" %-50s [%s]\n", name, - event_type_descriptors[type]); - prev_type = type; - ++printed; + printf(" %-50s [%s]\n", name, event_type_descriptors[type]); + + printed++; } - if (ntypes_printed) { - printed = 0; + if (printed) printf("\n"); - } +} + +/* + * Print the help text for the event symbols: + */ +void print_events(const char *event_glob) +{ + + printf("\n"); + printf("List of pre-defined events (to be used in -e):\n"); + + print_symbol_events(event_glob, PERF_TYPE_HARDWARE, + event_symbols_hw, PERF_COUNT_HW_MAX); + + print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, + event_symbols_sw, PERF_COUNT_SW_MAX); + print_hwcache_events(event_glob); if (event_glob != NULL) -- cgit v1.2.3