From 7a983a0fe2a29ec849f6748d6bd86904d6e88eea Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 20 Aug 2018 17:58:17 -0300 Subject: [PATCH 001/155] perf trace: Pass augmented args to the arg formatters when available If the tracepoint payload is bigger than what a syscall expected from what is in its format file in tracefs, then that will be used as augmented args, i.e. the expansion of syscall arg pointers, with things like a filename, structs, etc. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-bsbqx7xi2ot4q9bf570f7tqs@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 28 ++++++++++++++++++++++------ tools/perf/trace/beauty/beauty.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 22ab8e67c760..7deae6c8cb25 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -856,10 +856,12 @@ static struct syscall_fmt *syscall_fmt__find(const char *name) /* * is_exit: is this "exit" or "exit_group"? * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter. + * args_size: sum of the sizes of the syscall arguments, anything after that is augmented stuff: pathname for openat, etc. */ struct syscall { struct event_format *tp_format; int nr_args; + int args_size; bool is_exit; bool is_open; struct format_field *args; @@ -1258,10 +1260,12 @@ static int syscall__alloc_arg_fmts(struct syscall *sc, int nr_args) static int syscall__set_arg_fmts(struct syscall *sc) { - struct format_field *field; + struct format_field *field, *last_field = NULL; int idx = 0, len; for (field = sc->args; field; field = field->next, ++idx) { + last_field = field; + if (sc->fmt && sc->fmt->arg[idx].scnprintf) continue; @@ -1292,6 +1296,9 @@ static int syscall__set_arg_fmts(struct syscall *sc) } } + if (last_field) + sc->args_size = last_field->offset + last_field->size; + return 0; } @@ -1472,14 +1479,18 @@ static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size, } static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, - unsigned char *args, struct trace *trace, - struct thread *thread) + unsigned char *args, void *augmented_args, int augmented_args_size, + struct trace *trace, struct thread *thread) { size_t printed = 0; unsigned long val; u8 bit = 1; struct syscall_arg arg = { .args = args, + .augmented = { + .size = augmented_args_size, + .args = augmented_args, + }, .idx = 0, .mask = 0, .trace = trace, @@ -1692,7 +1703,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name); printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed, - args, trace, thread); + args, NULL, 0, trace, thread); if (sc->is_exit) { if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) { @@ -1723,7 +1734,8 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evse int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1; struct syscall *sc = trace__syscall_info(trace, evsel, id); char msg[1024]; - void *args; + void *args, *augmented_args = NULL; + int augmented_args_size; if (sc == NULL) return -1; @@ -1738,7 +1750,11 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evse goto out_put; args = perf_evsel__sc_tp_ptr(evsel, args, sample); - syscall__scnprintf_args(sc, msg, sizeof(msg), args, trace, thread); + augmented_args_size = sample->raw_size - sc->args_size; + if (augmented_args_size > 0) + augmented_args = sample->raw_data + sc->args_size; + + syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread); fprintf(trace->output, "%s", msg); err = 0; out_put: diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h index 9615af5d412b..6ca044d3d851 100644 --- a/tools/perf/trace/beauty/beauty.h +++ b/tools/perf/trace/beauty/beauty.h @@ -30,9 +30,34 @@ struct thread; size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_t size); +/** + * augmented_arg: extra payload for syscall pointer arguments + + * If perf_sample->raw_size is more than what a syscall sys_enter_FOO puts, + * then its the arguments contents, so that we can show more than just a + * pointer. This will be done initially with eBPF, the start of that is at the + * tools/perf/examples/bpf/augmented_syscalls.c example for the openat, but + * will eventually be done automagically caching the running kernel tracefs + * events data into an eBPF C script, that then gets compiled and its .o file + * cached for subsequent use. For char pointers like the ones for 'open' like + * syscalls its easy, for the rest we should use DWARF or better, BTF, much + * more compact. + * + * @size: 8 if all we need is an integer, otherwise all of the augmented arg. + * @int_arg: will be used for integer like pointer contents, like 'accept's 'upeer_addrlen' + * @value: u64 aligned, for structs, pathnames + */ +struct augmented_arg { + int size; + int int_arg; + u64 value[]; +}; + /** * @val: value of syscall argument being formatted * @args: All the args, use syscall_args__val(arg, nth) to access one + * @augmented_args: Extra data that can be collected, for instance, with eBPF for expanding the pathname for open, etc + * @augmented_args_size: augmented_args total payload size * @thread: tid state (maps, pid, tid, etc) * @trace: 'perf trace' internals: all threads, etc * @parm: private area, may be an strarray, for instance @@ -43,6 +68,10 @@ size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_ struct syscall_arg { unsigned long val; unsigned char *args; + struct { + struct augmented_arg *args; + int size; + } augmented; struct thread *thread; struct trace *trace; void *parm; From 6ccc18a9a17a1189b8b157176ce4a58c458c9eee Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Aug 2018 11:14:15 -0300 Subject: [PATCH 002/155] perf trace: Make the augmented_syscalls filter out the tracepoint event When we attach a eBPF object to a tracepoint, if we return 1, then that tracepoint will be stored in the perf's ring buffer. In the augmented_syscalls.c case we want to just attach and _override_ the tracepoint payload with an augmented, extended one. In this example, tools/perf/examples/bpf/augmented_syscalls.c, we are attaching to the 'openat' syscall, and adding, after the syscalls:sys_enter_openat usual payload as defined by /sys/kernel/debug/tracing/events/syscalls/sys_enter_openat/format, a snapshot of its sole pointer arg: # grep 'field:.*\*' /sys/kernel/debug/tracing/events/syscalls/sys_enter_openat/format field:const char * filename; offset:24; size:8; signed:0; # For now this is not being considered, the next csets will make use of it, but as this is overriding the syscall tracepoint enter, we don't want that event appearing on the ring buffer, just our synthesized one. Before: # perf trace -e ~acme/git/perf/tools/perf/examples/bpf/augmented_syscalls.c,openat cat /etc/passwd > /dev/null 0.000 ( ): __augmented_syscalls__:dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC 0.006 ( ): syscalls:sys_enter_openat:dfd: CWD, filename: , flags: CLOEXEC 0.007 ( 0.004 ms): cat/24044 openat(dfd: CWD, filename: 0x216dda8, flags: CLOEXEC ) = 3 0.028 ( ): __augmented_syscalls__:dfd: CWD, filename: /lib64/libc.so.6, flags: CLOEXEC 0.030 ( ): syscalls:sys_enter_openat:dfd: CWD, filename: , flags: CLOEXEC 0.031 ( 0.006 ms): cat/24044 openat(dfd: CWD, filename: 0x2375ce0, flags: CLOEXEC ) = 3 0.291 ( ): __augmented_syscalls__:dfd: CWD, filename: /etc/passwd 0.293 ( ): syscalls:sys_enter_openat:dfd: CWD, filename: 0.294 ( 0.004 ms): cat/24044 openat(dfd: CWD, filename: 0x637db06b ) = 3 # After: # perf trace -e ~acme/git/perf/tools/perf/examples/bpf/augmented_syscalls.c,openat cat /etc/passwd > /dev/null 0.000 ( ): __augmented_syscalls__:dfd: CWD, filename: 0x9c6a1da8, flags: CLOEXEC 0.005 ( 0.015 ms): cat/27341 openat(dfd: CWD, filename: 0x9c6a1da8, flags: CLOEXEC ) = 3 0.040 ( ): __augmented_syscalls__:dfd: CWD, filename: 0x9c8a9ce0, flags: CLOEXEC 0.041 ( 0.006 ms): cat/27341 openat(dfd: CWD, filename: 0x9c8a9ce0, flags: CLOEXEC ) = 3 0.294 ( ): __augmented_syscalls__:dfd: CWD, filename: 0x482a706b 0.296 ( 0.067 ms): cat/27341 openat(dfd: CWD, filename: 0x482a706b ) = 3 # Now lets replace that __augmented_syscalls__ name with the syscall name, using: # grep 'field:.*syscall_nr' /sys/kernel/debug/tracing/events/syscalls/sys_enter_openat/format field:int __syscall_nr; offset:8; size:4; signed:1; # That the synthesized payload has exactly where the syscall enter tracepoint puts it. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-og4r9k87mzp9hv7el046idmd@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/examples/bpf/augmented_syscalls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index 69a31386d8cd..10e7997ab481 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -49,7 +49,7 @@ int syscall_enter(openat)(struct syscall_enter_openat_args *args) probe_read_str(&augmented_args.filename, sizeof(augmented_args.filename), args->filename_ptr); perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, &augmented_args, sizeof(augmented_args)); - return 1; + return 0; } license(GPL); From 1cdf618f23867dd1dae58f10f1f82839f2bf73b4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Aug 2018 11:44:23 -0300 Subject: [PATCH 003/155] perf trace: Print the syscall name for augmented_syscalls Since we copy all the payload for raw_syscalls:sys_enter plus add expanded pointers, we can use the syscall id to get its name, etc: # grep 'field:.* id' /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/format field:long id; offset:8; size:8; signed:1; # Before: # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c,openat cat /etc/passwd > /dev/null 0.000 ( ): __augmented_syscalls__:dfd: CWD, filename: 0xec9f9da8, flags: CLOEXEC 0.006 ( 0.006 ms): cat/2395 openat(dfd: CWD, filename: 0xec9f9da8, flags: CLOEXEC) = 3 0.041 ( ): __augmented_syscalls__:dfd: CWD, filename: 0xecc01ce0, flags: CLOEXEC 0.042 ( 0.007 ms): cat/2395 openat(dfd: CWD, filename: 0xecc01ce0, flags: CLOEXEC) = 3 0.376 ( ): __augmented_syscalls__:dfd: CWD, filename: 0xac0a806b 0.379 ( 0.006 ms): cat/2395 openat(dfd: CWD, filename: 0xac0a806b) = 3 # After: # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c,openat cat /etc/passwd > /dev/null 0.000 ( ): openat(dfd: CWD, filename: 0x31b6dda8, flags: CLOEXEC) 0.009 ( 0.009 ms): cat/3619 openat(dfd: CWD, filename: 0x31b6dda8, flags: CLOEXEC) = 3 0.051 ( ): openat(dfd: CWD, filename: 0x31d75ce0, flags: CLOEXEC) 0.054 ( 0.010 ms): cat/3619 openat(dfd: CWD, filename: 0x31d75ce0, flags: CLOEXEC) = 3 0.539 ( ): openat(dfd: CWD, filename: 0xca71506b) 0.543 ( 0.115 ms): cat/3619 openat(dfd: CWD, filename: 0xca71506b) = 3 # Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-epz6y9i0eavmerc5ha98t7gn@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 7deae6c8cb25..bcf882afd6d0 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2055,13 +2055,33 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, if (trace->trace_syscalls) fprintf(trace->output, "( ): "); + if (evsel == trace->syscalls.events.augmented) { + int id = perf_evsel__sc_tp_uint(evsel, id, sample); + struct syscall *sc = trace__syscall_info(trace, evsel, id); + + if (sc) { + struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); + + if (thread) { + fprintf(trace->output, "%s(", sc->name); + trace__fprintf_sys_enter(trace, evsel, sample); + fputc(')', trace->output); + thread__put(thread); + goto newline; + } + } + + /* + * XXX: Not having the associated syscall info or not finding/adding + * the thread should never happen, but if it does... + * fall thru and print it as a bpf_output event. + */ + } + fprintf(trace->output, "%s:", evsel->name); if (perf_evsel__is_bpf_output(evsel)) { - if (evsel == trace->syscalls.events.augmented) - trace__fprintf_sys_enter(trace, evsel, sample); - else - bpf_output__fprintf(trace, sample); + bpf_output__fprintf(trace, sample); } else if (evsel->tp_format) { if (strncmp(evsel->tp_format->name, "sys_enter_", 10) || trace__fprintf_sys_enter(trace, evsel, sample)) { @@ -2071,6 +2091,7 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, } } +newline: fprintf(trace->output, "\n"); if (callchain_ret > 0) From 6dcbd212ff4988d8e6caa0b6700bd1c1d317dc02 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Aug 2018 11:40:09 -0300 Subject: [PATCH 004/155] perf trace: Extract the comm/tid printing for syscall enter Will be used with augmented syscalls, where we haven't transitioned completely to combining sys_enter_FOO with sys_exit_FOO, so we'll go as far as having it similar to the end result, strace like, as possible. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-canomaoiybkswwnhj69u9ae4@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index bcf882afd6d0..92488edd00eb 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1144,11 +1144,9 @@ static void sig_handler(int sig) interrupted = sig == SIGINT; } -static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread, - u64 duration, bool duration_calculated, u64 tstamp, FILE *fp) +static size_t trace__fprintf_comm_tid(struct trace *trace, struct thread *thread, FILE *fp) { - size_t printed = trace__fprintf_tstamp(trace, tstamp, fp); - printed += fprintf_duration(duration, duration_calculated, fp); + size_t printed = 0; if (trace->multiple_threads) { if (trace->show_comm) @@ -1159,6 +1157,14 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre return printed; } +static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread, + u64 duration, bool duration_calculated, u64 tstamp, FILE *fp) +{ + size_t printed = trace__fprintf_tstamp(trace, tstamp, fp); + printed += fprintf_duration(duration, duration_calculated, fp); + return printed + trace__fprintf_comm_tid(trace, thread, fp); +} + static int trace__process_event(struct trace *trace, struct machine *machine, union perf_event *event, struct perf_sample *sample) { From c96f4edcc3560a7dc910271d30d91c54a422d46c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Aug 2018 11:47:44 -0300 Subject: [PATCH 005/155] perf trace: Show comm/tid for augmented_syscalls To get us a bit more like the sys_enter + sys_exit combo: # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c,openat cat /etc/passwd > /dev/null 0.000 ( ): openat(dfd: CWD, filename: 0x31b6dda8, flags: CLOEXEC) 0.009 ( 0.009 ms): cat/3619 openat(dfd: CWD, filename: 0x31b6dda8, flags: CLOEXEC) = 3 0.051 ( ): openat(dfd: CWD, filename: 0x31d75ce0, flags: CLOEXEC) 0.054 ( 0.010 ms): cat/3619 openat(dfd: CWD, filename: 0x31d75ce0, flags: CLOEXEC) = 3 0.539 ( ): openat(dfd: CWD, filename: 0xca71506b) 0.543 ( 0.115 ms): cat/3619 openat(dfd: CWD, filename: 0xca71506b) = 3 # After: # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c,openat cat /etc/passwd > /dev/null 0.000 ( ): cat/4919 openat(dfd: CWD, filename: 0xc8358da8, flags: CLOEXEC) 0.007 ( 0.005 ms): cat/4919 openat(dfd: CWD, filename: 0xc8358da8, flags: CLOEXEC) = 3 0.032 ( ): cat/4919 openat(dfd: CWD, filename: 0xc8560ce0, flags: CLOEXEC) 0.033 ( 0.006 ms): cat/4919 openat(dfd: CWD, filename: 0xc8560ce0, flags: CLOEXEC) = 3 0.301 ( ): cat/4919 openat(dfd: CWD, filename: 0x91fa306b) 0.304 ( 0.004 ms): cat/4919 openat(dfd: CWD, filename: 0x91fa306b) = 3 # Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-6w8ytyo5y655a1hsyfpfily6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 92488edd00eb..e46ac9009172 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2069,6 +2069,7 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); if (thread) { + trace__fprintf_comm_tid(trace, thread, trace->output); fprintf(trace->output, "%s(", sc->name); trace__fprintf_sys_enter(trace, evsel, sample); fputc(')', trace->output); From 75d1e30681d006f4dc148c153395fb938acfc7c0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Aug 2018 12:00:39 -0300 Subject: [PATCH 006/155] perf trace: Use the augmented filename, expanding syscall enter pointers This is the final touch in showing how a syscall argument beautifier can access the augmented args put in place by the tools/perf/examples/bpf/augmented_syscalls.c eBPF script, right after the regular raw syscall args, i.e. the up to 6 long integer values in the syscall interface. With this we are able to show the 'openat' syscall arg, now with up to 64 bytes, but in time this will be configurable, just like with the 'strace -s strsize' argument, from 'strace''s man page: -s strsize Specify the maximum string size to print (the default is 32). This actually is the maximum string to _collect_ and store in the ring buffer, not just print. Before: # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c,openat cat /etc/passwd > /dev/null 0.000 ( ): cat/9658 openat(dfd: CWD, filename: 0x6626eda8, flags: CLOEXEC) 0.017 ( 0.007 ms): cat/9658 openat(dfd: CWD, filename: 0x6626eda8, flags: CLOEXEC) = 3 0.049 ( ): cat/9658 openat(dfd: CWD, filename: 0x66476ce0, flags: CLOEXEC) 0.051 ( 0.007 ms): cat/9658 openat(dfd: CWD, filename: 0x66476ce0, flags: CLOEXEC) = 3 0.377 ( ): cat/9658 openat(dfd: CWD, filename: 0x1e8f806b) 0.379 ( 0.005 ms): cat/9658 openat(dfd: CWD, filename: 0x1e8f806b) = 3 # After: # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c,openat cat /etc/passwd > /dev/null 0.000 ( ): cat/11966 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 0.006 ( 0.006 ms): cat/11966 openat(dfd: CWD, filename: 0x4bfdcda8, flags: CLOEXEC) = 3 0.034 ( ): cat/11966 openat(dfd: CWD, filename: /lib64/libc.so.6, flags: CLOEXEC) 0.036 ( 0.008 ms): cat/11966 openat(dfd: CWD, filename: 0x4c1e4ce0, flags: CLOEXEC) = 3 0.375 ( ): cat/11966 openat(dfd: CWD, filename: /etc/passwd) 0.377 ( 0.005 ms): cat/11966 openat(dfd: CWD, filename: 0xe87906b) = 3 # This cset should show all the aspects of establishing a protocol between an eBPF syscall arg augmenter program, tools/perf/examples/bpf/augmented_syscalls.c and a 'perf trace' beautifier, the one associated with all 'char *' point syscall args with names that can heuristically be associated with filenames. Now to wire up 'open' to show a second syscall using this scheme, all we have to do now is to change tools/perf/examples/bpf/augmented_syscalls.c, as 'perf trace' will notice that the perf_sample.raw_size is more than what is expected for a particular syscall payload as defined by its tracefs format file and will then use the augmented payload in the 'filename' syscall arg beautifier. The same protocol will be used for structs such as 'struct sockaddr *', 'struct pollfd', etc, with additions for handling arrays. This will all be done under the hood when 'perf trace' realizes the system has the necessary components, and also can be done by providing a precompiled augmented_syscalls.c eBPF ELF object. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-gj9kqb61wo7m3shtpzercbcr@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 10 ++++++++++ tools/perf/examples/bpf/augmented_syscalls.c | 17 +++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index e46ac9009172..5d841114a745 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1097,11 +1097,21 @@ static void thread__set_filename_pos(struct thread *thread, const char *bf, ttrace->filename.entry_str_pos = bf - ttrace->entry_str; } +static size_t syscall_arg__scnprintf_augmented_string(struct syscall_arg *arg, char *bf, size_t size) +{ + struct augmented_arg *augmented_arg = arg->augmented.args; + + return scnprintf(bf, size, "%.*s", augmented_arg->size, augmented_arg->value); +} + static size_t syscall_arg__scnprintf_filename(char *bf, size_t size, struct syscall_arg *arg) { unsigned long ptr = arg->val; + if (arg->augmented.args) + return syscall_arg__scnprintf_augmented_string(arg, bf, size); + if (!arg->trace->vfs_getname) return scnprintf(bf, size, "%#x", ptr); diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index 10e7997ab481..93960e891478 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -27,6 +27,12 @@ struct bpf_map SEC("maps") __augmented_syscalls__ = { .max_entries = __NR_CPUS__, }; +struct augmented_filename { + int size; + int reserved; + char value[256]; +}; + struct syscall_enter_openat_args { unsigned long long common_tp_fields; long syscall_nr; @@ -38,17 +44,20 @@ struct syscall_enter_openat_args { struct augmented_enter_openat_args { struct syscall_enter_openat_args args; - char filename[64]; + struct augmented_filename filename; }; int syscall_enter(openat)(struct syscall_enter_openat_args *args) { - struct augmented_enter_openat_args augmented_args; + struct augmented_enter_openat_args augmented_args = { .filename.reserved = 0, }; probe_read(&augmented_args.args, sizeof(augmented_args.args), args); - probe_read_str(&augmented_args.filename, sizeof(augmented_args.filename), args->filename_ptr); + augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, + sizeof(augmented_args.filename.value), + args->filename_ptr); perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, - &augmented_args, sizeof(augmented_args)); + &augmented_args, + sizeof(augmented_args) - sizeof(augmented_args.filename.value) + augmented_args.filename.size); return 0; } From daa1284af3b9a8d73b1dadaa12bc4068a4ce22ab Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Aug 2018 12:20:06 -0300 Subject: [PATCH 007/155] perf trace: Augment the 'open' syscall 'filename' arg As described in the previous cset, all we had to do was to touch the augmented_syscalls.c eBPF program, fire up 'perf trace' with that new eBPF script in system wide mode and wait for 'open' syscalls, in addition to 'openat' ones to see that it works: # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c 0.000 StreamT~s #200/16150 openat(dfd: CWD, filename: /home/acme/.mozilla/firefox/fqxhj76d.default/prefs.js, flags: CREAT|EXCL|TRUNC|WRONLY, mode: IRUSR|IWUSR) 0.065 StreamT~s #200/16150 openat(dfd: CWD, filename: /home/acme/.mozilla/firefox/fqxhj76d.default/prefs-1.js, flags: CREAT|EXCL|TRUNC|WRONLY, mode: IRUSR|IWUSR) 0.435 StreamT~s #200/16150 openat(dfd: CWD, filename: /home/acme/.mozilla/firefox/fqxhj76d.default/prefs-1.js, flags: CREAT|TRUNC|WRONLY, mode: IRUSR|IWUSR) 1.875 perf/16772 openat(dfd: CWD, filename: /sys/kernel/debug/tracing/events/syscalls/sys_enter_openat/form) 1227.260 gnome-shell/1463 openat(dfd: CWD, filename: /proc/self/stat) 1227.397 gnome-shell/2125 openat(dfd: CWD, filename: /proc/self/stat) 7227.619 gnome-shell/1463 openat(dfd: CWD, filename: /proc/self/stat) 7227.661 gnome-shell/2125 openat(dfd: CWD, filename: /proc/self/stat) 10018.079 gnome-shell/1463 openat(dfd: CWD, filename: /proc/self/stat) 10018.514 perf/16772 openat(dfd: CWD, filename: /proc/1237/status) 10018.568 perf/16772 openat(dfd: CWD, filename: /proc/1237/status) 10022.409 gnome-shell/2125 openat(dfd: CWD, filename: /proc/self/stat) 10090.044 NetworkManager/1237 openat(dfd: CWD, filename: /proc/2125/stat) 10090.351 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 10090.407 perf/16772 openat(dfd: CWD, filename: /sys/kernel/debug/tracing/events/syscalls/sys_enter_open/format) 10091.763 NetworkManager/1237 openat(dfd: CWD, filename: /proc/2125/stat) 10091.812 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 10092.807 NetworkManager/1237 openat(dfd: CWD, filename: /proc/2125/stat) 10092.851 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 10094.650 NetworkManager/1237 openat(dfd: CWD, filename: /proc/1463/stat) 10094.926 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 10096.010 NetworkManager/1237 openat(dfd: CWD, filename: /proc/1463/stat) 10096.057 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 10097.056 NetworkManager/1237 openat(dfd: CWD, filename: /proc/1463/stat) 10097.099 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13228.345 gnome-shell/1463 openat(dfd: CWD, filename: /proc/self/stat) 13232.734 gnome-shell/2125 openat(dfd: CWD, filename: /proc/self/stat) 15198.956 lighttpd/16748 open(filename: /proc/loadavg, mode: ISGID|IXOTH) ^C# It even catches 'perf' itself looking at the sys_enter_open and sys_enter_openat tracefs format dictionaries when it first finds them in the trace... :-) Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-upmogc57uatljr6el6u8537l@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/examples/bpf/augmented_syscalls.c | 27 ++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index 93960e891478..154379463c95 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -61,4 +61,31 @@ int syscall_enter(openat)(struct syscall_enter_openat_args *args) return 0; } +struct syscall_enter_open_args { + unsigned long long common_tp_fields; + long syscall_nr; + char *filename_ptr; + long flags; + long mode; +}; + +struct augmented_enter_open_args { + struct syscall_enter_open_args args; + struct augmented_filename filename; +}; + +int syscall_enter(open)(struct syscall_enter_open_args *args) +{ + struct augmented_enter_open_args augmented_args = { .filename.reserved = 0, }; + + probe_read(&augmented_args.args, sizeof(augmented_args.args), args); + augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, + sizeof(augmented_args.filename.value), + args->filename_ptr); + perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, + &augmented_args, + sizeof(augmented_args) - sizeof(augmented_args.filename.value) + augmented_args.filename.size); + return 0; +} + license(GPL); From 9779fc021410e7d8433d923a2202dac7e1384b05 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Aug 2018 13:21:36 -0300 Subject: [PATCH 008/155] perf trace: Augment inotify_add_watch pathname syscall arg Again, just changing tools/perf/examples/bpf/augmented_syscalls.c, that is starting to have too much boilerplate, some macro will come to the rescue. # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c 0.000 gmain/2590 inotify_add_watch(fd: 3, pathname: /var/cache/app-info/yaml, mask: 16789454) 0.023 gmain/2590 inotify_add_watch(fd: 3, pathname: /var/lib/app-info/xmls, mask: 16789454) 0.028 gmain/2590 inotify_add_watch(fd: 3, pathname: /var/lib/app-info/yaml, mask: 16789454) 0.032 gmain/2590 inotify_add_watch(fd: 3, pathname: /usr/share/app-info/yaml, mask: 16789454) 0.039 gmain/2590 inotify_add_watch(fd: 3, pathname: /usr/local/share/app-info/xmls, mask: 16789454) 0.045 gmain/2590 inotify_add_watch(fd: 3, pathname: /usr/local/share/app-info/yaml, mask: 16789454) 0.049 gmain/2590 inotify_add_watch(fd: 3, pathname: /home/acme/.local/share/app-info/yaml, mask: 16789454) 0.056 gmain/2590 inotify_add_watch(fd: 3, pathname: , mask: 16789454) 0.010 gmain/2245 inotify_add_watch(fd: 7, pathname: /home/acme/~, mask: 16789454) 0.087 perf/20116 openat(dfd: CWD, filename: /sys/kernel/debug/tracing/events/syscalls/sys_enter_inotify_add) 0.436 perf/20116 openat(dfd: CWD, filename: /sys/kernel/debug/tracing/events/syscalls/sys_enter_openat/form) 56.042 gmain/2791 inotify_add_watch(fd: 4, pathname: /var/lib/fwupd/remotes.d/lvfs-testing, mask: 16789454) 113.986 gmain/1721 inotify_add_watch(fd: 3, pathname: /var/lib/gdm/~, mask: 16789454) 3777.265 gsd-color/2408 openat(dfd: CWD, filename: /etc/localtime) 3777.550 gsd-color/2408 openat(dfd: CWD, filename: /etc/localtime) ^C[root@jouet perf]# Still not combining raw_syscalls:sys_enter + raw_syscalls:sys_exit, to get it strace-like, but that probably will come very naturally with some more wiring up... Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-ol83juin2cht9vzquynec5hz@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/examples/bpf/augmented_syscalls.c | 27 ++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index 154379463c95..6ec327850a15 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -88,4 +88,31 @@ int syscall_enter(open)(struct syscall_enter_open_args *args) return 0; } +struct syscall_enter_inotify_add_watch_args { + unsigned long long common_tp_fields; + long syscall_nr; + long fd; + char *pathname_ptr; + long mask; +}; + +struct augmented_enter_inotify_add_watch_args { + struct syscall_enter_inotify_add_watch_args args; + struct augmented_filename pathname; +}; + +int syscall_enter(inotify_add_watch)(struct syscall_enter_inotify_add_watch_args *args) +{ + struct augmented_enter_inotify_add_watch_args augmented_args = { .pathname.reserved = 0, }; + + probe_read(&augmented_args.args, sizeof(augmented_args.args), args); + augmented_args.pathname.size = probe_read_str(&augmented_args.pathname.value, + sizeof(augmented_args.pathname.value), + args->pathname_ptr); + perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, + &augmented_args, + sizeof(augmented_args) - sizeof(augmented_args.pathname.value) + augmented_args.pathname.size); + return 0; +} + license(GPL); From f6618ce6c024ec90b156700fc39eb313ec117881 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Aug 2018 13:44:49 -0300 Subject: [PATCH 009/155] perf trace: Introduce augmented_filename_syscall_enter() declarator Helping with tons of boilerplate for syscalls that only want to augment a filename. Now supporting one such syscall is just a matter of declaring its arguments struct + using: augmented_filename_syscall_enter(openat); Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-ls7ojdseu8fxw7fvj77ejpao@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/examples/bpf/augmented_syscalls.c | 78 ++++++-------------- 1 file changed, 23 insertions(+), 55 deletions(-) diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index 6ec327850a15..e8486e8597de 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -33,6 +33,25 @@ struct augmented_filename { char value[256]; }; +#define augmented_filename_syscall_enter(syscall) \ +struct augmented_enter_##syscall##_args { \ + struct syscall_enter_##syscall##_args args; \ + struct augmented_filename filename; \ +}; \ +int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \ +{ \ + struct augmented_enter_##syscall##_args augmented_args = { .filename.reserved = 0, }; \ + probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \ + augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, \ + sizeof(augmented_args.filename.value), \ + args->filename_ptr); \ + perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \ + &augmented_args, \ + (sizeof(augmented_args) - sizeof(augmented_args.filename.value) + \ + augmented_args.filename.size)); \ + return 0; \ +} + struct syscall_enter_openat_args { unsigned long long common_tp_fields; long syscall_nr; @@ -42,24 +61,7 @@ struct syscall_enter_openat_args { long mode; }; -struct augmented_enter_openat_args { - struct syscall_enter_openat_args args; - struct augmented_filename filename; -}; - -int syscall_enter(openat)(struct syscall_enter_openat_args *args) -{ - struct augmented_enter_openat_args augmented_args = { .filename.reserved = 0, }; - - probe_read(&augmented_args.args, sizeof(augmented_args.args), args); - augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, - sizeof(augmented_args.filename.value), - args->filename_ptr); - perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, - &augmented_args, - sizeof(augmented_args) - sizeof(augmented_args.filename.value) + augmented_args.filename.size); - return 0; -} +augmented_filename_syscall_enter(openat); struct syscall_enter_open_args { unsigned long long common_tp_fields; @@ -69,50 +71,16 @@ struct syscall_enter_open_args { long mode; }; -struct augmented_enter_open_args { - struct syscall_enter_open_args args; - struct augmented_filename filename; -}; - -int syscall_enter(open)(struct syscall_enter_open_args *args) -{ - struct augmented_enter_open_args augmented_args = { .filename.reserved = 0, }; - - probe_read(&augmented_args.args, sizeof(augmented_args.args), args); - augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, - sizeof(augmented_args.filename.value), - args->filename_ptr); - perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, - &augmented_args, - sizeof(augmented_args) - sizeof(augmented_args.filename.value) + augmented_args.filename.size); - return 0; -} +augmented_filename_syscall_enter(open); struct syscall_enter_inotify_add_watch_args { unsigned long long common_tp_fields; long syscall_nr; long fd; - char *pathname_ptr; + char *filename_ptr; long mask; }; -struct augmented_enter_inotify_add_watch_args { - struct syscall_enter_inotify_add_watch_args args; - struct augmented_filename pathname; -}; - -int syscall_enter(inotify_add_watch)(struct syscall_enter_inotify_add_watch_args *args) -{ - struct augmented_enter_inotify_add_watch_args augmented_args = { .pathname.reserved = 0, }; - - probe_read(&augmented_args.args, sizeof(augmented_args.args), args); - augmented_args.pathname.size = probe_read_str(&augmented_args.pathname.value, - sizeof(augmented_args.pathname.value), - args->pathname_ptr); - perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, - &augmented_args, - sizeof(augmented_args) - sizeof(augmented_args.pathname.value) + augmented_args.pathname.size); - return 0; -} +augmented_filename_syscall_enter(inotify_add_watch); license(GPL); From 16cc63593f67477e9ca62f10182e74e949af1acb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Aug 2018 13:55:50 -0300 Subject: [PATCH 010/155] perf trace: Augment 'newstat' (aka 'stat') filename ptr This one will need some more work, that 'statbuf' pointer requires a beautifier in 'perf trace'. # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c 0.000 weechat/3596 stat(filename: /etc/localtime, statbuf: 0x7ffd87d11f60) 0.186 perf/29818 openat(dfd: CWD, filename: /sys/kernel/debug/tracing/events/syscalls/sys_enter_stat/format) 0.279 perf/29818 openat(dfd: CWD, filename: /sys/kernel/debug/tracing/events/syscalls/sys_enter_newstat/for) 0.670 perf/29818 openat(dfd: CWD, filename: /sys/kernel/debug/tracing/events/syscalls/sys_enter_openat/form) 60.805 DNS Res~er #20/21308 stat(filename: /etc/resolv.conf, statbuf: 0x7ffa733fe4a0) 60.836 DNS Res~er #20/21308 open(filename: /etc/hosts, flags: CLOEXEC) 60.931 perf/29818 openat(dfd: CWD, filename: /sys/kernel/debug/tracing/events/syscalls/sys_enter_open/format) 607.070 DNS Res~er #21/29812 stat(filename: /etc/resolv.conf, statbuf: 0x7ffa5e1fe3f0) 607.098 DNS Res~er #21/29812 open(filename: /etc/hosts, flags: CLOEXEC) 999.336 weechat/3596 stat(filename: /etc/localtime, statbuf: 0x7ffd87d11f60) ^C# Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-4lhabe7m4uzo76lnqpyfmnvk@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/examples/bpf/augmented_syscalls.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index e8486e8597de..a9695c7f7aab 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -83,4 +83,15 @@ struct syscall_enter_inotify_add_watch_args { augmented_filename_syscall_enter(inotify_add_watch); +struct statbuf; + +struct syscall_enter_newstat_args { + unsigned long long common_tp_fields; + long syscall_nr; + char *filename_ptr; + struct stat *statbuf; +}; + +augmented_filename_syscall_enter(newstat); + license(GPL); From 9ab5aadebeddc77fccfdf94a048259315ce95fe1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Aug 2018 15:02:09 -0300 Subject: [PATCH 011/155] perf trace: Add a etcsnoop.c augmented syscalls eBPF utility We need to put common stuff into a separate header in tools/perf/include/bpf/ for these augmented syscalls, but I couldn't resist adding a etcsnoop.c tool, combining augmented syscalls + filtering, that in the future will be passed from 'perf trace''s command line, to use in building the eBPF program to do that specific filtering at the source, inside the kernel: Running system wide: (hope there isn't any embarassing stuff here... ;-) ) # perf trace -e tools/perf/examples/bpf/etcsnoop.c 0.000 sed/21878 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 1741.473 cat/21883 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 1741.892 cat/21883 openat(dfd: CWD, filename: /etc/passwd) 1748.948 sed/21886 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 1777.136 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1777.738 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1778.158 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1778.528 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1778.595 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1778.901 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1778.939 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1778.966 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1778.992 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.019 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.045 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.071 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.095 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.121 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.148 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.175 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.202 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.229 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.254 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.279 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.309 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.336 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.363 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.388 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.414 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.442 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.470 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.500 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.529 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.557 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.586 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.617 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.648 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.679 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.706 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.739 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.769 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.798 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.823 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.844 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.862 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.880 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.911 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.942 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1779.972 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1780.004 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 1780.035 gvfs-udisks2-v/2302 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 13059.154 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13060.739 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13061.990 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13063.177 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13064.265 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13065.483 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13067.383 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13068.902 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13069.922 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13070.915 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13072.612 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13074.816 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13077.343 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13078.731 NetworkManager/1237 open(filename: /etc/passwd, flags: CLOEXEC) 13559.064 DNS Res~er #22/21054 open(filename: /etc/hosts, flags: CLOEXEC) 22419.522 sed/21896 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 24473.313 git/21900 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 24491.988 less/21901 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 24493.793 git/21901 openat(dfd: CWD, filename: /etc/sysless) 24565.772 sed/21924 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 25878.752 git/21928 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 26075.666 git/21928 open(filename: /etc/localtime, flags: CLOEXEC) 26075.565 less/21929 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 26076.060 less/21929 openat(dfd: CWD, filename: /etc/sysless) 26346.395 sed/21932 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 26483.583 sed/21938 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 26954.890 sed/21944 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 27016.165 gsd-color/1762 openat(dfd: CWD, filename: /etc/localtime) 27016.414 gsd-color/1762 openat(dfd: CWD, filename: /etc/localtime) 27712.313 gsd-color/2408 openat(dfd: CWD, filename: /etc/localtime) 27712.616 gsd-color/2408 openat(dfd: CWD, filename: /etc/localtime) 27829.035 gnome-shell/2125 openat(dfd: CWD, filename: /etc/localtime) 27829.368 gnome-shell/2125 openat(dfd: CWD, filename: /etc/localtime) 27829.584 gnome-shell/2125 openat(dfd: CWD, filename: /etc/localtime) 27829.800 gnome-shell/2125 openat(dfd: CWD, filename: /etc/localtime) 27830.107 gnome-shell/2125 openat(dfd: CWD, filename: /etc/localtime) 27830.521 gnome-shell/2125 openat(dfd: CWD, filename: /etc/localtime) 27961.516 git/21948 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 27987.568 less/21949 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 27988.948 bash/21949 openat(dfd: CWD, filename: /etc/sysless) 28043.536 sed/21972 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 28736.008 sed/21978 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 34882.664 git/21991 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 34882.664 sort/21990 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 34884.441 uniq/21992 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 35593.098 git/21997 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 35638.839 git/21997 openat(dfd: CWD, filename: /etc/gitattributes) 35702.851 sed/22000 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 36076.039 sed/22006 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 37569.049 git/22014 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 37673.712 git/22014 open(filename: /etc/localtime, flags: CLOEXEC) 37781.710 vim/22040 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 37783.667 git/22040 openat(dfd: CWD, filename: /etc/vimrc) 37792.394 git/22040 open(filename: /etc/nsswitch.conf, flags: CLOEXEC) 37792.436 git/22040 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 37792.580 git/22040 open(filename: /etc/passwd, flags: CLOEXEC) 43893.625 DNS Res~er #23/21365 open(filename: /etc/hosts, flags: CLOEXEC) 48060.409 nm-dhcp-helper/22044 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48071.745 systemd/1 openat(dfd: CWD, filename: /etc/systemd/system/dbus-org.freedesktop.nm-dispatcher.service, flags: CLOEXEC|NOFOLLOW|NOCTTY) 48082.780 nm-dispatcher/22049 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48111.418 systemd/22049 open(filename: /etc/NetworkManager/dispatcher.d, flags: CLOEXEC|DIRECTORY|NONBLOCK) 48111.904 systemd/22049 open(filename: /etc/localtime, flags: CLOEXEC) 48118.357 00-netreport/22052 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48119.668 systemd/22052 open(filename: /etc/nsswitch.conf, flags: CLOEXEC) 48119.762 systemd/22052 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48119.887 systemd/22052 open(filename: /etc/passwd, flags: CLOEXEC) 48120.025 systemd/22052 openat(dfd: CWD, filename: /etc/NetworkManager/dispatcher.d/00-netreport) 48124.144 hostname/22054 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48125.492 systemd/22052 openat(dfd: CWD, filename: /etc/init.d/functions) 48127.253 systemd/22052 openat(dfd: CWD, filename: /etc/profile.d/lang.sh) 48127.388 systemd/22052 openat(dfd: CWD, filename: /etc/locale.conf) 48137.749 cat/22056 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48143.519 04-iscsi/22058 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48144.438 04-iscsi/22058 open(filename: /etc/nsswitch.conf, flags: CLOEXEC) 48144.478 04-iscsi/22058 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48144.577 04-iscsi/22058 open(filename: /etc/passwd, flags: CLOEXEC) 48144.819 04-iscsi/22058 openat(dfd: CWD, filename: /etc/NetworkManager/dispatcher.d/04-iscsi) 48145.620 10-ifcfg-rh-ro/22059 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48146.169 systemd/22059 open(filename: /etc/nsswitch.conf, flags: CLOEXEC) 48146.207 systemd/22059 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48146.287 systemd/22059 open(filename: /etc/passwd, flags: CLOEXEC) 48146.387 systemd/22059 openat(dfd: CWD, filename: /etc/NetworkManager/dispatcher.d/10-ifcfg-rh-routes.sh) 48147.215 11-dhclient/22060 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48147.787 11-dhclient/22060 open(filename: /etc/nsswitch.conf, flags: CLOEXEC) 48147.813 11-dhclient/22060 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48147.929 11-dhclient/22060 open(filename: /etc/passwd, flags: CLOEXEC) 48148.016 11-dhclient/22060 openat(dfd: CWD, filename: /etc/NetworkManager/dispatcher.d/11-dhclient) 48148.906 grep/22063 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48151.165 11-dhclient/22060 openat(dfd: CWD, filename: /etc/sysconfig/network) 48151.560 11-dhclient/22060 open(filename: /etc/dhcp/dhclient.d/, flags: CLOEXEC|DIRECTORY|NONBLOCK) 48151.704 11-dhclient/22060 openat(dfd: CWD, filename: /etc/dhcp/dhclient.d/chrony.sh) 48153.593 20-chrony/22065 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48154.695 20-chrony/22065 open(filename: /etc/nsswitch.conf, flags: CLOEXEC) 48154.756 20-chrony/22065 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48154.914 20-chrony/22065 open(filename: /etc/passwd, flags: CLOEXEC) 48155.067 20-chrony/22065 openat(dfd: CWD, filename: /etc/NetworkManager/dispatcher.d/20-chrony) 48156.962 25-polipo/22066 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48157.824 systemd/22066 open(filename: /etc/nsswitch.conf, flags: CLOEXEC) 48157.866 systemd/22066 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 48157.981 systemd/22066 open(filename: /etc/passwd, flags: CLOEXEC) 48158.090 systemd/22066 openat(dfd: CWD, filename: /etc/NetworkManager/dispatcher.d/25-polipo) 48533.616 gsd-housekeepi/2412 openat(dfd: CWD, filename: /etc/fstab, flags: CLOEXEC) 87122.021 gsd-color/1762 openat(dfd: CWD, filename: /etc/localtime) 87122.146 gsd-color/1762 openat(dfd: CWD, filename: /etc/localtime) 87825.582 gsd-color/2408 openat(dfd: CWD, filename: /etc/localtime) 87825.844 gsd-color/2408 openat(dfd: CWD, filename: /etc/localtime) 87829.524 gnome-shell/2125 openat(dfd: CWD, filename: /etc/localtime) 87830.531 gnome-shell/2125 openat(dfd: CWD, filename: /etc/localtime) 87831.288 gnome-shell/2125 openat(dfd: CWD, filename: /etc/localtime) 87832.011 gnome-shell/2125 openat(dfd: CWD, filename: /etc/localtime) 87832.672 gnome-shell/2125 openat(dfd: CWD, filename: /etc/localtime) 87833.276 gnome-shell/2125 openat(dfd: CWD, filename: /etc/localtime) ^C# Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-0o770jvdcy04ee6vhv6v471m@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/examples/bpf/etcsnoop.c | 80 ++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 tools/perf/examples/bpf/etcsnoop.c diff --git a/tools/perf/examples/bpf/etcsnoop.c b/tools/perf/examples/bpf/etcsnoop.c new file mode 100644 index 000000000000..b59e8812ee8c --- /dev/null +++ b/tools/perf/examples/bpf/etcsnoop.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Augment the filename syscalls with the contents of the filename pointer argument + * filtering only those that do not start with /etc/. + * + * Test it with: + * + * perf trace -e tools/perf/examples/bpf/augmented_syscalls.c cat /etc/passwd > /dev/null + * + * It'll catch some openat syscalls related to the dynamic linked and + * the last one should be the one for '/etc/passwd'. + * + * This matches what is marshalled into the raw_syscall:sys_enter payload + * expected by the 'perf trace' beautifiers, and can be used by them unmodified, + * which will be done as that feature is implemented in the next csets, for now + * it will appear in a dump done by the default tracepoint handler in 'perf trace', + * that uses bpf_output__fprintf() to just dump those contents, as done with + * the bpf-output event associated with the __bpf_output__ map declared in + * tools/perf/include/bpf/stdio.h. + */ + +#include + +struct bpf_map SEC("maps") __augmented_syscalls__ = { + .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, + .key_size = sizeof(int), + .value_size = sizeof(u32), + .max_entries = __NR_CPUS__, +}; + +struct augmented_filename { + int size; + int reserved; + char value[64]; +}; + +#define augmented_filename_syscall_enter(syscall) \ +struct augmented_enter_##syscall##_args { \ + struct syscall_enter_##syscall##_args args; \ + struct augmented_filename filename; \ +}; \ +int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \ +{ \ + char etc[6] = "/etc/"; \ + struct augmented_enter_##syscall##_args augmented_args = { .filename.reserved = 0, }; \ + probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \ + augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, \ + sizeof(augmented_args.filename.value), \ + args->filename_ptr); \ + if (__builtin_memcmp(augmented_args.filename.value, etc, 4) != 0) \ + return 0; \ + perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \ + &augmented_args, \ + (sizeof(augmented_args) - sizeof(augmented_args.filename.value) + \ + augmented_args.filename.size)); \ + return 0; \ +} + +struct syscall_enter_openat_args { + unsigned long long common_tp_fields; + long syscall_nr; + long dfd; + char *filename_ptr; + long flags; + long mode; +}; + +augmented_filename_syscall_enter(openat); + +struct syscall_enter_open_args { + unsigned long long common_tp_fields; + long syscall_nr; + char *filename_ptr; + long flags; + long mode; +}; + +augmented_filename_syscall_enter(open); + +license(GPL); From d35b168c3dcdf103c2b2d694ad8513a669781703 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 29 Aug 2018 23:53:22 -0300 Subject: [PATCH 012/155] perf bpf: Give precedence to bpf header dir I need to check the need for $KERNEL_INC_OPTIONS when building eBPF restricted C programs, for now just give precedence to $PERF_BPF_INC_OPTIONS so that we can get a linux/socket.h usable in eBPF programs. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-5z7qw529sdebrn9y1xxqw9hf@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/llvm-utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c index 19262f98cd4e..5b0b60f00275 100644 --- a/tools/perf/util/llvm-utils.c +++ b/tools/perf/util/llvm-utils.c @@ -19,7 +19,7 @@ #define CLANG_BPF_CMD_DEFAULT_TEMPLATE \ "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\ "-DLINUX_VERSION_CODE=$LINUX_VERSION_CODE " \ - "$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \ + "$CLANG_OPTIONS $PERF_BPF_INC_OPTIONS $KERNEL_INC_OPTIONS " \ "-Wno-unused-value -Wno-pointer-sign " \ "-working-directory $WORKING_DIR " \ "-c \"$CLANG_SOURCE\" -target bpf $CLANG_EMIT_LLVM -O2 -o - $LLVM_OPTIONS_PIPE" From 403f833d15a33bfd8e50dd79fa8e25fb4aa132f6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 29 Aug 2018 17:41:53 -0300 Subject: [PATCH 013/155] perf bpf: Add linux/socket.h to the headers accessible to bpf proggies So that we don't have to define sockaddr_storage in the augmented_syscalls.c bpf example when hooking into syscalls needing it, idea is to mimic the system headers. Eventually we probably need to have sys/socket.h, etc. Start by having at least linux/socket.h. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-yhzarcvsjue8pgpvkjhqgioc@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 4 +++- tools/perf/include/bpf/linux/socket.h | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tools/perf/include/bpf/linux/socket.h diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 5224ade3d5af..92514fb3689f 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -779,7 +779,9 @@ endif ifndef NO_LIBBPF $(call QUIET_INSTALL, bpf-headers) \ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'; \ - $(INSTALL) include/bpf/*.h -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf' + $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf/linux'; \ + $(INSTALL) include/bpf/*.h -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'; \ + $(INSTALL) include/bpf/linux/*.h -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf/linux' $(call QUIET_INSTALL, bpf-examples) \ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'; \ $(INSTALL) examples/bpf/*.c -t '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf' diff --git a/tools/perf/include/bpf/linux/socket.h b/tools/perf/include/bpf/linux/socket.h new file mode 100644 index 000000000000..7f844568dab8 --- /dev/null +++ b/tools/perf/include/bpf/linux/socket.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_LINUX_SOCKET_H +#define _UAPI_LINUX_SOCKET_H + +/* + * Desired design of maximum size and alignment (see RFC2553) + */ +#define _K_SS_MAXSIZE 128 /* Implementation specific max size */ +#define _K_SS_ALIGNSIZE (__alignof__ (struct sockaddr *)) + /* Implementation specific desired alignment */ + +typedef unsigned short __kernel_sa_family_t; + +struct __kernel_sockaddr_storage { + __kernel_sa_family_t ss_family; /* address family */ + /* Following field(s) are implementation specific */ + char __data[_K_SS_MAXSIZE - sizeof(unsigned short)]; + /* space to achieve desired size, */ + /* _SS_MAXSIZE value minus size of ss_family */ +} __attribute__ ((aligned(_K_SS_ALIGNSIZE))); /* force desired alignment */ + +#define sockaddr_storage __kernel_sockaddr_storage + +#endif /* _UAPI_LINUX_SOCKET_H */ From d5a7e6613b00d46a4971e8b69e18e2cfd7b00df3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 28 Aug 2018 16:24:44 -0300 Subject: [PATCH 014/155] perf trace augmented_syscalls: Augment connect's 'sockaddr' arg As the first example of augmenting something other than a 'filename', augment the 'struct sockaddr' argument for the 'connect' syscall: # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c ssh -6 fedorapeople.org 0.000 ssh/29669 connect(fd: 3, uservaddr: { .family: LOCAL, path: /var/run/nscd/socket }, addrlen: 110) 0.042 ssh/29669 connect(fd: 3, uservaddr: { .family: LOCAL, path: /var/run/nscd/socket }, addrlen: 110) 1.329 ssh/29669 connect(fd: 3, uservaddr: { .family: LOCAL, path: /var/run/nscd/socket }, addrlen: 110) 1.362 ssh/29669 connect(fd: 3, uservaddr: { .family: LOCAL, path: /var/run/nscd/socket }, addrlen: 110) 1.458 ssh/29669 connect(fd: 3, uservaddr: { .family: LOCAL, path: /var/run/nscd/socket }, addrlen: 110) 1.478 ssh/29669 connect(fd: 3, uservaddr: { .family: LOCAL, path: /var/run/nscd/socket }, addrlen: 110) 1.683 ssh/29669 connect(fd: 3, uservaddr: { .family: INET, port: 53, addr: 192.168.43.1 }, addrlen: 16) 4.710 ssh/29669 connect(fd: 3, uservaddr: { .family: INET6, port: 22, addr: 2610:28:3090:3001:5054:ff:fea7:9474 }, addrlen: 28) root@fedorapeople.org: Permission denied (publickey). # This is still just augmenting the syscalls:sys_enter_connect part, later we'll wire this up to augment the enter+exit combo, like in the tradicional 'perf trace' and 'strace' outputs. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-s7l541cbiqb22ifio6z7dpf6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 12 +--- tools/perf/examples/bpf/augmented_syscalls.c | 34 +++++++++++- tools/perf/trace/beauty/Build | 1 + tools/perf/trace/beauty/beauty.h | 5 ++ tools/perf/trace/beauty/sockaddr.c | 58 ++++++++++++++++++++ 5 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 tools/perf/trace/beauty/sockaddr.c diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 5d841114a745..ab2ed30b8dcc 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -498,16 +498,6 @@ static const char *clockid[] = { }; static DEFINE_STRARRAY(clockid); -static const char *socket_families[] = { - "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM", - "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI", - "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC", - "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC", - "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF", - "ALG", "NFC", "VSOCK", -}; -static DEFINE_STRARRAY(socket_families); - static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size, struct syscall_arg *arg) { @@ -645,6 +635,8 @@ static struct syscall_fmt { [4] = { .name = "tls", .scnprintf = SCA_HEX, }, }, }, { .name = "close", .arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, }, + { .name = "connect", + .arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* servaddr */ }, }, }, { .name = "epoll_ctl", .arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, }, { .name = "eventfd2", diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index a9695c7f7aab..6dfead0be74e 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -19,6 +19,7 @@ */ #include +#include struct bpf_map SEC("maps") __augmented_syscalls__ = { .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, @@ -33,7 +34,7 @@ struct augmented_filename { char value[256]; }; -#define augmented_filename_syscall_enter(syscall) \ +#define augmented_filename_syscall_enter(syscall) \ struct augmented_enter_##syscall##_args { \ struct syscall_enter_##syscall##_args args; \ struct augmented_filename filename; \ @@ -94,4 +95,35 @@ struct syscall_enter_newstat_args { augmented_filename_syscall_enter(newstat); +struct sockaddr; + +struct syscall_enter_connect_args { + unsigned long long common_tp_fields; + long syscall_nr; + long fd; + struct sockaddr *addr_ptr; + unsigned long addrlen; +}; + +struct augmented_enter_connect_args { + struct syscall_enter_connect_args args; + struct sockaddr_storage addr; +}; + +int syscall_enter(connect)(struct syscall_enter_connect_args *args) +{ + struct augmented_enter_connect_args augmented_args; + unsigned long addrlen = sizeof(augmented_args.addr); + + probe_read(&augmented_args.args, sizeof(augmented_args.args), args); +#ifdef FIXME_CLANG_OPTIMIZATION_THAT_ACCESSES_USER_CONTROLLED_ADDRLEN_DESPITE_THIS_CHECK + if (addrlen > augmented_args.args.addrlen) + addrlen = augmented_args.args.addrlen; +#endif + probe_read(&augmented_args.addr, addrlen, args->addr_ptr); + perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, &augmented_args, + sizeof(augmented_args) - sizeof(augmented_args.addr) + addrlen); + return 0; +} + license(GPL); diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build index f528ba35e140..c3b0afd67760 100644 --- a/tools/perf/trace/beauty/Build +++ b/tools/perf/trace/beauty/Build @@ -7,5 +7,6 @@ endif libperf-y += kcmp.o libperf-y += pkey_alloc.o libperf-y += prctl.o +libperf-y += sockaddr.o libperf-y += socket.o libperf-y += statx.o diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h index 6ca044d3d851..2570152d3909 100644 --- a/tools/perf/trace/beauty/beauty.h +++ b/tools/perf/trace/beauty/beauty.h @@ -30,6 +30,8 @@ struct thread; size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_t size); +extern struct strarray strarray__socket_families; + /** * augmented_arg: extra payload for syscall pointer arguments @@ -135,6 +137,9 @@ size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_a size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg); #define SCA_PRCTL_ARG3 syscall_arg__scnprintf_prctl_arg3 +size_t syscall_arg__scnprintf_sockaddr(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_SOCKADDR syscall_arg__scnprintf_sockaddr + size_t syscall_arg__scnprintf_socket_protocol(char *bf, size_t size, struct syscall_arg *arg); #define SCA_SK_PROTO syscall_arg__scnprintf_socket_protocol diff --git a/tools/perf/trace/beauty/sockaddr.c b/tools/perf/trace/beauty/sockaddr.c new file mode 100644 index 000000000000..3944a7d54d3c --- /dev/null +++ b/tools/perf/trace/beauty/sockaddr.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo + +#include "trace/beauty/beauty.h" +#include +#include +#include +#include + +static const char *socket_families[] = { + "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM", + "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI", + "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC", + "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC", + "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF", + "ALG", "NFC", "VSOCK", +}; +DEFINE_STRARRAY(socket_families); + +static size_t syscall_arg__scnprintf_augmented_sockaddr(struct syscall_arg *arg, char *bf, size_t size) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)arg->augmented.args; + char family[32]; + size_t printed; + + strarray__scnprintf(&strarray__socket_families, family, sizeof(family), "%d", sin->sin_family); + printed = scnprintf(bf, size, "{ .family: %s", family); + + if (sin->sin_family == AF_INET) { + char tmp[512]; + printed += scnprintf(bf + printed, size - printed, ", port: %d, addr: %s", ntohs(sin->sin_port), + inet_ntop(sin->sin_family, &sin->sin_addr, tmp, sizeof(tmp))); + } else if (sin->sin_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sin; + u32 flowinfo = ntohl(sin6->sin6_flowinfo); + char tmp[512]; + + printed += scnprintf(bf + printed, size - printed, ", port: %d, addr: %s", ntohs(sin6->sin6_port), + inet_ntop(sin6->sin6_family, &sin6->sin6_addr, tmp, sizeof(tmp))); + if (flowinfo != 0) + printed += scnprintf(bf + printed, size - printed, ", flowinfo: %lu", flowinfo); + if (sin6->sin6_scope_id != 0) + printed += scnprintf(bf + printed, size - printed, ", scope_id: %lu", sin6->sin6_scope_id); + } else if (sin->sin_family == AF_LOCAL) { + struct sockaddr_un *sun = (struct sockaddr_un *)sin; + printed += scnprintf(bf + printed, size - printed, ", path: %s", sun->sun_path); + } + + return printed + scnprintf(bf + printed, size - printed, " }"); +} + +size_t syscall_arg__scnprintf_sockaddr(char *bf, size_t size, struct syscall_arg *arg) +{ + if (arg->augmented.args) + return syscall_arg__scnprintf_augmented_sockaddr(arg, bf, size); + + return scnprintf(bf, size, "%#x", arg->val); +} From 24a6c2cd1dbd85bd5624a6d0b05de891d0f07696 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 28 Aug 2018 16:39:11 -0300 Subject: [PATCH 015/155] perf trace augmented_syscalls: Add augmented_sockaddr_syscall_enter() From the one for 'connect', so that we can use it with sendto and others that receive a 'struct sockaddr'. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-8bdqv1q0ndcjl1nqns5r5je2@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/examples/bpf/augmented_syscalls.c | 46 +++++++++++--------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index 6dfead0be74e..5f417e528419 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -95,6 +95,31 @@ struct syscall_enter_newstat_args { augmented_filename_syscall_enter(newstat); +#ifndef _K_SS_MAXSIZE +#define _K_SS_MAXSIZE 128 +#endif + +#define augmented_sockaddr_syscall_enter(syscall) \ +struct augmented_enter_##syscall##_args { \ + struct syscall_enter_##syscall##_args args; \ + struct sockaddr_storage addr; \ +}; \ +int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \ +{ \ + struct augmented_enter_##syscall##_args augmented_args; \ + unsigned long addrlen = sizeof(augmented_args.addr); \ + probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \ +/* FIXME_CLANG_OPTIMIZATION_THAT_ACCESSES_USER_CONTROLLED_ADDRLEN_DESPITE_THIS_CHECK */ \ +/* if (addrlen > augmented_args.args.addrlen) */ \ +/* addrlen = augmented_args.args.addrlen; */ \ +/* */ \ + probe_read(&augmented_args.addr, addrlen, args->addr_ptr); \ + perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \ + &augmented_args, \ + sizeof(augmented_args) - sizeof(augmented_args.addr) + addrlen); \ + return 0; \ +} + struct sockaddr; struct syscall_enter_connect_args { @@ -105,25 +130,6 @@ struct syscall_enter_connect_args { unsigned long addrlen; }; -struct augmented_enter_connect_args { - struct syscall_enter_connect_args args; - struct sockaddr_storage addr; -}; - -int syscall_enter(connect)(struct syscall_enter_connect_args *args) -{ - struct augmented_enter_connect_args augmented_args; - unsigned long addrlen = sizeof(augmented_args.addr); - - probe_read(&augmented_args.args, sizeof(augmented_args.args), args); -#ifdef FIXME_CLANG_OPTIMIZATION_THAT_ACCESSES_USER_CONTROLLED_ADDRLEN_DESPITE_THIS_CHECK - if (addrlen > augmented_args.args.addrlen) - addrlen = augmented_args.args.addrlen; -#endif - probe_read(&augmented_args.addr, addrlen, args->addr_ptr); - perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, &augmented_args, - sizeof(augmented_args) - sizeof(augmented_args.addr) + addrlen); - return 0; -} +augmented_sockaddr_syscall_enter(connect); license(GPL); From 02ef288420775542316e41dc610a6a88725aa83a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 28 Aug 2018 17:03:53 -0300 Subject: [PATCH 016/155] perf trace augmented_syscalls: Augment bind's 'myaddr' sockaddr arg One more, to reuse the augmented_sockaddr_syscall_enter() macro introduced from the augmentation of connect's sockaddr arg, also to get a subset of the struct arg augmentations done using the manual method, before switching to something automatic, using tracefs's format file or, even better, BTF containing the syscall args structs. # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c 0.000 sshd/11479 bind(fd: 3, umyaddr: { .family: NETLINK }, addrlen: 12) 1.752 sshd/11479 bind(fd: 3, umyaddr: { .family: INET, port: 22, addr: 0.0.0.0 }, addrlen: 16) 1.924 sshd/11479 bind(fd: 4, umyaddr: { .family: INET6, port: 22, addr: :: }, addrlen: 28) ^C# Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-a2drqpahpmc7uwb3n3gj2plu@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 2 ++ tools/perf/examples/bpf/augmented_syscalls.c | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index ab2ed30b8dcc..537bb30895df 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -621,6 +621,8 @@ static struct syscall_fmt { } syscall_fmts[] = { { .name = "access", .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, }, + { .name = "bind", + .arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* umyaddr */ }, }, }, { .name = "bpf", .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, }, { .name = "brk", .hexret = true, diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index 5f417e528419..71edb7ad8698 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -122,6 +122,16 @@ int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \ struct sockaddr; +struct syscall_enter_bind_args { + unsigned long long common_tp_fields; + long syscall_nr; + long fd; + struct sockaddr *addr_ptr; + unsigned long addrlen; +}; + +augmented_sockaddr_syscall_enter(bind); + struct syscall_enter_connect_args { unsigned long long common_tp_fields; long syscall_nr; From 6ebb686225a83200b94777cfc651c94f4e0f6f50 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 29 Aug 2018 08:47:08 -0300 Subject: [PATCH 017/155] perf trace augmented_syscalls: Augment sendto's 'addr' arg Its a 'struct sockaddr' pointer, augment it with the same beautifier as for 'connect' and 'bind', that all receive from userspace that pointer. Doing it in the other direction remains to be done, hooking at the syscalls:sys_exit_{accept4?,recvmsg} tracepoints somehow. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-k2eu68lsphnm2fthc32gq76c@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 3 ++- tools/perf/examples/bpf/augmented_syscalls.c | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 537bb30895df..759d14e3fe6b 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -795,7 +795,8 @@ static struct syscall_fmt { { .name = "sendmsg", .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, }, { .name = "sendto", - .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, }, + .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, + [4] = { .scnprintf = SCA_SOCKADDR, /* addr */ }, }, }, { .name = "set_tid_address", .errpid = true, }, { .name = "setitimer", .arg = { [0] = STRARRAY(which, itimers), }, }, diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index 71edb7ad8698..be06d2c9e8c9 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -142,4 +142,17 @@ struct syscall_enter_connect_args { augmented_sockaddr_syscall_enter(connect); +struct syscall_enter_sendto_args { + unsigned long long common_tp_fields; + long syscall_nr; + long fd; + void *buff; + long len; + unsigned long flags; + struct sockaddr *addr_ptr; + long addr_len; +}; + +augmented_sockaddr_syscall_enter(sendto); + license(GPL); From b043cb524d2892be75c78bc348e83863829d50a0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 29 Aug 2018 17:11:33 -0300 Subject: [PATCH 018/155] perf trace beauty: Reorganize 'struct sockaddr *' beautifier Use an array to multiplex by sockaddr->sa_family, this way adding new families gets a bit easier and tidy. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-v3s85ra659tc40g1s1xaqoun@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/trace/beauty/sockaddr.c | 60 +++++++++++++++++++----------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/tools/perf/trace/beauty/sockaddr.c b/tools/perf/trace/beauty/sockaddr.c index 3944a7d54d3c..71a79f72d9d9 100644 --- a/tools/perf/trace/beauty/sockaddr.c +++ b/tools/perf/trace/beauty/sockaddr.c @@ -17,34 +17,52 @@ static const char *socket_families[] = { }; DEFINE_STRARRAY(socket_families); +static size_t af_inet__scnprintf(struct sockaddr *sa, char *bf, size_t size) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + char tmp[16]; + return scnprintf(bf, size, ", port: %d, addr: %s", ntohs(sin->sin_port), + inet_ntop(sin->sin_family, &sin->sin_addr, tmp, sizeof(tmp))); +} + +static size_t af_inet6__scnprintf(struct sockaddr *sa, char *bf, size_t size) +{ + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + u32 flowinfo = ntohl(sin6->sin6_flowinfo); + char tmp[512]; + size_t printed = scnprintf(bf, size, ", port: %d, addr: %s", ntohs(sin6->sin6_port), + inet_ntop(sin6->sin6_family, &sin6->sin6_addr, tmp, sizeof(tmp))); + if (flowinfo != 0) + printed += scnprintf(bf + printed, size - printed, ", flowinfo: %lu", flowinfo); + if (sin6->sin6_scope_id != 0) + printed += scnprintf(bf + printed, size - printed, ", scope_id: %lu", sin6->sin6_scope_id); + + return printed; +} + +static size_t af_local__scnprintf(struct sockaddr *sa, char *bf, size_t size) +{ + struct sockaddr_un *sun = (struct sockaddr_un *)sa; + return scnprintf(bf, size, ", path: %s", sun->sun_path); +} + +static size_t (*af_scnprintfs[])(struct sockaddr *sa, char *bf, size_t size) = { + [AF_LOCAL] = af_local__scnprintf, + [AF_INET] = af_inet__scnprintf, + [AF_INET6] = af_inet6__scnprintf, +}; + static size_t syscall_arg__scnprintf_augmented_sockaddr(struct syscall_arg *arg, char *bf, size_t size) { - struct sockaddr_in *sin = (struct sockaddr_in *)arg->augmented.args; + struct sockaddr *sa = (struct sockaddr *)arg->augmented.args; char family[32]; size_t printed; - strarray__scnprintf(&strarray__socket_families, family, sizeof(family), "%d", sin->sin_family); + strarray__scnprintf(&strarray__socket_families, family, sizeof(family), "%d", sa->sa_family); printed = scnprintf(bf, size, "{ .family: %s", family); - if (sin->sin_family == AF_INET) { - char tmp[512]; - printed += scnprintf(bf + printed, size - printed, ", port: %d, addr: %s", ntohs(sin->sin_port), - inet_ntop(sin->sin_family, &sin->sin_addr, tmp, sizeof(tmp))); - } else if (sin->sin_family == AF_INET6) { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sin; - u32 flowinfo = ntohl(sin6->sin6_flowinfo); - char tmp[512]; - - printed += scnprintf(bf + printed, size - printed, ", port: %d, addr: %s", ntohs(sin6->sin6_port), - inet_ntop(sin6->sin6_family, &sin6->sin6_addr, tmp, sizeof(tmp))); - if (flowinfo != 0) - printed += scnprintf(bf + printed, size - printed, ", flowinfo: %lu", flowinfo); - if (sin6->sin6_scope_id != 0) - printed += scnprintf(bf + printed, size - printed, ", scope_id: %lu", sin6->sin6_scope_id); - } else if (sin->sin_family == AF_LOCAL) { - struct sockaddr_un *sun = (struct sockaddr_un *)sin; - printed += scnprintf(bf + printed, size - printed, ", path: %s", sun->sun_path); - } + if (sa->sa_family < ARRAY_SIZE(af_scnprintfs) && af_scnprintfs[sa->sa_family]) + printed += af_scnprintfs[sa->sa_family](sa, bf + printed, size - printed); return printed + scnprintf(bf + printed, size - printed, " }"); } From 766e0618e49490bf67a35542880bcecbcee2e5fa Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Thu, 9 Aug 2018 06:56:50 +0200 Subject: [PATCH 019/155] perf report: Create auxiliary trace data files for s390 Create auxiliary trace data log files when invoked with option --itrace=d as in: [root@s35lp76 perf] perf report -i perf.data.aux1 --stdio --itrace=d perf report creates several data files in the current directory named aux.smp.## where ## is a 2 digit hex number with leading zeros representing the CPU number this trace data was recorded from. The file contents is binary and contains the CPU-Measurement Sampling Data Blocks (SDBs). The directory to save the auxiliary trace buffer can be changed using the perf config file and command. Specify section 'auxtrace' keyword 'dumpdir' and assign it a valid directory name. If the directory does not exist or has the wrong file type, the current directory is used. [root@p23lp27 perf]# perf config auxtrace.dumpdir=/tmp [root@p23lp27 perf]# perf config --user -l auxtrace.dumpdir=/tmp [root@p23lp27 perf]# perf report ... [root@p23lp27 perf]# ll /tmp/aux.smp.00 -rw-r--r-- 1 root root 204800 Aug 2 13:48 /tmp/aux.smp.00 [root@p23lp27 perf]# Signed-off-by: Thomas Richter Reviewed-by: Hendrik Brueckner Cc: Heiko Carstens Cc: Martin Schwidefsky Link: http://lkml.kernel.org/r/20180809045650.89197-1-tmricht@linux.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/s390-cpumsf.c | 94 +++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/s390-cpumsf.c b/tools/perf/util/s390-cpumsf.c index d2c78ffd9fee..a2eeebbfb25f 100644 --- a/tools/perf/util/s390-cpumsf.c +++ b/tools/perf/util/s390-cpumsf.c @@ -147,6 +147,9 @@ #include #include +#include +#include + #include "cpumap.h" #include "color.h" #include "evsel.h" @@ -159,6 +162,7 @@ #include "auxtrace.h" #include "s390-cpumsf.h" #include "s390-cpumsf-kernel.h" +#include "config.h" struct s390_cpumsf { struct auxtrace auxtrace; @@ -170,6 +174,8 @@ struct s390_cpumsf { u32 pmu_type; u16 machine_type; bool data_queued; + bool use_logfile; + char *logdir; }; struct s390_cpumsf_queue { @@ -177,6 +183,7 @@ struct s390_cpumsf_queue { unsigned int queue_nr; struct auxtrace_buffer *buffer; int cpu; + FILE *logfile; }; /* Display s390 CPU measurement facility basic-sampling data entry */ @@ -595,6 +602,12 @@ static int s390_cpumsf_run_decoder(struct s390_cpumsf_queue *sfq, buffer->use_size = buffer->size; buffer->use_data = buffer->data; } + if (sfq->logfile) { /* Write into log file */ + size_t rc = fwrite(buffer->data, buffer->size, 1, + sfq->logfile); + if (rc != 1) + pr_err("Failed to write auxiliary data\n"); + } } else buffer = sfq->buffer; @@ -606,6 +619,13 @@ static int s390_cpumsf_run_decoder(struct s390_cpumsf_queue *sfq, return -ENOMEM; buffer->use_size = buffer->size; buffer->use_data = buffer->data; + + if (sfq->logfile) { /* Write into log file */ + size_t rc = fwrite(buffer->data, buffer->size, 1, + sfq->logfile); + if (rc != 1) + pr_err("Failed to write auxiliary data\n"); + } } pr_debug4("%s queue_nr:%d buffer:%" PRId64 " offset:%#" PRIx64 " size:%#zx rest:%#zx\n", __func__, sfq->queue_nr, buffer->buffer_nr, buffer->offset, @@ -640,6 +660,23 @@ s390_cpumsf_alloc_queue(struct s390_cpumsf *sf, unsigned int queue_nr) sfq->sf = sf; sfq->queue_nr = queue_nr; sfq->cpu = -1; + if (sf->use_logfile) { + char *name; + int rc; + + rc = (sf->logdir) + ? asprintf(&name, "%s/aux.smp.%02x", + sf->logdir, queue_nr) + : asprintf(&name, "aux.smp.%02x", queue_nr); + if (rc > 0) + sfq->logfile = fopen(name, "w"); + if (sfq->logfile == NULL) { + pr_err("Failed to open auxiliary log file %s," + "continue...\n", name); + sf->use_logfile = false; + } + free(name); + } return sfq; } @@ -850,8 +887,16 @@ static void s390_cpumsf_free_queues(struct perf_session *session) struct auxtrace_queues *queues = &sf->queues; unsigned int i; - for (i = 0; i < queues->nr_queues; i++) + for (i = 0; i < queues->nr_queues; i++) { + struct s390_cpumsf_queue *sfq = (struct s390_cpumsf_queue *) + queues->queue_array[i].priv; + + if (sfq != NULL && sfq->logfile) { + fclose(sfq->logfile); + sfq->logfile = NULL; + } zfree(&queues->queue_array[i].priv); + } auxtrace_queues__free(queues); } @@ -864,6 +909,7 @@ static void s390_cpumsf_free(struct perf_session *session) auxtrace_heap__free(&sf->heap); s390_cpumsf_free_queues(session); session->auxtrace = NULL; + free(sf->logdir); free(sf); } @@ -877,17 +923,55 @@ static int s390_cpumsf_get_type(const char *cpuid) /* Check itrace options set on perf report command. * Return true, if none are set or all options specified can be - * handled on s390. + * handled on s390 (currently only option 'd' for logging. * Return false otherwise. */ static bool check_auxtrace_itrace(struct itrace_synth_opts *itops) { + bool ison = false; + if (!itops || !itops->set) return true; - pr_err("No --itrace options supported\n"); + ison = itops->inject || itops->instructions || itops->branches || + itops->transactions || itops->ptwrites || + itops->pwr_events || itops->errors || + itops->dont_decode || itops->calls || itops->returns || + itops->callchain || itops->thread_stack || + itops->last_branch; + if (!ison) + return true; + pr_err("Unsupported --itrace options specified\n"); return false; } +/* Check for AUXTRACE dump directory if it is needed. + * On failure print an error message but continue. + * Return 0 on wrong keyword in config file and 1 otherwise. + */ +static int s390_cpumsf__config(const char *var, const char *value, void *cb) +{ + struct s390_cpumsf *sf = cb; + struct stat stbuf; + int rc; + + if (strcmp(var, "auxtrace.dumpdir")) + return 0; + sf->logdir = strdup(value); + if (sf->logdir == NULL) { + pr_err("Failed to find auxtrace log directory %s," + " continue with current directory...\n", value); + return 1; + } + rc = stat(sf->logdir, &stbuf); + if (rc == -1 || !S_ISDIR(stbuf.st_mode)) { + pr_err("Missing auxtrace log directory %s," + " continue with current directory...\n", value); + free(sf->logdir); + sf->logdir = NULL; + } + return 1; +} + int s390_cpumsf_process_auxtrace_info(union perf_event *event, struct perf_session *session) { @@ -906,6 +990,9 @@ int s390_cpumsf_process_auxtrace_info(union perf_event *event, err = -EINVAL; goto err_free; } + sf->use_logfile = session->itrace_synth_opts->log; + if (sf->use_logfile) + perf_config(s390_cpumsf__config, sf); err = auxtrace_queues__init(&sf->queues); if (err) @@ -940,6 +1027,7 @@ err_free_queues: auxtrace_queues__free(&sf->queues); session->auxtrace = NULL; err_free: + free(sf->logdir); free(sf); return err; } From 266b851cc2874774a59f04a7b3b059ca0f26569b Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Tue, 28 Aug 2018 18:50:38 -0400 Subject: [PATCH 020/155] tools lib traceevent, perf tools: Split trace-seq related APIs in a separate header file In order to make libtraceevent into a proper library, all its APIs should be defined in corresponding header files. This patch splits trace-seq related APIs in a separate header file: trace-seq.h Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/20180828185038.2dcb2743@gandalf.local.home Signed-off-by: Steven Rostedt Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 1 + tools/lib/traceevent/event-parse.h | 46 +----------------- tools/lib/traceevent/event-plugin.c | 1 + tools/lib/traceevent/plugin_function.c | 1 + tools/lib/traceevent/plugin_hrtimer.c | 1 + tools/lib/traceevent/plugin_jbd2.c | 1 + tools/lib/traceevent/plugin_kmem.c | 1 + tools/lib/traceevent/plugin_kvm.c | 1 + tools/lib/traceevent/plugin_mac80211.c | 1 + tools/lib/traceevent/plugin_sched_switch.c | 1 + tools/lib/traceevent/plugin_scsi.c | 1 + tools/lib/traceevent/plugin_xen.c | 1 + tools/lib/traceevent/trace-seq.c | 2 + tools/lib/traceevent/trace-seq.h | 55 ++++++++++++++++++++++ tools/perf/util/trace-event.h | 1 + 15 files changed, 71 insertions(+), 44 deletions(-) create mode 100644 tools/lib/traceevent/trace-seq.h diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index ce1e20227c64..70a42bec6931 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -24,6 +24,7 @@ #include #include "event-parse.h" #include "event-utils.h" +#include "trace-seq.h" static const char *input_buf; static unsigned long long input_buf_ptr; diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 44b7c2d41f9f..fa665c66bfa4 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -26,17 +26,12 @@ #include #include +#include "trace-seq.h" + #ifndef __maybe_unused #define __maybe_unused __attribute__((unused)) #endif -/* ----------------------- trace_seq ----------------------- */ - - -#ifndef TRACE_SEQ_BUF_SIZE -#define TRACE_SEQ_BUF_SIZE 4096 -#endif - #ifndef DEBUG_RECORD #define DEBUG_RECORD 0 #endif @@ -59,43 +54,6 @@ struct tep_record { #endif }; -enum trace_seq_fail { - TRACE_SEQ__GOOD, - TRACE_SEQ__BUFFER_POISONED, - TRACE_SEQ__MEM_ALLOC_FAILED, -}; - -/* - * Trace sequences are used to allow a function to call several other functions - * to create a string of data to use (up to a max of PAGE_SIZE). - */ - -struct trace_seq { - char *buffer; - unsigned int buffer_size; - unsigned int len; - unsigned int readpos; - enum trace_seq_fail state; -}; - -void trace_seq_init(struct trace_seq *s); -void trace_seq_reset(struct trace_seq *s); -void trace_seq_destroy(struct trace_seq *s); - -extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) - __attribute__ ((format (printf, 2, 3))); -extern int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) - __attribute__ ((format (printf, 2, 0))); - -extern int trace_seq_puts(struct trace_seq *s, const char *str); -extern int trace_seq_putc(struct trace_seq *s, unsigned char c); - -extern void trace_seq_terminate(struct trace_seq *s); - -extern int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp); -extern int trace_seq_do_printf(struct trace_seq *s); - - /* ----------------------- pevent ----------------------- */ struct tep_handle; diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index f17e25097e1e..ec16a103c0cc 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -15,6 +15,7 @@ #include #include "event-parse.h" #include "event-utils.h" +#include "trace-seq.h" #define LOCAL_PLUGIN_DIR ".traceevent/plugins" diff --git a/tools/lib/traceevent/plugin_function.c b/tools/lib/traceevent/plugin_function.c index 424747475d37..2919042e7dc2 100644 --- a/tools/lib/traceevent/plugin_function.c +++ b/tools/lib/traceevent/plugin_function.c @@ -23,6 +23,7 @@ #include "event-parse.h" #include "event-utils.h" +#include "trace-seq.h" static struct func_stack { int size; diff --git a/tools/lib/traceevent/plugin_hrtimer.c b/tools/lib/traceevent/plugin_hrtimer.c index b43bfec565d8..29b608076ea0 100644 --- a/tools/lib/traceevent/plugin_hrtimer.c +++ b/tools/lib/traceevent/plugin_hrtimer.c @@ -23,6 +23,7 @@ #include #include "event-parse.h" +#include "trace-seq.h" static int timer_expire_handler(struct trace_seq *s, struct tep_record *record, diff --git a/tools/lib/traceevent/plugin_jbd2.c b/tools/lib/traceevent/plugin_jbd2.c index 45a9acd19640..a5e34135dd6a 100644 --- a/tools/lib/traceevent/plugin_jbd2.c +++ b/tools/lib/traceevent/plugin_jbd2.c @@ -22,6 +22,7 @@ #include #include "event-parse.h" +#include "trace-seq.h" #define MINORBITS 20 #define MINORMASK ((1U << MINORBITS) - 1) diff --git a/tools/lib/traceevent/plugin_kmem.c b/tools/lib/traceevent/plugin_kmem.c index 73966b05abce..a7a162575e2c 100644 --- a/tools/lib/traceevent/plugin_kmem.c +++ b/tools/lib/traceevent/plugin_kmem.c @@ -22,6 +22,7 @@ #include #include "event-parse.h" +#include "trace-seq.h" static int call_site_handler(struct trace_seq *s, struct tep_record *record, struct event_format *event, void *context) diff --git a/tools/lib/traceevent/plugin_kvm.c b/tools/lib/traceevent/plugin_kvm.c index 1d0d15906225..a0dfd3d0f197 100644 --- a/tools/lib/traceevent/plugin_kvm.c +++ b/tools/lib/traceevent/plugin_kvm.c @@ -23,6 +23,7 @@ #include #include "event-parse.h" +#include "trace-seq.h" #ifdef HAVE_UDIS86 diff --git a/tools/lib/traceevent/plugin_mac80211.c b/tools/lib/traceevent/plugin_mac80211.c index de50a5316203..0b7779444b63 100644 --- a/tools/lib/traceevent/plugin_mac80211.c +++ b/tools/lib/traceevent/plugin_mac80211.c @@ -22,6 +22,7 @@ #include #include "event-parse.h" +#include "trace-seq.h" #define INDENT 65 diff --git a/tools/lib/traceevent/plugin_sched_switch.c b/tools/lib/traceevent/plugin_sched_switch.c index eecb4bd95c11..582d3be2849b 100644 --- a/tools/lib/traceevent/plugin_sched_switch.c +++ b/tools/lib/traceevent/plugin_sched_switch.c @@ -22,6 +22,7 @@ #include #include "event-parse.h" +#include "trace-seq.h" static void write_state(struct trace_seq *s, int val) { diff --git a/tools/lib/traceevent/plugin_scsi.c b/tools/lib/traceevent/plugin_scsi.c index 5ec346f6b842..4eba25cc1431 100644 --- a/tools/lib/traceevent/plugin_scsi.c +++ b/tools/lib/traceevent/plugin_scsi.c @@ -3,6 +3,7 @@ #include #include #include "event-parse.h" +#include "trace-seq.h" typedef unsigned long sector_t; typedef uint64_t u64; diff --git a/tools/lib/traceevent/plugin_xen.c b/tools/lib/traceevent/plugin_xen.c index b2acbd6e9c86..bc0496e4c296 100644 --- a/tools/lib/traceevent/plugin_xen.c +++ b/tools/lib/traceevent/plugin_xen.c @@ -3,6 +3,7 @@ #include #include #include "event-parse.h" +#include "trace-seq.h" #define __HYPERVISOR_set_trap_table 0 #define __HYPERVISOR_mmu_update 1 diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c index e3bac4543d3b..8ff1d55954d1 100644 --- a/tools/lib/traceevent/trace-seq.c +++ b/tools/lib/traceevent/trace-seq.c @@ -3,6 +3,8 @@ * Copyright (C) 2009 Red Hat Inc, Steven Rostedt * */ +#include "trace-seq.h" + #include #include #include diff --git a/tools/lib/traceevent/trace-seq.h b/tools/lib/traceevent/trace-seq.h new file mode 100644 index 000000000000..d68ec69f8d1a --- /dev/null +++ b/tools/lib/traceevent/trace-seq.h @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt + * + */ + +#ifndef _TRACE_SEQ_H +#define _TRACE_SEQ_H + +#include +#include + +/* ----------------------- trace_seq ----------------------- */ + +#ifndef TRACE_SEQ_BUF_SIZE +#define TRACE_SEQ_BUF_SIZE 4096 +#endif + +enum trace_seq_fail { + TRACE_SEQ__GOOD, + TRACE_SEQ__BUFFER_POISONED, + TRACE_SEQ__MEM_ALLOC_FAILED, +}; + +/* + * Trace sequences are used to allow a function to call several other functions + * to create a string of data to use (up to a max of PAGE_SIZE). + */ + +struct trace_seq { + char *buffer; + unsigned int buffer_size; + unsigned int len; + unsigned int readpos; + enum trace_seq_fail state; +}; + +void trace_seq_init(struct trace_seq *s); +void trace_seq_reset(struct trace_seq *s); +void trace_seq_destroy(struct trace_seq *s); + +extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) + __attribute__ ((format (printf, 2, 0))); + +extern int trace_seq_puts(struct trace_seq *s, const char *str); +extern int trace_seq_putc(struct trace_seq *s, unsigned char c); + +extern void trace_seq_terminate(struct trace_seq *s); + +extern int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp); +extern int trace_seq_do_printf(struct trace_seq *s); + +#endif /* _TRACE_SEQ_H */ diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 40204ec3a7a2..c69d77d7cf55 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -3,6 +3,7 @@ #define _PERF_UTIL_TRACE_EVENT_H #include +#include #include "parse-events.h" struct machine; From 664b6a95d771a6dcd7069996c825a03be411ef99 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 30 Aug 2018 08:48:44 -0300 Subject: [PATCH 021/155] perf bpf: Add syscall_exit() helper So that we can hook to the syscalls:sys_exit_SYSCALL tracepoints in addition to the syscalls:sys_enter_SYSCALL we hook using the syscall_enter() helper. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-6qh8aph1jklyvdu7w89c0izc@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/include/bpf/bpf.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/include/bpf/bpf.h b/tools/perf/include/bpf/bpf.h index 47897d65e799..52b6d87fe822 100644 --- a/tools/perf/include/bpf/bpf.h +++ b/tools/perf/include/bpf/bpf.h @@ -26,6 +26,9 @@ struct bpf_map { #define syscall_enter(name) \ SEC("syscalls:sys_enter_" #name) syscall_enter_ ## name +#define syscall_exit(name) \ + SEC("syscalls:sys_exit_" #name) syscall_exit_ ## name + #define license(name) \ char _license[] SEC("license") = #name; \ int _version SEC("version") = LINUX_VERSION_CODE; From 5e2d8a5acc99e7b9df9be216f0a73855e865f9a5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 30 Aug 2018 10:02:23 -0300 Subject: [PATCH 022/155] perf augmented_syscalls: Update the header comments Reflecting the fact that it now augments more than syscalls:sys_enter_SYSCALL tracepoints that have filename strings as args. Also mention how the extra data is handled by the by now modified 'perf trace' beautifiers, that will use special "augmented" beautifiers when extra data is found after the expected syscall enter/exit tracepoints. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-ybskanehmdilj5fs7080nz1g@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/examples/bpf/augmented_syscalls.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index be06d2c9e8c9..bfa28eaf27b3 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Augment the openat syscall with the contents of the filename pointer argument. + * Augment syscalls with the contents of the pointer arguments. * * Test it with: * @@ -10,12 +10,10 @@ * the last one should be the one for '/etc/passwd'. * * This matches what is marshalled into the raw_syscall:sys_enter payload - * expected by the 'perf trace' beautifiers, and can be used by them unmodified, - * which will be done as that feature is implemented in the next csets, for now - * it will appear in a dump done by the default tracepoint handler in 'perf trace', - * that uses bpf_output__fprintf() to just dump those contents, as done with - * the bpf-output event associated with the __bpf_output__ map declared in - * tools/perf/include/bpf/stdio.h. + * expected by the 'perf trace' beautifiers, and can be used by them, that will + * check if perf_sample->raw_data is more than what is expected for each + * syscalls:sys_{enter,exit}_SYSCALL tracepoint, uing the extra data as the + * contents of pointer arguments. */ #include From 4c8f0a726ef808244788a237e52ce3c612bff8c3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 30 Aug 2018 11:50:21 -0300 Subject: [PATCH 023/155] perf trace augmented_syscalls: Rename augmented_*_syscall__enter to just *_syscall As we'll also hook into the syscalls:sys_exit_SYSCALL for which there are enter hooks. This way we'll be able to iterate the ELF file for the eBPF program, find the syscalls that have hooks and filter them out from the general raw_syscalls:sys_{enter,exit} tracepoint for not-yet-augmented (the ones with pointer arguments not yet being attached to the usual syscalls tracepoint payload) and non augmentable syscalls (syscalls without pointer arguments). Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-cl1xyghwb1usp500354mv37h@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/examples/bpf/augmented_syscalls.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index bfa28eaf27b3..253b3ccbd17d 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -32,7 +32,7 @@ struct augmented_filename { char value[256]; }; -#define augmented_filename_syscall_enter(syscall) \ +#define augmented_filename_syscall(syscall) \ struct augmented_enter_##syscall##_args { \ struct syscall_enter_##syscall##_args args; \ struct augmented_filename filename; \ @@ -60,7 +60,7 @@ struct syscall_enter_openat_args { long mode; }; -augmented_filename_syscall_enter(openat); +augmented_filename_syscall(openat); struct syscall_enter_open_args { unsigned long long common_tp_fields; @@ -70,7 +70,7 @@ struct syscall_enter_open_args { long mode; }; -augmented_filename_syscall_enter(open); +augmented_filename_syscall(open); struct syscall_enter_inotify_add_watch_args { unsigned long long common_tp_fields; @@ -80,7 +80,7 @@ struct syscall_enter_inotify_add_watch_args { long mask; }; -augmented_filename_syscall_enter(inotify_add_watch); +augmented_filename_syscall(inotify_add_watch); struct statbuf; @@ -91,13 +91,13 @@ struct syscall_enter_newstat_args { struct stat *statbuf; }; -augmented_filename_syscall_enter(newstat); +augmented_filename_syscall(newstat); #ifndef _K_SS_MAXSIZE #define _K_SS_MAXSIZE 128 #endif -#define augmented_sockaddr_syscall_enter(syscall) \ +#define augmented_sockaddr_syscall(syscall) \ struct augmented_enter_##syscall##_args { \ struct syscall_enter_##syscall##_args args; \ struct sockaddr_storage addr; \ @@ -128,7 +128,7 @@ struct syscall_enter_bind_args { unsigned long addrlen; }; -augmented_sockaddr_syscall_enter(bind); +augmented_sockaddr_syscall(bind); struct syscall_enter_connect_args { unsigned long long common_tp_fields; @@ -138,7 +138,7 @@ struct syscall_enter_connect_args { unsigned long addrlen; }; -augmented_sockaddr_syscall_enter(connect); +augmented_sockaddr_syscall(connect); struct syscall_enter_sendto_args { unsigned long long common_tp_fields; @@ -151,6 +151,6 @@ struct syscall_enter_sendto_args { long addr_len; }; -augmented_sockaddr_syscall_enter(sendto); +augmented_sockaddr_syscall(sendto); license(GPL); From f5b076dc01e77fa016de8439f8ac21d1c310c5be Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 30 Aug 2018 12:32:35 -0300 Subject: [PATCH 024/155] perf trace augmented_syscalls: Hook into syscalls:sys_exit_SYSCALL too Hook the pair enter/exit when using augmented_{filename,sockaddr,etc}_syscall(), this way we'll be able to see what entries are in the ELF sections generated from augmented_syscalls.c and filter them out from the main raw_syscalls:* tracepoints used by 'perf trace'. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-cyav42qj5yylolw4attcw99z@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/examples/bpf/augmented_syscalls.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index 253b3ccbd17d..1419a9186937 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -26,6 +26,12 @@ struct bpf_map SEC("maps") __augmented_syscalls__ = { .max_entries = __NR_CPUS__, }; +struct syscall_exit_args { + unsigned long long common_tp_fields; + long syscall_nr; + long ret; +}; + struct augmented_filename { int size; int reserved; @@ -49,6 +55,10 @@ int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \ (sizeof(augmented_args) - sizeof(augmented_args.filename.value) + \ augmented_args.filename.size)); \ return 0; \ +} \ +int syscall_exit(syscall)(struct syscall_exit_args *args) \ +{ \ + return 1; /* 0 as soon as we start copying data returned by the kernel, e.g. 'read' */ \ } struct syscall_enter_openat_args { @@ -116,6 +126,10 @@ int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \ &augmented_args, \ sizeof(augmented_args) - sizeof(augmented_args.addr) + addrlen); \ return 0; \ +} \ +int syscall_exit(syscall)(struct syscall_exit_args *args) \ +{ \ + return 1; /* 0 as soon as we start copying data returned by the kernel, e.g. 'read' */ \ } struct sockaddr; From c4191e55b8741f72d44c7c1435c340681ae1ea4e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 30 Aug 2018 13:37:28 -0300 Subject: [PATCH 025/155] perf trace: Show comm and tid for tracepoint events So that all events have that info, improving reading by having information better aligned, etc. Before: # echo 1 > /proc/sys/vm/drop_caches # perf trace -e block:*,ext4:*,tools/perf/examples/bpf/augmented_syscalls.c,close cat tools/perf/examples/bpf/hello.c 0.000 ( ): #include int syscall_enter(openat)(void *args) { puts("Hello, world\n"); return 0; } license(GPL); cat/2731 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 0.025 ( ): syscalls:sys_exit_openat:0x3 0.063 ( 0.022 ms): cat/2731 close(fd: 3) = 0 0.110 ( ): cat/2731 openat(dfd: CWD, filename: /lib64/libc.so.6, flags: CLOEXEC) 0.123 ( ): syscalls:sys_exit_openat:0x3 0.243 ( 0.008 ms): cat/2731 close(fd: 3) = 0 0.485 ( ): cat/2731 open(filename: /usr/lib/locale/locale-archive, flags: CLOEXEC) 0.500 ( ): syscalls:sys_exit_open:0x3 0.531 ( 0.017 ms): cat/2731 close(fd: 3) = 0 0.587 ( ): cat/2731 openat(dfd: CWD, filename: tools/perf/examples/bpf/hello.c) 0.601 ( ): syscalls:sys_exit_openat:0x3 0.631 ( ): ext4:ext4_es_lookup_extent_enter:dev 253,2 ino 1311399 lblk 0 0.639 ( ): ext4:ext4_es_lookup_extent_exit:dev 253,2 ino 1311399 found 1 [0/1) 5276651 W0x10 0.654 ( ): block:block_bio_queue:253,2 R 42213208 + 8 [cat] 0.663 ( ): block:block_bio_remap:8,0 R 58206040 + 8 <- (253,2) 42213208 0.671 ( ): block:block_bio_remap:8,0 R 175570776 + 8 <- (8,6) 58206040 0.678 ( ): block:block_bio_queue:8,0 R 175570776 + 8 [cat] 0.692 ( ): block:block_getrq:8,0 R 175570776 + 8 [cat] 0.700 ( ): block:block_plug:[cat] 0.708 ( ): block:block_rq_insert:8,0 R 4096 () 175570776 + 8 [cat] 0.713 ( ): block:block_unplug:[cat] 1 0.716 ( ): block:block_rq_issue:8,0 R 4096 () 175570776 + 8 [cat] 0.949 ( 0.007 ms): cat/2731 close(fd: 3) = 0 0.969 ( 0.006 ms): cat/2731 close(fd: 1) = 0 0.982 ( 0.006 ms): cat/2731 close(fd: 2) = 0 # After: # echo 1 > /proc/sys/vm/drop_caches # perf trace -e block:*,ext4:*,tools/perf/examples/bpf/augmented_syscalls.c,close cat tools/perf/examples/bpf/hello.c 0.000 ( ): cat/1380 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC)#include int syscall_enter(openat)(void *args) { puts("Hello, world\n"); return 0; } license(GPL); 0.024 ( ): cat/1380 syscalls:sys_exit_openat:0x3 0.063 ( 0.024 ms): cat/1380 close(fd: 3) = 0 0.114 ( ): cat/1380 openat(dfd: CWD, filename: /lib64/libc.so.6, flags: CLOEXEC) 0.127 ( ): cat/1380 syscalls:sys_exit_openat:0x3 0.247 ( 0.009 ms): cat/1380 close(fd: 3) = 0 0.484 ( ): cat/1380 open(filename: /usr/lib/locale/locale-archive, flags: CLOEXEC) 0.499 ( ): cat/1380 syscalls:sys_exit_open:0x3 0.613 ( 0.010 ms): cat/1380 close(fd: 3) = 0 0.662 ( ): cat/1380 openat(dfd: CWD, filename: tools/perf/examples/bpf/hello.c) 0.678 ( ): cat/1380 syscalls:sys_exit_openat:0x3 0.712 ( ): cat/1380 ext4:ext4_es_lookup_extent_enter:dev 253,2 ino 1311399 lblk 0 0.721 ( ): cat/1380 ext4:ext4_es_lookup_extent_exit:dev 253,2 ino 1311399 found 1 [0/1) 5276651 W0x10 0.734 ( ): cat/1380 block:block_bio_queue:253,2 R 42213208 + 8 [cat] 0.745 ( ): cat/1380 block:block_bio_remap:8,0 R 58206040 + 8 <- (253,2) 42213208 0.754 ( ): cat/1380 block:block_bio_remap:8,0 R 175570776 + 8 <- (8,6) 58206040 0.761 ( ): cat/1380 block:block_bio_queue:8,0 R 175570776 + 8 [cat] 0.780 ( ): cat/1380 block:block_getrq:8,0 R 175570776 + 8 [cat] 0.791 ( ): cat/1380 block:block_plug:[cat] 0.802 ( ): cat/1380 block:block_rq_insert:8,0 R 4096 () 175570776 + 8 [cat] 0.806 ( ): cat/1380 block:block_unplug:[cat] 1 0.810 ( ): cat/1380 block:block_rq_issue:8,0 R 4096 () 175570776 + 8 [cat] 1.005 ( 0.011 ms): cat/1380 close(fd: 3) = 0 1.031 ( 0.008 ms): cat/1380 close(fd: 1) = 0 1.048 ( 0.008 ms): cat/1380 close(fd: 2) = 0 # Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-us1mwsupxffs4jlm3uqm5dvj@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 759d14e3fe6b..97ace635bed8 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2049,6 +2049,7 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, union perf_event *event __maybe_unused, struct perf_sample *sample) { + struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); int callchain_ret = 0; if (sample->callchain) { @@ -2066,21 +2067,18 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, if (trace->trace_syscalls) fprintf(trace->output, "( ): "); + if (thread) + trace__fprintf_comm_tid(trace, thread, trace->output); + if (evsel == trace->syscalls.events.augmented) { int id = perf_evsel__sc_tp_uint(evsel, id, sample); struct syscall *sc = trace__syscall_info(trace, evsel, id); if (sc) { - struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); - - if (thread) { - trace__fprintf_comm_tid(trace, thread, trace->output); - fprintf(trace->output, "%s(", sc->name); - trace__fprintf_sys_enter(trace, evsel, sample); - fputc(')', trace->output); - thread__put(thread); - goto newline; - } + fprintf(trace->output, "%s(", sc->name); + trace__fprintf_sys_enter(trace, evsel, sample); + fputc(')', trace->output); + goto newline; } /* @@ -2110,6 +2108,7 @@ newline: trace__fprintf_callchain(trace, sample); else if (callchain_ret < 0) pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); + thread__put(thread); out: return 0; } From d50ed0ce820414dbe249a6ad5c9830e29cc46fcc Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:10 +0200 Subject: [PATCH 026/155] perf stat: Use evsel->threads in create_perf_stat_counter() Get rid of the evsel_list dependency, here we can use the evsel->threads copy of the struct thread_map. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-2-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index d097b5b47eb8..d389ed623715 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -293,7 +293,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) if (target__has_cpu(&target) && !target__has_per_thread(&target)) return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); - return perf_evsel__open_per_thread(evsel, evsel_list->threads); + return perf_evsel__open_per_thread(evsel, evsel->threads); } static int process_synthesized_event(struct perf_tool *tool __maybe_unused, From 728c0ee0a896fcb0957b496afdb78bf195397645 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:11 +0200 Subject: [PATCH 027/155] perf stat: Move 'initial_delay' to 'struct perf_stat_config' Move the static 'initial_delay' variable to 'struct perf_stat_config', so it can be passed around and used outside the 'perf stat' command. Add 'struct perf_stat_config' argument to create_perf_stat_counter() and use its 'initial_delay' member instead of the static one. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-3-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 16 ++++++++-------- tools/perf/util/stat.h | 18 ++++++++++-------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index d389ed623715..719abdd3b7de 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -164,7 +164,6 @@ static bool group = false; static const char *pre_cmd = NULL; static const char *post_cmd = NULL; static bool sync_run = false; -static unsigned int initial_delay = 0; static unsigned int unit_width = 4; /* strlen("unit") */ static bool forever = false; static bool metric_only = false; @@ -236,7 +235,8 @@ static void perf_stat__reset_stats(void) perf_stat__reset_shadow_per_stat(&stat_config.stats[i]); } -static int create_perf_stat_counter(struct perf_evsel *evsel) +static int create_perf_stat_counter(struct perf_evsel *evsel, + struct perf_stat_config *config) { struct perf_event_attr *attr = &evsel->attr; struct perf_evsel *leader = evsel->leader; @@ -286,7 +286,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) * In case of initial_delay we enable tracee * events manually. */ - if (target__none(&target) && !initial_delay) + if (target__none(&target) && !config->initial_delay) attr->enable_on_exec = 1; } @@ -428,15 +428,15 @@ static void process_interval(void) static void enable_counters(void) { - if (initial_delay) - usleep(initial_delay * USEC_PER_MSEC); + if (stat_config.initial_delay) + usleep(stat_config.initial_delay * USEC_PER_MSEC); /* * We need to enable counters only if: * - we don't have tracee (attaching to task or cpu) * - we have initial delay configured */ - if (!target__none(&target) || initial_delay) + if (!target__none(&target) || stat_config.initial_delay) perf_evlist__enable(evsel_list); } @@ -609,7 +609,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) evlist__for_each_entry(evsel_list, counter) { try_again: - if (create_perf_stat_counter(counter) < 0) { + if (create_perf_stat_counter(counter, &stat_config) < 0) { /* Weak group failed. Reset the group. */ if ((errno == EINVAL || errno == EBADF) && @@ -2027,7 +2027,7 @@ static const struct option stat_options[] = { "aggregate counts per physical processor core", AGGR_CORE), OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode, "aggregate counts per thread", AGGR_THREAD), - OPT_UINTEGER('D', "delay", &initial_delay, + OPT_UINTEGER('D', "delay", &stat_config.initial_delay, "ms to wait before starting measurement after program start"), OPT_CALLBACK_NOOPT(0, "metric-only", &metric_only, NULL, "Only print computed metrics. No raw values", enable_metric_only), diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 36efb986f7fc..91e6609fce6e 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -6,6 +6,7 @@ #include #include "xyarray.h" #include "rblist.h" +#include "perf.h" struct stats { double n, mean, M2; @@ -85,14 +86,15 @@ struct runtime_stat { }; struct perf_stat_config { - enum aggr_mode aggr_mode; - bool scale; - FILE *output; - unsigned int interval; - unsigned int timeout; - int times; - struct runtime_stat *stats; - int stats_num; + enum aggr_mode aggr_mode; + bool scale; + FILE *output; + unsigned int interval; + unsigned int timeout; + unsigned int initial_delay; + int times; + struct runtime_stat *stats; + int stats_num; }; void update_stats(struct stats *stats, u64 val); From 5698f26b46e4f47f2371418eb92732048fa4fa66 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:12 +0200 Subject: [PATCH 028/155] perf stat: Move 'no_inherit' to 'struct perf_stat_config' Move the static 'no_inherit' variable to 'struct perf_stat_config', so it can be passed around and used outside the 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-4-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 5 ++--- tools/perf/util/stat.h | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 719abdd3b7de..84dbac526925 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -148,7 +148,6 @@ typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu); #define METRIC_ONLY_LEN 20 static int run_count = 1; -static bool no_inherit = false; static volatile pid_t child_pid = -1; static bool null_run = false; static int detailed_run = 0; @@ -254,7 +253,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel, if (leader->nr_members > 1) attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP; - attr->inherit = !no_inherit; + attr->inherit = !config->no_inherit; /* * Some events get initialized with sample_(period/type) set, @@ -1969,7 +1968,7 @@ static const struct option stat_options[] = { parse_events_option), OPT_CALLBACK(0, "filter", &evsel_list, "filter", "event filter", parse_filter), - OPT_BOOLEAN('i', "no-inherit", &no_inherit, + OPT_BOOLEAN('i', "no-inherit", &stat_config.no_inherit, "child tasks do not inherit counters"), OPT_STRING('p', "pid", &target.pid, "pid", "stat events on existing process id"), diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 91e6609fce6e..53b2415ba3f3 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -88,6 +88,7 @@ struct runtime_stat { struct perf_stat_config { enum aggr_mode aggr_mode; bool scale; + bool no_inherit; FILE *output; unsigned int interval; unsigned int timeout; From 35386233fcf78f20cb8a51199518da9f81eca280 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:13 +0200 Subject: [PATCH 029/155] perf stat: Use local config arg for scale in create_perf_stat_counter() Use the local 'scale' member in the 'struct perf_stat_config' argument instead of the global 'stat_config' variable, to make the function independent. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-5-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 84dbac526925..47789558899a 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -240,7 +240,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel, struct perf_event_attr *attr = &evsel->attr; struct perf_evsel *leader = evsel->leader; - if (stat_config.scale) { + if (config->scale) { attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING; } From 7d9ad16afe2bfc73b8967cc2aa2dc30f0170a8e2 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:14 +0200 Subject: [PATCH 030/155] perf stat: Add 'identifier' flag to 'struct perf_stat_config' Add 'identifier' flag to 'struct perf_stat_config' to carry the info whether to use PERF_SAMPLE_IDENTIFIER for events. This makes create_perf_stat_counter() independent. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-6-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 22 ++++++++++++---------- tools/perf/util/stat.h | 1 + 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 47789558899a..48c88f568fe1 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -261,16 +261,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel, */ attr->sample_period = 0; - /* - * But set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless - * while avoiding that older tools show confusing messages. - * - * However for pipe sessions we need to keep it zero, - * because script's perf_evsel__check_attr is triggered - * by attr->sample_type != 0, and we can't run it on - * stat sessions. - */ - if (!(STAT_RECORD && perf_stat.data.is_pipe)) + if (config->identifier) attr->sample_type = PERF_SAMPLE_IDENTIFIER; /* @@ -3064,6 +3055,17 @@ int cmd_stat(int argc, const char **argv) if (perf_stat_init_aggr_mode()) goto out; + /* + * Set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless + * while avoiding that older tools show confusing messages. + * + * However for pipe sessions we need to keep it zero, + * because script's perf_evsel__check_attr is triggered + * by attr->sample_type != 0, and we can't run it on + * stat sessions. + */ + stat_config.identifier = !(STAT_RECORD && perf_stat.data.is_pipe); + /* * We dont want to block the signals - that would cause * child tasks to inherit that and Ctrl-C would not work. diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 53b2415ba3f3..918cde064cdc 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -89,6 +89,7 @@ struct perf_stat_config { enum aggr_mode aggr_mode; bool scale; bool no_inherit; + bool identifier; FILE *output; unsigned int interval; unsigned int timeout; From 318ec1841a3f26799fe663d8f979a57623c0c470 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:15 +0200 Subject: [PATCH 031/155] perf tools: Switch 'session' argument to 'evlist' in perf_event__synthesize_attrs() To be able to pass in other than session's evlist. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-7-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-stat.c | 2 +- tools/perf/util/header.c | 6 +++--- tools/perf/util/header.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 22ebeb92ac51..9853552bcf16 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -758,7 +758,7 @@ static int record__synthesize(struct record *rec, bool tail) * We need to synthesize events first, because some * features works on top of them (on report side). */ - err = perf_event__synthesize_attrs(tool, session, + err = perf_event__synthesize_attrs(tool, rec->evlist, process_synthesized_event); if (err < 0) { pr_err("Couldn't synthesize attrs.\n"); diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 48c88f568fe1..8291f503d0cc 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -459,7 +459,7 @@ static int perf_stat_synthesize_config(bool is_pipe) int err; if (is_pipe) { - err = perf_event__synthesize_attrs(NULL, perf_stat.session, + err = perf_event__synthesize_attrs(NULL, evsel_list, process_synthesized_event); if (err < 0) { pr_err("Couldn't synthesize attrs.\n"); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 3cadc252dd89..91e6d9cfd906 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -3637,13 +3637,13 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp) } int perf_event__synthesize_attrs(struct perf_tool *tool, - struct perf_session *session, - perf_event__handler_t process) + struct perf_evlist *evlist, + perf_event__handler_t process) { struct perf_evsel *evsel; int err = 0; - evlist__for_each_entry(session->evlist, evsel) { + evlist__for_each_entry(evlist, evsel) { err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids, evsel->id, process); if (err) { diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 6d7fe44aadc0..ff2a1263fb9b 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -124,7 +124,7 @@ int perf_event__synthesize_attr(struct perf_tool *tool, struct perf_event_attr *attr, u32 ids, u64 *id, perf_event__handler_t process); int perf_event__synthesize_attrs(struct perf_tool *tool, - struct perf_session *session, + struct perf_evlist *evlist, perf_event__handler_t process); int perf_event__synthesize_event_update_unit(struct perf_tool *tool, struct perf_evsel *evsel, From 650d622046024623e71fea1f28acf1edb7e61a81 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:16 +0200 Subject: [PATCH 032/155] perf evsel: Introduce perf_evsel__store_ids() Add perf_evsel__store_ids() from stat's store_counter_ids() code to the evsel class, so that it can be used globally. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-8-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 33 +-------------------------------- tools/perf/util/evsel.c | 29 +++++++++++++++++++++++++++++ tools/perf/util/evsel.h | 1 + 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 8291f503d0cc..45bbd156d496 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -497,37 +497,6 @@ static int perf_stat_synthesize_config(bool is_pipe) return 0; } -#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) - -static int __store_counter_ids(struct perf_evsel *counter) -{ - int cpu, thread; - - for (cpu = 0; cpu < xyarray__max_x(counter->fd); cpu++) { - for (thread = 0; thread < xyarray__max_y(counter->fd); - thread++) { - int fd = FD(counter, cpu, thread); - - if (perf_evlist__id_add_fd(evsel_list, counter, - cpu, thread, fd) < 0) - return -1; - } - } - - return 0; -} - -static int store_counter_ids(struct perf_evsel *counter) -{ - struct cpu_map *cpus = counter->cpus; - struct thread_map *threads = counter->threads; - - if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr)) - return -ENOMEM; - - return __store_counter_ids(counter); -} - static bool perf_evsel__should_store_id(struct perf_evsel *counter) { return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID; @@ -658,7 +627,7 @@ try_again: unit_width = l; if (perf_evsel__should_store_id(counter) && - store_counter_ids(counter)) + perf_evsel__store_ids(counter, evsel_list)) return -1; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 1a61628a1c12..4ec909d57e9c 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -2940,3 +2940,32 @@ struct perf_env *perf_evsel__env(struct perf_evsel *evsel) return evsel->evlist->env; return NULL; } + +static int store_evsel_ids(struct perf_evsel *evsel, struct perf_evlist *evlist) +{ + int cpu, thread; + + for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) { + for (thread = 0; thread < xyarray__max_y(evsel->fd); + thread++) { + int fd = FD(evsel, cpu, thread); + + if (perf_evlist__id_add_fd(evlist, evsel, + cpu, thread, fd) < 0) + return -1; + } + } + + return 0; +} + +int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist) +{ + struct cpu_map *cpus = evsel->cpus; + struct thread_map *threads = evsel->threads; + + if (perf_evsel__alloc_id(evsel, cpus->nr, threads->nr)) + return -ENOMEM; + + return store_evsel_ids(evsel, evlist); +} diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 163c960614d3..4f8430a85531 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -481,4 +481,5 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, struct perf_env *perf_evsel__env(struct perf_evsel *evsel); +int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist); #endif /* __PERF_EVSEL_H */ From d09cefd2ef9945b4b767bb67f473a0eb2066374f Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:17 +0200 Subject: [PATCH 033/155] perf stat: Move create_perf_stat_counter() to stat.c Move create_perf_stat_counter() to the 'stat' class, so that we can use it globally. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-9-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 54 +-------------------------------------- tools/perf/util/stat.c | 53 ++++++++++++++++++++++++++++++++++++++ tools/perf/util/stat.h | 4 +++ 3 files changed, 58 insertions(+), 53 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 45bbd156d496..142cff8eb12b 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -234,58 +234,6 @@ static void perf_stat__reset_stats(void) perf_stat__reset_shadow_per_stat(&stat_config.stats[i]); } -static int create_perf_stat_counter(struct perf_evsel *evsel, - struct perf_stat_config *config) -{ - struct perf_event_attr *attr = &evsel->attr; - struct perf_evsel *leader = evsel->leader; - - if (config->scale) { - attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | - PERF_FORMAT_TOTAL_TIME_RUNNING; - } - - /* - * The event is part of non trivial group, let's enable - * the group read (for leader) and ID retrieval for all - * members. - */ - if (leader->nr_members > 1) - attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP; - - attr->inherit = !config->no_inherit; - - /* - * Some events get initialized with sample_(period/type) set, - * like tracepoints. Clear it up for counting. - */ - attr->sample_period = 0; - - if (config->identifier) - attr->sample_type = PERF_SAMPLE_IDENTIFIER; - - /* - * Disabling all counters initially, they will be enabled - * either manually by us or by kernel via enable_on_exec - * set later. - */ - if (perf_evsel__is_group_leader(evsel)) { - attr->disabled = 1; - - /* - * In case of initial_delay we enable tracee - * events manually. - */ - if (target__none(&target) && !config->initial_delay) - attr->enable_on_exec = 1; - } - - if (target__has_cpu(&target) && !target__has_per_thread(&target)) - return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); - - return perf_evsel__open_per_thread(evsel, evsel->threads); -} - static int process_synthesized_event(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample __maybe_unused, @@ -568,7 +516,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) evlist__for_each_entry(evsel_list, counter) { try_again: - if (create_perf_stat_counter(counter, &stat_config) < 0) { + if (create_perf_stat_counter(counter, &stat_config, &target) < 0) { /* Weak group failed. Reset the group. */ if ((errno == EINVAL || errno == EBADF) && diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index a0061e0b0fad..3bd24255376a 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -435,3 +435,56 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp) return ret; } + +int create_perf_stat_counter(struct perf_evsel *evsel, + struct perf_stat_config *config, + struct target *target) +{ + struct perf_event_attr *attr = &evsel->attr; + struct perf_evsel *leader = evsel->leader; + + if (config->scale) { + attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | + PERF_FORMAT_TOTAL_TIME_RUNNING; + } + + /* + * The event is part of non trivial group, let's enable + * the group read (for leader) and ID retrieval for all + * members. + */ + if (leader->nr_members > 1) + attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP; + + attr->inherit = !config->no_inherit; + + /* + * Some events get initialized with sample_(period/type) set, + * like tracepoints. Clear it up for counting. + */ + attr->sample_period = 0; + + if (config->identifier) + attr->sample_type = PERF_SAMPLE_IDENTIFIER; + + /* + * Disabling all counters initially, they will be enabled + * either manually by us or by kernel via enable_on_exec + * set later. + */ + if (perf_evsel__is_group_leader(evsel)) { + attr->disabled = 1; + + /* + * In case of initial_delay we enable tracee + * events manually. + */ + if (target__none(target) && !config->initial_delay) + attr->enable_on_exec = 1; + } + + if (target__has_cpu(target) && !target__has_per_thread(target)) + return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); + + return perf_evsel__open_per_thread(evsel, evsel->threads); +} diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 918cde064cdc..8fb596641545 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -175,4 +175,8 @@ int perf_event__process_stat_event(struct perf_tool *tool, size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp); size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp); size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp); + +int create_perf_stat_counter(struct perf_evsel *evsel, + struct perf_stat_config *config, + struct target *target); #endif From 491073a6126644d3c60b677b777006deb3c0e16b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:18 +0200 Subject: [PATCH 034/155] perf stat: Rename 'is_pipe' argument to 'attrs' in perf_stat_synthesize_config() The attrs name makes more sense. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-10-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 142cff8eb12b..0a358c2e1a93 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -402,11 +402,11 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf workload_exec_errno = info->si_value.sival_int; } -static int perf_stat_synthesize_config(bool is_pipe) +static int perf_stat_synthesize_config(bool attrs) { int err; - if (is_pipe) { + if (attrs) { err = perf_event__synthesize_attrs(NULL, evsel_list, process_synthesized_event); if (err < 0) { @@ -418,7 +418,7 @@ static int perf_stat_synthesize_config(bool is_pipe) err = perf_event__synthesize_extra_attr(NULL, evsel_list, process_synthesized_event, - is_pipe); + attrs); err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads, process_synthesized_event, From 73d586c3917d5109bb547c16d90d0eb97203986a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:19 +0200 Subject: [PATCH 035/155] perf stat: Add 'struct perf_stat_config' argument to perf_stat_synthesize_config() Add a 'struct perf_stat_config' argument to perf_stat_synthesize_config(), so we could synthesize arbitrary config. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-11-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 0a358c2e1a93..d0d19a5ffa85 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -402,7 +402,8 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf workload_exec_errno = info->si_value.sival_int; } -static int perf_stat_synthesize_config(bool attrs) +static int perf_stat_synthesize_config(struct perf_stat_config *config, + bool attrs) { int err; @@ -435,7 +436,7 @@ static int perf_stat_synthesize_config(bool attrs) return err; } - err = perf_event__synthesize_stat_config(NULL, &stat_config, + err = perf_event__synthesize_stat_config(NULL, config, process_synthesized_event, NULL); if (err < 0) { pr_err("Couldn't synthesize config.\n"); @@ -606,7 +607,7 @@ try_again: if (err < 0) return err; - err = perf_stat_synthesize_config(is_pipe); + err = perf_stat_synthesize_config(&stat_config, is_pipe); if (err < 0) return err; } From 1821f4eb480bdd3c7c2a1863431ba539c7b0c1f8 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:20 +0200 Subject: [PATCH 036/155] perf stat: Add 'struct perf_tool' argument to perf_stat_synthesize_config() So that we can use the function outside the 'perf stat' command with standard synthesize functions, that take 'struct perf_tool *' argument. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-12-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index d0d19a5ffa85..ae5029875e87 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -403,12 +403,13 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf } static int perf_stat_synthesize_config(struct perf_stat_config *config, + struct perf_tool *tool, bool attrs) { int err; if (attrs) { - err = perf_event__synthesize_attrs(NULL, evsel_list, + err = perf_event__synthesize_attrs(tool, evsel_list, process_synthesized_event); if (err < 0) { pr_err("Couldn't synthesize attrs.\n"); @@ -416,12 +417,12 @@ static int perf_stat_synthesize_config(struct perf_stat_config *config, } } - err = perf_event__synthesize_extra_attr(NULL, + err = perf_event__synthesize_extra_attr(tool, evsel_list, process_synthesized_event, attrs); - err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads, + err = perf_event__synthesize_thread_map2(tool, evsel_list->threads, process_synthesized_event, NULL); if (err < 0) { @@ -429,14 +430,14 @@ static int perf_stat_synthesize_config(struct perf_stat_config *config, return err; } - err = perf_event__synthesize_cpu_map(NULL, evsel_list->cpus, + err = perf_event__synthesize_cpu_map(tool, evsel_list->cpus, process_synthesized_event, NULL); if (err < 0) { pr_err("Couldn't synthesize thread map.\n"); return err; } - err = perf_event__synthesize_stat_config(NULL, config, + err = perf_event__synthesize_stat_config(tool, config, process_synthesized_event, NULL); if (err < 0) { pr_err("Couldn't synthesize config.\n"); @@ -607,7 +608,7 @@ try_again: if (err < 0) return err; - err = perf_stat_synthesize_config(&stat_config, is_pipe); + err = perf_stat_synthesize_config(&stat_config, NULL, is_pipe); if (err < 0) return err; } From 1c21e9899d6a9ea72d4d678faa7b0ec22bcf59a9 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:21 +0200 Subject: [PATCH 037/155] perf stat: Add 'struct perf_evlist' argument to perf_stat_synthesize_config() Get rid of the 'evsel_list' global variable dependency, here in perf_stat_synthesize_config() we are adding the 'evlist' arg. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-13-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index ae5029875e87..cb36344c25b7 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -404,12 +404,13 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf static int perf_stat_synthesize_config(struct perf_stat_config *config, struct perf_tool *tool, + struct perf_evlist *evlist, bool attrs) { int err; if (attrs) { - err = perf_event__synthesize_attrs(tool, evsel_list, + err = perf_event__synthesize_attrs(tool, evlist, process_synthesized_event); if (err < 0) { pr_err("Couldn't synthesize attrs.\n"); @@ -417,12 +418,11 @@ static int perf_stat_synthesize_config(struct perf_stat_config *config, } } - err = perf_event__synthesize_extra_attr(tool, - evsel_list, + err = perf_event__synthesize_extra_attr(tool, evlist, process_synthesized_event, attrs); - err = perf_event__synthesize_thread_map2(tool, evsel_list->threads, + err = perf_event__synthesize_thread_map2(tool, evlist->threads, process_synthesized_event, NULL); if (err < 0) { @@ -430,7 +430,7 @@ static int perf_stat_synthesize_config(struct perf_stat_config *config, return err; } - err = perf_event__synthesize_cpu_map(tool, evsel_list->cpus, + err = perf_event__synthesize_cpu_map(tool, evlist->cpus, process_synthesized_event, NULL); if (err < 0) { pr_err("Couldn't synthesize thread map.\n"); @@ -608,7 +608,8 @@ try_again: if (err < 0) return err; - err = perf_stat_synthesize_config(&stat_config, NULL, is_pipe); + err = perf_stat_synthesize_config(&stat_config, NULL, evsel_list, + is_pipe); if (err < 0) return err; } From c2c247f2dd87706961fa16d033f9dbf173145e70 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:22 +0200 Subject: [PATCH 038/155] perf stat: Add 'perf_event__handler_t' argument to perf_stat_synthesize_config() So that it's completely independent and can be used outside the 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-14-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index cb36344c25b7..1171d4e00276 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -405,40 +405,37 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf static int perf_stat_synthesize_config(struct perf_stat_config *config, struct perf_tool *tool, struct perf_evlist *evlist, + perf_event__handler_t process, bool attrs) { int err; if (attrs) { - err = perf_event__synthesize_attrs(tool, evlist, - process_synthesized_event); + err = perf_event__synthesize_attrs(tool, evlist, process); if (err < 0) { pr_err("Couldn't synthesize attrs.\n"); return err; } } - err = perf_event__synthesize_extra_attr(tool, evlist, - process_synthesized_event, + err = perf_event__synthesize_extra_attr(tool, evlist, process, attrs); err = perf_event__synthesize_thread_map2(tool, evlist->threads, - process_synthesized_event, - NULL); + process, NULL); if (err < 0) { pr_err("Couldn't synthesize thread map.\n"); return err; } err = perf_event__synthesize_cpu_map(tool, evlist->cpus, - process_synthesized_event, NULL); + process, NULL); if (err < 0) { pr_err("Couldn't synthesize thread map.\n"); return err; } - err = perf_event__synthesize_stat_config(tool, config, - process_synthesized_event, NULL); + err = perf_event__synthesize_stat_config(tool, config, process, NULL); if (err < 0) { pr_err("Couldn't synthesize config.\n"); return err; @@ -609,7 +606,7 @@ try_again: return err; err = perf_stat_synthesize_config(&stat_config, NULL, evsel_list, - is_pipe); + process_synthesized_event, is_pipe); if (err < 0) return err; } From 0a4e64d391a2c771ae33e648cf84d4492369560c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:23 +0200 Subject: [PATCH 039/155] perf stat: Move perf_stat_synthesize_config() to stat.c So that it can be used globally. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-15-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 42 --------------------------------------- tools/perf/util/stat.c | 42 +++++++++++++++++++++++++++++++++++++++ tools/perf/util/stat.h | 6 ++++++ 3 files changed, 48 insertions(+), 42 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 1171d4e00276..54768ec15dbc 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -402,48 +402,6 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf workload_exec_errno = info->si_value.sival_int; } -static int perf_stat_synthesize_config(struct perf_stat_config *config, - struct perf_tool *tool, - struct perf_evlist *evlist, - perf_event__handler_t process, - bool attrs) -{ - int err; - - if (attrs) { - err = perf_event__synthesize_attrs(tool, evlist, process); - if (err < 0) { - pr_err("Couldn't synthesize attrs.\n"); - return err; - } - } - - err = perf_event__synthesize_extra_attr(tool, evlist, process, - attrs); - - err = perf_event__synthesize_thread_map2(tool, evlist->threads, - process, NULL); - if (err < 0) { - pr_err("Couldn't synthesize thread map.\n"); - return err; - } - - err = perf_event__synthesize_cpu_map(tool, evlist->cpus, - process, NULL); - if (err < 0) { - pr_err("Couldn't synthesize thread map.\n"); - return err; - } - - err = perf_event__synthesize_stat_config(tool, config, process, NULL); - if (err < 0) { - pr_err("Couldn't synthesize config.\n"); - return err; - } - - return 0; -} - static bool perf_evsel__should_store_id(struct perf_evsel *counter) { return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID; diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 3bd24255376a..5d3172bcc4ae 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -488,3 +488,45 @@ int create_perf_stat_counter(struct perf_evsel *evsel, return perf_evsel__open_per_thread(evsel, evsel->threads); } + +int perf_stat_synthesize_config(struct perf_stat_config *config, + struct perf_tool *tool, + struct perf_evlist *evlist, + perf_event__handler_t process, + bool attrs) +{ + int err; + + if (attrs) { + err = perf_event__synthesize_attrs(tool, evlist, process); + if (err < 0) { + pr_err("Couldn't synthesize attrs.\n"); + return err; + } + } + + err = perf_event__synthesize_extra_attr(tool, evlist, process, + attrs); + + err = perf_event__synthesize_thread_map2(tool, evlist->threads, + process, NULL); + if (err < 0) { + pr_err("Couldn't synthesize thread map.\n"); + return err; + } + + err = perf_event__synthesize_cpu_map(tool, evlist->cpus, + process, NULL); + if (err < 0) { + pr_err("Couldn't synthesize thread map.\n"); + return err; + } + + err = perf_event__synthesize_stat_config(tool, config, process, NULL); + if (err < 0) { + pr_err("Couldn't synthesize config.\n"); + return err; + } + + return 0; +} diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 8fb596641545..da6a706daecc 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -7,6 +7,7 @@ #include "xyarray.h" #include "rblist.h" #include "perf.h" +#include "event.h" struct stats { double n, mean, M2; @@ -179,4 +180,9 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp); int create_perf_stat_counter(struct perf_evsel *evsel, struct perf_stat_config *config, struct target *target); +int perf_stat_synthesize_config(struct perf_stat_config *config, + struct perf_tool *tool, + struct perf_evlist *evlist, + perf_event__handler_t process, + bool attrs); #endif From a5a9eac1a018ad3bfcf9a3ec11eae99fd35f466b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:24 +0200 Subject: [PATCH 040/155] perf stat: Introduce perf_evlist__print_counters() To be in charge of printing out the stat output. It will be moved out of the 'perf stat' command in the following patches. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-16-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 54768ec15dbc..db11832bbdbc 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1692,7 +1692,10 @@ static void print_footer(void) "the same PMU. Try reorganizing the group.\n"); } -static void print_counters(struct timespec *ts, int argc, const char **argv) +static void +perf_evlist__print_counters(struct perf_evlist *evlist, + struct timespec *ts, + int argc, const char **argv) { int interval = stat_config.interval; struct perf_evsel *counter; @@ -1724,14 +1727,14 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) print_aggr(prefix); break; case AGGR_THREAD: - evlist__for_each_entry(evsel_list, counter) { + evlist__for_each_entry(evlist, counter) { if (is_duration_time(counter)) continue; print_aggr_thread(counter, prefix); } break; case AGGR_GLOBAL: - evlist__for_each_entry(evsel_list, counter) { + evlist__for_each_entry(evlist, counter) { if (is_duration_time(counter)) continue; print_counter_aggr(counter, prefix); @@ -1743,7 +1746,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) if (metric_only) print_no_aggr_metric(prefix); else { - evlist__for_each_entry(evsel_list, counter) { + evlist__for_each_entry(evlist, counter) { if (is_duration_time(counter)) continue; print_counter(counter, prefix); @@ -1761,6 +1764,11 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) fflush(stat_config.output); } +static void print_counters(struct timespec *ts, int argc, const char **argv) +{ + perf_evlist__print_counters(evsel_list, ts, argc, argv); +} + static volatile int signr = -1; static void skip_signal(int signo) From 0174820a8ba108f2e72dac5caaea3500c8ca6323 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:25 +0200 Subject: [PATCH 041/155] perf stat: Move STAT_RECORD out of perf_evlist__print_counters() It's stat related and should stay in the 'perf stat' command. The perf_evlist__print_counters function will be moved out in the following patches. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-17-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index db11832bbdbc..4ffbb6594eb6 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1701,10 +1701,6 @@ perf_evlist__print_counters(struct perf_evlist *evlist, struct perf_evsel *counter; char buf[64], *prefix = NULL; - /* Do not print anything if we record to the pipe. */ - if (STAT_RECORD && perf_stat.data.is_pipe) - return; - if (interval) print_interval(prefix = buf, ts); else @@ -1766,6 +1762,10 @@ perf_evlist__print_counters(struct perf_evlist *evlist, static void print_counters(struct timespec *ts, int argc, const char **argv) { + /* Do not print anything if we record to the pipe. */ + if (STAT_RECORD && perf_stat.data.is_pipe) + return; + perf_evlist__print_counters(evsel_list, ts, argc, argv); } From b64df7f33743cd6095b4a007f5f15ff4432fbcf5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:26 +0200 Subject: [PATCH 042/155] perf stat: Add 'struct perf_stat_config' argument to perf_evlist__print_counters() Add a 'struct perf_stat_config' argument to perf_evlist__print_counters(), so that it can be moved out of the 'perf stat' command to generic object in the following patches. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-18-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 4ffbb6594eb6..f340641fe63a 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1694,10 +1694,11 @@ static void print_footer(void) static void perf_evlist__print_counters(struct perf_evlist *evlist, + struct perf_stat_config *config, struct timespec *ts, int argc, const char **argv) { - int interval = stat_config.interval; + int interval = config->interval; struct perf_evsel *counter; char buf[64], *prefix = NULL; @@ -1713,11 +1714,11 @@ perf_evlist__print_counters(struct perf_evlist *evlist, print_metric_headers(prefix, false); if (num_print_iv++ == 25) num_print_iv = 0; - if (stat_config.aggr_mode == AGGR_GLOBAL && prefix) - fprintf(stat_config.output, "%s", prefix); + if (config->aggr_mode == AGGR_GLOBAL && prefix) + fprintf(config->output, "%s", prefix); } - switch (stat_config.aggr_mode) { + switch (config->aggr_mode) { case AGGR_CORE: case AGGR_SOCKET: print_aggr(prefix); @@ -1736,7 +1737,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, print_counter_aggr(counter, prefix); } if (metric_only) - fputc('\n', stat_config.output); + fputc('\n', config->output); break; case AGGR_NONE: if (metric_only) @@ -1757,7 +1758,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, if (!interval && !csv_output) print_footer(); - fflush(stat_config.output); + fflush(config->output); } static void print_counters(struct timespec *ts, int argc, const char **argv) @@ -1766,7 +1767,8 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) if (STAT_RECORD && perf_stat.data.is_pipe) return; - perf_evlist__print_counters(evsel_list, ts, argc, argv); + perf_evlist__print_counters(evsel_list, &stat_config, + ts, argc, argv); } static volatile int signr = -1; From f3ca50e61ff4aebfbefc666be2e064d277ad524c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:27 +0200 Subject: [PATCH 043/155] perf stat: Pass 'struct perf_stat_config' argument to local print functions Add 'struct perf_stat_config' argument to print functions, so that those functions can be moved out of the 'perf stat' command to a generic class in the following patches. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-19-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 149 ++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 69 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index f340641fe63a..f56da22abccc 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -660,30 +660,33 @@ static int run_perf_stat(int argc, const char **argv, int run_idx) return ret; } -static void print_running(u64 run, u64 ena) +static void print_running(struct perf_stat_config *config, + u64 run, u64 ena) { if (csv_output) { - fprintf(stat_config.output, "%s%" PRIu64 "%s%.2f", + fprintf(config->output, "%s%" PRIu64 "%s%.2f", csv_sep, run, csv_sep, ena ? 100.0 * run / ena : 100.0); } else if (run != ena) { - fprintf(stat_config.output, " (%.2f%%)", 100.0 * run / ena); + fprintf(config->output, " (%.2f%%)", 100.0 * run / ena); } } -static void print_noise_pct(double total, double avg) +static void print_noise_pct(struct perf_stat_config *config, + double total, double avg) { double pct = rel_stddev_stats(total, avg); if (csv_output) - fprintf(stat_config.output, "%s%.2f%%", csv_sep, pct); + fprintf(config->output, "%s%.2f%%", csv_sep, pct); else if (pct) - fprintf(stat_config.output, " ( +-%6.2f%% )", pct); + fprintf(config->output, " ( +-%6.2f%% )", pct); } -static void print_noise(struct perf_evsel *evsel, double avg) +static void print_noise(struct perf_stat_config *config, + struct perf_evsel *evsel, double avg) { struct perf_stat_evsel *ps; @@ -691,7 +694,7 @@ static void print_noise(struct perf_evsel *evsel, double avg) return; ps = evsel->stats; - print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); + print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg); } static void aggr_printout(struct perf_evsel *evsel, int id, int nr) @@ -987,13 +990,14 @@ static bool is_mixed_hw_group(struct perf_evsel *counter) return false; } -static void printout(int id, int nr, struct perf_evsel *counter, double uval, +static void printout(struct perf_stat_config *config, int id, int nr, + struct perf_evsel *counter, double uval, char *prefix, u64 run, u64 ena, double noise, struct runtime_stat *st) { struct perf_stat_output_ctx out; struct outstate os = { - .fh = stat_config.output, + .fh = config->output, .prefix = prefix ? prefix : "", .id = id, .nr = nr, @@ -1023,7 +1027,7 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval, pm = print_metric_csv; nl = new_line_csv; os.nfields = 3; - os.nfields += aggr_fields[stat_config.aggr_mode]; + os.nfields += aggr_fields[config->aggr_mode]; if (counter->cgrp) os.nfields++; } @@ -1034,7 +1038,7 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval, } aggr_printout(counter, id, nr); - fprintf(stat_config.output, "%*s%s", + fprintf(config->output, "%*s%s", csv_output ? 0 : 18, counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, csv_sep); @@ -1045,22 +1049,22 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval, print_mixed_hw_group_error = 1; } - fprintf(stat_config.output, "%-*s%s", + fprintf(config->output, "%-*s%s", csv_output ? 0 : unit_width, counter->unit, csv_sep); - fprintf(stat_config.output, "%*s", + fprintf(config->output, "%*s", csv_output ? 0 : -25, perf_evsel__name(counter)); if (counter->cgrp) - fprintf(stat_config.output, "%s%s", + fprintf(config->output, "%s%s", csv_sep, counter->cgrp->name); if (!csv_output) pm(&os, NULL, NULL, "", 0); - print_noise(counter, noise); - print_running(run, ena); + print_noise(config, counter, noise); + print_running(config, run, ena); if (csv_output) pm(&os, NULL, NULL, "", 0); return; @@ -1075,16 +1079,16 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval, out.force_header = false; if (csv_output && !metric_only) { - print_noise(counter, noise); - print_running(run, ena); + print_noise(config, counter, noise); + print_running(config, run, ena); } perf_stat__print_shadow_stats(counter, uval, first_shadow_cpu(counter, id), &out, &metric_events, st); if (!csv_output && !metric_only) { - print_noise(counter, noise); - print_running(run, ena); + print_noise(config, counter, noise); + print_running(config, run, ena); } } @@ -1211,9 +1215,10 @@ static void aggr_cb(struct perf_evsel *counter, void *data, bool first) } } -static void print_aggr(char *prefix) +static void print_aggr(struct perf_stat_config *config, + char *prefix) { - FILE *output = stat_config.output; + FILE *output = config->output; struct perf_evsel *counter; int s, id, nr; double uval; @@ -1256,8 +1261,8 @@ static void print_aggr(char *prefix) fprintf(output, "%s", prefix); uval = val * counter->scale; - printout(id, nr, counter, uval, prefix, run, ena, 1.0, - &rt_stat); + printout(config, id, nr, counter, uval, prefix, + run, ena, 1.0, &rt_stat); if (!metric_only) fputc('\n', output); } @@ -1320,9 +1325,10 @@ static struct perf_aggr_thread_value *sort_aggr_thread( return buf; } -static void print_aggr_thread(struct perf_evsel *counter, char *prefix) +static void print_aggr_thread(struct perf_stat_config *config, + struct perf_evsel *counter, char *prefix) { - FILE *output = stat_config.output; + FILE *output = config->output; int nthreads = thread_map__nr(counter->threads); int ncpus = cpu_map__nr(counter->cpus); int thread, sorted_threads, id; @@ -1339,12 +1345,12 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix) fprintf(output, "%s", prefix); id = buf[thread].id; - if (stat_config.stats) - printout(id, 0, buf[thread].counter, buf[thread].uval, + if (config->stats) + printout(config, id, 0, buf[thread].counter, buf[thread].uval, prefix, buf[thread].run, buf[thread].ena, 1.0, - &stat_config.stats[id]); + &config->stats[id]); else - printout(id, 0, buf[thread].counter, buf[thread].uval, + printout(config, id, 0, buf[thread].counter, buf[thread].uval, prefix, buf[thread].run, buf[thread].ena, 1.0, &rt_stat); fputc('\n', output); @@ -1372,9 +1378,10 @@ static void counter_aggr_cb(struct perf_evsel *counter, void *data, * Print out the results of a single counter: * aggregated counts in system-wide mode */ -static void print_counter_aggr(struct perf_evsel *counter, char *prefix) +static void print_counter_aggr(struct perf_stat_config *config, + struct perf_evsel *counter, char *prefix) { - FILE *output = stat_config.output; + FILE *output = config->output; double uval; struct caggr_data cd = { .avg = 0.0 }; @@ -1385,7 +1392,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix) fprintf(output, "%s", prefix); uval = cd.avg * counter->scale; - printout(-1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled, + printout(config, -1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled, cd.avg, &rt_stat); if (!metric_only) fprintf(output, "\n"); @@ -1405,9 +1412,10 @@ static void counter_cb(struct perf_evsel *counter, void *data, * Print out the results of a single counter: * does not use aggregated count in system-wide */ -static void print_counter(struct perf_evsel *counter, char *prefix) +static void print_counter(struct perf_stat_config *config, + struct perf_evsel *counter, char *prefix) { - FILE *output = stat_config.output; + FILE *output = config->output; u64 ena, run, val; double uval; int cpu; @@ -1425,14 +1433,15 @@ static void print_counter(struct perf_evsel *counter, char *prefix) fprintf(output, "%s", prefix); uval = val * counter->scale; - printout(cpu, 0, counter, uval, prefix, run, ena, 1.0, + printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0, &rt_stat); fputc('\n', output); } } -static void print_no_aggr_metric(char *prefix) +static void print_no_aggr_metric(struct perf_stat_config *config, + char *prefix) { int cpu; int nrcpus = 0; @@ -1445,7 +1454,7 @@ static void print_no_aggr_metric(char *prefix) bool first = true; if (prefix) - fputs(prefix, stat_config.output); + fputs(prefix, config->output); evlist__for_each_entry(evsel_list, counter) { if (is_duration_time(counter)) continue; @@ -1458,10 +1467,10 @@ static void print_no_aggr_metric(char *prefix) run = perf_counts(counter->counts, cpu, 0)->run; uval = val * counter->scale; - printout(cpu, 0, counter, uval, prefix, run, ena, 1.0, + printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0, &rt_stat); } - fputc('\n', stat_config.output); + fputc('\n', config->output); } } @@ -1481,25 +1490,25 @@ static const char *aggr_header_csv[] = { [AGGR_GLOBAL] = "" }; -static void print_metric_headers(const char *prefix, bool no_indent) +static void print_metric_headers(struct perf_stat_config *config, + const char *prefix, bool no_indent) { struct perf_stat_output_ctx out; struct perf_evsel *counter; struct outstate os = { - .fh = stat_config.output + .fh = config->output }; if (prefix) - fprintf(stat_config.output, "%s", prefix); + fprintf(config->output, "%s", prefix); if (!csv_output && !no_indent) - fprintf(stat_config.output, "%*s", - aggr_header_lens[stat_config.aggr_mode], ""); + fprintf(config->output, "%*s", + aggr_header_lens[config->aggr_mode], ""); if (csv_output) { - if (stat_config.interval) - fputs("time,", stat_config.output); - fputs(aggr_header_csv[stat_config.aggr_mode], - stat_config.output); + if (config->interval) + fputs("time,", config->output); + fputs(aggr_header_csv[config->aggr_mode], config->output); } /* Print metrics headers only */ @@ -1518,12 +1527,13 @@ static void print_metric_headers(const char *prefix, bool no_indent) &metric_events, &rt_stat); } - fputc('\n', stat_config.output); + fputc('\n', config->output); } -static void print_interval(char *prefix, struct timespec *ts) +static void print_interval(struct perf_stat_config *config, + char *prefix, struct timespec *ts) { - FILE *output = stat_config.output; + FILE *output = config->output; static int num_print_interval; if (interval_clear) @@ -1532,7 +1542,7 @@ static void print_interval(char *prefix, struct timespec *ts) sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep); if ((num_print_interval == 0 && !csv_output) || interval_clear) { - switch (stat_config.aggr_mode) { + switch (config->aggr_mode) { case AGGR_SOCKET: fprintf(output, "# time socket cpus"); if (!metric_only) @@ -1564,14 +1574,15 @@ static void print_interval(char *prefix, struct timespec *ts) } if ((num_print_interval == 0 || interval_clear) && metric_only) - print_metric_headers(" ", true); + print_metric_headers(config, " ", true); if (++num_print_interval == 25) num_print_interval = 0; } -static void print_header(int argc, const char **argv) +static void print_header(struct perf_stat_config *config, + int argc, const char **argv) { - FILE *output = stat_config.output; + FILE *output = config->output; int i; fflush(stdout); @@ -1639,10 +1650,10 @@ static double timeval2double(struct timeval *t) return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC; } -static void print_footer(void) +static void print_footer(struct perf_stat_config *config) { double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC; - FILE *output = stat_config.output; + FILE *output = config->output; int n; if (!null_run) @@ -1673,7 +1684,7 @@ static void print_footer(void) fprintf(output, " %17.*f +- %.*f seconds time elapsed", precision, avg, precision, sd); - print_noise_pct(sd, avg); + print_noise_pct(config, sd, avg); } fprintf(output, "\n\n"); @@ -1703,15 +1714,15 @@ perf_evlist__print_counters(struct perf_evlist *evlist, char buf[64], *prefix = NULL; if (interval) - print_interval(prefix = buf, ts); + print_interval(config, prefix = buf, ts); else - print_header(argc, argv); + print_header(config, argc, argv); if (metric_only) { static int num_print_iv; if (num_print_iv == 0 && !interval) - print_metric_headers(prefix, false); + print_metric_headers(config, prefix, false); if (num_print_iv++ == 25) num_print_iv = 0; if (config->aggr_mode == AGGR_GLOBAL && prefix) @@ -1721,32 +1732,32 @@ perf_evlist__print_counters(struct perf_evlist *evlist, switch (config->aggr_mode) { case AGGR_CORE: case AGGR_SOCKET: - print_aggr(prefix); + print_aggr(config, prefix); break; case AGGR_THREAD: evlist__for_each_entry(evlist, counter) { if (is_duration_time(counter)) continue; - print_aggr_thread(counter, prefix); + print_aggr_thread(config, counter, prefix); } break; case AGGR_GLOBAL: evlist__for_each_entry(evlist, counter) { if (is_duration_time(counter)) continue; - print_counter_aggr(counter, prefix); + print_counter_aggr(config, counter, prefix); } if (metric_only) fputc('\n', config->output); break; case AGGR_NONE: if (metric_only) - print_no_aggr_metric(prefix); + print_no_aggr_metric(config, prefix); else { evlist__for_each_entry(evlist, counter) { if (is_duration_time(counter)) continue; - print_counter(counter, prefix); + print_counter(config, counter, prefix); } } break; @@ -1756,7 +1767,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, } if (!interval && !csv_output) - print_footer(); + print_footer(config); fflush(config->output); } From 6ca9a082b1908ff7f8adedf08166043b83b266f6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:28 +0200 Subject: [PATCH 044/155] perf stat: Pass a 'struct perf_stat_config' argument to global print functions Add 'struct perf_stat_config' argument to the global print functions, so that these functions can be used out of the 'perf stat' command code. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-20-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 8 +- tools/perf/builtin-stat.c | 74 +++++++++-------- tools/perf/util/stat-shadow.c | 147 ++++++++++++++++++---------------- tools/perf/util/stat.h | 8 +- 4 files changed, 131 insertions(+), 106 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index ba481d73f910..6176bae177c2 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1544,7 +1544,8 @@ struct metric_ctx { FILE *fp; }; -static void script_print_metric(void *ctx, const char *color, +static void script_print_metric(struct perf_stat_config *config __maybe_unused, + void *ctx, const char *color, const char *fmt, const char *unit, double val) { @@ -1562,7 +1563,8 @@ static void script_print_metric(void *ctx, const char *color, fprintf(mctx->fp, " %s\n", unit); } -static void script_new_line(void *ctx) +static void script_new_line(struct perf_stat_config *config __maybe_unused, + void *ctx) { struct metric_ctx *mctx = ctx; @@ -1608,7 +1610,7 @@ static void perf_sample__fprint_metric(struct perf_script *script, evsel_script(evsel)->val = val; if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) { for_each_group_member (ev2, evsel->leader) { - perf_stat__print_shadow_stats(ev2, + perf_stat__print_shadow_stats(&stat_config, ev2, evsel_script(ev2)->val, sample->cpu, &ctx, diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index f56da22abccc..7a3361308e61 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -697,11 +697,12 @@ static void print_noise(struct perf_stat_config *config, print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg); } -static void aggr_printout(struct perf_evsel *evsel, int id, int nr) +static void aggr_printout(struct perf_stat_config *config, + struct perf_evsel *evsel, int id, int nr) { - switch (stat_config.aggr_mode) { + switch (config->aggr_mode) { case AGGR_CORE: - fprintf(stat_config.output, "S%d-C%*d%s%*d%s", + fprintf(config->output, "S%d-C%*d%s%*d%s", cpu_map__id_to_socket(id), csv_output ? 0 : -8, cpu_map__id_to_cpu(id), @@ -711,7 +712,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) csv_sep); break; case AGGR_SOCKET: - fprintf(stat_config.output, "S%*d%s%*d%s", + fprintf(config->output, "S%*d%s%*d%s", csv_output ? 0 : -5, id, csv_sep, @@ -720,12 +721,12 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) csv_sep); break; case AGGR_NONE: - fprintf(stat_config.output, "CPU%*d%s", + fprintf(config->output, "CPU%*d%s", csv_output ? 0 : -4, perf_evsel__cpus(evsel)->map[id], csv_sep); break; case AGGR_THREAD: - fprintf(stat_config.output, "%*s-%*d%s", + fprintf(config->output, "%*s-%*d%s", csv_output ? 0 : 16, thread_map__comm(evsel->threads, id), csv_output ? 0 : -8, @@ -750,24 +751,27 @@ struct outstate { #define METRIC_LEN 35 -static void new_line_std(void *ctx) +static void new_line_std(struct perf_stat_config *config __maybe_unused, + void *ctx) { struct outstate *os = ctx; os->newline = true; } -static void do_new_line_std(struct outstate *os) +static void do_new_line_std(struct perf_stat_config *config, + struct outstate *os) { fputc('\n', os->fh); fputs(os->prefix, os->fh); - aggr_printout(os->evsel, os->id, os->nr); - if (stat_config.aggr_mode == AGGR_NONE) + aggr_printout(config, os->evsel, os->id, os->nr); + if (config->aggr_mode == AGGR_NONE) fprintf(os->fh, " "); fprintf(os->fh, " "); } -static void print_metric_std(void *ctx, const char *color, const char *fmt, +static void print_metric_std(struct perf_stat_config *config, + void *ctx, const char *color, const char *fmt, const char *unit, double val) { struct outstate *os = ctx; @@ -783,7 +787,7 @@ static void print_metric_std(void *ctx, const char *color, const char *fmt, } if (newline) - do_new_line_std(os); + do_new_line_std(config, os); n = fprintf(out, " # "); if (color) @@ -793,7 +797,7 @@ static void print_metric_std(void *ctx, const char *color, const char *fmt, fprintf(out, " %-*s", METRIC_LEN - n - 1, unit); } -static void new_line_csv(void *ctx) +static void new_line_csv(struct perf_stat_config *config, void *ctx) { struct outstate *os = ctx; int i; @@ -801,12 +805,13 @@ static void new_line_csv(void *ctx) fputc('\n', os->fh); if (os->prefix) fprintf(os->fh, "%s%s", os->prefix, csv_sep); - aggr_printout(os->evsel, os->id, os->nr); + aggr_printout(config, os->evsel, os->id, os->nr); for (i = 0; i < os->nfields; i++) fputs(csv_sep, os->fh); } -static void print_metric_csv(void *ctx, +static void print_metric_csv(struct perf_stat_config *config __maybe_unused, + void *ctx, const char *color __maybe_unused, const char *fmt, const char *unit, double val) { @@ -853,7 +858,8 @@ static const char *fixunit(char *buf, struct perf_evsel *evsel, return unit; } -static void print_metric_only(void *ctx, const char *color, const char *fmt, +static void print_metric_only(struct perf_stat_config *config __maybe_unused, + void *ctx, const char *color, const char *fmt, const char *unit, double val) { struct outstate *os = ctx; @@ -874,7 +880,8 @@ static void print_metric_only(void *ctx, const char *color, const char *fmt, fprintf(out, "%*s ", mlen, str); } -static void print_metric_only_csv(void *ctx, const char *color __maybe_unused, +static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused, + void *ctx, const char *color __maybe_unused, const char *fmt, const char *unit, double val) { @@ -894,11 +901,13 @@ static void print_metric_only_csv(void *ctx, const char *color __maybe_unused, fprintf(out, "%s%s", vals, csv_sep); } -static void new_line_metric(void *ctx __maybe_unused) +static void new_line_metric(struct perf_stat_config *config __maybe_unused, + void *ctx __maybe_unused) { } -static void print_metric_header(void *ctx, const char *color __maybe_unused, +static void print_metric_header(struct perf_stat_config *config __maybe_unused, + void *ctx, const char *color __maybe_unused, const char *fmt __maybe_unused, const char *unit, double val __maybe_unused) { @@ -936,9 +945,10 @@ static int first_shadow_cpu(struct perf_evsel *evsel, int id) return 0; } -static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) +static void abs_printout(struct perf_stat_config *config, + int id, int nr, struct perf_evsel *evsel, double avg) { - FILE *output = stat_config.output; + FILE *output = config->output; double sc = evsel->scale; const char *fmt; @@ -951,7 +961,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s"; } - aggr_printout(evsel, id, nr); + aggr_printout(config, evsel, id, nr); fprintf(output, fmt, avg, csv_sep); @@ -1004,7 +1014,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, .evsel = counter, }; print_metric_t pm = print_metric_std; - void (*nl)(void *); + new_line_t nl; if (metric_only) { nl = new_line_metric; @@ -1033,10 +1043,10 @@ static void printout(struct perf_stat_config *config, int id, int nr, } if (run == 0 || ena == 0 || counter->counts->scaled == -1) { if (metric_only) { - pm(&os, NULL, "", "", 0); + pm(config, &os, NULL, "", "", 0); return; } - aggr_printout(counter, id, nr); + aggr_printout(config, counter, id, nr); fprintf(config->output, "%*s%s", csv_output ? 0 : 18, @@ -1062,16 +1072,16 @@ static void printout(struct perf_stat_config *config, int id, int nr, csv_sep, counter->cgrp->name); if (!csv_output) - pm(&os, NULL, NULL, "", 0); + pm(config, &os, NULL, NULL, "", 0); print_noise(config, counter, noise); print_running(config, run, ena); if (csv_output) - pm(&os, NULL, NULL, "", 0); + pm(config, &os, NULL, NULL, "", 0); return; } if (!metric_only) - abs_printout(id, nr, counter, uval); + abs_printout(config, id, nr, counter, uval); out.print_metric = pm; out.new_line = nl; @@ -1083,7 +1093,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, print_running(config, run, ena); } - perf_stat__print_shadow_stats(counter, uval, + perf_stat__print_shadow_stats(config, counter, uval, first_shadow_cpu(counter, id), &out, &metric_events, st); if (!csv_output && !metric_only) { @@ -1255,7 +1265,7 @@ static void print_aggr(struct perf_stat_config *config, val = ad.val; if (first && metric_only) { first = false; - aggr_printout(counter, id, nr); + aggr_printout(config, counter, id, nr); } if (prefix && !metric_only) fprintf(output, "%s", prefix); @@ -1459,7 +1469,7 @@ static void print_no_aggr_metric(struct perf_stat_config *config, if (is_duration_time(counter)) continue; if (first) { - aggr_printout(counter, cpu, 0); + aggr_printout(config, counter, cpu, 0); first = false; } val = perf_counts(counter->counts, cpu, 0)->val; @@ -1521,7 +1531,7 @@ static void print_metric_headers(struct perf_stat_config *config, out.new_line = new_line_metric; out.force_header = true; os.evsel = counter; - perf_stat__print_shadow_stats(counter, 0, + perf_stat__print_shadow_stats(config, counter, 0, 0, &out, &metric_events, diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 99990f5f2512..8ad32763cfff 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -410,7 +410,8 @@ static double runtime_stat_n(struct runtime_stat *st, return v->stats.n; } -static void print_stalled_cycles_frontend(int cpu, +static void print_stalled_cycles_frontend(struct perf_stat_config *config, + int cpu, struct perf_evsel *evsel, double avg, struct perf_stat_output_ctx *out, struct runtime_stat *st) @@ -427,13 +428,14 @@ static void print_stalled_cycles_frontend(int cpu, color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio); if (ratio) - out->print_metric(out->ctx, color, "%7.2f%%", "frontend cycles idle", + out->print_metric(config, out->ctx, color, "%7.2f%%", "frontend cycles idle", ratio); else - out->print_metric(out->ctx, NULL, NULL, "frontend cycles idle", 0); + out->print_metric(config, out->ctx, NULL, NULL, "frontend cycles idle", 0); } -static void print_stalled_cycles_backend(int cpu, +static void print_stalled_cycles_backend(struct perf_stat_config *config, + int cpu, struct perf_evsel *evsel, double avg, struct perf_stat_output_ctx *out, struct runtime_stat *st) @@ -449,10 +451,11 @@ static void print_stalled_cycles_backend(int cpu, color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio); - out->print_metric(out->ctx, color, "%7.2f%%", "backend cycles idle", ratio); + out->print_metric(config, out->ctx, color, "%7.2f%%", "backend cycles idle", ratio); } -static void print_branch_misses(int cpu, +static void print_branch_misses(struct perf_stat_config *config, + int cpu, struct perf_evsel *evsel, double avg, struct perf_stat_output_ctx *out, @@ -469,10 +472,11 @@ static void print_branch_misses(int cpu, color = get_ratio_color(GRC_CACHE_MISSES, ratio); - out->print_metric(out->ctx, color, "%7.2f%%", "of all branches", ratio); + out->print_metric(config, out->ctx, color, "%7.2f%%", "of all branches", ratio); } -static void print_l1_dcache_misses(int cpu, +static void print_l1_dcache_misses(struct perf_stat_config *config, + int cpu, struct perf_evsel *evsel, double avg, struct perf_stat_output_ctx *out, @@ -490,10 +494,11 @@ static void print_l1_dcache_misses(int cpu, color = get_ratio_color(GRC_CACHE_MISSES, ratio); - out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio); + out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio); } -static void print_l1_icache_misses(int cpu, +static void print_l1_icache_misses(struct perf_stat_config *config, + int cpu, struct perf_evsel *evsel, double avg, struct perf_stat_output_ctx *out, @@ -510,10 +515,11 @@ static void print_l1_icache_misses(int cpu, ratio = avg / total * 100.0; color = get_ratio_color(GRC_CACHE_MISSES, ratio); - out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio); + out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio); } -static void print_dtlb_cache_misses(int cpu, +static void print_dtlb_cache_misses(struct perf_stat_config *config, + int cpu, struct perf_evsel *evsel, double avg, struct perf_stat_output_ctx *out, @@ -529,10 +535,11 @@ static void print_dtlb_cache_misses(int cpu, ratio = avg / total * 100.0; color = get_ratio_color(GRC_CACHE_MISSES, ratio); - out->print_metric(out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio); + out->print_metric(config, out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio); } -static void print_itlb_cache_misses(int cpu, +static void print_itlb_cache_misses(struct perf_stat_config *config, + int cpu, struct perf_evsel *evsel, double avg, struct perf_stat_output_ctx *out, @@ -548,10 +555,11 @@ static void print_itlb_cache_misses(int cpu, ratio = avg / total * 100.0; color = get_ratio_color(GRC_CACHE_MISSES, ratio); - out->print_metric(out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio); + out->print_metric(config, out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio); } -static void print_ll_cache_misses(int cpu, +static void print_ll_cache_misses(struct perf_stat_config *config, + int cpu, struct perf_evsel *evsel, double avg, struct perf_stat_output_ctx *out, @@ -567,7 +575,7 @@ static void print_ll_cache_misses(int cpu, ratio = avg / total * 100.0; color = get_ratio_color(GRC_CACHE_MISSES, ratio); - out->print_metric(out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio); + out->print_metric(config, out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio); } /* @@ -674,7 +682,8 @@ static double td_be_bound(int ctx, int cpu, struct runtime_stat *st) return sanitize_val(1.0 - sum); } -static void print_smi_cost(int cpu, struct perf_evsel *evsel, +static void print_smi_cost(struct perf_stat_config *config, + int cpu, struct perf_evsel *evsel, struct perf_stat_output_ctx *out, struct runtime_stat *st) { @@ -694,11 +703,12 @@ static void print_smi_cost(int cpu, struct perf_evsel *evsel, if (cost > 10) color = PERF_COLOR_RED; - out->print_metric(out->ctx, color, "%8.1f%%", "SMI cycles%", cost); - out->print_metric(out->ctx, NULL, "%4.0f", "SMI#", smi_num); + out->print_metric(config, out->ctx, color, "%8.1f%%", "SMI cycles%", cost); + out->print_metric(config, out->ctx, NULL, "%4.0f", "SMI#", smi_num); } -static void generic_metric(const char *metric_expr, +static void generic_metric(struct perf_stat_config *config, + const char *metric_expr, struct perf_evsel **metric_events, char *name, const char *metric_name, @@ -737,20 +747,21 @@ static void generic_metric(const char *metric_expr, const char *p = metric_expr; if (expr__parse(&ratio, &pctx, &p) == 0) - print_metric(ctxp, NULL, "%8.1f", + print_metric(config, ctxp, NULL, "%8.1f", metric_name ? metric_name : out->force_header ? name : "", ratio); else - print_metric(ctxp, NULL, NULL, + print_metric(config, ctxp, NULL, NULL, out->force_header ? (metric_name ? metric_name : name) : "", 0); } else - print_metric(ctxp, NULL, NULL, "", 0); + print_metric(config, ctxp, NULL, NULL, "", 0); } -void perf_stat__print_shadow_stats(struct perf_evsel *evsel, +void perf_stat__print_shadow_stats(struct perf_stat_config *config, + struct perf_evsel *evsel, double avg, int cpu, struct perf_stat_output_ctx *out, struct rblist *metric_events, @@ -769,10 +780,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, if (total) { ratio = avg / total; - print_metric(ctxp, NULL, "%7.2f ", + print_metric(config, ctxp, NULL, "%7.2f ", "insn per cycle", ratio); } else { - print_metric(ctxp, NULL, NULL, "insn per cycle", 0); + print_metric(config, ctxp, NULL, NULL, "insn per cycle", 0); } total = runtime_stat_avg(st, STAT_STALLED_CYCLES_FRONT, @@ -783,20 +794,20 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, ctx, cpu)); if (total && avg) { - out->new_line(ctxp); + out->new_line(config, ctxp); ratio = total / avg; - print_metric(ctxp, NULL, "%7.2f ", + print_metric(config, ctxp, NULL, "%7.2f ", "stalled cycles per insn", ratio); } else if (have_frontend_stalled) { - print_metric(ctxp, NULL, NULL, + print_metric(config, ctxp, NULL, NULL, "stalled cycles per insn", 0); } } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) { if (runtime_stat_n(st, STAT_BRANCHES, ctx, cpu) != 0) - print_branch_misses(cpu, evsel, avg, out, st); + print_branch_misses(config, cpu, evsel, avg, out, st); else - print_metric(ctxp, NULL, NULL, "of all branches", 0); + print_metric(config, ctxp, NULL, NULL, "of all branches", 0); } else if ( evsel->attr.type == PERF_TYPE_HW_CACHE && evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D | @@ -804,9 +815,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { if (runtime_stat_n(st, STAT_L1_DCACHE, ctx, cpu) != 0) - print_l1_dcache_misses(cpu, evsel, avg, out, st); + print_l1_dcache_misses(config, cpu, evsel, avg, out, st); else - print_metric(ctxp, NULL, NULL, "of all L1-dcache hits", 0); + print_metric(config, ctxp, NULL, NULL, "of all L1-dcache hits", 0); } else if ( evsel->attr.type == PERF_TYPE_HW_CACHE && evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1I | @@ -814,9 +825,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { if (runtime_stat_n(st, STAT_L1_ICACHE, ctx, cpu) != 0) - print_l1_icache_misses(cpu, evsel, avg, out, st); + print_l1_icache_misses(config, cpu, evsel, avg, out, st); else - print_metric(ctxp, NULL, NULL, "of all L1-icache hits", 0); + print_metric(config, ctxp, NULL, NULL, "of all L1-icache hits", 0); } else if ( evsel->attr.type == PERF_TYPE_HW_CACHE && evsel->attr.config == ( PERF_COUNT_HW_CACHE_DTLB | @@ -824,9 +835,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { if (runtime_stat_n(st, STAT_DTLB_CACHE, ctx, cpu) != 0) - print_dtlb_cache_misses(cpu, evsel, avg, out, st); + print_dtlb_cache_misses(config, cpu, evsel, avg, out, st); else - print_metric(ctxp, NULL, NULL, "of all dTLB cache hits", 0); + print_metric(config, ctxp, NULL, NULL, "of all dTLB cache hits", 0); } else if ( evsel->attr.type == PERF_TYPE_HW_CACHE && evsel->attr.config == ( PERF_COUNT_HW_CACHE_ITLB | @@ -834,9 +845,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { if (runtime_stat_n(st, STAT_ITLB_CACHE, ctx, cpu) != 0) - print_itlb_cache_misses(cpu, evsel, avg, out, st); + print_itlb_cache_misses(config, cpu, evsel, avg, out, st); else - print_metric(ctxp, NULL, NULL, "of all iTLB cache hits", 0); + print_metric(config, ctxp, NULL, NULL, "of all iTLB cache hits", 0); } else if ( evsel->attr.type == PERF_TYPE_HW_CACHE && evsel->attr.config == ( PERF_COUNT_HW_CACHE_LL | @@ -844,9 +855,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { if (runtime_stat_n(st, STAT_LL_CACHE, ctx, cpu) != 0) - print_ll_cache_misses(cpu, evsel, avg, out, st); + print_ll_cache_misses(config, cpu, evsel, avg, out, st); else - print_metric(ctxp, NULL, NULL, "of all LL-cache hits", 0); + print_metric(config, ctxp, NULL, NULL, "of all LL-cache hits", 0); } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) { total = runtime_stat_avg(st, STAT_CACHEREFS, ctx, cpu); @@ -854,32 +865,32 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, ratio = avg * 100 / total; if (runtime_stat_n(st, STAT_CACHEREFS, ctx, cpu) != 0) - print_metric(ctxp, NULL, "%8.3f %%", + print_metric(config, ctxp, NULL, "%8.3f %%", "of all cache refs", ratio); else - print_metric(ctxp, NULL, NULL, "of all cache refs", 0); + print_metric(config, ctxp, NULL, NULL, "of all cache refs", 0); } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) { - print_stalled_cycles_frontend(cpu, evsel, avg, out, st); + print_stalled_cycles_frontend(config, cpu, evsel, avg, out, st); } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) { - print_stalled_cycles_backend(cpu, evsel, avg, out, st); + print_stalled_cycles_backend(config, cpu, evsel, avg, out, st); } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) { total = runtime_stat_avg(st, STAT_NSECS, 0, cpu); if (total) { ratio = avg / total; - print_metric(ctxp, NULL, "%8.3f", "GHz", ratio); + print_metric(config, ctxp, NULL, "%8.3f", "GHz", ratio); } else { - print_metric(ctxp, NULL, NULL, "Ghz", 0); + print_metric(config, ctxp, NULL, NULL, "Ghz", 0); } } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX)) { total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu); if (total) - print_metric(ctxp, NULL, + print_metric(config, ctxp, NULL, "%7.2f%%", "transactional cycles", 100.0 * (avg / total)); else - print_metric(ctxp, NULL, NULL, "transactional cycles", + print_metric(config, ctxp, NULL, NULL, "transactional cycles", 0); } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX_CP)) { total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu); @@ -888,10 +899,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, if (total2 < avg) total2 = avg; if (total) - print_metric(ctxp, NULL, "%7.2f%%", "aborted cycles", + print_metric(config, ctxp, NULL, "%7.2f%%", "aborted cycles", 100.0 * ((total2-avg) / total)); else - print_metric(ctxp, NULL, NULL, "aborted cycles", 0); + print_metric(config, ctxp, NULL, NULL, "aborted cycles", 0); } else if (perf_stat_evsel__is(evsel, TRANSACTION_START)) { total = runtime_stat_avg(st, STAT_CYCLES_IN_TX, ctx, cpu); @@ -900,10 +911,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, ratio = total / avg; if (runtime_stat_n(st, STAT_CYCLES_IN_TX, ctx, cpu) != 0) - print_metric(ctxp, NULL, "%8.0f", + print_metric(config, ctxp, NULL, "%8.0f", "cycles / transaction", ratio); else - print_metric(ctxp, NULL, NULL, "cycles / transaction", + print_metric(config, ctxp, NULL, NULL, "cycles / transaction", 0); } else if (perf_stat_evsel__is(evsel, ELISION_START)) { total = runtime_stat_avg(st, STAT_CYCLES_IN_TX, @@ -912,33 +923,33 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, if (avg) ratio = total / avg; - print_metric(ctxp, NULL, "%8.0f", "cycles / elision", ratio); + print_metric(config, ctxp, NULL, "%8.0f", "cycles / elision", ratio); } else if (perf_evsel__is_clock(evsel)) { if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0) - print_metric(ctxp, NULL, "%8.3f", "CPUs utilized", + print_metric(config, ctxp, NULL, "%8.3f", "CPUs utilized", avg / (ratio * evsel->scale)); else - print_metric(ctxp, NULL, NULL, "CPUs utilized", 0); + print_metric(config, ctxp, NULL, NULL, "CPUs utilized", 0); } else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_BUBBLES)) { double fe_bound = td_fe_bound(ctx, cpu, st); if (fe_bound > 0.2) color = PERF_COLOR_RED; - print_metric(ctxp, color, "%8.1f%%", "frontend bound", + print_metric(config, ctxp, color, "%8.1f%%", "frontend bound", fe_bound * 100.); } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_RETIRED)) { double retiring = td_retiring(ctx, cpu, st); if (retiring > 0.7) color = PERF_COLOR_GREEN; - print_metric(ctxp, color, "%8.1f%%", "retiring", + print_metric(config, ctxp, color, "%8.1f%%", "retiring", retiring * 100.); } else if (perf_stat_evsel__is(evsel, TOPDOWN_RECOVERY_BUBBLES)) { double bad_spec = td_bad_spec(ctx, cpu, st); if (bad_spec > 0.1) color = PERF_COLOR_RED; - print_metric(ctxp, color, "%8.1f%%", "bad speculation", + print_metric(config, ctxp, color, "%8.1f%%", "bad speculation", bad_spec * 100.); } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_ISSUED)) { double be_bound = td_be_bound(ctx, cpu, st); @@ -955,12 +966,12 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, if (be_bound > 0.2) color = PERF_COLOR_RED; if (td_total_slots(ctx, cpu, st) > 0) - print_metric(ctxp, color, "%8.1f%%", name, + print_metric(config, ctxp, color, "%8.1f%%", name, be_bound * 100.); else - print_metric(ctxp, NULL, NULL, name, 0); + print_metric(config, ctxp, NULL, NULL, name, 0); } else if (evsel->metric_expr) { - generic_metric(evsel->metric_expr, evsel->metric_events, evsel->name, + generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name, evsel->metric_name, avg, cpu, out, st); } else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) { char unit = 'M'; @@ -975,9 +986,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, unit = 'K'; } snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit); - print_metric(ctxp, NULL, "%8.3f", unit_buf, ratio); + print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio); } else if (perf_stat_evsel__is(evsel, SMI_NUM)) { - print_smi_cost(cpu, evsel, out, st); + print_smi_cost(config, cpu, evsel, out, st); } else { num = 0; } @@ -987,12 +998,12 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, list_for_each_entry (mexp, &me->head, nd) { if (num++ > 0) - out->new_line(ctxp); - generic_metric(mexp->metric_expr, mexp->metric_events, + out->new_line(config, ctxp); + generic_metric(config, mexp->metric_expr, mexp->metric_events, evsel->name, mexp->metric_name, avg, cpu, out, st); } } if (num == 0) - print_metric(ctxp, NULL, NULL, NULL, 0); + print_metric(config, ctxp, NULL, NULL, NULL, 0); } diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index da6a706daecc..dffcf2110706 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -135,9 +135,10 @@ bool __perf_evsel_stat__is(struct perf_evsel *evsel, extern struct runtime_stat rt_stat; extern struct stats walltime_nsecs_stats; -typedef void (*print_metric_t)(void *ctx, const char *color, const char *unit, +typedef void (*print_metric_t)(struct perf_stat_config *config, + void *ctx, const char *color, const char *unit, const char *fmt, double val); -typedef void (*new_line_t )(void *ctx); +typedef void (*new_line_t)(struct perf_stat_config *config, void *ctx); void runtime_stat__init(struct runtime_stat *st); void runtime_stat__exit(struct runtime_stat *st); @@ -153,7 +154,8 @@ struct perf_stat_output_ctx { bool force_header; }; -void perf_stat__print_shadow_stats(struct perf_evsel *evsel, +void perf_stat__print_shadow_stats(struct perf_stat_config *config, + struct perf_evsel *evsel, double avg, int cpu, struct perf_stat_output_ctx *out, struct rblist *metric_events, From fa7070a38676d660c0a71ab6981bfdca3b340ccd Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:29 +0200 Subject: [PATCH 045/155] perf stat: Move csv_* to 'struct perf_stat_config' Move the static csv_* variables to 'struct perf_stat_config', so that it can be passed around and used outside the 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-21-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 114 +++++++++++++++++++------------------- tools/perf/util/stat.h | 2 + 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 7a3361308e61..4c29e5065e02 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -157,8 +157,6 @@ static bool smi_cost = false; static bool smi_reset = false; static bool big_num = true; static int big_num_opt = -1; -static const char *csv_sep = NULL; -static bool csv_output = false; static bool group = false; static const char *pre_cmd = NULL; static const char *post_cmd = NULL; @@ -663,11 +661,11 @@ static int run_perf_stat(int argc, const char **argv, int run_idx) static void print_running(struct perf_stat_config *config, u64 run, u64 ena) { - if (csv_output) { + if (config->csv_output) { fprintf(config->output, "%s%" PRIu64 "%s%.2f", - csv_sep, + config->csv_sep, run, - csv_sep, + config->csv_sep, ena ? 100.0 * run / ena : 100.0); } else if (run != ena) { fprintf(config->output, " (%.2f%%)", 100.0 * run / ena); @@ -679,8 +677,8 @@ static void print_noise_pct(struct perf_stat_config *config, { double pct = rel_stddev_stats(total, avg); - if (csv_output) - fprintf(config->output, "%s%.2f%%", csv_sep, pct); + if (config->csv_output) + fprintf(config->output, "%s%.2f%%", config->csv_sep, pct); else if (pct) fprintf(config->output, " ( +-%6.2f%% )", pct); } @@ -704,34 +702,34 @@ static void aggr_printout(struct perf_stat_config *config, case AGGR_CORE: fprintf(config->output, "S%d-C%*d%s%*d%s", cpu_map__id_to_socket(id), - csv_output ? 0 : -8, + config->csv_output ? 0 : -8, cpu_map__id_to_cpu(id), - csv_sep, - csv_output ? 0 : 4, + config->csv_sep, + config->csv_output ? 0 : 4, nr, - csv_sep); + config->csv_sep); break; case AGGR_SOCKET: fprintf(config->output, "S%*d%s%*d%s", - csv_output ? 0 : -5, + config->csv_output ? 0 : -5, id, - csv_sep, - csv_output ? 0 : 4, + config->csv_sep, + config->csv_output ? 0 : 4, nr, - csv_sep); + config->csv_sep); break; case AGGR_NONE: fprintf(config->output, "CPU%*d%s", - csv_output ? 0 : -4, - perf_evsel__cpus(evsel)->map[id], csv_sep); + config->csv_output ? 0 : -4, + perf_evsel__cpus(evsel)->map[id], config->csv_sep); break; case AGGR_THREAD: fprintf(config->output, "%*s-%*d%s", - csv_output ? 0 : 16, + config->csv_output ? 0 : 16, thread_map__comm(evsel->threads, id), - csv_output ? 0 : -8, + config->csv_output ? 0 : -8, thread_map__pid(evsel->threads, id), - csv_sep); + config->csv_sep); break; case AGGR_GLOBAL: case AGGR_UNSET: @@ -804,10 +802,10 @@ static void new_line_csv(struct perf_stat_config *config, void *ctx) fputc('\n', os->fh); if (os->prefix) - fprintf(os->fh, "%s%s", os->prefix, csv_sep); + fprintf(os->fh, "%s%s", os->prefix, config->csv_sep); aggr_printout(config, os->evsel, os->id, os->nr); for (i = 0; i < os->nfields; i++) - fputs(csv_sep, os->fh); + fputs(config->csv_sep, os->fh); } static void print_metric_csv(struct perf_stat_config *config __maybe_unused, @@ -820,7 +818,7 @@ static void print_metric_csv(struct perf_stat_config *config __maybe_unused, char buf[64], *vals, *ends; if (unit == NULL || fmt == NULL) { - fprintf(out, "%s%s", csv_sep, csv_sep); + fprintf(out, "%s%s", config->csv_sep, config->csv_sep); return; } snprintf(buf, sizeof(buf), fmt, val); @@ -830,7 +828,7 @@ static void print_metric_csv(struct perf_stat_config *config __maybe_unused, *ends = 0; while (isspace(*unit)) unit++; - fprintf(out, "%s%s%s%s", csv_sep, vals, csv_sep, unit); + fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, unit); } /* Filter out some columns that don't work well in metrics only mode */ @@ -898,7 +896,7 @@ static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused while (isdigit(*ends) || *ends == '.') ends++; *ends = 0; - fprintf(out, "%s%s", vals, csv_sep); + fprintf(out, "%s%s", vals, config->csv_sep); } static void new_line_metric(struct perf_stat_config *config __maybe_unused, @@ -917,8 +915,8 @@ static void print_metric_header(struct perf_stat_config *config __maybe_unused, if (!valid_only_metric(unit)) return; unit = fixunit(tbuf, os->evsel, unit); - if (csv_output) - fprintf(os->fh, "%s%s", unit, csv_sep); + if (config->csv_output) + fprintf(os->fh, "%s%s", unit, config->csv_sep); else fprintf(os->fh, "%*s ", metric_only_len, unit); } @@ -952,7 +950,7 @@ static void abs_printout(struct perf_stat_config *config, double sc = evsel->scale; const char *fmt; - if (csv_output) { + if (config->csv_output) { fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s"; } else { if (big_num) @@ -963,17 +961,17 @@ static void abs_printout(struct perf_stat_config *config, aggr_printout(config, evsel, id, nr); - fprintf(output, fmt, avg, csv_sep); + fprintf(output, fmt, avg, config->csv_sep); if (evsel->unit) fprintf(output, "%-*s%s", - csv_output ? 0 : unit_width, - evsel->unit, csv_sep); + config->csv_output ? 0 : unit_width, + evsel->unit, config->csv_sep); - fprintf(output, "%-*s", csv_output ? 0 : 25, perf_evsel__name(evsel)); + fprintf(output, "%-*s", config->csv_output ? 0 : 25, perf_evsel__name(evsel)); if (evsel->cgrp) - fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); + fprintf(output, "%s%s", config->csv_sep, evsel->cgrp->name); } static bool is_mixed_hw_group(struct perf_evsel *counter) @@ -1018,14 +1016,14 @@ static void printout(struct perf_stat_config *config, int id, int nr, if (metric_only) { nl = new_line_metric; - if (csv_output) + if (config->csv_output) pm = print_metric_only_csv; else pm = print_metric_only; } else nl = new_line_std; - if (csv_output && !metric_only) { + if (config->csv_output && !metric_only) { static int aggr_fields[] = { [AGGR_GLOBAL] = 0, [AGGR_THREAD] = 1, @@ -1049,9 +1047,9 @@ static void printout(struct perf_stat_config *config, int id, int nr, aggr_printout(config, counter, id, nr); fprintf(config->output, "%*s%s", - csv_output ? 0 : 18, + config->csv_output ? 0 : 18, counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, - csv_sep); + config->csv_sep); if (counter->supported) { print_free_counters_hint = 1; @@ -1060,22 +1058,22 @@ static void printout(struct perf_stat_config *config, int id, int nr, } fprintf(config->output, "%-*s%s", - csv_output ? 0 : unit_width, - counter->unit, csv_sep); + config->csv_output ? 0 : unit_width, + counter->unit, config->csv_sep); fprintf(config->output, "%*s", - csv_output ? 0 : -25, + config->csv_output ? 0 : -25, perf_evsel__name(counter)); if (counter->cgrp) fprintf(config->output, "%s%s", - csv_sep, counter->cgrp->name); + config->csv_sep, counter->cgrp->name); - if (!csv_output) + if (!config->csv_output) pm(config, &os, NULL, NULL, "", 0); print_noise(config, counter, noise); print_running(config, run, ena); - if (csv_output) + if (config->csv_output) pm(config, &os, NULL, NULL, "", 0); return; } @@ -1088,7 +1086,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, out.ctx = &os; out.force_header = false; - if (csv_output && !metric_only) { + if (config->csv_output && !metric_only) { print_noise(config, counter, noise); print_running(config, run, ena); } @@ -1096,7 +1094,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, perf_stat__print_shadow_stats(config, counter, uval, first_shadow_cpu(counter, id), &out, &metric_events, st); - if (!csv_output && !metric_only) { + if (!config->csv_output && !metric_only) { print_noise(config, counter, noise); print_running(config, run, ena); } @@ -1512,10 +1510,10 @@ static void print_metric_headers(struct perf_stat_config *config, if (prefix) fprintf(config->output, "%s", prefix); - if (!csv_output && !no_indent) + if (!config->csv_output && !no_indent) fprintf(config->output, "%*s", aggr_header_lens[config->aggr_mode], ""); - if (csv_output) { + if (config->csv_output) { if (config->interval) fputs("time,", config->output); fputs(aggr_header_csv[config->aggr_mode], config->output); @@ -1549,9 +1547,9 @@ static void print_interval(struct perf_stat_config *config, if (interval_clear) puts(CONSOLE_CLEAR); - sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep); + sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep); - if ((num_print_interval == 0 && !csv_output) || interval_clear) { + if ((num_print_interval == 0 && !config->csv_output) || interval_clear) { switch (config->aggr_mode) { case AGGR_SOCKET: fprintf(output, "# time socket cpus"); @@ -1597,7 +1595,7 @@ static void print_header(struct perf_stat_config *config, fflush(stdout); - if (!csv_output) { + if (!config->csv_output) { fprintf(output, "\n"); fprintf(output, " Performance counter stats for "); if (target.system_wide) @@ -1776,7 +1774,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, break; } - if (!interval && !csv_output) + if (!interval && !config->csv_output) print_footer(config); fflush(config->output); @@ -1896,7 +1894,7 @@ static const struct option stat_options[] = { OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode, "disable CPU count aggregation", AGGR_NONE), OPT_BOOLEAN(0, "no-merge", &no_merge, "Do not merge identical named events"), - OPT_STRING('x', "field-separator", &csv_sep, "separator", + OPT_STRING('x', "field-separator", &stat_config.csv_sep, "separator", "print counts with custom separator"), OPT_CALLBACK('G', "cgroup", &evsel_list, "name", "monitor event in cgroup name only", parse_cgroups), @@ -2749,12 +2747,12 @@ int cmd_stat(int argc, const char **argv) perf_stat__collect_metric_expr(evsel_list); perf_stat__init_shadow_stats(); - if (csv_sep) { - csv_output = true; - if (!strcmp(csv_sep, "\\t")) - csv_sep = "\t"; + if (stat_config.csv_sep) { + stat_config.csv_output = true; + if (!strcmp(stat_config.csv_sep, "\\t")) + stat_config.csv_sep = "\t"; } else - csv_sep = DEFAULT_SEPARATOR; + stat_config.csv_sep = DEFAULT_SEPARATOR; if (argc && !strncmp(argv[0], "rec", 3)) { argc = __cmd_record(argc, argv); @@ -2827,7 +2825,7 @@ int cmd_stat(int argc, const char **argv) /* * let the spreadsheet do the pretty-printing */ - if (csv_output) { + if (stat_config.csv_output) { /* User explicitly passed -B? */ if (big_num_opt == 1) { fprintf(stderr, "-B option not supported with -x\n"); diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index dffcf2110706..18546d8b0279 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -91,6 +91,7 @@ struct perf_stat_config { bool scale; bool no_inherit; bool identifier; + bool csv_output; FILE *output; unsigned int interval; unsigned int timeout; @@ -98,6 +99,7 @@ struct perf_stat_config { int times; struct runtime_stat *stats; int stats_num; + const char *csv_sep; }; void update_stats(struct stats *stats, u64 val); From 132c6ba3c440fd21a45ff7f9d7a1f53813f4d0e3 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:30 +0200 Subject: [PATCH 046/155] perf stat: Move 'interval_clear' to 'struct perf_stat_config' Move the static 'interval_clear' variable to 'struct perf_stat_config', so it can be passed around and used outside the 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-22-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 9 ++++----- tools/perf/util/stat.h | 1 + 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 4c29e5065e02..89297ab77d21 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -172,7 +172,6 @@ static struct cpu_map *aggr_map; static aggr_get_id_t aggr_get_id; static bool append_file; static bool interval_count; -static bool interval_clear; static const char *output_name; static int output_fd; static int print_free_counters_hint; @@ -1544,12 +1543,12 @@ static void print_interval(struct perf_stat_config *config, FILE *output = config->output; static int num_print_interval; - if (interval_clear) + if (config->interval_clear) puts(CONSOLE_CLEAR); sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep); - if ((num_print_interval == 0 && !config->csv_output) || interval_clear) { + if ((num_print_interval == 0 && !config->csv_output) || config->interval_clear) { switch (config->aggr_mode) { case AGGR_SOCKET: fprintf(output, "# time socket cpus"); @@ -1581,7 +1580,7 @@ static void print_interval(struct perf_stat_config *config, } } - if ((num_print_interval == 0 || interval_clear) && metric_only) + if ((num_print_interval == 0 || config->interval_clear) && metric_only) print_metric_headers(config, " ", true); if (++num_print_interval == 25) num_print_interval = 0; @@ -1911,7 +1910,7 @@ static const struct option stat_options[] = { "(overhead is possible for values <= 100ms)"), OPT_INTEGER(0, "interval-count", &stat_config.times, "print counts for fixed number of times"), - OPT_BOOLEAN(0, "interval-clear", &interval_clear, + OPT_BOOLEAN(0, "interval-clear", &stat_config.interval_clear, "clear screen in between new interval"), OPT_UINTEGER(0, "timeout", &stat_config.timeout, "stop workload and print counts after a timeout period in ms (>= 10ms)"), diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 18546d8b0279..470ab37601be 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -92,6 +92,7 @@ struct perf_stat_config { bool no_inherit; bool identifier; bool csv_output; + bool interval_clear; FILE *output; unsigned int interval; unsigned int timeout; From 0ce5aa0266604c77ee64882b70c980e843629177 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:31 +0200 Subject: [PATCH 047/155] perf stat: Move 'metric_only' to 'struct perf_stat_config' Move the static 'metric_only' variable to 'struct perf_stat_config', so it can be passed around and used outside the 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-23-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 29 ++++++++++++++++------------- tools/perf/util/stat.h | 1 + 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 89297ab77d21..397cb4f28d7f 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -163,7 +163,6 @@ static const char *post_cmd = NULL; static bool sync_run = false; static unsigned int unit_width = 4; /* strlen("unit") */ static bool forever = false; -static bool metric_only = false; static bool force_metric_only = false; static bool no_merge = false; static bool walltime_run_table = false; @@ -1013,7 +1012,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, print_metric_t pm = print_metric_std; new_line_t nl; - if (metric_only) { + if (config->metric_only) { nl = new_line_metric; if (config->csv_output) pm = print_metric_only_csv; @@ -1022,7 +1021,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, } else nl = new_line_std; - if (config->csv_output && !metric_only) { + if (config->csv_output && !config->metric_only) { static int aggr_fields[] = { [AGGR_GLOBAL] = 0, [AGGR_THREAD] = 1, @@ -1039,7 +1038,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, os.nfields++; } if (run == 0 || ena == 0 || counter->counts->scaled == -1) { - if (metric_only) { + if (config->metric_only) { pm(config, &os, NULL, "", "", 0); return; } @@ -1077,7 +1076,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, return; } - if (!metric_only) + if (!config->metric_only) abs_printout(config, id, nr, counter, uval); out.print_metric = pm; @@ -1085,7 +1084,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, out.ctx = &os; out.force_header = false; - if (config->csv_output && !metric_only) { + if (config->csv_output && !config->metric_only) { print_noise(config, counter, noise); print_running(config, run, ena); } @@ -1093,7 +1092,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, perf_stat__print_shadow_stats(config, counter, uval, first_shadow_cpu(counter, id), &out, &metric_events, st); - if (!config->csv_output && !metric_only) { + if (!config->csv_output && !config->metric_only) { print_noise(config, counter, noise); print_running(config, run, ena); } @@ -1225,6 +1224,7 @@ static void aggr_cb(struct perf_evsel *counter, void *data, bool first) static void print_aggr(struct perf_stat_config *config, char *prefix) { + bool metric_only = config->metric_only; FILE *output = config->output; struct perf_evsel *counter; int s, id, nr; @@ -1388,6 +1388,7 @@ static void counter_aggr_cb(struct perf_evsel *counter, void *data, static void print_counter_aggr(struct perf_stat_config *config, struct perf_evsel *counter, char *prefix) { + bool metric_only = config->metric_only; FILE *output = config->output; double uval; struct caggr_data cd = { .avg = 0.0 }; @@ -1540,6 +1541,7 @@ static void print_metric_headers(struct perf_stat_config *config, static void print_interval(struct perf_stat_config *config, char *prefix, struct timespec *ts) { + bool metric_only = config->metric_only; FILE *output = config->output; static int num_print_interval; @@ -1716,6 +1718,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, struct timespec *ts, int argc, const char **argv) { + bool metric_only = config->metric_only; int interval = config->interval; struct perf_evsel *counter; char buf[64], *prefix = NULL; @@ -1843,7 +1846,7 @@ static int enable_metric_only(const struct option *opt __maybe_unused, const char *s __maybe_unused, int unset) { force_metric_only = true; - metric_only = !unset; + stat_config.metric_only = !unset; return 0; } @@ -1922,7 +1925,7 @@ static const struct option stat_options[] = { "aggregate counts per thread", AGGR_THREAD), OPT_UINTEGER('D', "delay", &stat_config.initial_delay, "ms to wait before starting measurement after program start"), - OPT_CALLBACK_NOOPT(0, "metric-only", &metric_only, NULL, + OPT_CALLBACK_NOOPT(0, "metric-only", &stat_config.metric_only, NULL, "Only print computed metrics. No raw values", enable_metric_only), OPT_BOOLEAN(0, "topdown", &topdown_run, "measure topdown level 1 statistics"), @@ -2345,7 +2348,7 @@ static int add_default_attributes(void) if (pmu_have_event("msr", "aperf") && pmu_have_event("msr", "smi")) { if (!force_metric_only) - metric_only = true; + stat_config.metric_only = true; err = parse_events(evsel_list, smi_cost_attrs, &errinfo); } else { fprintf(stderr, "To measure SMI cost, it needs " @@ -2376,7 +2379,7 @@ static int add_default_attributes(void) } if (!force_metric_only) - metric_only = true; + stat_config.metric_only = true; if (topdown_filter_events(topdown_attrs, &str, arch_topdown_check_group(&warn)) < 0) { pr_err("Out of memory\n"); @@ -2776,12 +2779,12 @@ int cmd_stat(int argc, const char **argv) goto out; } - if (metric_only && stat_config.aggr_mode == AGGR_THREAD) { + if (stat_config.metric_only && stat_config.aggr_mode == AGGR_THREAD) { fprintf(stderr, "--metric-only is not supported with --per-thread\n"); goto out; } - if (metric_only && run_count > 1) { + if (stat_config.metric_only && run_count > 1) { fprintf(stderr, "--metric-only is not supported with -r\n"); goto out; } diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 470ab37601be..da838182b99c 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -93,6 +93,7 @@ struct perf_stat_config { bool identifier; bool csv_output; bool interval_clear; + bool metric_only; FILE *output; unsigned int interval; unsigned int timeout; From df4f7b4d4b1e61e6b16ac2e3760be46bac86e4f4 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:32 +0200 Subject: [PATCH 048/155] perf stat: Move 'unit_width' to 'struct perf_stat_config' Move the static 'unit_width' variable to 'struct perf_stat_config', so it can be passed around and used outside the 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-24-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 11 ++++++----- tools/perf/util/stat.h | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 397cb4f28d7f..24171aa6c41f 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -161,7 +161,6 @@ static bool group = false; static const char *pre_cmd = NULL; static const char *post_cmd = NULL; static bool sync_run = false; -static unsigned int unit_width = 4; /* strlen("unit") */ static bool forever = false; static bool force_metric_only = false; static bool no_merge = false; @@ -200,6 +199,7 @@ static volatile int done = 0; static struct perf_stat_config stat_config = { .aggr_mode = AGGR_GLOBAL, .scale = true, + .unit_width = 4, /* strlen("unit") */ }; static bool is_duration_time(struct perf_evsel *evsel) @@ -524,8 +524,8 @@ try_again: counter->supported = true; l = strlen(counter->unit); - if (l > unit_width) - unit_width = l; + if (l > stat_config.unit_width) + stat_config.unit_width = l; if (perf_evsel__should_store_id(counter) && perf_evsel__store_ids(counter, evsel_list)) @@ -963,7 +963,7 @@ static void abs_printout(struct perf_stat_config *config, if (evsel->unit) fprintf(output, "%-*s%s", - config->csv_output ? 0 : unit_width, + config->csv_output ? 0 : config->unit_width, evsel->unit, config->csv_sep); fprintf(output, "%-*s", config->csv_output ? 0 : 25, perf_evsel__name(evsel)); @@ -1056,7 +1056,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, } fprintf(config->output, "%-*s%s", - config->csv_output ? 0 : unit_width, + config->csv_output ? 0 : config->unit_width, counter->unit, config->csv_sep); fprintf(config->output, "%*s", @@ -1542,6 +1542,7 @@ static void print_interval(struct perf_stat_config *config, char *prefix, struct timespec *ts) { bool metric_only = config->metric_only; + unsigned int unit_width = config->unit_width; FILE *output = config->output; static int num_print_interval; diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index da838182b99c..2dc66e0ba4b8 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -98,6 +98,7 @@ struct perf_stat_config { unsigned int interval; unsigned int timeout; unsigned int initial_delay; + unsigned int unit_width; int times; struct runtime_stat *stats; int stats_num; From c512e0eae4c63be8c5964c3942b2e9c04dcd459e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:33 +0200 Subject: [PATCH 049/155] perf stat: Add 'target' argument to perf_evlist__print_counters() Add 'struct target' argument to perf_evlist__print_counters(), so the function does not depend on the 'perf stat' command object local target and can be moved out. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-25-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 24171aa6c41f..528f85146b59 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1590,6 +1590,7 @@ static void print_interval(struct perf_stat_config *config, } static void print_header(struct perf_stat_config *config, + struct target *_target, int argc, const char **argv) { FILE *output = config->output; @@ -1600,18 +1601,18 @@ static void print_header(struct perf_stat_config *config, if (!config->csv_output) { fprintf(output, "\n"); fprintf(output, " Performance counter stats for "); - if (target.system_wide) + if (_target->system_wide) fprintf(output, "\'system wide"); - else if (target.cpu_list) - fprintf(output, "\'CPU(s) %s", target.cpu_list); - else if (!target__has_task(&target)) { + else if (_target->cpu_list) + fprintf(output, "\'CPU(s) %s", _target->cpu_list); + else if (!target__has_task(_target)) { fprintf(output, "\'%s", argv ? argv[0] : "pipe"); for (i = 1; argv && (i < argc); i++) fprintf(output, " %s", argv[i]); - } else if (target.pid) - fprintf(output, "process id \'%s", target.pid); + } else if (_target->pid) + fprintf(output, "process id \'%s", _target->pid); else - fprintf(output, "thread id \'%s", target.tid); + fprintf(output, "thread id \'%s", _target->tid); fprintf(output, "\'"); if (run_count > 1) @@ -1716,6 +1717,7 @@ static void print_footer(struct perf_stat_config *config) static void perf_evlist__print_counters(struct perf_evlist *evlist, struct perf_stat_config *config, + struct target *_target, struct timespec *ts, int argc, const char **argv) { @@ -1727,7 +1729,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, if (interval) print_interval(config, prefix = buf, ts); else - print_header(config, argc, argv); + print_header(config, _target, argc, argv); if (metric_only) { static int num_print_iv; @@ -1789,7 +1791,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) if (STAT_RECORD && perf_stat.data.is_pipe) return; - perf_evlist__print_counters(evsel_list, &stat_config, + perf_evlist__print_counters(evsel_list, &stat_config, &target, ts, argc, argv); } From bc0bcda201e87d62f0922fa664376355b0fc77ff Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:34 +0200 Subject: [PATCH 050/155] perf stat: Pass 'evlist' argument to print functions Add 'evlist' argument to print functions to get rid of the global 'evsel_list' variable dependency. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-26-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 528f85146b59..46181ac492c5 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1222,6 +1222,7 @@ static void aggr_cb(struct perf_evsel *counter, void *data, bool first) } static void print_aggr(struct perf_stat_config *config, + struct perf_evlist *evlist, char *prefix) { bool metric_only = config->metric_only; @@ -1248,7 +1249,7 @@ static void print_aggr(struct perf_stat_config *config, ad.id = id = aggr_map->map[s]; first = true; - evlist__for_each_entry(evsel_list, counter) { + evlist__for_each_entry(evlist, counter) { if (is_duration_time(counter)) continue; @@ -1449,6 +1450,7 @@ static void print_counter(struct perf_stat_config *config, } static void print_no_aggr_metric(struct perf_stat_config *config, + struct perf_evlist *evlist, char *prefix) { int cpu; @@ -1457,13 +1459,13 @@ static void print_no_aggr_metric(struct perf_stat_config *config, u64 ena, run, val; double uval; - nrcpus = evsel_list->cpus->nr; + nrcpus = evlist->cpus->nr; for (cpu = 0; cpu < nrcpus; cpu++) { bool first = true; if (prefix) fputs(prefix, config->output); - evlist__for_each_entry(evsel_list, counter) { + evlist__for_each_entry(evlist, counter) { if (is_duration_time(counter)) continue; if (first) { @@ -1499,6 +1501,7 @@ static const char *aggr_header_csv[] = { }; static void print_metric_headers(struct perf_stat_config *config, + struct perf_evlist *evlist, const char *prefix, bool no_indent) { struct perf_stat_output_ctx out; @@ -1520,7 +1523,7 @@ static void print_metric_headers(struct perf_stat_config *config, } /* Print metrics headers only */ - evlist__for_each_entry(evsel_list, counter) { + evlist__for_each_entry(evlist, counter) { if (is_duration_time(counter)) continue; os.evsel = counter; @@ -1539,6 +1542,7 @@ static void print_metric_headers(struct perf_stat_config *config, } static void print_interval(struct perf_stat_config *config, + struct perf_evlist *evlist, char *prefix, struct timespec *ts) { bool metric_only = config->metric_only; @@ -1584,7 +1588,7 @@ static void print_interval(struct perf_stat_config *config, } if ((num_print_interval == 0 || config->interval_clear) && metric_only) - print_metric_headers(config, " ", true); + print_metric_headers(config, evlist, " ", true); if (++num_print_interval == 25) num_print_interval = 0; } @@ -1727,7 +1731,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, char buf[64], *prefix = NULL; if (interval) - print_interval(config, prefix = buf, ts); + print_interval(config, evlist, prefix = buf, ts); else print_header(config, _target, argc, argv); @@ -1735,7 +1739,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, static int num_print_iv; if (num_print_iv == 0 && !interval) - print_metric_headers(config, prefix, false); + print_metric_headers(config, evlist, prefix, false); if (num_print_iv++ == 25) num_print_iv = 0; if (config->aggr_mode == AGGR_GLOBAL && prefix) @@ -1745,7 +1749,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, switch (config->aggr_mode) { case AGGR_CORE: case AGGR_SOCKET: - print_aggr(config, prefix); + print_aggr(config, evlist, prefix); break; case AGGR_THREAD: evlist__for_each_entry(evlist, counter) { @@ -1765,7 +1769,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, break; case AGGR_NONE: if (metric_only) - print_no_aggr_metric(config, prefix); + print_no_aggr_metric(config, evlist, prefix); else { evlist__for_each_entry(evlist, counter) { if (is_duration_time(counter)) From 0c538a9462953dfcde2fe961aca2cf75c2747040 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:35 +0200 Subject: [PATCH 051/155] perf stat: Use 'evsel->evlist' instead of 'evsel_list' in collect_all_aliases() Use 'evsel->evlist' instead of 'evsel_list' in collect_all_aliases(), to get rid of the global 'evsel_list' variable dependency. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-27-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 46181ac492c5..11741f3a8342 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1154,10 +1154,11 @@ static void collect_all_aliases(struct perf_evsel *counter, bool first), void *data) { + struct perf_evlist *evlist = counter->evlist; struct perf_evsel *alias; - alias = list_prepare_entry(counter, &(evsel_list->entries), node); - list_for_each_entry_continue (alias, &evsel_list->entries, node) { + alias = list_prepare_entry(counter, &(evlist->entries), node); + list_for_each_entry_continue (alias, &evlist->entries, node) { if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) || alias->scale != counter->scale || alias->cgrp != counter->cgrp || From d97ae04b3d5263be242a6a9f9eef6422fc86326a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:36 +0200 Subject: [PATCH 052/155] perf stat: Move 'run_count' to 'struct perf_stat_config' Move the static 'run_count' variable to 'struct perf_stat_config', so that it can be passed around and used outside the 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-28-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 39 ++++++++++++++++++++------------------- tools/perf/util/stat.h | 1 + 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 11741f3a8342..1276596840c9 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -147,7 +147,6 @@ typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu); #define METRIC_ONLY_LEN 20 -static int run_count = 1; static volatile pid_t child_pid = -1; static bool null_run = false; static int detailed_run = 0; @@ -200,6 +199,7 @@ static struct perf_stat_config stat_config = { .aggr_mode = AGGR_GLOBAL, .scale = true, .unit_width = 4, /* strlen("unit") */ + .run_count = 1, }; static bool is_duration_time(struct perf_evsel *evsel) @@ -686,7 +686,7 @@ static void print_noise(struct perf_stat_config *config, { struct perf_stat_evsel *ps; - if (run_count == 1) + if (config->run_count == 1) return; ps = evsel->stats; @@ -1620,8 +1620,8 @@ static void print_header(struct perf_stat_config *config, fprintf(output, "thread id \'%s", _target->tid); fprintf(output, "\'"); - if (run_count > 1) - fprintf(output, " (%d runs)", run_count); + if (config->run_count > 1) + fprintf(output, " (%d runs)", config->run_count); fprintf(output, ":\n\n"); } } @@ -1634,7 +1634,8 @@ static int get_precision(double num) return lround(ceil(-log10(num))); } -static void print_table(FILE *output, int precision, double avg) +static void print_table(struct perf_stat_config *config, + FILE *output, int precision, double avg) { char tmp[64]; int idx, indent = 0; @@ -1645,7 +1646,7 @@ static void print_table(FILE *output, int precision, double avg) fprintf(output, "%*s# Table of individual measurements:\n", indent, ""); - for (idx = 0; idx < run_count; idx++) { + for (idx = 0; idx < config->run_count; idx++) { double run = (double) walltime_run[idx] / NSEC_PER_SEC; int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5); @@ -1675,7 +1676,7 @@ static void print_footer(struct perf_stat_config *config) if (!null_run) fprintf(output, "\n"); - if (run_count == 1) { + if (config->run_count == 1) { fprintf(output, " %17.9f seconds time elapsed", avg); if (ru_display) { @@ -1695,7 +1696,7 @@ static void print_footer(struct perf_stat_config *config) int precision = get_precision(sd) + 2; if (walltime_run_table) - print_table(output, precision, avg); + print_table(config, output, precision, avg); fprintf(output, " %17.*f +- %.*f seconds time elapsed", precision, avg, precision, sd); @@ -1886,7 +1887,7 @@ static const struct option stat_options[] = { OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"), OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"), - OPT_INTEGER('r', "repeat", &run_count, + OPT_INTEGER('r', "repeat", &stat_config.run_count, "repeat command and print average + stddev (max: 100, forever: 0)"), OPT_BOOLEAN(0, "table", &walltime_run_table, "display details about each run (only with -r option)"), @@ -2484,7 +2485,7 @@ static int __cmd_record(int argc, const char **argv) if (output_name) data->file.path = output_name; - if (run_count != 1 || forever) { + if (stat_config.run_count != 1 || forever) { pr_err("Cannot use -r option with perf stat record.\n"); return -1; } @@ -2792,12 +2793,12 @@ int cmd_stat(int argc, const char **argv) goto out; } - if (stat_config.metric_only && run_count > 1) { + if (stat_config.metric_only && stat_config.run_count > 1) { fprintf(stderr, "--metric-only is not supported with -r\n"); goto out; } - if (walltime_run_table && run_count <= 1) { + if (walltime_run_table && stat_config.run_count <= 1) { fprintf(stderr, "--table is only supported with -r\n"); parse_options_usage(stat_usage, stat_options, "r", 1); parse_options_usage(NULL, stat_options, "table", 0); @@ -2853,20 +2854,20 @@ int cmd_stat(int argc, const char **argv) * Display user/system times only for single * run and when there's specified tracee. */ - if ((run_count == 1) && target__none(&target)) + if ((stat_config.run_count == 1) && target__none(&target)) ru_display = true; - if (run_count < 0) { + if (stat_config.run_count < 0) { pr_err("Run count must be a positive number\n"); parse_options_usage(stat_usage, stat_options, "r", 1); goto out; - } else if (run_count == 0) { + } else if (stat_config.run_count == 0) { forever = true; - run_count = 1; + stat_config.run_count = 1; } if (walltime_run_table) { - walltime_run = zalloc(run_count * sizeof(walltime_run[0])); + walltime_run = zalloc(stat_config.run_count * sizeof(walltime_run[0])); if (!walltime_run) { pr_err("failed to setup -r option"); goto out; @@ -2994,8 +2995,8 @@ int cmd_stat(int argc, const char **argv) signal(SIGABRT, skip_signal); status = 0; - for (run_idx = 0; forever || run_idx < run_count; run_idx++) { - if (run_count != 1 && verbose > 0) + for (run_idx = 0; forever || run_idx < stat_config.run_count; run_idx++) { + if (stat_config.run_count != 1 && verbose > 0) fprintf(output, "[ perf stat: executing run #%d ... ]\n", run_idx + 1); diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 2dc66e0ba4b8..351a36f5f5b0 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -100,6 +100,7 @@ struct perf_stat_config { unsigned int initial_delay; unsigned int unit_width; int times; + int run_count; struct runtime_stat *stats; int stats_num; const char *csv_sep; From ee1760e2cf623bc6834fc3e4e89c6ad030a25dfd Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:37 +0200 Subject: [PATCH 053/155] perf stat: Move 'metric_only_len' to 'struct perf_stat_config' Move the static 'metric_only_len' variable to 'struct perf_stat_config', so that it can be passed around and used outside the 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-29-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 10 +++++----- tools/perf/util/stat.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 1276596840c9..e96cef526ef0 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -176,7 +176,6 @@ static int print_mixed_hw_group_error; static u64 *walltime_run; static bool ru_display = false; static struct rusage ru_data; -static unsigned int metric_only_len = METRIC_ONLY_LEN; struct perf_stat { bool record; @@ -200,6 +199,7 @@ static struct perf_stat_config stat_config = { .scale = true, .unit_width = 4, /* strlen("unit") */ .run_count = 1, + .metric_only_len = METRIC_ONLY_LEN, }; static bool is_duration_time(struct perf_evsel *evsel) @@ -854,14 +854,14 @@ static const char *fixunit(char *buf, struct perf_evsel *evsel, return unit; } -static void print_metric_only(struct perf_stat_config *config __maybe_unused, +static void print_metric_only(struct perf_stat_config *config, void *ctx, const char *color, const char *fmt, const char *unit, double val) { struct outstate *os = ctx; FILE *out = os->fh; char buf[1024], str[1024]; - unsigned mlen = metric_only_len; + unsigned mlen = config->metric_only_len; if (!valid_only_metric(unit)) return; @@ -902,7 +902,7 @@ static void new_line_metric(struct perf_stat_config *config __maybe_unused, { } -static void print_metric_header(struct perf_stat_config *config __maybe_unused, +static void print_metric_header(struct perf_stat_config *config, void *ctx, const char *color __maybe_unused, const char *fmt __maybe_unused, const char *unit, double val __maybe_unused) @@ -916,7 +916,7 @@ static void print_metric_header(struct perf_stat_config *config __maybe_unused, if (config->csv_output) fprintf(os->fh, "%s%s", unit, config->csv_sep); else - fprintf(os->fh, "%*s ", metric_only_len, unit); + fprintf(os->fh, "%*s ", config->metric_only_len, unit); } static int first_shadow_cpu(struct perf_evsel *evsel, int id) diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 351a36f5f5b0..e70e6d93ee1b 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -99,6 +99,7 @@ struct perf_stat_config { unsigned int timeout; unsigned int initial_delay; unsigned int unit_width; + unsigned int metric_only_len; int times; int run_count; struct runtime_stat *stats; From ae2d7da554f0dda837b6639d247665f6df90e41f Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:38 +0200 Subject: [PATCH 054/155] perf stat: Pass 'struct perf_stat_config' to first_shadow_cpu() Pass a 'struct perf_stat_config' arg to first_shadow_cpu(), so that the function does not depend on the 'perf stat' command object local 'stat_config' variable and can then be moved out. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-30-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index e96cef526ef0..f5ac6545af34 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -919,17 +919,18 @@ static void print_metric_header(struct perf_stat_config *config, fprintf(os->fh, "%*s ", config->metric_only_len, unit); } -static int first_shadow_cpu(struct perf_evsel *evsel, int id) +static int first_shadow_cpu(struct perf_stat_config *config, + struct perf_evsel *evsel, int id) { int i; if (!aggr_get_id) return 0; - if (stat_config.aggr_mode == AGGR_NONE) + if (config->aggr_mode == AGGR_NONE) return id; - if (stat_config.aggr_mode == AGGR_GLOBAL) + if (config->aggr_mode == AGGR_GLOBAL) return 0; for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) { @@ -1090,7 +1091,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, } perf_stat__print_shadow_stats(config, counter, uval, - first_shadow_cpu(counter, id), + first_shadow_cpu(config, counter, id), &out, &metric_events, st); if (!config->csv_output && !config->metric_only) { print_noise(config, counter, noise); @@ -1098,7 +1099,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, } } -static void aggr_update_shadow(void) +static void aggr_update_shadow(struct perf_stat_config *config) { int cpu, s2, id, s; u64 val; @@ -1115,7 +1116,7 @@ static void aggr_update_shadow(void) val += perf_counts(counter->counts, cpu, 0)->val; } perf_stat__update_shadow_stats(counter, val, - first_shadow_cpu(counter, id), + first_shadow_cpu(config, counter, id), &rt_stat); } } @@ -1237,7 +1238,7 @@ static void print_aggr(struct perf_stat_config *config, if (!(aggr_map || aggr_get_id)) return; - aggr_update_shadow(); + aggr_update_shadow(config); /* * With metric_only everything is on a single line. From 77e0faf8552c9329d58a4de460928e03252647c6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:39 +0200 Subject: [PATCH 055/155] perf stat: Pass 'evlist' to aggr_update_shadow() Pass a 'evlist' argument to aggr_update_shadow(), to get rid of the global 'evsel_list' variable dependency. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-31-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index f5ac6545af34..2711d8f6e4b8 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1099,7 +1099,8 @@ static void printout(struct perf_stat_config *config, int id, int nr, } } -static void aggr_update_shadow(struct perf_stat_config *config) +static void aggr_update_shadow(struct perf_stat_config *config, + struct perf_evlist *evlist) { int cpu, s2, id, s; u64 val; @@ -1107,7 +1108,7 @@ static void aggr_update_shadow(struct perf_stat_config *config) for (s = 0; s < aggr_map->nr; s++) { id = aggr_map->map[s]; - evlist__for_each_entry(evsel_list, counter) { + evlist__for_each_entry(evlist, counter) { val = 0; for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { s2 = aggr_get_id(evsel_list->cpus, cpu); @@ -1238,7 +1239,7 @@ static void print_aggr(struct perf_stat_config *config, if (!(aggr_map || aggr_get_id)) return; - aggr_update_shadow(config); + aggr_update_shadow(config, evlist); /* * With metric_only everything is on a single line. From 26893a6018f88779c0aded934e99e0ebb6859a58 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:40 +0200 Subject: [PATCH 056/155] perf stat: Add 'walltime_nsecs_stats' pointer to 'struct perf_stat_config' Add 'walltime_nsecs_stats' pointer to 'struct perf_stat_config', so that it can be passed around and used outside the 'perf stat' command. It's initialized to point to stat's walltime_nsecs_stats value. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-32-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 15 ++++++++------- tools/perf/util/stat.h | 1 + 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 2711d8f6e4b8..381549a989b4 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -195,11 +195,12 @@ static struct perf_stat perf_stat; static volatile int done = 0; static struct perf_stat_config stat_config = { - .aggr_mode = AGGR_GLOBAL, - .scale = true, - .unit_width = 4, /* strlen("unit") */ - .run_count = 1, - .metric_only_len = METRIC_ONLY_LEN, + .aggr_mode = AGGR_GLOBAL, + .scale = true, + .unit_width = 4, /* strlen("unit") */ + .run_count = 1, + .metric_only_len = METRIC_ONLY_LEN, + .walltime_nsecs_stats = &walltime_nsecs_stats, }; static bool is_duration_time(struct perf_evsel *evsel) @@ -1671,7 +1672,7 @@ static double timeval2double(struct timeval *t) static void print_footer(struct perf_stat_config *config) { - double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC; + double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC; FILE *output = config->output; int n; @@ -1690,7 +1691,7 @@ static void print_footer(struct perf_stat_config *config) fprintf(output, " %17.9f seconds sys\n", ru_stime); } } else { - double sd = stddev_stats(&walltime_nsecs_stats) / NSEC_PER_SEC; + double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC; /* * Display at most 2 more significant * digits than the stddev inaccuracy. diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index e70e6d93ee1b..35550e3efd81 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -105,6 +105,7 @@ struct perf_stat_config { struct runtime_stat *stats; int stats_num; const char *csv_sep; + struct stats *walltime_nsecs_stats; }; void update_stats(struct stats *stats, u64 val); From aea0dca1629c72128cf7174d1d3f3807f7297005 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:41 +0200 Subject: [PATCH 057/155] perf stat: Move 'null_run' to 'struct perf_stat_config' Move the static 'null_run' variable to 'struct perf_stat_config', so that it can be passed around and used outside the 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-33-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 7 +++---- tools/perf/util/stat.h | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 381549a989b4..844c755564e3 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -148,7 +148,6 @@ typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu); #define METRIC_ONLY_LEN 20 static volatile pid_t child_pid = -1; -static bool null_run = false; static int detailed_run = 0; static bool transaction_run; static bool topdown_run = false; @@ -1676,7 +1675,7 @@ static void print_footer(struct perf_stat_config *config) FILE *output = config->output; int n; - if (!null_run) + if (!config->null_run) fprintf(output, "\n"); if (config->run_count == 1) { @@ -1894,7 +1893,7 @@ static const struct option stat_options[] = { "repeat command and print average + stddev (max: 100, forever: 0)"), OPT_BOOLEAN(0, "table", &walltime_run_table, "display details about each run (only with -r option)"), - OPT_BOOLEAN('n', "null", &null_run, + OPT_BOOLEAN('n', "null", &stat_config.null_run, "null run - dont start any counters"), OPT_INCR('d', "detailed", &detailed_run, "detailed run - start a lot of events"), @@ -2309,7 +2308,7 @@ static int add_default_attributes(void) struct parse_events_error errinfo; /* Set attrs if no event is selected and !null_run: */ - if (null_run) + if (stat_config.null_run) return 0; if (transaction_run) { diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 35550e3efd81..c198926c0e27 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -94,6 +94,7 @@ struct perf_stat_config { bool csv_output; bool interval_clear; bool metric_only; + bool null_run; FILE *output; unsigned int interval; unsigned int timeout; From 31084123c1962dd4235655c1839a50c9cf6c709b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:42 +0200 Subject: [PATCH 058/155] perf stat: Move 'print_free_counters_hint' to 'struct perf_stat_config' Move the 'print_free_counters_hint' variable to 'struct perf_stat_config', so that it can be passed around and used outside the 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-34-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 5 ++--- tools/perf/util/stat.h | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 844c755564e3..8748bb5e5403 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -170,7 +170,6 @@ static bool append_file; static bool interval_count; static const char *output_name; static int output_fd; -static int print_free_counters_hint; static int print_mixed_hw_group_error; static u64 *walltime_run; static bool ru_display = false; @@ -1051,7 +1050,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, config->csv_sep); if (counter->supported) { - print_free_counters_hint = 1; + config->print_free_counters_hint = 1; if (is_mixed_hw_group(counter)) print_mixed_hw_group_error = 1; } @@ -1707,7 +1706,7 @@ static void print_footer(struct perf_stat_config *config) } fprintf(output, "\n\n"); - if (print_free_counters_hint && + if (config->print_free_counters_hint && sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 && n > 0) fprintf(output, diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index c198926c0e27..8cad17363e90 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -103,6 +103,7 @@ struct perf_stat_config { unsigned int metric_only_len; int times; int run_count; + int print_free_counters_hint; struct runtime_stat *stats; int stats_num; const char *csv_sep; From 3b3cd9a41c2b5d97309099ba6eae69b2d3177226 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:43 +0200 Subject: [PATCH 059/155] perf stat: Move 'print_mixed_hw_group_error' to 'struct perf_stat_config' Move the 'print_mixed_hw_group_error' global variable to 'struct perf_stat_config', so that it can be passed around and used outside the 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-35-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 5 ++--- tools/perf/util/stat.h | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 8748bb5e5403..f61c2dc8c7e8 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -170,7 +170,6 @@ static bool append_file; static bool interval_count; static const char *output_name; static int output_fd; -static int print_mixed_hw_group_error; static u64 *walltime_run; static bool ru_display = false; static struct rusage ru_data; @@ -1052,7 +1051,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, if (counter->supported) { config->print_free_counters_hint = 1; if (is_mixed_hw_group(counter)) - print_mixed_hw_group_error = 1; + config->print_mixed_hw_group_error = 1; } fprintf(config->output, "%-*s%s", @@ -1715,7 +1714,7 @@ static void print_footer(struct perf_stat_config *config) " perf stat ...\n" " echo 1 > /proc/sys/kernel/nmi_watchdog\n"); - if (print_mixed_hw_group_error) + if (config->print_mixed_hw_group_error) fprintf(output, "The events in group usually have to be from " "the same PMU. Try reorganizing the group.\n"); diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 8cad17363e90..6fb4dac26ccc 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -104,6 +104,7 @@ struct perf_stat_config { int times; int run_count; int print_free_counters_hint; + int print_mixed_hw_group_error; struct runtime_stat *stats; int stats_num; const char *csv_sep; From 8897a8916efb29fa8bbe9e5f6e5d56362aedf64e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:44 +0200 Subject: [PATCH 060/155] perf stat: Move ru_* data to 'struct perf_stat_config' Move the 'ru_*' global variables to 'struct perf_stat_config', so that it can be passed around and used outside the 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-36-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 12 +++++------- tools/perf/util/stat.h | 6 ++++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index f61c2dc8c7e8..942ebfd8ef2e 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -171,8 +171,6 @@ static bool interval_count; static const char *output_name; static int output_fd; static u64 *walltime_run; -static bool ru_display = false; -static struct rusage ru_data; struct perf_stat { bool record; @@ -583,7 +581,7 @@ try_again: break; } } - wait4(child_pid, &status, 0, &ru_data); + wait4(child_pid, &status, 0, &stat_config.ru_data); if (workload_exec_errno) { const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); @@ -1679,9 +1677,9 @@ static void print_footer(struct perf_stat_config *config) if (config->run_count == 1) { fprintf(output, " %17.9f seconds time elapsed", avg); - if (ru_display) { - double ru_utime = timeval2double(&ru_data.ru_utime); - double ru_stime = timeval2double(&ru_data.ru_stime); + if (config->ru_display) { + double ru_utime = timeval2double(&config->ru_data.ru_utime); + double ru_stime = timeval2double(&config->ru_data.ru_stime); fprintf(output, "\n\n"); fprintf(output, " %17.9f seconds user\n", ru_utime); @@ -2855,7 +2853,7 @@ int cmd_stat(int argc, const char **argv) * run and when there's specified tracee. */ if ((stat_config.run_count == 1) && target__none(&target)) - ru_display = true; + stat_config.ru_display = true; if (stat_config.run_count < 0) { pr_err("Run count must be a positive number\n"); diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 6fb4dac26ccc..1fd0b7e196c6 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -4,6 +4,10 @@ #include #include +#include +#include +#include +#include #include "xyarray.h" #include "rblist.h" #include "perf.h" @@ -95,6 +99,7 @@ struct perf_stat_config { bool interval_clear; bool metric_only; bool null_run; + bool ru_display; FILE *output; unsigned int interval; unsigned int timeout; @@ -109,6 +114,7 @@ struct perf_stat_config { int stats_num; const char *csv_sep; struct stats *walltime_nsecs_stats; + struct rusage ru_data; }; void update_stats(struct stats *stats, u64 val); From 6f6b6594b5f380b0a972b66b275caa6c54bb1fea Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:45 +0200 Subject: [PATCH 061/155] perf stat: Move *_aggr_* data to 'struct perf_stat_config' Move the *_aggr_* global variables to 'struct perf_stat_config', so that it can be passed around and used outside 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-37-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 112 ++++++++++++++++++++------------------ tools/perf/util/stat.h | 6 ++ 2 files changed, 64 insertions(+), 54 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 942ebfd8ef2e..2f606f76b66a 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -143,8 +143,6 @@ static struct target target = { .uid = UINT_MAX, }; -typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu); - #define METRIC_ONLY_LEN 20 static volatile pid_t child_pid = -1; @@ -164,8 +162,6 @@ static bool force_metric_only = false; static bool no_merge = false; static bool walltime_run_table = false; static struct timespec ref_time; -static struct cpu_map *aggr_map; -static aggr_get_id_t aggr_get_id; static bool append_file; static bool interval_count; static const char *output_name; @@ -920,7 +916,7 @@ static int first_shadow_cpu(struct perf_stat_config *config, { int i; - if (!aggr_get_id) + if (!config->aggr_get_id) return 0; if (config->aggr_mode == AGGR_NONE) @@ -932,7 +928,7 @@ static int first_shadow_cpu(struct perf_stat_config *config, for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) { int cpu2 = perf_evsel__cpus(evsel)->map[i]; - if (aggr_get_id(evsel_list->cpus, cpu2) == id) + if (config->aggr_get_id(config, evsel_list->cpus, cpu2) == id) return cpu2; } return 0; @@ -1102,12 +1098,12 @@ static void aggr_update_shadow(struct perf_stat_config *config, u64 val; struct perf_evsel *counter; - for (s = 0; s < aggr_map->nr; s++) { - id = aggr_map->map[s]; + for (s = 0; s < config->aggr_map->nr; s++) { + id = config->aggr_map->map[s]; evlist__for_each_entry(evlist, counter) { val = 0; for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { - s2 = aggr_get_id(evsel_list->cpus, cpu); + s2 = config->aggr_get_id(config, evsel_list->cpus, cpu); if (s2 != id) continue; val += perf_counts(counter->counts, cpu, 0)->val; @@ -1147,8 +1143,8 @@ static void uniquify_event_name(struct perf_evsel *counter) counter->uniquified_name = true; } -static void collect_all_aliases(struct perf_evsel *counter, - void (*cb)(struct perf_evsel *counter, void *data, +static void collect_all_aliases(struct perf_stat_config *config, struct perf_evsel *counter, + void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data, bool first), void *data) { @@ -1164,22 +1160,22 @@ static void collect_all_aliases(struct perf_evsel *counter, perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter)) break; alias->merged_stat = true; - cb(alias, data, false); + cb(config, alias, data, false); } } -static bool collect_data(struct perf_evsel *counter, - void (*cb)(struct perf_evsel *counter, void *data, +static bool collect_data(struct perf_stat_config *config, struct perf_evsel *counter, + void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data, bool first), void *data) { if (counter->merged_stat) return false; - cb(counter, data, true); + cb(config, counter, data, true); if (no_merge) uniquify_event_name(counter); else if (counter->auto_merge_stats) - collect_all_aliases(counter, cb, data); + collect_all_aliases(config, counter, cb, data); return true; } @@ -1190,7 +1186,8 @@ struct aggr_data { int cpu; }; -static void aggr_cb(struct perf_evsel *counter, void *data, bool first) +static void aggr_cb(struct perf_stat_config *config, + struct perf_evsel *counter, void *data, bool first) { struct aggr_data *ad = data; int cpu, s2; @@ -1198,7 +1195,7 @@ static void aggr_cb(struct perf_evsel *counter, void *data, bool first) for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { struct perf_counts_values *counts; - s2 = aggr_get_id(perf_evsel__cpus(counter), cpu); + s2 = config->aggr_get_id(config, perf_evsel__cpus(counter), cpu); if (s2 != ad->id) continue; if (first) @@ -1232,7 +1229,7 @@ static void print_aggr(struct perf_stat_config *config, u64 ena, run, val; bool first; - if (!(aggr_map || aggr_get_id)) + if (!(config->aggr_map || config->aggr_get_id)) return; aggr_update_shadow(config, evlist); @@ -1241,12 +1238,12 @@ static void print_aggr(struct perf_stat_config *config, * With metric_only everything is on a single line. * Without each counter has its own line. */ - for (s = 0; s < aggr_map->nr; s++) { + for (s = 0; s < config->aggr_map->nr; s++) { struct aggr_data ad; if (prefix && metric_only) fprintf(output, "%s", prefix); - ad.id = id = aggr_map->map[s]; + ad.id = id = config->aggr_map->map[s]; first = true; evlist__for_each_entry(evlist, counter) { if (is_duration_time(counter)) @@ -1254,7 +1251,7 @@ static void print_aggr(struct perf_stat_config *config, ad.val = ad.ena = ad.run = 0; ad.nr = 0; - if (!collect_data(counter, aggr_cb, &ad)) + if (!collect_data(config, counter, aggr_cb, &ad)) continue; nr = ad.nr; ena = ad.ena; @@ -1370,7 +1367,8 @@ struct caggr_data { double avg, avg_enabled, avg_running; }; -static void counter_aggr_cb(struct perf_evsel *counter, void *data, +static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused, + struct perf_evsel *counter, void *data, bool first __maybe_unused) { struct caggr_data *cd = data; @@ -1393,7 +1391,7 @@ static void print_counter_aggr(struct perf_stat_config *config, double uval; struct caggr_data cd = { .avg = 0.0 }; - if (!collect_data(counter, counter_aggr_cb, &cd)) + if (!collect_data(config, counter, counter_aggr_cb, &cd)) return; if (prefix && !metric_only) @@ -1406,7 +1404,8 @@ static void print_counter_aggr(struct perf_stat_config *config, fprintf(output, "\n"); } -static void counter_cb(struct perf_evsel *counter, void *data, +static void counter_cb(struct perf_stat_config *config __maybe_unused, + struct perf_evsel *counter, void *data, bool first __maybe_unused) { struct aggr_data *ad = data; @@ -1431,7 +1430,7 @@ static void print_counter(struct perf_stat_config *config, for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { struct aggr_data ad = { .cpu = cpu }; - if (!collect_data(counter, counter_cb, &ad)) + if (!collect_data(config, counter, counter_cb, &ad)) return; val = ad.val; ena = ad.ena; @@ -1944,12 +1943,14 @@ static const struct option stat_options[] = { OPT_END() }; -static int perf_stat__get_socket(struct cpu_map *map, int cpu) +static int perf_stat__get_socket(struct perf_stat_config *config __maybe_unused, + struct cpu_map *map, int cpu) { return cpu_map__get_socket(map, cpu, NULL); } -static int perf_stat__get_core(struct cpu_map *map, int cpu) +static int perf_stat__get_core(struct perf_stat_config *config __maybe_unused, + struct cpu_map *map, int cpu) { return cpu_map__get_core(map, cpu, NULL); } @@ -1966,9 +1967,8 @@ static int cpu_map__get_max(struct cpu_map *map) return max; } -static struct cpu_map *cpus_aggr_map; - -static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int idx) +static int perf_stat__get_aggr(struct perf_stat_config *config, + aggr_get_id_t get_id, struct cpu_map *map, int idx) { int cpu; @@ -1977,20 +1977,22 @@ static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int id cpu = map->map[idx]; - if (cpus_aggr_map->map[cpu] == -1) - cpus_aggr_map->map[cpu] = get_id(map, idx); + if (config->cpus_aggr_map->map[cpu] == -1) + config->cpus_aggr_map->map[cpu] = get_id(config, map, idx); - return cpus_aggr_map->map[cpu]; + return config->cpus_aggr_map->map[cpu]; } -static int perf_stat__get_socket_cached(struct cpu_map *map, int idx) +static int perf_stat__get_socket_cached(struct perf_stat_config *config, + struct cpu_map *map, int idx) { - return perf_stat__get_aggr(perf_stat__get_socket, map, idx); + return perf_stat__get_aggr(config, perf_stat__get_socket, map, idx); } -static int perf_stat__get_core_cached(struct cpu_map *map, int idx) +static int perf_stat__get_core_cached(struct perf_stat_config *config, + struct cpu_map *map, int idx) { - return perf_stat__get_aggr(perf_stat__get_core, map, idx); + return perf_stat__get_aggr(config, perf_stat__get_core, map, idx); } static int perf_stat_init_aggr_mode(void) @@ -1999,18 +2001,18 @@ static int perf_stat_init_aggr_mode(void) switch (stat_config.aggr_mode) { case AGGR_SOCKET: - if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) { + if (cpu_map__build_socket_map(evsel_list->cpus, &stat_config.aggr_map)) { perror("cannot build socket map"); return -1; } - aggr_get_id = perf_stat__get_socket_cached; + stat_config.aggr_get_id = perf_stat__get_socket_cached; break; case AGGR_CORE: - if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) { + if (cpu_map__build_core_map(evsel_list->cpus, &stat_config.aggr_map)) { perror("cannot build core map"); return -1; } - aggr_get_id = perf_stat__get_core_cached; + stat_config.aggr_get_id = perf_stat__get_core_cached; break; case AGGR_NONE: case AGGR_GLOBAL: @@ -2026,16 +2028,16 @@ static int perf_stat_init_aggr_mode(void) * the aggregation translate cpumap. */ nr = cpu_map__get_max(evsel_list->cpus); - cpus_aggr_map = cpu_map__empty_new(nr + 1); - return cpus_aggr_map ? 0 : -ENOMEM; + stat_config.cpus_aggr_map = cpu_map__empty_new(nr + 1); + return stat_config.cpus_aggr_map ? 0 : -ENOMEM; } static void perf_stat__exit_aggr_mode(void) { - cpu_map__put(aggr_map); - cpu_map__put(cpus_aggr_map); - aggr_map = NULL; - cpus_aggr_map = NULL; + cpu_map__put(stat_config.aggr_map); + cpu_map__put(stat_config.cpus_aggr_map); + stat_config.aggr_map = NULL; + stat_config.cpus_aggr_map = NULL; } static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, int idx) @@ -2093,12 +2095,14 @@ static int perf_env__build_core_map(struct perf_env *env, struct cpu_map *cpus, return cpu_map__build_map(cpus, corep, perf_env__get_core, env); } -static int perf_stat__get_socket_file(struct cpu_map *map, int idx) +static int perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused, + struct cpu_map *map, int idx) { return perf_env__get_socket(map, idx, &perf_stat.session->header.env); } -static int perf_stat__get_core_file(struct cpu_map *map, int idx) +static int perf_stat__get_core_file(struct perf_stat_config *config __maybe_unused, + struct cpu_map *map, int idx) { return perf_env__get_core(map, idx, &perf_stat.session->header.env); } @@ -2109,18 +2113,18 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st) switch (stat_config.aggr_mode) { case AGGR_SOCKET: - if (perf_env__build_socket_map(env, evsel_list->cpus, &aggr_map)) { + if (perf_env__build_socket_map(env, evsel_list->cpus, &stat_config.aggr_map)) { perror("cannot build socket map"); return -1; } - aggr_get_id = perf_stat__get_socket_file; + stat_config.aggr_get_id = perf_stat__get_socket_file; break; case AGGR_CORE: - if (perf_env__build_core_map(env, evsel_list->cpus, &aggr_map)) { + if (perf_env__build_core_map(env, evsel_list->cpus, &stat_config.aggr_map)) { perror("cannot build core map"); return -1; } - aggr_get_id = perf_stat__get_core_file; + stat_config.aggr_get_id = perf_stat__get_core_file; break; case AGGR_NONE: case AGGR_GLOBAL: diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 1fd0b7e196c6..be202b066e62 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -90,6 +90,9 @@ struct runtime_stat { struct rblist value_list; }; +typedef int (*aggr_get_id_t)(struct perf_stat_config *config, + struct cpu_map *m, int cpu); + struct perf_stat_config { enum aggr_mode aggr_mode; bool scale; @@ -115,6 +118,9 @@ struct perf_stat_config { const char *csv_sep; struct stats *walltime_nsecs_stats; struct rusage ru_data; + struct cpu_map *aggr_map; + aggr_get_id_t aggr_get_id; + struct cpu_map *cpus_aggr_map; }; void update_stats(struct stats *stats, u64 val); From a138af663500a07742bb27793302625135a0f6c4 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:46 +0200 Subject: [PATCH 062/155] perf stat: Do not use the global 'evsel_list' in print functions Get rid of the the 'evsel_list' global variable dependency, here we can use the 'evlist' pointer from the evsel. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-38-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 2f606f76b66a..445673f688de 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -914,6 +914,7 @@ static void print_metric_header(struct perf_stat_config *config, static int first_shadow_cpu(struct perf_stat_config *config, struct perf_evsel *evsel, int id) { + struct perf_evlist *evlist = evsel->evlist; int i; if (!config->aggr_get_id) @@ -928,7 +929,7 @@ static int first_shadow_cpu(struct perf_stat_config *config, for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) { int cpu2 = perf_evsel__cpus(evsel)->map[i]; - if (config->aggr_get_id(config, evsel_list->cpus, cpu2) == id) + if (config->aggr_get_id(config, evlist->cpus, cpu2) == id) return cpu2; } return 0; @@ -1103,7 +1104,7 @@ static void aggr_update_shadow(struct perf_stat_config *config, evlist__for_each_entry(evlist, counter) { val = 0; for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { - s2 = config->aggr_get_id(config, evsel_list->cpus, cpu); + s2 = config->aggr_get_id(config, evlist->cpus, cpu); if (s2 != id) continue; val += perf_counts(counter->counts, cpu, 0)->val; From 34ff0866d46ae206de884f54e7235f57096e5588 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:47 +0200 Subject: [PATCH 063/155] perf stat: Move 'big_num' data to 'struct perf_stat_config' Move the static variable 'big_num' to 'struct perf_stat_config', so that it can be passed around and used outside 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-39-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 8 ++++---- tools/perf/util/stat.h | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 445673f688de..8ca85017a973 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -151,7 +151,6 @@ static bool transaction_run; static bool topdown_run = false; static bool smi_cost = false; static bool smi_reset = false; -static bool big_num = true; static int big_num_opt = -1; static bool group = false; static const char *pre_cmd = NULL; @@ -192,6 +191,7 @@ static struct perf_stat_config stat_config = { .run_count = 1, .metric_only_len = METRIC_ONLY_LEN, .walltime_nsecs_stats = &walltime_nsecs_stats, + .big_num = true, }; static bool is_duration_time(struct perf_evsel *evsel) @@ -945,7 +945,7 @@ static void abs_printout(struct perf_stat_config *config, if (config->csv_output) { fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s"; } else { - if (big_num) + if (config->big_num) fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s"; else fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s"; @@ -2847,9 +2847,9 @@ int cmd_stat(int argc, const char **argv) parse_options_usage(NULL, stat_options, "x", 1); goto out; } else /* Nope, so disable big number formatting */ - big_num = false; + stat_config.big_num = false; } else if (big_num_opt == 0) /* User passed --no-big-num */ - big_num = false; + stat_config.big_num = false; setup_system_wide(argc); diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index be202b066e62..843672214cca 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -103,6 +103,7 @@ struct perf_stat_config { bool metric_only; bool null_run; bool ru_display; + bool big_num; FILE *output; unsigned int interval; unsigned int timeout; From fdee335b00b0807e8d65b8e3d81214556f07bed3 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:48 +0200 Subject: [PATCH 064/155] perf stat: Move 'no_merge' data to 'struct perf_stat_config' Move the static variable 'no_merge' to 'struct perf_stat_config', so that it can be passed around and used outside 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-40-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 5 ++--- tools/perf/util/stat.h | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 8ca85017a973..c4df076f1e54 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -158,7 +158,6 @@ static const char *post_cmd = NULL; static bool sync_run = false; static bool forever = false; static bool force_metric_only = false; -static bool no_merge = false; static bool walltime_run_table = false; static struct timespec ref_time; static bool append_file; @@ -1173,7 +1172,7 @@ static bool collect_data(struct perf_stat_config *config, struct perf_evsel *cou if (counter->merged_stat) return false; cb(config, counter, data, true); - if (no_merge) + if (config->no_merge) uniquify_event_name(counter); else if (counter->auto_merge_stats) collect_all_aliases(config, counter, cb, data); @@ -1902,7 +1901,7 @@ static const struct option stat_options[] = { "list of cpus to monitor in system-wide"), OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode, "disable CPU count aggregation", AGGR_NONE), - OPT_BOOLEAN(0, "no-merge", &no_merge, "Do not merge identical named events"), + OPT_BOOLEAN(0, "no-merge", &stat_config.no_merge, "Do not merge identical named events"), OPT_STRING('x', "field-separator", &stat_config.csv_sep, "separator", "print counts with custom separator"), OPT_CALLBACK('G', "cgroup", &evsel_list, "name", diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 843672214cca..0758107fe56f 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -104,6 +104,7 @@ struct perf_stat_config { bool null_run; bool ru_display; bool big_num; + bool no_merge; FILE *output; unsigned int interval; unsigned int timeout; From be54d59325314be9d4d53852cbfbeeaebc3b9239 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:49 +0200 Subject: [PATCH 065/155] perf stat: Propagate 'struct target' arg to sort_aggr_thread() Propagate the 'struct target' arg to sort_aggr_thread() so that the function does not depend on the 'perf stat' command object local variable 'target' and can be moved out. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-41-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index c4df076f1e54..486b0cf7818d 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1284,7 +1284,8 @@ static int cmp_val(const void *a, const void *b) static struct perf_aggr_thread_value *sort_aggr_thread( struct perf_evsel *counter, int nthreads, int ncpus, - int *ret) + int *ret, + struct target *_target) { int cpu, thread, i = 0; double uval; @@ -1309,7 +1310,7 @@ static struct perf_aggr_thread_value *sort_aggr_thread( * Skip value 0 when enabling --per-thread globally, * otherwise too many 0 output. */ - if (uval == 0.0 && target__has_per_thread(&target)) + if (uval == 0.0 && target__has_per_thread(_target)) continue; buf[i].counter = counter; @@ -1330,6 +1331,7 @@ static struct perf_aggr_thread_value *sort_aggr_thread( } static void print_aggr_thread(struct perf_stat_config *config, + struct target *_target, struct perf_evsel *counter, char *prefix) { FILE *output = config->output; @@ -1338,7 +1340,7 @@ static void print_aggr_thread(struct perf_stat_config *config, int thread, sorted_threads, id; struct perf_aggr_thread_value *buf; - buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads); + buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads, _target); if (!buf) { perror("cannot sort aggr thread"); return; @@ -1754,7 +1756,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, evlist__for_each_entry(evlist, counter) { if (is_duration_time(counter)) continue; - print_aggr_thread(config, counter, prefix); + print_aggr_thread(config, _target, counter, prefix); } break; case AGGR_GLOBAL: From 54ac0b1bd25cbdeda226b32a0459e09de46157b3 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:50 +0200 Subject: [PATCH 066/155] perf stat: Move 'walltime_*' data to 'struct perf_stat_config' Move the static variables 'walltime_*' to 'struct perf_stat_config', so that it can be passed around and used outside 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-42-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 22 ++++++++++------------ tools/perf/util/stat.h | 2 ++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 486b0cf7818d..8a4979748cbb 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -158,13 +158,11 @@ static const char *post_cmd = NULL; static bool sync_run = false; static bool forever = false; static bool force_metric_only = false; -static bool walltime_run_table = false; static struct timespec ref_time; static bool append_file; static bool interval_count; static const char *output_name; static int output_fd; -static u64 *walltime_run; struct perf_stat { bool record; @@ -604,8 +602,8 @@ try_again: t1 = rdclock(); - if (walltime_run_table) - walltime_run[run_idx] = t1 - t0; + if (stat_config.walltime_run_table) + stat_config.walltime_run[run_idx] = t1 - t0; update_stats(&walltime_nsecs_stats, t1 - t0); @@ -1646,7 +1644,7 @@ static void print_table(struct perf_stat_config *config, fprintf(output, "%*s# Table of individual measurements:\n", indent, ""); for (idx = 0; idx < config->run_count; idx++) { - double run = (double) walltime_run[idx] / NSEC_PER_SEC; + double run = (double) config->walltime_run[idx] / NSEC_PER_SEC; int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5); fprintf(output, " %17.*f (%+.*f) ", @@ -1694,7 +1692,7 @@ static void print_footer(struct perf_stat_config *config) */ int precision = get_precision(sd) + 2; - if (walltime_run_table) + if (config->walltime_run_table) print_table(config, output, precision, avg); fprintf(output, " %17.*f +- %.*f seconds time elapsed", @@ -1888,7 +1886,7 @@ static const struct option stat_options[] = { "be more verbose (show counter open errors, etc)"), OPT_INTEGER('r', "repeat", &stat_config.run_count, "repeat command and print average + stddev (max: 100, forever: 0)"), - OPT_BOOLEAN(0, "table", &walltime_run_table, + OPT_BOOLEAN(0, "table", &stat_config.walltime_run_table, "display details about each run (only with -r option)"), OPT_BOOLEAN('n', "null", &stat_config.null_run, "null run - dont start any counters"), @@ -2802,7 +2800,7 @@ int cmd_stat(int argc, const char **argv) goto out; } - if (walltime_run_table && stat_config.run_count <= 1) { + if (stat_config.walltime_run_table && stat_config.run_count <= 1) { fprintf(stderr, "--table is only supported with -r\n"); parse_options_usage(stat_usage, stat_options, "r", 1); parse_options_usage(NULL, stat_options, "table", 0); @@ -2870,9 +2868,9 @@ int cmd_stat(int argc, const char **argv) stat_config.run_count = 1; } - if (walltime_run_table) { - walltime_run = zalloc(stat_config.run_count * sizeof(walltime_run[0])); - if (!walltime_run) { + if (stat_config.walltime_run_table) { + stat_config.walltime_run = zalloc(stat_config.run_count * sizeof(stat_config.walltime_run[0])); + if (!stat_config.walltime_run) { pr_err("failed to setup -r option"); goto out; } @@ -3052,7 +3050,7 @@ int cmd_stat(int argc, const char **argv) perf_stat__exit_aggr_mode(); perf_evlist__free_stats(evsel_list); out: - free(walltime_run); + free(stat_config.walltime_run); if (smi_cost && smi_reset) sysfs__write_int(FREEZE_ON_SMI_PATH, 0); diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 0758107fe56f..5193cbf6e4c6 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -105,6 +105,7 @@ struct perf_stat_config { bool ru_display; bool big_num; bool no_merge; + bool walltime_run_table; FILE *output; unsigned int interval; unsigned int timeout; @@ -123,6 +124,7 @@ struct perf_stat_config { struct cpu_map *aggr_map; aggr_get_id_t aggr_get_id; struct cpu_map *cpus_aggr_map; + u64 *walltime_run; }; void update_stats(struct stats *stats, u64 val); From d0192fdba09a8901db133fe5a1fcd22d40fcf545 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:51 +0200 Subject: [PATCH 067/155] perf stat: Move 'metric_events' to 'struct perf_stat_config' Move the static variable 'metric_events' to 'struct perf_stat_config', so that it can be passed around and used outside 'perf stat' command. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-43-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 10 ++++------ tools/perf/util/stat.h | 1 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 8a4979748cbb..f4ddedc8619b 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -137,8 +137,6 @@ static const char *smi_cost_attrs = { static struct perf_evlist *evsel_list; -static struct rblist metric_events; - static struct target target = { .uid = UINT_MAX, }; @@ -1082,7 +1080,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, perf_stat__print_shadow_stats(config, counter, uval, first_shadow_cpu(config, counter, id), - &out, &metric_events, st); + &out, &config->metric_events, st); if (!config->csv_output && !config->metric_only) { print_noise(config, counter, noise); print_running(config, run, ena); @@ -1533,7 +1531,7 @@ static void print_metric_headers(struct perf_stat_config *config, perf_stat__print_shadow_stats(config, counter, 0, 0, &out, - &metric_events, + &config->metric_events, &rt_stat); } fputc('\n', config->output); @@ -1860,7 +1858,7 @@ static int parse_metric_groups(const struct option *opt, const char *str, int unset __maybe_unused) { - return metricgroup__parse_groups(opt, str, &metric_events); + return metricgroup__parse_groups(opt, str, &stat_config.metric_events); } static const struct option stat_options[] = { @@ -2321,7 +2319,7 @@ static int add_default_attributes(void) struct option opt = { .value = &evsel_list }; return metricgroup__parse_groups(&opt, "transaction", - &metric_events); + &stat_config.metric_events); } if (pmu_have_event("cpu", "cycles-ct") && diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 5193cbf6e4c6..8d3354e21e19 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -125,6 +125,7 @@ struct perf_stat_config { aggr_get_id_t aggr_get_id; struct cpu_map *cpus_aggr_map; u64 *walltime_run; + struct rblist metric_events; }; void update_stats(struct stats *stats, u64 val); From 088519f318be3a41d1afe8d628c4a1eb5a50b4c0 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 30 Aug 2018 08:32:52 +0200 Subject: [PATCH 068/155] perf stat: Move the display functions to stat-display.c Move perf_evlist__print_counters() with all its dependency functions to the stat-display.c object. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180830063252.23729-44-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 1150 ------------------------------- tools/perf/util/Build | 1 + tools/perf/util/stat-display.c | 1166 ++++++++++++++++++++++++++++++++ tools/perf/util/stat.h | 6 + 4 files changed, 1173 insertions(+), 1150 deletions(-) create mode 100644 tools/perf/util/stat-display.c diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index f4ddedc8619b..0b0e3961d511 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -88,8 +88,6 @@ #include "sane_ctype.h" #define DEFAULT_SEPARATOR " " -#define CNTR_NOT_SUPPORTED "" -#define CNTR_NOT_COUNTED "" #define FREEZE_ON_SMI_PATH "devices/cpu/freeze_on_smi" static void print_counters(struct timespec *ts, int argc, const char **argv); @@ -189,11 +187,6 @@ static struct perf_stat_config stat_config = { .big_num = true, }; -static bool is_duration_time(struct perf_evsel *evsel) -{ - return !strcmp(evsel->name, "duration_time"); -} - static inline void diff_timespec(struct timespec *r, struct timespec *a, struct timespec *b) { @@ -643,1149 +636,6 @@ static int run_perf_stat(int argc, const char **argv, int run_idx) return ret; } -static void print_running(struct perf_stat_config *config, - u64 run, u64 ena) -{ - if (config->csv_output) { - fprintf(config->output, "%s%" PRIu64 "%s%.2f", - config->csv_sep, - run, - config->csv_sep, - ena ? 100.0 * run / ena : 100.0); - } else if (run != ena) { - fprintf(config->output, " (%.2f%%)", 100.0 * run / ena); - } -} - -static void print_noise_pct(struct perf_stat_config *config, - double total, double avg) -{ - double pct = rel_stddev_stats(total, avg); - - if (config->csv_output) - fprintf(config->output, "%s%.2f%%", config->csv_sep, pct); - else if (pct) - fprintf(config->output, " ( +-%6.2f%% )", pct); -} - -static void print_noise(struct perf_stat_config *config, - struct perf_evsel *evsel, double avg) -{ - struct perf_stat_evsel *ps; - - if (config->run_count == 1) - return; - - ps = evsel->stats; - print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg); -} - -static void aggr_printout(struct perf_stat_config *config, - struct perf_evsel *evsel, int id, int nr) -{ - switch (config->aggr_mode) { - case AGGR_CORE: - fprintf(config->output, "S%d-C%*d%s%*d%s", - cpu_map__id_to_socket(id), - config->csv_output ? 0 : -8, - cpu_map__id_to_cpu(id), - config->csv_sep, - config->csv_output ? 0 : 4, - nr, - config->csv_sep); - break; - case AGGR_SOCKET: - fprintf(config->output, "S%*d%s%*d%s", - config->csv_output ? 0 : -5, - id, - config->csv_sep, - config->csv_output ? 0 : 4, - nr, - config->csv_sep); - break; - case AGGR_NONE: - fprintf(config->output, "CPU%*d%s", - config->csv_output ? 0 : -4, - perf_evsel__cpus(evsel)->map[id], config->csv_sep); - break; - case AGGR_THREAD: - fprintf(config->output, "%*s-%*d%s", - config->csv_output ? 0 : 16, - thread_map__comm(evsel->threads, id), - config->csv_output ? 0 : -8, - thread_map__pid(evsel->threads, id), - config->csv_sep); - break; - case AGGR_GLOBAL: - case AGGR_UNSET: - default: - break; - } -} - -struct outstate { - FILE *fh; - bool newline; - const char *prefix; - int nfields; - int id, nr; - struct perf_evsel *evsel; -}; - -#define METRIC_LEN 35 - -static void new_line_std(struct perf_stat_config *config __maybe_unused, - void *ctx) -{ - struct outstate *os = ctx; - - os->newline = true; -} - -static void do_new_line_std(struct perf_stat_config *config, - struct outstate *os) -{ - fputc('\n', os->fh); - fputs(os->prefix, os->fh); - aggr_printout(config, os->evsel, os->id, os->nr); - if (config->aggr_mode == AGGR_NONE) - fprintf(os->fh, " "); - fprintf(os->fh, " "); -} - -static void print_metric_std(struct perf_stat_config *config, - void *ctx, const char *color, const char *fmt, - const char *unit, double val) -{ - struct outstate *os = ctx; - FILE *out = os->fh; - int n; - bool newline = os->newline; - - os->newline = false; - - if (unit == NULL || fmt == NULL) { - fprintf(out, "%-*s", METRIC_LEN, ""); - return; - } - - if (newline) - do_new_line_std(config, os); - - n = fprintf(out, " # "); - if (color) - n += color_fprintf(out, color, fmt, val); - else - n += fprintf(out, fmt, val); - fprintf(out, " %-*s", METRIC_LEN - n - 1, unit); -} - -static void new_line_csv(struct perf_stat_config *config, void *ctx) -{ - struct outstate *os = ctx; - int i; - - fputc('\n', os->fh); - if (os->prefix) - fprintf(os->fh, "%s%s", os->prefix, config->csv_sep); - aggr_printout(config, os->evsel, os->id, os->nr); - for (i = 0; i < os->nfields; i++) - fputs(config->csv_sep, os->fh); -} - -static void print_metric_csv(struct perf_stat_config *config __maybe_unused, - void *ctx, - const char *color __maybe_unused, - const char *fmt, const char *unit, double val) -{ - struct outstate *os = ctx; - FILE *out = os->fh; - char buf[64], *vals, *ends; - - if (unit == NULL || fmt == NULL) { - fprintf(out, "%s%s", config->csv_sep, config->csv_sep); - return; - } - snprintf(buf, sizeof(buf), fmt, val); - ends = vals = ltrim(buf); - while (isdigit(*ends) || *ends == '.') - ends++; - *ends = 0; - while (isspace(*unit)) - unit++; - fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, unit); -} - -/* Filter out some columns that don't work well in metrics only mode */ - -static bool valid_only_metric(const char *unit) -{ - if (!unit) - return false; - if (strstr(unit, "/sec") || - strstr(unit, "hz") || - strstr(unit, "Hz") || - strstr(unit, "CPUs utilized")) - return false; - return true; -} - -static const char *fixunit(char *buf, struct perf_evsel *evsel, - const char *unit) -{ - if (!strncmp(unit, "of all", 6)) { - snprintf(buf, 1024, "%s %s", perf_evsel__name(evsel), - unit); - return buf; - } - return unit; -} - -static void print_metric_only(struct perf_stat_config *config, - void *ctx, const char *color, const char *fmt, - const char *unit, double val) -{ - struct outstate *os = ctx; - FILE *out = os->fh; - char buf[1024], str[1024]; - unsigned mlen = config->metric_only_len; - - if (!valid_only_metric(unit)) - return; - unit = fixunit(buf, os->evsel, unit); - if (mlen < strlen(unit)) - mlen = strlen(unit) + 1; - - if (color) - mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1; - - color_snprintf(str, sizeof(str), color ?: "", fmt, val); - fprintf(out, "%*s ", mlen, str); -} - -static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused, - void *ctx, const char *color __maybe_unused, - const char *fmt, - const char *unit, double val) -{ - struct outstate *os = ctx; - FILE *out = os->fh; - char buf[64], *vals, *ends; - char tbuf[1024]; - - if (!valid_only_metric(unit)) - return; - unit = fixunit(tbuf, os->evsel, unit); - snprintf(buf, sizeof buf, fmt, val); - ends = vals = ltrim(buf); - while (isdigit(*ends) || *ends == '.') - ends++; - *ends = 0; - fprintf(out, "%s%s", vals, config->csv_sep); -} - -static void new_line_metric(struct perf_stat_config *config __maybe_unused, - void *ctx __maybe_unused) -{ -} - -static void print_metric_header(struct perf_stat_config *config, - void *ctx, const char *color __maybe_unused, - const char *fmt __maybe_unused, - const char *unit, double val __maybe_unused) -{ - struct outstate *os = ctx; - char tbuf[1024]; - - if (!valid_only_metric(unit)) - return; - unit = fixunit(tbuf, os->evsel, unit); - if (config->csv_output) - fprintf(os->fh, "%s%s", unit, config->csv_sep); - else - fprintf(os->fh, "%*s ", config->metric_only_len, unit); -} - -static int first_shadow_cpu(struct perf_stat_config *config, - struct perf_evsel *evsel, int id) -{ - struct perf_evlist *evlist = evsel->evlist; - int i; - - if (!config->aggr_get_id) - return 0; - - if (config->aggr_mode == AGGR_NONE) - return id; - - if (config->aggr_mode == AGGR_GLOBAL) - return 0; - - for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) { - int cpu2 = perf_evsel__cpus(evsel)->map[i]; - - if (config->aggr_get_id(config, evlist->cpus, cpu2) == id) - return cpu2; - } - return 0; -} - -static void abs_printout(struct perf_stat_config *config, - int id, int nr, struct perf_evsel *evsel, double avg) -{ - FILE *output = config->output; - double sc = evsel->scale; - const char *fmt; - - if (config->csv_output) { - fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s"; - } else { - if (config->big_num) - fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s"; - else - fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s"; - } - - aggr_printout(config, evsel, id, nr); - - fprintf(output, fmt, avg, config->csv_sep); - - if (evsel->unit) - fprintf(output, "%-*s%s", - config->csv_output ? 0 : config->unit_width, - evsel->unit, config->csv_sep); - - fprintf(output, "%-*s", config->csv_output ? 0 : 25, perf_evsel__name(evsel)); - - if (evsel->cgrp) - fprintf(output, "%s%s", config->csv_sep, evsel->cgrp->name); -} - -static bool is_mixed_hw_group(struct perf_evsel *counter) -{ - struct perf_evlist *evlist = counter->evlist; - u32 pmu_type = counter->attr.type; - struct perf_evsel *pos; - - if (counter->nr_members < 2) - return false; - - evlist__for_each_entry(evlist, pos) { - /* software events can be part of any hardware group */ - if (pos->attr.type == PERF_TYPE_SOFTWARE) - continue; - if (pmu_type == PERF_TYPE_SOFTWARE) { - pmu_type = pos->attr.type; - continue; - } - if (pmu_type != pos->attr.type) - return true; - } - - return false; -} - -static void printout(struct perf_stat_config *config, int id, int nr, - struct perf_evsel *counter, double uval, - char *prefix, u64 run, u64 ena, double noise, - struct runtime_stat *st) -{ - struct perf_stat_output_ctx out; - struct outstate os = { - .fh = config->output, - .prefix = prefix ? prefix : "", - .id = id, - .nr = nr, - .evsel = counter, - }; - print_metric_t pm = print_metric_std; - new_line_t nl; - - if (config->metric_only) { - nl = new_line_metric; - if (config->csv_output) - pm = print_metric_only_csv; - else - pm = print_metric_only; - } else - nl = new_line_std; - - if (config->csv_output && !config->metric_only) { - static int aggr_fields[] = { - [AGGR_GLOBAL] = 0, - [AGGR_THREAD] = 1, - [AGGR_NONE] = 1, - [AGGR_SOCKET] = 2, - [AGGR_CORE] = 2, - }; - - pm = print_metric_csv; - nl = new_line_csv; - os.nfields = 3; - os.nfields += aggr_fields[config->aggr_mode]; - if (counter->cgrp) - os.nfields++; - } - if (run == 0 || ena == 0 || counter->counts->scaled == -1) { - if (config->metric_only) { - pm(config, &os, NULL, "", "", 0); - return; - } - aggr_printout(config, counter, id, nr); - - fprintf(config->output, "%*s%s", - config->csv_output ? 0 : 18, - counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, - config->csv_sep); - - if (counter->supported) { - config->print_free_counters_hint = 1; - if (is_mixed_hw_group(counter)) - config->print_mixed_hw_group_error = 1; - } - - fprintf(config->output, "%-*s%s", - config->csv_output ? 0 : config->unit_width, - counter->unit, config->csv_sep); - - fprintf(config->output, "%*s", - config->csv_output ? 0 : -25, - perf_evsel__name(counter)); - - if (counter->cgrp) - fprintf(config->output, "%s%s", - config->csv_sep, counter->cgrp->name); - - if (!config->csv_output) - pm(config, &os, NULL, NULL, "", 0); - print_noise(config, counter, noise); - print_running(config, run, ena); - if (config->csv_output) - pm(config, &os, NULL, NULL, "", 0); - return; - } - - if (!config->metric_only) - abs_printout(config, id, nr, counter, uval); - - out.print_metric = pm; - out.new_line = nl; - out.ctx = &os; - out.force_header = false; - - if (config->csv_output && !config->metric_only) { - print_noise(config, counter, noise); - print_running(config, run, ena); - } - - perf_stat__print_shadow_stats(config, counter, uval, - first_shadow_cpu(config, counter, id), - &out, &config->metric_events, st); - if (!config->csv_output && !config->metric_only) { - print_noise(config, counter, noise); - print_running(config, run, ena); - } -} - -static void aggr_update_shadow(struct perf_stat_config *config, - struct perf_evlist *evlist) -{ - int cpu, s2, id, s; - u64 val; - struct perf_evsel *counter; - - for (s = 0; s < config->aggr_map->nr; s++) { - id = config->aggr_map->map[s]; - evlist__for_each_entry(evlist, counter) { - val = 0; - for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { - s2 = config->aggr_get_id(config, evlist->cpus, cpu); - if (s2 != id) - continue; - val += perf_counts(counter->counts, cpu, 0)->val; - } - perf_stat__update_shadow_stats(counter, val, - first_shadow_cpu(config, counter, id), - &rt_stat); - } - } -} - -static void uniquify_event_name(struct perf_evsel *counter) -{ - char *new_name; - char *config; - - if (counter->uniquified_name || - !counter->pmu_name || !strncmp(counter->name, counter->pmu_name, - strlen(counter->pmu_name))) - return; - - config = strchr(counter->name, '/'); - if (config) { - if (asprintf(&new_name, - "%s%s", counter->pmu_name, config) > 0) { - free(counter->name); - counter->name = new_name; - } - } else { - if (asprintf(&new_name, - "%s [%s]", counter->name, counter->pmu_name) > 0) { - free(counter->name); - counter->name = new_name; - } - } - - counter->uniquified_name = true; -} - -static void collect_all_aliases(struct perf_stat_config *config, struct perf_evsel *counter, - void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data, - bool first), - void *data) -{ - struct perf_evlist *evlist = counter->evlist; - struct perf_evsel *alias; - - alias = list_prepare_entry(counter, &(evlist->entries), node); - list_for_each_entry_continue (alias, &evlist->entries, node) { - if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) || - alias->scale != counter->scale || - alias->cgrp != counter->cgrp || - strcmp(alias->unit, counter->unit) || - perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter)) - break; - alias->merged_stat = true; - cb(config, alias, data, false); - } -} - -static bool collect_data(struct perf_stat_config *config, struct perf_evsel *counter, - void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data, - bool first), - void *data) -{ - if (counter->merged_stat) - return false; - cb(config, counter, data, true); - if (config->no_merge) - uniquify_event_name(counter); - else if (counter->auto_merge_stats) - collect_all_aliases(config, counter, cb, data); - return true; -} - -struct aggr_data { - u64 ena, run, val; - int id; - int nr; - int cpu; -}; - -static void aggr_cb(struct perf_stat_config *config, - struct perf_evsel *counter, void *data, bool first) -{ - struct aggr_data *ad = data; - int cpu, s2; - - for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { - struct perf_counts_values *counts; - - s2 = config->aggr_get_id(config, perf_evsel__cpus(counter), cpu); - if (s2 != ad->id) - continue; - if (first) - ad->nr++; - counts = perf_counts(counter->counts, cpu, 0); - /* - * When any result is bad, make them all to give - * consistent output in interval mode. - */ - if (counts->ena == 0 || counts->run == 0 || - counter->counts->scaled == -1) { - ad->ena = 0; - ad->run = 0; - break; - } - ad->val += counts->val; - ad->ena += counts->ena; - ad->run += counts->run; - } -} - -static void print_aggr(struct perf_stat_config *config, - struct perf_evlist *evlist, - char *prefix) -{ - bool metric_only = config->metric_only; - FILE *output = config->output; - struct perf_evsel *counter; - int s, id, nr; - double uval; - u64 ena, run, val; - bool first; - - if (!(config->aggr_map || config->aggr_get_id)) - return; - - aggr_update_shadow(config, evlist); - - /* - * With metric_only everything is on a single line. - * Without each counter has its own line. - */ - for (s = 0; s < config->aggr_map->nr; s++) { - struct aggr_data ad; - if (prefix && metric_only) - fprintf(output, "%s", prefix); - - ad.id = id = config->aggr_map->map[s]; - first = true; - evlist__for_each_entry(evlist, counter) { - if (is_duration_time(counter)) - continue; - - ad.val = ad.ena = ad.run = 0; - ad.nr = 0; - if (!collect_data(config, counter, aggr_cb, &ad)) - continue; - nr = ad.nr; - ena = ad.ena; - run = ad.run; - val = ad.val; - if (first && metric_only) { - first = false; - aggr_printout(config, counter, id, nr); - } - if (prefix && !metric_only) - fprintf(output, "%s", prefix); - - uval = val * counter->scale; - printout(config, id, nr, counter, uval, prefix, - run, ena, 1.0, &rt_stat); - if (!metric_only) - fputc('\n', output); - } - if (metric_only) - fputc('\n', output); - } -} - -static int cmp_val(const void *a, const void *b) -{ - return ((struct perf_aggr_thread_value *)b)->val - - ((struct perf_aggr_thread_value *)a)->val; -} - -static struct perf_aggr_thread_value *sort_aggr_thread( - struct perf_evsel *counter, - int nthreads, int ncpus, - int *ret, - struct target *_target) -{ - int cpu, thread, i = 0; - double uval; - struct perf_aggr_thread_value *buf; - - buf = calloc(nthreads, sizeof(struct perf_aggr_thread_value)); - if (!buf) - return NULL; - - for (thread = 0; thread < nthreads; thread++) { - u64 ena = 0, run = 0, val = 0; - - for (cpu = 0; cpu < ncpus; cpu++) { - val += perf_counts(counter->counts, cpu, thread)->val; - ena += perf_counts(counter->counts, cpu, thread)->ena; - run += perf_counts(counter->counts, cpu, thread)->run; - } - - uval = val * counter->scale; - - /* - * Skip value 0 when enabling --per-thread globally, - * otherwise too many 0 output. - */ - if (uval == 0.0 && target__has_per_thread(_target)) - continue; - - buf[i].counter = counter; - buf[i].id = thread; - buf[i].uval = uval; - buf[i].val = val; - buf[i].run = run; - buf[i].ena = ena; - i++; - } - - qsort(buf, i, sizeof(struct perf_aggr_thread_value), cmp_val); - - if (ret) - *ret = i; - - return buf; -} - -static void print_aggr_thread(struct perf_stat_config *config, - struct target *_target, - struct perf_evsel *counter, char *prefix) -{ - FILE *output = config->output; - int nthreads = thread_map__nr(counter->threads); - int ncpus = cpu_map__nr(counter->cpus); - int thread, sorted_threads, id; - struct perf_aggr_thread_value *buf; - - buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads, _target); - if (!buf) { - perror("cannot sort aggr thread"); - return; - } - - for (thread = 0; thread < sorted_threads; thread++) { - if (prefix) - fprintf(output, "%s", prefix); - - id = buf[thread].id; - if (config->stats) - printout(config, id, 0, buf[thread].counter, buf[thread].uval, - prefix, buf[thread].run, buf[thread].ena, 1.0, - &config->stats[id]); - else - printout(config, id, 0, buf[thread].counter, buf[thread].uval, - prefix, buf[thread].run, buf[thread].ena, 1.0, - &rt_stat); - fputc('\n', output); - } - - free(buf); -} - -struct caggr_data { - double avg, avg_enabled, avg_running; -}; - -static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused, - struct perf_evsel *counter, void *data, - bool first __maybe_unused) -{ - struct caggr_data *cd = data; - struct perf_stat_evsel *ps = counter->stats; - - cd->avg += avg_stats(&ps->res_stats[0]); - cd->avg_enabled += avg_stats(&ps->res_stats[1]); - cd->avg_running += avg_stats(&ps->res_stats[2]); -} - -/* - * Print out the results of a single counter: - * aggregated counts in system-wide mode - */ -static void print_counter_aggr(struct perf_stat_config *config, - struct perf_evsel *counter, char *prefix) -{ - bool metric_only = config->metric_only; - FILE *output = config->output; - double uval; - struct caggr_data cd = { .avg = 0.0 }; - - if (!collect_data(config, counter, counter_aggr_cb, &cd)) - return; - - if (prefix && !metric_only) - fprintf(output, "%s", prefix); - - uval = cd.avg * counter->scale; - printout(config, -1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled, - cd.avg, &rt_stat); - if (!metric_only) - fprintf(output, "\n"); -} - -static void counter_cb(struct perf_stat_config *config __maybe_unused, - struct perf_evsel *counter, void *data, - bool first __maybe_unused) -{ - struct aggr_data *ad = data; - - ad->val += perf_counts(counter->counts, ad->cpu, 0)->val; - ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena; - ad->run += perf_counts(counter->counts, ad->cpu, 0)->run; -} - -/* - * Print out the results of a single counter: - * does not use aggregated count in system-wide - */ -static void print_counter(struct perf_stat_config *config, - struct perf_evsel *counter, char *prefix) -{ - FILE *output = config->output; - u64 ena, run, val; - double uval; - int cpu; - - for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { - struct aggr_data ad = { .cpu = cpu }; - - if (!collect_data(config, counter, counter_cb, &ad)) - return; - val = ad.val; - ena = ad.ena; - run = ad.run; - - if (prefix) - fprintf(output, "%s", prefix); - - uval = val * counter->scale; - printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0, - &rt_stat); - - fputc('\n', output); - } -} - -static void print_no_aggr_metric(struct perf_stat_config *config, - struct perf_evlist *evlist, - char *prefix) -{ - int cpu; - int nrcpus = 0; - struct perf_evsel *counter; - u64 ena, run, val; - double uval; - - nrcpus = evlist->cpus->nr; - for (cpu = 0; cpu < nrcpus; cpu++) { - bool first = true; - - if (prefix) - fputs(prefix, config->output); - evlist__for_each_entry(evlist, counter) { - if (is_duration_time(counter)) - continue; - if (first) { - aggr_printout(config, counter, cpu, 0); - first = false; - } - val = perf_counts(counter->counts, cpu, 0)->val; - ena = perf_counts(counter->counts, cpu, 0)->ena; - run = perf_counts(counter->counts, cpu, 0)->run; - - uval = val * counter->scale; - printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0, - &rt_stat); - } - fputc('\n', config->output); - } -} - -static int aggr_header_lens[] = { - [AGGR_CORE] = 18, - [AGGR_SOCKET] = 12, - [AGGR_NONE] = 6, - [AGGR_THREAD] = 24, - [AGGR_GLOBAL] = 0, -}; - -static const char *aggr_header_csv[] = { - [AGGR_CORE] = "core,cpus,", - [AGGR_SOCKET] = "socket,cpus", - [AGGR_NONE] = "cpu,", - [AGGR_THREAD] = "comm-pid,", - [AGGR_GLOBAL] = "" -}; - -static void print_metric_headers(struct perf_stat_config *config, - struct perf_evlist *evlist, - const char *prefix, bool no_indent) -{ - struct perf_stat_output_ctx out; - struct perf_evsel *counter; - struct outstate os = { - .fh = config->output - }; - - if (prefix) - fprintf(config->output, "%s", prefix); - - if (!config->csv_output && !no_indent) - fprintf(config->output, "%*s", - aggr_header_lens[config->aggr_mode], ""); - if (config->csv_output) { - if (config->interval) - fputs("time,", config->output); - fputs(aggr_header_csv[config->aggr_mode], config->output); - } - - /* Print metrics headers only */ - evlist__for_each_entry(evlist, counter) { - if (is_duration_time(counter)) - continue; - os.evsel = counter; - out.ctx = &os; - out.print_metric = print_metric_header; - out.new_line = new_line_metric; - out.force_header = true; - os.evsel = counter; - perf_stat__print_shadow_stats(config, counter, 0, - 0, - &out, - &config->metric_events, - &rt_stat); - } - fputc('\n', config->output); -} - -static void print_interval(struct perf_stat_config *config, - struct perf_evlist *evlist, - char *prefix, struct timespec *ts) -{ - bool metric_only = config->metric_only; - unsigned int unit_width = config->unit_width; - FILE *output = config->output; - static int num_print_interval; - - if (config->interval_clear) - puts(CONSOLE_CLEAR); - - sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep); - - if ((num_print_interval == 0 && !config->csv_output) || config->interval_clear) { - switch (config->aggr_mode) { - case AGGR_SOCKET: - fprintf(output, "# time socket cpus"); - if (!metric_only) - fprintf(output, " counts %*s events\n", unit_width, "unit"); - break; - case AGGR_CORE: - fprintf(output, "# time core cpus"); - if (!metric_only) - fprintf(output, " counts %*s events\n", unit_width, "unit"); - break; - case AGGR_NONE: - fprintf(output, "# time CPU "); - if (!metric_only) - fprintf(output, " counts %*s events\n", unit_width, "unit"); - break; - case AGGR_THREAD: - fprintf(output, "# time comm-pid"); - if (!metric_only) - fprintf(output, " counts %*s events\n", unit_width, "unit"); - break; - case AGGR_GLOBAL: - default: - fprintf(output, "# time"); - if (!metric_only) - fprintf(output, " counts %*s events\n", unit_width, "unit"); - case AGGR_UNSET: - break; - } - } - - if ((num_print_interval == 0 || config->interval_clear) && metric_only) - print_metric_headers(config, evlist, " ", true); - if (++num_print_interval == 25) - num_print_interval = 0; -} - -static void print_header(struct perf_stat_config *config, - struct target *_target, - int argc, const char **argv) -{ - FILE *output = config->output; - int i; - - fflush(stdout); - - if (!config->csv_output) { - fprintf(output, "\n"); - fprintf(output, " Performance counter stats for "); - if (_target->system_wide) - fprintf(output, "\'system wide"); - else if (_target->cpu_list) - fprintf(output, "\'CPU(s) %s", _target->cpu_list); - else if (!target__has_task(_target)) { - fprintf(output, "\'%s", argv ? argv[0] : "pipe"); - for (i = 1; argv && (i < argc); i++) - fprintf(output, " %s", argv[i]); - } else if (_target->pid) - fprintf(output, "process id \'%s", _target->pid); - else - fprintf(output, "thread id \'%s", _target->tid); - - fprintf(output, "\'"); - if (config->run_count > 1) - fprintf(output, " (%d runs)", config->run_count); - fprintf(output, ":\n\n"); - } -} - -static int get_precision(double num) -{ - if (num > 1) - return 0; - - return lround(ceil(-log10(num))); -} - -static void print_table(struct perf_stat_config *config, - FILE *output, int precision, double avg) -{ - char tmp[64]; - int idx, indent = 0; - - scnprintf(tmp, 64, " %17.*f", precision, avg); - while (tmp[indent] == ' ') - indent++; - - fprintf(output, "%*s# Table of individual measurements:\n", indent, ""); - - for (idx = 0; idx < config->run_count; idx++) { - double run = (double) config->walltime_run[idx] / NSEC_PER_SEC; - int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5); - - fprintf(output, " %17.*f (%+.*f) ", - precision, run, precision, run - avg); - - for (h = 0; h < n; h++) - fprintf(output, "#"); - - fprintf(output, "\n"); - } - - fprintf(output, "\n%*s# Final result:\n", indent, ""); -} - -static double timeval2double(struct timeval *t) -{ - return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC; -} - -static void print_footer(struct perf_stat_config *config) -{ - double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC; - FILE *output = config->output; - int n; - - if (!config->null_run) - fprintf(output, "\n"); - - if (config->run_count == 1) { - fprintf(output, " %17.9f seconds time elapsed", avg); - - if (config->ru_display) { - double ru_utime = timeval2double(&config->ru_data.ru_utime); - double ru_stime = timeval2double(&config->ru_data.ru_stime); - - fprintf(output, "\n\n"); - fprintf(output, " %17.9f seconds user\n", ru_utime); - fprintf(output, " %17.9f seconds sys\n", ru_stime); - } - } else { - double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC; - /* - * Display at most 2 more significant - * digits than the stddev inaccuracy. - */ - int precision = get_precision(sd) + 2; - - if (config->walltime_run_table) - print_table(config, output, precision, avg); - - fprintf(output, " %17.*f +- %.*f seconds time elapsed", - precision, avg, precision, sd); - - print_noise_pct(config, sd, avg); - } - fprintf(output, "\n\n"); - - if (config->print_free_counters_hint && - sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 && - n > 0) - fprintf(output, -"Some events weren't counted. Try disabling the NMI watchdog:\n" -" echo 0 > /proc/sys/kernel/nmi_watchdog\n" -" perf stat ...\n" -" echo 1 > /proc/sys/kernel/nmi_watchdog\n"); - - if (config->print_mixed_hw_group_error) - fprintf(output, - "The events in group usually have to be from " - "the same PMU. Try reorganizing the group.\n"); -} - -static void -perf_evlist__print_counters(struct perf_evlist *evlist, - struct perf_stat_config *config, - struct target *_target, - struct timespec *ts, - int argc, const char **argv) -{ - bool metric_only = config->metric_only; - int interval = config->interval; - struct perf_evsel *counter; - char buf[64], *prefix = NULL; - - if (interval) - print_interval(config, evlist, prefix = buf, ts); - else - print_header(config, _target, argc, argv); - - if (metric_only) { - static int num_print_iv; - - if (num_print_iv == 0 && !interval) - print_metric_headers(config, evlist, prefix, false); - if (num_print_iv++ == 25) - num_print_iv = 0; - if (config->aggr_mode == AGGR_GLOBAL && prefix) - fprintf(config->output, "%s", prefix); - } - - switch (config->aggr_mode) { - case AGGR_CORE: - case AGGR_SOCKET: - print_aggr(config, evlist, prefix); - break; - case AGGR_THREAD: - evlist__for_each_entry(evlist, counter) { - if (is_duration_time(counter)) - continue; - print_aggr_thread(config, _target, counter, prefix); - } - break; - case AGGR_GLOBAL: - evlist__for_each_entry(evlist, counter) { - if (is_duration_time(counter)) - continue; - print_counter_aggr(config, counter, prefix); - } - if (metric_only) - fputc('\n', config->output); - break; - case AGGR_NONE: - if (metric_only) - print_no_aggr_metric(config, evlist, prefix); - else { - evlist__for_each_entry(evlist, counter) { - if (is_duration_time(counter)) - continue; - print_counter(config, counter, prefix); - } - } - break; - case AGGR_UNSET: - default: - break; - } - - if (!interval && !config->csv_output) - print_footer(config); - - fflush(config->output); -} - static void print_counters(struct timespec *ts, int argc, const char **argv) { /* Do not print anything if we record to the pipe. */ diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 7efe15b9618d..ecd9f9ceda77 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -73,6 +73,7 @@ libperf-y += vdso.o libperf-y += counts.o libperf-y += stat.o libperf-y += stat-shadow.o +libperf-y += stat-display.o libperf-y += record.o libperf-y += srcline.o libperf-y += data.o diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c new file mode 100644 index 000000000000..e7b4c44ebb62 --- /dev/null +++ b/tools/perf/util/stat-display.c @@ -0,0 +1,1166 @@ +#include +#include +#include +#include +#include "evlist.h" +#include "evsel.h" +#include "stat.h" +#include "top.h" +#include "thread_map.h" +#include "cpumap.h" +#include "string2.h" +#include "sane_ctype.h" +#include "cgroup.h" +#include +#include + +#define CNTR_NOT_SUPPORTED "" +#define CNTR_NOT_COUNTED "" + +static bool is_duration_time(struct perf_evsel *evsel) +{ + return !strcmp(evsel->name, "duration_time"); +} + +static void print_running(struct perf_stat_config *config, + u64 run, u64 ena) +{ + if (config->csv_output) { + fprintf(config->output, "%s%" PRIu64 "%s%.2f", + config->csv_sep, + run, + config->csv_sep, + ena ? 100.0 * run / ena : 100.0); + } else if (run != ena) { + fprintf(config->output, " (%.2f%%)", 100.0 * run / ena); + } +} + +static void print_noise_pct(struct perf_stat_config *config, + double total, double avg) +{ + double pct = rel_stddev_stats(total, avg); + + if (config->csv_output) + fprintf(config->output, "%s%.2f%%", config->csv_sep, pct); + else if (pct) + fprintf(config->output, " ( +-%6.2f%% )", pct); +} + +static void print_noise(struct perf_stat_config *config, + struct perf_evsel *evsel, double avg) +{ + struct perf_stat_evsel *ps; + + if (config->run_count == 1) + return; + + ps = evsel->stats; + print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg); +} + +static void aggr_printout(struct perf_stat_config *config, + struct perf_evsel *evsel, int id, int nr) +{ + switch (config->aggr_mode) { + case AGGR_CORE: + fprintf(config->output, "S%d-C%*d%s%*d%s", + cpu_map__id_to_socket(id), + config->csv_output ? 0 : -8, + cpu_map__id_to_cpu(id), + config->csv_sep, + config->csv_output ? 0 : 4, + nr, + config->csv_sep); + break; + case AGGR_SOCKET: + fprintf(config->output, "S%*d%s%*d%s", + config->csv_output ? 0 : -5, + id, + config->csv_sep, + config->csv_output ? 0 : 4, + nr, + config->csv_sep); + break; + case AGGR_NONE: + fprintf(config->output, "CPU%*d%s", + config->csv_output ? 0 : -4, + perf_evsel__cpus(evsel)->map[id], config->csv_sep); + break; + case AGGR_THREAD: + fprintf(config->output, "%*s-%*d%s", + config->csv_output ? 0 : 16, + thread_map__comm(evsel->threads, id), + config->csv_output ? 0 : -8, + thread_map__pid(evsel->threads, id), + config->csv_sep); + break; + case AGGR_GLOBAL: + case AGGR_UNSET: + default: + break; + } +} + +struct outstate { + FILE *fh; + bool newline; + const char *prefix; + int nfields; + int id, nr; + struct perf_evsel *evsel; +}; + +#define METRIC_LEN 35 + +static void new_line_std(struct perf_stat_config *config __maybe_unused, + void *ctx) +{ + struct outstate *os = ctx; + + os->newline = true; +} + +static void do_new_line_std(struct perf_stat_config *config, + struct outstate *os) +{ + fputc('\n', os->fh); + fputs(os->prefix, os->fh); + aggr_printout(config, os->evsel, os->id, os->nr); + if (config->aggr_mode == AGGR_NONE) + fprintf(os->fh, " "); + fprintf(os->fh, " "); +} + +static void print_metric_std(struct perf_stat_config *config, + void *ctx, const char *color, const char *fmt, + const char *unit, double val) +{ + struct outstate *os = ctx; + FILE *out = os->fh; + int n; + bool newline = os->newline; + + os->newline = false; + + if (unit == NULL || fmt == NULL) { + fprintf(out, "%-*s", METRIC_LEN, ""); + return; + } + + if (newline) + do_new_line_std(config, os); + + n = fprintf(out, " # "); + if (color) + n += color_fprintf(out, color, fmt, val); + else + n += fprintf(out, fmt, val); + fprintf(out, " %-*s", METRIC_LEN - n - 1, unit); +} + +static void new_line_csv(struct perf_stat_config *config, void *ctx) +{ + struct outstate *os = ctx; + int i; + + fputc('\n', os->fh); + if (os->prefix) + fprintf(os->fh, "%s%s", os->prefix, config->csv_sep); + aggr_printout(config, os->evsel, os->id, os->nr); + for (i = 0; i < os->nfields; i++) + fputs(config->csv_sep, os->fh); +} + +static void print_metric_csv(struct perf_stat_config *config __maybe_unused, + void *ctx, + const char *color __maybe_unused, + const char *fmt, const char *unit, double val) +{ + struct outstate *os = ctx; + FILE *out = os->fh; + char buf[64], *vals, *ends; + + if (unit == NULL || fmt == NULL) { + fprintf(out, "%s%s", config->csv_sep, config->csv_sep); + return; + } + snprintf(buf, sizeof(buf), fmt, val); + ends = vals = ltrim(buf); + while (isdigit(*ends) || *ends == '.') + ends++; + *ends = 0; + while (isspace(*unit)) + unit++; + fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, unit); +} + +/* Filter out some columns that don't work well in metrics only mode */ + +static bool valid_only_metric(const char *unit) +{ + if (!unit) + return false; + if (strstr(unit, "/sec") || + strstr(unit, "hz") || + strstr(unit, "Hz") || + strstr(unit, "CPUs utilized")) + return false; + return true; +} + +static const char *fixunit(char *buf, struct perf_evsel *evsel, + const char *unit) +{ + if (!strncmp(unit, "of all", 6)) { + snprintf(buf, 1024, "%s %s", perf_evsel__name(evsel), + unit); + return buf; + } + return unit; +} + +static void print_metric_only(struct perf_stat_config *config, + void *ctx, const char *color, const char *fmt, + const char *unit, double val) +{ + struct outstate *os = ctx; + FILE *out = os->fh; + char buf[1024], str[1024]; + unsigned mlen = config->metric_only_len; + + if (!valid_only_metric(unit)) + return; + unit = fixunit(buf, os->evsel, unit); + if (mlen < strlen(unit)) + mlen = strlen(unit) + 1; + + if (color) + mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1; + + color_snprintf(str, sizeof(str), color ?: "", fmt, val); + fprintf(out, "%*s ", mlen, str); +} + +static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused, + void *ctx, const char *color __maybe_unused, + const char *fmt, + const char *unit, double val) +{ + struct outstate *os = ctx; + FILE *out = os->fh; + char buf[64], *vals, *ends; + char tbuf[1024]; + + if (!valid_only_metric(unit)) + return; + unit = fixunit(tbuf, os->evsel, unit); + snprintf(buf, sizeof buf, fmt, val); + ends = vals = ltrim(buf); + while (isdigit(*ends) || *ends == '.') + ends++; + *ends = 0; + fprintf(out, "%s%s", vals, config->csv_sep); +} + +static void new_line_metric(struct perf_stat_config *config __maybe_unused, + void *ctx __maybe_unused) +{ +} + +static void print_metric_header(struct perf_stat_config *config, + void *ctx, const char *color __maybe_unused, + const char *fmt __maybe_unused, + const char *unit, double val __maybe_unused) +{ + struct outstate *os = ctx; + char tbuf[1024]; + + if (!valid_only_metric(unit)) + return; + unit = fixunit(tbuf, os->evsel, unit); + if (config->csv_output) + fprintf(os->fh, "%s%s", unit, config->csv_sep); + else + fprintf(os->fh, "%*s ", config->metric_only_len, unit); +} + +static int first_shadow_cpu(struct perf_stat_config *config, + struct perf_evsel *evsel, int id) +{ + struct perf_evlist *evlist = evsel->evlist; + int i; + + if (!config->aggr_get_id) + return 0; + + if (config->aggr_mode == AGGR_NONE) + return id; + + if (config->aggr_mode == AGGR_GLOBAL) + return 0; + + for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) { + int cpu2 = perf_evsel__cpus(evsel)->map[i]; + + if (config->aggr_get_id(config, evlist->cpus, cpu2) == id) + return cpu2; + } + return 0; +} + +static void abs_printout(struct perf_stat_config *config, + int id, int nr, struct perf_evsel *evsel, double avg) +{ + FILE *output = config->output; + double sc = evsel->scale; + const char *fmt; + + if (config->csv_output) { + fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s"; + } else { + if (config->big_num) + fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s"; + else + fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s"; + } + + aggr_printout(config, evsel, id, nr); + + fprintf(output, fmt, avg, config->csv_sep); + + if (evsel->unit) + fprintf(output, "%-*s%s", + config->csv_output ? 0 : config->unit_width, + evsel->unit, config->csv_sep); + + fprintf(output, "%-*s", config->csv_output ? 0 : 25, perf_evsel__name(evsel)); + + if (evsel->cgrp) + fprintf(output, "%s%s", config->csv_sep, evsel->cgrp->name); +} + +static bool is_mixed_hw_group(struct perf_evsel *counter) +{ + struct perf_evlist *evlist = counter->evlist; + u32 pmu_type = counter->attr.type; + struct perf_evsel *pos; + + if (counter->nr_members < 2) + return false; + + evlist__for_each_entry(evlist, pos) { + /* software events can be part of any hardware group */ + if (pos->attr.type == PERF_TYPE_SOFTWARE) + continue; + if (pmu_type == PERF_TYPE_SOFTWARE) { + pmu_type = pos->attr.type; + continue; + } + if (pmu_type != pos->attr.type) + return true; + } + + return false; +} + +static void printout(struct perf_stat_config *config, int id, int nr, + struct perf_evsel *counter, double uval, + char *prefix, u64 run, u64 ena, double noise, + struct runtime_stat *st) +{ + struct perf_stat_output_ctx out; + struct outstate os = { + .fh = config->output, + .prefix = prefix ? prefix : "", + .id = id, + .nr = nr, + .evsel = counter, + }; + print_metric_t pm = print_metric_std; + new_line_t nl; + + if (config->metric_only) { + nl = new_line_metric; + if (config->csv_output) + pm = print_metric_only_csv; + else + pm = print_metric_only; + } else + nl = new_line_std; + + if (config->csv_output && !config->metric_only) { + static int aggr_fields[] = { + [AGGR_GLOBAL] = 0, + [AGGR_THREAD] = 1, + [AGGR_NONE] = 1, + [AGGR_SOCKET] = 2, + [AGGR_CORE] = 2, + }; + + pm = print_metric_csv; + nl = new_line_csv; + os.nfields = 3; + os.nfields += aggr_fields[config->aggr_mode]; + if (counter->cgrp) + os.nfields++; + } + if (run == 0 || ena == 0 || counter->counts->scaled == -1) { + if (config->metric_only) { + pm(config, &os, NULL, "", "", 0); + return; + } + aggr_printout(config, counter, id, nr); + + fprintf(config->output, "%*s%s", + config->csv_output ? 0 : 18, + counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, + config->csv_sep); + + if (counter->supported) { + config->print_free_counters_hint = 1; + if (is_mixed_hw_group(counter)) + config->print_mixed_hw_group_error = 1; + } + + fprintf(config->output, "%-*s%s", + config->csv_output ? 0 : config->unit_width, + counter->unit, config->csv_sep); + + fprintf(config->output, "%*s", + config->csv_output ? 0 : -25, + perf_evsel__name(counter)); + + if (counter->cgrp) + fprintf(config->output, "%s%s", + config->csv_sep, counter->cgrp->name); + + if (!config->csv_output) + pm(config, &os, NULL, NULL, "", 0); + print_noise(config, counter, noise); + print_running(config, run, ena); + if (config->csv_output) + pm(config, &os, NULL, NULL, "", 0); + return; + } + + if (!config->metric_only) + abs_printout(config, id, nr, counter, uval); + + out.print_metric = pm; + out.new_line = nl; + out.ctx = &os; + out.force_header = false; + + if (config->csv_output && !config->metric_only) { + print_noise(config, counter, noise); + print_running(config, run, ena); + } + + perf_stat__print_shadow_stats(config, counter, uval, + first_shadow_cpu(config, counter, id), + &out, &config->metric_events, st); + if (!config->csv_output && !config->metric_only) { + print_noise(config, counter, noise); + print_running(config, run, ena); + } +} + +static void aggr_update_shadow(struct perf_stat_config *config, + struct perf_evlist *evlist) +{ + int cpu, s2, id, s; + u64 val; + struct perf_evsel *counter; + + for (s = 0; s < config->aggr_map->nr; s++) { + id = config->aggr_map->map[s]; + evlist__for_each_entry(evlist, counter) { + val = 0; + for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { + s2 = config->aggr_get_id(config, evlist->cpus, cpu); + if (s2 != id) + continue; + val += perf_counts(counter->counts, cpu, 0)->val; + } + perf_stat__update_shadow_stats(counter, val, + first_shadow_cpu(config, counter, id), + &rt_stat); + } + } +} + +static void uniquify_event_name(struct perf_evsel *counter) +{ + char *new_name; + char *config; + + if (counter->uniquified_name || + !counter->pmu_name || !strncmp(counter->name, counter->pmu_name, + strlen(counter->pmu_name))) + return; + + config = strchr(counter->name, '/'); + if (config) { + if (asprintf(&new_name, + "%s%s", counter->pmu_name, config) > 0) { + free(counter->name); + counter->name = new_name; + } + } else { + if (asprintf(&new_name, + "%s [%s]", counter->name, counter->pmu_name) > 0) { + free(counter->name); + counter->name = new_name; + } + } + + counter->uniquified_name = true; +} + +static void collect_all_aliases(struct perf_stat_config *config, struct perf_evsel *counter, + void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data, + bool first), + void *data) +{ + struct perf_evlist *evlist = counter->evlist; + struct perf_evsel *alias; + + alias = list_prepare_entry(counter, &(evlist->entries), node); + list_for_each_entry_continue (alias, &evlist->entries, node) { + if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) || + alias->scale != counter->scale || + alias->cgrp != counter->cgrp || + strcmp(alias->unit, counter->unit) || + perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter)) + break; + alias->merged_stat = true; + cb(config, alias, data, false); + } +} + +static bool collect_data(struct perf_stat_config *config, struct perf_evsel *counter, + void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data, + bool first), + void *data) +{ + if (counter->merged_stat) + return false; + cb(config, counter, data, true); + if (config->no_merge) + uniquify_event_name(counter); + else if (counter->auto_merge_stats) + collect_all_aliases(config, counter, cb, data); + return true; +} + +struct aggr_data { + u64 ena, run, val; + int id; + int nr; + int cpu; +}; + +static void aggr_cb(struct perf_stat_config *config, + struct perf_evsel *counter, void *data, bool first) +{ + struct aggr_data *ad = data; + int cpu, s2; + + for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { + struct perf_counts_values *counts; + + s2 = config->aggr_get_id(config, perf_evsel__cpus(counter), cpu); + if (s2 != ad->id) + continue; + if (first) + ad->nr++; + counts = perf_counts(counter->counts, cpu, 0); + /* + * When any result is bad, make them all to give + * consistent output in interval mode. + */ + if (counts->ena == 0 || counts->run == 0 || + counter->counts->scaled == -1) { + ad->ena = 0; + ad->run = 0; + break; + } + ad->val += counts->val; + ad->ena += counts->ena; + ad->run += counts->run; + } +} + +static void print_aggr(struct perf_stat_config *config, + struct perf_evlist *evlist, + char *prefix) +{ + bool metric_only = config->metric_only; + FILE *output = config->output; + struct perf_evsel *counter; + int s, id, nr; + double uval; + u64 ena, run, val; + bool first; + + if (!(config->aggr_map || config->aggr_get_id)) + return; + + aggr_update_shadow(config, evlist); + + /* + * With metric_only everything is on a single line. + * Without each counter has its own line. + */ + for (s = 0; s < config->aggr_map->nr; s++) { + struct aggr_data ad; + if (prefix && metric_only) + fprintf(output, "%s", prefix); + + ad.id = id = config->aggr_map->map[s]; + first = true; + evlist__for_each_entry(evlist, counter) { + if (is_duration_time(counter)) + continue; + + ad.val = ad.ena = ad.run = 0; + ad.nr = 0; + if (!collect_data(config, counter, aggr_cb, &ad)) + continue; + nr = ad.nr; + ena = ad.ena; + run = ad.run; + val = ad.val; + if (first && metric_only) { + first = false; + aggr_printout(config, counter, id, nr); + } + if (prefix && !metric_only) + fprintf(output, "%s", prefix); + + uval = val * counter->scale; + printout(config, id, nr, counter, uval, prefix, + run, ena, 1.0, &rt_stat); + if (!metric_only) + fputc('\n', output); + } + if (metric_only) + fputc('\n', output); + } +} + +static int cmp_val(const void *a, const void *b) +{ + return ((struct perf_aggr_thread_value *)b)->val - + ((struct perf_aggr_thread_value *)a)->val; +} + +static struct perf_aggr_thread_value *sort_aggr_thread( + struct perf_evsel *counter, + int nthreads, int ncpus, + int *ret, + struct target *_target) +{ + int cpu, thread, i = 0; + double uval; + struct perf_aggr_thread_value *buf; + + buf = calloc(nthreads, sizeof(struct perf_aggr_thread_value)); + if (!buf) + return NULL; + + for (thread = 0; thread < nthreads; thread++) { + u64 ena = 0, run = 0, val = 0; + + for (cpu = 0; cpu < ncpus; cpu++) { + val += perf_counts(counter->counts, cpu, thread)->val; + ena += perf_counts(counter->counts, cpu, thread)->ena; + run += perf_counts(counter->counts, cpu, thread)->run; + } + + uval = val * counter->scale; + + /* + * Skip value 0 when enabling --per-thread globally, + * otherwise too many 0 output. + */ + if (uval == 0.0 && target__has_per_thread(_target)) + continue; + + buf[i].counter = counter; + buf[i].id = thread; + buf[i].uval = uval; + buf[i].val = val; + buf[i].run = run; + buf[i].ena = ena; + i++; + } + + qsort(buf, i, sizeof(struct perf_aggr_thread_value), cmp_val); + + if (ret) + *ret = i; + + return buf; +} + +static void print_aggr_thread(struct perf_stat_config *config, + struct target *_target, + struct perf_evsel *counter, char *prefix) +{ + FILE *output = config->output; + int nthreads = thread_map__nr(counter->threads); + int ncpus = cpu_map__nr(counter->cpus); + int thread, sorted_threads, id; + struct perf_aggr_thread_value *buf; + + buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads, _target); + if (!buf) { + perror("cannot sort aggr thread"); + return; + } + + for (thread = 0; thread < sorted_threads; thread++) { + if (prefix) + fprintf(output, "%s", prefix); + + id = buf[thread].id; + if (config->stats) + printout(config, id, 0, buf[thread].counter, buf[thread].uval, + prefix, buf[thread].run, buf[thread].ena, 1.0, + &config->stats[id]); + else + printout(config, id, 0, buf[thread].counter, buf[thread].uval, + prefix, buf[thread].run, buf[thread].ena, 1.0, + &rt_stat); + fputc('\n', output); + } + + free(buf); +} + +struct caggr_data { + double avg, avg_enabled, avg_running; +}; + +static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused, + struct perf_evsel *counter, void *data, + bool first __maybe_unused) +{ + struct caggr_data *cd = data; + struct perf_stat_evsel *ps = counter->stats; + + cd->avg += avg_stats(&ps->res_stats[0]); + cd->avg_enabled += avg_stats(&ps->res_stats[1]); + cd->avg_running += avg_stats(&ps->res_stats[2]); +} + +/* + * Print out the results of a single counter: + * aggregated counts in system-wide mode + */ +static void print_counter_aggr(struct perf_stat_config *config, + struct perf_evsel *counter, char *prefix) +{ + bool metric_only = config->metric_only; + FILE *output = config->output; + double uval; + struct caggr_data cd = { .avg = 0.0 }; + + if (!collect_data(config, counter, counter_aggr_cb, &cd)) + return; + + if (prefix && !metric_only) + fprintf(output, "%s", prefix); + + uval = cd.avg * counter->scale; + printout(config, -1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled, + cd.avg, &rt_stat); + if (!metric_only) + fprintf(output, "\n"); +} + +static void counter_cb(struct perf_stat_config *config __maybe_unused, + struct perf_evsel *counter, void *data, + bool first __maybe_unused) +{ + struct aggr_data *ad = data; + + ad->val += perf_counts(counter->counts, ad->cpu, 0)->val; + ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena; + ad->run += perf_counts(counter->counts, ad->cpu, 0)->run; +} + +/* + * Print out the results of a single counter: + * does not use aggregated count in system-wide + */ +static void print_counter(struct perf_stat_config *config, + struct perf_evsel *counter, char *prefix) +{ + FILE *output = config->output; + u64 ena, run, val; + double uval; + int cpu; + + for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { + struct aggr_data ad = { .cpu = cpu }; + + if (!collect_data(config, counter, counter_cb, &ad)) + return; + val = ad.val; + ena = ad.ena; + run = ad.run; + + if (prefix) + fprintf(output, "%s", prefix); + + uval = val * counter->scale; + printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0, + &rt_stat); + + fputc('\n', output); + } +} + +static void print_no_aggr_metric(struct perf_stat_config *config, + struct perf_evlist *evlist, + char *prefix) +{ + int cpu; + int nrcpus = 0; + struct perf_evsel *counter; + u64 ena, run, val; + double uval; + + nrcpus = evlist->cpus->nr; + for (cpu = 0; cpu < nrcpus; cpu++) { + bool first = true; + + if (prefix) + fputs(prefix, config->output); + evlist__for_each_entry(evlist, counter) { + if (is_duration_time(counter)) + continue; + if (first) { + aggr_printout(config, counter, cpu, 0); + first = false; + } + val = perf_counts(counter->counts, cpu, 0)->val; + ena = perf_counts(counter->counts, cpu, 0)->ena; + run = perf_counts(counter->counts, cpu, 0)->run; + + uval = val * counter->scale; + printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0, + &rt_stat); + } + fputc('\n', config->output); + } +} + +static int aggr_header_lens[] = { + [AGGR_CORE] = 18, + [AGGR_SOCKET] = 12, + [AGGR_NONE] = 6, + [AGGR_THREAD] = 24, + [AGGR_GLOBAL] = 0, +}; + +static const char *aggr_header_csv[] = { + [AGGR_CORE] = "core,cpus,", + [AGGR_SOCKET] = "socket,cpus", + [AGGR_NONE] = "cpu,", + [AGGR_THREAD] = "comm-pid,", + [AGGR_GLOBAL] = "" +}; + +static void print_metric_headers(struct perf_stat_config *config, + struct perf_evlist *evlist, + const char *prefix, bool no_indent) +{ + struct perf_stat_output_ctx out; + struct perf_evsel *counter; + struct outstate os = { + .fh = config->output + }; + + if (prefix) + fprintf(config->output, "%s", prefix); + + if (!config->csv_output && !no_indent) + fprintf(config->output, "%*s", + aggr_header_lens[config->aggr_mode], ""); + if (config->csv_output) { + if (config->interval) + fputs("time,", config->output); + fputs(aggr_header_csv[config->aggr_mode], config->output); + } + + /* Print metrics headers only */ + evlist__for_each_entry(evlist, counter) { + if (is_duration_time(counter)) + continue; + os.evsel = counter; + out.ctx = &os; + out.print_metric = print_metric_header; + out.new_line = new_line_metric; + out.force_header = true; + os.evsel = counter; + perf_stat__print_shadow_stats(config, counter, 0, + 0, + &out, + &config->metric_events, + &rt_stat); + } + fputc('\n', config->output); +} + +static void print_interval(struct perf_stat_config *config, + struct perf_evlist *evlist, + char *prefix, struct timespec *ts) +{ + bool metric_only = config->metric_only; + unsigned int unit_width = config->unit_width; + FILE *output = config->output; + static int num_print_interval; + + if (config->interval_clear) + puts(CONSOLE_CLEAR); + + sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep); + + if ((num_print_interval == 0 && !config->csv_output) || config->interval_clear) { + switch (config->aggr_mode) { + case AGGR_SOCKET: + fprintf(output, "# time socket cpus"); + if (!metric_only) + fprintf(output, " counts %*s events\n", unit_width, "unit"); + break; + case AGGR_CORE: + fprintf(output, "# time core cpus"); + if (!metric_only) + fprintf(output, " counts %*s events\n", unit_width, "unit"); + break; + case AGGR_NONE: + fprintf(output, "# time CPU "); + if (!metric_only) + fprintf(output, " counts %*s events\n", unit_width, "unit"); + break; + case AGGR_THREAD: + fprintf(output, "# time comm-pid"); + if (!metric_only) + fprintf(output, " counts %*s events\n", unit_width, "unit"); + break; + case AGGR_GLOBAL: + default: + fprintf(output, "# time"); + if (!metric_only) + fprintf(output, " counts %*s events\n", unit_width, "unit"); + case AGGR_UNSET: + break; + } + } + + if ((num_print_interval == 0 || config->interval_clear) && metric_only) + print_metric_headers(config, evlist, " ", true); + if (++num_print_interval == 25) + num_print_interval = 0; +} + +static void print_header(struct perf_stat_config *config, + struct target *_target, + int argc, const char **argv) +{ + FILE *output = config->output; + int i; + + fflush(stdout); + + if (!config->csv_output) { + fprintf(output, "\n"); + fprintf(output, " Performance counter stats for "); + if (_target->system_wide) + fprintf(output, "\'system wide"); + else if (_target->cpu_list) + fprintf(output, "\'CPU(s) %s", _target->cpu_list); + else if (!target__has_task(_target)) { + fprintf(output, "\'%s", argv ? argv[0] : "pipe"); + for (i = 1; argv && (i < argc); i++) + fprintf(output, " %s", argv[i]); + } else if (_target->pid) + fprintf(output, "process id \'%s", _target->pid); + else + fprintf(output, "thread id \'%s", _target->tid); + + fprintf(output, "\'"); + if (config->run_count > 1) + fprintf(output, " (%d runs)", config->run_count); + fprintf(output, ":\n\n"); + } +} + +static int get_precision(double num) +{ + if (num > 1) + return 0; + + return lround(ceil(-log10(num))); +} + +static void print_table(struct perf_stat_config *config, + FILE *output, int precision, double avg) +{ + char tmp[64]; + int idx, indent = 0; + + scnprintf(tmp, 64, " %17.*f", precision, avg); + while (tmp[indent] == ' ') + indent++; + + fprintf(output, "%*s# Table of individual measurements:\n", indent, ""); + + for (idx = 0; idx < config->run_count; idx++) { + double run = (double) config->walltime_run[idx] / NSEC_PER_SEC; + int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5); + + fprintf(output, " %17.*f (%+.*f) ", + precision, run, precision, run - avg); + + for (h = 0; h < n; h++) + fprintf(output, "#"); + + fprintf(output, "\n"); + } + + fprintf(output, "\n%*s# Final result:\n", indent, ""); +} + +static double timeval2double(struct timeval *t) +{ + return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC; +} + +static void print_footer(struct perf_stat_config *config) +{ + double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC; + FILE *output = config->output; + int n; + + if (!config->null_run) + fprintf(output, "\n"); + + if (config->run_count == 1) { + fprintf(output, " %17.9f seconds time elapsed", avg); + + if (config->ru_display) { + double ru_utime = timeval2double(&config->ru_data.ru_utime); + double ru_stime = timeval2double(&config->ru_data.ru_stime); + + fprintf(output, "\n\n"); + fprintf(output, " %17.9f seconds user\n", ru_utime); + fprintf(output, " %17.9f seconds sys\n", ru_stime); + } + } else { + double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC; + /* + * Display at most 2 more significant + * digits than the stddev inaccuracy. + */ + int precision = get_precision(sd) + 2; + + if (config->walltime_run_table) + print_table(config, output, precision, avg); + + fprintf(output, " %17.*f +- %.*f seconds time elapsed", + precision, avg, precision, sd); + + print_noise_pct(config, sd, avg); + } + fprintf(output, "\n\n"); + + if (config->print_free_counters_hint && + sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 && + n > 0) + fprintf(output, +"Some events weren't counted. Try disabling the NMI watchdog:\n" +" echo 0 > /proc/sys/kernel/nmi_watchdog\n" +" perf stat ...\n" +" echo 1 > /proc/sys/kernel/nmi_watchdog\n"); + + if (config->print_mixed_hw_group_error) + fprintf(output, + "The events in group usually have to be from " + "the same PMU. Try reorganizing the group.\n"); +} + +void +perf_evlist__print_counters(struct perf_evlist *evlist, + struct perf_stat_config *config, + struct target *_target, + struct timespec *ts, + int argc, const char **argv) +{ + bool metric_only = config->metric_only; + int interval = config->interval; + struct perf_evsel *counter; + char buf[64], *prefix = NULL; + + if (interval) + print_interval(config, evlist, prefix = buf, ts); + else + print_header(config, _target, argc, argv); + + if (metric_only) { + static int num_print_iv; + + if (num_print_iv == 0 && !interval) + print_metric_headers(config, evlist, prefix, false); + if (num_print_iv++ == 25) + num_print_iv = 0; + if (config->aggr_mode == AGGR_GLOBAL && prefix) + fprintf(config->output, "%s", prefix); + } + + switch (config->aggr_mode) { + case AGGR_CORE: + case AGGR_SOCKET: + print_aggr(config, evlist, prefix); + break; + case AGGR_THREAD: + evlist__for_each_entry(evlist, counter) { + if (is_duration_time(counter)) + continue; + print_aggr_thread(config, _target, counter, prefix); + } + break; + case AGGR_GLOBAL: + evlist__for_each_entry(evlist, counter) { + if (is_duration_time(counter)) + continue; + print_counter_aggr(config, counter, prefix); + } + if (metric_only) + fputc('\n', config->output); + break; + case AGGR_NONE: + if (metric_only) + print_no_aggr_metric(config, evlist, prefix); + else { + evlist__for_each_entry(evlist, counter) { + if (is_duration_time(counter)) + continue; + print_counter(config, counter, prefix); + } + } + break; + case AGGR_UNSET: + default: + break; + } + + if (!interval && !config->csv_output) + print_footer(config); + + fflush(config->output); +} diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 8d3354e21e19..3a13a6dc5a62 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -215,4 +215,10 @@ int perf_stat_synthesize_config(struct perf_stat_config *config, struct perf_evlist *evlist, perf_event__handler_t process, bool attrs); +void +perf_evlist__print_counters(struct perf_evlist *evlist, + struct perf_stat_config *config, + struct target *_target, + struct timespec *ts, + int argc, const char **argv); #endif From 3de3e8bbf302545ef9acebb9f900939ac5c3820f Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 27 Aug 2018 20:53:44 -0700 Subject: [PATCH 069/155] perf trace beauty: Alias 'umount' to 'umount2' Before: # perf trace -e *mount* umount /dev/mapper/fedora-home /s 11.576 ( 0.004 ms) umount/3138 umount2(arg0: 94501956754656, arg1: 0, arg2: 1, arg3: 140051050083104, arg4: 4, arg5: 94501956755136) = -1 EINVAL Invalid argument # After: # perf trace -e *mount* umount /s 0.000 ( 9.241 ms): umount/5251 umount2(name: 0x55f74a986480) = 0 Signed-off-by: Benjamin Peterson Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180828035344.31500-1-benjamin@python.org [ split from a larger patch ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 97ace635bed8..c106189f4066 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -825,6 +825,7 @@ static struct syscall_fmt { .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, { .name = "tkill", .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, + { .name = "umount2", .alias = "umount", }, { .name = "uname", .alias = "newuname", }, { .name = "unlinkat", .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, }, From 58094c48f4079cfc784f53a73caaa446db436389 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Mon, 27 Aug 2018 15:08:07 -0500 Subject: [PATCH 070/155] perf annotate: Handle arm64 move instructions Add default handler for non-jump instructions. This really only has an effect on instructions that compute a PC-relative address, such as 'adrp,' as seen in these couple of examples: BEFORE: adrp x0, ffff20000aa11000 AFTER: adrp x0, kallsyms_token_index+0xce000 BEFORE: adrp x23, ffff20000ae94000 <__per_cpu_load> AFTER: adrp x23, __per_cpu_load The implementation is identical to that of s390, but with a slight adjustment for objdump whitespace propagation (arm64 objdump puts spaces after commas, whereas s390's presumably doesn't). The mov__scnprintf() declaration is moved from s390's to arm64's instructions.c because arm64's gets included before s390's. Committer testing: Ran 'perf annotate --stdio2 > /tmp/{before,after}' no diff. Signed-off-by: Kim Phillips Tested-by: Arnaldo Carvalho de Melo Tested-by: Thomas Richter Cc: Alexander Shishkin Cc: Greg Kroah-Hartman Cc: Hendrik Brueckner Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-arm-kernel@lists.infradead.org Link: http://lkml.kernel.org/r/20180827150807.304110d2e9919a17c832ca48@arm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm64/annotate/instructions.c | 59 ++++++++++++++++++- tools/perf/arch/s390/annotate/instructions.c | 2 - 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c index 6688977e4ac7..76c6345a57d5 100644 --- a/tools/perf/arch/arm64/annotate/instructions.c +++ b/tools/perf/arch/arm64/annotate/instructions.c @@ -8,6 +8,63 @@ struct arm64_annotate { jump_insn; }; +static int arm64_mov__parse(struct arch *arch __maybe_unused, + struct ins_operands *ops, + struct map_symbol *ms __maybe_unused) +{ + char *s = strchr(ops->raw, ','), *target, *endptr; + + if (s == NULL) + return -1; + + *s = '\0'; + ops->source.raw = strdup(ops->raw); + *s = ','; + + if (ops->source.raw == NULL) + return -1; + + target = ++s; + ops->target.raw = strdup(target); + if (ops->target.raw == NULL) + goto out_free_source; + + ops->target.addr = strtoull(target, &endptr, 16); + if (endptr == target) + goto out_free_target; + + s = strchr(endptr, '<'); + if (s == NULL) + goto out_free_target; + endptr = strchr(s + 1, '>'); + if (endptr == NULL) + goto out_free_target; + + *endptr = '\0'; + *s = ' '; + ops->target.name = strdup(s); + *s = '<'; + *endptr = '>'; + if (ops->target.name == NULL) + goto out_free_target; + + return 0; + +out_free_target: + zfree(&ops->target.raw); +out_free_source: + zfree(&ops->source.raw); + return -1; +} + +static int mov__scnprintf(struct ins *ins, char *bf, size_t size, + struct ins_operands *ops); + +static struct ins_ops arm64_mov_ops = { + .parse = arm64_mov__parse, + .scnprintf = mov__scnprintf, +}; + static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name) { struct arm64_annotate *arm = arch->priv; @@ -21,7 +78,7 @@ static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const else if (!strcmp(name, "ret")) ops = &ret_ops; else - return NULL; + ops = &arm64_mov_ops; arch__associate_ins_ops(arch, name, ops); return ops; diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c index cee4e2f7c057..de0dd66dbb48 100644 --- a/tools/perf/arch/s390/annotate/instructions.c +++ b/tools/perf/arch/s390/annotate/instructions.c @@ -100,8 +100,6 @@ out_free_source: return -1; } -static int mov__scnprintf(struct ins *ins, char *bf, size_t size, - struct ins_operands *ops); static struct ins_ops s390_mov_ops = { .parse = s390_mov__parse, From 21d7eb9a24739cdc5ea19c90a79e5a585866ba35 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 3 Sep 2018 15:02:22 -0300 Subject: [PATCH 071/155] perf augmented_syscalls: Check probe_read_str() return separately Using a value returned from probe_read_str() to tell how many bytes to copy using perf_event_output() has issues in some older kernels, like 4.17.17-100.fc27.x86_64, so separate the bounds checking done on how many bytes to copy to a separate variable, so that the next patch has only what is being done to make the test pass on older BPF validators. For reference, see the discussion in this thread: https://www.spinics.net/lists/netdev/msg480099.html Cc: Adrian Hunter Cc: Daniel Borkmann Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Cc: Yonghong Song Link: https://lkml.kernel.org/n/tip-jtsapwibyxrnv1xjfsgzp0fj@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/examples/bpf/augmented_syscalls.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index 1419a9186937..0decbcfa8b90 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -33,9 +33,9 @@ struct syscall_exit_args { }; struct augmented_filename { - int size; - int reserved; - char value[256]; + unsigned int size; + int reserved; + char value[256]; }; #define augmented_filename_syscall(syscall) \ @@ -46,14 +46,15 @@ struct augmented_enter_##syscall##_args { \ int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \ { \ struct augmented_enter_##syscall##_args augmented_args = { .filename.reserved = 0, }; \ + unsigned int len = sizeof(augmented_args); \ probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \ augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, \ sizeof(augmented_args.filename.value), \ args->filename_ptr); \ + if (augmented_args.filename.size < sizeof(augmented_args.filename.value)) \ + len -= sizeof(augmented_args.filename.value) - augmented_args.filename.size; \ perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \ - &augmented_args, \ - (sizeof(augmented_args) - sizeof(augmented_args.filename.value) + \ - augmented_args.filename.size)); \ + &augmented_args, len); \ return 0; \ } \ int syscall_exit(syscall)(struct syscall_exit_args *args) \ From 7538d16397dfc72d8b61a99c32c592a75ae7f157 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 3 Sep 2018 15:18:37 -0300 Subject: [PATCH 072/155] perf augmented_syscalls: Avoid optimization to pass older BPF validators See https://www.spinics.net/lists/netdev/msg480099.html for the whole discussio, but to make the augmented_syscalls.c BPF program to get built and loaded successfully in a greater range of kernels, add an extra check. Related patch: a60dd35d2e39 ("bpf: change bpf_perf_event_output arg5 type to ARG_CONST_SIZE_OR_ZERO") That is in the kernel since v4.15, I couldn't figure why this is hitting me with 4.17.17, but adding the workaround discussed there makes this work with this fedora kernel and with 4.18.recent. Before: # uname -a Linux seventh 4.17.17-100.fc27.x86_64 #1 SMP Mon Aug 20 15:53:11 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c cat /etc/passwd > /dev/null libbpf: load bpf program failed: Permission denied libbpf: -- BEGIN DUMP LOG --- libbpf: 0: (bf) r6 = r1 1: (b7) r1 = 0 2: (7b) *(u64 *)(r10 -8) = r1 3: (7b) *(u64 *)(r10 -16) = r1 4: (7b) *(u64 *)(r10 -24) = r1 5: (7b) *(u64 *)(r10 -32) = r1 6: (7b) *(u64 *)(r10 -40) = r1 7: (7b) *(u64 *)(r10 -48) = r1 8: (7b) *(u64 *)(r10 -56) = r1 9: (7b) *(u64 *)(r10 -64) = r1 10: (7b) *(u64 *)(r10 -72) = r1 11: (7b) *(u64 *)(r10 -80) = r1 12: (7b) *(u64 *)(r10 -88) = r1 13: (7b) *(u64 *)(r10 -96) = r1 14: (7b) *(u64 *)(r10 -104) = r1 15: (7b) *(u64 *)(r10 -112) = r1 16: (7b) *(u64 *)(r10 -120) = r1 17: (7b) *(u64 *)(r10 -128) = r1 18: (7b) *(u64 *)(r10 -136) = r1 19: (7b) *(u64 *)(r10 -144) = r1 20: (7b) *(u64 *)(r10 -152) = r1 21: (7b) *(u64 *)(r10 -160) = r1 22: (7b) *(u64 *)(r10 -168) = r1 23: (7b) *(u64 *)(r10 -176) = r1 24: (7b) *(u64 *)(r10 -184) = r1 25: (7b) *(u64 *)(r10 -192) = r1 26: (7b) *(u64 *)(r10 -200) = r1 27: (7b) *(u64 *)(r10 -208) = r1 28: (7b) *(u64 *)(r10 -216) = r1 29: (7b) *(u64 *)(r10 -224) = r1 30: (7b) *(u64 *)(r10 -232) = r1 31: (7b) *(u64 *)(r10 -240) = r1 32: (7b) *(u64 *)(r10 -248) = r1 33: (7b) *(u64 *)(r10 -256) = r1 34: (7b) *(u64 *)(r10 -264) = r1 35: (7b) *(u64 *)(r10 -272) = r1 36: (7b) *(u64 *)(r10 -280) = r1 37: (7b) *(u64 *)(r10 -288) = r1 38: (7b) *(u64 *)(r10 -296) = r1 39: (7b) *(u64 *)(r10 -304) = r1 40: (7b) *(u64 *)(r10 -312) = r1 41: (bf) r7 = r10 42: (07) r7 += -312 43: (bf) r1 = r7 44: (b7) r2 = 48 45: (bf) r3 = r6 46: (85) call bpf_probe_read#4 47: (79) r3 = *(u64 *)(r6 +24) 48: (bf) r1 = r10 49: (07) r1 += -256 50: (b7) r8 = 256 51: (b7) r2 = 256 52: (85) call bpf_probe_read_str#45 53: (bf) r1 = r0 54: (67) r1 <<= 32 55: (77) r1 >>= 32 56: (bf) r5 = r0 57: (07) r5 += 56 58: (2d) if r8 > r1 goto pc+1 R0=inv(id=0) R1=inv(id=0,umin_value=256,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R5=inv(id=0) R6=ctx(id=0,off=0,imm=0) R7=fp-312,call_-1 R8=inv256 R10=fp0,call_-1 fp-264=0 59: (b7) r5 = 312 60: (63) *(u32 *)(r10 -264) = r0 61: (67) r5 <<= 32 62: (77) r5 >>= 32 63: (bf) r1 = r6 64: (18) r2 = 0xffff8b9120cc8500 66: (18) r3 = 0xffffffff 68: (bf) r4 = r7 69: (85) call bpf_perf_event_output#25 70: (b7) r0 = 0 71: (95) exit from 58 to 60: R0=inv(id=0) R1=inv(id=0,umax_value=255,var_off=(0x0; 0xff)) R5=inv(id=0) R6=ctx(id=0,off=0,imm=0) R7=fp-312,call_-1 R8=inv256 R10=fp0,call_-1 fp-264=0 60: (63) *(u32 *)(r10 -264) = r0 61: (67) r5 <<= 32 62: (77) r5 >>= 32 63: (bf) r1 = r6 64: (18) r2 = 0xffff8b9120cc8500 66: (18) r3 = 0xffffffff 68: (bf) r4 = r7 69: (85) call bpf_perf_event_output#25 R5 unbounded memory access, use 'var &= const' or 'if (var < const)' libbpf: -- END LOG -- libbpf: failed to load program 'syscalls:sys_enter_openat' libbpf: failed to load object 'tools/perf/examples/bpf/augmented_syscalls.c' bpf: load objects failed: err=-4007: (Kernel verifier blocks program loading) event syntax error: 'tools/perf/examples/bpf/augmented_syscalls.c' \___ Kernel verifier blocks program loading After: # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c cat /etc/passwd > /dev/null 0.000 cat/29249 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 0.008 cat/29249 syscalls:sys_exit_openat:0x3 0.021 cat/29249 openat(dfd: CWD, filename: /lib64/libc.so.6, flags: CLOEXEC) 0.025 cat/29249 syscalls:sys_exit_openat:0x3 0.180 cat/29249 open(filename: /usr/lib/locale/locale-archive, flags: CLOEXEC) 0.185 cat/29249 syscalls:sys_exit_open:0x3 0.242 cat/29249 openat(dfd: CWD, filename: /etc/passwd) 0.245 cat/29249 syscalls:sys_exit_openat:0x3 # It also works with a more recent kernel: # uname -a Linux jouet 4.18.0-00014-g4e67b2a5df5d #6 SMP Thu Aug 30 17:34:17 -03 2018 x86_64 x86_64 x86_64 GNU/Linux # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c cat /etc/passwd > /dev/null 0.000 cat/26451 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) 0.020 cat/26451 syscalls:sys_exit_openat:0x3 0.039 cat/26451 openat(dfd: CWD, filename: /lib64/libc.so.6, flags: CLOEXEC) 0.044 cat/26451 syscalls:sys_exit_openat:0x3 0.231 cat/26451 open(filename: /usr/lib/locale/locale-archive, flags: CLOEXEC) 0.238 cat/26451 syscalls:sys_exit_open:0x3 0.278 cat/26451 openat(dfd: CWD, filename: /etc/passwd) 0.282 cat/26451 syscalls:sys_exit_openat:0x3 # Cc: Adrian Hunter Cc: Daniel Borkmann Cc: David Ahern Cc: Gianluca Borello Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Cc: Yonghong Song Link: https://lkml.kernel.org/n/tip-wkpsivs1a9afwldbul46btbv@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/examples/bpf/augmented_syscalls.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c index 0decbcfa8b90..2ae44813ef2d 100644 --- a/tools/perf/examples/bpf/augmented_syscalls.c +++ b/tools/perf/examples/bpf/augmented_syscalls.c @@ -51,8 +51,10 @@ int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \ augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, \ sizeof(augmented_args.filename.value), \ args->filename_ptr); \ - if (augmented_args.filename.size < sizeof(augmented_args.filename.value)) \ + if (augmented_args.filename.size < sizeof(augmented_args.filename.value)) { \ len -= sizeof(augmented_args.filename.value) - augmented_args.filename.size; \ + len &= sizeof(augmented_args.filename.value) - 1; \ + } \ perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \ &augmented_args, len); \ return 0; \ From 8a041f86a83f9783ba23a423a2d5a51b48136850 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 3 Sep 2018 16:07:53 -0300 Subject: [PATCH 073/155] perf trace: Introduce syscall__augmented_args() method That will be used by trace__sys_enter when we start combining the augmented syscalls:sys_enter_FOO + syscalls:sys_exit_FOO. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-iiseo3s0qbf9i3rzn8k597bv@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index c106189f4066..12356deb6046 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1677,6 +1677,17 @@ static int trace__fprintf_sample(struct trace *trace, struct perf_evsel *evsel, return printed; } +static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sample, int *augmented_args_size) +{ + void *augmented_args = NULL; + + *augmented_args_size = sample->raw_size - sc->args_size; + if (*augmented_args_size > 0) + augmented_args = sample->raw_data + sc->args_size; + + return augmented_args; +} + static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, union perf_event *event __maybe_unused, struct perf_sample *sample) @@ -1762,10 +1773,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evse goto out_put; args = perf_evsel__sc_tp_ptr(evsel, args, sample); - augmented_args_size = sample->raw_size - sc->args_size; - if (augmented_args_size > 0) - augmented_args = sample->raw_data + sc->args_size; - + augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size); syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread); fprintf(trace->output, "%s", msg); err = 0; From db2da3f85cd6314321b6a9441a5af8841c93394d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 3 Sep 2018 16:24:09 -0300 Subject: [PATCH 074/155] perf trace: Setup augmented_args in the raw_syscalls:sys_enter handler Without using something to augment the raw_syscalls:sys_enter tracepoint payload with the pointer contents, this will work just like before, i.e. the augmented_args arg will be NULL and the augmented_args_size will be 0. This just paves the way for the next cset where we will associate the trace__sys_enter tracepoint handler with the augmented "bpf-output" event named "__augmented_args__". Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-p8uvt2a6ug3uwlhja3cno4la@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 12356deb6046..2b99a02355cf 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1697,6 +1697,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, size_t printed = 0; struct thread *thread; int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1; + int augmented_args_size = 0; + void *augmented_args = NULL; struct syscall *sc = trace__syscall_info(trace, evsel, id); struct thread_trace *ttrace; @@ -1720,13 +1722,24 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) trace__printf_interrupted_entry(trace); - + /* + * If this is raw_syscalls.sys_enter, then it always comes with the 6 possible + * arguments, even if the syscall being handled, say "openat", uses only 4 arguments + * this breaks syscall__augmented_args() check for augmented args, as we calculate + * syscall->args_size using each syscalls:sys_enter_NAME tracefs format file, + * so when handling, say the openat syscall, we end up getting 6 args for the + * raw_syscalls:sys_enter event, when we expected just 4, we end up mistakenly + * thinking that the extra 2 u64 args are the augmented filename, so just check + * here and avoid using augmented syscalls when the evsel is the raw_syscalls one. + */ + if (evsel != trace->syscalls.events.sys_enter) + augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size); ttrace->entry_time = sample->time; msg = ttrace->entry_str; printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name); printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed, - args, NULL, 0, trace, thread); + args, augmented_args, augmented_args_size, trace, thread); if (sc->is_exit) { if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) { From b1a9e2535e20cdd6cd14eec8128278bc5d97843c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 3 Sep 2018 16:29:39 -0300 Subject: [PATCH 075/155] perf trace: Use the raw_syscalls:sys_enter for the augmented syscalls Now we combine what comes from the "bpf-output" event, i.e. what is added in the augmented_syscalls.c BPF program via the __augmented_syscalls__ BPF map, i.e. the payload we get with raw_syscalls:sys_enter tracepoints plus the pointer contents, right after that payload, with the raw_syscall:sys_exit also added, without augmentation, in the augmented_syscalls.c program. The end result is that for the hooked syscalls, we get strace like output with pointer expansion, something that wasn't possible before with just raw_syscalls:sys_enter + raw_syscalls:sys_exit. E.g.: # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c ping -c 2 ::1 0.000 ( 0.008 ms): ping/19573 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) = 3 0.036 ( 0.006 ms): ping/19573 openat(dfd: CWD, filename: /lib64/libcap.so.2, flags: CLOEXEC) = 3 0.070 ( 0.004 ms): ping/19573 openat(dfd: CWD, filename: /lib64/libidn.so.11, flags: CLOEXEC) = 3 0.095 ( 0.004 ms): ping/19573 openat(dfd: CWD, filename: /lib64/libcrypto.so.1.1, flags: CLOEXEC) = 3 0.127 ( 0.004 ms): ping/19573 openat(dfd: CWD, filename: /lib64/libresolv.so.2, flags: CLOEXEC) = 3 0.156 ( 0.004 ms): ping/19573 openat(dfd: CWD, filename: /lib64/libm.so.6, flags: CLOEXEC) = 3 0.181 ( 0.004 ms): ping/19573 openat(dfd: CWD, filename: /lib64/libc.so.6, flags: CLOEXEC) = 3 0.212 ( 0.004 ms): ping/19573 openat(dfd: CWD, filename: /lib64/libz.so.1, flags: CLOEXEC) = 3 0.242 ( 0.004 ms): ping/19573 openat(dfd: CWD, filename: /lib64/libdl.so.2, flags: CLOEXEC) = 3 0.266 ( 0.003 ms): ping/19573 openat(dfd: CWD, filename: /lib64/libpthread.so.0, flags: CLOEXEC) = 3 0.709 ( 0.006 ms): ping/19573 open(filename: /usr/lib/locale/locale-archive, flags: CLOEXEC) = 3 PING ::1(::1) 56 data bytes 1.133 ( 0.011 ms): ping/19573 connect(fd: 5, uservaddr: { .family: INET6, port: 1025, addr: ::1 }, addrlen: 28) = 0 64 bytes from ::1: icmp_seq=1 ttl=64 time=0.033 ms 1.234 ( 0.036 ms): ping/19573 sendto(fd: 4, buff: 0x555e5b975720, len: 64, addr: { .family: INET6, port: 58, addr: ::1 }, addr_len: 28) = 64 64 bytes from ::1: icmp_seq=2 ttl=64 time=0.120 ms --- ::1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1000ms rtt min/avg/max/mdev = 0.033/0.076/0.120/0.044 ms 1002.060 ( 0.129 ms): ping/19573 sendto(fd: 4, buff: 0x555e5b975720, len: 64, flags: CONFIRM, addr: { .family: INET6, port: 58, addr: ::1 }, addr_len: 28) = 64 # # perf trace -e tools/perf/examples/bpf/augmented_syscalls.c cat tools/perf/examples/bpf/hello.c #include int syscall_enter(openat)(void *args) { puts("Hello, world\n"); return 0; } license(GPL); 0.000 ( 0.008 ms): cat/20054 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) = 3 0.020 ( 0.005 ms): cat/20054 openat(dfd: CWD, filename: /lib64/libc.so.6, flags: CLOEXEC) = 3 0.176 ( 0.011 ms): cat/20054 open(filename: /usr/lib/locale/locale-archive, flags: CLOEXEC) = 3 0.243 ( 0.006 ms): cat/20054 openat(dfd: CWD, filename: tools/perf/examples/bpf/hello.c) = 3 # Now to think how to hook on all syscalls, fallbacking to the non-augmented raw_syscalls:sys_enter payload. Probably the best way is to use a BPF_MAP_TYPE_PROG_ARRAY just like samples/bpf/tracex5_kern.c does. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-nlt60y69o26xi59z5vtpdrj5@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 41 +++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 2b99a02355cf..7ce277d22a91 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -288,6 +288,13 @@ static int perf_evsel__init_augmented_syscall_tp_args(struct perf_evsel *evsel) return __tp_field__init_ptr(&sc->args, sc->id.offset + sizeof(u64)); } +static int perf_evsel__init_augmented_syscall_tp_ret(struct perf_evsel *evsel) +{ + struct syscall_tp *sc = evsel->priv; + + return __tp_field__init_uint(&sc->ret, sizeof(u64), sc->id.offset + sizeof(u64), evsel->needs_swap); +} + static int perf_evsel__init_raw_syscall_tp(struct perf_evsel *evsel, void *handler) { evsel->priv = malloc(sizeof(struct syscall_tp)); @@ -3346,12 +3353,8 @@ int cmd_trace(int argc, const char **argv) goto out; } - if (evsel) { - if (perf_evsel__init_augmented_syscall_tp(evsel) || - perf_evsel__init_augmented_syscall_tp_args(evsel)) - goto out; + if (evsel) trace.syscalls.events.augmented = evsel; - } err = bpf__setup_stdout(trace.evlist); if (err) { @@ -3396,6 +3399,34 @@ int cmd_trace(int argc, const char **argv) } } + /* + * If we are augmenting syscalls, then combine what we put in the + * __augmented_syscalls__ BPF map with what is in the + * syscalls:sys_exit_FOO tracepoints, i.e. just like we do without BPF, + * combining raw_syscalls:sys_enter with raw_syscalls:sys_exit. + * + * We'll switch to look at two BPF maps, one for sys_enter and the + * other for sys_exit when we start augmenting the sys_exit paths with + * buffers that are being copied from kernel to userspace, think 'read' + * syscall. + */ + if (trace.syscalls.events.augmented) { + evsel = trace.syscalls.events.augmented; + + if (perf_evsel__init_augmented_syscall_tp(evsel) || + perf_evsel__init_augmented_syscall_tp_args(evsel)) + goto out; + evsel->handler = trace__sys_enter; + + evlist__for_each_entry(trace.evlist, evsel) { + if (strstarts(perf_evsel__name(evsel), "syscalls:sys_exit_")) { + perf_evsel__init_augmented_syscall_tp(evsel); + perf_evsel__init_augmented_syscall_tp_ret(evsel); + evsel->handler = trace__sys_exit; + } + } + } + if ((argc >= 1) && (strcmp(argv[0], "record") == 0)) return trace__record(&trace, argc-1, &argv[1]); From d8e75a110df7e3318990c9fb207ae0aa7812895a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 4 Sep 2018 10:43:07 -0300 Subject: [PATCH 076/155] perf map: Turn some pr_warning() to pr_debug() Annoying when using it with --stdio/--stdio2, so just turn them debug, we can get those using -v. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-t3684lkugnf1w4lwcmpj9ivm@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/map.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 36d0763311ef..3f07a587c8e6 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -320,12 +320,11 @@ int map__load(struct map *map) build_id__sprintf(map->dso->build_id, sizeof(map->dso->build_id), sbuild_id); - pr_warning("%s with build id %s not found", - name, sbuild_id); + pr_debug("%s with build id %s not found", name, sbuild_id); } else - pr_warning("Failed to open %s", name); + pr_debug("Failed to open %s", name); - pr_warning(", continuing without symbols\n"); + pr_debug(", continuing without symbols\n"); return -1; } else if (nr == 0) { #ifdef HAVE_LIBELF_SUPPORT @@ -334,12 +333,11 @@ int map__load(struct map *map) if (len > sizeof(DSO__DELETED) && strcmp(name + real_len + 1, DSO__DELETED) == 0) { - pr_warning("%.*s was updated (is prelink enabled?). " + pr_debug("%.*s was updated (is prelink enabled?). " "Restart the long running apps that use it!\n", (int)real_len, name); } else { - pr_warning("no symbols found in %s, maybe install " - "a debug package?\n", name); + pr_debug("no symbols found in %s, maybe install a debug package?\n", name); } #endif return -1; @@ -701,8 +699,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp if (verbose >= 2) { if (use_browser) { - pr_warning("overlapping maps in %s " - "(disable tui for more info)\n", + pr_debug("overlapping maps in %s (disable tui for more info)\n", map->dso->name); } else { fputs("overlapping maps:\n", fp); From 1632936480a53d85ef3012cd9f290e247251cbb9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 5 Sep 2018 10:47:56 -0300 Subject: [PATCH 077/155] perf tests: Fix record+probe_libc_inet_pton.sh without ping's debuginfo When we don't have the iputils-debuginfo package installed, i.e. when we don't have the DWARF information needed to resolve ping's samples, we end up failing this 'perf test' entry: # perf test ping 62: probe libc's inet_pton & backtrace it with ping : Ok # rpm -e iputils-debuginfo # perf test ping 62: probe libc's inet_pton & backtrace it with ping : FAILED! # Fix it to accept "[unknown]" where the symbol + offset, when resolved, is expected. I think this will fail in the other arches as well, but since I can't test now, I'm leaving s390x and ppc cases as-is. Cc: Adrian Hunter Cc: Alexander Shishkin Cc: David Ahern Cc: Hendrik Brueckner Cc: Jiri Olsa Cc: Kim Phillips Cc: Michael Petlan Cc: Namhyung Kim Cc: Naveen N. Rao Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Sandipan Das Cc: Sukadev Bhattiprolu Cc: Thomas Richter Cc: Wang Nan Fixes: 7903a7086723 ("perf script: Show symbol offsets by default") Link: https://lkml.kernel.org/n/tip-hnizqwqrs03vcq1b74yao0f6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/record+probe_libc_inet_pton.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh index 3013ac8f83d0..cab7b0aea6ea 100755 --- a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh +++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh @@ -48,7 +48,7 @@ trace_libc_inet_pton_backtrace() { *) eventattr='max-stack=3' echo "getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc\)$" >> $expected - echo ".*\+0x[[:xdigit:]]+[[:space:]]\(.*/bin/ping.*\)$" >> $expected + echo ".*(\+0x[[:xdigit:]]+|\[unknown\])[[:space:]]\(.*/bin/ping.*\)$" >> $expected ;; esac From 2766d2ee960c52adc415931130dd6910158dd04d Mon Sep 17 00:00:00 2001 From: Zubin Mithra Date: Fri, 10 Aug 2018 08:43:14 -0700 Subject: [PATCH 078/155] perf/x86: Add __ro_after_init annotations x86_pmu_{format,events,attr,caps}_group is written to in init_hw_perf_events and not modified after. This makes them suitable candidates for annotating as __ro_after_init. Signed-off-by: Zubin Mithra Reviewed-by: Kees Cook Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: acme@kernel.org Cc: alexander.shishkin@linux.intel.com Cc: groeck@chromium.org Link: http://lkml.kernel.org/r/20180810154314.96710-1-zsm@chromium.org Signed-off-by: Ingo Molnar --- arch/x86/events/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index dfb2f7c0d019..7a6fb9b2bec5 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -1584,7 +1584,7 @@ static void __init pmu_check_apic(void) } -static struct attribute_group x86_pmu_format_group = { +static struct attribute_group x86_pmu_format_group __ro_after_init = { .name = "format", .attrs = NULL, }; @@ -1715,7 +1715,7 @@ static struct attribute *events_attr[] = { NULL, }; -static struct attribute_group x86_pmu_events_group = { +static struct attribute_group x86_pmu_events_group __ro_after_init = { .name = "events", .attrs = events_attr, }; @@ -2230,7 +2230,7 @@ static struct attribute *x86_pmu_attrs[] = { NULL, }; -static struct attribute_group x86_pmu_attr_group = { +static struct attribute_group x86_pmu_attr_group __ro_after_init = { .attrs = x86_pmu_attrs, }; @@ -2248,7 +2248,7 @@ static struct attribute *x86_pmu_caps_attrs[] = { NULL }; -static struct attribute_group x86_pmu_caps_group = { +static struct attribute_group x86_pmu_caps_group __ro_after_init = { .name = "caps", .attrs = x86_pmu_caps_attrs, }; From d0555fc78fdba5646a460e83bd2d8249c539bb89 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 11 Sep 2018 19:19:14 +0900 Subject: [PATCH 079/155] kprobes: Remove pointless BUG_ON() from disarming process All aggr_probes at this line are already disarmed by disable_kprobe() or checked by kprobe_disarmed(). So this BUG_ON() is pointless, remove it. Signed-off-by: Masami Hiramatsu Cc: Anil S Keshavamurthy Cc: David S . Miller Cc: Linus Torvalds Cc: Naveen N . Rao Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/153666115463.21306.8799008438116029806.stgit@devbox Signed-off-by: Ingo Molnar --- kernel/kprobes.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index ab257be4d924..d1edd8d5641e 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1704,7 +1704,6 @@ noclean: return 0; disarmed: - BUG_ON(!kprobe_disarmed(ap)); hlist_del_rcu(&ap->hlist); return 0; } From c72e6742f62d7bb82a77a41ca53940cb8f73e60f Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 11 Sep 2018 19:19:43 +0900 Subject: [PATCH 080/155] kprobes: Remove pointless BUG_ON() from add_new_kprobe() Before calling add_new_kprobe(), aggr_probe's GONE flag and kprobe GONE flag are cleared. We don't need to worry about that flag at this point. Signed-off-by: Masami Hiramatsu Cc: Anil S Keshavamurthy Cc: David S . Miller Cc: Linus Torvalds Cc: Naveen N . Rao Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/153666118298.21306.4915366706875652652.stgit@devbox Signed-off-by: Ingo Molnar --- kernel/kprobes.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index d1edd8d5641e..231569e1e2c8 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1259,8 +1259,6 @@ NOKPROBE_SYMBOL(cleanup_rp_inst); /* Add the new probe to ap->list */ static int add_new_kprobe(struct kprobe *ap, struct kprobe *p) { - BUG_ON(kprobe_gone(ap) || kprobe_gone(p)); - if (p->post_handler) unoptimize_kprobe(ap, true); /* Fall back to normal kprobe */ From a6d18e65dff2b73ceeb187c598b48898e36ad7b1 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 11 Sep 2018 19:20:11 +0900 Subject: [PATCH 081/155] kprobes: Remove pointless BUG_ON() from reuse_unused_kprobe() Since reuse_unused_kprobe() is called when the given kprobe is unused, checking it inside again with BUG_ON() is pointless. Remove it. Signed-off-by: Masami Hiramatsu Cc: Anil S Keshavamurthy Cc: David S . Miller Cc: Linus Torvalds Cc: Naveen N . Rao Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/153666121154.21306.17540752948574483565.stgit@devbox Signed-off-by: Ingo Molnar --- kernel/kprobes.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 231569e1e2c8..277a6cbe83db 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -704,7 +704,6 @@ static void reuse_unused_kprobe(struct kprobe *ap) { struct optimized_kprobe *op; - BUG_ON(!kprobe_unused(ap)); /* * Unused kprobe MUST be on the way of delayed unoptimizing (means * there is still a relative jump) and disabled. From 819319fc93461c07b9cdb3064f154bd8cfd48172 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 11 Sep 2018 19:20:40 +0900 Subject: [PATCH 082/155] kprobes: Return error if we fail to reuse kprobe instead of BUG_ON() Make reuse_unused_kprobe() to return error code if it fails to reuse unused kprobe for optprobe instead of calling BUG_ON(). Signed-off-by: Masami Hiramatsu Cc: Anil S Keshavamurthy Cc: David S . Miller Cc: Linus Torvalds Cc: Naveen N . Rao Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/153666124040.21306.14150398706331307654.stgit@devbox Signed-off-by: Ingo Molnar --- kernel/kprobes.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 277a6cbe83db..63c342e5e6c3 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -700,9 +700,10 @@ static void unoptimize_kprobe(struct kprobe *p, bool force) } /* Cancel unoptimizing for reusing */ -static void reuse_unused_kprobe(struct kprobe *ap) +static int reuse_unused_kprobe(struct kprobe *ap) { struct optimized_kprobe *op; + int ret; /* * Unused kprobe MUST be on the way of delayed unoptimizing (means @@ -713,8 +714,12 @@ static void reuse_unused_kprobe(struct kprobe *ap) /* Enable the probe again */ ap->flags &= ~KPROBE_FLAG_DISABLED; /* Optimize it again (remove from op->list) */ - BUG_ON(!kprobe_optready(ap)); + ret = kprobe_optready(ap); + if (ret) + return ret; + optimize_kprobe(ap); + return 0; } /* Remove optimized instructions */ @@ -939,11 +944,16 @@ static void __disarm_kprobe(struct kprobe *p, bool reopt) #define kprobe_disarmed(p) kprobe_disabled(p) #define wait_for_kprobe_optimizer() do {} while (0) -/* There should be no unused kprobes can be reused without optimization */ -static void reuse_unused_kprobe(struct kprobe *ap) +static int reuse_unused_kprobe(struct kprobe *ap) { + /* + * If the optimized kprobe is NOT supported, the aggr kprobe is + * released at the same time that the last aggregated kprobe is + * unregistered. + * Thus there should be no chance to reuse unused kprobe. + */ printk(KERN_ERR "Error: There should be no unused kprobe here.\n"); - BUG_ON(kprobe_unused(ap)); + return -EINVAL; } static void free_aggr_kprobe(struct kprobe *p) @@ -1315,9 +1325,12 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p) goto out; } init_aggr_kprobe(ap, orig_p); - } else if (kprobe_unused(ap)) + } else if (kprobe_unused(ap)) { /* This probe is going to die. Rescue it */ - reuse_unused_kprobe(ap); + ret = reuse_unused_kprobe(ap); + if (ret) + goto out; + } if (kprobe_gone(ap)) { /* From cbdd96f5586151e48317d90a403941ec23f12660 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 11 Sep 2018 19:21:09 +0900 Subject: [PATCH 083/155] kprobes: Don't call BUG_ON() if there is a kprobe in use on free list Instead of calling BUG_ON(), if we find a kprobe in use on free kprobe list, just remove it from the list and keep it on kprobe hash list as same as other in-use kprobes. Signed-off-by: Masami Hiramatsu Cc: Anil S Keshavamurthy Cc: David S . Miller Cc: Linus Torvalds Cc: Naveen N . Rao Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/153666126882.21306.10738207224288507996.stgit@devbox Signed-off-by: Ingo Molnar --- kernel/kprobes.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 63c342e5e6c3..90e98e233647 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -546,8 +546,14 @@ static void do_free_cleaned_kprobes(void) struct optimized_kprobe *op, *tmp; list_for_each_entry_safe(op, tmp, &freeing_list, list) { - BUG_ON(!kprobe_unused(&op->kp)); list_del_init(&op->list); + if (WARN_ON_ONCE(!kprobe_unused(&op->kp))) { + /* + * This must not happen, but if there is a kprobe + * still in use, keep it on kprobes hash list. + */ + continue; + } free_aggr_kprobe(&op->kp); } } From 49e73246cbe6fe0df9cae2db87f31cdc3a0b2b61 Mon Sep 17 00:00:00 2001 From: Zubin Mithra Date: Wed, 12 Sep 2018 09:45:10 -0700 Subject: [PATCH 084/155] perf/x86/intel/pt: Annotate 'pt_cap_group' with __ro_after_init 'pt_cap_group' is written to in pt_pmu_hw_init() and not modified after. This makes it a suitable candidate for annotating as __ro_after_init. Signed-off-by: Zubin Mithra Reviewed-by: Guenter Roeck Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: keescook@chromium.org Link: http://lkml.kernel.org/r/20180912164510.23444-1-zsm@chromium.org Signed-off-by: Ingo Molnar --- arch/x86/events/intel/pt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c index 8d016ce5b80d..3a0aa83cbd07 100644 --- a/arch/x86/events/intel/pt.c +++ b/arch/x86/events/intel/pt.c @@ -95,7 +95,7 @@ static ssize_t pt_cap_show(struct device *cdev, return snprintf(buf, PAGE_SIZE, "%x\n", pt_cap_get(cap)); } -static struct attribute_group pt_cap_group = { +static struct attribute_group pt_cap_group __ro_after_init = { .name = "caps", }; From 1627314fb54a33ebd23bd08f2e215eaed0f44712 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Wed, 4 Apr 2018 17:53:23 +0300 Subject: [PATCH 085/155] perf: Suppress AUX/OVERWRITE records It has been pointed out to me many times that it is useful to be able to switch off AUX records to save the bandwidth for records that actually matter, for example, in AUX overwrite mode. The usefulness of PERF_RECORD_AUX is in some of its flags, like the TRUNCATED flag that tells the decoder where exactly gaps in the trace are. The OVERWRITE flag, on the other hand will be set on every single record in overwrite mode. However, a PERF_RECORD_AUX[flags=OVERWRITE] is generated on every target task's sched_out, which over time adds up to a lot of useless information. If any folks out there have userspace that depends on a constant stream of OVERWRITE records for a good reason, they'll have to let us know. Signed-off-by: Alexander Shishkin Acked-by: Ingo Molnar Acked-by: Peter Zijlstra Acked-by: Will Deacon Cc: Adrian Hunter Cc: Markus T Metzger Link: http://lkml.kernel.org/r/20180404145323.28651-1-alexander.shishkin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- kernel/events/ring_buffer.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 5d3cf407e374..4a9937076331 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -459,10 +459,20 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size) if (size || handle->aux_flags) { /* * Only send RECORD_AUX if we have something useful to communicate + * + * Note: the OVERWRITE records by themselves are not considered + * useful, as they don't communicate any *new* information, + * aside from the short-lived offset, that becomes history at + * the next event sched-in and therefore isn't useful. + * The userspace that needs to copy out AUX data in overwrite + * mode should know to use user_page::aux_head for the actual + * offset. So, from now on we don't output AUX records that + * have *only* OVERWRITE flag set. */ - perf_event_aux_event(handle->event, aux_head, size, - handle->aux_flags); + if (handle->aux_flags & ~(u64)PERF_AUX_FLAG_OVERWRITE) + perf_event_aux_event(handle->event, aux_head, size, + handle->aux_flags); } rb->user_page->aux_head = rb->aux_head; From 2e85d5979e8d2866db6185de231461b21159ef6f Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Wed, 12 Sep 2018 11:42:29 +0530 Subject: [PATCH 086/155] perf test: Add watchpoint test We don't have a 'perf test' entry available to test the watchpoint functionality. Add a simple set of tests: - Read only watchpoint - Write only watchpoint - Read / Write watchpoint - Runtime watchpoint modification Ex.: on powerpc: $ sudo perf test 22 22: Watchpoint : 22.1: Read Only Watchpoint : Ok 22.2: Write Only Watchpoint : Ok 22.3: Read / Write Watchpoint : Ok 22.4: Modify Watchpoint : Ok Signed-off-by: Ravi Bangoria Acked-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Hendrik Brueckner Cc: Kate Stewart Cc: Kim Phillips Cc: Namhyung Kim Cc: Naveen N. Rao Cc: Sandipan Das Cc: Thomas Gleixner Cc: Thomas Richter Link: http://lkml.kernel.org/r/20180912061229.22832-1-ravi.bangoria@linux.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 9 ++ tools/perf/tests/tests.h | 3 + tools/perf/tests/wp.c | 229 ++++++++++++++++++++++++++++++++ 4 files changed, 242 insertions(+) create mode 100644 tools/perf/tests/wp.c diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index 6c108fa79ae3..0b2b8305c965 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -21,6 +21,7 @@ perf-y += python-use.o perf-y += bp_signal.o perf-y += bp_signal_overflow.o perf-y += bp_account.o +perf-y += wp.o perf-y += task-exit.o perf-y += sw-clock.o perf-y += mmap-thread-lookup.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index d7a5e1b9aa6f..54ca7d87236f 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -120,6 +120,15 @@ static struct test generic_tests[] = { .func = test__bp_accounting, .is_supported = test__bp_signal_is_supported, }, + { + .desc = "Watchpoint", + .func = test__wp, + .subtest = { + .skip_if_fail = false, + .get_nr = test__wp_subtest_get_nr, + .get_desc = test__wp_subtest_get_desc, + }, + }, { .desc = "Number of exit events of a simple workload", .func = test__task_exit, diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index a9760e790563..8e26a4148f30 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -59,6 +59,9 @@ int test__python_use(struct test *test, int subtest); int test__bp_signal(struct test *test, int subtest); int test__bp_signal_overflow(struct test *test, int subtest); int test__bp_accounting(struct test *test, int subtest); +int test__wp(struct test *test, int subtest); +const char *test__wp_subtest_get_desc(int subtest); +int test__wp_subtest_get_nr(void); int test__task_exit(struct test *test, int subtest); int test__mem(struct test *test, int subtest); int test__sw_clock_freq(struct test *test, int subtest); diff --git a/tools/perf/tests/wp.c b/tools/perf/tests/wp.c new file mode 100644 index 000000000000..017a99317f94 --- /dev/null +++ b/tools/perf/tests/wp.c @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include "tests.h" +#include "debug.h" +#include "cloexec.h" + +#define WP_TEST_ASSERT_VAL(fd, text, val) \ +do { \ + long long count; \ + wp_read(fd, &count, sizeof(long long)); \ + TEST_ASSERT_VAL(text, count == val); \ +} while (0) + +volatile u64 data1; +volatile u8 data2[3]; + +static int wp_read(int fd, long long *count, int size) +{ + int ret = read(fd, count, size); + + if (ret != size) { + pr_debug("failed to read: %d\n", ret); + return -1; + } + return 0; +} + +static void get__perf_event_attr(struct perf_event_attr *attr, int wp_type, + void *wp_addr, unsigned long wp_len) +{ + memset(attr, 0, sizeof(struct perf_event_attr)); + attr->type = PERF_TYPE_BREAKPOINT; + attr->size = sizeof(struct perf_event_attr); + attr->config = 0; + attr->bp_type = wp_type; + attr->bp_addr = (unsigned long)wp_addr; + attr->bp_len = wp_len; + attr->sample_period = 1; + attr->sample_type = PERF_SAMPLE_IP; + attr->exclude_kernel = 1; + attr->exclude_hv = 1; +} + +static int __event(int wp_type, void *wp_addr, unsigned long wp_len) +{ + int fd; + struct perf_event_attr attr; + + get__perf_event_attr(&attr, wp_type, wp_addr, wp_len); + fd = sys_perf_event_open(&attr, 0, -1, -1, + perf_event_open_cloexec_flag()); + if (fd < 0) + pr_debug("failed opening event %x\n", attr.bp_type); + + return fd; +} + +static int wp_ro_test(void) +{ + int fd; + unsigned long tmp, tmp1 = rand(); + + fd = __event(HW_BREAKPOINT_R, (void *)&data1, sizeof(data1)); + if (fd < 0) + return -1; + + tmp = data1; + WP_TEST_ASSERT_VAL(fd, "RO watchpoint", 1); + + data1 = tmp1 + tmp; + WP_TEST_ASSERT_VAL(fd, "RO watchpoint", 1); + + close(fd); + return 0; +} + +static int wp_wo_test(void) +{ + int fd; + unsigned long tmp, tmp1 = rand(); + + fd = __event(HW_BREAKPOINT_W, (void *)&data1, sizeof(data1)); + if (fd < 0) + return -1; + + tmp = data1; + WP_TEST_ASSERT_VAL(fd, "WO watchpoint", 0); + + data1 = tmp1 + tmp; + WP_TEST_ASSERT_VAL(fd, "WO watchpoint", 1); + + close(fd); + return 0; +} + +static int wp_rw_test(void) +{ + int fd; + unsigned long tmp, tmp1 = rand(); + + fd = __event(HW_BREAKPOINT_R | HW_BREAKPOINT_W, (void *)&data1, + sizeof(data1)); + if (fd < 0) + return -1; + + tmp = data1; + WP_TEST_ASSERT_VAL(fd, "RW watchpoint", 1); + + data1 = tmp1 + tmp; + WP_TEST_ASSERT_VAL(fd, "RW watchpoint", 2); + + close(fd); + return 0; +} + +static int wp_modify_test(void) +{ + int fd, ret; + unsigned long tmp = rand(); + struct perf_event_attr new_attr; + + fd = __event(HW_BREAKPOINT_W, (void *)&data1, sizeof(data1)); + if (fd < 0) + return -1; + + data1 = tmp; + WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 1); + + /* Modify watchpoint with disabled = 1 */ + get__perf_event_attr(&new_attr, HW_BREAKPOINT_W, (void *)&data2[0], + sizeof(u8) * 2); + new_attr.disabled = 1; + ret = ioctl(fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr); + if (ret < 0) { + pr_debug("ioctl(PERF_EVENT_IOC_MODIFY_ATTRIBUTES) failed\n"); + close(fd); + return ret; + } + + data2[1] = tmp; /* Not Counted */ + WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 1); + + /* Enable the event */ + ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); + if (ret < 0) { + pr_debug("Failed to enable event\n"); + close(fd); + return ret; + } + + data2[1] = tmp; /* Counted */ + WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 2); + + data2[2] = tmp; /* Not Counted */ + WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 2); + + close(fd); + return 0; +} + +static bool wp_ro_supported(void) +{ +#if defined (__x86_64__) || defined (__i386__) + return false; +#else + return true; +#endif +} + +static void wp_ro_skip_msg(void) +{ +#if defined (__x86_64__) || defined (__i386__) + pr_debug("Hardware does not support read only watchpoints.\n"); +#endif +} + +static struct { + const char *desc; + int (*target_func)(void); + bool (*is_supported)(void); + void (*skip_msg)(void); +} wp_testcase_table[] = { + { + .desc = "Read Only Watchpoint", + .target_func = &wp_ro_test, + .is_supported = &wp_ro_supported, + .skip_msg = &wp_ro_skip_msg, + }, + { + .desc = "Write Only Watchpoint", + .target_func = &wp_wo_test, + }, + { + .desc = "Read / Write Watchpoint", + .target_func = &wp_rw_test, + }, + { + .desc = "Modify Watchpoint", + .target_func = &wp_modify_test, + }, +}; + +int test__wp_subtest_get_nr(void) +{ + return (int)ARRAY_SIZE(wp_testcase_table); +} + +const char *test__wp_subtest_get_desc(int i) +{ + if (i < 0 || i >= (int)ARRAY_SIZE(wp_testcase_table)) + return NULL; + return wp_testcase_table[i].desc; +} + +int test__wp(struct test *test __maybe_unused, int i) +{ + if (i < 0 || i >= (int)ARRAY_SIZE(wp_testcase_table)) + return TEST_FAIL; + + if (wp_testcase_table[i].is_supported && + !wp_testcase_table[i].is_supported()) { + wp_testcase_table[i].skip_msg(); + return TEST_SKIP; + } + + return !wp_testcase_table[i].target_func() ? TEST_OK : TEST_FAIL; +} From d5ceb62b36545b597e89adb5eb778c3e15431c10 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 7 Sep 2018 12:24:54 +0200 Subject: [PATCH 087/155] perf ordered_events: Add 'struct ordered_events_buffer' layer When ordering events, we use preallocated buffers to store separate events. Those buffers currently don't have their own struct, but since they are basically an array of 'struct ordered_event' objects, we use the first event to hold buffers data - list head, that holds all buffers together: struct ordered_events { ... struct ordered_event *buffer; ... }; struct ordered_event { u64 timestamp; u64 file_offset; union perf_event *event; struct list_head list; }; This is quite convoluted and error prone as demonstrated by free-ing issue discovered and fixed by Stephane in here [1]. This patch adds the 'struct ordered_events_buffer' object, that holds the buffer data and frees it up properly. [1] - https://marc.info/?l=linux-kernel&m=153376761329335&w=2 Reported-by: Stephane Eranian Signed-off-by: Jiri Olsa Tested-by: Stephane Eranian Acked-by: Namhyung Kim Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180907102455.7030-1-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/ordered-events.c | 83 +++++++++++++++++++++++++++----- tools/perf/util/ordered-events.h | 37 ++++++++------ 2 files changed, 91 insertions(+), 29 deletions(-) diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c index bad9e0296e9a..84ce25272c13 100644 --- a/tools/perf/util/ordered-events.c +++ b/tools/perf/util/ordered-events.c @@ -80,14 +80,20 @@ static union perf_event *dup_event(struct ordered_events *oe, return oe->copy_on_queue ? __dup_event(oe, event) : event; } -static void free_dup_event(struct ordered_events *oe, union perf_event *event) +static void __free_dup_event(struct ordered_events *oe, union perf_event *event) { - if (event && oe->copy_on_queue) { + if (event) { oe->cur_alloc_size -= event->header.size; free(event); } } +static void free_dup_event(struct ordered_events *oe, union perf_event *event) +{ + if (oe->copy_on_queue) + __free_dup_event(oe, event); +} + #define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event)) static struct ordered_event *alloc_event(struct ordered_events *oe, union perf_event *event) @@ -100,15 +106,43 @@ static struct ordered_event *alloc_event(struct ordered_events *oe, if (!new_event) return NULL; + /* + * We maintain the following scheme of buffers for ordered + * event allocation: + * + * to_free list -> buffer1 (64K) + * buffer2 (64K) + * ... + * + * Each buffer keeps an array of ordered events objects: + * buffer -> event[0] + * event[1] + * ... + * + * Each allocated ordered event is linked to one of + * following lists: + * - time ordered list 'events' + * - list of currently removed events 'cache' + * + * Allocation of the ordered event uses the following order + * to get the memory: + * - use recently removed object from 'cache' list + * - use available object in current allocation buffer + * - allocate new buffer if the current buffer is full + * + * Removal of ordered event object moves it from events to + * the cache list. + */ if (!list_empty(cache)) { new = list_entry(cache->next, struct ordered_event, list); list_del(&new->list); } else if (oe->buffer) { - new = oe->buffer + oe->buffer_idx; + new = &oe->buffer->event[oe->buffer_idx]; if (++oe->buffer_idx == MAX_SAMPLE_BUFFER) oe->buffer = NULL; } else if (oe->cur_alloc_size < oe->max_alloc_size) { - size_t size = MAX_SAMPLE_BUFFER * sizeof(*new); + size_t size = sizeof(*oe->buffer) + + MAX_SAMPLE_BUFFER * sizeof(*new); oe->buffer = malloc(size); if (!oe->buffer) { @@ -122,11 +156,11 @@ static struct ordered_event *alloc_event(struct ordered_events *oe, oe->cur_alloc_size += size; list_add(&oe->buffer->list, &oe->to_free); - /* First entry is abused to maintain the to_free list. */ - oe->buffer_idx = 2; - new = oe->buffer + 1; + oe->buffer_idx = 1; + new = &oe->buffer->event[0]; } else { pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size); + return NULL; } new->event = new_event; @@ -300,15 +334,38 @@ void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t d oe->deliver = deliver; } +static void +ordered_events_buffer__free(struct ordered_events_buffer *buffer, + unsigned int max, struct ordered_events *oe) +{ + if (oe->copy_on_queue) { + unsigned int i; + + for (i = 0; i < max; i++) + __free_dup_event(oe, buffer->event[i].event); + } + + free(buffer); +} + void ordered_events__free(struct ordered_events *oe) { - while (!list_empty(&oe->to_free)) { - struct ordered_event *event; + struct ordered_events_buffer *buffer, *tmp; - event = list_entry(oe->to_free.next, struct ordered_event, list); - list_del(&event->list); - free_dup_event(oe, event->event); - free(event); + if (list_empty(&oe->to_free)) + return; + + /* + * Current buffer might not have all the events allocated + * yet, we need to free only allocated ones ... + */ + list_del(&oe->buffer->list); + ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe); + + /* ... and continue with the rest */ + list_for_each_entry_safe(buffer, tmp, &oe->to_free, list) { + list_del(&buffer->list); + ordered_events_buffer__free(buffer, MAX_SAMPLE_BUFFER, oe); } } diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h index 8c7a2948593e..1338d5c345dc 100644 --- a/tools/perf/util/ordered-events.h +++ b/tools/perf/util/ordered-events.h @@ -25,23 +25,28 @@ struct ordered_events; typedef int (*ordered_events__deliver_t)(struct ordered_events *oe, struct ordered_event *event); +struct ordered_events_buffer { + struct list_head list; + struct ordered_event event[0]; +}; + struct ordered_events { - u64 last_flush; - u64 next_flush; - u64 max_timestamp; - u64 max_alloc_size; - u64 cur_alloc_size; - struct list_head events; - struct list_head cache; - struct list_head to_free; - struct ordered_event *buffer; - struct ordered_event *last; - ordered_events__deliver_t deliver; - int buffer_idx; - unsigned int nr_events; - enum oe_flush last_flush_type; - u32 nr_unordered_events; - bool copy_on_queue; + u64 last_flush; + u64 next_flush; + u64 max_timestamp; + u64 max_alloc_size; + u64 cur_alloc_size; + struct list_head events; + struct list_head cache; + struct list_head to_free; + struct ordered_events_buffer *buffer; + struct ordered_event *last; + ordered_events__deliver_t deliver; + int buffer_idx; + unsigned int nr_events; + enum oe_flush last_flush_type; + u32 nr_unordered_events; + bool copy_on_queue; }; int ordered_events__queue(struct ordered_events *oe, union perf_event *event, From 53da12e013498c4eca592939bb18a5dbd1d228c9 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 7 Sep 2018 12:24:55 +0200 Subject: [PATCH 088/155] perf ordered_events: Prevent crossing max_alloc_size Stephane reported a possible issue in the ordered events code, which could lead to allocating more memory than guarded by max_alloc_size. He also suggested the fix to properly check that the new size is below the max_alloc_size limit. Reported-by: Stephane Eranian Suggested-by: Stephane Eranian Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180907102455.7030-2-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/ordered-events.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c index 84ce25272c13..1904e7f6ec84 100644 --- a/tools/perf/util/ordered-events.c +++ b/tools/perf/util/ordered-events.c @@ -101,6 +101,7 @@ static struct ordered_event *alloc_event(struct ordered_events *oe, struct list_head *cache = &oe->cache; struct ordered_event *new = NULL; union perf_event *new_event; + size_t size; new_event = dup_event(oe, event); if (!new_event) @@ -133,6 +134,8 @@ static struct ordered_event *alloc_event(struct ordered_events *oe, * Removal of ordered event object moves it from events to * the cache list. */ + size = sizeof(*oe->buffer) + MAX_SAMPLE_BUFFER * sizeof(*new); + if (!list_empty(cache)) { new = list_entry(cache->next, struct ordered_event, list); list_del(&new->list); @@ -140,10 +143,7 @@ static struct ordered_event *alloc_event(struct ordered_events *oe, new = &oe->buffer->event[oe->buffer_idx]; if (++oe->buffer_idx == MAX_SAMPLE_BUFFER) oe->buffer = NULL; - } else if (oe->cur_alloc_size < oe->max_alloc_size) { - size_t size = sizeof(*oe->buffer) + - MAX_SAMPLE_BUFFER * sizeof(*new); - + } else if ((oe->cur_alloc_size + size) < oe->max_alloc_size) { oe->buffer = malloc(size); if (!oe->buffer) { free_dup_event(oe, new_event); From 01ab2e91103b8c23dfedfeb799bc8b810d585bd0 Mon Sep 17 00:00:00 2001 From: Ding Xiang Date: Fri, 7 Sep 2018 09:34:41 +0800 Subject: [PATCH 089/155] tools include: Adopt PTR_ERR_OR_ZERO from the kernel err.h header Add PTR_ERR_OR_ZERO, so that tools can use it, just like the kernel. Signed-off-by: Ding Xiang Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1536284082-23466-1-git-send-email-dingxiang@cmss.chinamobile.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/linux/err.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/include/linux/err.h b/tools/include/linux/err.h index 7a8b61ad44cb..094649667bae 100644 --- a/tools/include/linux/err.h +++ b/tools/include/linux/err.h @@ -52,4 +52,11 @@ static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr) return unlikely(!ptr) || IS_ERR_VALUE((unsigned long)ptr); } +static inline int __must_check PTR_ERR_OR_ZERO(__force const void *ptr) +{ + if (IS_ERR(ptr)) + return PTR_ERR(ptr); + else + return 0; +} #endif /* _LINUX_ERR_H */ From e381d1c21eea186daed6834af444575e06841355 Mon Sep 17 00:00:00 2001 From: Ding Xiang Date: Fri, 7 Sep 2018 09:34:42 +0800 Subject: [PATCH 090/155] perf bpf-loader: use PTR_ERR_OR_ZERO inetead of return code Use PTR_ERR_OR_ZERO() in bpf__setup_stdout() return code instead of open coded equivalent. Signed-off-by: Ding Xiang Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1536284082-23466-2-git-send-email-dingxiang@cmss.chinamobile.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf-loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index 47aac41349a2..f9ae1a993806 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -1615,7 +1615,7 @@ struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const cha int bpf__setup_stdout(struct perf_evlist *evlist) { struct perf_evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__"); - return IS_ERR(evsel) ? PTR_ERR(evsel) : 0; + return PTR_ERR_OR_ZERO(evsel); } #define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START) From 89f1688a57a8f0b685fccd648e601a1f830fa744 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 13 Sep 2018 14:54:03 +0200 Subject: [PATCH 091/155] perf tools: Remove perf_tool from event_op2 Now that we keep a perf_tool pointer inside perf_session, there's no need to have a perf_tool argument in the event_op2 callback. Remove it. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180913125450.21342-2-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 7 ++-- tools/perf/builtin-inject.c | 26 ++++++-------- tools/perf/builtin-report.c | 9 +++-- tools/perf/builtin-script.c | 38 ++++++++++---------- tools/perf/builtin-stat.c | 23 ++++++------ tools/perf/util/auxtrace.c | 10 +++--- tools/perf/util/auxtrace.h | 10 +++--- tools/perf/util/header.c | 16 ++++----- tools/perf/util/header.h | 15 ++++---- tools/perf/util/session.c | 67 +++++++++++++++-------------------- tools/perf/util/session.h | 5 ++- tools/perf/util/stat.c | 5 ++- tools/perf/util/stat.h | 5 ++- tools/perf/util/tool.h | 3 +- 14 files changed, 103 insertions(+), 136 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 830481b8db26..93d679eaf1f4 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -283,12 +283,11 @@ out_put: return ret; } -static int process_feature_event(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session) +static int process_feature_event(struct perf_session *session, + union perf_event *event) { if (event->feat.feat_id < HEADER_LAST_FEATURE) - return perf_event__process_feature(tool, event, session); + return perf_event__process_feature(session, event); return 0; } diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index a3b346359ba0..d77ed2aea95a 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -86,12 +86,10 @@ static int perf_event__drop_oe(struct perf_tool *tool __maybe_unused, } #endif -static int perf_event__repipe_op2_synth(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session - __maybe_unused) +static int perf_event__repipe_op2_synth(struct perf_session *session, + union perf_event *event) { - return perf_event__repipe_synth(tool, event); + return perf_event__repipe_synth(session->tool, event); } static int perf_event__repipe_attr(struct perf_tool *tool, @@ -362,26 +360,24 @@ static int perf_event__repipe_exit(struct perf_tool *tool, return err; } -static int perf_event__repipe_tracing_data(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session) +static int perf_event__repipe_tracing_data(struct perf_session *session, + union perf_event *event) { int err; - perf_event__repipe_synth(tool, event); - err = perf_event__process_tracing_data(tool, event, session); + perf_event__repipe_synth(session->tool, event); + err = perf_event__process_tracing_data(session, event); return err; } -static int perf_event__repipe_id_index(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session) +static int perf_event__repipe_id_index(struct perf_session *session, + union perf_event *event) { int err; - perf_event__repipe_synth(tool, event); - err = perf_event__process_id_index(tool, event, session); + perf_event__repipe_synth(session->tool, event); + err = perf_event__process_id_index(session, event); return err; } diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 76e12bcd1765..7507e4d6dce1 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -201,14 +201,13 @@ static void setup_forced_leader(struct report *report, perf_evlist__force_leader(evlist); } -static int process_feature_event(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session __maybe_unused) +static int process_feature_event(struct perf_session *session, + union perf_event *event) { - struct report *rep = container_of(tool, struct report, tool); + struct report *rep = container_of(session->tool, struct report, tool); if (event->feat.feat_id < HEADER_LAST_FEATURE) - return perf_event__process_feature(tool, event, session); + return perf_event__process_feature(session, event); if (event->feat.feat_id != HEADER_LAST_FEATURE) { pr_err("failed: wrong feature ID: %" PRIu64 "\n", diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 6176bae177c2..765391b6c88c 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2965,9 +2965,8 @@ static void script__setup_sample_type(struct perf_script *script) } } -static int process_stat_round_event(struct perf_tool *tool __maybe_unused, - union perf_event *event, - struct perf_session *session) +static int process_stat_round_event(struct perf_session *session, + union perf_event *event) { struct stat_round_event *round = &event->stat_round; struct perf_evsel *counter; @@ -2981,9 +2980,8 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused, return 0; } -static int process_stat_config_event(struct perf_tool *tool __maybe_unused, - union perf_event *event, - struct perf_session *session __maybe_unused) +static int process_stat_config_event(struct perf_session *session __maybe_unused, + union perf_event *event) { perf_event__read_stat_config(&stat_config, &event->stat_config); return 0; @@ -3009,10 +3007,10 @@ static int set_maps(struct perf_script *script) } static -int process_thread_map_event(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session __maybe_unused) +int process_thread_map_event(struct perf_session *session, + union perf_event *event) { + struct perf_tool *tool = session->tool; struct perf_script *script = container_of(tool, struct perf_script, tool); if (script->threads) { @@ -3028,10 +3026,10 @@ int process_thread_map_event(struct perf_tool *tool, } static -int process_cpu_map_event(struct perf_tool *tool __maybe_unused, - union perf_event *event, - struct perf_session *session __maybe_unused) +int process_cpu_map_event(struct perf_session *session, + union perf_event *event) { + struct perf_tool *tool = session->tool; struct perf_script *script = container_of(tool, struct perf_script, tool); if (script->cpus) { @@ -3046,21 +3044,21 @@ int process_cpu_map_event(struct perf_tool *tool __maybe_unused, return set_maps(script); } -static int process_feature_event(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session) +static int process_feature_event(struct perf_session *session, + union perf_event *event) { if (event->feat.feat_id < HEADER_LAST_FEATURE) - return perf_event__process_feature(tool, event, session); + return perf_event__process_feature(session, event); return 0; } #ifdef HAVE_AUXTRACE_SUPPORT -static int perf_script__process_auxtrace_info(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session) +static int perf_script__process_auxtrace_info(struct perf_session *session, + union perf_event *event) { - int ret = perf_event__process_auxtrace_info(tool, event, session); + struct perf_tool *tool = session->tool; + + int ret = perf_event__process_auxtrace_info(session, event); if (ret == 0) { struct perf_script *script = container_of(tool, struct perf_script, tool); diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 0b0e3961d511..b86aba1c8028 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1354,9 +1354,8 @@ static int __cmd_record(int argc, const char **argv) return argc; } -static int process_stat_round_event(struct perf_tool *tool __maybe_unused, - union perf_event *event, - struct perf_session *session) +static int process_stat_round_event(struct perf_session *session, + union perf_event *event) { struct stat_round_event *stat_round = &event->stat_round; struct perf_evsel *counter; @@ -1381,10 +1380,10 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused, } static -int process_stat_config_event(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session __maybe_unused) +int process_stat_config_event(struct perf_session *session, + union perf_event *event) { + struct perf_tool *tool = session->tool; struct perf_stat *st = container_of(tool, struct perf_stat, tool); perf_event__read_stat_config(&stat_config, &event->stat_config); @@ -1424,10 +1423,10 @@ static int set_maps(struct perf_stat *st) } static -int process_thread_map_event(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session __maybe_unused) +int process_thread_map_event(struct perf_session *session, + union perf_event *event) { + struct perf_tool *tool = session->tool; struct perf_stat *st = container_of(tool, struct perf_stat, tool); if (st->threads) { @@ -1443,10 +1442,10 @@ int process_thread_map_event(struct perf_tool *tool, } static -int process_cpu_map_event(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session __maybe_unused) +int process_cpu_map_event(struct perf_session *session, + union perf_event *event) { + struct perf_tool *tool = session->tool; struct perf_stat *st = container_of(tool, struct perf_stat, tool); struct cpu_map *cpus; diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index db1511359c5e..86f0bc445f93 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -906,9 +906,8 @@ out_free: return err; } -int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused, - union perf_event *event, - struct perf_session *session) +int perf_event__process_auxtrace_info(struct perf_session *session, + union perf_event *event) { enum auxtrace_type type = event->auxtrace_info.type; @@ -1185,9 +1184,8 @@ void events_stats__auxtrace_error_warn(const struct events_stats *stats) } } -int perf_event__process_auxtrace_error(struct perf_tool *tool __maybe_unused, - union perf_event *event, - struct perf_session *session) +int perf_event__process_auxtrace_error(struct perf_session *session, + union perf_event *event) { if (auxtrace__dont_decode(session)) return 0; diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index 71fc3bd74299..97776470a52e 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -517,15 +517,13 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr, struct perf_tool *tool, struct perf_session *session, perf_event__handler_t process); -int perf_event__process_auxtrace_info(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session); +int perf_event__process_auxtrace_info(struct perf_session *session, + union perf_event *event); s64 perf_event__process_auxtrace(struct perf_tool *tool, union perf_event *event, struct perf_session *session); -int perf_event__process_auxtrace_error(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session); +int perf_event__process_auxtrace_error(struct perf_session *session, + union perf_event *event); int itrace_parse_synth_opts(const struct option *opt, const char *str, int unset); void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 91e6d9cfd906..c78051ad1fcc 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -3448,10 +3448,10 @@ int perf_event__synthesize_features(struct perf_tool *tool, return ret; } -int perf_event__process_feature(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session __maybe_unused) +int perf_event__process_feature(struct perf_session *session, + union perf_event *event) { + struct perf_tool *tool = session->tool; struct feat_fd ff = { .fd = 0 }; struct feature_event *fe = (struct feature_event *)event; int type = fe->header.type; @@ -3856,9 +3856,8 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, return aligned_size; } -int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused, - union perf_event *event, - struct perf_session *session) +int perf_event__process_tracing_data(struct perf_session *session, + union perf_event *event) { ssize_t size_read, padding, size = event->tracing_data.size; int fd = perf_data__fd(session->data); @@ -3924,9 +3923,8 @@ int perf_event__synthesize_build_id(struct perf_tool *tool, return err; } -int perf_event__process_build_id(struct perf_tool *tool __maybe_unused, - union perf_event *event, - struct perf_session *session) +int perf_event__process_build_id(struct perf_session *session, + union perf_event *event) { __event_process_build_id(&event->build_id, event->build_id.filename, diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index ff2a1263fb9b..e17903caa71d 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -116,9 +116,8 @@ int perf_event__synthesize_extra_attr(struct perf_tool *tool, perf_event__handler_t process, bool is_pipe); -int perf_event__process_feature(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session); +int perf_event__process_feature(struct perf_session *session, + union perf_event *event); int perf_event__synthesize_attr(struct perf_tool *tool, struct perf_event_attr *attr, u32 ids, u64 *id, @@ -148,17 +147,15 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp); int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, struct perf_evlist *evlist, perf_event__handler_t process); -int perf_event__process_tracing_data(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session); +int perf_event__process_tracing_data(struct perf_session *session, + union perf_event *event); int perf_event__synthesize_build_id(struct perf_tool *tool, struct dso *pos, u16 misc, perf_event__handler_t process, struct machine *machine); -int perf_event__process_build_id(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session); +int perf_event__process_build_id(struct perf_session *session, + union perf_event *event); bool is_perf_magic(u64 magic); #define NAME_ALIGN 64 diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 8b9369303561..e781cdba845c 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -199,12 +199,10 @@ void perf_session__delete(struct perf_session *session) free(session); } -static int process_event_synth_tracing_data_stub(struct perf_tool *tool +static int process_event_synth_tracing_data_stub(struct perf_session *session __maybe_unused, union perf_event *event - __maybe_unused, - struct perf_session *session - __maybe_unused) + __maybe_unused) { dump_printf(": unhandled!\n"); return 0; @@ -288,9 +286,8 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused, return event->auxtrace.size; } -static int process_event_op2_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_session *session __maybe_unused) +static int process_event_op2_stub(struct perf_session *session __maybe_unused, + union perf_event *event __maybe_unused) { dump_printf(": unhandled!\n"); return 0; @@ -298,9 +295,8 @@ static int process_event_op2_stub(struct perf_tool *tool __maybe_unused, static -int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_session *session __maybe_unused) +int process_event_thread_map_stub(struct perf_session *session __maybe_unused, + union perf_event *event __maybe_unused) { if (dump_trace) perf_event__fprintf_thread_map(event, stdout); @@ -310,9 +306,8 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused, } static -int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_session *session __maybe_unused) +int process_event_cpu_map_stub(struct perf_session *session __maybe_unused, + union perf_event *event __maybe_unused) { if (dump_trace) perf_event__fprintf_cpu_map(event, stdout); @@ -322,9 +317,8 @@ int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused, } static -int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_session *session __maybe_unused) +int process_event_stat_config_stub(struct perf_session *session __maybe_unused, + union perf_event *event __maybe_unused) { if (dump_trace) perf_event__fprintf_stat_config(event, stdout); @@ -333,10 +327,8 @@ int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused, return 0; } -static int process_stat_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_session *perf_session - __maybe_unused) +static int process_stat_stub(struct perf_session *perf_session __maybe_unused, + union perf_event *event) { if (dump_trace) perf_event__fprintf_stat(event, stdout); @@ -345,10 +337,8 @@ static int process_stat_stub(struct perf_tool *tool __maybe_unused, return 0; } -static int process_stat_round_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_session *perf_session - __maybe_unused) +static int process_stat_round_stub(struct perf_session *perf_session __maybe_unused, + union perf_event *event) { if (dump_trace) perf_event__fprintf_stat_round(event, stdout); @@ -1374,37 +1364,37 @@ static s64 perf_session__process_user_event(struct perf_session *session, case PERF_RECORD_HEADER_TRACING_DATA: /* setup for reading amidst mmap */ lseek(fd, file_offset, SEEK_SET); - return tool->tracing_data(tool, event, session); + return tool->tracing_data(session, event); case PERF_RECORD_HEADER_BUILD_ID: - return tool->build_id(tool, event, session); + return tool->build_id(session, event); case PERF_RECORD_FINISHED_ROUND: return tool->finished_round(tool, event, oe); case PERF_RECORD_ID_INDEX: - return tool->id_index(tool, event, session); + return tool->id_index(session, event); case PERF_RECORD_AUXTRACE_INFO: - return tool->auxtrace_info(tool, event, session); + return tool->auxtrace_info(session, event); case PERF_RECORD_AUXTRACE: /* setup for reading amidst mmap */ lseek(fd, file_offset + event->header.size, SEEK_SET); return tool->auxtrace(tool, event, session); case PERF_RECORD_AUXTRACE_ERROR: perf_session__auxtrace_error_inc(session, event); - return tool->auxtrace_error(tool, event, session); + return tool->auxtrace_error(session, event); case PERF_RECORD_THREAD_MAP: - return tool->thread_map(tool, event, session); + return tool->thread_map(session, event); case PERF_RECORD_CPU_MAP: - return tool->cpu_map(tool, event, session); + return tool->cpu_map(session, event); case PERF_RECORD_STAT_CONFIG: - return tool->stat_config(tool, event, session); + return tool->stat_config(session, event); case PERF_RECORD_STAT: - return tool->stat(tool, event, session); + return tool->stat(session, event); case PERF_RECORD_STAT_ROUND: - return tool->stat_round(tool, event, session); + return tool->stat_round(session, event); case PERF_RECORD_TIME_CONV: session->time_conv = event->time_conv; - return tool->time_conv(tool, event, session); + return tool->time_conv(session, event); case PERF_RECORD_HEADER_FEATURE: - return tool->feature(tool, event, session); + return tool->feature(session, event); default: return -EINVAL; } @@ -2133,9 +2123,8 @@ out: return err; } -int perf_event__process_id_index(struct perf_tool *tool __maybe_unused, - union perf_event *event, - struct perf_session *session) +int perf_event__process_id_index(struct perf_session *session, + union perf_event *event) { struct perf_evlist *evlist = session->evlist; struct id_index_event *ie = &event->id_index; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index da40b4b380ca..d96eccd7d27f 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -120,9 +120,8 @@ int perf_session__deliver_synth_event(struct perf_session *session, union perf_event *event, struct perf_sample *sample); -int perf_event__process_id_index(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session); +int perf_event__process_id_index(struct perf_session *session, + union perf_event *event); int perf_event__synthesize_id_index(struct perf_tool *tool, perf_event__handler_t process, diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 5d3172bcc4ae..4d40515307b8 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -374,9 +374,8 @@ int perf_stat_process_counter(struct perf_stat_config *config, return 0; } -int perf_event__process_stat_event(struct perf_tool *tool __maybe_unused, - union perf_event *event, - struct perf_session *session) +int perf_event__process_stat_event(struct perf_session *session, + union perf_event *event) { struct perf_counts_values count; struct stat_event *st = &event->stat; diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 3a13a6dc5a62..2f9c9159a364 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -199,9 +199,8 @@ int perf_stat_process_counter(struct perf_stat_config *config, struct perf_tool; union perf_event; struct perf_session; -int perf_event__process_stat_event(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session); +int perf_event__process_stat_event(struct perf_session *session, + union perf_event *event); size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp); size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp); diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 183c91453522..9c7f78d76275 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -26,8 +26,7 @@ typedef int (*event_attr_op)(struct perf_tool *tool, union perf_event *event, struct perf_evlist **pevlist); -typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event, - struct perf_session *session); +typedef int (*event_op2)(struct perf_session *session, union perf_event *event); typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event, struct ordered_events *oe); From 7336555a682c09fd9a3fdf38724493e52653be50 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 13 Sep 2018 14:54:04 +0200 Subject: [PATCH 092/155] perf tools: Remove perf_tool from event_op3 Now that we keep a perf_tool pointer inside perf_session, there's no need to have a perf_tool argument in the event_op3 callback. Remove it. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180913125450.21342-3-jolsa@kernel.org [ Fix the builtin-inject.c build for !HAVE_AUXTRACE_SUPPORT ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 11 +++++------ tools/perf/util/auxtrace.c | 7 +++---- tools/perf/util/auxtrace.h | 5 ++--- tools/perf/util/session.c | 8 +++----- tools/perf/util/tool.h | 4 +--- 5 files changed, 14 insertions(+), 21 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index d77ed2aea95a..b4a29f435b06 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -131,10 +131,10 @@ static int copy_bytes(struct perf_inject *inject, int fd, off_t size) return 0; } -static s64 perf_event__repipe_auxtrace(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session) +static s64 perf_event__repipe_auxtrace(struct perf_session *session, + union perf_event *event) { + struct perf_tool *tool = session->tool; struct perf_inject *inject = container_of(tool, struct perf_inject, tool); int ret; @@ -172,9 +172,8 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool, #else static s64 -perf_event__repipe_auxtrace(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_session *session __maybe_unused) +perf_event__repipe_auxtrace(struct perf_session *session __maybe_unused, + union perf_event *event __maybe_unused) { pr_err("AUX area tracing not supported\n"); return -EINVAL; diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 86f0bc445f93..3017b205a157 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -931,9 +931,8 @@ int perf_event__process_auxtrace_info(struct perf_session *session, } } -s64 perf_event__process_auxtrace(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session) +s64 perf_event__process_auxtrace(struct perf_session *session, + union perf_event *event) { s64 err; @@ -949,7 +948,7 @@ s64 perf_event__process_auxtrace(struct perf_tool *tool, if (!session->auxtrace || event->header.type != PERF_RECORD_AUXTRACE) return -EINVAL; - err = session->auxtrace->process_auxtrace_event(session, event, tool); + err = session->auxtrace->process_auxtrace_event(session, event, session->tool); if (err < 0) return err; diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index 97776470a52e..6be89776358c 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -519,9 +519,8 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr, perf_event__handler_t process); int perf_event__process_auxtrace_info(struct perf_session *session, union perf_event *event); -s64 perf_event__process_auxtrace(struct perf_tool *tool, - union perf_event *event, - struct perf_session *session); +s64 perf_event__process_auxtrace(struct perf_session *session, + union perf_event *event); int perf_event__process_auxtrace_error(struct perf_session *session, union perf_event *event); int itrace_parse_synth_opts(const struct option *opt, const char *str, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index e781cdba845c..7d2c8ce6cfad 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -275,10 +275,8 @@ static int skipn(int fd, off_t n) return 0; } -static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event, - struct perf_session *session - __maybe_unused) +static s64 process_event_auxtrace_stub(struct perf_session *session __maybe_unused, + union perf_event *event) { dump_printf(": unhandled!\n"); if (perf_data__is_pipe(session->data)) @@ -1376,7 +1374,7 @@ static s64 perf_session__process_user_event(struct perf_session *session, case PERF_RECORD_AUXTRACE: /* setup for reading amidst mmap */ lseek(fd, file_offset + event->header.size, SEEK_SET); - return tool->auxtrace(tool, event, session); + return tool->auxtrace(session, event); case PERF_RECORD_AUXTRACE_ERROR: perf_session__auxtrace_error_inc(session, event); return tool->auxtrace_error(session, event); diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 9c7f78d76275..56e4ca54020a 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -27,13 +27,11 @@ typedef int (*event_attr_op)(struct perf_tool *tool, struct perf_evlist **pevlist); typedef int (*event_op2)(struct perf_session *session, union perf_event *event); +typedef s64 (*event_op3)(struct perf_session *session, union perf_event *event); typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event, struct ordered_events *oe); -typedef s64 (*event_op3)(struct perf_tool *tool, union perf_event *event, - struct perf_session *session); - enum show_feature_header { SHOW_FEAT_NO_HEADER = 0, SHOW_FEAT_HEADER, From e035f4ca2ac97c30842fb03101198a86730de3ad Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 13 Sep 2018 14:54:05 +0200 Subject: [PATCH 093/155] perf auxtrace: Pass struct perf_mmap into mmap__read* functions The perf_mmap struct will hold a file pointer to write the mmap's contents, so we need to propagate it down the stack to record__write callers instead of its member the auxtrace_mmap struct. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180913125450.21342-4-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 27 +++++++++++++-------------- tools/perf/util/auxtrace.c | 11 ++++++----- tools/perf/util/auxtrace.h | 5 +++-- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 9853552bcf16..fd8b12c5f4ae 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -207,11 +207,11 @@ static int record__process_auxtrace(struct perf_tool *tool, } static int record__auxtrace_mmap_read(struct record *rec, - struct auxtrace_mmap *mm) + struct perf_mmap *map) { int ret; - ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, + ret = auxtrace_mmap__read(map, rec->itr, &rec->tool, record__process_auxtrace); if (ret < 0) return ret; @@ -223,11 +223,11 @@ static int record__auxtrace_mmap_read(struct record *rec, } static int record__auxtrace_mmap_read_snapshot(struct record *rec, - struct auxtrace_mmap *mm) + struct perf_mmap *map) { int ret; - ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, + ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool, record__process_auxtrace, rec->opts.auxtrace_snapshot_size); if (ret < 0) @@ -245,13 +245,12 @@ static int record__auxtrace_read_snapshot_all(struct record *rec) int rc = 0; for (i = 0; i < rec->evlist->nr_mmaps; i++) { - struct auxtrace_mmap *mm = - &rec->evlist->mmap[i].auxtrace_mmap; + struct perf_mmap *map = &rec->evlist->mmap[i]; - if (!mm->base) + if (!map->auxtrace_mmap.base) continue; - if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { + if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) { rc = -1; goto out; } @@ -295,7 +294,7 @@ static int record__auxtrace_init(struct record *rec) static inline int record__auxtrace_mmap_read(struct record *rec __maybe_unused, - struct auxtrace_mmap *mm __maybe_unused) + struct perf_mmap *map __maybe_unused) { return 0; } @@ -529,17 +528,17 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli return 0; for (i = 0; i < evlist->nr_mmaps; i++) { - struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap; + struct perf_mmap *map = &maps[i]; - if (maps[i].base) { - if (perf_mmap__push(&maps[i], rec, record__pushfn) != 0) { + if (map->base) { + if (perf_mmap__push(map, rec, record__pushfn) != 0) { rc = -1; goto out; } } - if (mm->base && !rec->opts.auxtrace_snapshot_mode && - record__auxtrace_mmap_read(rec, mm) != 0) { + if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode && + record__auxtrace_mmap_read(rec, map) != 0) { rc = -1; goto out; } diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 3017b205a157..2fecee57f555 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -1193,11 +1193,12 @@ int perf_event__process_auxtrace_error(struct perf_session *session, return 0; } -static int __auxtrace_mmap__read(struct auxtrace_mmap *mm, +static int __auxtrace_mmap__read(struct perf_mmap *map, struct auxtrace_record *itr, struct perf_tool *tool, process_auxtrace_t fn, bool snapshot, size_t snapshot_size) { + struct auxtrace_mmap *mm = &map->auxtrace_mmap; u64 head, old = mm->prev, offset, ref; unsigned char *data = mm->base; size_t size, head_off, old_off, len1, len2, padding; @@ -1303,18 +1304,18 @@ static int __auxtrace_mmap__read(struct auxtrace_mmap *mm, return 1; } -int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr, +int auxtrace_mmap__read(struct perf_mmap *map, struct auxtrace_record *itr, struct perf_tool *tool, process_auxtrace_t fn) { - return __auxtrace_mmap__read(mm, itr, tool, fn, false, 0); + return __auxtrace_mmap__read(map, itr, tool, fn, false, 0); } -int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm, +int auxtrace_mmap__read_snapshot(struct perf_mmap *map, struct auxtrace_record *itr, struct perf_tool *tool, process_auxtrace_t fn, size_t snapshot_size) { - return __auxtrace_mmap__read(mm, itr, tool, fn, true, snapshot_size); + return __auxtrace_mmap__read(map, itr, tool, fn, true, snapshot_size); } /** diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index 6be89776358c..7eeb141361b9 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -33,6 +33,7 @@ union perf_event; struct perf_session; struct perf_evlist; struct perf_tool; +struct perf_mmap; struct option; struct record_opts; struct auxtrace_info_event; @@ -437,10 +438,10 @@ typedef int (*process_auxtrace_t)(struct perf_tool *tool, union perf_event *event, void *data1, size_t len1, void *data2, size_t len2); -int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr, +int auxtrace_mmap__read(struct perf_mmap *map, struct auxtrace_record *itr, struct perf_tool *tool, process_auxtrace_t fn); -int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm, +int auxtrace_mmap__read_snapshot(struct perf_mmap *map, struct auxtrace_record *itr, struct perf_tool *tool, process_auxtrace_t fn, size_t snapshot_size); From ded2b8fe2e431d8029ab50238744fcce06a2f0c6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 13 Sep 2018 14:54:06 +0200 Subject: [PATCH 094/155] perf tools: Add 'struct perf_mmap' arg to record__write() The struct perf_mmap map argument will hold the file pointer to write the data to. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180913125450.21342-5-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 24 ++++++++++++++---------- tools/perf/util/auxtrace.c | 2 +- tools/perf/util/auxtrace.h | 1 + tools/perf/util/mmap.c | 6 +++--- tools/perf/util/mmap.h | 2 +- 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index fd8b12c5f4ae..0980dfe3396b 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -106,9 +106,12 @@ static bool switch_output_time(struct record *rec) trigger_is_ready(&switch_output_trigger); } -static int record__write(struct record *rec, void *bf, size_t size) +static int record__write(struct record *rec, struct perf_mmap *map __maybe_unused, + void *bf, size_t size) { - if (perf_data__write(rec->session->data, bf, size) < 0) { + struct perf_data_file *file = &rec->session->data->file; + + if (perf_data_file__write(file, bf, size) < 0) { pr_err("failed to write perf data, error: %m\n"); return -1; } @@ -127,15 +130,15 @@ static int process_synthesized_event(struct perf_tool *tool, struct machine *machine __maybe_unused) { struct record *rec = container_of(tool, struct record, tool); - return record__write(rec, event, event->header.size); + return record__write(rec, NULL, event, event->header.size); } -static int record__pushfn(void *to, void *bf, size_t size) +static int record__pushfn(struct perf_mmap *map, void *to, void *bf, size_t size) { struct record *rec = to; rec->samples++; - return record__write(rec, bf, size); + return record__write(rec, map, bf, size); } static volatile int done; @@ -170,6 +173,7 @@ static void record__sig_exit(void) #ifdef HAVE_AUXTRACE_SUPPORT static int record__process_auxtrace(struct perf_tool *tool, + struct perf_mmap *map, union perf_event *event, void *data1, size_t len1, void *data2, size_t len2) { @@ -197,11 +201,11 @@ static int record__process_auxtrace(struct perf_tool *tool, if (padding) padding = 8 - padding; - record__write(rec, event, event->header.size); - record__write(rec, data1, len1); + record__write(rec, map, event, event->header.size); + record__write(rec, map, data1, len1); if (len2) - record__write(rec, data2, len2); - record__write(rec, &pad, padding); + record__write(rec, map, data2, len2); + record__write(rec, map, &pad, padding); return 0; } @@ -549,7 +553,7 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli * at least one event. */ if (bytes_written != rec->bytes_written) - rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); + rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event)); if (overwrite) perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 2fecee57f555..c4617bcfd521 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -1285,7 +1285,7 @@ static int __auxtrace_mmap__read(struct perf_mmap *map, ev.auxtrace.tid = mm->tid; ev.auxtrace.cpu = mm->cpu; - if (fn(tool, &ev, data1, len1, data2, len2)) + if (fn(tool, map, &ev, data1, len1, data2, len2)) return -1; mm->prev = head; diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index 7eeb141361b9..a86b7eab6673 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -435,6 +435,7 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, bool per_cpu); typedef int (*process_auxtrace_t)(struct perf_tool *tool, + struct perf_mmap *map, union perf_event *event, void *data1, size_t len1, void *data2, size_t len2); diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c index 215f69f41672..cdb95b3a1213 100644 --- a/tools/perf/util/mmap.c +++ b/tools/perf/util/mmap.c @@ -281,7 +281,7 @@ int perf_mmap__read_init(struct perf_mmap *map) } int perf_mmap__push(struct perf_mmap *md, void *to, - int push(void *to, void *buf, size_t size)) + int push(struct perf_mmap *map, void *to, void *buf, size_t size)) { u64 head = perf_mmap__read_head(md); unsigned char *data = md->base + page_size; @@ -300,7 +300,7 @@ int perf_mmap__push(struct perf_mmap *md, void *to, size = md->mask + 1 - (md->start & md->mask); md->start += size; - if (push(to, buf, size) < 0) { + if (push(md, to, buf, size) < 0) { rc = -1; goto out; } @@ -310,7 +310,7 @@ int perf_mmap__push(struct perf_mmap *md, void *to, size = md->end - md->start; md->start += size; - if (push(to, buf, size) < 0) { + if (push(md, to, buf, size) < 0) { rc = -1; goto out; } diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h index 05a6d47c7956..e603314dc792 100644 --- a/tools/perf/util/mmap.h +++ b/tools/perf/util/mmap.h @@ -93,7 +93,7 @@ union perf_event *perf_mmap__read_forward(struct perf_mmap *map); union perf_event *perf_mmap__read_event(struct perf_mmap *map); int perf_mmap__push(struct perf_mmap *md, void *to, - int push(void *to, void *buf, size_t size)); + int push(struct perf_mmap *map, void *to, void *buf, size_t size)); size_t perf_mmap__mmap_len(struct perf_mmap *map); From ed93d0a26012a4a12231c16b18628a324079dc45 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 13 Sep 2018 14:54:11 +0200 Subject: [PATCH 095/155] perf util: Make copyfile_offset() global It will be used outside of util object in following patches. Committer note: We need to have the header with the definition for loff_t in util.h since we now use it in the copyfile_offset() signature. Also move that prototype closer to the other copyfile_ prefixed functions. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180913125450.21342-10-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/util.c | 2 +- tools/perf/util/util.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index eac5b858a371..093352e93d50 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -221,7 +221,7 @@ out: return err; } -static int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size) +int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size) { void *ptr; loff_t pgoff; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index dc58254a2b69..14508ee7707a 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -6,6 +6,7 @@ /* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */ #define _DEFAULT_SOURCE 1 +#include #include #include #include @@ -35,6 +36,7 @@ bool lsdir_no_dot_filter(const char *name, struct dirent *d); int copyfile(const char *from, const char *to); int copyfile_mode(const char *from, const char *to, mode_t mode); int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi); +int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size); ssize_t readn(int fd, void *buf, size_t n); ssize_t writen(int fd, const void *buf, size_t n); From c04c859f439fb4de9039246370d60a07b9b5bcb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Wed, 29 Aug 2018 16:16:48 -0400 Subject: [PATCH 096/155] perf tools: Initialize perf_data_file fd field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building the perf CTF converter fails with gcc 4.8.4 on Ubuntu 14.04 with the following error: error: missing initializer for field ‘fd’ of ‘struct perf_data_file’ [-Werror=missing-field-initializers] Per 4b838b0db4e9 ("perf tools: Add compression id into 'struct kmod_path'") and the ensuing discussion on the mailing list, it appears that this affects other distributions and gcc versions. Signed-off-by: Jeremie Galarneau Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20180829201648.19588-1-jeremie.galarneau@efficios.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/data-convert-bt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index abd38abf1d91..f75d4aa612c5 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -1578,7 +1578,7 @@ int bt_convert__perf2ctf(const char *input, const char *path, { struct perf_session *session; struct perf_data data = { - .file.path = input, + .file = { .path = input, .fd = -1 }, .mode = PERF_DATA_MODE_READ, .force = opts->force, }; From 24ef0fd0a1f389b156e6ef0edd71072728831bd9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 18 Sep 2018 16:08:02 -0300 Subject: [PATCH 097/155] perf python: Use -Wno-redundant-decls to build with PYTHON=python3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building in ClearLinux using 'make PYTHON=python3' with gcc 8.2.1 it fails with: GEN /tmp/build/perf/python/perf.so In file included from /usr/include/python3.7m/Python.h:126, from /git/linux/tools/perf/util/python.c:2: /usr/include/python3.7m/import.h:58:24: error: redundant redeclaration of ‘_PyImport_AddModuleObject’ [-Werror=redundant-decls] PyAPI_FUNC(PyObject *) _PyImport_AddModuleObject(PyObject *, PyObject *); ^~~~~~~~~~~~~~~~~~~~~~~~~ /usr/include/python3.7m/import.h:47:24: note: previous declaration of ‘_PyImport_AddModuleObject’ was here PyAPI_FUNC(PyObject *) _PyImport_AddModuleObject(PyObject *name, ^~~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors error: command 'gcc' failed with exit status 1 And indeed there is a redundant declaration in that Python.h file, one with parameter names and the other without, so just add -Wno-error=redundant-decls to the python setup instructions. Now perf builds with gcc in ClearLinux with the following Dockerfile: # docker.io/acmel/linux-perf-tools-build-clearlinux:latest FROM docker.io/clearlinux:latest MAINTAINER Arnaldo Carvalho de Melo RUN swupd update && \ swupd bundle-add sysadmin-basic-dev RUN mkdir -m 777 -p /git /tmp/build/perf /tmp/build/objtool /tmp/build/linux && \ groupadd -r perfbuilder && \ useradd -m -r -g perfbuilder perfbuilder && \ chown -R perfbuilder.perfbuilder /tmp/build/ /git/ USER perfbuilder COPY rx_and_build.sh / ENV EXTRA_MAKE_ARGS=PYTHON=python3 ENTRYPOINT ["/rx_and_build.sh"] Now to figure out why the build fails with clang, that is present in the above container as detected by the rx_and_build.sh script: clang version 6.0.1 (tags/RELEASE_601/final) Target: x86_64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/sbin make: Entering directory '/git/linux/tools/perf' BUILD: Doing 'make -j4' parallel build HOSTCC /tmp/build/perf/fixdep.o HOSTLD /tmp/build/perf/fixdep-in.o LINK /tmp/build/perf/fixdep Auto-detecting system features: ... dwarf: [ OFF ] ... dwarf_getlocations: [ OFF ] ... glibc: [ OFF ] ... gtk2: [ OFF ] ... libaudit: [ OFF ] ... libbfd: [ OFF ] ... libelf: [ OFF ] ... libnuma: [ OFF ] ... numa_num_possible_cpus: [ OFF ] ... libperl: [ OFF ] ... libpython: [ OFF ] ... libslang: [ OFF ] ... libcrypto: [ OFF ] ... libunwind: [ OFF ] ... libdw-dwarf-unwind: [ OFF ] ... zlib: [ OFF ] ... lzma: [ OFF ] ... get_cpuid: [ OFF ] ... bpf: [ OFF ] Makefile.config:331: *** No gnu/libc-version.h found, please install glibc-dev[el]. Stop. make[1]: *** [Makefile.perf:206: sub-make] Error 2 make: *** [Makefile:70: all] Error 2 make: Leaving directory '/git/linux/tools/perf' Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Thiago Macieira Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-c3khb9ac86s00qxzjrueomme@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py index 97efbcad076e..1942f6dd24f6 100644 --- a/tools/perf/util/setup.py +++ b/tools/perf/util/setup.py @@ -35,7 +35,7 @@ class install_lib(_install_lib): cflags = getenv('CFLAGS', '').split() # switch off several checks (need to be at the end of cflags list) -cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ] +cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter', '-Wno-redundant-decls' ] if cc != "clang": cflags += ['-Wno-cast-function-type' ] From 3b9c25c0a04675c5d8d4390d9d9b661135751b27 Mon Sep 17 00:00:00 2001 From: Sangwon Hong Date: Wed, 19 Sep 2018 00:49:11 -0700 Subject: [PATCH 098/155] perf help: Add missing subcommand `version` There isn't subcommand `version` when typing `perf help`. Before : $ perf help | grep version usage: perf [--version] [--help] [OPTIONS] COMMAND [ARGS] So add perf-version in command-list.txt for listing it when typing `perf help`. After : $ perf help | grep version usage: perf [--version] [--help] [OPTIONS] COMMAND [ARGS] version display the version of perf binary Signed-off-by: Sangwon Hong Tested-by: Arnaldo Carvalho de Melo Cc: Jin Yao Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/20180919074911.41931-1-qpakzk@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/command-list.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt index 2d0caf20ff3a..bc6c585f74fc 100644 --- a/tools/perf/command-list.txt +++ b/tools/perf/command-list.txt @@ -30,3 +30,4 @@ perf-test mainporcelain common perf-timechart mainporcelain common perf-top mainporcelain common perf-trace mainporcelain audit +perf-version mainporcelain common From c12e039d1233f24ab2726945f883037f47b26f1d Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 13 Sep 2018 20:10:31 -0700 Subject: [PATCH 099/155] perf tools: Report itrace options in help I often forget all the options that --itrace accepts. Instead of burying them in the man page only report them in the normal command line help too to make them easier accessible. v2: Align Signed-off-by: Andi Kleen Cc: Jiri Olsa Cc: Kim Phillips Link: http://lkml.kernel.org/r/20180914031038.4160-2-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 3 ++- tools/perf/builtin-report.c | 2 +- tools/perf/builtin-script.c | 2 +- tools/perf/util/auxtrace.h | 19 +++++++++++++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index b4a29f435b06..eda41673c4f3 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -798,7 +798,8 @@ int cmd_inject(int argc, const char **argv) "kallsyms pathname"), OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"), OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts, - NULL, "opts", "Instruction Tracing options", + NULL, "opts", "Instruction Tracing options\n" + ITRACE_HELP, itrace_parse_synth_opts), OPT_BOOLEAN(0, "strip", &inject.strip, "strip non-synthesized events (use with --itrace)"), diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 7507e4d6dce1..c0703979c51d 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -1104,7 +1104,7 @@ int cmd_report(int argc, const char **argv) OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", "how to display percentage of filtered entries", parse_filter_percentage), OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", - "Instruction Tracing options", + "Instruction Tracing options\n" ITRACE_HELP, itrace_parse_synth_opts), OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename, "Show full source file name path for source lines"), diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 765391b6c88c..66699dd351e0 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -3193,7 +3193,7 @@ int cmd_script(int argc, const char **argv) OPT_BOOLEAN(0, "ns", &nanosecs, "Use 9 decimal places when displaying time"), OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", - "Instruction Tracing options", + "Instruction Tracing options\n" ITRACE_HELP, itrace_parse_synth_opts), OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename, "Show full source file name path for source lines"), diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index a86b7eab6673..0a6ce9c4fc11 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -576,6 +576,23 @@ static inline void auxtrace__free(struct perf_session *session) return session->auxtrace->free(session); } +#define ITRACE_HELP \ +" i: synthesize instructions events\n" \ +" b: synthesize branches events\n" \ +" c: synthesize branches events (calls only)\n" \ +" r: synthesize branches events (returns only)\n" \ +" x: synthesize transactions events\n" \ +" w: synthesize ptwrite events\n" \ +" p: synthesize power events\n" \ +" e: synthesize error events\n" \ +" d: create a debug log\n" \ +" g[len]: synthesize a call chain (use with i or x)\n" \ +" l[len]: synthesize last branch entries (use with i or x)\n" \ +" sNUMBER: skip initial number of events\n" \ +" PERIOD[ns|us|ms|i|t]: specify period to sample stream\n" \ +" concatenate multiple options. Default is ibxwpe or cewp\n" + + #else static inline struct auxtrace_record * @@ -716,6 +733,8 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, struct perf_evlist *evlist, int idx, bool per_cpu); +#define ITRACE_HELP "" + #endif #endif From 03a1f49f26482cf832e7f0157ae5da716d927701 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 18 Sep 2018 05:32:07 -0700 Subject: [PATCH 100/155] tools lib subcmd: Support overwriting the pager Add an interface to the auto pager code that allows callers to overwrite the pager. Signed-off-by: Andi Kleen Cc: Adrian Hunter Cc: Jiri Olsa Cc: Josh Poimboeuf Cc: Kim Phillips Cc: Namhyung Kim Link: http://lkml.kernel.org/r/20180918123214.26728-3-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/subcmd/pager.c | 11 ++++++++++- tools/lib/subcmd/pager.h | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/lib/subcmd/pager.c b/tools/lib/subcmd/pager.c index 9997a8805a82..e3d47b59b14d 100644 --- a/tools/lib/subcmd/pager.c +++ b/tools/lib/subcmd/pager.c @@ -23,6 +23,13 @@ void pager_init(const char *pager_env) subcmd_config.pager_env = pager_env; } +static const char *forced_pager; + +void force_pager(const char *pager) +{ + forced_pager = pager; +} + static void pager_preexec(void) { /* @@ -66,7 +73,9 @@ void setup_pager(void) const char *pager = getenv(subcmd_config.pager_env); struct winsize sz; - if (!isatty(1)) + if (forced_pager) + pager = forced_pager; + if (!isatty(1) && !forced_pager) return; if (ioctl(1, TIOCGWINSZ, &sz) == 0) pager_columns = sz.ws_col; diff --git a/tools/lib/subcmd/pager.h b/tools/lib/subcmd/pager.h index f1a53cf29880..a818964693ab 100644 --- a/tools/lib/subcmd/pager.h +++ b/tools/lib/subcmd/pager.h @@ -7,5 +7,6 @@ extern void pager_init(const char *pager_env); extern void setup_pager(void); extern int pager_in_use(void); extern int pager_get_columns(void); +extern void force_pager(const char *); #endif /* __SUBCMD_PAGER_H */ From 37fed3de555199733805a2d3e03aee7727c09ea4 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 18 Sep 2018 05:32:09 -0700 Subject: [PATCH 101/155] perf script: Allow sym and dso without ip, addr Currently sym and dso require printing ip and addr because the print function is tied to those outputs. With callindent it makes sense to print the symbol or dso without numerical IP or ADDR. So change the dependency check to only check the underlying attribute. Also the branch target output relies on the user_set flag to determine if the branch target should be implicitely printed. When modifying the fields with + or - also set user_set, so that ADDR can be removed. We also need to set wildcard_set to make the initial sanity check pass. This allows to remove a lot of noise in callindent output by dropping the numerical addresses, which are not all that useful. Before % perf script --itrace=cr -F +callindent swapper 0 [000] 156546.354971: 1 branches: pt_config 0 [unknown] ([unknown]) => ffffffff81010486 pt_config ([kernel.kallsyms]) swapper 0 [000] 156546.354971: 1 branches: pt_config ffffffff81010499 pt_config ([kernel.kallsyms]) => ffffffff8101063e pt_event_add ([kernel.kallsyms]) swapper 0 [000] 156546.354971: 1 branches: pt_event_add ffffffff81010635 pt_event_add ([kernel.kallsyms]) => ffffffff8115e687 event_sched_in.isra.107 ([kernel.kallsyms]) swapper 0 [000] 156546.354971: 1 branches: perf_pmu_enable ffffffff8115e726 event_sched_in.isra.107 ([kernel.kallsyms]) => ffffffff811579b0 perf_pmu_enable ([kernel.kallsyms]) swapper 0 [000] 156546.354971: 1 branches: perf_pmu_nop_void ffffffff81151730 perf_pmu_nop_void ([kernel.kallsyms]) => ffffffff8115e72b event_sched_in.isra.107 ([kernel.kallsyms]) swapper 0 [000] 156546.354971: 1 branches: event_sched_in.isra.107 ffffffff8115e737 event_sched_in.isra.107 ([kernel.kallsyms]) => ffffffff8115e7a5 group_sched_in ([kernel.kallsyms]) swapper 0 [000] 156546.354971: 1 branches: __x86_indirect_thunk_rax ffffffff8115e7f6 group_sched_in ([kernel.kallsyms]) => ffffffff81a03000 __x86_indirect_thunk_rax ([kernel.kallsyms]) After % perf script --itrace=cr -F +callindent,-ip,-sym,-symoff swapper 0 [000] 156546.354971: 1 branches: pt_config swapper 0 [000] 156546.354971: 1 branches: pt_config swapper 0 [000] 156546.354971: 1 branches: pt_event_add swapper 0 [000] 156546.354971: 1 branches: perf_pmu_enable swapper 0 [000] 156546.354971: 1 branches: perf_pmu_nop_void swapper 0 [000] 156546.354971: 1 branches: event_sched_in.isra.107 swapper 0 [000] 156546.354971: 1 branches: __x86_indirect_thunk_rax swapper 0 [000] 156546.354971: 1 branches: perf_pmu_nop_int swapper 0 [000] 156546.354971: 1 branches: group_sched_in swapper 0 [000] 156546.354971: 1 branches: event_filter_match swapper 0 [000] 156546.354971: 1 branches: event_filter_match swapper 0 [000] 156546.354971: 1 branches: group_sched_in Signed-off-by: Andi Kleen Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Jiri Olsa Cc: Kim Phillips Link: http://lkml.kernel.org/r/20180918123214.26728-5-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 66699dd351e0..7aa59696e97a 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -406,9 +406,10 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, PERF_OUTPUT_WEIGHT)) return -EINVAL; - if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { + if (PRINT_FIELD(SYM) && + !(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) { pr_err("Display of symbols requested but neither sample IP nor " - "sample address\nis selected. Hence, no addresses to convert " + "sample address\navailable. Hence, no addresses to convert " "to symbols.\n"); return -EINVAL; } @@ -417,10 +418,9 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, "selected.\n"); return -EINVAL; } - if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR) && - !PRINT_FIELD(BRSTACK) && !PRINT_FIELD(BRSTACKSYM) && !PRINT_FIELD(BRSTACKOFF)) { - pr_err("Display of DSO requested but no address to convert. Select\n" - "sample IP, sample address, brstack, brstacksym, or brstackoff.\n"); + if (PRINT_FIELD(DSO) && + !(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) { + pr_err("Display of DSO requested but no address to convert.\n"); return -EINVAL; } if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) { @@ -2491,6 +2491,8 @@ parse: output[j].fields &= ~all_output_options[i].field; else output[j].fields |= all_output_options[i].field; + output[j].user_set = true; + output[j].wildcard_set = true; } } } else { @@ -2501,7 +2503,8 @@ parse: rc = -EINVAL; goto out; } - output[type].fields |= all_output_options[i].field; + output[type].user_set = true; + output[type].wildcard_set = true; } } From a78cdee6fbb136694334ade4cedb331a9d0b4d5e Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 18 Sep 2018 05:32:10 -0700 Subject: [PATCH 102/155] perf script: Print DSO for callindent Now that we don't need to print the IP/ADDR for callindent the DSO is also not printed. It's useful for some cases, so add an own DSO printout for callindent for the case when IP/ADDR is not enabled. Before: % perf script --itrace=cr -F +callindent,-ip,-sym,-symoff,-addr swapper 0 [000] 3377.917072: 1 branches: pt_config swapper 0 [000] 3377.917072: 1 branches: pt_config swapper 0 [000] 3377.917072: 1 branches: pt_event_add swapper 0 [000] 3377.917072: 1 branches: perf_pmu_enable swapper 0 [000] 3377.917072: 1 branches: perf_pmu_nop_void swapper 0 [000] 3377.917072: 1 branches: event_sched_in.isra.107 swapper 0 [000] 3377.917072: 1 branches: __x86_indirect_thunk_rax swapper 0 [000] 3377.917072: 1 branches: perf_pmu_nop_int swapper 0 [000] 3377.917072: 1 branches: group_sched_in swapper 0 [000] 3377.917072: 1 branches: event_filter_match swapper 0 [000] 3377.917072: 1 branches: event_filter_match swapper 0 [000] 3377.917072: 1 branches: group_sched_in After: swapper 0 [000] 3377.917072: 1 branches: ([unknown]) pt_config swapper 0 [000] 3377.917072: 1 branches: ([kernel.kallsyms]) pt_config swapper 0 [000] 3377.917072: 1 branches: ([kernel.kallsyms]) pt_event_add swapper 0 [000] 3377.917072: 1 branches: ([kernel.kallsyms]) perf_pmu_enable swapper 0 [000] 3377.917072: 1 branches: ([kernel.kallsyms]) perf_pmu_nop_void swapper 0 [000] 3377.917072: 1 branches: ([kernel.kallsyms]) event_sched_in.isra.107 swapper 0 [000] 3377.917072: 1 branches: ([kernel.kallsyms]) __x86_indirect_thunk_rax swapper 0 [000] 3377.917072: 1 branches: ([kernel.kallsyms]) perf_pmu_nop_int swapper 0 [000] 3377.917072: 1 branches: ([kernel.kallsyms]) group_sched_in swapper 0 [000] 3377.917072: 1 branches: ([kernel.kallsyms]) event_filter_match swapper 0 [000] 3377.917072: 1 branches: ([kernel.kallsyms]) event_filter_match swapper 0 [000] 3377.917072: 1 branches: ([kernel.kallsyms]) group_sched_in swapper 0 [000] 3377.917072: 1 branches: ([kernel.kallsyms]) __x86_indirect_thunk_rax swapper 0 [000] 3377.917072: 1 branches: ([kernel.kallsyms]) perf_pmu_nop_txn swapper 0 [000] 3377.917072: 1 branches: ([kernel.kallsyms]) event_sched_in.isra.107 (in the kernel case of course it's not very useful, but it's important with user programs where symbols are not unique) Signed-off-by: Andi Kleen Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Jiri Olsa Cc: Kim Phillips Link: http://lkml.kernel.org/r/20180918123214.26728-6-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 7aa59696e97a..7732346bd9dd 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1115,6 +1115,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample, const char *name = NULL; static int spacing; int len = 0; + int dlen = 0; u64 ip = 0; /* @@ -1141,6 +1142,12 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample, ip = sample->ip; } + if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) { + dlen += fprintf(fp, "("); + dlen += map__fprintf_dsoname(al->map, fp); + dlen += fprintf(fp, ")\t"); + } + if (name) len = fprintf(fp, "%*s%s", (int)depth * 4, "", name); else if (ip) @@ -1159,7 +1166,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample, if (len < spacing) len += fprintf(fp, "%*s", spacing - len, ""); - return len; + return len + dlen; } static int perf_sample__fprintf_insn(struct perf_sample *sample, From 4963b0f88bb91ed0122f7b08876ae89fcafb2842 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:44 -0400 Subject: [PATCH 103/155] tools lib traceevent, perf tools: Rename struct event_format to struct tep_event_format In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This renames struct event_format to struct tep_event_format Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185722.495820809@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 186 +++++++++--------- tools/lib/traceevent/event-parse.h | 66 +++---- tools/lib/traceevent/parse-filter.c | 42 ++-- tools/lib/traceevent/plugin_function.c | 2 +- tools/lib/traceevent/plugin_hrtimer.c | 4 +- tools/lib/traceevent/plugin_kmem.c | 2 +- tools/lib/traceevent/plugin_kvm.c | 14 +- tools/lib/traceevent/plugin_mac80211.c | 4 +- tools/lib/traceevent/plugin_sched_switch.c | 4 +- tools/perf/builtin-trace.c | 2 +- tools/perf/util/evsel.h | 4 +- tools/perf/util/header.c | 2 +- tools/perf/util/python.c | 4 +- .../util/scripting-engines/trace-event-perl.c | 6 +- .../scripting-engines/trace-event-python.c | 8 +- tools/perf/util/trace-event-parse.c | 14 +- tools/perf/util/trace-event.c | 8 +- tools/perf/util/trace-event.h | 16 +- 18 files changed, 194 insertions(+), 194 deletions(-) diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 70a42bec6931..bb2ebb322124 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -95,7 +95,7 @@ struct tep_function_handler { static unsigned long long process_defined_func(struct trace_seq *s, void *data, int size, - struct event_format *event, struct print_arg *arg); + struct tep_event_format *event, struct print_arg *arg); static void free_func_handle(struct tep_function_handler *func); @@ -738,16 +738,16 @@ void tep_print_printk(struct tep_handle *pevent) } } -static struct event_format *alloc_event(void) +static struct tep_event_format *alloc_event(void) { - return calloc(1, sizeof(struct event_format)); + return calloc(1, sizeof(struct tep_event_format)); } -static int add_event(struct tep_handle *pevent, struct event_format *event) +static int add_event(struct tep_handle *pevent, struct tep_event_format *event) { int i; - struct event_format **events = realloc(pevent->events, sizeof(event) * - (pevent->nr_events + 1)); + struct tep_event_format **events = realloc(pevent->events, sizeof(event) * + (pevent->nr_events + 1)); if (!events) return -1; @@ -1354,7 +1354,7 @@ static unsigned int type_size(const char *name) return 0; } -static int event_read_fields(struct event_format *event, struct format_field **fields) +static int event_read_fields(struct tep_event_format *event, struct format_field **fields) { struct format_field *field = NULL; enum event_type type; @@ -1641,7 +1641,7 @@ fail_expect: return -1; } -static int event_read_format(struct event_format *event) +static int event_read_format(struct tep_event_format *event) { char *token; int ret; @@ -1674,11 +1674,11 @@ static int event_read_format(struct event_format *event) } static enum event_type -process_arg_token(struct event_format *event, struct print_arg *arg, +process_arg_token(struct tep_event_format *event, struct print_arg *arg, char **tok, enum event_type type); static enum event_type -process_arg(struct event_format *event, struct print_arg *arg, char **tok) +process_arg(struct tep_event_format *event, struct print_arg *arg, char **tok) { enum event_type type; char *token; @@ -1690,14 +1690,14 @@ process_arg(struct event_format *event, struct print_arg *arg, char **tok) } static enum event_type -process_op(struct event_format *event, struct print_arg *arg, char **tok); +process_op(struct tep_event_format *event, struct print_arg *arg, char **tok); /* * For __print_symbolic() and __print_flags, we need to completely * evaluate the first argument, which defines what to print next. */ static enum event_type -process_field_arg(struct event_format *event, struct print_arg *arg, char **tok) +process_field_arg(struct tep_event_format *event, struct print_arg *arg, char **tok) { enum event_type type; @@ -1711,7 +1711,7 @@ process_field_arg(struct event_format *event, struct print_arg *arg, char **tok) } static enum event_type -process_cond(struct event_format *event, struct print_arg *top, char **tok) +process_cond(struct tep_event_format *event, struct print_arg *top, char **tok) { struct print_arg *arg, *left, *right; enum event_type type; @@ -1767,7 +1767,7 @@ out_free: } static enum event_type -process_array(struct event_format *event, struct print_arg *top, char **tok) +process_array(struct tep_event_format *event, struct print_arg *top, char **tok) { struct print_arg *arg; enum event_type type; @@ -1869,7 +1869,7 @@ static int set_op_prio(struct print_arg *arg) /* Note, *tok does not get freed, but will most likely be saved */ static enum event_type -process_op(struct event_format *event, struct print_arg *arg, char **tok) +process_op(struct tep_event_format *event, struct print_arg *arg, char **tok) { struct print_arg *left, *right = NULL; enum event_type type; @@ -2070,7 +2070,7 @@ out_free: } static enum event_type -process_entry(struct event_format *event __maybe_unused, struct print_arg *arg, +process_entry(struct tep_event_format *event __maybe_unused, struct print_arg *arg, char **tok) { enum event_type type; @@ -2109,7 +2109,7 @@ process_entry(struct event_format *event __maybe_unused, struct print_arg *arg, return EVENT_ERROR; } -static int alloc_and_process_delim(struct event_format *event, char *next_token, +static int alloc_and_process_delim(struct tep_event_format *event, char *next_token, struct print_arg **print_arg) { struct print_arg *field; @@ -2444,7 +2444,7 @@ static char *arg_eval (struct print_arg *arg) } static enum event_type -process_fields(struct event_format *event, struct print_flag_sym **list, char **tok) +process_fields(struct tep_event_format *event, struct print_flag_sym **list, char **tok) { enum event_type type; struct print_arg *arg = NULL; @@ -2525,7 +2525,7 @@ out_free: } static enum event_type -process_flags(struct event_format *event, struct print_arg *arg, char **tok) +process_flags(struct tep_event_format *event, struct print_arg *arg, char **tok) { struct print_arg *field; enum event_type type; @@ -2578,7 +2578,7 @@ out_free: } static enum event_type -process_symbols(struct event_format *event, struct print_arg *arg, char **tok) +process_symbols(struct tep_event_format *event, struct print_arg *arg, char **tok) { struct print_arg *field; enum event_type type; @@ -2617,7 +2617,7 @@ out_free: } static enum event_type -process_hex_common(struct event_format *event, struct print_arg *arg, +process_hex_common(struct tep_event_format *event, struct print_arg *arg, char **tok, enum print_arg_type type) { memset(arg, 0, sizeof(*arg)); @@ -2640,20 +2640,20 @@ out: } static enum event_type -process_hex(struct event_format *event, struct print_arg *arg, char **tok) +process_hex(struct tep_event_format *event, struct print_arg *arg, char **tok) { return process_hex_common(event, arg, tok, PRINT_HEX); } static enum event_type -process_hex_str(struct event_format *event, struct print_arg *arg, +process_hex_str(struct tep_event_format *event, struct print_arg *arg, char **tok) { return process_hex_common(event, arg, tok, PRINT_HEX_STR); } static enum event_type -process_int_array(struct event_format *event, struct print_arg *arg, char **tok) +process_int_array(struct tep_event_format *event, struct print_arg *arg, char **tok) { memset(arg, 0, sizeof(*arg)); arg->type = PRINT_INT_ARRAY; @@ -2681,7 +2681,7 @@ out: } static enum event_type -process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok) +process_dynamic_array(struct tep_event_format *event, struct print_arg *arg, char **tok) { struct format_field *field; enum event_type type; @@ -2745,7 +2745,7 @@ process_dynamic_array(struct event_format *event, struct print_arg *arg, char ** } static enum event_type -process_dynamic_array_len(struct event_format *event, struct print_arg *arg, +process_dynamic_array_len(struct tep_event_format *event, struct print_arg *arg, char **tok) { struct format_field *field; @@ -2781,7 +2781,7 @@ process_dynamic_array_len(struct event_format *event, struct print_arg *arg, } static enum event_type -process_paren(struct event_format *event, struct print_arg *arg, char **tok) +process_paren(struct tep_event_format *event, struct print_arg *arg, char **tok) { struct print_arg *item_arg; enum event_type type; @@ -2844,7 +2844,7 @@ process_paren(struct event_format *event, struct print_arg *arg, char **tok) static enum event_type -process_str(struct event_format *event __maybe_unused, struct print_arg *arg, +process_str(struct tep_event_format *event __maybe_unused, struct print_arg *arg, char **tok) { enum event_type type; @@ -2873,8 +2873,8 @@ process_str(struct event_format *event __maybe_unused, struct print_arg *arg, } static enum event_type -process_bitmask(struct event_format *event __maybe_unused, struct print_arg *arg, - char **tok) +process_bitmask(struct tep_event_format *event __maybe_unused, struct print_arg *arg, + char **tok) { enum event_type type; char *token; @@ -2934,7 +2934,7 @@ static void remove_func_handler(struct tep_handle *pevent, char *func_name) } static enum event_type -process_func_handler(struct event_format *event, struct tep_function_handler *func, +process_func_handler(struct tep_event_format *event, struct tep_function_handler *func, struct print_arg *arg, char **tok) { struct print_arg **next_arg; @@ -2992,7 +2992,7 @@ err: } static enum event_type -process_function(struct event_format *event, struct print_arg *arg, +process_function(struct tep_event_format *event, struct print_arg *arg, char *token, char **tok) { struct tep_function_handler *func; @@ -3048,7 +3048,7 @@ process_function(struct event_format *event, struct print_arg *arg, } static enum event_type -process_arg_token(struct event_format *event, struct print_arg *arg, +process_arg_token(struct tep_event_format *event, struct print_arg *arg, char **tok, enum event_type type) { char *token; @@ -3136,7 +3136,7 @@ process_arg_token(struct event_format *event, struct print_arg *arg, return type; } -static int event_read_print_args(struct event_format *event, struct print_arg **list) +static int event_read_print_args(struct tep_event_format *event, struct print_arg **list) { enum event_type type = EVENT_ERROR; struct print_arg *arg; @@ -3194,7 +3194,7 @@ static int event_read_print_args(struct event_format *event, struct print_arg ** return args; } -static int event_read_print(struct event_format *event) +static int event_read_print(struct tep_event_format *event) { enum event_type type; char *token; @@ -3260,7 +3260,7 @@ static int event_read_print(struct event_format *event) * This only searchs the common fields and not all field. */ struct format_field * -tep_find_common_field(struct event_format *event, const char *name) +tep_find_common_field(struct tep_event_format *event, const char *name) { struct format_field *format; @@ -3282,7 +3282,7 @@ tep_find_common_field(struct event_format *event, const char *name) * This does not search common fields. */ struct format_field * -tep_find_field(struct event_format *event, const char *name) +tep_find_field(struct tep_event_format *event, const char *name) { struct format_field *format; @@ -3305,7 +3305,7 @@ tep_find_field(struct event_format *event, const char *name) * the non-common ones if a common one was not found. */ struct format_field * -tep_find_any_field(struct event_format *event, const char *name) +tep_find_any_field(struct tep_event_format *event, const char *name) { struct format_field *format; @@ -3374,7 +3374,7 @@ int tep_read_number_field(struct format_field *field, const void *data, static int get_common_info(struct tep_handle *pevent, const char *type, int *offset, int *size) { - struct event_format *event; + struct tep_event_format *event; struct format_field *field; /* @@ -3461,11 +3461,11 @@ static int events_id_cmp(const void *a, const void *b); * * Returns an event that has a given @id. */ -struct event_format *tep_find_event(struct tep_handle *pevent, int id) +struct tep_event_format *tep_find_event(struct tep_handle *pevent, int id) { - struct event_format **eventptr; - struct event_format key; - struct event_format *pkey = &key; + struct tep_event_format **eventptr; + struct tep_event_format key; + struct tep_event_format *pkey = &key; /* Check cache first */ if (pevent->last_event && pevent->last_event->id == id) @@ -3493,11 +3493,11 @@ struct event_format *tep_find_event(struct tep_handle *pevent, int id) * This returns an event with a given @name and under the system * @sys. If @sys is NULL the first event with @name is returned. */ -struct event_format * +struct tep_event_format * tep_find_event_by_name(struct tep_handle *pevent, const char *sys, const char *name) { - struct event_format *event; + struct tep_event_format *event; int i; if (pevent->last_event && @@ -3522,7 +3522,7 @@ tep_find_event_by_name(struct tep_handle *pevent, } static unsigned long long -eval_num_arg(void *data, int size, struct event_format *event, struct print_arg *arg) +eval_num_arg(void *data, int size, struct tep_event_format *event, struct print_arg *arg) { struct tep_handle *pevent = event->pevent; unsigned long long val = 0; @@ -3862,7 +3862,7 @@ static void print_bitmask_to_seq(struct tep_handle *pevent, } static void print_str_arg(struct trace_seq *s, void *data, int size, - struct event_format *event, const char *format, + struct tep_event_format *event, const char *format, int len_arg, struct print_arg *arg) { struct tep_handle *pevent = event->pevent; @@ -4117,7 +4117,7 @@ out_warning_field: static unsigned long long process_defined_func(struct trace_seq *s, void *data, int size, - struct event_format *event, struct print_arg *arg) + struct tep_event_format *event, struct print_arg *arg) { struct tep_function_handler *func_handle = arg->func.func; struct func_params *param; @@ -4212,7 +4212,7 @@ static void free_args(struct print_arg *args) } } -static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event_format *event) +static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct tep_event_format *event) { struct tep_handle *pevent = event->pevent; struct format_field *field, *ip_field; @@ -4389,7 +4389,7 @@ out_free: static char * get_bprint_format(void *data, int size __maybe_unused, - struct event_format *event) + struct tep_event_format *event) { struct tep_handle *pevent = event->pevent; unsigned long long addr; @@ -4424,7 +4424,7 @@ get_bprint_format(void *data, int size __maybe_unused, } static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size, - struct event_format *event, struct print_arg *arg) + struct tep_event_format *event, struct print_arg *arg) { unsigned char *buf; const char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"; @@ -4577,7 +4577,7 @@ static void print_ip6_addr(struct trace_seq *s, char i, unsigned char *buf) * %pISpc print an IP address based on sockaddr; p adds port. */ static int print_ipv4_arg(struct trace_seq *s, const char *ptr, char i, - void *data, int size, struct event_format *event, + void *data, int size, struct tep_event_format *event, struct print_arg *arg) { unsigned char *buf; @@ -4614,7 +4614,7 @@ static int print_ipv4_arg(struct trace_seq *s, const char *ptr, char i, } static int print_ipv6_arg(struct trace_seq *s, const char *ptr, char i, - void *data, int size, struct event_format *event, + void *data, int size, struct tep_event_format *event, struct print_arg *arg) { char have_c = 0; @@ -4664,7 +4664,7 @@ static int print_ipv6_arg(struct trace_seq *s, const char *ptr, char i, } static int print_ipsa_arg(struct trace_seq *s, const char *ptr, char i, - void *data, int size, struct event_format *event, + void *data, int size, struct tep_event_format *event, struct print_arg *arg) { char have_c = 0, have_p = 0; @@ -4746,7 +4746,7 @@ static int print_ipsa_arg(struct trace_seq *s, const char *ptr, char i, } static int print_ip_arg(struct trace_seq *s, const char *ptr, - void *data, int size, struct event_format *event, + void *data, int size, struct tep_event_format *event, struct print_arg *arg) { char i = *ptr; /* 'i' or 'I' */ @@ -4853,7 +4853,7 @@ void tep_print_field(struct trace_seq *s, void *data, } void tep_print_fields(struct trace_seq *s, void *data, - int size __maybe_unused, struct event_format *event) + int size __maybe_unused, struct tep_event_format *event) { struct format_field *field; @@ -4865,7 +4865,7 @@ void tep_print_fields(struct trace_seq *s, void *data, } } -static void pretty_print(struct trace_seq *s, void *data, int size, struct event_format *event) +static void pretty_print(struct trace_seq *s, void *data, int size, struct tep_event_format *event) { struct tep_handle *pevent = event->pevent; struct print_fmt *print_fmt = &event->print_fmt; @@ -5228,7 +5228,7 @@ int tep_data_type(struct tep_handle *pevent, struct tep_record *rec) * * This returns the event form a given @type; */ -struct event_format *tep_data_event_from_type(struct tep_handle *pevent, int type) +struct tep_event_format *tep_data_event_from_type(struct tep_handle *pevent, int type) { return tep_find_event(pevent, type); } @@ -5386,7 +5386,7 @@ int tep_cmdline_pid(struct tep_handle *pevent, struct cmdline *cmdline) * This parses the raw @data using the given @event information and * writes the print format into the trace_seq. */ -void tep_event_info(struct trace_seq *s, struct event_format *event, +void tep_event_info(struct trace_seq *s, struct tep_event_format *event, struct tep_record *record) { int print_pretty = 1; @@ -5427,7 +5427,7 @@ static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock) * Returns the associated event for a given record, or NULL if non is * is found. */ -struct event_format * +struct tep_event_format * tep_find_event_by_record(struct tep_handle *pevent, struct tep_record *record) { int type; @@ -5452,7 +5452,7 @@ tep_find_event_by_record(struct tep_handle *pevent, struct tep_record *record) * Writes the tasks comm, pid and CPU to @s. */ void tep_print_event_task(struct tep_handle *pevent, struct trace_seq *s, - struct event_format *event, + struct tep_event_format *event, struct tep_record *record) { void *data = record->data; @@ -5480,7 +5480,7 @@ void tep_print_event_task(struct tep_handle *pevent, struct trace_seq *s, * Writes the timestamp of the record into @s. */ void tep_print_event_time(struct tep_handle *pevent, struct trace_seq *s, - struct event_format *event, + struct tep_event_format *event, struct tep_record *record, bool use_trace_clock) { @@ -5530,7 +5530,7 @@ void tep_print_event_time(struct tep_handle *pevent, struct trace_seq *s, * Writes the parsing of the record's data to @s. */ void tep_print_event_data(struct tep_handle *pevent, struct trace_seq *s, - struct event_format *event, + struct tep_event_format *event, struct tep_record *record) { static const char *spaces = " "; /* 20 spaces */ @@ -5549,7 +5549,7 @@ void tep_print_event_data(struct tep_handle *pevent, struct trace_seq *s, void tep_print_event(struct tep_handle *pevent, struct trace_seq *s, struct tep_record *record, bool use_trace_clock) { - struct event_format *event; + struct tep_event_format *event; event = tep_find_event_by_record(pevent, record); if (!event) { @@ -5571,8 +5571,8 @@ void tep_print_event(struct tep_handle *pevent, struct trace_seq *s, static int events_id_cmp(const void *a, const void *b) { - struct event_format * const * ea = a; - struct event_format * const * eb = b; + struct tep_event_format * const * ea = a; + struct tep_event_format * const * eb = b; if ((*ea)->id < (*eb)->id) return -1; @@ -5585,8 +5585,8 @@ static int events_id_cmp(const void *a, const void *b) static int events_name_cmp(const void *a, const void *b) { - struct event_format * const * ea = a; - struct event_format * const * eb = b; + struct tep_event_format * const * ea = a; + struct tep_event_format * const * eb = b; int res; res = strcmp((*ea)->name, (*eb)->name); @@ -5602,8 +5602,8 @@ static int events_name_cmp(const void *a, const void *b) static int events_system_cmp(const void *a, const void *b) { - struct event_format * const * ea = a; - struct event_format * const * eb = b; + struct tep_event_format * const * ea = a; + struct tep_event_format * const * eb = b; int res; res = strcmp((*ea)->system, (*eb)->system); @@ -5617,9 +5617,9 @@ static int events_system_cmp(const void *a, const void *b) return events_id_cmp(a, b); } -struct event_format **tep_list_events(struct tep_handle *pevent, enum event_sort_type sort_type) +struct tep_event_format **tep_list_events(struct tep_handle *pevent, enum event_sort_type sort_type) { - struct event_format **events; + struct tep_event_format **events; int (*sort)(const void *a, const void *b); events = pevent->sort_events; @@ -5702,7 +5702,7 @@ get_event_fields(const char *type, const char *name, * Returns an allocated array of fields. The last item in the array is NULL. * The array must be freed with free(). */ -struct format_field **tep_event_common_fields(struct event_format *event) +struct format_field **tep_event_common_fields(struct tep_event_format *event) { return get_event_fields("common", event->name, event->format.nr_common, @@ -5716,7 +5716,7 @@ struct format_field **tep_event_common_fields(struct event_format *event) * Returns an allocated array of fields. The last item in the array is NULL. * The array must be freed with free(). */ -struct format_field **tep_event_fields(struct event_format *event) +struct format_field **tep_event_fields(struct tep_event_format *event) { return get_event_fields("event", event->name, event->format.nr_fields, @@ -5958,7 +5958,7 @@ int tep_parse_header_page(struct tep_handle *pevent, char *buf, unsigned long si return 0; } -static int event_matches(struct event_format *event, +static int event_matches(struct tep_event_format *event, int id, const char *sys_name, const char *event_name) { @@ -5981,7 +5981,7 @@ static void free_handler(struct event_handler *handle) free(handle); } -static int find_event_handle(struct tep_handle *pevent, struct event_format *event) +static int find_event_handle(struct tep_handle *pevent, struct tep_event_format *event) { struct event_handler *handle, **next; @@ -6022,11 +6022,11 @@ static int find_event_handle(struct tep_handle *pevent, struct event_format *eve * * /sys/kernel/debug/tracing/events/.../.../format */ -enum tep_errno __tep_parse_format(struct event_format **eventp, +enum tep_errno __tep_parse_format(struct tep_event_format **eventp, struct tep_handle *pevent, const char *buf, unsigned long size, const char *sys) { - struct event_format *event; + struct tep_event_format *event; int ret; init_input_buf(buf, size); @@ -6131,12 +6131,12 @@ enum tep_errno __tep_parse_format(struct event_format **eventp, static enum tep_errno __parse_event(struct tep_handle *pevent, - struct event_format **eventp, + struct tep_event_format **eventp, const char *buf, unsigned long size, const char *sys) { int ret = __tep_parse_format(eventp, pevent, buf, size, sys); - struct event_format *event = *eventp; + struct tep_event_format *event = *eventp; if (event == NULL) return ret; @@ -6173,7 +6173,7 @@ event_add_failed: * /sys/kernel/debug/tracing/events/.../.../format */ enum tep_errno tep_parse_format(struct tep_handle *pevent, - struct event_format **eventp, + struct tep_event_format **eventp, const char *buf, unsigned long size, const char *sys) { @@ -6197,7 +6197,7 @@ enum tep_errno tep_parse_format(struct tep_handle *pevent, enum tep_errno tep_parse_event(struct tep_handle *pevent, const char *buf, unsigned long size, const char *sys) { - struct event_format *event = NULL; + struct tep_event_format *event = NULL; return __parse_event(pevent, &event, buf, size, sys); } @@ -6263,7 +6263,7 @@ int get_field_val(struct trace_seq *s, struct format_field *field, * * On failure, it returns NULL. */ -void *tep_get_field_raw(struct trace_seq *s, struct event_format *event, +void *tep_get_field_raw(struct trace_seq *s, struct tep_event_format *event, const char *name, struct tep_record *record, int *len, int err) { @@ -6310,7 +6310,7 @@ void *tep_get_field_raw(struct trace_seq *s, struct event_format *event, * * Returns 0 on success -1 on field not found. */ -int tep_get_field_val(struct trace_seq *s, struct event_format *event, +int tep_get_field_val(struct trace_seq *s, struct tep_event_format *event, const char *name, struct tep_record *record, unsigned long long *val, int err) { @@ -6335,7 +6335,7 @@ int tep_get_field_val(struct trace_seq *s, struct event_format *event, * * Returns 0 on success -1 on field not found. */ -int tep_get_common_field_val(struct trace_seq *s, struct event_format *event, +int tep_get_common_field_val(struct trace_seq *s, struct tep_event_format *event, const char *name, struct tep_record *record, unsigned long long *val, int err) { @@ -6360,7 +6360,7 @@ int tep_get_common_field_val(struct trace_seq *s, struct event_format *event, * * Returns 0 on success -1 on field not found. */ -int tep_get_any_field_val(struct trace_seq *s, struct event_format *event, +int tep_get_any_field_val(struct trace_seq *s, struct tep_event_format *event, const char *name, struct tep_record *record, unsigned long long *val, int err) { @@ -6386,7 +6386,7 @@ int tep_get_any_field_val(struct trace_seq *s, struct event_format *event, * Returns: 0 on success, -1 field not found, or 1 if buffer is full. */ int tep_print_num_field(struct trace_seq *s, const char *fmt, - struct event_format *event, const char *name, + struct tep_event_format *event, const char *name, struct tep_record *record, int err) { struct format_field *field = tep_find_field(event, name); @@ -6418,7 +6418,7 @@ int tep_print_num_field(struct trace_seq *s, const char *fmt, * Returns: 0 on success, -1 field not found, or 1 if buffer is full. */ int tep_print_func_field(struct trace_seq *s, const char *fmt, - struct event_format *event, const char *name, + struct tep_event_format *event, const char *name, struct tep_record *record, int err) { struct format_field *field = tep_find_field(event, name); @@ -6578,11 +6578,11 @@ int tep_unregister_print_function(struct tep_handle *pevent, return -1; } -static struct event_format *search_event(struct tep_handle *pevent, int id, +static struct tep_event_format *search_event(struct tep_handle *pevent, int id, const char *sys_name, const char *event_name) { - struct event_format *event; + struct tep_event_format *event; if (id >= 0) { /* search by id */ @@ -6622,7 +6622,7 @@ int tep_register_event_handler(struct tep_handle *pevent, int id, const char *sys_name, const char *event_name, tep_event_handler_func func, void *context) { - struct event_format *event; + struct tep_event_format *event; struct event_handler *handle; event = search_event(pevent, id, sys_name, event_name); @@ -6706,7 +6706,7 @@ int tep_unregister_event_handler(struct tep_handle *pevent, int id, const char *sys_name, const char *event_name, tep_event_handler_func func, void *context) { - struct event_format *event; + struct tep_event_format *event; struct event_handler *handle; struct event_handler **next; @@ -6784,7 +6784,7 @@ static void free_formats(struct format *format) free_format_fields(format->fields); } -void tep_free_format(struct event_format *event) +void tep_free_format(struct tep_event_format *event) { free(event->name); free(event->system); diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index fa665c66bfa4..82de69c2b054 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -54,14 +54,14 @@ struct tep_record { #endif }; -/* ----------------------- pevent ----------------------- */ +/* ----------------------- tep ----------------------- */ struct tep_handle; -struct event_format; +struct tep_event_format; typedef int (*tep_event_handler_func)(struct trace_seq *s, struct tep_record *record, - struct event_format *event, + struct tep_event_format *event, void *context); typedef int (*tep_plugin_load_func)(struct tep_handle *pevent); @@ -143,7 +143,7 @@ enum format_flags { struct format_field { struct format_field *next; - struct event_format *event; + struct tep_event_format *event; char *type; char *name; char *alias; @@ -277,7 +277,7 @@ struct print_fmt { struct print_arg *args; }; -struct event_format { +struct tep_event_format { struct tep_handle *pevent; char *name; int id; @@ -451,9 +451,9 @@ struct tep_handle { unsigned int printk_count; - struct event_format **events; + struct tep_event_format **events; int nr_events; - struct event_format **sort_events; + struct tep_event_format **sort_events; enum event_sort_type last_type; int type_offset; @@ -485,7 +485,7 @@ struct tep_handle { struct tep_function_handler *func_handlers; /* cache */ - struct event_format *last_event; + struct tep_event_format *last_event; char *trace_clock; }; @@ -585,14 +585,14 @@ int tep_register_print_string(struct tep_handle *pevent, const char *fmt, int tep_pid_is_registered(struct tep_handle *pevent, int pid); void tep_print_event_task(struct tep_handle *pevent, struct trace_seq *s, - struct event_format *event, + struct tep_event_format *event, struct tep_record *record); void tep_print_event_time(struct tep_handle *pevent, struct trace_seq *s, - struct event_format *event, + struct tep_event_format *event, struct tep_record *record, bool use_trace_clock); void tep_print_event_data(struct tep_handle *pevent, struct trace_seq *s, - struct event_format *event, + struct tep_event_format *event, struct tep_record *record); void tep_print_event(struct tep_handle *pevent, struct trace_seq *s, struct tep_record *record, bool use_trace_clock); @@ -603,32 +603,32 @@ int tep_parse_header_page(struct tep_handle *pevent, char *buf, unsigned long si enum tep_errno tep_parse_event(struct tep_handle *pevent, const char *buf, unsigned long size, const char *sys); enum tep_errno tep_parse_format(struct tep_handle *pevent, - struct event_format **eventp, + struct tep_event_format **eventp, const char *buf, unsigned long size, const char *sys); -void tep_free_format(struct event_format *event); +void tep_free_format(struct tep_event_format *event); void tep_free_format_field(struct format_field *field); -void *tep_get_field_raw(struct trace_seq *s, struct event_format *event, +void *tep_get_field_raw(struct trace_seq *s, struct tep_event_format *event, const char *name, struct tep_record *record, int *len, int err); -int tep_get_field_val(struct trace_seq *s, struct event_format *event, +int tep_get_field_val(struct trace_seq *s, struct tep_event_format *event, const char *name, struct tep_record *record, unsigned long long *val, int err); -int tep_get_common_field_val(struct trace_seq *s, struct event_format *event, +int tep_get_common_field_val(struct trace_seq *s, struct tep_event_format *event, const char *name, struct tep_record *record, unsigned long long *val, int err); -int tep_get_any_field_val(struct trace_seq *s, struct event_format *event, +int tep_get_any_field_val(struct trace_seq *s, struct tep_event_format *event, const char *name, struct tep_record *record, unsigned long long *val, int err); int tep_print_num_field(struct trace_seq *s, const char *fmt, - struct event_format *event, const char *name, - struct tep_record *record, int err); + struct tep_event_format *event, const char *name, + struct tep_record *record, int err); int tep_print_func_field(struct trace_seq *s, const char *fmt, - struct event_format *event, const char *name, + struct tep_event_format *event, const char *name, struct tep_record *record, int err); int tep_register_event_handler(struct tep_handle *pevent, int id, @@ -644,9 +644,9 @@ int tep_register_print_function(struct tep_handle *pevent, int tep_unregister_print_function(struct tep_handle *pevent, tep_func_handler func, char *name); -struct format_field *tep_find_common_field(struct event_format *event, const char *name); -struct format_field *tep_find_field(struct event_format *event, const char *name); -struct format_field *tep_find_any_field(struct event_format *event, const char *name); +struct format_field *tep_find_common_field(struct tep_event_format *event, const char *name); +struct format_field *tep_find_field(struct tep_event_format *event, const char *name); +struct format_field *tep_find_any_field(struct tep_event_format *event, const char *name); const char *tep_find_function(struct tep_handle *pevent, unsigned long long addr); unsigned long long @@ -655,18 +655,18 @@ unsigned long long tep_read_number(struct tep_handle *pevent, const void *ptr, i int tep_read_number_field(struct format_field *field, const void *data, unsigned long long *value); -struct event_format *tep_find_event(struct tep_handle *pevent, int id); +struct tep_event_format *tep_find_event(struct tep_handle *pevent, int id); -struct event_format * +struct tep_event_format * tep_find_event_by_name(struct tep_handle *pevent, const char *sys, const char *name); -struct event_format * +struct tep_event_format * tep_find_event_by_record(struct tep_handle *pevent, struct tep_record *record); void tep_data_lat_fmt(struct tep_handle *pevent, struct trace_seq *s, struct tep_record *record); int tep_data_type(struct tep_handle *pevent, struct tep_record *rec); -struct event_format *tep_data_event_from_type(struct tep_handle *pevent, int type); +struct tep_event_format *tep_data_event_from_type(struct tep_handle *pevent, int type); int tep_data_pid(struct tep_handle *pevent, struct tep_record *rec); int tep_data_preempt_count(struct tep_handle *pevent, struct tep_record *rec); int tep_data_flags(struct tep_handle *pevent, struct tep_record *rec); @@ -679,15 +679,15 @@ int tep_cmdline_pid(struct tep_handle *pevent, struct cmdline *cmdline); void tep_print_field(struct trace_seq *s, void *data, struct format_field *field); void tep_print_fields(struct trace_seq *s, void *data, - int size __maybe_unused, struct event_format *event); -void tep_event_info(struct trace_seq *s, struct event_format *event, + int size __maybe_unused, struct tep_event_format *event); +void tep_event_info(struct trace_seq *s, struct tep_event_format *event, struct tep_record *record); int tep_strerror(struct tep_handle *pevent, enum tep_errno errnum, char *buf, size_t buflen); -struct event_format **tep_list_events(struct tep_handle *pevent, enum event_sort_type); -struct format_field **tep_event_common_fields(struct event_format *event); -struct format_field **tep_event_fields(struct event_format *event); +struct tep_event_format **tep_list_events(struct tep_handle *pevent, enum event_sort_type); +struct format_field **tep_event_common_fields(struct tep_event_format *event); +struct format_field **tep_event_fields(struct tep_event_format *event); static inline int tep_get_cpus(struct tep_handle *pevent) { @@ -884,7 +884,7 @@ struct filter_arg { struct filter_type { int event_id; - struct event_format *event; + struct tep_event_format *event; struct filter_arg *filter; }; diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index e76154c02ee7..5572756307ab 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -26,7 +26,7 @@ static struct format_field cpu = { struct event_list { struct event_list *next; - struct event_format *event; + struct tep_event_format *event; }; static void show_error(char *error_buf, const char *fmt, ...) @@ -228,7 +228,7 @@ static void free_arg(struct filter_arg *arg) } static int add_event(struct event_list **events, - struct event_format *event) + struct tep_event_format *event) { struct event_list *list; @@ -242,7 +242,7 @@ static int add_event(struct event_list **events, return 0; } -static int event_match(struct event_format *event, +static int event_match(struct tep_event_format *event, regex_t *sreg, regex_t *ereg) { if (sreg) { @@ -258,7 +258,7 @@ static enum tep_errno find_event(struct tep_handle *pevent, struct event_list **events, char *sys_name, char *event_name) { - struct event_format *event; + struct tep_event_format *event; regex_t ereg; regex_t sreg; int match = 0; @@ -333,7 +333,7 @@ static void free_events(struct event_list *events) } static enum tep_errno -create_arg_item(struct event_format *event, const char *token, +create_arg_item(struct tep_event_format *event, const char *token, enum event_type type, struct filter_arg **parg, char *error_str) { struct format_field *field; @@ -939,7 +939,7 @@ static int collapse_tree(struct filter_arg *arg, } static enum tep_errno -process_filter(struct event_format *event, struct filter_arg **parg, +process_filter(struct tep_event_format *event, struct filter_arg **parg, char *error_str, int not) { enum event_type type; @@ -1179,7 +1179,7 @@ process_filter(struct event_format *event, struct filter_arg **parg, } static enum tep_errno -process_event(struct event_format *event, const char *filter_str, +process_event(struct tep_event_format *event, const char *filter_str, struct filter_arg **parg, char *error_str) { int ret; @@ -1204,7 +1204,7 @@ process_event(struct event_format *event, const char *filter_str, } static enum tep_errno -filter_event(struct event_filter *filter, struct event_format *event, +filter_event(struct event_filter *filter, struct tep_event_format *event, const char *filter_str, char *error_str) { struct filter_type *filter_type; @@ -1456,7 +1456,7 @@ static int copy_filter_type(struct event_filter *filter, struct filter_type *filter_type) { struct filter_arg *arg; - struct event_format *event; + struct tep_event_format *event; const char *sys; const char *name; char *str; @@ -1538,7 +1538,7 @@ int tep_update_trivial(struct event_filter *dest, struct event_filter *source, { struct tep_handle *src_pevent; struct tep_handle *dest_pevent; - struct event_format *event; + struct tep_event_format *event; struct filter_type *filter_type; struct filter_arg *arg; char *str; @@ -1682,11 +1682,11 @@ int tep_filter_event_has_trivial(struct event_filter *filter, } } -static int test_filter(struct event_format *event, struct filter_arg *arg, +static int test_filter(struct tep_event_format *event, struct filter_arg *arg, struct tep_record *record, enum tep_errno *err); static const char * -get_comm(struct event_format *event, struct tep_record *record) +get_comm(struct tep_event_format *event, struct tep_record *record) { const char *comm; int pid; @@ -1697,7 +1697,7 @@ get_comm(struct event_format *event, struct tep_record *record) } static unsigned long long -get_value(struct event_format *event, +get_value(struct tep_event_format *event, struct format_field *field, struct tep_record *record) { unsigned long long val; @@ -1733,11 +1733,11 @@ get_value(struct event_format *event, } static unsigned long long -get_arg_value(struct event_format *event, struct filter_arg *arg, +get_arg_value(struct tep_event_format *event, struct filter_arg *arg, struct tep_record *record, enum tep_errno *err); static unsigned long long -get_exp_value(struct event_format *event, struct filter_arg *arg, +get_exp_value(struct tep_event_format *event, struct filter_arg *arg, struct tep_record *record, enum tep_errno *err) { unsigned long long lval, rval; @@ -1792,7 +1792,7 @@ get_exp_value(struct event_format *event, struct filter_arg *arg, } static unsigned long long -get_arg_value(struct event_format *event, struct filter_arg *arg, +get_arg_value(struct tep_event_format *event, struct filter_arg *arg, struct tep_record *record, enum tep_errno *err) { switch (arg->type) { @@ -1816,7 +1816,7 @@ get_arg_value(struct event_format *event, struct filter_arg *arg, return 0; } -static int test_num(struct event_format *event, struct filter_arg *arg, +static int test_num(struct tep_event_format *event, struct filter_arg *arg, struct tep_record *record, enum tep_errno *err) { unsigned long long lval, rval; @@ -1859,7 +1859,7 @@ static int test_num(struct event_format *event, struct filter_arg *arg, static const char *get_field_str(struct filter_arg *arg, struct tep_record *record) { - struct event_format *event; + struct tep_event_format *event; struct tep_handle *pevent; unsigned long long addr; const char *val = NULL; @@ -1907,7 +1907,7 @@ static const char *get_field_str(struct filter_arg *arg, struct tep_record *reco return val; } -static int test_str(struct event_format *event, struct filter_arg *arg, +static int test_str(struct tep_event_format *event, struct filter_arg *arg, struct tep_record *record, enum tep_errno *err) { const char *val; @@ -1938,7 +1938,7 @@ static int test_str(struct event_format *event, struct filter_arg *arg, } } -static int test_op(struct event_format *event, struct filter_arg *arg, +static int test_op(struct tep_event_format *event, struct filter_arg *arg, struct tep_record *record, enum tep_errno *err) { switch (arg->op.type) { @@ -1960,7 +1960,7 @@ static int test_op(struct event_format *event, struct filter_arg *arg, } } -static int test_filter(struct event_format *event, struct filter_arg *arg, +static int test_filter(struct tep_event_format *event, struct filter_arg *arg, struct tep_record *record, enum tep_errno *err) { if (*err) { diff --git a/tools/lib/traceevent/plugin_function.c b/tools/lib/traceevent/plugin_function.c index 2919042e7dc2..528acc75d81a 100644 --- a/tools/lib/traceevent/plugin_function.c +++ b/tools/lib/traceevent/plugin_function.c @@ -124,7 +124,7 @@ static int add_and_get_index(const char *parent, const char *child, int cpu) } static int function_handler(struct trace_seq *s, struct tep_record *record, - struct event_format *event, void *context) + struct tep_event_format *event, void *context) { struct tep_handle *pevent = event->pevent; unsigned long long function; diff --git a/tools/lib/traceevent/plugin_hrtimer.c b/tools/lib/traceevent/plugin_hrtimer.c index 29b608076ea0..9aa05b4ca811 100644 --- a/tools/lib/traceevent/plugin_hrtimer.c +++ b/tools/lib/traceevent/plugin_hrtimer.c @@ -27,7 +27,7 @@ static int timer_expire_handler(struct trace_seq *s, struct tep_record *record, - struct event_format *event, void *context) + struct tep_event_format *event, void *context) { trace_seq_printf(s, "hrtimer="); @@ -47,7 +47,7 @@ static int timer_expire_handler(struct trace_seq *s, static int timer_start_handler(struct trace_seq *s, struct tep_record *record, - struct event_format *event, void *context) + struct tep_event_format *event, void *context) { trace_seq_printf(s, "hrtimer="); diff --git a/tools/lib/traceevent/plugin_kmem.c b/tools/lib/traceevent/plugin_kmem.c index a7a162575e2c..5632aff43aba 100644 --- a/tools/lib/traceevent/plugin_kmem.c +++ b/tools/lib/traceevent/plugin_kmem.c @@ -25,7 +25,7 @@ #include "trace-seq.h" static int call_site_handler(struct trace_seq *s, struct tep_record *record, - struct event_format *event, void *context) + struct tep_event_format *event, void *context) { struct format_field *field; unsigned long long val, addr; diff --git a/tools/lib/traceevent/plugin_kvm.c b/tools/lib/traceevent/plugin_kvm.c index a0dfd3d0f197..d13c22846fa9 100644 --- a/tools/lib/traceevent/plugin_kvm.c +++ b/tools/lib/traceevent/plugin_kvm.c @@ -249,7 +249,7 @@ static const char *find_exit_reason(unsigned isa, int val) } static int print_exit_reason(struct trace_seq *s, struct tep_record *record, - struct event_format *event, const char *field) + struct tep_event_format *event, const char *field) { unsigned long long isa; unsigned long long val; @@ -270,7 +270,7 @@ static int print_exit_reason(struct trace_seq *s, struct tep_record *record, } static int kvm_exit_handler(struct trace_seq *s, struct tep_record *record, - struct event_format *event, void *context) + struct tep_event_format *event, void *context) { unsigned long long info1 = 0, info2 = 0; @@ -293,7 +293,7 @@ static int kvm_exit_handler(struct trace_seq *s, struct tep_record *record, static int kvm_emulate_insn_handler(struct trace_seq *s, struct tep_record *record, - struct event_format *event, void *context) + struct tep_event_format *event, void *context) { unsigned long long rip, csbase, len, flags, failed; int llen; @@ -332,7 +332,7 @@ static int kvm_emulate_insn_handler(struct trace_seq *s, static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct tep_record *record, - struct event_format *event, void *context) + struct tep_event_format *event, void *context) { if (print_exit_reason(s, record, event, "exit_code") < 0) return -1; @@ -346,7 +346,7 @@ static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct tep_reco } static int kvm_nested_vmexit_handler(struct trace_seq *s, struct tep_record *record, - struct event_format *event, void *context) + struct tep_event_format *event, void *context) { tep_print_num_field(s, "rip %llx ", event, "rip", record, 1); @@ -372,7 +372,7 @@ union kvm_mmu_page_role { }; static int kvm_mmu_print_role(struct trace_seq *s, struct tep_record *record, - struct event_format *event, void *context) + struct tep_event_format *event, void *context) { unsigned long long val; static const char *access_str[] = { @@ -419,7 +419,7 @@ static int kvm_mmu_print_role(struct trace_seq *s, struct tep_record *record, static int kvm_mmu_get_page_handler(struct trace_seq *s, struct tep_record *record, - struct event_format *event, void *context) + struct tep_event_format *event, void *context) { unsigned long long val; diff --git a/tools/lib/traceevent/plugin_mac80211.c b/tools/lib/traceevent/plugin_mac80211.c index 0b7779444b63..c16469614690 100644 --- a/tools/lib/traceevent/plugin_mac80211.c +++ b/tools/lib/traceevent/plugin_mac80211.c @@ -26,7 +26,7 @@ #define INDENT 65 -static void print_string(struct trace_seq *s, struct event_format *event, +static void print_string(struct trace_seq *s, struct tep_event_format *event, const char *name, const void *data) { struct format_field *f = tep_find_field(event, name); @@ -60,7 +60,7 @@ static void print_string(struct trace_seq *s, struct event_format *event, static int drv_bss_info_changed(struct trace_seq *s, struct tep_record *record, - struct event_format *event, void *context) + struct tep_event_format *event, void *context) { void *data = record->data; diff --git a/tools/lib/traceevent/plugin_sched_switch.c b/tools/lib/traceevent/plugin_sched_switch.c index 582d3be2849b..a7eeb42894ae 100644 --- a/tools/lib/traceevent/plugin_sched_switch.c +++ b/tools/lib/traceevent/plugin_sched_switch.c @@ -67,7 +67,7 @@ static void write_and_save_comm(struct format_field *field, static int sched_wakeup_handler(struct trace_seq *s, struct tep_record *record, - struct event_format *event, void *context) + struct tep_event_format *event, void *context) { struct format_field *field; unsigned long long val; @@ -96,7 +96,7 @@ static int sched_wakeup_handler(struct trace_seq *s, static int sched_switch_handler(struct trace_seq *s, struct tep_record *record, - struct event_format *event, void *context) + struct tep_event_format *event, void *context) { struct format_field *field; unsigned long long val; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 7ce277d22a91..9f8c365dacb1 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -862,7 +862,7 @@ static struct syscall_fmt *syscall_fmt__find(const char *name) * args_size: sum of the sizes of the syscall arguments, anything after that is augmented stuff: pathname for openat, etc. */ struct syscall { - struct event_format *tp_format; + struct tep_event_format *tp_format; int nr_args; int args_size; bool is_exit; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 4f8430a85531..c0f275cf96ee 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -102,7 +102,7 @@ struct perf_evsel { char *name; double scale; const char *unit; - struct event_format *tp_format; + struct tep_event_format *tp_format; off_t id_offset; struct perf_stat_evsel *stats; void *priv; @@ -211,7 +211,7 @@ static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char * struct perf_evsel *perf_evsel__new_cycles(bool precise); -struct event_format *event_format__new(const char *sys, const char *name); +struct tep_event_format *event_format__new(const char *sys, const char *name); void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr, int idx); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index c78051ad1fcc..1ec1d9bc2d63 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -3206,7 +3206,7 @@ static int read_attr(int fd, struct perf_header *ph, static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel, struct tep_handle *pevent) { - struct event_format *event; + struct tep_event_format *event; char bf[128]; /* already prepared */ diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index ce501ba14b08..6714d2c517db 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -386,7 +386,7 @@ get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) struct format_field *field; if (!evsel->tp_format) { - struct event_format *tp_format; + struct tep_event_format *tp_format; tp_format = trace_event__tp_format_id(evsel->attr.config); if (!tp_format) @@ -1240,7 +1240,7 @@ static struct { static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel, PyObject *args, PyObject *kwargs) { - struct event_format *tp_format; + struct tep_event_format *tp_format; static char *kwlist[] = { "sys", "name", NULL }; char *sys = NULL; char *name = NULL; diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 45484f0f7292..370cc60f0afa 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -189,7 +189,7 @@ static void define_flag_field(const char *ev_name, LEAVE; } -static void define_event_symbols(struct event_format *event, +static void define_event_symbols(struct tep_event_format *event, const char *ev_name, struct print_arg *args) { @@ -338,7 +338,7 @@ static void perl_process_tracepoint(struct perf_sample *sample, struct addr_location *al) { struct thread *thread = al->thread; - struct event_format *event = evsel->tp_format; + struct tep_event_format *event = evsel->tp_format; struct format_field *field; static char handler[256]; unsigned long long val; @@ -537,7 +537,7 @@ static int perl_stop_script(void) static int perl_generate_script(struct tep_handle *pevent, const char *outfile) { - struct event_format *event = NULL; + struct tep_event_format *event = NULL; struct format_field *f; char fname[PATH_MAX]; int not_first, count; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index dfc6093f118c..9a8a7b7ff64a 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -264,7 +264,7 @@ static void define_field(enum print_arg_type field_type, Py_DECREF(t); } -static void define_event_symbols(struct event_format *event, +static void define_event_symbols(struct tep_event_format *event, const char *ev_name, struct print_arg *args) { @@ -332,7 +332,7 @@ static void define_event_symbols(struct event_format *event, define_event_symbols(event, ev_name, args->next); } -static PyObject *get_field_numeric_entry(struct event_format *event, +static PyObject *get_field_numeric_entry(struct tep_event_format *event, struct format_field *field, void *data) { bool is_array = field->flags & FIELD_IS_ARRAY; @@ -790,7 +790,7 @@ static void python_process_tracepoint(struct perf_sample *sample, struct perf_evsel *evsel, struct addr_location *al) { - struct event_format *event = evsel->tp_format; + struct tep_event_format *event = evsel->tp_format; PyObject *handler, *context, *t, *obj = NULL, *callchain; PyObject *dict = NULL, *all_entries_dict = NULL; static char handler_name[256]; @@ -1590,7 +1590,7 @@ static int python_stop_script(void) static int python_generate_script(struct tep_handle *pevent, const char *outfile) { - struct event_format *event = NULL; + struct tep_event_format *event = NULL; struct format_field *f; char fname[PATH_MAX]; int not_first, count; diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index e76214f8d596..643cf28e1345 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -33,7 +33,7 @@ static int get_common_field(struct scripting_context *context, int *offset, int *size, const char *type) { struct tep_handle *pevent = context->pevent; - struct event_format *event; + struct tep_event_format *event; struct format_field *field; if (!*size) { @@ -94,7 +94,7 @@ int common_pc(struct scripting_context *context) } unsigned long long -raw_field_value(struct event_format *event, const char *name, void *data) +raw_field_value(struct tep_event_format *event, const char *name, void *data) { struct format_field *field; unsigned long long val; @@ -108,12 +108,12 @@ raw_field_value(struct event_format *event, const char *name, void *data) return val; } -unsigned long long read_size(struct event_format *event, void *ptr, int size) +unsigned long long read_size(struct tep_event_format *event, void *ptr, int size) { return tep_read_number(event->pevent, ptr, size); } -void event_format__fprintf(struct event_format *event, +void event_format__fprintf(struct tep_event_format *event, int cpu, void *data, int size, FILE *fp) { struct tep_record record; @@ -130,7 +130,7 @@ void event_format__fprintf(struct event_format *event, trace_seq_destroy(&s); } -void event_format__print(struct event_format *event, +void event_format__print(struct tep_event_format *event, int cpu, void *data, int size) { return event_format__fprintf(event, cpu, data, size, stdout); @@ -188,8 +188,8 @@ int parse_event_file(struct tep_handle *pevent, return tep_parse_event(pevent, buf, size, sys); } -struct event_format *trace_find_next_event(struct tep_handle *pevent, - struct event_format *event) +struct tep_event_format *trace_find_next_event(struct tep_handle *pevent, + struct tep_event_format *event) { static int idx; diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c index 58bb72f266f3..95664b2f771e 100644 --- a/tools/perf/util/trace-event.c +++ b/tools/perf/util/trace-event.c @@ -72,12 +72,12 @@ void trace_event__cleanup(struct trace_event *t) /* * Returns pointer with encoded error via interface. */ -static struct event_format* +static struct tep_event_format* tp_format(const char *sys, const char *name) { char *tp_dir = get_events_file(sys); struct tep_handle *pevent = tevent.pevent; - struct event_format *event = NULL; + struct tep_event_format *event = NULL; char path[PATH_MAX]; size_t size; char *data; @@ -102,7 +102,7 @@ tp_format(const char *sys, const char *name) /* * Returns pointer with encoded error via interface. */ -struct event_format* +struct tep_event_format* trace_event__tp_format(const char *sys, const char *name) { if (!tevent_initialized && trace_event__init2()) @@ -111,7 +111,7 @@ trace_event__tp_format(const char *sys, const char *name) return tp_format(sys, name); } -struct event_format *trace_event__tp_format_id(int id) +struct tep_event_format *trace_event__tp_format_id(int id) { if (!tevent_initialized && trace_event__init2()) return ERR_PTR(-ENOMEM); diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index c69d77d7cf55..2da6eff0caaf 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -22,17 +22,17 @@ int trace_event__init(struct trace_event *t); void trace_event__cleanup(struct trace_event *t); int trace_event__register_resolver(struct machine *machine, tep_func_resolver_t *func); -struct event_format* +struct tep_event_format* trace_event__tp_format(const char *sys, const char *name); -struct event_format *trace_event__tp_format_id(int id); +struct tep_event_format *trace_event__tp_format_id(int id); int bigendian(void); -void event_format__fprintf(struct event_format *event, +void event_format__fprintf(struct tep_event_format *event, int cpu, void *data, int size, FILE *fp); -void event_format__print(struct event_format *event, +void event_format__print(struct tep_event_format *event, int cpu, void *data, int size); int parse_ftrace_file(struct tep_handle *pevent, char *buf, unsigned long size); @@ -40,7 +40,7 @@ int parse_event_file(struct tep_handle *pevent, char *buf, unsigned long size, char *sys); unsigned long long -raw_field_value(struct event_format *event, const char *name, void *data); +raw_field_value(struct tep_event_format *event, const char *name, void *data); void parse_proc_kallsyms(struct tep_handle *pevent, char *file, unsigned int size); void parse_ftrace_printk(struct tep_handle *pevent, char *file, unsigned int size); @@ -48,9 +48,9 @@ void parse_saved_cmdline(struct tep_handle *pevent, char *file, unsigned int siz ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe); -struct event_format *trace_find_next_event(struct tep_handle *pevent, - struct event_format *event); -unsigned long long read_size(struct event_format *event, void *ptr, int size); +struct tep_event_format *trace_find_next_event(struct tep_handle *pevent, + struct tep_event_format *event); +unsigned long long read_size(struct tep_event_format *event, void *ptr, int size); unsigned long long eval_flag(const char *flag); int read_tracing_data(int fd, struct list_head *pattrs); From 2c92f9828b3ca4e82e7ceffeea76c6fba4044acc Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:45 -0400 Subject: [PATCH 104/155] tools lib traceevent, perf tools: Rename struct format{_field} to struct tep_format{_field} In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This renames struct format to struct tep_format and struct format_field to struct tep_format_field Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185722.661319373@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 82 +++++++++---------- tools/lib/traceevent/event-parse.h | 42 +++++----- tools/lib/traceevent/parse-filter.c | 8 +- tools/lib/traceevent/plugin_kmem.c | 2 +- tools/lib/traceevent/plugin_mac80211.c | 2 +- tools/lib/traceevent/plugin_sched_switch.c | 6 +- tools/perf/builtin-trace.c | 14 ++-- tools/perf/tests/evsel-tp-sched.c | 2 +- tools/perf/util/data-convert-bt.c | 22 ++--- tools/perf/util/evsel.c | 8 +- tools/perf/util/evsel.h | 6 +- tools/perf/util/evsel_fprintf.c | 2 +- tools/perf/util/python.c | 4 +- .../util/scripting-engines/trace-event-perl.c | 4 +- .../scripting-engines/trace-event-python.c | 6 +- tools/perf/util/sort.c | 18 ++-- tools/perf/util/trace-event-parse.c | 4 +- 17 files changed, 116 insertions(+), 116 deletions(-) diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index bb2ebb322124..32547abb6500 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -1299,7 +1299,7 @@ static int event_read_id(void) return -1; } -static int field_is_string(struct format_field *field) +static int field_is_string(struct tep_format_field *field) { if ((field->flags & FIELD_IS_ARRAY) && (strstr(field->type, "char") || strstr(field->type, "u8") || @@ -1309,7 +1309,7 @@ static int field_is_string(struct format_field *field) return 0; } -static int field_is_dynamic(struct format_field *field) +static int field_is_dynamic(struct tep_format_field *field) { if (strncmp(field->type, "__data_loc", 10) == 0) return 1; @@ -1317,7 +1317,7 @@ static int field_is_dynamic(struct format_field *field) return 0; } -static int field_is_long(struct format_field *field) +static int field_is_long(struct tep_format_field *field) { /* includes long long */ if (strstr(field->type, "long")) @@ -1354,9 +1354,9 @@ static unsigned int type_size(const char *name) return 0; } -static int event_read_fields(struct tep_event_format *event, struct format_field **fields) +static int event_read_fields(struct tep_event_format *event, struct tep_format_field **fields) { - struct format_field *field = NULL; + struct tep_format_field *field = NULL; enum event_type type; char *token; char *last_token; @@ -2683,7 +2683,7 @@ out: static enum event_type process_dynamic_array(struct tep_event_format *event, struct print_arg *arg, char **tok) { - struct format_field *field; + struct tep_format_field *field; enum event_type type; char *token; @@ -2748,7 +2748,7 @@ static enum event_type process_dynamic_array_len(struct tep_event_format *event, struct print_arg *arg, char **tok) { - struct format_field *field; + struct tep_format_field *field; enum event_type type; char *token; @@ -3259,10 +3259,10 @@ static int event_read_print(struct tep_event_format *event) * Returns a common field from the event by the given @name. * This only searchs the common fields and not all field. */ -struct format_field * +struct tep_format_field * tep_find_common_field(struct tep_event_format *event, const char *name) { - struct format_field *format; + struct tep_format_field *format; for (format = event->format.common_fields; format; format = format->next) { @@ -3281,10 +3281,10 @@ tep_find_common_field(struct tep_event_format *event, const char *name) * Returns a non-common field by the given @name. * This does not search common fields. */ -struct format_field * +struct tep_format_field * tep_find_field(struct tep_event_format *event, const char *name) { - struct format_field *format; + struct tep_format_field *format; for (format = event->format.fields; format; format = format->next) { @@ -3304,10 +3304,10 @@ tep_find_field(struct tep_event_format *event, const char *name) * This searchs the common field names first, then * the non-common ones if a common one was not found. */ -struct format_field * +struct tep_format_field * tep_find_any_field(struct tep_event_format *event, const char *name) { - struct format_field *format; + struct tep_format_field *format; format = tep_find_common_field(event, name); if (format) @@ -3353,7 +3353,7 @@ unsigned long long tep_read_number(struct tep_handle *pevent, * * Returns 0 on success, -1 otherwise. */ -int tep_read_number_field(struct format_field *field, const void *data, +int tep_read_number_field(struct tep_format_field *field, const void *data, unsigned long long *value) { if (!field) @@ -3375,7 +3375,7 @@ static int get_common_info(struct tep_handle *pevent, const char *type, int *offset, int *size) { struct tep_event_format *event; - struct format_field *field; + struct tep_format_field *field; /* * All events should have the same common elements. @@ -3867,7 +3867,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, { struct tep_handle *pevent = event->pevent; struct print_flag_sym *flag; - struct format_field *field; + struct tep_format_field *field; struct printk_map *printk; long long val, fval; unsigned long long addr; @@ -4008,7 +4008,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, if (arg->int_array.field->type == PRINT_DYNAMIC_ARRAY) { unsigned long offset; - struct format_field *field = + struct tep_format_field *field = arg->int_array.field->dynarray.field; offset = tep_read_number(pevent, data + field->offset, @@ -4056,7 +4056,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, int str_offset; if (arg->string.offset == -1) { - struct format_field *f; + struct tep_format_field *f; f = tep_find_any_field(event, arg->string.string); arg->string.offset = f->offset; @@ -4074,7 +4074,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, int bitmask_size; if (arg->bitmask.offset == -1) { - struct format_field *f; + struct tep_format_field *f; f = tep_find_any_field(event, arg->bitmask.bitmask); arg->bitmask.offset = f->offset; @@ -4215,7 +4215,7 @@ static void free_args(struct print_arg *args) static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct tep_event_format *event) { struct tep_handle *pevent = event->pevent; - struct format_field *field, *ip_field; + struct tep_format_field *field, *ip_field; struct print_arg *args, *arg, **next; unsigned long long ip, val; char *ptr; @@ -4393,7 +4393,7 @@ get_bprint_format(void *data, int size __maybe_unused, { struct tep_handle *pevent = event->pevent; unsigned long long addr; - struct format_field *field; + struct tep_format_field *field; struct printk_map *printk; char *format; @@ -4788,7 +4788,7 @@ static int is_printable_array(char *p, unsigned int len) } void tep_print_field(struct trace_seq *s, void *data, - struct format_field *field) + struct tep_format_field *field) { unsigned long long val; unsigned int offset, len, i; @@ -4855,7 +4855,7 @@ void tep_print_field(struct trace_seq *s, void *data, void tep_print_fields(struct trace_seq *s, void *data, int size __maybe_unused, struct tep_event_format *event) { - struct format_field *field; + struct tep_format_field *field; field = event->format.fields; while (field) { @@ -5664,12 +5664,12 @@ struct tep_event_format **tep_list_events(struct tep_handle *pevent, enum event_ return events; } -static struct format_field ** +static struct tep_format_field ** get_event_fields(const char *type, const char *name, - int count, struct format_field *list) + int count, struct tep_format_field *list) { - struct format_field **fields; - struct format_field *field; + struct tep_format_field **fields; + struct tep_format_field *field; int i = 0; fields = malloc(sizeof(*fields) * (count + 1)); @@ -5702,7 +5702,7 @@ get_event_fields(const char *type, const char *name, * Returns an allocated array of fields. The last item in the array is NULL. * The array must be freed with free(). */ -struct format_field **tep_event_common_fields(struct tep_event_format *event) +struct tep_format_field **tep_event_common_fields(struct tep_event_format *event) { return get_event_fields("common", event->name, event->format.nr_common, @@ -5716,7 +5716,7 @@ struct format_field **tep_event_common_fields(struct tep_event_format *event) * Returns an allocated array of fields. The last item in the array is NULL. * The array must be freed with free(). */ -struct format_field **tep_event_fields(struct tep_event_format *event) +struct tep_format_field **tep_event_fields(struct tep_event_format *event) { return get_event_fields("event", event->name, event->format.nr_fields, @@ -6090,7 +6090,7 @@ enum tep_errno __tep_parse_format(struct tep_event_format **eventp, } if (!ret && (event->flags & EVENT_FL_ISFTRACE)) { - struct format_field *field; + struct tep_format_field *field; struct print_arg *arg, **list; /* old ftrace had no args */ @@ -6230,7 +6230,7 @@ int tep_strerror(struct tep_handle *pevent __maybe_unused, return 0; } -int get_field_val(struct trace_seq *s, struct format_field *field, +int get_field_val(struct trace_seq *s, struct tep_format_field *field, const char *name, struct tep_record *record, unsigned long long *val, int err) { @@ -6267,7 +6267,7 @@ void *tep_get_field_raw(struct trace_seq *s, struct tep_event_format *event, const char *name, struct tep_record *record, int *len, int err) { - struct format_field *field; + struct tep_format_field *field; void *data = record->data; unsigned offset; int dummy; @@ -6314,7 +6314,7 @@ int tep_get_field_val(struct trace_seq *s, struct tep_event_format *event, const char *name, struct tep_record *record, unsigned long long *val, int err) { - struct format_field *field; + struct tep_format_field *field; if (!event) return -1; @@ -6339,7 +6339,7 @@ int tep_get_common_field_val(struct trace_seq *s, struct tep_event_format *event const char *name, struct tep_record *record, unsigned long long *val, int err) { - struct format_field *field; + struct tep_format_field *field; if (!event) return -1; @@ -6364,7 +6364,7 @@ int tep_get_any_field_val(struct trace_seq *s, struct tep_event_format *event, const char *name, struct tep_record *record, unsigned long long *val, int err) { - struct format_field *field; + struct tep_format_field *field; if (!event) return -1; @@ -6389,7 +6389,7 @@ int tep_print_num_field(struct trace_seq *s, const char *fmt, struct tep_event_format *event, const char *name, struct tep_record *record, int err) { - struct format_field *field = tep_find_field(event, name); + struct tep_format_field *field = tep_find_field(event, name); unsigned long long val; if (!field) @@ -6421,7 +6421,7 @@ int tep_print_func_field(struct trace_seq *s, const char *fmt, struct tep_event_format *event, const char *name, struct tep_record *record, int err) { - struct format_field *field = tep_find_field(event, name); + struct tep_format_field *field = tep_find_field(event, name); struct tep_handle *pevent = event->pevent; unsigned long long val; struct func_map *func; @@ -6758,7 +6758,7 @@ void tep_ref(struct tep_handle *pevent) pevent->ref_count++; } -void tep_free_format_field(struct format_field *field) +void tep_free_format_field(struct tep_format_field *field) { free(field->type); if (field->alias != field->name) @@ -6767,9 +6767,9 @@ void tep_free_format_field(struct format_field *field) free(field); } -static void free_format_fields(struct format_field *field) +static void free_format_fields(struct tep_format_field *field) { - struct format_field *next; + struct tep_format_field *next; while (field) { next = field->next; @@ -6778,7 +6778,7 @@ static void free_format_fields(struct format_field *field) } } -static void free_formats(struct format *format) +static void free_formats(struct tep_format *format) { free_format_fields(format->common_fields); free_format_fields(format->fields); diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 82de69c2b054..aba859056867 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -141,8 +141,8 @@ enum format_flags { FIELD_IS_SYMBOLIC = 128, }; -struct format_field { - struct format_field *next; +struct tep_format_field { + struct tep_format_field *next; struct tep_event_format *event; char *type; char *name; @@ -154,11 +154,11 @@ struct format_field { unsigned long flags; }; -struct format { +struct tep_format { int nr_common; int nr_fields; - struct format_field *common_fields; - struct format_field *fields; + struct tep_format_field *common_fields; + struct tep_format_field *fields; }; struct print_arg_atom { @@ -177,7 +177,7 @@ struct print_arg_bitmask { struct print_arg_field { char *name; - struct format_field *field; + struct tep_format_field *field; }; struct print_flag_sym { @@ -214,7 +214,7 @@ struct print_arg_int_array { }; struct print_arg_dynarray { - struct format_field *field; + struct tep_format_field *field; struct print_arg *index; }; @@ -282,7 +282,7 @@ struct tep_event_format { char *name; int id; int flags; - struct format format; + struct tep_format format; struct print_fmt print_fmt; char *system; tep_event_handler_func handler; @@ -477,9 +477,9 @@ struct tep_handle { int flags; - struct format_field *bprint_ip_field; - struct format_field *bprint_fmt_field; - struct format_field *bprint_buf_field; + struct tep_format_field *bprint_ip_field; + struct tep_format_field *bprint_fmt_field; + struct tep_format_field *bprint_buf_field; struct event_handler *handlers; struct tep_function_handler *func_handlers; @@ -607,7 +607,7 @@ enum tep_errno tep_parse_format(struct tep_handle *pevent, const char *buf, unsigned long size, const char *sys); void tep_free_format(struct tep_event_format *event); -void tep_free_format_field(struct format_field *field); +void tep_free_format_field(struct tep_format_field *field); void *tep_get_field_raw(struct trace_seq *s, struct tep_event_format *event, const char *name, struct tep_record *record, @@ -644,15 +644,15 @@ int tep_register_print_function(struct tep_handle *pevent, int tep_unregister_print_function(struct tep_handle *pevent, tep_func_handler func, char *name); -struct format_field *tep_find_common_field(struct tep_event_format *event, const char *name); -struct format_field *tep_find_field(struct tep_event_format *event, const char *name); -struct format_field *tep_find_any_field(struct tep_event_format *event, const char *name); +struct tep_format_field *tep_find_common_field(struct tep_event_format *event, const char *name); +struct tep_format_field *tep_find_field(struct tep_event_format *event, const char *name); +struct tep_format_field *tep_find_any_field(struct tep_event_format *event, const char *name); const char *tep_find_function(struct tep_handle *pevent, unsigned long long addr); unsigned long long tep_find_function_address(struct tep_handle *pevent, unsigned long long addr); unsigned long long tep_read_number(struct tep_handle *pevent, const void *ptr, int size); -int tep_read_number_field(struct format_field *field, const void *data, +int tep_read_number_field(struct tep_format_field *field, const void *data, unsigned long long *value); struct tep_event_format *tep_find_event(struct tep_handle *pevent, int id); @@ -677,7 +677,7 @@ struct cmdline *tep_data_pid_from_comm(struct tep_handle *pevent, const char *co int tep_cmdline_pid(struct tep_handle *pevent, struct cmdline *cmdline); void tep_print_field(struct trace_seq *s, void *data, - struct format_field *field); + struct tep_format_field *field); void tep_print_fields(struct trace_seq *s, void *data, int size __maybe_unused, struct tep_event_format *event); void tep_event_info(struct trace_seq *s, struct tep_event_format *event, @@ -686,8 +686,8 @@ int tep_strerror(struct tep_handle *pevent, enum tep_errno errnum, char *buf, size_t buflen); struct tep_event_format **tep_list_events(struct tep_handle *pevent, enum event_sort_type); -struct format_field **tep_event_common_fields(struct tep_event_format *event); -struct format_field **tep_event_fields(struct tep_event_format *event); +struct tep_format_field **tep_event_common_fields(struct tep_event_format *event); +struct tep_format_field **tep_event_fields(struct tep_event_format *event); static inline int tep_get_cpus(struct tep_handle *pevent) { @@ -832,7 +832,7 @@ struct filter_arg_boolean { }; struct filter_arg_field { - struct format_field *field; + struct tep_format_field *field; }; struct filter_arg_value { @@ -863,7 +863,7 @@ struct filter_arg_num { struct filter_arg_str { enum filter_cmp_type type; - struct format_field *field; + struct tep_format_field *field; char *val; char *buffer; regex_t reg; diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 5572756307ab..a0353f2c051a 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -16,11 +16,11 @@ #define COMM "COMM" #define CPU "CPU" -static struct format_field comm = { +static struct tep_format_field comm = { .name = "COMM", }; -static struct format_field cpu = { +static struct tep_format_field cpu = { .name = "CPU", }; @@ -336,7 +336,7 @@ static enum tep_errno create_arg_item(struct tep_event_format *event, const char *token, enum event_type type, struct filter_arg **parg, char *error_str) { - struct format_field *field; + struct tep_format_field *field; struct filter_arg *arg; arg = allocate_arg(); @@ -1698,7 +1698,7 @@ get_comm(struct tep_event_format *event, struct tep_record *record) static unsigned long long get_value(struct tep_event_format *event, - struct format_field *field, struct tep_record *record) + struct tep_format_field *field, struct tep_record *record) { unsigned long long val; diff --git a/tools/lib/traceevent/plugin_kmem.c b/tools/lib/traceevent/plugin_kmem.c index 5632aff43aba..1beb4eaddfdf 100644 --- a/tools/lib/traceevent/plugin_kmem.c +++ b/tools/lib/traceevent/plugin_kmem.c @@ -27,7 +27,7 @@ static int call_site_handler(struct trace_seq *s, struct tep_record *record, struct tep_event_format *event, void *context) { - struct format_field *field; + struct tep_format_field *field; unsigned long long val, addr; void *data = record->data; const char *func; diff --git a/tools/lib/traceevent/plugin_mac80211.c b/tools/lib/traceevent/plugin_mac80211.c index c16469614690..da3855e7b86f 100644 --- a/tools/lib/traceevent/plugin_mac80211.c +++ b/tools/lib/traceevent/plugin_mac80211.c @@ -29,7 +29,7 @@ static void print_string(struct trace_seq *s, struct tep_event_format *event, const char *name, const void *data) { - struct format_field *f = tep_find_field(event, name); + struct tep_format_field *f = tep_find_field(event, name); int offset; int length; diff --git a/tools/lib/traceevent/plugin_sched_switch.c b/tools/lib/traceevent/plugin_sched_switch.c index a7eeb42894ae..77882272672f 100644 --- a/tools/lib/traceevent/plugin_sched_switch.c +++ b/tools/lib/traceevent/plugin_sched_switch.c @@ -45,7 +45,7 @@ static void write_state(struct trace_seq *s, int val) trace_seq_putc(s, 'R'); } -static void write_and_save_comm(struct format_field *field, +static void write_and_save_comm(struct tep_format_field *field, struct tep_record *record, struct trace_seq *s, int pid) { @@ -69,7 +69,7 @@ static int sched_wakeup_handler(struct trace_seq *s, struct tep_record *record, struct tep_event_format *event, void *context) { - struct format_field *field; + struct tep_format_field *field; unsigned long long val; if (tep_get_field_val(s, event, "pid", record, &val, 1)) @@ -98,7 +98,7 @@ static int sched_switch_handler(struct trace_seq *s, struct tep_record *record, struct tep_event_format *event, void *context) { - struct format_field *field; + struct tep_format_field *field; unsigned long long val; if (tep_get_field_val(s, event, "prev_pid", record, &val, 1)) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 9f8c365dacb1..95f3c255d977 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -181,7 +181,7 @@ static int __tp_field__init_uint(struct tp_field *field, int size, int offset, b return 0; } -static int tp_field__init_uint(struct tp_field *field, struct format_field *format_field, bool needs_swap) +static int tp_field__init_uint(struct tp_field *field, struct tep_format_field *format_field, bool needs_swap) { return __tp_field__init_uint(field, format_field->size, format_field->offset, needs_swap); } @@ -198,7 +198,7 @@ static int __tp_field__init_ptr(struct tp_field *field, int offset) return 0; } -static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field) +static int tp_field__init_ptr(struct tp_field *field, struct tep_format_field *format_field) { return __tp_field__init_ptr(field, format_field->offset); } @@ -214,7 +214,7 @@ static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel, struct tp_field *field, const char *name) { - struct format_field *format_field = perf_evsel__field(evsel, name); + struct tep_format_field *format_field = perf_evsel__field(evsel, name); if (format_field == NULL) return -1; @@ -230,7 +230,7 @@ static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel, struct tp_field *field, const char *name) { - struct format_field *format_field = perf_evsel__field(evsel, name); + struct tep_format_field *format_field = perf_evsel__field(evsel, name); if (format_field == NULL) return -1; @@ -867,7 +867,7 @@ struct syscall { int args_size; bool is_exit; bool is_open; - struct format_field *args; + struct tep_format_field *args; const char *name; struct syscall_fmt *fmt; struct syscall_arg_fmt *arg_fmt; @@ -1279,7 +1279,7 @@ static int syscall__alloc_arg_fmts(struct syscall *sc, int nr_args) static int syscall__set_arg_fmts(struct syscall *sc) { - struct format_field *field, *last_field = NULL; + struct tep_format_field *field, *last_field = NULL; int idx = 0, len; for (field = sc->args; field; field = field->next, ++idx) { @@ -1525,7 +1525,7 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, ttrace->ret_scnprintf = NULL; if (sc->args != NULL) { - struct format_field *field; + struct tep_format_field *field; for (field = sc->args; field; field = field->next, ++arg.idx, bit <<= 1) { diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c index 699561fa512c..da9d3c0f8ead 100644 --- a/tools/perf/tests/evsel-tp-sched.c +++ b/tools/perf/tests/evsel-tp-sched.c @@ -8,7 +8,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, int size, bool should_be_signed) { - struct format_field *field = perf_evsel__field(evsel, name); + struct tep_format_field *field = perf_evsel__field(evsel, name); int is_signed; int ret = 0; diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index f75d4aa612c5..1817bbcc4a62 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -182,7 +182,7 @@ err_put_field: } static struct bt_ctf_field_type* -get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) +get_tracepoint_field_type(struct ctf_writer *cw, struct tep_format_field *field) { unsigned long flags = field->flags; @@ -287,7 +287,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw, struct bt_ctf_event_class *event_class, struct bt_ctf_event *event, struct perf_sample *sample, - struct format_field *fmtf) + struct tep_format_field *fmtf) { struct bt_ctf_field_type *type; struct bt_ctf_field *array_field; @@ -396,10 +396,10 @@ err_put_field: static int add_tracepoint_fields_values(struct ctf_writer *cw, struct bt_ctf_event_class *event_class, struct bt_ctf_event *event, - struct format_field *fields, + struct tep_format_field *fields, struct perf_sample *sample) { - struct format_field *field; + struct tep_format_field *field; int ret; for (field = fields; field; field = field->next) { @@ -417,8 +417,8 @@ static int add_tracepoint_values(struct ctf_writer *cw, struct perf_evsel *evsel, struct perf_sample *sample) { - struct format_field *common_fields = evsel->tp_format->format.common_fields; - struct format_field *fields = evsel->tp_format->format.fields; + struct tep_format_field *common_fields = evsel->tp_format->format.common_fields; + struct tep_format_field *fields = evsel->tp_format->format.fields; int ret; ret = add_tracepoint_fields_values(cw, event_class, event, @@ -970,7 +970,7 @@ out: static int event_class_add_field(struct bt_ctf_event_class *event_class, struct bt_ctf_field_type *type, - struct format_field *field) + struct tep_format_field *field) { struct bt_ctf_field_type *t = NULL; char *name; @@ -1009,10 +1009,10 @@ static int event_class_add_field(struct bt_ctf_event_class *event_class, } static int add_tracepoint_fields_types(struct ctf_writer *cw, - struct format_field *fields, + struct tep_format_field *fields, struct bt_ctf_event_class *event_class) { - struct format_field *field; + struct tep_format_field *field; int ret; for (field = fields; field; field = field->next) { @@ -1055,8 +1055,8 @@ static int add_tracepoint_types(struct ctf_writer *cw, struct perf_evsel *evsel, struct bt_ctf_event_class *class) { - struct format_field *common_fields = evsel->tp_format->format.common_fields; - struct format_field *fields = evsel->tp_format->format.fields; + struct tep_format_field *common_fields = evsel->tp_format->format.common_fields; + struct tep_format_field *fields = evsel->tp_format->format.fields; int ret; ret = add_tracepoint_fields_types(cw, common_fields, class); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 4ec909d57e9c..751c98a2e336 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -2682,7 +2682,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, return 0; } -struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name) +struct tep_format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name) { return tep_find_field(evsel->tp_format, name); } @@ -2690,7 +2690,7 @@ struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *nam void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample, const char *name) { - struct format_field *field = perf_evsel__field(evsel, name); + struct tep_format_field *field = perf_evsel__field(evsel, name); int offset; if (!field) @@ -2706,7 +2706,7 @@ void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample, return sample->raw_data + offset; } -u64 format_field__intval(struct format_field *field, struct perf_sample *sample, +u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample, bool needs_swap) { u64 value; @@ -2748,7 +2748,7 @@ u64 format_field__intval(struct format_field *field, struct perf_sample *sample, u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, const char *name) { - struct format_field *field = perf_evsel__field(evsel, name); + struct tep_format_field *field = perf_evsel__field(evsel, name); if (!field) return 0; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index c0f275cf96ee..4107c39f4a54 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -296,11 +296,11 @@ static inline char *perf_evsel__strval(struct perf_evsel *evsel, return perf_evsel__rawptr(evsel, sample, name); } -struct format_field; +struct tep_format_field; -u64 format_field__intval(struct format_field *field, struct perf_sample *sample, bool needs_swap); +u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample, bool needs_swap); -struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); +struct tep_format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); #define perf_evsel__match(evsel, t, c) \ (evsel->attr.type == PERF_TYPE_##t && \ diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c index 06dfb027879d..0d0a4c6f368b 100644 --- a/tools/perf/util/evsel_fprintf.c +++ b/tools/perf/util/evsel_fprintf.c @@ -73,7 +73,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, } if (details->trace_fields) { - struct format_field *field; + struct tep_format_field *field; if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { printed += comma_fprintf(fp, &first, " (not a tracepoint)"); diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 6714d2c517db..ebf84fe8cd29 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -340,7 +340,7 @@ static bool is_tracepoint(struct pyrf_event *pevent) } static PyObject* -tracepoint_field(struct pyrf_event *pe, struct format_field *field) +tracepoint_field(struct pyrf_event *pe, struct tep_format_field *field) { struct tep_handle *pevent = field->event->pevent; void *data = pe->sample.raw_data; @@ -383,7 +383,7 @@ get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) { const char *str = _PyUnicode_AsString(PyObject_Str(attr_name)); struct perf_evsel *evsel = pevent->evsel; - struct format_field *field; + struct tep_format_field *field; if (!evsel->tp_format) { struct tep_event_format *tp_format; diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 370cc60f0afa..1bb0b0c685b7 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -339,7 +339,7 @@ static void perl_process_tracepoint(struct perf_sample *sample, { struct thread *thread = al->thread; struct tep_event_format *event = evsel->tp_format; - struct format_field *field; + struct tep_format_field *field; static char handler[256]; unsigned long long val; unsigned long s, ns; @@ -538,7 +538,7 @@ static int perl_stop_script(void) static int perl_generate_script(struct tep_handle *pevent, const char *outfile) { struct tep_event_format *event = NULL; - struct format_field *f; + struct tep_format_field *f; char fname[PATH_MAX]; int not_first, count; FILE *ofp; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 9a8a7b7ff64a..dc26e58a791e 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -333,7 +333,7 @@ static void define_event_symbols(struct tep_event_format *event, } static PyObject *get_field_numeric_entry(struct tep_event_format *event, - struct format_field *field, void *data) + struct tep_format_field *field, void *data) { bool is_array = field->flags & FIELD_IS_ARRAY; PyObject *obj = NULL, *list = NULL; @@ -794,7 +794,7 @@ static void python_process_tracepoint(struct perf_sample *sample, PyObject *handler, *context, *t, *obj = NULL, *callchain; PyObject *dict = NULL, *all_entries_dict = NULL; static char handler_name[256]; - struct format_field *field; + struct tep_format_field *field; unsigned long s, ns; unsigned n = 0; int pid; @@ -1591,7 +1591,7 @@ static int python_stop_script(void) static int python_generate_script(struct tep_handle *pevent, const char *outfile) { struct tep_event_format *event = NULL; - struct format_field *f; + struct tep_format_field *f; char fname[PATH_MAX]; int not_first, count; FILE *ofp; diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index b284276ec963..5e3179d995f9 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1884,7 +1884,7 @@ static int __sort_dimension__add_hpp_output(struct sort_dimension *sd, struct hpp_dynamic_entry { struct perf_hpp_fmt hpp; struct perf_evsel *evsel; - struct format_field *field; + struct tep_format_field *field; unsigned dynamic_len; bool raw_trace; }; @@ -1915,7 +1915,7 @@ static void update_dynamic_len(struct hpp_dynamic_entry *hde, struct hist_entry *he) { char *str, *pos; - struct format_field *field = hde->field; + struct tep_format_field *field = hde->field; size_t namelen; bool last = false; @@ -2000,7 +2000,7 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hpp_dynamic_entry *hde; size_t len = fmt->user_len; char *str, *pos; - struct format_field *field; + struct tep_format_field *field; size_t namelen; bool last = false; int ret; @@ -2060,7 +2060,7 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt, struct hist_entry *a, struct hist_entry *b) { struct hpp_dynamic_entry *hde; - struct format_field *field; + struct tep_format_field *field; unsigned offset, size; hde = container_of(fmt, struct hpp_dynamic_entry, hpp); @@ -2117,7 +2117,7 @@ static void hde_free(struct perf_hpp_fmt *fmt) } static struct hpp_dynamic_entry * -__alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field, +__alloc_dynamic_entry(struct perf_evsel *evsel, struct tep_format_field *field, int level) { struct hpp_dynamic_entry *hde; @@ -2252,7 +2252,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam } static int __dynamic_dimension__add(struct perf_evsel *evsel, - struct format_field *field, + struct tep_format_field *field, bool raw_trace, int level) { struct hpp_dynamic_entry *hde; @@ -2270,7 +2270,7 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel, static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level) { int ret; - struct format_field *field; + struct tep_format_field *field; field = evsel->tp_format->format.fields; while (field) { @@ -2305,7 +2305,7 @@ static int add_all_matching_fields(struct perf_evlist *evlist, { int ret = -ESRCH; struct perf_evsel *evsel; - struct format_field *field; + struct tep_format_field *field; evlist__for_each_entry(evlist, evsel) { if (evsel->attr.type != PERF_TYPE_TRACEPOINT) @@ -2327,7 +2327,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok, { char *str, *event_name, *field_name, *opt_name; struct perf_evsel *evsel; - struct format_field *field; + struct tep_format_field *field; bool raw_trace = symbol_conf.raw_trace; int ret = 0; diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 643cf28e1345..a4d7de1c96d1 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -34,7 +34,7 @@ static int get_common_field(struct scripting_context *context, { struct tep_handle *pevent = context->pevent; struct tep_event_format *event; - struct format_field *field; + struct tep_format_field *field; if (!*size) { if (!pevent->events) @@ -96,7 +96,7 @@ int common_pc(struct scripting_context *context) unsigned long long raw_field_value(struct tep_event_format *event, const char *name, void *data) { - struct format_field *field; + struct tep_format_field *field; unsigned long long val; field = tep_find_any_field(event, name); From bb39ccb204cc2e8135660b9cb768ffcf242bf33e Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:46 -0400 Subject: [PATCH 105/155] tools lib traceevent, perf tools: Rename enum format_flags to enum tep_format_flags In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This renames enum format_flags to enum tep_format_flags and adds prefix TEP_ to all of its members. Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185722.803127871@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 48 +++++++++---------- tools/lib/traceevent/event-parse.h | 18 +++---- tools/lib/traceevent/parse-filter.c | 8 ++-- tools/perf/builtin-trace.c | 2 +- tools/perf/tests/evsel-tp-sched.c | 2 +- tools/perf/util/data-convert-bt.c | 34 ++++++------- tools/perf/util/evsel.c | 2 +- tools/perf/util/python.c | 12 ++--- .../util/scripting-engines/trace-event-perl.c | 18 +++---- .../scripting-engines/trace-event-python.c | 26 +++++----- tools/perf/util/sort.c | 4 +- 11 files changed, 87 insertions(+), 87 deletions(-) diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 32547abb6500..508c89365c90 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -1301,7 +1301,7 @@ static int event_read_id(void) static int field_is_string(struct tep_format_field *field) { - if ((field->flags & FIELD_IS_ARRAY) && + if ((field->flags & TEP_FIELD_IS_ARRAY) && (strstr(field->type, "char") || strstr(field->type, "u8") || strstr(field->type, "s8"))) return 1; @@ -1328,7 +1328,7 @@ static int field_is_long(struct tep_format_field *field) static unsigned int type_size(const char *name) { - /* This covers all FIELD_IS_STRING types. */ + /* This covers all TEP_FIELD_IS_STRING types. */ static struct { const char *type; unsigned int size; @@ -1416,7 +1416,7 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f type == EVENT_OP && strcmp(token, ".") == 0)) { if (strcmp(token, "*") == 0) - field->flags |= FIELD_IS_POINTER; + field->flags |= TEP_FIELD_IS_POINTER; if (field->type) { char *new_type; @@ -1455,7 +1455,7 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f char *new_brackets; int len; - field->flags |= FIELD_IS_ARRAY; + field->flags |= TEP_FIELD_IS_ARRAY; type = read_token(&token); @@ -1544,11 +1544,11 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f } if (field_is_string(field)) - field->flags |= FIELD_IS_STRING; + field->flags |= TEP_FIELD_IS_STRING; if (field_is_dynamic(field)) - field->flags |= FIELD_IS_DYNAMIC; + field->flags |= TEP_FIELD_IS_DYNAMIC; if (field_is_long(field)) - field->flags |= FIELD_IS_LONG; + field->flags |= TEP_FIELD_IS_LONG; if (test_type_token(type, token, EVENT_OP, ";")) goto fail; @@ -1597,7 +1597,7 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f goto fail; if (strtoul(token, NULL, 0)) - field->flags |= FIELD_IS_SIGNED; + field->flags |= TEP_FIELD_IS_SIGNED; free_token(token); if (read_expected(EVENT_OP, ";") < 0) @@ -1609,14 +1609,14 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f free_token(token); - if (field->flags & FIELD_IS_ARRAY) { + if (field->flags & TEP_FIELD_IS_ARRAY) { if (field->arraylen) field->elementsize = field->size / field->arraylen; - else if (field->flags & FIELD_IS_DYNAMIC) + else if (field->flags & TEP_FIELD_IS_DYNAMIC) field->elementsize = size_dynamic; - else if (field->flags & FIELD_IS_STRING) + else if (field->flags & TEP_FIELD_IS_STRING) field->elementsize = 1; - else if (field->flags & FIELD_IS_LONG) + else if (field->flags & TEP_FIELD_IS_LONG) field->elementsize = event->pevent ? event->pevent->long_size : sizeof(long); @@ -2089,11 +2089,11 @@ process_entry(struct tep_event_format *event __maybe_unused, struct print_arg *a if (is_flag_field) { arg->field.field = tep_find_any_field(event, arg->field.name); - arg->field.field->flags |= FIELD_IS_FLAG; + arg->field.field->flags |= TEP_FIELD_IS_FLAG; is_flag_field = 0; } else if (is_symbolic_field) { arg->field.field = tep_find_any_field(event, arg->field.name); - arg->field.field->flags |= FIELD_IS_SYMBOLIC; + arg->field.field->flags |= TEP_FIELD_IS_SYMBOLIC; is_symbolic_field = 0; } @@ -3901,7 +3901,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, * and the size is the same as long_size, assume that it * is a pointer. */ - if (!(field->flags & FIELD_IS_ARRAY) && + if (!(field->flags & TEP_FIELD_IS_ARRAY) && field->size == pevent->long_size) { /* Handle heterogeneous recording and processing @@ -4794,16 +4794,16 @@ void tep_print_field(struct trace_seq *s, void *data, unsigned int offset, len, i; struct tep_handle *pevent = field->event->pevent; - if (field->flags & FIELD_IS_ARRAY) { + if (field->flags & TEP_FIELD_IS_ARRAY) { offset = field->offset; len = field->size; - if (field->flags & FIELD_IS_DYNAMIC) { + if (field->flags & TEP_FIELD_IS_DYNAMIC) { val = tep_read_number(pevent, data + offset, len); offset = val; len = offset >> 16; offset &= 0xffff; } - if (field->flags & FIELD_IS_STRING && + if (field->flags & TEP_FIELD_IS_STRING && is_printable_array(data + offset, len)) { trace_seq_printf(s, "%s", (char *)data + offset); } else { @@ -4815,21 +4815,21 @@ void tep_print_field(struct trace_seq *s, void *data, *((unsigned char *)data + offset + i)); } trace_seq_putc(s, ']'); - field->flags &= ~FIELD_IS_STRING; + field->flags &= ~TEP_FIELD_IS_STRING; } } else { val = tep_read_number(pevent, data + field->offset, field->size); - if (field->flags & FIELD_IS_POINTER) { + if (field->flags & TEP_FIELD_IS_POINTER) { trace_seq_printf(s, "0x%llx", val); - } else if (field->flags & FIELD_IS_SIGNED) { + } else if (field->flags & TEP_FIELD_IS_SIGNED) { switch (field->size) { case 4: /* * If field is long then print it in hex. * A long usually stores pointers. */ - if (field->flags & FIELD_IS_LONG) + if (field->flags & TEP_FIELD_IS_LONG) trace_seq_printf(s, "0x%x", (int)val); else trace_seq_printf(s, "%d", (int)val); @@ -4844,7 +4844,7 @@ void tep_print_field(struct trace_seq *s, void *data, trace_seq_printf(s, "%lld", val); } } else { - if (field->flags & FIELD_IS_LONG) + if (field->flags & TEP_FIELD_IS_LONG) trace_seq_printf(s, "0x%llx", val); else trace_seq_printf(s, "%llu", val); @@ -6288,7 +6288,7 @@ void *tep_get_field_raw(struct trace_seq *s, struct tep_event_format *event, len = &dummy; offset = field->offset; - if (field->flags & FIELD_IS_DYNAMIC) { + if (field->flags & TEP_FIELD_IS_DYNAMIC) { offset = tep_read_number(event->pevent, data + offset, field->size); *len = offset >> 16; diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index aba859056867..f1e1baee8cbd 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -130,15 +130,15 @@ struct tep_plugin_option { #define TEP_PLUGIN_OPTIONS_NAME MAKE_STR(TEP_PLUGIN_OPTIONS) #define TEP_PLUGIN_ALIAS_NAME MAKE_STR(TEP_PLUGIN_ALIAS) -enum format_flags { - FIELD_IS_ARRAY = 1, - FIELD_IS_POINTER = 2, - FIELD_IS_SIGNED = 4, - FIELD_IS_STRING = 8, - FIELD_IS_DYNAMIC = 16, - FIELD_IS_LONG = 32, - FIELD_IS_FLAG = 64, - FIELD_IS_SYMBOLIC = 128, +enum tep_format_flags { + TEP_FIELD_IS_ARRAY = 1, + TEP_FIELD_IS_POINTER = 2, + TEP_FIELD_IS_SIGNED = 4, + TEP_FIELD_IS_STRING = 8, + TEP_FIELD_IS_DYNAMIC = 16, + TEP_FIELD_IS_LONG = 32, + TEP_FIELD_IS_FLAG = 64, + TEP_FIELD_IS_SYMBOLIC = 128, }; struct tep_format_field { diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index a0353f2c051a..dcd97acbbc49 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -1716,7 +1716,7 @@ get_value(struct tep_event_format *event, tep_read_number_field(field, record->data, &val); - if (!(field->flags & FIELD_IS_SIGNED)) + if (!(field->flags & TEP_FIELD_IS_SIGNED)) return val; switch (field->size) { @@ -1867,11 +1867,11 @@ static const char *get_field_str(struct filter_arg *arg, struct tep_record *reco char hex[64]; /* If the field is not a string convert it */ - if (arg->str.field->flags & FIELD_IS_STRING) { + if (arg->str.field->flags & TEP_FIELD_IS_STRING) { val = record->data + arg->str.field->offset; size = arg->str.field->size; - if (arg->str.field->flags & FIELD_IS_DYNAMIC) { + if (arg->str.field->flags & TEP_FIELD_IS_DYNAMIC) { addr = *(unsigned int *)val; val = record->data + (addr & 0xffff); size = addr >> 16; @@ -1893,7 +1893,7 @@ static const char *get_field_str(struct filter_arg *arg, struct tep_record *reco pevent = event->pevent; addr = get_value(event, arg->str.field, record); - if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG)) + if (arg->str.field->flags & (TEP_FIELD_IS_POINTER | TEP_FIELD_IS_LONG)) /* convert to a kernel symbol */ val = tep_find_function(pevent, addr); diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 95f3c255d977..90289f31dd87 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1293,7 +1293,7 @@ static int syscall__set_arg_fmts(struct syscall *sc) strcmp(field->name, "path") == 0 || strcmp(field->name, "pathname") == 0)) sc->arg_fmt[idx].scnprintf = SCA_FILENAME; - else if (field->flags & FIELD_IS_POINTER) + else if (field->flags & TEP_FIELD_IS_POINTER) sc->arg_fmt[idx].scnprintf = syscall_arg__scnprintf_hex; else if (strcmp(field->type, "pid_t") == 0) sc->arg_fmt[idx].scnprintf = SCA_PID; diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c index da9d3c0f8ead..5f8501c68da4 100644 --- a/tools/perf/tests/evsel-tp-sched.c +++ b/tools/perf/tests/evsel-tp-sched.c @@ -17,7 +17,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, return -1; } - is_signed = !!(field->flags | FIELD_IS_SIGNED); + is_signed = !!(field->flags | TEP_FIELD_IS_SIGNED); if (should_be_signed && !is_signed) { pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n", evsel->name, name, is_signed, should_be_signed); diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 1817bbcc4a62..2a36fab76994 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -186,16 +186,16 @@ get_tracepoint_field_type(struct ctf_writer *cw, struct tep_format_field *field) { unsigned long flags = field->flags; - if (flags & FIELD_IS_STRING) + if (flags & TEP_FIELD_IS_STRING) return cw->data.string; - if (!(flags & FIELD_IS_SIGNED)) { + if (!(flags & TEP_FIELD_IS_SIGNED)) { /* unsigned long are mostly pointers */ - if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER) + if (flags & TEP_FIELD_IS_LONG || flags & TEP_FIELD_IS_POINTER) return cw->data.u64_hex; } - if (flags & FIELD_IS_SIGNED) { + if (flags & TEP_FIELD_IS_SIGNED) { if (field->size == 8) return cw->data.s64; else @@ -304,10 +304,10 @@ static int add_tracepoint_field_value(struct ctf_writer *cw, name = fmtf->alias; offset = fmtf->offset; len = fmtf->size; - if (flags & FIELD_IS_STRING) - flags &= ~FIELD_IS_ARRAY; + if (flags & TEP_FIELD_IS_STRING) + flags &= ~TEP_FIELD_IS_ARRAY; - if (flags & FIELD_IS_DYNAMIC) { + if (flags & TEP_FIELD_IS_DYNAMIC) { unsigned long long tmp_val; tmp_val = tep_read_number(fmtf->event->pevent, @@ -317,7 +317,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw, offset &= 0xffff; } - if (flags & FIELD_IS_ARRAY) { + if (flags & TEP_FIELD_IS_ARRAY) { type = bt_ctf_event_class_get_field_by_name( event_class, name); @@ -338,7 +338,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw, type = get_tracepoint_field_type(cw, fmtf); for (i = 0; i < n_items; i++) { - if (flags & FIELD_IS_ARRAY) + if (flags & TEP_FIELD_IS_ARRAY) field = bt_ctf_field_array_get_field(array_field, i); else field = bt_ctf_field_create(type); @@ -348,7 +348,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw, return -1; } - if (flags & FIELD_IS_STRING) + if (flags & TEP_FIELD_IS_STRING) ret = string_set_value(field, data + offset + i * len); else { unsigned long long value_int; @@ -357,7 +357,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw, fmtf->event->pevent, data + offset + i * len, len); - if (!(flags & FIELD_IS_SIGNED)) + if (!(flags & TEP_FIELD_IS_SIGNED)) ret = bt_ctf_field_unsigned_integer_set_value( field, value_int); else @@ -369,7 +369,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw, pr_err("failed to set file value %s\n", name); goto err_put_field; } - if (!(flags & FIELD_IS_ARRAY)) { + if (!(flags & TEP_FIELD_IS_ARRAY)) { ret = bt_ctf_event_set_payload(event, name, field); if (ret) { pr_err("failed to set payload %s\n", name); @@ -378,7 +378,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw, } bt_ctf_field_put(field); } - if (flags & FIELD_IS_ARRAY) { + if (flags & TEP_FIELD_IS_ARRAY) { ret = bt_ctf_event_set_payload(event, name, array_field); if (ret) { pr_err("Failed add payload array %s\n", name); @@ -1030,15 +1030,15 @@ static int add_tracepoint_fields_types(struct ctf_writer *cw, * type and don't care that it is an array. What we don't * support is an array of strings. */ - if (flags & FIELD_IS_STRING) - flags &= ~FIELD_IS_ARRAY; + if (flags & TEP_FIELD_IS_STRING) + flags &= ~TEP_FIELD_IS_ARRAY; - if (flags & FIELD_IS_ARRAY) + if (flags & TEP_FIELD_IS_ARRAY) type = bt_ctf_field_type_array_create(type, field->arraylen); ret = event_class_add_field(event_class, type, field); - if (flags & FIELD_IS_ARRAY) + if (flags & TEP_FIELD_IS_ARRAY) bt_ctf_field_type_put(type); if (ret) { diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 751c98a2e336..cb7f01059940 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -2698,7 +2698,7 @@ void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample, offset = field->offset; - if (field->flags & FIELD_IS_DYNAMIC) { + if (field->flags & TEP_FIELD_IS_DYNAMIC) { offset = *(int *)(sample->raw_data + field->offset); offset &= 0xffff; } diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index ebf84fe8cd29..50150dfc0cdf 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -348,28 +348,28 @@ tracepoint_field(struct pyrf_event *pe, struct tep_format_field *field) unsigned long long val; unsigned int offset, len; - if (field->flags & FIELD_IS_ARRAY) { + if (field->flags & TEP_FIELD_IS_ARRAY) { offset = field->offset; len = field->size; - if (field->flags & FIELD_IS_DYNAMIC) { + if (field->flags & TEP_FIELD_IS_DYNAMIC) { val = tep_read_number(pevent, data + offset, len); offset = val; len = offset >> 16; offset &= 0xffff; } - if (field->flags & FIELD_IS_STRING && + if (field->flags & TEP_FIELD_IS_STRING && is_printable_array(data + offset, len)) { ret = _PyUnicode_FromString((char *)data + offset); } else { ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); - field->flags &= ~FIELD_IS_STRING; + field->flags &= ~TEP_FIELD_IS_STRING; } } else { val = tep_read_number(pevent, data + field->offset, field->size); - if (field->flags & FIELD_IS_POINTER) + if (field->flags & TEP_FIELD_IS_POINTER) ret = PyLong_FromUnsignedLong((unsigned long) val); - else if (field->flags & FIELD_IS_SIGNED) + else if (field->flags & TEP_FIELD_IS_SIGNED) ret = PyLong_FromLong((long) val); else ret = PyLong_FromUnsignedLong((unsigned long) val); diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 1bb0b0c685b7..5d6a55183ad6 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -388,9 +388,9 @@ static void perl_process_tracepoint(struct perf_sample *sample, /* common fields other than pid can be accessed via xsub fns */ for (field = event->format.fields; field; field = field->next) { - if (field->flags & FIELD_IS_STRING) { + if (field->flags & TEP_FIELD_IS_STRING) { int offset; - if (field->flags & FIELD_IS_DYNAMIC) { + if (field->flags & TEP_FIELD_IS_DYNAMIC) { offset = *(int *)(data + field->offset); offset &= 0xffff; } else @@ -399,7 +399,7 @@ static void perl_process_tracepoint(struct perf_sample *sample, } else { /* FIELD_IS_NUMERIC */ val = read_size(event, data + field->offset, field->size); - if (field->flags & FIELD_IS_SIGNED) { + if (field->flags & TEP_FIELD_IS_SIGNED) { XPUSHs(sv_2mortal(newSViv(val))); } else { XPUSHs(sv_2mortal(newSVuv(val))); @@ -646,11 +646,11 @@ sub print_backtrace\n\ count++; fprintf(ofp, "%s=", f->name); - if (f->flags & FIELD_IS_STRING || - f->flags & FIELD_IS_FLAG || - f->flags & FIELD_IS_SYMBOLIC) + if (f->flags & TEP_FIELD_IS_STRING || + f->flags & TEP_FIELD_IS_FLAG || + f->flags & TEP_FIELD_IS_SYMBOLIC) fprintf(ofp, "%%s"); - else if (f->flags & FIELD_IS_SIGNED) + else if (f->flags & TEP_FIELD_IS_SIGNED) fprintf(ofp, "%%d"); else fprintf(ofp, "%%u"); @@ -668,7 +668,7 @@ sub print_backtrace\n\ if (++count % 5 == 0) fprintf(ofp, "\n\t "); - if (f->flags & FIELD_IS_FLAG) { + if (f->flags & TEP_FIELD_IS_FLAG) { if ((count - 1) % 5 != 0) { fprintf(ofp, "\n\t "); count = 4; @@ -678,7 +678,7 @@ sub print_backtrace\n\ event->name); fprintf(ofp, "\"%s\", $%s)", f->name, f->name); - } else if (f->flags & FIELD_IS_SYMBOLIC) { + } else if (f->flags & TEP_FIELD_IS_SYMBOLIC) { if ((count - 1) % 5 != 0) { fprintf(ofp, "\n\t "); count = 4; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index dc26e58a791e..ba191def1ea9 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -335,7 +335,7 @@ static void define_event_symbols(struct tep_event_format *event, static PyObject *get_field_numeric_entry(struct tep_event_format *event, struct tep_format_field *field, void *data) { - bool is_array = field->flags & FIELD_IS_ARRAY; + bool is_array = field->flags & TEP_FIELD_IS_ARRAY; PyObject *obj = NULL, *list = NULL; unsigned long long val; unsigned int item_size, n_items, i; @@ -353,7 +353,7 @@ static PyObject *get_field_numeric_entry(struct tep_event_format *event, val = read_size(event, data + field->offset + i * item_size, item_size); - if (field->flags & FIELD_IS_SIGNED) { + if (field->flags & TEP_FIELD_IS_SIGNED) { if ((long long)val >= LONG_MIN && (long long)val <= LONG_MAX) obj = _PyLong_FromLong(val); @@ -867,22 +867,22 @@ static void python_process_tracepoint(struct perf_sample *sample, unsigned int offset, len; unsigned long long val; - if (field->flags & FIELD_IS_ARRAY) { + if (field->flags & TEP_FIELD_IS_ARRAY) { offset = field->offset; len = field->size; - if (field->flags & FIELD_IS_DYNAMIC) { + if (field->flags & TEP_FIELD_IS_DYNAMIC) { val = tep_read_number(scripting_context->pevent, data + offset, len); offset = val; len = offset >> 16; offset &= 0xffff; } - if (field->flags & FIELD_IS_STRING && + if (field->flags & TEP_FIELD_IS_STRING && is_printable_array(data + offset, len)) { obj = _PyUnicode_FromString((char *) data + offset); } else { obj = PyByteArray_FromStringAndSize((const char *) data + offset, len); - field->flags &= ~FIELD_IS_STRING; + field->flags &= ~TEP_FIELD_IS_STRING; } } else { /* FIELD_IS_NUMERIC */ obj = get_field_numeric_entry(event, field, data); @@ -1686,12 +1686,12 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile count++; fprintf(ofp, "%s=", f->name); - if (f->flags & FIELD_IS_STRING || - f->flags & FIELD_IS_FLAG || - f->flags & FIELD_IS_ARRAY || - f->flags & FIELD_IS_SYMBOLIC) + if (f->flags & TEP_FIELD_IS_STRING || + f->flags & TEP_FIELD_IS_FLAG || + f->flags & TEP_FIELD_IS_ARRAY || + f->flags & TEP_FIELD_IS_SYMBOLIC) fprintf(ofp, "%%s"); - else if (f->flags & FIELD_IS_SIGNED) + else if (f->flags & TEP_FIELD_IS_SIGNED) fprintf(ofp, "%%d"); else fprintf(ofp, "%%u"); @@ -1709,7 +1709,7 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile if (++count % 5 == 0) fprintf(ofp, "\n\t\t"); - if (f->flags & FIELD_IS_FLAG) { + if (f->flags & TEP_FIELD_IS_FLAG) { if ((count - 1) % 5 != 0) { fprintf(ofp, "\n\t\t"); count = 4; @@ -1719,7 +1719,7 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile event->name); fprintf(ofp, "\"%s\", %s)", f->name, f->name); - } else if (f->flags & FIELD_IS_SYMBOLIC) { + } else if (f->flags & TEP_FIELD_IS_SYMBOLIC) { if ((count - 1) % 5 != 0) { fprintf(ofp, "\n\t\t"); count = 4; diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 5e3179d995f9..f96c005b3c41 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1899,7 +1899,7 @@ static int hde_width(struct hpp_dynamic_entry *hde) if (namelen > len) len = namelen; - if (!(hde->field->flags & FIELD_IS_STRING)) { + if (!(hde->field->flags & TEP_FIELD_IS_STRING)) { /* length for print hex numbers */ fieldlen = hde->field->size * 2 + 2; } @@ -2071,7 +2071,7 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt, } field = hde->field; - if (field->flags & FIELD_IS_DYNAMIC) { + if (field->flags & TEP_FIELD_IS_DYNAMIC) { unsigned long long dyn; tep_read_number_field(field, a->raw_data, &dyn); From f25d9e09e9354bded677d21b51a7b1879cfa02a8 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:47 -0400 Subject: [PATCH 106/155] tools lib traceevent: Rename enum event_{sort_}type to enum tep_event_{sort_}type In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This renames enum event_type to enum tep_event_type, enum event_sort_type to enum tep_event_sort_type and add prefix TEP_ to all enum's members Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185722.961022207@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 488 ++++++++++++++-------------- tools/lib/traceevent/event-parse.h | 34 +- tools/lib/traceevent/parse-filter.c | 36 +- 3 files changed, 279 insertions(+), 279 deletions(-) diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 508c89365c90..1696dd9534bc 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -770,12 +770,12 @@ static int add_event(struct tep_handle *pevent, struct tep_event_format *event) return 0; } -static int event_item_type(enum event_type type) +static int event_item_type(enum tep_event_type type) { switch (type) { - case EVENT_ITEM ... EVENT_SQUOTE: + case TEP_EVENT_ITEM ... TEP_EVENT_SQUOTE: return 1; - case EVENT_ERROR ... EVENT_DELIM: + case TEP_EVENT_ERROR ... TEP_EVENT_DELIM: default: return 0; } @@ -863,24 +863,24 @@ static void free_arg(struct print_arg *arg) free(arg); } -static enum event_type get_type(int ch) +static enum tep_event_type get_type(int ch) { if (ch == '\n') - return EVENT_NEWLINE; + return TEP_EVENT_NEWLINE; if (isspace(ch)) - return EVENT_SPACE; + return TEP_EVENT_SPACE; if (isalnum(ch) || ch == '_') - return EVENT_ITEM; + return TEP_EVENT_ITEM; if (ch == '\'') - return EVENT_SQUOTE; + return TEP_EVENT_SQUOTE; if (ch == '"') - return EVENT_DQUOTE; + return TEP_EVENT_DQUOTE; if (!isprint(ch)) - return EVENT_NONE; + return TEP_EVENT_NONE; if (ch == '(' || ch == ')' || ch == ',') - return EVENT_DELIM; + return TEP_EVENT_DELIM; - return EVENT_OP; + return TEP_EVENT_OP; } static int __read_char(void) @@ -928,38 +928,38 @@ static int extend_token(char **tok, char *buf, int size) return 0; } -static enum event_type force_token(const char *str, char **tok); +static enum tep_event_type force_token(const char *str, char **tok); -static enum event_type __read_token(char **tok) +static enum tep_event_type __read_token(char **tok) { char buf[BUFSIZ]; int ch, last_ch, quote_ch, next_ch; int i = 0; int tok_size = 0; - enum event_type type; + enum tep_event_type type; *tok = NULL; ch = __read_char(); if (ch < 0) - return EVENT_NONE; + return TEP_EVENT_NONE; type = get_type(ch); - if (type == EVENT_NONE) + if (type == TEP_EVENT_NONE) return type; buf[i++] = ch; switch (type) { - case EVENT_NEWLINE: - case EVENT_DELIM: + case TEP_EVENT_NEWLINE: + case TEP_EVENT_DELIM: if (asprintf(tok, "%c", ch) < 0) - return EVENT_ERROR; + return TEP_EVENT_ERROR; return type; - case EVENT_OP: + case TEP_EVENT_OP: switch (ch) { case '-': next_ch = __peek_char(); @@ -1002,8 +1002,8 @@ static enum event_type __read_token(char **tok) buf[i++] = __read_char(); goto out; - case EVENT_DQUOTE: - case EVENT_SQUOTE: + case TEP_EVENT_DQUOTE: + case TEP_EVENT_SQUOTE: /* don't keep quotes */ i--; quote_ch = ch; @@ -1015,7 +1015,7 @@ static enum event_type __read_token(char **tok) tok_size += BUFSIZ; if (extend_token(tok, buf, tok_size) < 0) - return EVENT_NONE; + return TEP_EVENT_NONE; i = 0; } last_ch = ch; @@ -1032,7 +1032,7 @@ static enum event_type __read_token(char **tok) * For strings (double quotes) check the next token. * If it is another string, concatinate the two. */ - if (type == EVENT_DQUOTE) { + if (type == TEP_EVENT_DQUOTE) { unsigned long long save_input_buf_ptr = input_buf_ptr; do { @@ -1045,8 +1045,8 @@ static enum event_type __read_token(char **tok) goto out; - case EVENT_ERROR ... EVENT_SPACE: - case EVENT_ITEM: + case TEP_EVENT_ERROR ... TEP_EVENT_SPACE: + case TEP_EVENT_ITEM: default: break; } @@ -1057,7 +1057,7 @@ static enum event_type __read_token(char **tok) tok_size += BUFSIZ; if (extend_token(tok, buf, tok_size) < 0) - return EVENT_NONE; + return TEP_EVENT_NONE; i = 0; } ch = __read_char(); @@ -1067,9 +1067,9 @@ static enum event_type __read_token(char **tok) out: buf[i] = 0; if (extend_token(tok, buf, tok_size + i + 1) < 0) - return EVENT_NONE; + return TEP_EVENT_NONE; - if (type == EVENT_ITEM) { + if (type == TEP_EVENT_ITEM) { /* * Older versions of the kernel has a bug that * creates invalid symbols and will break the mac80211 @@ -1096,12 +1096,12 @@ static enum event_type __read_token(char **tok) return type; } -static enum event_type force_token(const char *str, char **tok) +static enum tep_event_type force_token(const char *str, char **tok) { const char *save_input_buf; unsigned long long save_input_buf_ptr; unsigned long long save_input_buf_siz; - enum event_type type; + enum tep_event_type type; /* save off the current input pointers */ save_input_buf = input_buf; @@ -1126,13 +1126,13 @@ static void free_token(char *tok) free(tok); } -static enum event_type read_token(char **tok) +static enum tep_event_type read_token(char **tok) { - enum event_type type; + enum tep_event_type type; for (;;) { type = __read_token(tok); - if (type != EVENT_SPACE) + if (type != TEP_EVENT_SPACE) return type; free_token(*tok); @@ -1140,7 +1140,7 @@ static enum event_type read_token(char **tok) /* not reached */ *tok = NULL; - return EVENT_NONE; + return TEP_EVENT_NONE; } /** @@ -1152,7 +1152,7 @@ static enum event_type read_token(char **tok) * * Returns the token type. */ -enum event_type tep_read_token(char **tok) +enum tep_event_type tep_read_token(char **tok) { return read_token(tok); } @@ -1167,13 +1167,13 @@ void tep_free_token(char *token) } /* no newline */ -static enum event_type read_token_item(char **tok) +static enum tep_event_type read_token_item(char **tok) { - enum event_type type; + enum tep_event_type type; for (;;) { type = __read_token(tok); - if (type != EVENT_SPACE && type != EVENT_NEWLINE) + if (type != TEP_EVENT_SPACE && type != TEP_EVENT_NEWLINE) return type; free_token(*tok); *tok = NULL; @@ -1181,10 +1181,10 @@ static enum event_type read_token_item(char **tok) /* not reached */ *tok = NULL; - return EVENT_NONE; + return TEP_EVENT_NONE; } -static int test_type(enum event_type type, enum event_type expect) +static int test_type(enum tep_event_type type, enum tep_event_type expect) { if (type != expect) { do_warning("Error: expected type %d but read %d", @@ -1194,8 +1194,8 @@ static int test_type(enum event_type type, enum event_type expect) return 0; } -static int test_type_token(enum event_type type, const char *token, - enum event_type expect, const char *expect_tok) +static int test_type_token(enum tep_event_type type, const char *token, + enum tep_event_type expect, const char *expect_tok) { if (type != expect) { do_warning("Error: expected type %d but read %d", @@ -1211,9 +1211,9 @@ static int test_type_token(enum event_type type, const char *token, return 0; } -static int __read_expect_type(enum event_type expect, char **tok, int newline_ok) +static int __read_expect_type(enum tep_event_type expect, char **tok, int newline_ok) { - enum event_type type; + enum tep_event_type type; if (newline_ok) type = read_token(tok); @@ -1222,15 +1222,15 @@ static int __read_expect_type(enum event_type expect, char **tok, int newline_ok return test_type(type, expect); } -static int read_expect_type(enum event_type expect, char **tok) +static int read_expect_type(enum tep_event_type expect, char **tok) { return __read_expect_type(expect, tok, 1); } -static int __read_expected(enum event_type expect, const char *str, +static int __read_expected(enum tep_event_type expect, const char *str, int newline_ok) { - enum event_type type; + enum tep_event_type type; char *token; int ret; @@ -1246,12 +1246,12 @@ static int __read_expected(enum event_type expect, const char *str, return ret; } -static int read_expected(enum event_type expect, const char *str) +static int read_expected(enum tep_event_type expect, const char *str) { return __read_expected(expect, str, 1); } -static int read_expected_item(enum event_type expect, const char *str) +static int read_expected_item(enum tep_event_type expect, const char *str) { return __read_expected(expect, str, 0); } @@ -1260,13 +1260,13 @@ static char *event_read_name(void) { char *token; - if (read_expected(EVENT_ITEM, "name") < 0) + if (read_expected(TEP_EVENT_ITEM, "name") < 0) return NULL; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return NULL; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto fail; return token; @@ -1281,13 +1281,13 @@ static int event_read_id(void) char *token; int id; - if (read_expected_item(EVENT_ITEM, "ID") < 0) + if (read_expected_item(TEP_EVENT_ITEM, "ID") < 0) return -1; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return -1; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto fail; id = strtoul(token, NULL, 0); @@ -1357,7 +1357,7 @@ static unsigned int type_size(const char *name) static int event_read_fields(struct tep_event_format *event, struct tep_format_field **fields) { struct tep_format_field *field = NULL; - enum event_type type; + enum tep_event_type type; char *token; char *last_token; int count = 0; @@ -1366,14 +1366,14 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f unsigned int size_dynamic = 0; type = read_token(&token); - if (type == EVENT_NEWLINE) { + if (type == TEP_EVENT_NEWLINE) { free_token(token); return count; } count++; - if (test_type_token(type, token, EVENT_ITEM, "field")) + if (test_type_token(type, token, TEP_EVENT_ITEM, "field")) goto fail; free_token(token); @@ -1383,16 +1383,16 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f * Just ignore it. */ if (event->flags & EVENT_FL_ISFTRACE && - type == EVENT_ITEM && strcmp(token, "special") == 0) { + type == TEP_EVENT_ITEM && strcmp(token, "special") == 0) { free_token(token); type = read_token(&token); } - if (test_type_token(type, token, EVENT_OP, ":") < 0) + if (test_type_token(type, token, TEP_EVENT_OP, ":") < 0) goto fail; free_token(token); - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto fail; last_token = token; @@ -1406,14 +1406,14 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f /* read the rest of the type */ for (;;) { type = read_token(&token); - if (type == EVENT_ITEM || - (type == EVENT_OP && strcmp(token, "*") == 0) || + if (type == TEP_EVENT_ITEM || + (type == TEP_EVENT_OP && strcmp(token, "*") == 0) || /* * Some of the ftrace fields are broken and have * an illegal "." in them. */ (event->flags & EVENT_FL_ISFTRACE && - type == EVENT_OP && strcmp(token, ".") == 0)) { + type == TEP_EVENT_OP && strcmp(token, ".") == 0)) { if (strcmp(token, "*") == 0) field->flags |= TEP_FIELD_IS_POINTER; @@ -1446,11 +1446,11 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f } field->name = field->alias = last_token; - if (test_type(type, EVENT_OP)) + if (test_type(type, TEP_EVENT_OP)) goto fail; if (strcmp(token, "[") == 0) { - enum event_type last_type = type; + enum tep_event_type last_type = type; char *brackets = token; char *new_brackets; int len; @@ -1459,14 +1459,14 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f type = read_token(&token); - if (type == EVENT_ITEM) + if (type == TEP_EVENT_ITEM) field->arraylen = strtoul(token, NULL, 0); else field->arraylen = 0; while (strcmp(token, "]") != 0) { - if (last_type == EVENT_ITEM && - type == EVENT_ITEM) + if (last_type == TEP_EVENT_ITEM && + type == TEP_EVENT_ITEM) len = 2; else len = 1; @@ -1487,7 +1487,7 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f field->arraylen = strtoul(token, NULL, 0); free_token(token); type = read_token(&token); - if (type == EVENT_NONE) { + if (type == TEP_EVENT_NONE) { do_warning_event(event, "failed to find token"); goto fail; } @@ -1510,7 +1510,7 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f * If the next token is not an OP, then it is of * the format: type [] item; */ - if (type == EVENT_ITEM) { + if (type == TEP_EVENT_ITEM) { char *new_type; new_type = realloc(field->type, strlen(field->type) + @@ -1550,60 +1550,60 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f if (field_is_long(field)) field->flags |= TEP_FIELD_IS_LONG; - if (test_type_token(type, token, EVENT_OP, ";")) + if (test_type_token(type, token, TEP_EVENT_OP, ";")) goto fail; free_token(token); - if (read_expected(EVENT_ITEM, "offset") < 0) + if (read_expected(TEP_EVENT_ITEM, "offset") < 0) goto fail_expect; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) goto fail_expect; - if (read_expect_type(EVENT_ITEM, &token)) + if (read_expect_type(TEP_EVENT_ITEM, &token)) goto fail; field->offset = strtoul(token, NULL, 0); free_token(token); - if (read_expected(EVENT_OP, ";") < 0) + if (read_expected(TEP_EVENT_OP, ";") < 0) goto fail_expect; - if (read_expected(EVENT_ITEM, "size") < 0) + if (read_expected(TEP_EVENT_ITEM, "size") < 0) goto fail_expect; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) goto fail_expect; - if (read_expect_type(EVENT_ITEM, &token)) + if (read_expect_type(TEP_EVENT_ITEM, &token)) goto fail; field->size = strtoul(token, NULL, 0); free_token(token); - if (read_expected(EVENT_OP, ";") < 0) + if (read_expected(TEP_EVENT_OP, ";") < 0) goto fail_expect; type = read_token(&token); - if (type != EVENT_NEWLINE) { + if (type != TEP_EVENT_NEWLINE) { /* newer versions of the kernel have a "signed" type */ - if (test_type_token(type, token, EVENT_ITEM, "signed")) + if (test_type_token(type, token, TEP_EVENT_ITEM, "signed")) goto fail; free_token(token); - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) goto fail_expect; - if (read_expect_type(EVENT_ITEM, &token)) + if (read_expect_type(TEP_EVENT_ITEM, &token)) goto fail; if (strtoul(token, NULL, 0)) field->flags |= TEP_FIELD_IS_SIGNED; free_token(token); - if (read_expected(EVENT_OP, ";") < 0) + if (read_expected(TEP_EVENT_OP, ";") < 0) goto fail_expect; - if (read_expect_type(EVENT_NEWLINE, &token)) + if (read_expect_type(TEP_EVENT_NEWLINE, &token)) goto fail; } @@ -1646,13 +1646,13 @@ static int event_read_format(struct tep_event_format *event) char *token; int ret; - if (read_expected_item(EVENT_ITEM, "format") < 0) + if (read_expected_item(TEP_EVENT_ITEM, "format") < 0) return -1; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return -1; - if (read_expect_type(EVENT_NEWLINE, &token)) + if (read_expect_type(TEP_EVENT_NEWLINE, &token)) goto fail; free_token(token); @@ -1673,14 +1673,14 @@ static int event_read_format(struct tep_event_format *event) return -1; } -static enum event_type +static enum tep_event_type process_arg_token(struct tep_event_format *event, struct print_arg *arg, - char **tok, enum event_type type); + char **tok, enum tep_event_type type); -static enum event_type +static enum tep_event_type process_arg(struct tep_event_format *event, struct print_arg *arg, char **tok) { - enum event_type type; + enum tep_event_type type; char *token; type = read_token(&token); @@ -1689,32 +1689,32 @@ process_arg(struct tep_event_format *event, struct print_arg *arg, char **tok) return process_arg_token(event, arg, tok, type); } -static enum event_type +static enum tep_event_type process_op(struct tep_event_format *event, struct print_arg *arg, char **tok); /* * For __print_symbolic() and __print_flags, we need to completely * evaluate the first argument, which defines what to print next. */ -static enum event_type +static enum tep_event_type process_field_arg(struct tep_event_format *event, struct print_arg *arg, char **tok) { - enum event_type type; + enum tep_event_type type; type = process_arg(event, arg, tok); - while (type == EVENT_OP) { + while (type == TEP_EVENT_OP) { type = process_op(event, arg, tok); } return type; } -static enum event_type +static enum tep_event_type process_cond(struct tep_event_format *event, struct print_arg *top, char **tok) { struct print_arg *arg, *left, *right; - enum event_type type; + enum tep_event_type type; char *token = NULL; arg = alloc_arg(); @@ -1737,16 +1737,16 @@ process_cond(struct tep_event_format *event, struct print_arg *top, char **tok) type = process_arg(event, left, &token); again: - if (type == EVENT_ERROR) + if (type == TEP_EVENT_ERROR) goto out_free; /* Handle other operations in the arguments */ - if (type == EVENT_OP && strcmp(token, ":") != 0) { + if (type == TEP_EVENT_OP && strcmp(token, ":") != 0) { type = process_op(event, left, &token); goto again; } - if (test_type_token(type, token, EVENT_OP, ":")) + if (test_type_token(type, token, TEP_EVENT_OP, ":")) goto out_free; arg->op.op = token; @@ -1763,14 +1763,14 @@ out_free: top->op.right = NULL; free_token(token); free_arg(arg); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type +static enum tep_event_type process_array(struct tep_event_format *event, struct print_arg *top, char **tok) { struct print_arg *arg; - enum event_type type; + enum tep_event_type type; char *token = NULL; arg = alloc_arg(); @@ -1778,12 +1778,12 @@ process_array(struct tep_event_format *event, struct print_arg *top, char **tok) do_warning_event(event, "%s: not enough memory!", __func__); /* '*tok' is set to top->op.op. No need to free. */ *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } *tok = NULL; type = process_arg(event, arg, &token); - if (test_type_token(type, token, EVENT_OP, "]")) + if (test_type_token(type, token, TEP_EVENT_OP, "]")) goto out_free; top->op.right = arg; @@ -1797,7 +1797,7 @@ process_array(struct tep_event_format *event, struct print_arg *top, char **tok) out_free: free_token(token); free_arg(arg); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } static int get_op_prio(char *op) @@ -1868,11 +1868,11 @@ static int set_op_prio(struct print_arg *arg) } /* Note, *tok does not get freed, but will most likely be saved */ -static enum event_type +static enum tep_event_type process_op(struct tep_event_format *event, struct print_arg *arg, char **tok) { struct print_arg *left, *right = NULL; - enum event_type type; + enum tep_event_type type; char *token; /* the op is passed in via tok */ @@ -1974,7 +1974,7 @@ process_op(struct tep_event_format *event, struct print_arg *arg, char **tok) /* could just be a type pointer */ if ((strcmp(arg->op.op, "*") == 0) && - type == EVENT_DELIM && (strcmp(token, ")") == 0)) { + type == TEP_EVENT_DELIM && (strcmp(token, ")") == 0)) { char *new_atom; if (left->type != PRINT_ATOM) { @@ -2000,7 +2000,7 @@ process_op(struct tep_event_format *event, struct print_arg *arg, char **tok) goto out_warn_free; type = process_arg_token(event, right, tok, type); - if (type == EVENT_ERROR) { + if (type == TEP_EVENT_ERROR) { free_arg(right); /* token was freed in process_arg_token() via *tok */ token = NULL; @@ -2047,7 +2047,7 @@ process_op(struct tep_event_format *event, struct print_arg *arg, char **tok) goto out_free; } - if (type == EVENT_OP && strcmp(*tok, ":") != 0) { + if (type == TEP_EVENT_OP && strcmp(*tok, ":") != 0) { int prio; /* higher prios need to be closer to the root */ @@ -2066,21 +2066,21 @@ out_warn_free: out_free: free_token(token); *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type +static enum tep_event_type process_entry(struct tep_event_format *event __maybe_unused, struct print_arg *arg, char **tok) { - enum event_type type; + enum tep_event_type type; char *field; char *token; - if (read_expected(EVENT_OP, "->") < 0) + if (read_expected(TEP_EVENT_OP, "->") < 0) goto out_err; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto out_free; field = token; @@ -2106,14 +2106,14 @@ process_entry(struct tep_event_format *event __maybe_unused, struct print_arg *a free_token(token); out_err: *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } static int alloc_and_process_delim(struct tep_event_format *event, char *next_token, struct print_arg **print_arg) { struct print_arg *field; - enum event_type type; + enum tep_event_type type; char *token; int ret = 0; @@ -2126,7 +2126,7 @@ static int alloc_and_process_delim(struct tep_event_format *event, char *next_to type = process_arg(event, field, &token); - if (test_type_token(type, token, EVENT_DELIM, next_token)) { + if (test_type_token(type, token, TEP_EVENT_DELIM, next_token)) { errno = EINVAL; ret = -1; free_arg(field); @@ -2443,10 +2443,10 @@ static char *arg_eval (struct print_arg *arg) return NULL; } -static enum event_type +static enum tep_event_type process_fields(struct tep_event_format *event, struct print_flag_sym **list, char **tok) { - enum event_type type; + enum tep_event_type type; struct print_arg *arg = NULL; struct print_flag_sym *field; char *token = *tok; @@ -2455,7 +2455,7 @@ process_fields(struct tep_event_format *event, struct print_flag_sym **list, cha do { free_token(token); type = read_token_item(&token); - if (test_type_token(type, token, EVENT_OP, "{")) + if (test_type_token(type, token, TEP_EVENT_OP, "{")) break; arg = alloc_arg(); @@ -2465,13 +2465,13 @@ process_fields(struct tep_event_format *event, struct print_flag_sym **list, cha free_token(token); type = process_arg(event, arg, &token); - if (type == EVENT_OP) + if (type == TEP_EVENT_OP) type = process_op(event, arg, &token); - if (type == EVENT_ERROR) + if (type == TEP_EVENT_ERROR) goto out_free; - if (test_type_token(type, token, EVENT_DELIM, ",")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ",")) goto out_free; field = calloc(1, sizeof(*field)); @@ -2492,7 +2492,7 @@ process_fields(struct tep_event_format *event, struct print_flag_sym **list, cha free_token(token); type = process_arg(event, arg, &token); - if (test_type_token(type, token, EVENT_OP, "}")) + if (test_type_token(type, token, TEP_EVENT_OP, "}")) goto out_free_field; value = arg_eval(arg); @@ -2509,7 +2509,7 @@ process_fields(struct tep_event_format *event, struct print_flag_sym **list, cha free_token(token); type = read_token_item(&token); - } while (type == EVENT_DELIM && strcmp(token, ",") == 0); + } while (type == TEP_EVENT_DELIM && strcmp(token, ",") == 0); *tok = token; return type; @@ -2521,14 +2521,14 @@ out_free: free_token(token); *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type +static enum tep_event_type process_flags(struct tep_event_format *event, struct print_arg *arg, char **tok) { struct print_arg *field; - enum event_type type; + enum tep_event_type type; char *token = NULL; memset(arg, 0, sizeof(*arg)); @@ -2543,10 +2543,10 @@ process_flags(struct tep_event_format *event, struct print_arg *arg, char **tok) type = process_field_arg(event, field, &token); /* Handle operations in the first argument */ - while (type == EVENT_OP) + while (type == TEP_EVENT_OP) type = process_op(event, field, &token); - if (test_type_token(type, token, EVENT_DELIM, ",")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ",")) goto out_free_field; free_token(token); @@ -2558,11 +2558,11 @@ process_flags(struct tep_event_format *event, struct print_arg *arg, char **tok) type = read_token_item(&token); } - if (test_type_token(type, token, EVENT_DELIM, ",")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ",")) goto out_free; type = process_fields(event, &arg->flags.flags, &token); - if (test_type_token(type, token, EVENT_DELIM, ")")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ")")) goto out_free; free_token(token); @@ -2574,14 +2574,14 @@ out_free_field: out_free: free_token(token); *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type +static enum tep_event_type process_symbols(struct tep_event_format *event, struct print_arg *arg, char **tok) { struct print_arg *field; - enum event_type type; + enum tep_event_type type; char *token = NULL; memset(arg, 0, sizeof(*arg)); @@ -2595,13 +2595,13 @@ process_symbols(struct tep_event_format *event, struct print_arg *arg, char **to type = process_field_arg(event, field, &token); - if (test_type_token(type, token, EVENT_DELIM, ",")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ",")) goto out_free_field; arg->symbol.field = field; type = process_fields(event, &arg->symbol.symbols, &token); - if (test_type_token(type, token, EVENT_DELIM, ")")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ")")) goto out_free; free_token(token); @@ -2613,10 +2613,10 @@ out_free_field: out_free: free_token(token); *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type +static enum tep_event_type process_hex_common(struct tep_event_format *event, struct print_arg *arg, char **tok, enum print_arg_type type) { @@ -2636,23 +2636,23 @@ free_field: arg->hex.field = NULL; out: *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type +static enum tep_event_type process_hex(struct tep_event_format *event, struct print_arg *arg, char **tok) { return process_hex_common(event, arg, tok, PRINT_HEX); } -static enum event_type +static enum tep_event_type process_hex_str(struct tep_event_format *event, struct print_arg *arg, char **tok) { return process_hex_common(event, arg, tok, PRINT_HEX_STR); } -static enum event_type +static enum tep_event_type process_int_array(struct tep_event_format *event, struct print_arg *arg, char **tok) { memset(arg, 0, sizeof(*arg)); @@ -2677,14 +2677,14 @@ free_field: arg->int_array.field = NULL; out: *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type +static enum tep_event_type process_dynamic_array(struct tep_event_format *event, struct print_arg *arg, char **tok) { struct tep_format_field *field; - enum event_type type; + enum tep_event_type type; char *token; memset(arg, 0, sizeof(*arg)); @@ -2696,7 +2696,7 @@ process_dynamic_array(struct tep_event_format *event, struct print_arg *arg, cha */ type = read_token(&token); *tok = token; - if (type != EVENT_ITEM) + if (type != TEP_EVENT_ITEM) goto out_free; /* Find the field */ @@ -2708,13 +2708,13 @@ process_dynamic_array(struct tep_event_format *event, struct print_arg *arg, cha arg->dynarray.field = field; arg->dynarray.index = 0; - if (read_expected(EVENT_DELIM, ")") < 0) + if (read_expected(TEP_EVENT_DELIM, ")") < 0) goto out_free; free_token(token); type = read_token_item(&token); *tok = token; - if (type != EVENT_OP || strcmp(token, "[") != 0) + if (type != TEP_EVENT_OP || strcmp(token, "[") != 0) return type; free_token(token); @@ -2722,14 +2722,14 @@ process_dynamic_array(struct tep_event_format *event, struct print_arg *arg, cha if (!arg) { do_warning_event(event, "%s: not enough memory!", __func__); *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } type = process_arg(event, arg, &token); - if (type == EVENT_ERROR) + if (type == TEP_EVENT_ERROR) goto out_free_arg; - if (!test_type_token(type, token, EVENT_OP, "]")) + if (!test_type_token(type, token, TEP_EVENT_OP, "]")) goto out_free_arg; free_token(token); @@ -2741,18 +2741,18 @@ process_dynamic_array(struct tep_event_format *event, struct print_arg *arg, cha out_free: free_token(token); *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type +static enum tep_event_type process_dynamic_array_len(struct tep_event_format *event, struct print_arg *arg, char **tok) { struct tep_format_field *field; - enum event_type type; + enum tep_event_type type; char *token; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto out_free; arg->type = PRINT_DYNAMIC_ARRAY_LEN; @@ -2765,7 +2765,7 @@ process_dynamic_array_len(struct tep_event_format *event, struct print_arg *arg, arg->dynarray.field = field; arg->dynarray.index = 0; - if (read_expected(EVENT_DELIM, ")") < 0) + if (read_expected(TEP_EVENT_DELIM, ")") < 0) goto out_err; type = read_token(&token); @@ -2777,28 +2777,28 @@ process_dynamic_array_len(struct tep_event_format *event, struct print_arg *arg, free_token(token); out_err: *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type +static enum tep_event_type process_paren(struct tep_event_format *event, struct print_arg *arg, char **tok) { struct print_arg *item_arg; - enum event_type type; + enum tep_event_type type; char *token; type = process_arg(event, arg, &token); - if (type == EVENT_ERROR) + if (type == TEP_EVENT_ERROR) goto out_free; - if (type == EVENT_OP) + if (type == TEP_EVENT_OP) type = process_op(event, arg, &token); - if (type == EVENT_ERROR) + if (type == TEP_EVENT_ERROR) goto out_free; - if (test_type_token(type, token, EVENT_DELIM, ")")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ")")) goto out_free; free_token(token); @@ -2809,7 +2809,7 @@ process_paren(struct tep_event_format *event, struct print_arg *arg, char **tok) * this was a typecast. */ if (event_item_type(type) || - (type == EVENT_DELIM && strcmp(token, "(") == 0)) { + (type == TEP_EVENT_DELIM && strcmp(token, "(") == 0)) { /* make this a typecast and contine */ @@ -2839,25 +2839,25 @@ process_paren(struct tep_event_format *event, struct print_arg *arg, char **tok) out_free: free_token(token); *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type +static enum tep_event_type process_str(struct tep_event_format *event __maybe_unused, struct print_arg *arg, char **tok) { - enum event_type type; + enum tep_event_type type; char *token; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto out_free; arg->type = PRINT_STRING; arg->string.string = token; arg->string.offset = -1; - if (read_expected(EVENT_DELIM, ")") < 0) + if (read_expected(TEP_EVENT_DELIM, ")") < 0) goto out_err; type = read_token(&token); @@ -2869,24 +2869,24 @@ process_str(struct tep_event_format *event __maybe_unused, struct print_arg *arg free_token(token); out_err: *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type +static enum tep_event_type process_bitmask(struct tep_event_format *event __maybe_unused, struct print_arg *arg, char **tok) { - enum event_type type; + enum tep_event_type type; char *token; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto out_free; arg->type = PRINT_BITMASK; arg->bitmask.bitmask = token; arg->bitmask.offset = -1; - if (read_expected(EVENT_DELIM, ")") < 0) + if (read_expected(TEP_EVENT_DELIM, ")") < 0) goto out_err; type = read_token(&token); @@ -2898,7 +2898,7 @@ process_bitmask(struct tep_event_format *event __maybe_unused, struct print_arg free_token(token); out_err: *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } static struct tep_function_handler * @@ -2933,13 +2933,13 @@ static void remove_func_handler(struct tep_handle *pevent, char *func_name) } } -static enum event_type +static enum tep_event_type process_func_handler(struct tep_event_format *event, struct tep_function_handler *func, struct print_arg *arg, char **tok) { struct print_arg **next_arg; struct print_arg *farg; - enum event_type type; + enum tep_event_type type; char *token; int i; @@ -2954,12 +2954,12 @@ process_func_handler(struct tep_event_format *event, struct tep_function_handler if (!farg) { do_warning_event(event, "%s: not enough memory!", __func__); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } type = process_arg(event, farg, &token); if (i < (func->nr_args - 1)) { - if (type != EVENT_DELIM || strcmp(token, ",") != 0) { + if (type != TEP_EVENT_DELIM || strcmp(token, ",") != 0) { do_warning_event(event, "Error: function '%s()' expects %d arguments but event %s only uses %d", func->name, func->nr_args, @@ -2967,7 +2967,7 @@ process_func_handler(struct tep_event_format *event, struct tep_function_handler goto err; } } else { - if (type != EVENT_DELIM || strcmp(token, ")") != 0) { + if (type != TEP_EVENT_DELIM || strcmp(token, ")") != 0) { do_warning_event(event, "Error: function '%s()' only expects %d arguments but event %s has more", func->name, func->nr_args, event->name); @@ -2988,10 +2988,10 @@ process_func_handler(struct tep_event_format *event, struct tep_function_handler err: free_arg(farg); free_token(token); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type +static enum tep_event_type process_function(struct tep_event_format *event, struct print_arg *arg, char *token, char **tok) { @@ -3044,12 +3044,12 @@ process_function(struct tep_event_format *event, struct print_arg *arg, do_warning_event(event, "function %s not defined", token); free_token(token); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type +static enum tep_event_type process_arg_token(struct tep_event_format *event, struct print_arg *arg, - char **tok, enum event_type type) + char **tok, enum tep_event_type type) { char *token; char *atom; @@ -3057,7 +3057,7 @@ process_arg_token(struct tep_event_format *event, struct print_arg *arg, token = *tok; switch (type) { - case EVENT_ITEM: + case TEP_EVENT_ITEM: if (strcmp(token, "REC") == 0) { free_token(token); type = process_entry(event, arg, &token); @@ -3071,7 +3071,7 @@ process_arg_token(struct tep_event_format *event, struct print_arg *arg, * If the next token is a parenthesis, then this * is a function. */ - if (type == EVENT_DELIM && strcmp(token, "(") == 0) { + if (type == TEP_EVENT_DELIM && strcmp(token, "(") == 0) { free_token(token); token = NULL; /* this will free atom. */ @@ -3079,7 +3079,7 @@ process_arg_token(struct tep_event_format *event, struct print_arg *arg, break; } /* atoms can be more than one token long */ - while (type == EVENT_ITEM) { + while (type == TEP_EVENT_ITEM) { char *new_atom; new_atom = realloc(atom, strlen(atom) + strlen(token) + 2); @@ -3087,7 +3087,7 @@ process_arg_token(struct tep_event_format *event, struct print_arg *arg, free(atom); *tok = NULL; free_token(token); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } atom = new_atom; strcat(atom, " "); @@ -3100,19 +3100,19 @@ process_arg_token(struct tep_event_format *event, struct print_arg *arg, arg->atom.atom = atom; break; - case EVENT_DQUOTE: - case EVENT_SQUOTE: + case TEP_EVENT_DQUOTE: + case TEP_EVENT_SQUOTE: arg->type = PRINT_ATOM; arg->atom.atom = token; type = read_token_item(&token); break; - case EVENT_DELIM: + case TEP_EVENT_DELIM: if (strcmp(token, "(") == 0) { free_token(token); type = process_paren(event, arg, &token); break; } - case EVENT_OP: + case TEP_EVENT_OP: /* handle single ops */ arg->type = PRINT_OP; arg->op.op = token; @@ -3120,16 +3120,16 @@ process_arg_token(struct tep_event_format *event, struct print_arg *arg, type = process_op(event, arg, &token); /* On error, the op is freed */ - if (type == EVENT_ERROR) + if (type == TEP_EVENT_ERROR) arg->op.op = NULL; /* return error type if errored */ break; - case EVENT_ERROR ... EVENT_NEWLINE: + case TEP_EVENT_ERROR ... TEP_EVENT_NEWLINE: default: do_warning_event(event, "unexpected type %d", type); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } *tok = token; @@ -3138,13 +3138,13 @@ process_arg_token(struct tep_event_format *event, struct print_arg *arg, static int event_read_print_args(struct tep_event_format *event, struct print_arg **list) { - enum event_type type = EVENT_ERROR; + enum tep_event_type type = TEP_EVENT_ERROR; struct print_arg *arg; char *token; int args = 0; do { - if (type == EVENT_NEWLINE) { + if (type == TEP_EVENT_NEWLINE) { type = read_token_item(&token); continue; } @@ -3158,7 +3158,7 @@ static int event_read_print_args(struct tep_event_format *event, struct print_ar type = process_arg(event, arg, &token); - if (type == EVENT_ERROR) { + if (type == TEP_EVENT_ERROR) { free_token(token); free_arg(arg); return -1; @@ -3167,10 +3167,10 @@ static int event_read_print_args(struct tep_event_format *event, struct print_ar *list = arg; args++; - if (type == EVENT_OP) { + if (type == TEP_EVENT_OP) { type = process_op(event, arg, &token); free_token(token); - if (type == EVENT_ERROR) { + if (type == TEP_EVENT_ERROR) { *list = NULL; free_arg(arg); return -1; @@ -3179,16 +3179,16 @@ static int event_read_print_args(struct tep_event_format *event, struct print_ar continue; } - if (type == EVENT_DELIM && strcmp(token, ",") == 0) { + if (type == TEP_EVENT_DELIM && strcmp(token, ",") == 0) { free_token(token); *list = arg; list = &arg->next; continue; } break; - } while (type != EVENT_NONE); + } while (type != TEP_EVENT_NONE); - if (type != EVENT_NONE && type != EVENT_ERROR) + if (type != TEP_EVENT_NONE && type != TEP_EVENT_ERROR) free_token(token); return args; @@ -3196,20 +3196,20 @@ static int event_read_print_args(struct tep_event_format *event, struct print_ar static int event_read_print(struct tep_event_format *event) { - enum event_type type; + enum tep_event_type type; char *token; int ret; - if (read_expected_item(EVENT_ITEM, "print") < 0) + if (read_expected_item(TEP_EVENT_ITEM, "print") < 0) return -1; - if (read_expected(EVENT_ITEM, "fmt") < 0) + if (read_expected(TEP_EVENT_ITEM, "fmt") < 0) return -1; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return -1; - if (read_expect_type(EVENT_DQUOTE, &token) < 0) + if (read_expect_type(TEP_EVENT_DQUOTE, &token) < 0) goto fail; concat: @@ -3219,11 +3219,11 @@ static int event_read_print(struct tep_event_format *event) /* ok to have no arg */ type = read_token_item(&token); - if (type == EVENT_NONE) + if (type == TEP_EVENT_NONE) return 0; /* Handle concatenation of print lines */ - if (type == EVENT_DQUOTE) { + if (type == TEP_EVENT_DQUOTE) { char *cat; if (asprintf(&cat, "%s%s", event->print_fmt.format, token) < 0) @@ -3235,7 +3235,7 @@ static int event_read_print(struct tep_event_format *event) goto concat; } - if (test_type_token(type, token, EVENT_DELIM, ",")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ",")) goto fail; free_token(token); @@ -5617,7 +5617,7 @@ static int events_system_cmp(const void *a, const void *b) return events_id_cmp(a, b); } -struct tep_event_format **tep_list_events(struct tep_handle *pevent, enum event_sort_type sort_type) +struct tep_event_format **tep_list_events(struct tep_handle *pevent, enum tep_event_sort_type sort_type) { struct tep_event_format **events; int (*sort)(const void *a, const void *b); @@ -5638,20 +5638,20 @@ struct tep_event_format **tep_list_events(struct tep_handle *pevent, enum event_ pevent->sort_events = events; /* the internal events are sorted by id */ - if (sort_type == EVENT_SORT_ID) { + if (sort_type == TEP_EVENT_SORT_ID) { pevent->last_type = sort_type; return events; } } switch (sort_type) { - case EVENT_SORT_ID: + case TEP_EVENT_SORT_ID: sort = events_id_cmp; break; - case EVENT_SORT_NAME: + case TEP_EVENT_SORT_NAME: sort = events_name_cmp; break; - case EVENT_SORT_SYSTEM: + case TEP_EVENT_SORT_SYSTEM: sort = events_system_cmp; break; default: @@ -5834,13 +5834,13 @@ static void parse_header_field(const char *field, save_input_buf_ptr = input_buf_ptr; save_input_buf_siz = input_buf_siz; - if (read_expected(EVENT_ITEM, "field") < 0) + if (read_expected(TEP_EVENT_ITEM, "field") < 0) return; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return; /* type */ - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto fail; free_token(token); @@ -5848,42 +5848,42 @@ static void parse_header_field(const char *field, * If this is not a mandatory field, then test it first. */ if (mandatory) { - if (read_expected(EVENT_ITEM, field) < 0) + if (read_expected(TEP_EVENT_ITEM, field) < 0) return; } else { - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto fail; if (strcmp(token, field) != 0) goto discard; free_token(token); } - if (read_expected(EVENT_OP, ";") < 0) + if (read_expected(TEP_EVENT_OP, ";") < 0) return; - if (read_expected(EVENT_ITEM, "offset") < 0) + if (read_expected(TEP_EVENT_ITEM, "offset") < 0) return; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto fail; *offset = atoi(token); free_token(token); - if (read_expected(EVENT_OP, ";") < 0) + if (read_expected(TEP_EVENT_OP, ";") < 0) return; - if (read_expected(EVENT_ITEM, "size") < 0) + if (read_expected(TEP_EVENT_ITEM, "size") < 0) return; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto fail; *size = atoi(token); free_token(token); - if (read_expected(EVENT_OP, ";") < 0) + if (read_expected(TEP_EVENT_OP, ";") < 0) return; type = read_token(&token); - if (type != EVENT_NEWLINE) { + if (type != TEP_EVENT_NEWLINE) { /* newer versions of the kernel have a "signed" type */ - if (type != EVENT_ITEM) + if (type != TEP_EVENT_ITEM) goto fail; if (strcmp(token, "signed") != 0) @@ -5891,17 +5891,17 @@ static void parse_header_field(const char *field, free_token(token); - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return; - if (read_expect_type(EVENT_ITEM, &token)) + if (read_expect_type(TEP_EVENT_ITEM, &token)) goto fail; free_token(token); - if (read_expected(EVENT_OP, ";") < 0) + if (read_expected(TEP_EVENT_OP, ";") < 0) return; - if (read_expect_type(EVENT_NEWLINE, &token)) + if (read_expect_type(TEP_EVENT_NEWLINE, &token)) goto fail; } fail: diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index f1e1baee8cbd..10aaeda34c6b 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -301,22 +301,22 @@ enum { EVENT_FL_FAILED = 0x80000000 }; -enum event_sort_type { - EVENT_SORT_ID, - EVENT_SORT_NAME, - EVENT_SORT_SYSTEM, +enum tep_event_sort_type { + TEP_EVENT_SORT_ID, + TEP_EVENT_SORT_NAME, + TEP_EVENT_SORT_SYSTEM, }; -enum event_type { - EVENT_ERROR, - EVENT_NONE, - EVENT_SPACE, - EVENT_NEWLINE, - EVENT_OP, - EVENT_DELIM, - EVENT_ITEM, - EVENT_DQUOTE, - EVENT_SQUOTE, +enum tep_event_type { + TEP_EVENT_ERROR, + TEP_EVENT_NONE, + TEP_EVENT_SPACE, + TEP_EVENT_NEWLINE, + TEP_EVENT_OP, + TEP_EVENT_DELIM, + TEP_EVENT_ITEM, + TEP_EVENT_DQUOTE, + TEP_EVENT_SQUOTE, }; typedef unsigned long long (*tep_func_handler)(struct trace_seq *s, @@ -454,7 +454,7 @@ struct tep_handle { struct tep_event_format **events; int nr_events; struct tep_event_format **sort_events; - enum event_sort_type last_type; + enum tep_event_sort_type last_type; int type_offset; int type_size; @@ -685,7 +685,7 @@ void tep_event_info(struct trace_seq *s, struct tep_event_format *event, int tep_strerror(struct tep_handle *pevent, enum tep_errno errnum, char *buf, size_t buflen); -struct tep_event_format **tep_list_events(struct tep_handle *pevent, enum event_sort_type); +struct tep_event_format **tep_list_events(struct tep_handle *pevent, enum tep_event_sort_type); struct tep_format_field **tep_event_common_fields(struct tep_event_format *event); struct tep_format_field **tep_event_fields(struct tep_event_format *event); @@ -756,7 +756,7 @@ void tep_unref(struct tep_handle *pevent); /* access to the internal parser */ void tep_buffer_init(const char *buf, unsigned long long size); -enum event_type tep_read_token(char **tok); +enum tep_event_type tep_read_token(char **tok); void tep_free_token(char *token); int tep_peek_char(void); const char *tep_get_input_buf(void); diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index dcd97acbbc49..153e248de75b 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -61,15 +61,15 @@ static void free_token(char *token) tep_free_token(token); } -static enum event_type read_token(char **tok) +static enum tep_event_type read_token(char **tok) { - enum event_type type; + enum tep_event_type type; char *token = NULL; do { free_token(token); type = tep_read_token(&token); - } while (type == EVENT_NEWLINE || type == EVENT_SPACE); + } while (type == TEP_EVENT_NEWLINE || type == TEP_EVENT_SPACE); /* If token is = or ! check to see if the next char is ~ */ if (token && @@ -79,7 +79,7 @@ static enum event_type read_token(char **tok) *tok = malloc(3); if (*tok == NULL) { free_token(token); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } sprintf(*tok, "%c%c", *token, '~'); free_token(token); @@ -334,7 +334,7 @@ static void free_events(struct event_list *events) static enum tep_errno create_arg_item(struct tep_event_format *event, const char *token, - enum event_type type, struct filter_arg **parg, char *error_str) + enum tep_event_type type, struct filter_arg **parg, char *error_str) { struct tep_format_field *field; struct filter_arg *arg; @@ -347,11 +347,11 @@ create_arg_item(struct tep_event_format *event, const char *token, switch (type) { - case EVENT_SQUOTE: - case EVENT_DQUOTE: + case TEP_EVENT_SQUOTE: + case TEP_EVENT_DQUOTE: arg->type = FILTER_ARG_VALUE; arg->value.type = - type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR; + type == TEP_EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR; arg->value.str = strdup(token); if (!arg->value.str) { free_arg(arg); @@ -359,7 +359,7 @@ create_arg_item(struct tep_event_format *event, const char *token, return TEP_ERRNO__MEM_ALLOC_FAILED; } break; - case EVENT_ITEM: + case TEP_EVENT_ITEM: /* if it is a number, then convert it */ if (isdigit(token[0])) { arg->type = FILTER_ARG_VALUE; @@ -942,7 +942,7 @@ static enum tep_errno process_filter(struct tep_event_format *event, struct filter_arg **parg, char *error_str, int not) { - enum event_type type; + enum tep_event_type type; char *token = NULL; struct filter_arg *current_op = NULL; struct filter_arg *current_exp = NULL; @@ -960,9 +960,9 @@ process_filter(struct tep_event_format *event, struct filter_arg **parg, free(token); type = read_token(&token); switch (type) { - case EVENT_SQUOTE: - case EVENT_DQUOTE: - case EVENT_ITEM: + case TEP_EVENT_SQUOTE: + case TEP_EVENT_DQUOTE: + case TEP_EVENT_ITEM: ret = create_arg_item(event, token, type, &arg, error_str); if (ret < 0) goto fail; @@ -987,7 +987,7 @@ process_filter(struct tep_event_format *event, struct filter_arg **parg, arg = NULL; break; - case EVENT_DELIM: + case TEP_EVENT_DELIM: if (*token == ',') { show_error(error_str, "Illegal token ','"); ret = TEP_ERRNO__ILLEGAL_TOKEN; @@ -1054,7 +1054,7 @@ process_filter(struct tep_event_format *event, struct filter_arg **parg, } break; - case EVENT_OP: + case TEP_EVENT_OP: op_type = process_op(token, &btype, &ctype, &etype); /* All expect a left arg except for NOT */ @@ -1139,14 +1139,14 @@ process_filter(struct tep_event_format *event, struct filter_arg **parg, if (ret < 0) goto fail_syntax; break; - case EVENT_NONE: + case TEP_EVENT_NONE: break; - case EVENT_ERROR: + case TEP_EVENT_ERROR: goto fail_alloc; default: goto fail_syntax; } - } while (type != EVENT_NONE); + } while (type != TEP_EVENT_NONE); if (!current_op && !current_exp) goto fail_syntax; From c1953bcc73115b5f1f7e8a45f124cf9f434494cd Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:48 -0400 Subject: [PATCH 107/155] tools lib traceevent: Add prefix TEP_ to all EVENT_FL_* flags In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This adds prefix TEP_ to all members of nameless enum EVENT_FL_* Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185723.116643250@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 42 +++++++++++++++--------------- tools/lib/traceevent/event-parse.h | 16 ++++++------ 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 1696dd9534bc..a651c3323f2c 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -1382,7 +1382,7 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f * The ftrace fields may still use the "special" name. * Just ignore it. */ - if (event->flags & EVENT_FL_ISFTRACE && + if (event->flags & TEP_EVENT_FL_ISFTRACE && type == TEP_EVENT_ITEM && strcmp(token, "special") == 0) { free_token(token); type = read_token(&token); @@ -1412,7 +1412,7 @@ static int event_read_fields(struct tep_event_format *event, struct tep_format_f * Some of the ftrace fields are broken and have * an illegal "." in them. */ - (event->flags & EVENT_FL_ISFTRACE && + (event->flags & TEP_EVENT_FL_ISFTRACE && type == TEP_EVENT_OP && strcmp(token, ".") == 0)) { if (strcmp(token, "*") == 0) @@ -1963,7 +1963,7 @@ process_op(struct tep_event_format *event, struct print_arg *arg, char **tok) arg->op.right = NULL; if (set_op_prio(arg) == -1) { - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; /* arg->op.op (= token) will be freed at out_free */ arg->op.op = NULL; goto out_free; @@ -2042,7 +2042,7 @@ process_op(struct tep_event_format *event, struct print_arg *arg, char **tok) } else { do_warning_event(event, "unknown op '%s'", token); - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; /* the arg is now the left side */ goto out_free; } @@ -4884,13 +4884,13 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct tep_e int len; int ls; - if (event->flags & EVENT_FL_FAILED) { + if (event->flags & TEP_EVENT_FL_FAILED) { trace_seq_printf(s, "[FAILED TO PARSE]"); tep_print_fields(s, data, size, event); return; } - if (event->flags & EVENT_FL_ISBPRINT) { + if (event->flags & TEP_EVENT_FL_ISBPRINT) { bprint_fmt = get_bprint_format(data, size, event); args = make_bprint_args(bprint_fmt, data, size, event); arg = args; @@ -4945,7 +4945,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct tep_e /* The argument is the length. */ if (!arg) { do_warning_event(event, "no argument match"); - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; goto out_failed; } len_arg = eval_num_arg(data, size, event, arg); @@ -4998,7 +4998,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct tep_e case 'u': if (!arg) { do_warning_event(event, "no argument match"); - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; goto out_failed; } @@ -5008,7 +5008,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct tep_e /* should never happen */ if (len > 31) { do_warning_event(event, "bad format!"); - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; len = 31; } @@ -5074,13 +5074,13 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct tep_e break; default: do_warning_event(event, "bad count (%d)", ls); - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; } break; case 's': if (!arg) { do_warning_event(event, "no matching argument"); - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; goto out_failed; } @@ -5090,7 +5090,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct tep_e /* should never happen */ if (len > 31) { do_warning_event(event, "bad format!"); - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; len = 31; } @@ -5115,7 +5115,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct tep_e trace_seq_putc(s, *ptr); } - if (event->flags & EVENT_FL_FAILED) { + if (event->flags & TEP_EVENT_FL_FAILED) { out_failed: trace_seq_printf(s, "[FAILED TO PARSE]"); } @@ -5391,11 +5391,11 @@ void tep_event_info(struct trace_seq *s, struct tep_event_format *event, { int print_pretty = 1; - if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW)) + if (event->pevent->print_raw || (event->flags & TEP_EVENT_FL_PRINTRAW)) tep_print_fields(s, record->data, record->size, event); else { - if (event->handler && !(event->flags & EVENT_FL_NOHANDLE)) + if (event->handler && !(event->flags & TEP_EVENT_FL_NOHANDLE)) print_pretty = event->handler(s, record, event, event->context); @@ -6043,10 +6043,10 @@ enum tep_errno __tep_parse_format(struct tep_event_format **eventp, } if (strcmp(sys, "ftrace") == 0) { - event->flags |= EVENT_FL_ISFTRACE; + event->flags |= TEP_EVENT_FL_ISFTRACE; if (strcmp(event->name, "bprint") == 0) - event->flags |= EVENT_FL_ISBPRINT; + event->flags |= TEP_EVENT_FL_ISBPRINT; } event->id = event_read_id(); @@ -6089,7 +6089,7 @@ enum tep_errno __tep_parse_format(struct tep_event_format **eventp, goto event_parse_failed; } - if (!ret && (event->flags & EVENT_FL_ISFTRACE)) { + if (!ret && (event->flags & TEP_EVENT_FL_ISFTRACE)) { struct tep_format_field *field; struct print_arg *arg, **list; @@ -6098,13 +6098,13 @@ enum tep_errno __tep_parse_format(struct tep_event_format **eventp, for (field = event->format.fields; field; field = field->next) { arg = alloc_arg(); if (!arg) { - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; return TEP_ERRNO__OLD_FTRACE_ARG_FAILED; } arg->type = PRINT_FIELD; arg->field.name = strdup(field->name); if (!arg->field.name) { - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; free_arg(arg); return TEP_ERRNO__OLD_FTRACE_ARG_FAILED; } @@ -6118,7 +6118,7 @@ enum tep_errno __tep_parse_format(struct tep_event_format **eventp, return 0; event_parse_failed: - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; return ret; event_alloc_failed: diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 10aaeda34c6b..b7798d91607e 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -290,15 +290,15 @@ struct tep_event_format { }; enum { - EVENT_FL_ISFTRACE = 0x01, - EVENT_FL_ISPRINT = 0x02, - EVENT_FL_ISBPRINT = 0x04, - EVENT_FL_ISFUNCENT = 0x10, - EVENT_FL_ISFUNCRET = 0x20, - EVENT_FL_NOHANDLE = 0x40, - EVENT_FL_PRINTRAW = 0x80, + TEP_EVENT_FL_ISFTRACE = 0x01, + TEP_EVENT_FL_ISPRINT = 0x02, + TEP_EVENT_FL_ISBPRINT = 0x04, + TEP_EVENT_FL_ISFUNCENT = 0x10, + TEP_EVENT_FL_ISFUNCRET = 0x20, + TEP_EVENT_FL_NOHANDLE = 0x40, + TEP_EVENT_FL_PRINTRAW = 0x80, - EVENT_FL_FAILED = 0x80000000 + TEP_EVENT_FL_FAILED = 0x80000000 }; enum tep_event_sort_type { From 5647f94b90f6681bcc6f37abeb3bc3d1850b12cb Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:49 -0400 Subject: [PATCH 108/155] tools lib traceevent, perf tools: Add prefix tep_ to all print_* structures In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This adds prefix tep_ to all print_* structures Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185723.381753268@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 144 +++++++++--------- tools/lib/traceevent/event-parse.h | 98 ++++++------ .../util/scripting-engines/trace-event-perl.c | 6 +- .../scripting-engines/trace-event-python.c | 4 +- 4 files changed, 126 insertions(+), 126 deletions(-) diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index a651c3323f2c..3beab91afded 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -95,7 +95,7 @@ struct tep_function_handler { static unsigned long long process_defined_func(struct trace_seq *s, void *data, int size, - struct tep_event_format *event, struct print_arg *arg); + struct tep_event_format *event, struct tep_print_arg *arg); static void free_func_handle(struct tep_function_handler *func); @@ -118,9 +118,9 @@ void breakpoint(void) x++; } -struct print_arg *alloc_arg(void) +struct tep_print_arg *alloc_arg(void) { - return calloc(1, sizeof(struct print_arg)); + return calloc(1, sizeof(struct tep_print_arg)); } struct cmdline { @@ -781,9 +781,9 @@ static int event_item_type(enum tep_event_type type) } } -static void free_flag_sym(struct print_flag_sym *fsym) +static void free_flag_sym(struct tep_print_flag_sym *fsym) { - struct print_flag_sym *next; + struct tep_print_flag_sym *next; while (fsym) { next = fsym->next; @@ -794,9 +794,9 @@ static void free_flag_sym(struct print_flag_sym *fsym) } } -static void free_arg(struct print_arg *arg) +static void free_arg(struct tep_print_arg *arg) { - struct print_arg *farg; + struct tep_print_arg *farg; if (!arg) return; @@ -1674,11 +1674,11 @@ static int event_read_format(struct tep_event_format *event) } static enum tep_event_type -process_arg_token(struct tep_event_format *event, struct print_arg *arg, +process_arg_token(struct tep_event_format *event, struct tep_print_arg *arg, char **tok, enum tep_event_type type); static enum tep_event_type -process_arg(struct tep_event_format *event, struct print_arg *arg, char **tok) +process_arg(struct tep_event_format *event, struct tep_print_arg *arg, char **tok) { enum tep_event_type type; char *token; @@ -1690,14 +1690,14 @@ process_arg(struct tep_event_format *event, struct print_arg *arg, char **tok) } static enum tep_event_type -process_op(struct tep_event_format *event, struct print_arg *arg, char **tok); +process_op(struct tep_event_format *event, struct tep_print_arg *arg, char **tok); /* * For __print_symbolic() and __print_flags, we need to completely * evaluate the first argument, which defines what to print next. */ static enum tep_event_type -process_field_arg(struct tep_event_format *event, struct print_arg *arg, char **tok) +process_field_arg(struct tep_event_format *event, struct tep_print_arg *arg, char **tok) { enum tep_event_type type; @@ -1711,9 +1711,9 @@ process_field_arg(struct tep_event_format *event, struct print_arg *arg, char ** } static enum tep_event_type -process_cond(struct tep_event_format *event, struct print_arg *top, char **tok) +process_cond(struct tep_event_format *event, struct tep_print_arg *top, char **tok) { - struct print_arg *arg, *left, *right; + struct tep_print_arg *arg, *left, *right; enum tep_event_type type; char *token = NULL; @@ -1767,9 +1767,9 @@ out_free: } static enum tep_event_type -process_array(struct tep_event_format *event, struct print_arg *top, char **tok) +process_array(struct tep_event_format *event, struct tep_print_arg *top, char **tok) { - struct print_arg *arg; + struct tep_print_arg *arg; enum tep_event_type type; char *token = NULL; @@ -1855,7 +1855,7 @@ static int get_op_prio(char *op) } } -static int set_op_prio(struct print_arg *arg) +static int set_op_prio(struct tep_print_arg *arg) { /* single ops are the greatest */ @@ -1869,9 +1869,9 @@ static int set_op_prio(struct print_arg *arg) /* Note, *tok does not get freed, but will most likely be saved */ static enum tep_event_type -process_op(struct tep_event_format *event, struct print_arg *arg, char **tok) +process_op(struct tep_event_format *event, struct tep_print_arg *arg, char **tok) { - struct print_arg *left, *right = NULL; + struct tep_print_arg *left, *right = NULL; enum tep_event_type type; char *token; @@ -2009,7 +2009,7 @@ process_op(struct tep_event_format *event, struct print_arg *arg, char **tok) if (right->type == PRINT_OP && get_op_prio(arg->op.op) < get_op_prio(right->op.op)) { - struct print_arg tmp; + struct tep_print_arg tmp; /* rotate ops according to the priority */ arg->op.right = right->op.left; @@ -2070,7 +2070,7 @@ out_free: } static enum tep_event_type -process_entry(struct tep_event_format *event __maybe_unused, struct print_arg *arg, +process_entry(struct tep_event_format *event __maybe_unused, struct tep_print_arg *arg, char **tok) { enum tep_event_type type; @@ -2110,9 +2110,9 @@ process_entry(struct tep_event_format *event __maybe_unused, struct print_arg *a } static int alloc_and_process_delim(struct tep_event_format *event, char *next_token, - struct print_arg **print_arg) + struct tep_print_arg **print_arg) { - struct print_arg *field; + struct tep_print_arg *field; enum tep_event_type type; char *token; int ret = 0; @@ -2141,7 +2141,7 @@ out_free_token: return ret; } -static char *arg_eval (struct print_arg *arg); +static char *arg_eval (struct tep_print_arg *arg); static unsigned long long eval_type_str(unsigned long long val, const char *type, int pointer) @@ -2238,7 +2238,7 @@ eval_type_str(unsigned long long val, const char *type, int pointer) * Try to figure out the type. */ static unsigned long long -eval_type(unsigned long long val, struct print_arg *arg, int pointer) +eval_type(unsigned long long val, struct tep_print_arg *arg, int pointer) { if (arg->type != PRINT_TYPE) { do_warning("expected type argument"); @@ -2248,7 +2248,7 @@ eval_type(unsigned long long val, struct print_arg *arg, int pointer) return eval_type_str(val, arg->typecast.type, pointer); } -static int arg_num_eval(struct print_arg *arg, long long *val) +static int arg_num_eval(struct tep_print_arg *arg, long long *val) { long long left, right; int ret = 1; @@ -2414,7 +2414,7 @@ static int arg_num_eval(struct print_arg *arg, long long *val) return ret; } -static char *arg_eval (struct print_arg *arg) +static char *arg_eval (struct tep_print_arg *arg) { long long val; static char buf[20]; @@ -2444,11 +2444,11 @@ static char *arg_eval (struct print_arg *arg) } static enum tep_event_type -process_fields(struct tep_event_format *event, struct print_flag_sym **list, char **tok) +process_fields(struct tep_event_format *event, struct tep_print_flag_sym **list, char **tok) { enum tep_event_type type; - struct print_arg *arg = NULL; - struct print_flag_sym *field; + struct tep_print_arg *arg = NULL; + struct tep_print_flag_sym *field; char *token = *tok; char *value; @@ -2525,9 +2525,9 @@ out_free: } static enum tep_event_type -process_flags(struct tep_event_format *event, struct print_arg *arg, char **tok) +process_flags(struct tep_event_format *event, struct tep_print_arg *arg, char **tok) { - struct print_arg *field; + struct tep_print_arg *field; enum tep_event_type type; char *token = NULL; @@ -2578,9 +2578,9 @@ out_free: } static enum tep_event_type -process_symbols(struct tep_event_format *event, struct print_arg *arg, char **tok) +process_symbols(struct tep_event_format *event, struct tep_print_arg *arg, char **tok) { - struct print_arg *field; + struct tep_print_arg *field; enum tep_event_type type; char *token = NULL; @@ -2617,7 +2617,7 @@ out_free: } static enum tep_event_type -process_hex_common(struct tep_event_format *event, struct print_arg *arg, +process_hex_common(struct tep_event_format *event, struct tep_print_arg *arg, char **tok, enum print_arg_type type) { memset(arg, 0, sizeof(*arg)); @@ -2640,20 +2640,20 @@ out: } static enum tep_event_type -process_hex(struct tep_event_format *event, struct print_arg *arg, char **tok) +process_hex(struct tep_event_format *event, struct tep_print_arg *arg, char **tok) { return process_hex_common(event, arg, tok, PRINT_HEX); } static enum tep_event_type -process_hex_str(struct tep_event_format *event, struct print_arg *arg, +process_hex_str(struct tep_event_format *event, struct tep_print_arg *arg, char **tok) { return process_hex_common(event, arg, tok, PRINT_HEX_STR); } static enum tep_event_type -process_int_array(struct tep_event_format *event, struct print_arg *arg, char **tok) +process_int_array(struct tep_event_format *event, struct tep_print_arg *arg, char **tok) { memset(arg, 0, sizeof(*arg)); arg->type = PRINT_INT_ARRAY; @@ -2681,7 +2681,7 @@ out: } static enum tep_event_type -process_dynamic_array(struct tep_event_format *event, struct print_arg *arg, char **tok) +process_dynamic_array(struct tep_event_format *event, struct tep_print_arg *arg, char **tok) { struct tep_format_field *field; enum tep_event_type type; @@ -2745,7 +2745,7 @@ process_dynamic_array(struct tep_event_format *event, struct print_arg *arg, cha } static enum tep_event_type -process_dynamic_array_len(struct tep_event_format *event, struct print_arg *arg, +process_dynamic_array_len(struct tep_event_format *event, struct tep_print_arg *arg, char **tok) { struct tep_format_field *field; @@ -2781,9 +2781,9 @@ process_dynamic_array_len(struct tep_event_format *event, struct print_arg *arg, } static enum tep_event_type -process_paren(struct tep_event_format *event, struct print_arg *arg, char **tok) +process_paren(struct tep_event_format *event, struct tep_print_arg *arg, char **tok) { - struct print_arg *item_arg; + struct tep_print_arg *item_arg; enum tep_event_type type; char *token; @@ -2844,7 +2844,7 @@ process_paren(struct tep_event_format *event, struct print_arg *arg, char **tok) static enum tep_event_type -process_str(struct tep_event_format *event __maybe_unused, struct print_arg *arg, +process_str(struct tep_event_format *event __maybe_unused, struct tep_print_arg *arg, char **tok) { enum tep_event_type type; @@ -2873,7 +2873,7 @@ process_str(struct tep_event_format *event __maybe_unused, struct print_arg *arg } static enum tep_event_type -process_bitmask(struct tep_event_format *event __maybe_unused, struct print_arg *arg, +process_bitmask(struct tep_event_format *event __maybe_unused, struct tep_print_arg *arg, char **tok) { enum tep_event_type type; @@ -2935,10 +2935,10 @@ static void remove_func_handler(struct tep_handle *pevent, char *func_name) static enum tep_event_type process_func_handler(struct tep_event_format *event, struct tep_function_handler *func, - struct print_arg *arg, char **tok) + struct tep_print_arg *arg, char **tok) { - struct print_arg **next_arg; - struct print_arg *farg; + struct tep_print_arg **next_arg; + struct tep_print_arg *farg; enum tep_event_type type; char *token; int i; @@ -2992,7 +2992,7 @@ err: } static enum tep_event_type -process_function(struct tep_event_format *event, struct print_arg *arg, +process_function(struct tep_event_format *event, struct tep_print_arg *arg, char *token, char **tok) { struct tep_function_handler *func; @@ -3048,7 +3048,7 @@ process_function(struct tep_event_format *event, struct print_arg *arg, } static enum tep_event_type -process_arg_token(struct tep_event_format *event, struct print_arg *arg, +process_arg_token(struct tep_event_format *event, struct tep_print_arg *arg, char **tok, enum tep_event_type type) { char *token; @@ -3136,10 +3136,10 @@ process_arg_token(struct tep_event_format *event, struct print_arg *arg, return type; } -static int event_read_print_args(struct tep_event_format *event, struct print_arg **list) +static int event_read_print_args(struct tep_event_format *event, struct tep_print_arg **list) { enum tep_event_type type = TEP_EVENT_ERROR; - struct print_arg *arg; + struct tep_print_arg *arg; char *token; int args = 0; @@ -3522,13 +3522,13 @@ tep_find_event_by_name(struct tep_handle *pevent, } static unsigned long long -eval_num_arg(void *data, int size, struct tep_event_format *event, struct print_arg *arg) +eval_num_arg(void *data, int size, struct tep_event_format *event, struct tep_print_arg *arg) { struct tep_handle *pevent = event->pevent; unsigned long long val = 0; unsigned long long left, right; - struct print_arg *typearg = NULL; - struct print_arg *larg; + struct tep_print_arg *typearg = NULL; + struct tep_print_arg *larg; unsigned long offset; unsigned int field_size; @@ -3863,10 +3863,10 @@ static void print_bitmask_to_seq(struct tep_handle *pevent, static void print_str_arg(struct trace_seq *s, void *data, int size, struct tep_event_format *event, const char *format, - int len_arg, struct print_arg *arg) + int len_arg, struct tep_print_arg *arg) { struct tep_handle *pevent = event->pevent; - struct print_flag_sym *flag; + struct tep_print_flag_sym *flag; struct tep_format_field *field; struct printk_map *printk; long long val, fval; @@ -4117,13 +4117,13 @@ out_warning_field: static unsigned long long process_defined_func(struct trace_seq *s, void *data, int size, - struct tep_event_format *event, struct print_arg *arg) + struct tep_event_format *event, struct tep_print_arg *arg) { struct tep_function_handler *func_handle = arg->func.func; struct func_params *param; unsigned long long *args; unsigned long long ret; - struct print_arg *farg; + struct tep_print_arg *farg; struct trace_seq str; struct save_str { struct save_str *next; @@ -4200,9 +4200,9 @@ out_free: return ret; } -static void free_args(struct print_arg *args) +static void free_args(struct tep_print_arg *args) { - struct print_arg *next; + struct tep_print_arg *next; while (args) { next = args->next; @@ -4212,11 +4212,11 @@ static void free_args(struct print_arg *args) } } -static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct tep_event_format *event) +static struct tep_print_arg *make_bprint_args(char *fmt, void *data, int size, struct tep_event_format *event) { struct tep_handle *pevent = event->pevent; struct tep_format_field *field, *ip_field; - struct print_arg *args, *arg, **next; + struct tep_print_arg *args, *arg, **next; unsigned long long ip, val; char *ptr; void *bptr; @@ -4424,7 +4424,7 @@ get_bprint_format(void *data, int size __maybe_unused, } static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size, - struct tep_event_format *event, struct print_arg *arg) + struct tep_event_format *event, struct tep_print_arg *arg) { unsigned char *buf; const char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"; @@ -4578,7 +4578,7 @@ static void print_ip6_addr(struct trace_seq *s, char i, unsigned char *buf) */ static int print_ipv4_arg(struct trace_seq *s, const char *ptr, char i, void *data, int size, struct tep_event_format *event, - struct print_arg *arg) + struct tep_print_arg *arg) { unsigned char *buf; @@ -4615,7 +4615,7 @@ static int print_ipv4_arg(struct trace_seq *s, const char *ptr, char i, static int print_ipv6_arg(struct trace_seq *s, const char *ptr, char i, void *data, int size, struct tep_event_format *event, - struct print_arg *arg) + struct tep_print_arg *arg) { char have_c = 0; unsigned char *buf; @@ -4665,7 +4665,7 @@ static int print_ipv6_arg(struct trace_seq *s, const char *ptr, char i, static int print_ipsa_arg(struct trace_seq *s, const char *ptr, char i, void *data, int size, struct tep_event_format *event, - struct print_arg *arg) + struct tep_print_arg *arg) { char have_c = 0, have_p = 0; unsigned char *buf; @@ -4747,7 +4747,7 @@ static int print_ipsa_arg(struct trace_seq *s, const char *ptr, char i, static int print_ip_arg(struct trace_seq *s, const char *ptr, void *data, int size, struct tep_event_format *event, - struct print_arg *arg) + struct tep_print_arg *arg) { char i = *ptr; /* 'i' or 'I' */ char ver; @@ -4868,9 +4868,9 @@ void tep_print_fields(struct trace_seq *s, void *data, static void pretty_print(struct trace_seq *s, void *data, int size, struct tep_event_format *event) { struct tep_handle *pevent = event->pevent; - struct print_fmt *print_fmt = &event->print_fmt; - struct print_arg *arg = print_fmt->args; - struct print_arg *args = NULL; + struct tep_print_fmt *print_fmt = &event->print_fmt; + struct tep_print_arg *arg = print_fmt->args; + struct tep_print_arg *args = NULL; const char *ptr = print_fmt->format; unsigned long long val; struct func_map *func; @@ -5723,7 +5723,7 @@ struct tep_format_field **tep_event_fields(struct tep_event_format *event) event->format.fields); } -static void print_fields(struct trace_seq *s, struct print_flag_sym *field) +static void print_fields(struct trace_seq *s, struct tep_print_flag_sym *field) { trace_seq_printf(s, "{ %s, %s }", field->value, field->str); if (field->next) { @@ -5733,7 +5733,7 @@ static void print_fields(struct trace_seq *s, struct print_flag_sym *field) } /* for debugging */ -static void print_args(struct print_arg *args) +static void print_args(struct tep_print_arg *args) { int print_paren = 1; struct trace_seq s; @@ -6091,7 +6091,7 @@ enum tep_errno __tep_parse_format(struct tep_event_format **eventp, if (!ret && (event->flags & TEP_EVENT_FL_ISFTRACE)) { struct tep_format_field *field; - struct print_arg *arg, **list; + struct tep_print_arg *arg, **list; /* old ftrace had no args */ list = &event->print_fmt.args; diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index b7798d91607e..21923a11c9c0 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -161,77 +161,77 @@ struct tep_format { struct tep_format_field *fields; }; -struct print_arg_atom { +struct tep_print_arg_atom { char *atom; }; -struct print_arg_string { +struct tep_print_arg_string { char *string; int offset; }; -struct print_arg_bitmask { +struct tep_print_arg_bitmask { char *bitmask; int offset; }; -struct print_arg_field { +struct tep_print_arg_field { char *name; struct tep_format_field *field; }; -struct print_flag_sym { - struct print_flag_sym *next; - char *value; - char *str; +struct tep_print_flag_sym { + struct tep_print_flag_sym *next; + char *value; + char *str; }; -struct print_arg_typecast { +struct tep_print_arg_typecast { char *type; - struct print_arg *item; + struct tep_print_arg *item; }; -struct print_arg_flags { - struct print_arg *field; - char *delim; - struct print_flag_sym *flags; +struct tep_print_arg_flags { + struct tep_print_arg *field; + char *delim; + struct tep_print_flag_sym *flags; }; -struct print_arg_symbol { - struct print_arg *field; - struct print_flag_sym *symbols; +struct tep_print_arg_symbol { + struct tep_print_arg *field; + struct tep_print_flag_sym *symbols; }; -struct print_arg_hex { - struct print_arg *field; - struct print_arg *size; +struct tep_print_arg_hex { + struct tep_print_arg *field; + struct tep_print_arg *size; }; -struct print_arg_int_array { - struct print_arg *field; - struct print_arg *count; - struct print_arg *el_size; +struct tep_print_arg_int_array { + struct tep_print_arg *field; + struct tep_print_arg *count; + struct tep_print_arg *el_size; }; -struct print_arg_dynarray { +struct tep_print_arg_dynarray { struct tep_format_field *field; - struct print_arg *index; + struct tep_print_arg *index; }; -struct print_arg; +struct tep_print_arg; -struct print_arg_op { +struct tep_print_arg_op { char *op; int prio; - struct print_arg *left; - struct print_arg *right; + struct tep_print_arg *left; + struct tep_print_arg *right; }; struct tep_function_handler; -struct print_arg_func { +struct tep_print_arg_func { struct tep_function_handler *func; - struct print_arg *args; + struct tep_print_arg *args; }; enum print_arg_type { @@ -253,28 +253,28 @@ enum print_arg_type { PRINT_HEX_STR, }; -struct print_arg { - struct print_arg *next; +struct tep_print_arg { + struct tep_print_arg *next; enum print_arg_type type; union { - struct print_arg_atom atom; - struct print_arg_field field; - struct print_arg_typecast typecast; - struct print_arg_flags flags; - struct print_arg_symbol symbol; - struct print_arg_hex hex; - struct print_arg_int_array int_array; - struct print_arg_func func; - struct print_arg_string string; - struct print_arg_bitmask bitmask; - struct print_arg_op op; - struct print_arg_dynarray dynarray; + struct tep_print_arg_atom atom; + struct tep_print_arg_field field; + struct tep_print_arg_typecast typecast; + struct tep_print_arg_flags flags; + struct tep_print_arg_symbol symbol; + struct tep_print_arg_hex hex; + struct tep_print_arg_int_array int_array; + struct tep_print_arg_func func; + struct tep_print_arg_string string; + struct tep_print_arg_bitmask bitmask; + struct tep_print_arg_op op; + struct tep_print_arg_dynarray dynarray; }; }; -struct print_fmt { +struct tep_print_fmt { char *format; - struct print_arg *args; + struct tep_print_arg *args; }; struct tep_event_format { @@ -283,7 +283,7 @@ struct tep_event_format { int id; int flags; struct tep_format format; - struct print_fmt print_fmt; + struct tep_print_fmt print_fmt; char *system; tep_event_handler_func handler; void *context; diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 5d6a55183ad6..481a1ecb1eaf 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -99,7 +99,7 @@ static void define_symbolic_value(const char *ev_name, LEAVE; } -static void define_symbolic_values(struct print_flag_sym *field, +static void define_symbolic_values(struct tep_print_flag_sym *field, const char *ev_name, const char *field_name) { @@ -157,7 +157,7 @@ static void define_flag_value(const char *ev_name, LEAVE; } -static void define_flag_values(struct print_flag_sym *field, +static void define_flag_values(struct tep_print_flag_sym *field, const char *ev_name, const char *field_name) { @@ -191,7 +191,7 @@ static void define_flag_field(const char *ev_name, static void define_event_symbols(struct tep_event_format *event, const char *ev_name, - struct print_arg *args) + struct tep_print_arg *args) { if (args == NULL) return; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index ba191def1ea9..35dc5f3b581b 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -224,7 +224,7 @@ static void define_value(enum print_arg_type field_type, } static void define_values(enum print_arg_type field_type, - struct print_flag_sym *field, + struct tep_print_flag_sym *field, const char *ev_name, const char *field_name) { @@ -266,7 +266,7 @@ static void define_field(enum print_arg_type field_type, static void define_event_symbols(struct tep_event_format *event, const char *ev_name, - struct print_arg *args) + struct tep_print_arg *args) { if (args == NULL) return; From 1e97216f20330fb001f57d0f6f48e76c060bfd16 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:50 -0400 Subject: [PATCH 109/155] tools lib traceevent, perf tools: Rename enum print_arg_type to enum tep_print_arg_type In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This renames enum print_arg_type to enum tep_print_arg_type and add prefix TEP_ to all its members. Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185723.533960748@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 248 +++++++++--------- tools/lib/traceevent/event-parse.h | 36 +-- .../util/scripting-engines/trace-event-perl.c | 32 +-- .../scripting-engines/trace-event-python.c | 56 ++-- 4 files changed, 186 insertions(+), 186 deletions(-) diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 3beab91afded..055bee7b738a 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -802,52 +802,52 @@ static void free_arg(struct tep_print_arg *arg) return; switch (arg->type) { - case PRINT_ATOM: + case TEP_PRINT_ATOM: free(arg->atom.atom); break; - case PRINT_FIELD: + case TEP_PRINT_FIELD: free(arg->field.name); break; - case PRINT_FLAGS: + case TEP_PRINT_FLAGS: free_arg(arg->flags.field); free(arg->flags.delim); free_flag_sym(arg->flags.flags); break; - case PRINT_SYMBOL: + case TEP_PRINT_SYMBOL: free_arg(arg->symbol.field); free_flag_sym(arg->symbol.symbols); break; - case PRINT_HEX: - case PRINT_HEX_STR: + case TEP_PRINT_HEX: + case TEP_PRINT_HEX_STR: free_arg(arg->hex.field); free_arg(arg->hex.size); break; - case PRINT_INT_ARRAY: + case TEP_PRINT_INT_ARRAY: free_arg(arg->int_array.field); free_arg(arg->int_array.count); free_arg(arg->int_array.el_size); break; - case PRINT_TYPE: + case TEP_PRINT_TYPE: free(arg->typecast.type); free_arg(arg->typecast.item); break; - case PRINT_STRING: - case PRINT_BSTRING: + case TEP_PRINT_STRING: + case TEP_PRINT_BSTRING: free(arg->string.string); break; - case PRINT_BITMASK: + case TEP_PRINT_BITMASK: free(arg->bitmask.bitmask); break; - case PRINT_DYNAMIC_ARRAY: - case PRINT_DYNAMIC_ARRAY_LEN: + case TEP_PRINT_DYNAMIC_ARRAY: + case TEP_PRINT_DYNAMIC_ARRAY_LEN: free(arg->dynarray.index); break; - case PRINT_OP: + case TEP_PRINT_OP: free(arg->op.op); free_arg(arg->op.left); free_arg(arg->op.right); break; - case PRINT_FUNC: + case TEP_PRINT_FUNC: while (arg->func.args) { farg = arg->func.args; arg->func.args = farg->next; @@ -855,7 +855,7 @@ static void free_arg(struct tep_print_arg *arg) } break; - case PRINT_NULL: + case TEP_PRINT_NULL: default: break; } @@ -1729,7 +1729,7 @@ process_cond(struct tep_event_format *event, struct tep_print_arg *top, char **t goto out_free; } - arg->type = PRINT_OP; + arg->type = TEP_PRINT_OP; arg->op.left = left; arg->op.right = right; @@ -1859,7 +1859,7 @@ static int set_op_prio(struct tep_print_arg *arg) { /* single ops are the greatest */ - if (!arg->op.left || arg->op.left->type == PRINT_NULL) + if (!arg->op.left || arg->op.left->type == TEP_PRINT_NULL) arg->op.prio = 0; else arg->op.prio = get_op_prio(arg->op.op); @@ -1878,7 +1878,7 @@ process_op(struct tep_event_format *event, struct tep_print_arg *arg, char **tok /* the op is passed in via tok */ token = *tok; - if (arg->type == PRINT_OP && !arg->op.left) { + if (arg->type == TEP_PRINT_OP && !arg->op.left) { /* handle single op */ if (token[1]) { do_warning_event(event, "bad op token %s", token); @@ -1901,7 +1901,7 @@ process_op(struct tep_event_format *event, struct tep_print_arg *arg, char **tok if (!left) goto out_warn_free; - left->type = PRINT_NULL; + left->type = TEP_PRINT_NULL; arg->op.left = left; right = alloc_arg(); @@ -1923,7 +1923,7 @@ process_op(struct tep_event_format *event, struct tep_print_arg *arg, char **tok /* copy the top arg to the left */ *left = *arg; - arg->type = PRINT_OP; + arg->type = TEP_PRINT_OP; arg->op.op = token; arg->op.left = left; arg->op.prio = 0; @@ -1957,7 +1957,7 @@ process_op(struct tep_event_format *event, struct tep_print_arg *arg, char **tok /* copy the top arg to the left */ *left = *arg; - arg->type = PRINT_OP; + arg->type = TEP_PRINT_OP; arg->op.op = token; arg->op.left = left; arg->op.right = NULL; @@ -1977,7 +1977,7 @@ process_op(struct tep_event_format *event, struct tep_print_arg *arg, char **tok type == TEP_EVENT_DELIM && (strcmp(token, ")") == 0)) { char *new_atom; - if (left->type != PRINT_ATOM) { + if (left->type != TEP_PRINT_ATOM) { do_warning_event(event, "bad pointer type"); goto out_free; } @@ -2007,7 +2007,7 @@ process_op(struct tep_event_format *event, struct tep_print_arg *arg, char **tok goto out_free; } - if (right->type == PRINT_OP && + if (right->type == TEP_PRINT_OP && get_op_prio(arg->op.op) < get_op_prio(right->op.op)) { struct tep_print_arg tmp; @@ -2031,7 +2031,7 @@ process_op(struct tep_event_format *event, struct tep_print_arg *arg, char **tok *left = *arg; - arg->type = PRINT_OP; + arg->type = TEP_PRINT_OP; arg->op.op = token; arg->op.left = left; @@ -2084,7 +2084,7 @@ process_entry(struct tep_event_format *event __maybe_unused, struct tep_print_ar goto out_free; field = token; - arg->type = PRINT_FIELD; + arg->type = TEP_PRINT_FIELD; arg->field.name = field; if (is_flag_field) { @@ -2240,7 +2240,7 @@ eval_type_str(unsigned long long val, const char *type, int pointer) static unsigned long long eval_type(unsigned long long val, struct tep_print_arg *arg, int pointer) { - if (arg->type != PRINT_TYPE) { + if (arg->type != TEP_PRINT_TYPE) { do_warning("expected type argument"); return 0; } @@ -2254,16 +2254,16 @@ static int arg_num_eval(struct tep_print_arg *arg, long long *val) int ret = 1; switch (arg->type) { - case PRINT_ATOM: + case TEP_PRINT_ATOM: *val = strtoll(arg->atom.atom, NULL, 0); break; - case PRINT_TYPE: + case TEP_PRINT_TYPE: ret = arg_num_eval(arg->typecast.item, val); if (!ret) break; *val = eval_type(*val, arg, 0); break; - case PRINT_OP: + case TEP_PRINT_OP: switch (arg->op.op[0]) { case '|': ret = arg_num_eval(arg->op.left, &left); @@ -2366,7 +2366,7 @@ static int arg_num_eval(struct tep_print_arg *arg, long long *val) break; case '-': /* check for negative */ - if (arg->op.left->type == PRINT_NULL) + if (arg->op.left->type == TEP_PRINT_NULL) left = 0; else ret = arg_num_eval(arg->op.left, &left); @@ -2378,7 +2378,7 @@ static int arg_num_eval(struct tep_print_arg *arg, long long *val) *val = left - right; break; case '+': - if (arg->op.left->type == PRINT_NULL) + if (arg->op.left->type == TEP_PRINT_NULL) left = 0; else ret = arg_num_eval(arg->op.left, &left); @@ -2401,11 +2401,11 @@ static int arg_num_eval(struct tep_print_arg *arg, long long *val) } break; - case PRINT_NULL: - case PRINT_FIELD ... PRINT_SYMBOL: - case PRINT_STRING: - case PRINT_BSTRING: - case PRINT_BITMASK: + case TEP_PRINT_NULL: + case TEP_PRINT_FIELD ... TEP_PRINT_SYMBOL: + case TEP_PRINT_STRING: + case TEP_PRINT_BSTRING: + case TEP_PRINT_BITMASK: default: do_warning("invalid eval type %d", arg->type); ret = 0; @@ -2420,21 +2420,21 @@ static char *arg_eval (struct tep_print_arg *arg) static char buf[20]; switch (arg->type) { - case PRINT_ATOM: + case TEP_PRINT_ATOM: return arg->atom.atom; - case PRINT_TYPE: + case TEP_PRINT_TYPE: return arg_eval(arg->typecast.item); - case PRINT_OP: + case TEP_PRINT_OP: if (!arg_num_eval(arg, &val)) break; sprintf(buf, "%lld", val); return buf; - case PRINT_NULL: - case PRINT_FIELD ... PRINT_SYMBOL: - case PRINT_STRING: - case PRINT_BSTRING: - case PRINT_BITMASK: + case TEP_PRINT_NULL: + case TEP_PRINT_FIELD ... TEP_PRINT_SYMBOL: + case TEP_PRINT_STRING: + case TEP_PRINT_BSTRING: + case TEP_PRINT_BITMASK: default: do_warning("invalid eval type %d", arg->type); break; @@ -2532,7 +2532,7 @@ process_flags(struct tep_event_format *event, struct tep_print_arg *arg, char ** char *token = NULL; memset(arg, 0, sizeof(*arg)); - arg->type = PRINT_FLAGS; + arg->type = TEP_PRINT_FLAGS; field = alloc_arg(); if (!field) { @@ -2585,7 +2585,7 @@ process_symbols(struct tep_event_format *event, struct tep_print_arg *arg, char char *token = NULL; memset(arg, 0, sizeof(*arg)); - arg->type = PRINT_SYMBOL; + arg->type = TEP_PRINT_SYMBOL; field = alloc_arg(); if (!field) { @@ -2618,7 +2618,7 @@ out_free: static enum tep_event_type process_hex_common(struct tep_event_format *event, struct tep_print_arg *arg, - char **tok, enum print_arg_type type) + char **tok, enum tep_print_arg_type type) { memset(arg, 0, sizeof(*arg)); arg->type = type; @@ -2642,21 +2642,21 @@ out: static enum tep_event_type process_hex(struct tep_event_format *event, struct tep_print_arg *arg, char **tok) { - return process_hex_common(event, arg, tok, PRINT_HEX); + return process_hex_common(event, arg, tok, TEP_PRINT_HEX); } static enum tep_event_type process_hex_str(struct tep_event_format *event, struct tep_print_arg *arg, char **tok) { - return process_hex_common(event, arg, tok, PRINT_HEX_STR); + return process_hex_common(event, arg, tok, TEP_PRINT_HEX_STR); } static enum tep_event_type process_int_array(struct tep_event_format *event, struct tep_print_arg *arg, char **tok) { memset(arg, 0, sizeof(*arg)); - arg->type = PRINT_INT_ARRAY; + arg->type = TEP_PRINT_INT_ARRAY; if (alloc_and_process_delim(event, ",", &arg->int_array.field)) goto out; @@ -2688,7 +2688,7 @@ process_dynamic_array(struct tep_event_format *event, struct tep_print_arg *arg, char *token; memset(arg, 0, sizeof(*arg)); - arg->type = PRINT_DYNAMIC_ARRAY; + arg->type = TEP_PRINT_DYNAMIC_ARRAY; /* * The item within the parenthesis is another field that holds @@ -2755,7 +2755,7 @@ process_dynamic_array_len(struct tep_event_format *event, struct tep_print_arg * if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto out_free; - arg->type = PRINT_DYNAMIC_ARRAY_LEN; + arg->type = TEP_PRINT_DYNAMIC_ARRAY_LEN; /* Find the field */ field = tep_find_field(event, token); @@ -2814,8 +2814,8 @@ process_paren(struct tep_event_format *event, struct tep_print_arg *arg, char ** /* make this a typecast and contine */ /* prevous must be an atom */ - if (arg->type != PRINT_ATOM) { - do_warning_event(event, "previous needed to be PRINT_ATOM"); + if (arg->type != TEP_PRINT_ATOM) { + do_warning_event(event, "previous needed to be TEP_PRINT_ATOM"); goto out_free; } @@ -2826,7 +2826,7 @@ process_paren(struct tep_event_format *event, struct tep_print_arg *arg, char ** goto out_free; } - arg->type = PRINT_TYPE; + arg->type = TEP_PRINT_TYPE; arg->typecast.type = arg->atom.atom; arg->typecast.item = item_arg; type = process_arg_token(event, item_arg, &token, type); @@ -2853,7 +2853,7 @@ process_str(struct tep_event_format *event __maybe_unused, struct tep_print_arg if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto out_free; - arg->type = PRINT_STRING; + arg->type = TEP_PRINT_STRING; arg->string.string = token; arg->string.offset = -1; @@ -2882,7 +2882,7 @@ process_bitmask(struct tep_event_format *event __maybe_unused, struct tep_print_ if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto out_free; - arg->type = PRINT_BITMASK; + arg->type = TEP_PRINT_BITMASK; arg->bitmask.bitmask = token; arg->bitmask.offset = -1; @@ -2943,7 +2943,7 @@ process_func_handler(struct tep_event_format *event, struct tep_function_handler char *token; int i; - arg->type = PRINT_FUNC; + arg->type = TEP_PRINT_FUNC; arg->func.func = func; *tok = NULL; @@ -3096,13 +3096,13 @@ process_arg_token(struct tep_event_format *event, struct tep_print_arg *arg, type = read_token_item(&token); } - arg->type = PRINT_ATOM; + arg->type = TEP_PRINT_ATOM; arg->atom.atom = atom; break; case TEP_EVENT_DQUOTE: case TEP_EVENT_SQUOTE: - arg->type = PRINT_ATOM; + arg->type = TEP_PRINT_ATOM; arg->atom.atom = token; type = read_token_item(&token); break; @@ -3114,7 +3114,7 @@ process_arg_token(struct tep_event_format *event, struct tep_print_arg *arg, } case TEP_EVENT_OP: /* handle single ops */ - arg->type = PRINT_OP; + arg->type = TEP_PRINT_OP; arg->op.op = token; arg->op.left = NULL; type = process_op(event, arg, &token); @@ -3533,12 +3533,12 @@ eval_num_arg(void *data, int size, struct tep_event_format *event, struct tep_pr unsigned int field_size; switch (arg->type) { - case PRINT_NULL: + case TEP_PRINT_NULL: /* ?? */ return 0; - case PRINT_ATOM: + case TEP_PRINT_ATOM: return strtoull(arg->atom.atom, NULL, 0); - case PRINT_FIELD: + case TEP_PRINT_FIELD: if (!arg->field.field) { arg->field.field = tep_find_any_field(event, arg->field.name); if (!arg->field.field) @@ -3549,27 +3549,27 @@ eval_num_arg(void *data, int size, struct tep_event_format *event, struct tep_pr val = tep_read_number(pevent, data + arg->field.field->offset, arg->field.field->size); break; - case PRINT_FLAGS: - case PRINT_SYMBOL: - case PRINT_INT_ARRAY: - case PRINT_HEX: - case PRINT_HEX_STR: + case TEP_PRINT_FLAGS: + case TEP_PRINT_SYMBOL: + case TEP_PRINT_INT_ARRAY: + case TEP_PRINT_HEX: + case TEP_PRINT_HEX_STR: break; - case PRINT_TYPE: + case TEP_PRINT_TYPE: val = eval_num_arg(data, size, event, arg->typecast.item); return eval_type(val, arg, 0); - case PRINT_STRING: - case PRINT_BSTRING: - case PRINT_BITMASK: + case TEP_PRINT_STRING: + case TEP_PRINT_BSTRING: + case TEP_PRINT_BITMASK: return 0; - case PRINT_FUNC: { + case TEP_PRINT_FUNC: { struct trace_seq s; trace_seq_init(&s); val = process_defined_func(&s, data, size, event, arg); trace_seq_destroy(&s); return val; } - case PRINT_OP: + case TEP_PRINT_OP: if (strcmp(arg->op.op, "[") == 0) { /* * Arrays are special, since we don't want @@ -3579,7 +3579,7 @@ eval_num_arg(void *data, int size, struct tep_event_format *event, struct tep_pr /* handle typecasts */ larg = arg->op.left; - while (larg->type == PRINT_TYPE) { + while (larg->type == TEP_PRINT_TYPE) { if (!typearg) typearg = larg; larg = larg->typecast.item; @@ -3589,7 +3589,7 @@ eval_num_arg(void *data, int size, struct tep_event_format *event, struct tep_pr field_size = pevent->long_size; switch (larg->type) { - case PRINT_DYNAMIC_ARRAY: + case TEP_PRINT_DYNAMIC_ARRAY: offset = tep_read_number(pevent, data + larg->dynarray.field->offset, larg->dynarray.field->size); @@ -3603,7 +3603,7 @@ eval_num_arg(void *data, int size, struct tep_event_format *event, struct tep_pr offset &= 0xffff; offset += right; break; - case PRINT_FIELD: + case TEP_PRINT_FIELD: if (!larg->field.field) { larg->field.field = tep_find_any_field(event, larg->field.name); @@ -3719,7 +3719,7 @@ eval_num_arg(void *data, int size, struct tep_event_format *event, struct tep_pr goto out_warning_op; } break; - case PRINT_DYNAMIC_ARRAY_LEN: + case TEP_PRINT_DYNAMIC_ARRAY_LEN: offset = tep_read_number(pevent, data + arg->dynarray.field->offset, arg->dynarray.field->size); @@ -3730,7 +3730,7 @@ eval_num_arg(void *data, int size, struct tep_event_format *event, struct tep_pr */ val = (unsigned long long)(offset >> 16); break; - case PRINT_DYNAMIC_ARRAY: + case TEP_PRINT_DYNAMIC_ARRAY: /* Without [], we pass the address to the dynamic data */ offset = tep_read_number(pevent, data + arg->dynarray.field->offset, @@ -3877,13 +3877,13 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, int i, len; switch (arg->type) { - case PRINT_NULL: + case TEP_PRINT_NULL: /* ?? */ return; - case PRINT_ATOM: + case TEP_PRINT_ATOM: print_str_to_seq(s, format, len_arg, arg->atom.atom); return; - case PRINT_FIELD: + case TEP_PRINT_FIELD: field = arg->field.field; if (!field) { field = tep_find_any_field(event, arg->field.name); @@ -3940,7 +3940,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, print_str_to_seq(s, format, len_arg, str); free(str); break; - case PRINT_FLAGS: + case TEP_PRINT_FLAGS: val = eval_num_arg(data, size, event, arg->flags.field); print = 0; for (flag = arg->flags.flags; flag; flag = flag->next) { @@ -3963,7 +3963,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, trace_seq_printf(s, "0x%llx", val); } break; - case PRINT_SYMBOL: + case TEP_PRINT_SYMBOL: val = eval_num_arg(data, size, event, arg->symbol.field); for (flag = arg->symbol.symbols; flag; flag = flag->next) { fval = eval_flag(flag->value); @@ -3975,9 +3975,9 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, if (!flag) trace_seq_printf(s, "0x%llx", val); break; - case PRINT_HEX: - case PRINT_HEX_STR: - if (arg->hex.field->type == PRINT_DYNAMIC_ARRAY) { + case TEP_PRINT_HEX: + case TEP_PRINT_HEX_STR: + if (arg->hex.field->type == TEP_PRINT_DYNAMIC_ARRAY) { unsigned long offset; offset = tep_read_number(pevent, data + arg->hex.field->dynarray.field->offset, @@ -3996,17 +3996,17 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, } len = eval_num_arg(data, size, event, arg->hex.size); for (i = 0; i < len; i++) { - if (i && arg->type == PRINT_HEX) + if (i && arg->type == TEP_PRINT_HEX) trace_seq_putc(s, ' '); trace_seq_printf(s, "%02x", hex[i]); } break; - case PRINT_INT_ARRAY: { + case TEP_PRINT_INT_ARRAY: { void *num; int el_size; - if (arg->int_array.field->type == PRINT_DYNAMIC_ARRAY) { + if (arg->int_array.field->type == TEP_PRINT_DYNAMIC_ARRAY) { unsigned long offset; struct tep_format_field *field = arg->int_array.field->dynarray.field; @@ -4050,9 +4050,9 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, } break; } - case PRINT_TYPE: + case TEP_PRINT_TYPE: break; - case PRINT_STRING: { + case TEP_PRINT_STRING: { int str_offset; if (arg->string.offset == -1) { @@ -4066,10 +4066,10 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset); break; } - case PRINT_BSTRING: + case TEP_PRINT_BSTRING: print_str_to_seq(s, format, len_arg, arg->string.string); break; - case PRINT_BITMASK: { + case TEP_PRINT_BITMASK: { int bitmask_offset; int bitmask_size; @@ -4086,7 +4086,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, data + bitmask_offset, bitmask_size); break; } - case PRINT_OP: + case TEP_PRINT_OP: /* * The only op for string should be ? : */ @@ -4100,7 +4100,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, print_str_arg(s, data, size, event, format, len_arg, arg->op.right->op.right); break; - case PRINT_FUNC: + case TEP_PRINT_FUNC: process_defined_func(s, data, size, event, arg); break; default: @@ -4255,7 +4255,7 @@ static struct tep_print_arg *make_bprint_args(char *fmt, void *data, int size, s arg->next = NULL; next = &arg->next; - arg->type = PRINT_ATOM; + arg->type = TEP_PRINT_ATOM; if (asprintf(&arg->atom.atom, "%lld", ip) < 0) goto out_free; @@ -4343,7 +4343,7 @@ static struct tep_print_arg *make_bprint_args(char *fmt, void *data, int size, s goto out_free; } arg->next = NULL; - arg->type = PRINT_ATOM; + arg->type = TEP_PRINT_ATOM; if (asprintf(&arg->atom.atom, "%lld", val) < 0) { free(arg); goto out_free; @@ -4367,7 +4367,7 @@ static struct tep_print_arg *make_bprint_args(char *fmt, void *data, int size, s goto out_free; } arg->next = NULL; - arg->type = PRINT_BSTRING; + arg->type = TEP_PRINT_BSTRING; arg->string.string = strdup(bptr); if (!arg->string.string) goto out_free; @@ -4429,12 +4429,12 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size, unsigned char *buf; const char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"; - if (arg->type == PRINT_FUNC) { + if (arg->type == TEP_PRINT_FUNC) { process_defined_func(s, data, size, event, arg); return; } - if (arg->type != PRINT_FIELD) { + if (arg->type != TEP_PRINT_FIELD) { trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); return; @@ -4582,12 +4582,12 @@ static int print_ipv4_arg(struct trace_seq *s, const char *ptr, char i, { unsigned char *buf; - if (arg->type == PRINT_FUNC) { + if (arg->type == TEP_PRINT_FUNC) { process_defined_func(s, data, size, event, arg); return 0; } - if (arg->type != PRINT_FIELD) { + if (arg->type != TEP_PRINT_FIELD) { trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); return 0; } @@ -4628,12 +4628,12 @@ static int print_ipv6_arg(struct trace_seq *s, const char *ptr, char i, rc++; } - if (arg->type == PRINT_FUNC) { + if (arg->type == TEP_PRINT_FUNC) { process_defined_func(s, data, size, event, arg); return rc; } - if (arg->type != PRINT_FIELD) { + if (arg->type != TEP_PRINT_FIELD) { trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); return rc; } @@ -4686,12 +4686,12 @@ static int print_ipsa_arg(struct trace_seq *s, const char *ptr, char i, } } - if (arg->type == PRINT_FUNC) { + if (arg->type == TEP_PRINT_FUNC) { process_defined_func(s, data, size, event, arg); return rc; } - if (arg->type != PRINT_FIELD) { + if (arg->type != TEP_PRINT_FIELD) { trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); return rc; } @@ -4967,7 +4967,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct tep_e if (isalnum(ptr[1])) ptr++; - if (arg->type == PRINT_BSTRING) { + if (arg->type == TEP_PRINT_BSTRING) { trace_seq_puts(s, arg->string.string); break; } @@ -5739,16 +5739,16 @@ static void print_args(struct tep_print_arg *args) struct trace_seq s; switch (args->type) { - case PRINT_NULL: + case TEP_PRINT_NULL: printf("null"); break; - case PRINT_ATOM: + case TEP_PRINT_ATOM: printf("%s", args->atom.atom); break; - case PRINT_FIELD: + case TEP_PRINT_FIELD: printf("REC->%s", args->field.name); break; - case PRINT_FLAGS: + case TEP_PRINT_FLAGS: printf("__print_flags("); print_args(args->flags.field); printf(", %s, ", args->flags.delim); @@ -5758,7 +5758,7 @@ static void print_args(struct tep_print_arg *args) trace_seq_destroy(&s); printf(")"); break; - case PRINT_SYMBOL: + case TEP_PRINT_SYMBOL: printf("__print_symbolic("); print_args(args->symbol.field); printf(", "); @@ -5768,21 +5768,21 @@ static void print_args(struct tep_print_arg *args) trace_seq_destroy(&s); printf(")"); break; - case PRINT_HEX: + case TEP_PRINT_HEX: printf("__print_hex("); print_args(args->hex.field); printf(", "); print_args(args->hex.size); printf(")"); break; - case PRINT_HEX_STR: + case TEP_PRINT_HEX_STR: printf("__print_hex_str("); print_args(args->hex.field); printf(", "); print_args(args->hex.size); printf(")"); break; - case PRINT_INT_ARRAY: + case TEP_PRINT_INT_ARRAY: printf("__print_array("); print_args(args->int_array.field); printf(", "); @@ -5791,18 +5791,18 @@ static void print_args(struct tep_print_arg *args) print_args(args->int_array.el_size); printf(")"); break; - case PRINT_STRING: - case PRINT_BSTRING: + case TEP_PRINT_STRING: + case TEP_PRINT_BSTRING: printf("__get_str(%s)", args->string.string); break; - case PRINT_BITMASK: + case TEP_PRINT_BITMASK: printf("__get_bitmask(%s)", args->bitmask.bitmask); break; - case PRINT_TYPE: + case TEP_PRINT_TYPE: printf("(%s)", args->typecast.type); print_args(args->typecast.item); break; - case PRINT_OP: + case TEP_PRINT_OP: if (strcmp(args->op.op, ":") == 0) print_paren = 0; if (print_paren) @@ -6101,7 +6101,7 @@ enum tep_errno __tep_parse_format(struct tep_event_format **eventp, event->flags |= TEP_EVENT_FL_FAILED; return TEP_ERRNO__OLD_FTRACE_ARG_FAILED; } - arg->type = PRINT_FIELD; + arg->type = TEP_PRINT_FIELD; arg->field.name = strdup(field->name); if (!arg->field.name) { event->flags |= TEP_EVENT_FL_FAILED; diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 21923a11c9c0..7c4bf915d09a 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -234,28 +234,28 @@ struct tep_print_arg_func { struct tep_print_arg *args; }; -enum print_arg_type { - PRINT_NULL, - PRINT_ATOM, - PRINT_FIELD, - PRINT_FLAGS, - PRINT_SYMBOL, - PRINT_HEX, - PRINT_INT_ARRAY, - PRINT_TYPE, - PRINT_STRING, - PRINT_BSTRING, - PRINT_DYNAMIC_ARRAY, - PRINT_OP, - PRINT_FUNC, - PRINT_BITMASK, - PRINT_DYNAMIC_ARRAY_LEN, - PRINT_HEX_STR, +enum tep_print_arg_type { + TEP_PRINT_NULL, + TEP_PRINT_ATOM, + TEP_PRINT_FIELD, + TEP_PRINT_FLAGS, + TEP_PRINT_SYMBOL, + TEP_PRINT_HEX, + TEP_PRINT_INT_ARRAY, + TEP_PRINT_TYPE, + TEP_PRINT_STRING, + TEP_PRINT_BSTRING, + TEP_PRINT_DYNAMIC_ARRAY, + TEP_PRINT_OP, + TEP_PRINT_FUNC, + TEP_PRINT_BITMASK, + TEP_PRINT_DYNAMIC_ARRAY_LEN, + TEP_PRINT_HEX_STR, }; struct tep_print_arg { struct tep_print_arg *next; - enum print_arg_type type; + enum tep_print_arg_type type; union { struct tep_print_arg_atom atom; struct tep_print_arg_field field; diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 481a1ecb1eaf..89cb887648f9 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -197,54 +197,54 @@ static void define_event_symbols(struct tep_event_format *event, return; switch (args->type) { - case PRINT_NULL: + case TEP_PRINT_NULL: break; - case PRINT_ATOM: + case TEP_PRINT_ATOM: define_flag_value(ev_name, cur_field_name, "0", args->atom.atom); zero_flag_atom = 0; break; - case PRINT_FIELD: + case TEP_PRINT_FIELD: free(cur_field_name); cur_field_name = strdup(args->field.name); break; - case PRINT_FLAGS: + case TEP_PRINT_FLAGS: define_event_symbols(event, ev_name, args->flags.field); define_flag_field(ev_name, cur_field_name, args->flags.delim); define_flag_values(args->flags.flags, ev_name, cur_field_name); break; - case PRINT_SYMBOL: + case TEP_PRINT_SYMBOL: define_event_symbols(event, ev_name, args->symbol.field); define_symbolic_field(ev_name, cur_field_name); define_symbolic_values(args->symbol.symbols, ev_name, cur_field_name); break; - case PRINT_HEX: - case PRINT_HEX_STR: + case TEP_PRINT_HEX: + case TEP_PRINT_HEX_STR: define_event_symbols(event, ev_name, args->hex.field); define_event_symbols(event, ev_name, args->hex.size); break; - case PRINT_INT_ARRAY: + case TEP_PRINT_INT_ARRAY: define_event_symbols(event, ev_name, args->int_array.field); define_event_symbols(event, ev_name, args->int_array.count); define_event_symbols(event, ev_name, args->int_array.el_size); break; - case PRINT_BSTRING: - case PRINT_DYNAMIC_ARRAY: - case PRINT_DYNAMIC_ARRAY_LEN: - case PRINT_STRING: - case PRINT_BITMASK: + case TEP_PRINT_BSTRING: + case TEP_PRINT_DYNAMIC_ARRAY: + case TEP_PRINT_DYNAMIC_ARRAY_LEN: + case TEP_PRINT_STRING: + case TEP_PRINT_BITMASK: break; - case PRINT_TYPE: + case TEP_PRINT_TYPE: define_event_symbols(event, ev_name, args->typecast.item); break; - case PRINT_OP: + case TEP_PRINT_OP: if (strcmp(args->op.op, ":") == 0) zero_flag_atom = 1; define_event_symbols(event, ev_name, args->op.left); define_event_symbols(event, ev_name, args->op.right); break; - case PRINT_FUNC: + case TEP_PRINT_FUNC: default: pr_err("Unsupported print arg type\n"); /* we should warn... */ diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 35dc5f3b581b..69aa93d4ee99 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -193,7 +193,7 @@ static void try_call_object(const char *handler_name, PyObject *args) call_object(handler, args, handler_name); } -static void define_value(enum print_arg_type field_type, +static void define_value(enum tep_print_arg_type field_type, const char *ev_name, const char *field_name, const char *field_value, @@ -204,7 +204,7 @@ static void define_value(enum print_arg_type field_type, unsigned long long value; unsigned n = 0; - if (field_type == PRINT_SYMBOL) + if (field_type == TEP_PRINT_SYMBOL) handler_name = "define_symbolic_value"; t = PyTuple_New(4); @@ -223,7 +223,7 @@ static void define_value(enum print_arg_type field_type, Py_DECREF(t); } -static void define_values(enum print_arg_type field_type, +static void define_values(enum tep_print_arg_type field_type, struct tep_print_flag_sym *field, const char *ev_name, const char *field_name) @@ -235,7 +235,7 @@ static void define_values(enum print_arg_type field_type, define_values(field_type, field->next, ev_name, field_name); } -static void define_field(enum print_arg_type field_type, +static void define_field(enum tep_print_arg_type field_type, const char *ev_name, const char *field_name, const char *delim) @@ -244,10 +244,10 @@ static void define_field(enum print_arg_type field_type, PyObject *t; unsigned n = 0; - if (field_type == PRINT_SYMBOL) + if (field_type == TEP_PRINT_SYMBOL) handler_name = "define_symbolic_field"; - if (field_type == PRINT_FLAGS) + if (field_type == TEP_PRINT_FLAGS) t = PyTuple_New(3); else t = PyTuple_New(2); @@ -256,7 +256,7 @@ static void define_field(enum print_arg_type field_type, PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); - if (field_type == PRINT_FLAGS) + if (field_type == TEP_PRINT_FLAGS) PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim)); try_call_object(handler_name, t); @@ -272,46 +272,46 @@ static void define_event_symbols(struct tep_event_format *event, return; switch (args->type) { - case PRINT_NULL: + case TEP_PRINT_NULL: break; - case PRINT_ATOM: - define_value(PRINT_FLAGS, ev_name, cur_field_name, "0", + case TEP_PRINT_ATOM: + define_value(TEP_PRINT_FLAGS, ev_name, cur_field_name, "0", args->atom.atom); zero_flag_atom = 0; break; - case PRINT_FIELD: + case TEP_PRINT_FIELD: free(cur_field_name); cur_field_name = strdup(args->field.name); break; - case PRINT_FLAGS: + case TEP_PRINT_FLAGS: define_event_symbols(event, ev_name, args->flags.field); - define_field(PRINT_FLAGS, ev_name, cur_field_name, + define_field(TEP_PRINT_FLAGS, ev_name, cur_field_name, args->flags.delim); - define_values(PRINT_FLAGS, args->flags.flags, ev_name, + define_values(TEP_PRINT_FLAGS, args->flags.flags, ev_name, cur_field_name); break; - case PRINT_SYMBOL: + case TEP_PRINT_SYMBOL: define_event_symbols(event, ev_name, args->symbol.field); - define_field(PRINT_SYMBOL, ev_name, cur_field_name, NULL); - define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name, + define_field(TEP_PRINT_SYMBOL, ev_name, cur_field_name, NULL); + define_values(TEP_PRINT_SYMBOL, args->symbol.symbols, ev_name, cur_field_name); break; - case PRINT_HEX: - case PRINT_HEX_STR: + case TEP_PRINT_HEX: + case TEP_PRINT_HEX_STR: define_event_symbols(event, ev_name, args->hex.field); define_event_symbols(event, ev_name, args->hex.size); break; - case PRINT_INT_ARRAY: + case TEP_PRINT_INT_ARRAY: define_event_symbols(event, ev_name, args->int_array.field); define_event_symbols(event, ev_name, args->int_array.count); define_event_symbols(event, ev_name, args->int_array.el_size); break; - case PRINT_STRING: + case TEP_PRINT_STRING: break; - case PRINT_TYPE: + case TEP_PRINT_TYPE: define_event_symbols(event, ev_name, args->typecast.item); break; - case PRINT_OP: + case TEP_PRINT_OP: if (strcmp(args->op.op, ":") == 0) zero_flag_atom = 1; define_event_symbols(event, ev_name, args->op.left); @@ -319,11 +319,11 @@ static void define_event_symbols(struct tep_event_format *event, break; default: /* gcc warns for these? */ - case PRINT_BSTRING: - case PRINT_DYNAMIC_ARRAY: - case PRINT_DYNAMIC_ARRAY_LEN: - case PRINT_FUNC: - case PRINT_BITMASK: + case TEP_PRINT_BSTRING: + case TEP_PRINT_DYNAMIC_ARRAY: + case TEP_PRINT_DYNAMIC_ARRAY_LEN: + case TEP_PRINT_FUNC: + case TEP_PRINT_BITMASK: /* we should warn... */ return; } From e906bb788f2c4e870787f09b831923ca893a4671 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:51 -0400 Subject: [PATCH 110/155] tools lib traceevent: Add prefix tep_ to enums filter_{boolean,op,cmp}_type In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This adds prefix tep_ to enums filter_boolean_type, filter_op_type, filter_cmp_type and all enum's members Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185723.680572508@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 46 ++++----- tools/lib/traceevent/parse-filter.c | 144 ++++++++++++++-------------- 2 files changed, 95 insertions(+), 95 deletions(-) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 7c4bf915d09a..c9d7c5376fc2 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -768,29 +768,29 @@ void tep_print_printk(struct tep_handle *pevent); /* ----------------------- filtering ----------------------- */ -enum filter_boolean_type { - FILTER_FALSE, - FILTER_TRUE, +enum tep_filter_boolean_type { + TEP_FILTER_FALSE, + TEP_FILTER_TRUE, }; -enum filter_op_type { - FILTER_OP_AND = 1, - FILTER_OP_OR, - FILTER_OP_NOT, +enum tep_filter_op_type { + TEP_FILTER_OP_AND = 1, + TEP_FILTER_OP_OR, + TEP_FILTER_OP_NOT, }; -enum filter_cmp_type { - FILTER_CMP_NONE, - FILTER_CMP_EQ, - FILTER_CMP_NE, - FILTER_CMP_GT, - FILTER_CMP_LT, - FILTER_CMP_GE, - FILTER_CMP_LE, - FILTER_CMP_MATCH, - FILTER_CMP_NOT_MATCH, - FILTER_CMP_REGEX, - FILTER_CMP_NOT_REGEX, +enum tep_filter_cmp_type { + TEP_FILTER_CMP_NONE, + TEP_FILTER_CMP_EQ, + TEP_FILTER_CMP_NE, + TEP_FILTER_CMP_GT, + TEP_FILTER_CMP_LT, + TEP_FILTER_CMP_GE, + TEP_FILTER_CMP_LE, + TEP_FILTER_CMP_MATCH, + TEP_FILTER_CMP_NOT_MATCH, + TEP_FILTER_CMP_REGEX, + TEP_FILTER_CMP_NOT_REGEX, }; enum filter_exp_type { @@ -828,7 +828,7 @@ enum filter_value_type { struct fliter_arg; struct filter_arg_boolean { - enum filter_boolean_type value; + enum tep_filter_boolean_type value; }; struct filter_arg_field { @@ -844,7 +844,7 @@ struct filter_arg_value { }; struct filter_arg_op { - enum filter_op_type type; + enum tep_filter_op_type type; struct filter_arg *left; struct filter_arg *right; }; @@ -856,13 +856,13 @@ struct filter_arg_exp { }; struct filter_arg_num { - enum filter_cmp_type type; + enum tep_filter_cmp_type type; struct filter_arg *left; struct filter_arg *right; }; struct filter_arg_str { - enum filter_cmp_type type; + enum tep_filter_cmp_type type; struct tep_format_field *field; char *val; char *buffer; diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 153e248de75b..55ce8e603485 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -378,7 +378,7 @@ create_arg_item(struct tep_event_format *event, const char *token, } else { /* not a field, Make it false */ arg->type = FILTER_ARG_BOOLEAN; - arg->boolean.value = FILTER_FALSE; + arg->boolean.value = TEP_FILTER_FALSE; break; } } @@ -395,7 +395,7 @@ create_arg_item(struct tep_event_format *event, const char *token, } static struct filter_arg * -create_arg_op(enum filter_op_type btype) +create_arg_op(enum tep_filter_op_type btype) { struct filter_arg *arg; @@ -425,7 +425,7 @@ create_arg_exp(enum filter_exp_type etype) } static struct filter_arg * -create_arg_cmp(enum filter_cmp_type ctype) +create_arg_cmp(enum tep_filter_cmp_type ctype) { struct filter_arg *arg; @@ -488,8 +488,8 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) * is not a REGEX. */ if (strlen(arg->value.str) == 1 && - op->num.type != FILTER_CMP_REGEX && - op->num.type != FILTER_CMP_NOT_REGEX) { + op->num.type != TEP_FILTER_CMP_REGEX && + op->num.type != TEP_FILTER_CMP_NOT_REGEX) { arg->value.type = FILTER_NUMBER; goto do_int; } @@ -512,7 +512,7 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) free_arg(left); free_arg(arg); op->type = FILTER_ARG_BOOLEAN; - op->boolean.value = FILTER_FALSE; + op->boolean.value = TEP_FILTER_FALSE; break; } @@ -525,15 +525,15 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) /* Make sure this is a valid string compare */ switch (op_type) { - case FILTER_CMP_EQ: - op_type = FILTER_CMP_MATCH; + case TEP_FILTER_CMP_EQ: + op_type = TEP_FILTER_CMP_MATCH; break; - case FILTER_CMP_NE: - op_type = FILTER_CMP_NOT_MATCH; + case TEP_FILTER_CMP_NE: + op_type = TEP_FILTER_CMP_NOT_MATCH; break; - case FILTER_CMP_REGEX: - case FILTER_CMP_NOT_REGEX: + case TEP_FILTER_CMP_REGEX: + case TEP_FILTER_CMP_NOT_REGEX: ret = regcomp(&op->str.reg, str, REG_ICASE|REG_NOSUB); if (ret) { show_error(error_str, @@ -577,8 +577,8 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) do_int: switch (op->num.type) { - case FILTER_CMP_REGEX: - case FILTER_CMP_NOT_REGEX: + case TEP_FILTER_CMP_REGEX: + case TEP_FILTER_CMP_NOT_REGEX: show_error(error_str, "Op not allowed with integers"); return TEP_ERRNO__ILLEGAL_INTEGER_CMP; @@ -652,22 +652,22 @@ enum op_type { }; static enum op_type process_op(const char *token, - enum filter_op_type *btype, - enum filter_cmp_type *ctype, + enum tep_filter_op_type *btype, + enum tep_filter_cmp_type *ctype, enum filter_exp_type *etype) { - *btype = FILTER_OP_NOT; + *btype = TEP_FILTER_OP_NOT; *etype = FILTER_EXP_NONE; - *ctype = FILTER_CMP_NONE; + *ctype = TEP_FILTER_CMP_NONE; if (strcmp(token, "&&") == 0) - *btype = FILTER_OP_AND; + *btype = TEP_FILTER_OP_AND; else if (strcmp(token, "||") == 0) - *btype = FILTER_OP_OR; + *btype = TEP_FILTER_OP_OR; else if (strcmp(token, "!") == 0) return OP_NOT; - if (*btype != FILTER_OP_NOT) + if (*btype != TEP_FILTER_OP_NOT) return OP_BOOL; /* Check for value expressions */ @@ -699,21 +699,21 @@ static enum op_type process_op(const char *token, /* Check for compares */ if (strcmp(token, "==") == 0) - *ctype = FILTER_CMP_EQ; + *ctype = TEP_FILTER_CMP_EQ; else if (strcmp(token, "!=") == 0) - *ctype = FILTER_CMP_NE; + *ctype = TEP_FILTER_CMP_NE; else if (strcmp(token, "<") == 0) - *ctype = FILTER_CMP_LT; + *ctype = TEP_FILTER_CMP_LT; else if (strcmp(token, ">") == 0) - *ctype = FILTER_CMP_GT; + *ctype = TEP_FILTER_CMP_GT; else if (strcmp(token, "<=") == 0) - *ctype = FILTER_CMP_LE; + *ctype = TEP_FILTER_CMP_LE; else if (strcmp(token, ">=") == 0) - *ctype = FILTER_CMP_GE; + *ctype = TEP_FILTER_CMP_GE; else if (strcmp(token, "=~") == 0) - *ctype = FILTER_CMP_REGEX; + *ctype = TEP_FILTER_CMP_REGEX; else if (strcmp(token, "!~") == 0) - *ctype = FILTER_CMP_NOT_REGEX; + *ctype = TEP_FILTER_CMP_NOT_REGEX; else return OP_NONE; @@ -840,13 +840,13 @@ static int test_arg(struct filter_arg *parent, struct filter_arg *arg, return FILTER_VAL_NORM; case FILTER_ARG_OP: - if (arg->op.type != FILTER_OP_NOT) { + if (arg->op.type != TEP_FILTER_OP_NOT) { lval = test_arg(arg, arg->op.left, error_str); switch (lval) { case FILTER_VAL_NORM: break; case FILTER_VAL_TRUE: - if (arg->op.type == FILTER_OP_OR) + if (arg->op.type == TEP_FILTER_OP_OR) return FILTER_VAL_TRUE; rval = test_arg(arg, arg->op.right, error_str); if (rval != FILTER_VAL_NORM) @@ -856,7 +856,7 @@ static int test_arg(struct filter_arg *parent, struct filter_arg *arg, error_str); case FILTER_VAL_FALSE: - if (arg->op.type == FILTER_OP_AND) + if (arg->op.type == TEP_FILTER_OP_AND) return FILTER_VAL_FALSE; rval = test_arg(arg, arg->op.right, error_str); if (rval != FILTER_VAL_NORM) @@ -877,18 +877,18 @@ static int test_arg(struct filter_arg *parent, struct filter_arg *arg, break; case FILTER_VAL_TRUE: - if (arg->op.type == FILTER_OP_OR) + if (arg->op.type == TEP_FILTER_OP_OR) return FILTER_VAL_TRUE; - if (arg->op.type == FILTER_OP_NOT) + if (arg->op.type == TEP_FILTER_OP_NOT) return FILTER_VAL_FALSE; return reparent_op_arg(parent, arg, arg->op.left, error_str); case FILTER_VAL_FALSE: - if (arg->op.type == FILTER_OP_AND) + if (arg->op.type == TEP_FILTER_OP_AND) return FILTER_VAL_FALSE; - if (arg->op.type == FILTER_OP_NOT) + if (arg->op.type == TEP_FILTER_OP_NOT) return FILTER_VAL_TRUE; return reparent_op_arg(parent, arg, arg->op.left, @@ -949,9 +949,9 @@ process_filter(struct tep_event_format *event, struct filter_arg **parg, struct filter_arg *left_item = NULL; struct filter_arg *arg = NULL; enum op_type op_type; - enum filter_op_type btype; + enum tep_filter_op_type btype; enum filter_exp_type etype; - enum filter_cmp_type ctype; + enum tep_filter_cmp_type ctype; enum tep_errno ret; *parg = NULL; @@ -1197,7 +1197,7 @@ process_event(struct tep_event_format *event, const char *filter_str, return TEP_ERRNO__MEM_ALLOC_FAILED; (*parg)->type = FILTER_ARG_BOOLEAN; - (*parg)->boolean.value = FILTER_FALSE; + (*parg)->boolean.value = TEP_FILTER_FALSE; } return 0; @@ -1223,7 +1223,7 @@ filter_event(struct event_filter *filter, struct tep_event_format *event, return TEP_ERRNO__MEM_ALLOC_FAILED; arg->type = FILTER_ARG_BOOLEAN; - arg->boolean.value = FILTER_TRUE; + arg->boolean.value = TEP_FILTER_TRUE; } filter_type = add_filter_type(filter, event->id); @@ -1832,22 +1832,22 @@ static int test_num(struct tep_event_format *event, struct filter_arg *arg, } switch (arg->num.type) { - case FILTER_CMP_EQ: + case TEP_FILTER_CMP_EQ: return lval == rval; - case FILTER_CMP_NE: + case TEP_FILTER_CMP_NE: return lval != rval; - case FILTER_CMP_GT: + case TEP_FILTER_CMP_GT: return lval > rval; - case FILTER_CMP_LT: + case TEP_FILTER_CMP_LT: return lval < rval; - case FILTER_CMP_GE: + case TEP_FILTER_CMP_GE: return lval >= rval; - case FILTER_CMP_LE: + case TEP_FILTER_CMP_LE: return lval <= rval; default: @@ -1918,17 +1918,17 @@ static int test_str(struct tep_event_format *event, struct filter_arg *arg, val = get_field_str(arg, record); switch (arg->str.type) { - case FILTER_CMP_MATCH: + case TEP_FILTER_CMP_MATCH: return strcmp(val, arg->str.val) == 0; - case FILTER_CMP_NOT_MATCH: + case TEP_FILTER_CMP_NOT_MATCH: return strcmp(val, arg->str.val) != 0; - case FILTER_CMP_REGEX: + case TEP_FILTER_CMP_REGEX: /* Returns zero on match */ return !regexec(&arg->str.reg, val, 0, NULL, 0); - case FILTER_CMP_NOT_REGEX: + case TEP_FILTER_CMP_NOT_REGEX: return regexec(&arg->str.reg, val, 0, NULL, 0); default: @@ -1942,15 +1942,15 @@ static int test_op(struct tep_event_format *event, struct filter_arg *arg, struct tep_record *record, enum tep_errno *err) { switch (arg->op.type) { - case FILTER_OP_AND: + case TEP_FILTER_OP_AND: return test_filter(event, arg->op.left, record, err) && test_filter(event, arg->op.right, record, err); - case FILTER_OP_OR: + case TEP_FILTER_OP_OR: return test_filter(event, arg->op.left, record, err) || test_filter(event, arg->op.right, record, err); - case FILTER_OP_NOT: + case TEP_FILTER_OP_NOT: return !test_filter(event, arg->op.right, record, err); default: @@ -2070,10 +2070,10 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) int val; switch (arg->op.type) { - case FILTER_OP_AND: + case TEP_FILTER_OP_AND: op = "&&"; /* fall through */ - case FILTER_OP_OR: + case TEP_FILTER_OP_OR: if (!op) op = "||"; @@ -2094,8 +2094,8 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) right_val = 0; if (left_val >= 0) { - if ((arg->op.type == FILTER_OP_AND && !left_val) || - (arg->op.type == FILTER_OP_OR && left_val)) { + if ((arg->op.type == TEP_FILTER_OP_AND && !left_val) || + (arg->op.type == TEP_FILTER_OP_OR && left_val)) { /* Just return left value */ str = left; left = NULL; @@ -2105,10 +2105,10 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) /* just evaluate this. */ val = 0; switch (arg->op.type) { - case FILTER_OP_AND: + case TEP_FILTER_OP_AND: val = left_val && right_val; break; - case FILTER_OP_OR: + case TEP_FILTER_OP_OR: val = left_val || right_val; break; default: @@ -2119,8 +2119,8 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) } } if (right_val >= 0) { - if ((arg->op.type == FILTER_OP_AND && !right_val) || - (arg->op.type == FILTER_OP_OR && right_val)) { + if ((arg->op.type == TEP_FILTER_OP_AND && !right_val) || + (arg->op.type == TEP_FILTER_OP_OR && right_val)) { /* Just return right value */ str = right; right = NULL; @@ -2135,7 +2135,7 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) asprintf(&str, "(%s) %s (%s)", left, op, right); break; - case FILTER_OP_NOT: + case TEP_FILTER_OP_NOT: op = "!"; right = arg_to_str(filter, arg->op.right); if (!right) @@ -2246,26 +2246,26 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg) goto out; switch (arg->num.type) { - case FILTER_CMP_EQ: + case TEP_FILTER_CMP_EQ: op = "=="; /* fall through */ - case FILTER_CMP_NE: + case TEP_FILTER_CMP_NE: if (!op) op = "!="; /* fall through */ - case FILTER_CMP_GT: + case TEP_FILTER_CMP_GT: if (!op) op = ">"; /* fall through */ - case FILTER_CMP_LT: + case TEP_FILTER_CMP_LT: if (!op) op = "<"; /* fall through */ - case FILTER_CMP_GE: + case TEP_FILTER_CMP_GE: if (!op) op = ">="; /* fall through */ - case FILTER_CMP_LE: + case TEP_FILTER_CMP_LE: if (!op) op = "<="; @@ -2289,18 +2289,18 @@ static char *str_to_str(struct event_filter *filter, struct filter_arg *arg) char *op = NULL; switch (arg->str.type) { - case FILTER_CMP_MATCH: + case TEP_FILTER_CMP_MATCH: op = "=="; /* fall through */ - case FILTER_CMP_NOT_MATCH: + case TEP_FILTER_CMP_NOT_MATCH: if (!op) op = "!="; /* fall through */ - case FILTER_CMP_REGEX: + case TEP_FILTER_CMP_REGEX: if (!op) op = "=~"; /* fall through */ - case FILTER_CMP_NOT_REGEX: + case TEP_FILTER_CMP_NOT_REGEX: if (!op) op = "!~"; From 4746d22a4c1b12993540924f8cca12a256646614 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:52 -0400 Subject: [PATCH 111/155] tools lib traceevent: Add prefix tep_ to enums filter_{exp,arg}_type In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This adds prefix tep_ to enums filter_exp_type, filter_arg_type and all enum's members Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185723.824559046@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 52 +++---- tools/lib/traceevent/parse-filter.c | 210 ++++++++++++++-------------- 2 files changed, 131 insertions(+), 131 deletions(-) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index c9d7c5376fc2..5e55c83d43fe 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -793,30 +793,30 @@ enum tep_filter_cmp_type { TEP_FILTER_CMP_NOT_REGEX, }; -enum filter_exp_type { - FILTER_EXP_NONE, - FILTER_EXP_ADD, - FILTER_EXP_SUB, - FILTER_EXP_MUL, - FILTER_EXP_DIV, - FILTER_EXP_MOD, - FILTER_EXP_RSHIFT, - FILTER_EXP_LSHIFT, - FILTER_EXP_AND, - FILTER_EXP_OR, - FILTER_EXP_XOR, - FILTER_EXP_NOT, +enum tep_filter_exp_type { + TEP_FILTER_EXP_NONE, + TEP_FILTER_EXP_ADD, + TEP_FILTER_EXP_SUB, + TEP_FILTER_EXP_MUL, + TEP_FILTER_EXP_DIV, + TEP_FILTER_EXP_MOD, + TEP_FILTER_EXP_RSHIFT, + TEP_FILTER_EXP_LSHIFT, + TEP_FILTER_EXP_AND, + TEP_FILTER_EXP_OR, + TEP_FILTER_EXP_XOR, + TEP_FILTER_EXP_NOT, }; -enum filter_arg_type { - FILTER_ARG_NONE, - FILTER_ARG_BOOLEAN, - FILTER_ARG_VALUE, - FILTER_ARG_FIELD, - FILTER_ARG_EXP, - FILTER_ARG_OP, - FILTER_ARG_NUM, - FILTER_ARG_STR, +enum tep_filter_arg_type { + TEP_FILTER_ARG_NONE, + TEP_FILTER_ARG_BOOLEAN, + TEP_FILTER_ARG_VALUE, + TEP_FILTER_ARG_FIELD, + TEP_FILTER_ARG_EXP, + TEP_FILTER_ARG_OP, + TEP_FILTER_ARG_NUM, + TEP_FILTER_ARG_STR, }; enum filter_value_type { @@ -850,9 +850,9 @@ struct filter_arg_op { }; struct filter_arg_exp { - enum filter_exp_type type; - struct filter_arg *left; - struct filter_arg *right; + enum tep_filter_exp_type type; + struct filter_arg *left; + struct filter_arg *right; }; struct filter_arg_num { @@ -870,7 +870,7 @@ struct filter_arg_str { }; struct filter_arg { - enum filter_arg_type type; + enum tep_filter_arg_type type; union { struct filter_arg_boolean boolean; struct filter_arg_field field; diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 55ce8e603485..d1e0dd5b63ea 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -191,33 +191,33 @@ static void free_arg(struct filter_arg *arg) return; switch (arg->type) { - case FILTER_ARG_NONE: - case FILTER_ARG_BOOLEAN: + case TEP_FILTER_ARG_NONE: + case TEP_FILTER_ARG_BOOLEAN: break; - case FILTER_ARG_NUM: + case TEP_FILTER_ARG_NUM: free_arg(arg->num.left); free_arg(arg->num.right); break; - case FILTER_ARG_EXP: + case TEP_FILTER_ARG_EXP: free_arg(arg->exp.left); free_arg(arg->exp.right); break; - case FILTER_ARG_STR: + case TEP_FILTER_ARG_STR: free(arg->str.val); regfree(&arg->str.reg); free(arg->str.buffer); break; - case FILTER_ARG_VALUE: + case TEP_FILTER_ARG_VALUE: if (arg->value.type == FILTER_STRING || arg->value.type == FILTER_CHAR) free(arg->value.str); break; - case FILTER_ARG_OP: + case TEP_FILTER_ARG_OP: free_arg(arg->op.left); free_arg(arg->op.right); default: @@ -349,7 +349,7 @@ create_arg_item(struct tep_event_format *event, const char *token, case TEP_EVENT_SQUOTE: case TEP_EVENT_DQUOTE: - arg->type = FILTER_ARG_VALUE; + arg->type = TEP_FILTER_ARG_VALUE; arg->value.type = type == TEP_EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR; arg->value.str = strdup(token); @@ -362,7 +362,7 @@ create_arg_item(struct tep_event_format *event, const char *token, case TEP_EVENT_ITEM: /* if it is a number, then convert it */ if (isdigit(token[0])) { - arg->type = FILTER_ARG_VALUE; + arg->type = TEP_FILTER_ARG_VALUE; arg->value.type = FILTER_NUMBER; arg->value.val = strtoull(token, NULL, 0); break; @@ -377,12 +377,12 @@ create_arg_item(struct tep_event_format *event, const char *token, field = &cpu; } else { /* not a field, Make it false */ - arg->type = FILTER_ARG_BOOLEAN; + arg->type = TEP_FILTER_ARG_BOOLEAN; arg->boolean.value = TEP_FILTER_FALSE; break; } } - arg->type = FILTER_ARG_FIELD; + arg->type = TEP_FILTER_ARG_FIELD; arg->field.field = field; break; default: @@ -403,14 +403,14 @@ create_arg_op(enum tep_filter_op_type btype) if (!arg) return NULL; - arg->type = FILTER_ARG_OP; + arg->type = TEP_FILTER_ARG_OP; arg->op.type = btype; return arg; } static struct filter_arg * -create_arg_exp(enum filter_exp_type etype) +create_arg_exp(enum tep_filter_exp_type etype) { struct filter_arg *arg; @@ -418,7 +418,7 @@ create_arg_exp(enum filter_exp_type etype) if (!arg) return NULL; - arg->type = FILTER_ARG_EXP; + arg->type = TEP_FILTER_ARG_EXP; arg->exp.type = etype; return arg; @@ -434,7 +434,7 @@ create_arg_cmp(enum tep_filter_cmp_type ctype) return NULL; /* Use NUM and change if necessary */ - arg->type = FILTER_ARG_NUM; + arg->type = TEP_FILTER_ARG_NUM; arg->num.type = ctype; return arg; @@ -449,27 +449,27 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) int ret; switch (op->type) { - case FILTER_ARG_EXP: + case TEP_FILTER_ARG_EXP: if (op->exp.right) goto out_fail; op->exp.right = arg; break; - case FILTER_ARG_OP: + case TEP_FILTER_ARG_OP: if (op->op.right) goto out_fail; op->op.right = arg; break; - case FILTER_ARG_NUM: + case TEP_FILTER_ARG_NUM: if (op->op.right) goto out_fail; /* * The arg must be num, str, or field */ switch (arg->type) { - case FILTER_ARG_VALUE: - case FILTER_ARG_FIELD: + case TEP_FILTER_ARG_VALUE: + case TEP_FILTER_ARG_FIELD: break; default: show_error(error_str, "Illegal rvalue"); @@ -508,16 +508,16 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) * If left arg was a field not found then * NULL the entire op. */ - if (left->type == FILTER_ARG_BOOLEAN) { + if (left->type == TEP_FILTER_ARG_BOOLEAN) { free_arg(left); free_arg(arg); - op->type = FILTER_ARG_BOOLEAN; + op->type = TEP_FILTER_ARG_BOOLEAN; op->boolean.value = TEP_FILTER_FALSE; break; } /* Left arg must be a field */ - if (left->type != FILTER_ARG_FIELD) { + if (left->type != TEP_FILTER_ARG_FIELD) { show_error(error_str, "Illegal lvalue for string comparison"); return TEP_ERRNO__ILLEGAL_LVALUE; @@ -548,7 +548,7 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) return TEP_ERRNO__ILLEGAL_STRING_CMP; } - op->type = FILTER_ARG_STR; + op->type = TEP_FILTER_ARG_STR; op->str.type = op_type; op->str.field = left->field.field; op->str.val = strdup(str); @@ -618,22 +618,22 @@ rotate_op_right(struct filter_arg *a, struct filter_arg *b) static enum tep_errno add_left(struct filter_arg *op, struct filter_arg *arg) { switch (op->type) { - case FILTER_ARG_EXP: - if (arg->type == FILTER_ARG_OP) + case TEP_FILTER_ARG_EXP: + if (arg->type == TEP_FILTER_ARG_OP) arg = rotate_op_right(arg, op); op->exp.left = arg; break; - case FILTER_ARG_OP: + case TEP_FILTER_ARG_OP: op->op.left = arg; break; - case FILTER_ARG_NUM: - if (arg->type == FILTER_ARG_OP) + case TEP_FILTER_ARG_NUM: + if (arg->type == TEP_FILTER_ARG_OP) arg = rotate_op_right(arg, op); /* left arg of compares must be a field */ - if (arg->type != FILTER_ARG_FIELD && - arg->type != FILTER_ARG_BOOLEAN) + if (arg->type != TEP_FILTER_ARG_FIELD && + arg->type != TEP_FILTER_ARG_BOOLEAN) return TEP_ERRNO__INVALID_ARG_TYPE; op->num.left = arg; break; @@ -654,10 +654,10 @@ enum op_type { static enum op_type process_op(const char *token, enum tep_filter_op_type *btype, enum tep_filter_cmp_type *ctype, - enum filter_exp_type *etype) + enum tep_filter_exp_type *etype) { *btype = TEP_FILTER_OP_NOT; - *etype = FILTER_EXP_NONE; + *etype = TEP_FILTER_EXP_NONE; *ctype = TEP_FILTER_CMP_NONE; if (strcmp(token, "&&") == 0) @@ -672,29 +672,29 @@ static enum op_type process_op(const char *token, /* Check for value expressions */ if (strcmp(token, "+") == 0) { - *etype = FILTER_EXP_ADD; + *etype = TEP_FILTER_EXP_ADD; } else if (strcmp(token, "-") == 0) { - *etype = FILTER_EXP_SUB; + *etype = TEP_FILTER_EXP_SUB; } else if (strcmp(token, "*") == 0) { - *etype = FILTER_EXP_MUL; + *etype = TEP_FILTER_EXP_MUL; } else if (strcmp(token, "/") == 0) { - *etype = FILTER_EXP_DIV; + *etype = TEP_FILTER_EXP_DIV; } else if (strcmp(token, "%") == 0) { - *etype = FILTER_EXP_MOD; + *etype = TEP_FILTER_EXP_MOD; } else if (strcmp(token, ">>") == 0) { - *etype = FILTER_EXP_RSHIFT; + *etype = TEP_FILTER_EXP_RSHIFT; } else if (strcmp(token, "<<") == 0) { - *etype = FILTER_EXP_LSHIFT; + *etype = TEP_FILTER_EXP_LSHIFT; } else if (strcmp(token, "&") == 0) { - *etype = FILTER_EXP_AND; + *etype = TEP_FILTER_EXP_AND; } else if (strcmp(token, "|") == 0) { - *etype = FILTER_EXP_OR; + *etype = TEP_FILTER_EXP_OR; } else if (strcmp(token, "^") == 0) { - *etype = FILTER_EXP_XOR; + *etype = TEP_FILTER_EXP_XOR; } else if (strcmp(token, "~") == 0) - *etype = FILTER_EXP_NOT; + *etype = TEP_FILTER_EXP_NOT; - if (*etype != FILTER_EXP_NONE) + if (*etype != TEP_FILTER_EXP_NONE) return OP_EXP; /* Check for compares */ @@ -723,20 +723,20 @@ static enum op_type process_op(const char *token, static int check_op_done(struct filter_arg *arg) { switch (arg->type) { - case FILTER_ARG_EXP: + case TEP_FILTER_ARG_EXP: return arg->exp.right != NULL; - case FILTER_ARG_OP: + case TEP_FILTER_ARG_OP: return arg->op.right != NULL; - case FILTER_ARG_NUM: + case TEP_FILTER_ARG_NUM: return arg->num.right != NULL; - case FILTER_ARG_STR: + case TEP_FILTER_ARG_STR: /* A string conversion is always done */ return 1; - case FILTER_ARG_BOOLEAN: + case TEP_FILTER_ARG_BOOLEAN: /* field not found, is ok */ return 1; @@ -758,8 +758,8 @@ reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, struct filter_arg *other_child; struct filter_arg **ptr; - if (parent->type != FILTER_ARG_OP && - arg->type != FILTER_ARG_OP) { + if (parent->type != TEP_FILTER_ARG_OP && + arg->type != TEP_FILTER_ARG_OP) { show_error(error_str, "can not reparent other than OP"); return TEP_ERRNO__REPARENT_NOT_OP; } @@ -812,16 +812,16 @@ static int test_arg(struct filter_arg *parent, struct filter_arg *arg, switch (arg->type) { /* bad case */ - case FILTER_ARG_BOOLEAN: + case TEP_FILTER_ARG_BOOLEAN: return FILTER_VAL_FALSE + arg->boolean.value; /* good cases: */ - case FILTER_ARG_STR: - case FILTER_ARG_VALUE: - case FILTER_ARG_FIELD: + case TEP_FILTER_ARG_STR: + case TEP_FILTER_ARG_VALUE: + case TEP_FILTER_ARG_FIELD: return FILTER_VAL_NORM; - case FILTER_ARG_EXP: + case TEP_FILTER_ARG_EXP: lval = test_arg(arg, arg->exp.left, error_str); if (lval != FILTER_VAL_NORM) return lval; @@ -830,7 +830,7 @@ static int test_arg(struct filter_arg *parent, struct filter_arg *arg, return rval; return FILTER_VAL_NORM; - case FILTER_ARG_NUM: + case TEP_FILTER_ARG_NUM: lval = test_arg(arg, arg->num.left, error_str); if (lval != FILTER_VAL_NORM) return lval; @@ -839,7 +839,7 @@ static int test_arg(struct filter_arg *parent, struct filter_arg *arg, return rval; return FILTER_VAL_NORM; - case FILTER_ARG_OP: + case TEP_FILTER_ARG_OP: if (arg->op.type != TEP_FILTER_OP_NOT) { lval = test_arg(arg, arg->op.left, error_str); switch (lval) { @@ -919,7 +919,7 @@ static int collapse_tree(struct filter_arg *arg, free_arg(arg); arg = allocate_arg(); if (arg) { - arg->type = FILTER_ARG_BOOLEAN; + arg->type = TEP_FILTER_ARG_BOOLEAN; arg->boolean.value = ret == FILTER_VAL_TRUE; } else { show_error(error_str, "Failed to allocate filter arg"); @@ -950,7 +950,7 @@ process_filter(struct tep_event_format *event, struct filter_arg **parg, struct filter_arg *arg = NULL; enum op_type op_type; enum tep_filter_op_type btype; - enum filter_exp_type etype; + enum tep_filter_exp_type etype; enum tep_filter_cmp_type ctype; enum tep_errno ret; @@ -1196,7 +1196,7 @@ process_event(struct tep_event_format *event, const char *filter_str, if (*parg == NULL) return TEP_ERRNO__MEM_ALLOC_FAILED; - (*parg)->type = FILTER_ARG_BOOLEAN; + (*parg)->type = TEP_FILTER_ARG_BOOLEAN; (*parg)->boolean.value = TEP_FILTER_FALSE; } @@ -1222,7 +1222,7 @@ filter_event(struct event_filter *filter, struct tep_event_format *event, if (arg == NULL) return TEP_ERRNO__MEM_ALLOC_FAILED; - arg->type = FILTER_ARG_BOOLEAN; + arg->type = TEP_FILTER_ARG_BOOLEAN; arg->boolean.value = TEP_FILTER_TRUE; } @@ -1478,7 +1478,7 @@ static int copy_filter_type(struct event_filter *filter, if (arg == NULL) return -1; - arg->type = FILTER_ARG_BOOLEAN; + arg->type = TEP_FILTER_ARG_BOOLEAN; if (strcmp(str, "TRUE") == 0) arg->boolean.value = 1; else @@ -1554,7 +1554,7 @@ int tep_update_trivial(struct event_filter *dest, struct event_filter *source, for (i = 0; i < dest->filters; i++) { filter_type = &dest->event_filters[i]; arg = filter_type->filter; - if (arg->type != FILTER_ARG_BOOLEAN) + if (arg->type != TEP_FILTER_ARG_BOOLEAN) continue; if ((arg->boolean.value && type == FILTER_TRIVIAL_FALSE) || (!arg->boolean.value && type == FILTER_TRIVIAL_TRUE)) @@ -1611,7 +1611,7 @@ int tep_filter_clear_trivial(struct event_filter *filter, int *new_ids; filter_type = &filter->event_filters[i]; - if (filter_type->filter->type != FILTER_ARG_BOOLEAN) + if (filter_type->filter->type != TEP_FILTER_ARG_BOOLEAN) continue; switch (type) { case FILTER_TRIVIAL_FALSE: @@ -1668,7 +1668,7 @@ int tep_filter_event_has_trivial(struct event_filter *filter, if (!filter_type) return 0; - if (filter_type->filter->type != FILTER_ARG_BOOLEAN) + if (filter_type->filter->type != TEP_FILTER_ARG_BOOLEAN) return 0; switch (type) { @@ -1753,37 +1753,37 @@ get_exp_value(struct tep_event_format *event, struct filter_arg *arg, } switch (arg->exp.type) { - case FILTER_EXP_ADD: + case TEP_FILTER_EXP_ADD: return lval + rval; - case FILTER_EXP_SUB: + case TEP_FILTER_EXP_SUB: return lval - rval; - case FILTER_EXP_MUL: + case TEP_FILTER_EXP_MUL: return lval * rval; - case FILTER_EXP_DIV: + case TEP_FILTER_EXP_DIV: return lval / rval; - case FILTER_EXP_MOD: + case TEP_FILTER_EXP_MOD: return lval % rval; - case FILTER_EXP_RSHIFT: + case TEP_FILTER_EXP_RSHIFT: return lval >> rval; - case FILTER_EXP_LSHIFT: + case TEP_FILTER_EXP_LSHIFT: return lval << rval; - case FILTER_EXP_AND: + case TEP_FILTER_EXP_AND: return lval & rval; - case FILTER_EXP_OR: + case TEP_FILTER_EXP_OR: return lval | rval; - case FILTER_EXP_XOR: + case TEP_FILTER_EXP_XOR: return lval ^ rval; - case FILTER_EXP_NOT: + case TEP_FILTER_EXP_NOT: default: if (!*err) *err = TEP_ERRNO__INVALID_EXP_TYPE; @@ -1796,17 +1796,17 @@ get_arg_value(struct tep_event_format *event, struct filter_arg *arg, struct tep_record *record, enum tep_errno *err) { switch (arg->type) { - case FILTER_ARG_FIELD: + case TEP_FILTER_ARG_FIELD: return get_value(event, arg->field.field, record); - case FILTER_ARG_VALUE: + case TEP_FILTER_ARG_VALUE: if (arg->value.type != FILTER_NUMBER) { if (!*err) *err = TEP_ERRNO__NOT_A_NUMBER; } return arg->value.val; - case FILTER_ARG_EXP: + case TEP_FILTER_ARG_EXP: return get_exp_value(event, arg, record, err); default: @@ -1971,22 +1971,22 @@ static int test_filter(struct tep_event_format *event, struct filter_arg *arg, } switch (arg->type) { - case FILTER_ARG_BOOLEAN: + case TEP_FILTER_ARG_BOOLEAN: /* easy case */ return arg->boolean.value; - case FILTER_ARG_OP: + case TEP_FILTER_ARG_OP: return test_op(event, arg, record, err); - case FILTER_ARG_NUM: + case TEP_FILTER_ARG_NUM: return test_num(event, arg, record, err); - case FILTER_ARG_STR: + case TEP_FILTER_ARG_STR: return test_str(event, arg, record, err); - case FILTER_ARG_EXP: - case FILTER_ARG_VALUE: - case FILTER_ARG_FIELD: + case TEP_FILTER_ARG_EXP: + case TEP_FILTER_ARG_VALUE: + case TEP_FILTER_ARG_FIELD: /* * Expressions, fields and values evaluate * to true if they return non zero @@ -2190,34 +2190,34 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg) goto out; switch (arg->exp.type) { - case FILTER_EXP_ADD: + case TEP_FILTER_EXP_ADD: op = "+"; break; - case FILTER_EXP_SUB: + case TEP_FILTER_EXP_SUB: op = "-"; break; - case FILTER_EXP_MUL: + case TEP_FILTER_EXP_MUL: op = "*"; break; - case FILTER_EXP_DIV: + case TEP_FILTER_EXP_DIV: op = "/"; break; - case FILTER_EXP_MOD: + case TEP_FILTER_EXP_MOD: op = "%"; break; - case FILTER_EXP_RSHIFT: + case TEP_FILTER_EXP_RSHIFT: op = ">>"; break; - case FILTER_EXP_LSHIFT: + case TEP_FILTER_EXP_LSHIFT: op = "<<"; break; - case FILTER_EXP_AND: + case TEP_FILTER_EXP_AND: op = "&"; break; - case FILTER_EXP_OR: + case TEP_FILTER_EXP_OR: op = "|"; break; - case FILTER_EXP_XOR: + case TEP_FILTER_EXP_XOR: op = "^"; break; default: @@ -2320,26 +2320,26 @@ static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg) char *str = NULL; switch (arg->type) { - case FILTER_ARG_BOOLEAN: + case TEP_FILTER_ARG_BOOLEAN: asprintf(&str, arg->boolean.value ? "TRUE" : "FALSE"); return str; - case FILTER_ARG_OP: + case TEP_FILTER_ARG_OP: return op_to_str(filter, arg); - case FILTER_ARG_NUM: + case TEP_FILTER_ARG_NUM: return num_to_str(filter, arg); - case FILTER_ARG_STR: + case TEP_FILTER_ARG_STR: return str_to_str(filter, arg); - case FILTER_ARG_VALUE: + case TEP_FILTER_ARG_VALUE: return val_to_str(filter, arg); - case FILTER_ARG_FIELD: + case TEP_FILTER_ARG_FIELD: return field_to_str(filter, arg); - case FILTER_ARG_EXP: + case TEP_FILTER_ARG_EXP: return exp_to_str(filter, arg); default: From 0515ca53caa681ad945fbea218e691e8637b4d7d Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:53 -0400 Subject: [PATCH 112/155] tools lib traceevent: Add prefix tep_ to struct filter_{arg,value_type} In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This adds prefix tep_ to struct filter_arg, enum filter_value_type and all enum's members. Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185723.972818215@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 28 +++---- tools/lib/traceevent/parse-filter.c | 120 ++++++++++++++-------------- 2 files changed, 74 insertions(+), 74 deletions(-) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 5e55c83d43fe..64ce3eb0dcbc 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -819,13 +819,13 @@ enum tep_filter_arg_type { TEP_FILTER_ARG_STR, }; -enum filter_value_type { - FILTER_NUMBER, - FILTER_STRING, - FILTER_CHAR +enum tep_filter_value_type { + TEP_FILTER_NUMBER, + TEP_FILTER_STRING, + TEP_FILTER_CHAR }; -struct fliter_arg; +struct tep_filter_arg; struct filter_arg_boolean { enum tep_filter_boolean_type value; @@ -836,7 +836,7 @@ struct filter_arg_field { }; struct filter_arg_value { - enum filter_value_type type; + enum tep_filter_value_type type; union { char *str; unsigned long long val; @@ -845,20 +845,20 @@ struct filter_arg_value { struct filter_arg_op { enum tep_filter_op_type type; - struct filter_arg *left; - struct filter_arg *right; + struct tep_filter_arg *left; + struct tep_filter_arg *right; }; struct filter_arg_exp { enum tep_filter_exp_type type; - struct filter_arg *left; - struct filter_arg *right; + struct tep_filter_arg *left; + struct tep_filter_arg *right; }; struct filter_arg_num { enum tep_filter_cmp_type type; - struct filter_arg *left; - struct filter_arg *right; + struct tep_filter_arg *left; + struct tep_filter_arg *right; }; struct filter_arg_str { @@ -869,7 +869,7 @@ struct filter_arg_str { regex_t reg; }; -struct filter_arg { +struct tep_filter_arg { enum tep_filter_arg_type type; union { struct filter_arg_boolean boolean; @@ -885,7 +885,7 @@ struct filter_arg { struct filter_type { int event_id; struct tep_event_format *event; - struct filter_arg *filter; + struct tep_filter_arg *filter; }; #define TEP_FILTER_ERROR_BUFSZ 1024 diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index d1e0dd5b63ea..b9ca1b9e14e4 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -180,12 +180,12 @@ struct event_filter *tep_filter_alloc(struct tep_handle *pevent) return filter; } -static struct filter_arg *allocate_arg(void) +static struct tep_filter_arg *allocate_arg(void) { - return calloc(1, sizeof(struct filter_arg)); + return calloc(1, sizeof(struct tep_filter_arg)); } -static void free_arg(struct filter_arg *arg) +static void free_arg(struct tep_filter_arg *arg) { if (!arg) return; @@ -212,8 +212,8 @@ static void free_arg(struct filter_arg *arg) break; case TEP_FILTER_ARG_VALUE: - if (arg->value.type == FILTER_STRING || - arg->value.type == FILTER_CHAR) + if (arg->value.type == TEP_FILTER_STRING || + arg->value.type == TEP_FILTER_CHAR) free(arg->value.str); break; @@ -334,10 +334,10 @@ static void free_events(struct event_list *events) static enum tep_errno create_arg_item(struct tep_event_format *event, const char *token, - enum tep_event_type type, struct filter_arg **parg, char *error_str) + enum tep_event_type type, struct tep_filter_arg **parg, char *error_str) { struct tep_format_field *field; - struct filter_arg *arg; + struct tep_filter_arg *arg; arg = allocate_arg(); if (arg == NULL) { @@ -351,7 +351,7 @@ create_arg_item(struct tep_event_format *event, const char *token, case TEP_EVENT_DQUOTE: arg->type = TEP_FILTER_ARG_VALUE; arg->value.type = - type == TEP_EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR; + type == TEP_EVENT_DQUOTE ? TEP_FILTER_STRING : TEP_FILTER_CHAR; arg->value.str = strdup(token); if (!arg->value.str) { free_arg(arg); @@ -363,7 +363,7 @@ create_arg_item(struct tep_event_format *event, const char *token, /* if it is a number, then convert it */ if (isdigit(token[0])) { arg->type = TEP_FILTER_ARG_VALUE; - arg->value.type = FILTER_NUMBER; + arg->value.type = TEP_FILTER_NUMBER; arg->value.val = strtoull(token, NULL, 0); break; } @@ -394,10 +394,10 @@ create_arg_item(struct tep_event_format *event, const char *token, return 0; } -static struct filter_arg * +static struct tep_filter_arg * create_arg_op(enum tep_filter_op_type btype) { - struct filter_arg *arg; + struct tep_filter_arg *arg; arg = allocate_arg(); if (!arg) @@ -409,10 +409,10 @@ create_arg_op(enum tep_filter_op_type btype) return arg; } -static struct filter_arg * +static struct tep_filter_arg * create_arg_exp(enum tep_filter_exp_type etype) { - struct filter_arg *arg; + struct tep_filter_arg *arg; arg = allocate_arg(); if (!arg) @@ -424,10 +424,10 @@ create_arg_exp(enum tep_filter_exp_type etype) return arg; } -static struct filter_arg * +static struct tep_filter_arg * create_arg_cmp(enum tep_filter_cmp_type ctype) { - struct filter_arg *arg; + struct tep_filter_arg *arg; arg = allocate_arg(); if (!arg) @@ -441,9 +441,9 @@ create_arg_cmp(enum tep_filter_cmp_type ctype) } static enum tep_errno -add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) +add_right(struct tep_filter_arg *op, struct tep_filter_arg *arg, char *error_str) { - struct filter_arg *left; + struct tep_filter_arg *left; char *str; int op_type; int ret; @@ -481,7 +481,7 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) * convert this to a string or regex. */ switch (arg->value.type) { - case FILTER_CHAR: + case TEP_FILTER_CHAR: /* * A char should be converted to number if * the string is 1 byte, and the compare @@ -490,11 +490,11 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) if (strlen(arg->value.str) == 1 && op->num.type != TEP_FILTER_CMP_REGEX && op->num.type != TEP_FILTER_CMP_NOT_REGEX) { - arg->value.type = FILTER_NUMBER; + arg->value.type = TEP_FILTER_NUMBER; goto do_int; } /* fall through */ - case FILTER_STRING: + case TEP_FILTER_STRING: /* convert op to a string arg */ op_type = op->num.type; @@ -573,7 +573,7 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) break; - case FILTER_NUMBER: + case TEP_FILTER_NUMBER: do_int: switch (op->num.type) { @@ -605,17 +605,17 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) return TEP_ERRNO__SYNTAX_ERROR; } -static struct filter_arg * -rotate_op_right(struct filter_arg *a, struct filter_arg *b) +static struct tep_filter_arg * +rotate_op_right(struct tep_filter_arg *a, struct tep_filter_arg *b) { - struct filter_arg *arg; + struct tep_filter_arg *arg; arg = a->op.right; a->op.right = b; return arg; } -static enum tep_errno add_left(struct filter_arg *op, struct filter_arg *arg) +static enum tep_errno add_left(struct tep_filter_arg *op, struct tep_filter_arg *arg) { switch (op->type) { case TEP_FILTER_ARG_EXP: @@ -720,7 +720,7 @@ static enum op_type process_op(const char *token, return OP_CMP; } -static int check_op_done(struct filter_arg *arg) +static int check_op_done(struct tep_filter_arg *arg) { switch (arg->type) { case TEP_FILTER_ARG_EXP: @@ -752,11 +752,11 @@ enum filter_vals { }; static enum tep_errno -reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, - struct filter_arg *arg, char *error_str) +reparent_op_arg(struct tep_filter_arg *parent, struct tep_filter_arg *old_child, + struct tep_filter_arg *arg, char *error_str) { - struct filter_arg *other_child; - struct filter_arg **ptr; + struct tep_filter_arg *other_child; + struct tep_filter_arg **ptr; if (parent->type != TEP_FILTER_ARG_OP && arg->type != TEP_FILTER_ARG_OP) { @@ -804,7 +804,7 @@ reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, } /* Returns either filter_vals (success) or tep_errno (failfure) */ -static int test_arg(struct filter_arg *parent, struct filter_arg *arg, +static int test_arg(struct tep_filter_arg *parent, struct tep_filter_arg *arg, char *error_str) { int lval, rval; @@ -904,8 +904,8 @@ static int test_arg(struct filter_arg *parent, struct filter_arg *arg, } /* Remove any unknown event fields */ -static int collapse_tree(struct filter_arg *arg, - struct filter_arg **arg_collapsed, char *error_str) +static int collapse_tree(struct tep_filter_arg *arg, + struct tep_filter_arg **arg_collapsed, char *error_str) { int ret; @@ -939,15 +939,15 @@ static int collapse_tree(struct filter_arg *arg, } static enum tep_errno -process_filter(struct tep_event_format *event, struct filter_arg **parg, +process_filter(struct tep_event_format *event, struct tep_filter_arg **parg, char *error_str, int not) { enum tep_event_type type; char *token = NULL; - struct filter_arg *current_op = NULL; - struct filter_arg *current_exp = NULL; - struct filter_arg *left_item = NULL; - struct filter_arg *arg = NULL; + struct tep_filter_arg *current_op = NULL; + struct tep_filter_arg *current_exp = NULL; + struct tep_filter_arg *left_item = NULL; + struct tep_filter_arg *arg = NULL; enum op_type op_type; enum tep_filter_op_type btype; enum tep_filter_exp_type etype; @@ -1180,7 +1180,7 @@ process_filter(struct tep_event_format *event, struct filter_arg **parg, static enum tep_errno process_event(struct tep_event_format *event, const char *filter_str, - struct filter_arg **parg, char *error_str) + struct tep_filter_arg **parg, char *error_str) { int ret; @@ -1208,7 +1208,7 @@ filter_event(struct event_filter *filter, struct tep_event_format *event, const char *filter_str, char *error_str) { struct filter_type *filter_type; - struct filter_arg *arg; + struct tep_filter_arg *arg; enum tep_errno ret; if (filter_str) { @@ -1449,13 +1449,13 @@ void tep_filter_free(struct event_filter *filter) free(filter); } -static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg); +static char *arg_to_str(struct event_filter *filter, struct tep_filter_arg *arg); static int copy_filter_type(struct event_filter *filter, struct event_filter *source, struct filter_type *filter_type) { - struct filter_arg *arg; + struct tep_filter_arg *arg; struct tep_event_format *event; const char *sys; const char *name; @@ -1540,7 +1540,7 @@ int tep_update_trivial(struct event_filter *dest, struct event_filter *source, struct tep_handle *dest_pevent; struct tep_event_format *event; struct filter_type *filter_type; - struct filter_arg *arg; + struct tep_filter_arg *arg; char *str; int i; @@ -1682,7 +1682,7 @@ int tep_filter_event_has_trivial(struct event_filter *filter, } } -static int test_filter(struct tep_event_format *event, struct filter_arg *arg, +static int test_filter(struct tep_event_format *event, struct tep_filter_arg *arg, struct tep_record *record, enum tep_errno *err); static const char * @@ -1733,11 +1733,11 @@ get_value(struct tep_event_format *event, } static unsigned long long -get_arg_value(struct tep_event_format *event, struct filter_arg *arg, +get_arg_value(struct tep_event_format *event, struct tep_filter_arg *arg, struct tep_record *record, enum tep_errno *err); static unsigned long long -get_exp_value(struct tep_event_format *event, struct filter_arg *arg, +get_exp_value(struct tep_event_format *event, struct tep_filter_arg *arg, struct tep_record *record, enum tep_errno *err) { unsigned long long lval, rval; @@ -1792,7 +1792,7 @@ get_exp_value(struct tep_event_format *event, struct filter_arg *arg, } static unsigned long long -get_arg_value(struct tep_event_format *event, struct filter_arg *arg, +get_arg_value(struct tep_event_format *event, struct tep_filter_arg *arg, struct tep_record *record, enum tep_errno *err) { switch (arg->type) { @@ -1800,7 +1800,7 @@ get_arg_value(struct tep_event_format *event, struct filter_arg *arg, return get_value(event, arg->field.field, record); case TEP_FILTER_ARG_VALUE: - if (arg->value.type != FILTER_NUMBER) { + if (arg->value.type != TEP_FILTER_NUMBER) { if (!*err) *err = TEP_ERRNO__NOT_A_NUMBER; } @@ -1816,7 +1816,7 @@ get_arg_value(struct tep_event_format *event, struct filter_arg *arg, return 0; } -static int test_num(struct tep_event_format *event, struct filter_arg *arg, +static int test_num(struct tep_event_format *event, struct tep_filter_arg *arg, struct tep_record *record, enum tep_errno *err) { unsigned long long lval, rval; @@ -1857,7 +1857,7 @@ static int test_num(struct tep_event_format *event, struct filter_arg *arg, } } -static const char *get_field_str(struct filter_arg *arg, struct tep_record *record) +static const char *get_field_str(struct tep_filter_arg *arg, struct tep_record *record) { struct tep_event_format *event; struct tep_handle *pevent; @@ -1907,7 +1907,7 @@ static const char *get_field_str(struct filter_arg *arg, struct tep_record *reco return val; } -static int test_str(struct tep_event_format *event, struct filter_arg *arg, +static int test_str(struct tep_event_format *event, struct tep_filter_arg *arg, struct tep_record *record, enum tep_errno *err) { const char *val; @@ -1938,7 +1938,7 @@ static int test_str(struct tep_event_format *event, struct filter_arg *arg, } } -static int test_op(struct tep_event_format *event, struct filter_arg *arg, +static int test_op(struct tep_event_format *event, struct tep_filter_arg *arg, struct tep_record *record, enum tep_errno *err) { switch (arg->op.type) { @@ -1960,7 +1960,7 @@ static int test_op(struct tep_event_format *event, struct filter_arg *arg, } } -static int test_filter(struct tep_event_format *event, struct filter_arg *arg, +static int test_filter(struct tep_event_format *event, struct tep_filter_arg *arg, struct tep_record *record, enum tep_errno *err) { if (*err) { @@ -2059,7 +2059,7 @@ enum tep_errno tep_filter_match(struct event_filter *filter, return ret ? TEP_ERRNO__FILTER_MATCH : TEP_ERRNO__FILTER_MISS; } -static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) +static char *op_to_str(struct event_filter *filter, struct tep_filter_arg *arg) { char *str = NULL; char *left = NULL; @@ -2163,7 +2163,7 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) return str; } -static char *val_to_str(struct event_filter *filter, struct filter_arg *arg) +static char *val_to_str(struct event_filter *filter, struct tep_filter_arg *arg) { char *str = NULL; @@ -2172,12 +2172,12 @@ static char *val_to_str(struct event_filter *filter, struct filter_arg *arg) return str; } -static char *field_to_str(struct event_filter *filter, struct filter_arg *arg) +static char *field_to_str(struct event_filter *filter, struct tep_filter_arg *arg) { return strdup(arg->field.field->name); } -static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg) +static char *exp_to_str(struct event_filter *filter, struct tep_filter_arg *arg) { char *lstr; char *rstr; @@ -2233,7 +2233,7 @@ out: return str; } -static char *num_to_str(struct event_filter *filter, struct filter_arg *arg) +static char *num_to_str(struct event_filter *filter, struct tep_filter_arg *arg) { char *lstr; char *rstr; @@ -2283,7 +2283,7 @@ out: return str; } -static char *str_to_str(struct event_filter *filter, struct filter_arg *arg) +static char *str_to_str(struct event_filter *filter, struct tep_filter_arg *arg) { char *str = NULL; char *op = NULL; @@ -2315,7 +2315,7 @@ static char *str_to_str(struct event_filter *filter, struct filter_arg *arg) return str; } -static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg) +static char *arg_to_str(struct event_filter *filter, struct tep_filter_arg *arg) { char *str = NULL; From 88e6c21a11c5464ebdaefeb18822ab55f37a6473 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:54 -0400 Subject: [PATCH 113/155] tools lib traceevent: Add prefix tep_ to various structs filter_arg_*. In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This adds prefix tep_ to to various structs filter_arg_*.. Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185724.152948543@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 48 +++++++++++++++--------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 64ce3eb0dcbc..1330fca2da1e 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -827,15 +827,15 @@ enum tep_filter_value_type { struct tep_filter_arg; -struct filter_arg_boolean { +struct tep_filter_arg_boolean { enum tep_filter_boolean_type value; }; -struct filter_arg_field { - struct tep_format_field *field; +struct tep_filter_arg_field { + struct tep_format_field *field; }; -struct filter_arg_value { +struct tep_filter_arg_value { enum tep_filter_value_type type; union { char *str; @@ -843,42 +843,42 @@ struct filter_arg_value { }; }; -struct filter_arg_op { - enum tep_filter_op_type type; - struct tep_filter_arg *left; - struct tep_filter_arg *right; +struct tep_filter_arg_op { + enum tep_filter_op_type type; + struct tep_filter_arg *left; + struct tep_filter_arg *right; }; -struct filter_arg_exp { +struct tep_filter_arg_exp { enum tep_filter_exp_type type; struct tep_filter_arg *left; struct tep_filter_arg *right; }; -struct filter_arg_num { +struct tep_filter_arg_num { enum tep_filter_cmp_type type; - struct tep_filter_arg *left; - struct tep_filter_arg *right; + struct tep_filter_arg *left; + struct tep_filter_arg *right; }; -struct filter_arg_str { +struct tep_filter_arg_str { enum tep_filter_cmp_type type; - struct tep_format_field *field; - char *val; - char *buffer; - regex_t reg; + struct tep_format_field *field; + char *val; + char *buffer; + regex_t reg; }; struct tep_filter_arg { enum tep_filter_arg_type type; union { - struct filter_arg_boolean boolean; - struct filter_arg_field field; - struct filter_arg_value value; - struct filter_arg_op op; - struct filter_arg_exp exp; - struct filter_arg_num num; - struct filter_arg_str str; + struct tep_filter_arg_boolean boolean; + struct tep_filter_arg_field field; + struct tep_filter_arg_value value; + struct tep_filter_arg_op op; + struct tep_filter_arg_exp exp; + struct tep_filter_arg_num num; + struct tep_filter_arg_str str; }; }; From 9334c9616b71202c751a12edf5f83f51ec5a1663 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:55 -0400 Subject: [PATCH 114/155] tools lib traceevent: Add prefix tep_ to structs filter_type and event_filter In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This adds prefix tep_ to structs filter_type and event_filter Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185724.309837130@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 34 +++++----- tools/lib/traceevent/parse-filter.c | 96 ++++++++++++++--------------- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 1330fca2da1e..1abf15882460 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -882,7 +882,7 @@ struct tep_filter_arg { }; }; -struct filter_type { +struct tep_filter_type { int event_id; struct tep_event_format *event; struct tep_filter_arg *filter; @@ -890,14 +890,14 @@ struct filter_type { #define TEP_FILTER_ERROR_BUFSZ 1024 -struct event_filter { +struct tep_event_filter { struct tep_handle *pevent; int filters; - struct filter_type *event_filters; + struct tep_filter_type *event_filters; char error_buffer[TEP_FILTER_ERROR_BUFSZ]; }; -struct event_filter *tep_filter_alloc(struct tep_handle *pevent); +struct tep_event_filter *tep_filter_alloc(struct tep_handle *pevent); /* for backward compatibility */ #define FILTER_NONE TEP_ERRNO__NO_FILTER @@ -911,39 +911,39 @@ enum filter_trivial_type { FILTER_TRIVIAL_BOTH, }; -enum tep_errno tep_filter_add_filter_str(struct event_filter *filter, +enum tep_errno tep_filter_add_filter_str(struct tep_event_filter *filter, const char *filter_str); -enum tep_errno tep_filter_match(struct event_filter *filter, +enum tep_errno tep_filter_match(struct tep_event_filter *filter, struct tep_record *record); -int tep_filter_strerror(struct event_filter *filter, enum tep_errno err, +int tep_filter_strerror(struct tep_event_filter *filter, enum tep_errno err, char *buf, size_t buflen); -int tep_event_filtered(struct event_filter *filter, +int tep_event_filtered(struct tep_event_filter *filter, int event_id); -void tep_filter_reset(struct event_filter *filter); +void tep_filter_reset(struct tep_event_filter *filter); -int tep_filter_clear_trivial(struct event_filter *filter, +int tep_filter_clear_trivial(struct tep_event_filter *filter, enum filter_trivial_type type); -void tep_filter_free(struct event_filter *filter); +void tep_filter_free(struct tep_event_filter *filter); -char *tep_filter_make_string(struct event_filter *filter, int event_id); +char *tep_filter_make_string(struct tep_event_filter *filter, int event_id); -int tep_filter_remove_event(struct event_filter *filter, +int tep_filter_remove_event(struct tep_event_filter *filter, int event_id); -int tep_filter_event_has_trivial(struct event_filter *filter, +int tep_filter_event_has_trivial(struct tep_event_filter *filter, int event_id, enum filter_trivial_type type); -int tep_filter_copy(struct event_filter *dest, struct event_filter *source); +int tep_filter_copy(struct tep_event_filter *dest, struct tep_event_filter *source); -int tep_update_trivial(struct event_filter *dest, struct event_filter *source, +int tep_update_trivial(struct tep_event_filter *dest, struct tep_event_filter *source, enum filter_trivial_type type); -int tep_filter_compare(struct event_filter *filter1, struct event_filter *filter2); +int tep_filter_compare(struct tep_event_filter *filter1, struct tep_event_filter *filter2); #endif /* _PARSE_EVENTS_H */ diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index b9ca1b9e14e4..875bfaf79771 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -94,8 +94,8 @@ static enum tep_event_type read_token(char **tok) static int filter_cmp(const void *a, const void *b) { - const struct filter_type *ea = a; - const struct filter_type *eb = b; + const struct tep_filter_type *ea = a; + const struct tep_filter_type *eb = b; if (ea->event_id < eb->event_id) return -1; @@ -106,11 +106,11 @@ static int filter_cmp(const void *a, const void *b) return 0; } -static struct filter_type * -find_filter_type(struct event_filter *filter, int id) +static struct tep_filter_type * +find_filter_type(struct tep_event_filter *filter, int id) { - struct filter_type *filter_type; - struct filter_type key; + struct tep_filter_type *filter_type; + struct tep_filter_type key; key.event_id = id; @@ -122,10 +122,10 @@ find_filter_type(struct event_filter *filter, int id) return filter_type; } -static struct filter_type * -add_filter_type(struct event_filter *filter, int id) +static struct tep_filter_type * +add_filter_type(struct tep_event_filter *filter, int id) { - struct filter_type *filter_type; + struct tep_filter_type *filter_type; int i; filter_type = find_filter_type(filter, id); @@ -165,9 +165,9 @@ add_filter_type(struct event_filter *filter, int id) * tep_filter_alloc - create a new event filter * @pevent: The pevent that this filter is associated with */ -struct event_filter *tep_filter_alloc(struct tep_handle *pevent) +struct tep_event_filter *tep_filter_alloc(struct tep_handle *pevent) { - struct event_filter *filter; + struct tep_event_filter *filter; filter = malloc(sizeof(*filter)); if (filter == NULL) @@ -1204,10 +1204,10 @@ process_event(struct tep_event_format *event, const char *filter_str, } static enum tep_errno -filter_event(struct event_filter *filter, struct tep_event_format *event, +filter_event(struct tep_event_filter *filter, struct tep_event_format *event, const char *filter_str, char *error_str) { - struct filter_type *filter_type; + struct tep_filter_type *filter_type; struct tep_filter_arg *arg; enum tep_errno ret; @@ -1237,7 +1237,7 @@ filter_event(struct event_filter *filter, struct tep_event_format *event, return 0; } -static void filter_init_error_buf(struct event_filter *filter) +static void filter_init_error_buf(struct tep_event_filter *filter) { /* clear buffer to reset show error */ tep_buffer_init("", 0); @@ -1253,7 +1253,7 @@ static void filter_init_error_buf(struct event_filter *filter) * negative error code. Use tep_filter_strerror() to see * actual error message in case of error. */ -enum tep_errno tep_filter_add_filter_str(struct event_filter *filter, +enum tep_errno tep_filter_add_filter_str(struct tep_event_filter *filter, const char *filter_str) { struct tep_handle *pevent = filter->pevent; @@ -1351,7 +1351,7 @@ enum tep_errno tep_filter_add_filter_str(struct event_filter *filter, return rtn; } -static void free_filter_type(struct filter_type *filter_type) +static void free_filter_type(struct tep_filter_type *filter_type) { free_arg(filter_type->filter); } @@ -1365,7 +1365,7 @@ static void free_filter_type(struct filter_type *filter_type) * * Returns 0 if message was filled successfully, -1 if error */ -int tep_filter_strerror(struct event_filter *filter, enum tep_errno err, +int tep_filter_strerror(struct tep_event_filter *filter, enum tep_errno err, char *buf, size_t buflen) { if (err <= __TEP_ERRNO__START || err >= __TEP_ERRNO__END) @@ -1393,10 +1393,10 @@ int tep_filter_strerror(struct event_filter *filter, enum tep_errno err, * Returns 1: if an event was removed * 0: if the event was not found */ -int tep_filter_remove_event(struct event_filter *filter, +int tep_filter_remove_event(struct tep_event_filter *filter, int event_id) { - struct filter_type *filter_type; + struct tep_filter_type *filter_type; unsigned long len; if (!filter->filters) @@ -1428,7 +1428,7 @@ int tep_filter_remove_event(struct event_filter *filter, * * Removes all filters from a filter and resets it. */ -void tep_filter_reset(struct event_filter *filter) +void tep_filter_reset(struct tep_event_filter *filter) { int i; @@ -1440,7 +1440,7 @@ void tep_filter_reset(struct event_filter *filter) filter->event_filters = NULL; } -void tep_filter_free(struct event_filter *filter) +void tep_filter_free(struct tep_event_filter *filter) { tep_unref(filter->pevent); @@ -1449,11 +1449,11 @@ void tep_filter_free(struct event_filter *filter) free(filter); } -static char *arg_to_str(struct event_filter *filter, struct tep_filter_arg *arg); +static char *arg_to_str(struct tep_event_filter *filter, struct tep_filter_arg *arg); -static int copy_filter_type(struct event_filter *filter, - struct event_filter *source, - struct filter_type *filter_type) +static int copy_filter_type(struct tep_event_filter *filter, + struct tep_event_filter *source, + struct tep_filter_type *filter_type) { struct tep_filter_arg *arg; struct tep_event_format *event; @@ -1507,7 +1507,7 @@ static int copy_filter_type(struct event_filter *filter, * * Returns 0 on success and -1 if not all filters were copied */ -int tep_filter_copy(struct event_filter *dest, struct event_filter *source) +int tep_filter_copy(struct tep_event_filter *dest, struct tep_event_filter *source) { int ret = 0; int i; @@ -1533,13 +1533,13 @@ int tep_filter_copy(struct event_filter *dest, struct event_filter *source) * Returns 0 on success and -1 if there was a problem updating, but * events may have still been updated on error. */ -int tep_update_trivial(struct event_filter *dest, struct event_filter *source, +int tep_update_trivial(struct tep_event_filter *dest, struct tep_event_filter *source, enum filter_trivial_type type) { struct tep_handle *src_pevent; struct tep_handle *dest_pevent; struct tep_event_format *event; - struct filter_type *filter_type; + struct tep_filter_type *filter_type; struct tep_filter_arg *arg; char *str; int i; @@ -1592,10 +1592,10 @@ int tep_update_trivial(struct event_filter *dest, struct event_filter *source, * * Returns 0 on success and -1 if there was a problem. */ -int tep_filter_clear_trivial(struct event_filter *filter, +int tep_filter_clear_trivial(struct tep_event_filter *filter, enum filter_trivial_type type) { - struct filter_type *filter_type; + struct tep_filter_type *filter_type; int count = 0; int *ids = NULL; int i; @@ -1654,11 +1654,11 @@ int tep_filter_clear_trivial(struct event_filter *filter, * Returns 1 if the event contains a matching trivial type * otherwise 0. */ -int tep_filter_event_has_trivial(struct event_filter *filter, +int tep_filter_event_has_trivial(struct tep_event_filter *filter, int event_id, enum filter_trivial_type type) { - struct filter_type *filter_type; + struct tep_filter_type *filter_type; if (!filter->filters) return 0; @@ -2008,9 +2008,9 @@ static int test_filter(struct tep_event_format *event, struct tep_filter_arg *ar * Returns 1 if filter found for @event_id * otherwise 0; */ -int tep_event_filtered(struct event_filter *filter, int event_id) +int tep_event_filtered(struct tep_event_filter *filter, int event_id) { - struct filter_type *filter_type; + struct tep_filter_type *filter_type; if (!filter->filters) return 0; @@ -2032,11 +2032,11 @@ int tep_event_filtered(struct event_filter *filter, int event_id) * NO_FILTER - if no filters exist * otherwise - error occurred during test */ -enum tep_errno tep_filter_match(struct event_filter *filter, +enum tep_errno tep_filter_match(struct tep_event_filter *filter, struct tep_record *record) { struct tep_handle *pevent = filter->pevent; - struct filter_type *filter_type; + struct tep_filter_type *filter_type; int event_id; int ret; enum tep_errno err = 0; @@ -2059,7 +2059,7 @@ enum tep_errno tep_filter_match(struct event_filter *filter, return ret ? TEP_ERRNO__FILTER_MATCH : TEP_ERRNO__FILTER_MISS; } -static char *op_to_str(struct event_filter *filter, struct tep_filter_arg *arg) +static char *op_to_str(struct tep_event_filter *filter, struct tep_filter_arg *arg) { char *str = NULL; char *left = NULL; @@ -2163,7 +2163,7 @@ static char *op_to_str(struct event_filter *filter, struct tep_filter_arg *arg) return str; } -static char *val_to_str(struct event_filter *filter, struct tep_filter_arg *arg) +static char *val_to_str(struct tep_event_filter *filter, struct tep_filter_arg *arg) { char *str = NULL; @@ -2172,12 +2172,12 @@ static char *val_to_str(struct event_filter *filter, struct tep_filter_arg *arg) return str; } -static char *field_to_str(struct event_filter *filter, struct tep_filter_arg *arg) +static char *field_to_str(struct tep_event_filter *filter, struct tep_filter_arg *arg) { return strdup(arg->field.field->name); } -static char *exp_to_str(struct event_filter *filter, struct tep_filter_arg *arg) +static char *exp_to_str(struct tep_event_filter *filter, struct tep_filter_arg *arg) { char *lstr; char *rstr; @@ -2233,7 +2233,7 @@ out: return str; } -static char *num_to_str(struct event_filter *filter, struct tep_filter_arg *arg) +static char *num_to_str(struct tep_event_filter *filter, struct tep_filter_arg *arg) { char *lstr; char *rstr; @@ -2283,7 +2283,7 @@ out: return str; } -static char *str_to_str(struct event_filter *filter, struct tep_filter_arg *arg) +static char *str_to_str(struct tep_event_filter *filter, struct tep_filter_arg *arg) { char *str = NULL; char *op = NULL; @@ -2315,7 +2315,7 @@ static char *str_to_str(struct event_filter *filter, struct tep_filter_arg *arg) return str; } -static char *arg_to_str(struct event_filter *filter, struct tep_filter_arg *arg) +static char *arg_to_str(struct tep_event_filter *filter, struct tep_filter_arg *arg) { char *str = NULL; @@ -2359,9 +2359,9 @@ static char *arg_to_str(struct event_filter *filter, struct tep_filter_arg *arg) * NULL is returned if no filter is found or allocation failed. */ char * -tep_filter_make_string(struct event_filter *filter, int event_id) +tep_filter_make_string(struct tep_event_filter *filter, int event_id) { - struct filter_type *filter_type; + struct tep_filter_type *filter_type; if (!filter->filters) return NULL; @@ -2383,10 +2383,10 @@ tep_filter_make_string(struct event_filter *filter, int event_id) * 1 if the two filters hold the same content. * 0 if they do not. */ -int tep_filter_compare(struct event_filter *filter1, struct event_filter *filter2) +int tep_filter_compare(struct tep_event_filter *filter1, struct tep_event_filter *filter2) { - struct filter_type *filter_type1; - struct filter_type *filter_type2; + struct tep_filter_type *filter_type1; + struct tep_filter_type *filter_type2; char *str1, *str2; int result; int i; From 785be0c98d24aaf417588322c74999520ea790a4 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:56 -0400 Subject: [PATCH 115/155] tools lib traceevent: Rename struct plugin_list to struct tep_plugin_list In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This renames struct plugin_list to struct tep_plugin_list Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185724.586889128@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 8 ++++---- tools/lib/traceevent/event-plugin.c | 18 +++++++++--------- tools/perf/util/trace-event.h | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 1abf15882460..2a7b0a857f39 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -389,12 +389,12 @@ enum tep_errno { }; #undef _PE -struct plugin_list; +struct tep_plugin_list; #define INVALID_PLUGIN_LIST_OPTION ((char **)((unsigned long)-1)) -struct plugin_list *tep_load_plugins(struct tep_handle *pevent); -void tep_unload_plugins(struct plugin_list *plugin_list, +struct tep_plugin_list *tep_load_plugins(struct tep_handle *pevent); +void tep_unload_plugins(struct tep_plugin_list *plugin_list, struct tep_handle *pevent); char **tep_plugin_list_options(void); void tep_plugin_free_options_list(char **list); @@ -403,7 +403,7 @@ int tep_plugin_add_options(const char *name, void tep_plugin_remove_options(struct tep_plugin_option *options); void tep_print_plugins(struct trace_seq *s, const char *prefix, const char *suffix, - const struct plugin_list *list); + const struct tep_plugin_list *list); struct cmdline; struct cmdline_list; diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index ec16a103c0cc..46eb64eb0c2e 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -31,8 +31,8 @@ static struct trace_plugin_options { char *value; } *trace_plugin_options; -struct plugin_list { - struct plugin_list *next; +struct tep_plugin_list { + struct tep_plugin_list *next; char *name; void *handle; }; @@ -259,7 +259,7 @@ void tep_plugin_remove_options(struct tep_plugin_option *options) */ void tep_print_plugins(struct trace_seq *s, const char *prefix, const char *suffix, - const struct plugin_list *list) + const struct tep_plugin_list *list) { while (list) { trace_seq_printf(s, "%s%s%s", prefix, list->name, suffix); @@ -271,9 +271,9 @@ static void load_plugin(struct tep_handle *pevent, const char *path, const char *file, void *data) { - struct plugin_list **plugin_list = data; + struct tep_plugin_list **plugin_list = data; tep_plugin_load_func func; - struct plugin_list *list; + struct tep_plugin_list *list; const char *alias; char *plugin; void *handle; @@ -417,20 +417,20 @@ load_plugins(struct tep_handle *pevent, const char *suffix, free(path); } -struct plugin_list* +struct tep_plugin_list* tep_load_plugins(struct tep_handle *pevent) { - struct plugin_list *list = NULL; + struct tep_plugin_list *list = NULL; load_plugins(pevent, ".so", load_plugin, &list); return list; } void -tep_unload_plugins(struct plugin_list *plugin_list, struct tep_handle *pevent) +tep_unload_plugins(struct tep_plugin_list *plugin_list, struct tep_handle *pevent) { tep_plugin_unload_func func; - struct plugin_list *list; + struct tep_plugin_list *list; while (plugin_list) { list = plugin_list; diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 2da6eff0caaf..f024d73bfc40 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -11,11 +11,11 @@ struct perf_sample; union perf_event; struct perf_tool; struct thread; -struct plugin_list; +struct tep_plugin_list; struct trace_event { struct tep_handle *pevent; - struct plugin_list *plugin_list; + struct tep_plugin_list *plugin_list; }; int trace_event__init(struct trace_event *t); From 1affd34f192a516436a2e0cec15a97bc1001678a Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:57 -0400 Subject: [PATCH 116/155] tools lib traceevent: Rename data2host*() APIs In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This renames data2host*() APIs Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185724.751088939@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 10 +++++----- tools/lib/traceevent/event-parse.h | 14 +++++++------- tools/perf/util/trace-event-read.c | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 055bee7b738a..7980fc6c3bac 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -3331,11 +3331,11 @@ unsigned long long tep_read_number(struct tep_handle *pevent, case 1: return *(unsigned char *)ptr; case 2: - return data2host2(pevent, ptr); + return tep_data2host2(pevent, ptr); case 4: - return data2host4(pevent, ptr); + return tep_data2host4(pevent, ptr); case 8: - return data2host8(pevent, ptr); + return tep_data2host8(pevent, ptr); default: /* BUG! */ return 0; @@ -4061,7 +4061,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, f = tep_find_any_field(event, arg->string.string); arg->string.offset = f->offset; } - str_offset = data2host4(pevent, data + arg->string.offset); + str_offset = tep_data2host4(pevent, data + arg->string.offset); str_offset &= 0xffff; print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset); break; @@ -4079,7 +4079,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, f = tep_find_any_field(event, arg->bitmask.bitmask); arg->bitmask.offset = f->offset; } - bitmask_offset = data2host4(pevent, data + arg->bitmask.offset); + bitmask_offset = tep_data2host4(pevent, data + arg->bitmask.offset); bitmask_size = bitmask_offset >> 16; bitmask_offset &= 0xffff; print_bitmask_to_seq(pevent, s, format, len_arg, diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 2a7b0a857f39..830147dc6b21 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -496,7 +496,7 @@ static inline void tep_set_flag(struct tep_handle *pevent, int flag) } static inline unsigned short -__data2host2(struct tep_handle *pevent, unsigned short data) +__tep_data2host2(struct tep_handle *pevent, unsigned short data) { unsigned short swap; @@ -510,7 +510,7 @@ __data2host2(struct tep_handle *pevent, unsigned short data) } static inline unsigned int -__data2host4(struct tep_handle *pevent, unsigned int data) +__tep_data2host4(struct tep_handle *pevent, unsigned int data) { unsigned int swap; @@ -526,7 +526,7 @@ __data2host4(struct tep_handle *pevent, unsigned int data) } static inline unsigned long long -__data2host8(struct tep_handle *pevent, unsigned long long data) +__tep_data2host8(struct tep_handle *pevent, unsigned long long data) { unsigned long long swap; @@ -545,14 +545,14 @@ __data2host8(struct tep_handle *pevent, unsigned long long data) return swap; } -#define data2host2(pevent, ptr) __data2host2(pevent, *(unsigned short *)(ptr)) -#define data2host4(pevent, ptr) __data2host4(pevent, *(unsigned int *)(ptr)) -#define data2host8(pevent, ptr) \ +#define tep_data2host2(pevent, ptr) __tep_data2host2(pevent, *(unsigned short *)(ptr)) +#define tep_data2host4(pevent, ptr) __tep_data2host4(pevent, *(unsigned int *)(ptr)) +#define tep_data2host8(pevent, ptr) \ ({ \ unsigned long long __val; \ \ memcpy(&__val, (ptr), sizeof(unsigned long long)); \ - __data2host8(pevent, __val); \ + __tep_data2host8(pevent, __val); \ }) static inline int tep_host_bigendian(void) diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index 3dfc1db6b25b..b98ee2a2eb44 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -102,7 +102,7 @@ static unsigned int read4(struct tep_handle *pevent) if (do_read(&data, 4) < 0) return 0; - return __data2host4(pevent, data); + return __tep_data2host4(pevent, data); } static unsigned long long read8(struct tep_handle *pevent) @@ -111,7 +111,7 @@ static unsigned long long read8(struct tep_handle *pevent) if (do_read(&data, 8) < 0) return 0; - return __data2host8(pevent, data); + return __tep_data2host8(pevent, data); } static char *read_string(void) From 035c450ffa0483e715fc7b14a2e8b744bf8a740a Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 19 Sep 2018 14:56:58 -0400 Subject: [PATCH 117/155] tools lib traceevent: Add prefix tep_ to enum filter_trivial_type In order to make libtraceevent into a proper library, variables, data structures and functions require a unique prefix to prevent name space conflicts. That prefix will be "tep_". This adds prefix tep_ to enum filter_trivial_type and all its members. Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lkml.kernel.org/r/20180919185725.076387655@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 14 +++++++------- tools/lib/traceevent/parse-filter.c | 22 +++++++++++----------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 830147dc6b21..9c29a5f7aa39 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -905,10 +905,10 @@ struct tep_event_filter *tep_filter_alloc(struct tep_handle *pevent); #define FILTER_MISS TEP_ERRNO__FILTER_MISS #define FILTER_MATCH TEP_ERRNO__FILTER_MATCH -enum filter_trivial_type { - FILTER_TRIVIAL_FALSE, - FILTER_TRIVIAL_TRUE, - FILTER_TRIVIAL_BOTH, +enum tep_filter_trivial_type { + TEP_FILTER_TRIVIAL_FALSE, + TEP_FILTER_TRIVIAL_TRUE, + TEP_FILTER_TRIVIAL_BOTH, }; enum tep_errno tep_filter_add_filter_str(struct tep_event_filter *filter, @@ -926,7 +926,7 @@ int tep_event_filtered(struct tep_event_filter *filter, void tep_filter_reset(struct tep_event_filter *filter); int tep_filter_clear_trivial(struct tep_event_filter *filter, - enum filter_trivial_type type); + enum tep_filter_trivial_type type); void tep_filter_free(struct tep_event_filter *filter); @@ -937,12 +937,12 @@ int tep_filter_remove_event(struct tep_event_filter *filter, int tep_filter_event_has_trivial(struct tep_event_filter *filter, int event_id, - enum filter_trivial_type type); + enum tep_filter_trivial_type type); int tep_filter_copy(struct tep_event_filter *dest, struct tep_event_filter *source); int tep_update_trivial(struct tep_event_filter *dest, struct tep_event_filter *source, - enum filter_trivial_type type); + enum tep_filter_trivial_type type); int tep_filter_compare(struct tep_event_filter *filter1, struct tep_event_filter *filter2); diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 875bfaf79771..d64b6128fa7d 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -1534,7 +1534,7 @@ int tep_filter_copy(struct tep_event_filter *dest, struct tep_event_filter *sour * events may have still been updated on error. */ int tep_update_trivial(struct tep_event_filter *dest, struct tep_event_filter *source, - enum filter_trivial_type type) + enum tep_filter_trivial_type type) { struct tep_handle *src_pevent; struct tep_handle *dest_pevent; @@ -1556,8 +1556,8 @@ int tep_update_trivial(struct tep_event_filter *dest, struct tep_event_filter *s arg = filter_type->filter; if (arg->type != TEP_FILTER_ARG_BOOLEAN) continue; - if ((arg->boolean.value && type == FILTER_TRIVIAL_FALSE) || - (!arg->boolean.value && type == FILTER_TRIVIAL_TRUE)) + if ((arg->boolean.value && type == TEP_FILTER_TRIVIAL_FALSE) || + (!arg->boolean.value && type == TEP_FILTER_TRIVIAL_TRUE)) continue; event = filter_type->event; @@ -1593,7 +1593,7 @@ int tep_update_trivial(struct tep_event_filter *dest, struct tep_event_filter *s * Returns 0 on success and -1 if there was a problem. */ int tep_filter_clear_trivial(struct tep_event_filter *filter, - enum filter_trivial_type type) + enum tep_filter_trivial_type type) { struct tep_filter_type *filter_type; int count = 0; @@ -1614,11 +1614,11 @@ int tep_filter_clear_trivial(struct tep_event_filter *filter, if (filter_type->filter->type != TEP_FILTER_ARG_BOOLEAN) continue; switch (type) { - case FILTER_TRIVIAL_FALSE: + case TEP_FILTER_TRIVIAL_FALSE: if (filter_type->filter->boolean.value) continue; break; - case FILTER_TRIVIAL_TRUE: + case TEP_FILTER_TRIVIAL_TRUE: if (!filter_type->filter->boolean.value) continue; default: @@ -1656,7 +1656,7 @@ int tep_filter_clear_trivial(struct tep_event_filter *filter, */ int tep_filter_event_has_trivial(struct tep_event_filter *filter, int event_id, - enum filter_trivial_type type) + enum tep_filter_trivial_type type) { struct tep_filter_type *filter_type; @@ -1672,10 +1672,10 @@ int tep_filter_event_has_trivial(struct tep_event_filter *filter, return 0; switch (type) { - case FILTER_TRIVIAL_FALSE: + case TEP_FILTER_TRIVIAL_FALSE: return !filter_type->filter->boolean.value; - case FILTER_TRIVIAL_TRUE: + case TEP_FILTER_TRIVIAL_TRUE: return filter_type->filter->boolean.value; default: return 1; @@ -2409,8 +2409,8 @@ int tep_filter_compare(struct tep_event_filter *filter1, struct tep_event_filter if (filter_type1->filter->type != filter_type2->filter->type) break; switch (filter_type1->filter->type) { - case FILTER_TRIVIAL_FALSE: - case FILTER_TRIVIAL_TRUE: + case TEP_FILTER_TRIVIAL_FALSE: + case TEP_FILTER_TRIVIAL_TRUE: /* trivial types just need the type compared */ continue; default: From 62cb1b8868a70c932b15959a98594df537df2ffc Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 20 Sep 2018 16:00:43 +0300 Subject: [PATCH 118/155] perf script: Enhance sample flags for trace begin / end Allow for different combinations of sample flags with "trace begin" or "trace end". Previously, the Intel PT decoder would indicate begin / end by a branch from / to zero. That hides useful information, in particular when a trace ends with a call. Before remedying that, prepare 'perf script' to display sample flags with more combinations that include trace begin / end. In those cases display 'tr start' and 'tr end' separately. Signed-off-by: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20180920130048.31432-2-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 7732346bd9dd..4da5e32b9e03 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1262,6 +1262,18 @@ static struct { {0, NULL} }; +static const char *sample_flags_to_name(u32 flags) +{ + int i; + + for (i = 0; sample_flags[i].name ; i++) { + if (sample_flags[i].flags == flags) + return sample_flags[i].name; + } + + return NULL; +} + static int perf_sample__fprintf_flags(u32 flags, FILE *fp) { const char *chars = PERF_IP_FLAG_CHARS; @@ -1271,11 +1283,20 @@ static int perf_sample__fprintf_flags(u32 flags, FILE *fp) char str[33]; int i, pos = 0; - for (i = 0; sample_flags[i].name ; i++) { - if (sample_flags[i].flags == (flags & ~PERF_IP_FLAG_IN_TX)) { - name = sample_flags[i].name; - break; - } + name = sample_flags_to_name(flags & ~PERF_IP_FLAG_IN_TX); + if (name) + return fprintf(fp, " %-15s%4s ", name, in_tx ? "(x)" : ""); + + if (flags & PERF_IP_FLAG_TRACE_BEGIN) { + name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_BEGIN)); + if (name) + return fprintf(fp, " tr strt %-7s%4s ", name, in_tx ? "(x)" : ""); + } + + if (flags & PERF_IP_FLAG_TRACE_END) { + name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_END)); + if (name) + return fprintf(fp, " tr end %-7s%4s ", name, in_tx ? "(x)" : ""); } for (i = 0; i < n; i++, flags >>= 1) { @@ -1288,10 +1309,7 @@ static int perf_sample__fprintf_flags(u32 flags, FILE *fp) } str[pos] = 0; - if (name) - return fprintf(fp, " %-7s%4s ", name, in_tx ? "(x)" : ""); - - return fprintf(fp, " %-11s ", str); + return fprintf(fp, " %-19s ", str); } struct printer_data { From ff645daf30cafb6fa74bee9a73733700bac2aff7 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 20 Sep 2018 16:00:44 +0300 Subject: [PATCH 119/155] perf db-export: Add trace begin / end branch type variants Add branch types to cover different combinations with "trace begin" or "trace end". Previously, the Intel PT decoder would indicate begin / end by a branch from / to zero. That hides useful information, in particular when a trace ends with a call. Before remedying that, prepare the database export to export branch types with more combinations that include trace begin / end. In those cases extend the descriptions to include 'trace begin' and 'trace end' separately. Signed-off-by: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20180920130048.31432-3-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/db-export.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c index 7123746edcf4..69fbb0a72d0c 100644 --- a/tools/perf/util/db-export.c +++ b/tools/perf/util/db-export.c @@ -463,6 +463,28 @@ int db_export__branch_types(struct db_export *dbe) if (err) break; } + + /* Add trace begin / end variants */ + for (i = 0; branch_types[i].name ; i++) { + const char *name = branch_types[i].name; + u32 type = branch_types[i].branch_type; + char buf[64]; + + if (type == PERF_IP_FLAG_BRANCH || + (type & (PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END))) + continue; + + snprintf(buf, sizeof(buf), "trace begin / %s", name); + err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_BEGIN, buf); + if (err) + break; + + snprintf(buf, sizeof(buf), "%s / trace end", name); + err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_END, buf); + if (err) + break; + } + return err; } From 4d60e5e36aa6f11b4d9eadc5d2b94128f24870c7 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 20 Sep 2018 16:00:45 +0300 Subject: [PATCH 120/155] perf tools: Improve thread_stack__event() for trace begin / end thread_stack__event() is used to create call stacks, by keeping track of calls and returns. Improve the handling of trace begin / end to allow for a trace that ends in a call. Previously, the Intel PT decoder would indicate begin / end by a branch from / to zero. That hides useful information, in particular when a trace ends with a call. Before remedying that, enhance the thread stack so that it does not expect to see the 'return' for a 'call' that ends the trace. Committer notes: Added this: return thread_stack__push(thread->ts, ret_addr, - flags && PERF_IP_FLAG_TRACE_END); + flags & PERF_IP_FLAG_TRACE_END); To fix problem spotted by: debian:9: clang version 3.8.1-24 (tags/RELEASE_381/final) debian:experimental: clang version 6.0.1-6 (tags/RELEASE_601/final) Signed-off-by: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20180920130048.31432-4-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread-stack.c | 35 +++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c index dd17d6a38d3a..e3f7dfecafa9 100644 --- a/tools/perf/util/thread-stack.c +++ b/tools/perf/util/thread-stack.c @@ -36,6 +36,7 @@ * @branch_count: the branch count when the entry was created * @cp: call path * @no_call: a 'call' was not seen + * @trace_end: a 'call' but trace ended */ struct thread_stack_entry { u64 ret_addr; @@ -44,6 +45,7 @@ struct thread_stack_entry { u64 branch_count; struct call_path *cp; bool no_call; + bool trace_end; }; /** @@ -112,7 +114,8 @@ static struct thread_stack *thread_stack__new(struct thread *thread, return ts; } -static int thread_stack__push(struct thread_stack *ts, u64 ret_addr) +static int thread_stack__push(struct thread_stack *ts, u64 ret_addr, + bool trace_end) { int err = 0; @@ -124,6 +127,7 @@ static int thread_stack__push(struct thread_stack *ts, u64 ret_addr) } } + ts->stack[ts->cnt].trace_end = trace_end; ts->stack[ts->cnt++].ret_addr = ret_addr; return err; @@ -150,6 +154,18 @@ static void thread_stack__pop(struct thread_stack *ts, u64 ret_addr) } } +static void thread_stack__pop_trace_end(struct thread_stack *ts) +{ + size_t i; + + for (i = ts->cnt; i; ) { + if (ts->stack[--i].trace_end) + ts->cnt = i; + else + return; + } +} + static bool thread_stack__in_kernel(struct thread_stack *ts) { if (!ts->cnt) @@ -254,10 +270,19 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip, ret_addr = from_ip + insn_len; if (ret_addr == to_ip) return 0; /* Zero-length calls are excluded */ - return thread_stack__push(thread->ts, ret_addr); - } else if (flags & PERF_IP_FLAG_RETURN) { - if (!from_ip) - return 0; + return thread_stack__push(thread->ts, ret_addr, + flags & PERF_IP_FLAG_TRACE_END); + } else if (flags & PERF_IP_FLAG_TRACE_BEGIN) { + /* + * If the caller did not change the trace number (which would + * have flushed the stack) then try to make sense of the stack. + * Possibly, tracing began after returning to the current + * address, so try to pop that. Also, do not expect a call made + * when the trace ended, to return, so pop that. + */ + thread_stack__pop(thread->ts, to_ip); + thread_stack__pop_trace_end(thread->ts); + } else if ((flags & PERF_IP_FLAG_RETURN) && from_ip) { thread_stack__pop(thread->ts, to_ip); } From 2dcde4e152a3e319cc7e76c7c6b8548a3c72310d Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 20 Sep 2018 16:00:46 +0300 Subject: [PATCH 121/155] perf tools: Improve thread_stack__process() for trace begin / end thread_stack__process() is used to create call paths for database export. Improve the handling of trace begin / end to allow for a trace that ends in a call. Previously, the Intel PT decoder would indicate begin / end by a branch from / to zero. That hides useful information, in particular when a trace ends with a call. Before remedying that, enhance the thread stack so that it identifies the trace end by the flag instead of by ip == 0. Signed-off-by: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20180920130048.31432-5-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread-stack.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c index e3f7dfecafa9..c091635bf7dc 100644 --- a/tools/perf/util/thread-stack.c +++ b/tools/perf/util/thread-stack.c @@ -357,7 +357,7 @@ void call_return_processor__free(struct call_return_processor *crp) static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr, u64 timestamp, u64 ref, struct call_path *cp, - bool no_call) + bool no_call, bool trace_end) { struct thread_stack_entry *tse; int err; @@ -375,6 +375,7 @@ static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr, tse->branch_count = ts->branch_count; tse->cp = cp; tse->no_call = no_call; + tse->trace_end = trace_end; return 0; } @@ -448,7 +449,7 @@ static int thread_stack__bottom(struct thread *thread, struct thread_stack *ts, return -ENOMEM; return thread_stack__push_cp(thread->ts, ip, sample->time, ref, cp, - true); + true, false); } static int thread_stack__no_call_return(struct thread *thread, @@ -480,7 +481,7 @@ static int thread_stack__no_call_return(struct thread *thread, if (!cp) return -ENOMEM; return thread_stack__push_cp(ts, 0, sample->time, ref, - cp, true); + cp, true, false); } } else if (thread_stack__in_kernel(ts) && sample->ip < ks) { /* Return to userspace, so pop all kernel addresses */ @@ -505,7 +506,7 @@ static int thread_stack__no_call_return(struct thread *thread, return -ENOMEM; err = thread_stack__push_cp(ts, sample->addr, sample->time, ref, cp, - true); + true, false); if (err) return err; @@ -525,7 +526,7 @@ static int thread_stack__trace_begin(struct thread *thread, /* Pop trace end */ tse = &ts->stack[ts->cnt - 1]; - if (tse->cp->sym == NULL && tse->cp->ip == 0) { + if (tse->trace_end) { err = thread_stack__call_return(thread, ts, --ts->cnt, timestamp, ref, false); if (err) @@ -554,7 +555,7 @@ static int thread_stack__trace_end(struct thread_stack *ts, ret_addr = sample->ip + sample->insn_len; return thread_stack__push_cp(ts, ret_addr, sample->time, ref, cp, - false); + false, true); } int thread_stack__process(struct thread *thread, struct comm *comm, @@ -604,6 +605,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm, ts->last_time = sample->time; if (sample->flags & PERF_IP_FLAG_CALL) { + bool trace_end = sample->flags & PERF_IP_FLAG_TRACE_END; struct call_path_root *cpr = ts->crp->cpr; struct call_path *cp; u64 ret_addr; @@ -621,7 +623,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm, if (!cp) return -ENOMEM; err = thread_stack__push_cp(ts, ret_addr, sample->time, ref, - cp, false); + cp, false, trace_end); } else if (sample->flags & PERF_IP_FLAG_RETURN) { if (!sample->ip || !sample->addr) return 0; From c6b5da093a8ba740b71dd0052f3846016986fd21 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 20 Sep 2018 16:00:47 +0300 Subject: [PATCH 122/155] perf intel-pt: Add decoder flags for trace begin / end Previously, the decoder would indicate begin / end by a branch from / to zero. That hides useful information, in particular when a trace ends with a call. To prepare for remedying that, add Intel PT decoder flags for trace begin / end and map them to the existing sample flags. Signed-off-by: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20180920130048.31432-6-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/intel-pt-decoder/intel-pt-decoder.h | 2 ++ tools/perf/util/intel-pt.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h index 51c18d67f4ca..ed088d4726ba 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h @@ -37,6 +37,8 @@ enum intel_pt_sample_type { INTEL_PT_EX_STOP = 1 << 6, INTEL_PT_PWR_EXIT = 1 << 7, INTEL_PT_CBR_CHG = 1 << 8, + INTEL_PT_TRACE_BEGIN = 1 << 9, + INTEL_PT_TRACE_END = 1 << 10, }; enum intel_pt_period_type { diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index aec68908d604..48c1d415c6b0 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -908,6 +908,11 @@ static void intel_pt_sample_flags(struct intel_pt_queue *ptq) ptq->insn_len = ptq->state->insn_len; memcpy(ptq->insn, ptq->state->insn, INTEL_PT_INSN_BUF_SZ); } + + if (ptq->state->type & INTEL_PT_TRACE_BEGIN) + ptq->flags |= PERF_IP_FLAG_TRACE_BEGIN; + if (ptq->state->type & INTEL_PT_TRACE_END) + ptq->flags |= PERF_IP_FLAG_TRACE_END; } static int intel_pt_setup_queue(struct intel_pt *pt, From bea6385789b8b5e1e3228a281978ca6c4a8c70a0 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 20 Sep 2018 16:00:48 +0300 Subject: [PATCH 123/155] perf intel-pt: Implement decoder flags for trace begin / end Have the Intel PT decoder implement the new Intel PT decoder flags for trace begin / end. Previously, the decoder would indicate begin / end by a branch from / to zero. That hides useful information, in particular when a trace ends with a call. That happens when using address filters, for example: $ perf record -e intel_pt/cyc,mtc_period=0,noretcomp/u --filter='filter main @ /bin/uname ' uname Linux [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.031 MB perf.data ] Before: $ perf script --itrace=cre -Ftime,flags,ip,sym,symoff,addr --ns 7249.622183310: tr strt 0 [unknown] => 401590 main+0x0 7249.622183311: call 4015b9 main+0x29 => 0 [unknown] 7249.622183711: tr strt 0 [unknown] => 4015be main+0x2e 7249.622183714: call 4015c8 main+0x38 => 0 [unknown] 7249.622247731: tr strt 0 [unknown] => 4015cd main+0x3d 7249.622247760: call 4015d7 main+0x47 => 0 [unknown] 7249.622248340: tr strt 0 [unknown] => 4015dc main+0x4c 7249.622248341: call 4015e1 main+0x51 => 0 [unknown] 7249.622248681: tr strt 0 [unknown] => 4015e6 main+0x56 7249.622248682: call 4015eb main+0x5b => 0 [unknown] 7249.622248970: tr strt 0 [unknown] => 4015f0 main+0x60 7249.622248971: call 401612 main+0x82 => 0 [unknown] 7249.622249757: tr strt 0 [unknown] => 401617 main+0x87 7249.622249770: call 401847 main+0x2b7 => 0 [unknown] 7249.622250606: tr strt 0 [unknown] => 40184c main+0x2bc 7249.622250612: call 4019bf main+0x42f => 0 [unknown] 7249.622256823: tr strt 0 [unknown] => 4019c4 main+0x434 7249.622256863: call 4019f5 main+0x465 => 0 [unknown] 7249.622264217: tr strt 0 [unknown] => 4019fa main+0x46a 7249.622264235: call 401832 main+0x2a2 => 0 [unknown] After: $ perf script --itrace=cre -Ftime,flags,ip,sym,symoff,addr --ns 7249.622183310: tr strt 0 [unknown] => 401590 main+0x0 7249.622183311: tr end call 4015b9 main+0x29 => 401ef0 set_program_name+0x0 7249.622183711: tr strt 0 [unknown] => 4015be main+0x2e 7249.622183714: tr end call 4015c8 main+0x38 => 4014b0 setlocale@plt+0x0 7249.622247731: tr strt 0 [unknown] => 4015cd main+0x3d 7249.622247760: tr end call 4015d7 main+0x47 => 4012d0 bindtextdomain@plt+0x0 7249.622248340: tr strt 0 [unknown] => 4015dc main+0x4c 7249.622248341: tr end call 4015e1 main+0x51 => 4012b0 textdomain@plt+0x0 7249.622248681: tr strt 0 [unknown] => 4015e6 main+0x56 7249.622248682: tr end call 4015eb main+0x5b => 404340 atexit+0x0 7249.622248970: tr strt 0 [unknown] => 4015f0 main+0x60 7249.622248971: tr end call 401612 main+0x82 => 401320 getopt_long@plt+0x0 7249.622249757: tr strt 0 [unknown] => 401617 main+0x87 7249.622249770: tr end call 401847 main+0x2b7 => 401360 uname@plt+0x0 7249.622250606: tr strt 0 [unknown] => 40184c main+0x2bc 7249.622250612: tr end call 4019bf main+0x42f => 401b10 print_element+0x0 7249.622256823: tr strt 0 [unknown] => 4019c4 main+0x434 7249.622256863: tr end call 4019f5 main+0x465 => 401340 __overflow@plt+0x0 7249.622264217: tr strt 0 [unknown] => 4019fa main+0x46a 7249.622264235: tr end call 401832 main+0x2a2 => 401520 exit@plt+0x0 Signed-off-by: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20180920130048.31432-7-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- .../util/intel-pt-decoder/intel-pt-decoder.c | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index d404bed7003a..58f6a9ceb590 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -1165,7 +1165,7 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder) decoder->pge = false; decoder->continuous_period = false; decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; - decoder->state.to_ip = 0; + decoder->state.type |= INTEL_PT_TRACE_END; return 0; } if (err == INTEL_PT_RETURN) @@ -1179,9 +1179,13 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder) decoder->continuous_period = false; decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; decoder->state.from_ip = decoder->ip; - decoder->state.to_ip = 0; - if (decoder->packet.count != 0) + if (decoder->packet.count == 0) { + decoder->state.to_ip = 0; + } else { + decoder->state.to_ip = decoder->last_ip; decoder->ip = decoder->last_ip; + } + decoder->state.type |= INTEL_PT_TRACE_END; } else { decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; decoder->state.from_ip = decoder->ip; @@ -1208,7 +1212,8 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder) decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; decoder->ip = to_ip; decoder->state.from_ip = decoder->ip; - decoder->state.to_ip = 0; + decoder->state.to_ip = to_ip; + decoder->state.type |= INTEL_PT_TRACE_END; return 0; } intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch", @@ -1640,14 +1645,15 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder) case INTEL_PT_TIP_PGD: decoder->state.from_ip = decoder->ip; - decoder->state.to_ip = 0; - if (decoder->packet.count != 0) { + if (decoder->packet.count == 0) { + decoder->state.to_ip = 0; + } else { intel_pt_set_ip(decoder); - intel_pt_log("Omitting PGD ip " x64_fmt "\n", - decoder->ip); + decoder->state.to_ip = decoder->ip; } decoder->pge = false; decoder->continuous_period = false; + decoder->state.type |= INTEL_PT_TRACE_END; return 0; case INTEL_PT_TIP_PGE: @@ -1661,6 +1667,7 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder) intel_pt_set_ip(decoder); decoder->state.to_ip = decoder->ip; } + decoder->state.type |= INTEL_PT_TRACE_BEGIN; return 0; case INTEL_PT_TIP: @@ -1739,6 +1746,7 @@ next: intel_pt_set_ip(decoder); decoder->state.from_ip = 0; decoder->state.to_ip = decoder->ip; + decoder->state.type |= INTEL_PT_TRACE_BEGIN; return 0; } @@ -2077,9 +2085,13 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD; if (intel_pt_have_ip(decoder)) intel_pt_set_ip(decoder); - if (decoder->ip) - return 0; - break; + if (!decoder->ip) + break; + if (decoder->packet.type == INTEL_PT_TIP_PGE) + decoder->state.type |= INTEL_PT_TRACE_BEGIN; + if (decoder->packet.type == INTEL_PT_TIP_PGD) + decoder->state.type |= INTEL_PT_TRACE_END; + return 0; case INTEL_PT_FUP: if (intel_pt_have_ip(decoder)) From d35c595bf0053b7df80ef9d44140ac5da6cc698b Mon Sep 17 00:00:00 2001 From: Sean V Kelley Date: Sun, 16 Sep 2018 15:12:03 -0700 Subject: [PATCH 124/155] perf vendor events arm64: Revise core JSON events for eMAG Split the PMU events into meaningful functional groups. Update core pmu events based on supported ARMv8 recommended IMPLEMENTATION DEFINED events. The JSON files are updated with reference to a PMU table shared here: https://github.com/AmpereComputing/ampere-centos-kernel/blob/amp-centos-7.5-kernel/Documentation/arm64/eMAG-ARM-CoreImpDefined.pdf Changes in v3: - Removed CHAIN event as it wouldn't be useful in Perf - William - Will factor out events 0x00-0x38 in a follow-on patch - William - to armv8-recommended.json Changes in V2: - Provided documentation for changes - John, William - Broke up into meaningful groups - William Signed-off-by: Sean V Kelley Reviewed-by: William Cohen Cc: John Garry Cc: linux-arm-kernel@lists.infradead.org LPU-Reference: 20180916221203.7935-1-seanvk.dev@oregontracks.org Link: https://lkml.kernel.org/n/tip-tzvs1ip6srcv2et0ny58e0wy@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- .../arch/arm64/ampere/emag/branch.json | 23 +++ .../arch/arm64/ampere/emag/bus.json | 26 +++ .../arch/arm64/ampere/emag/cache.json | 191 ++++++++++++++++++ .../arch/arm64/ampere/emag/clock.json | 20 ++ .../arch/arm64/ampere/emag/core-imp-def.json | 32 --- .../arch/arm64/ampere/emag/exception.json | 50 +++++ .../arch/arm64/ampere/emag/instruction.json | 89 ++++++++ .../arch/arm64/ampere/emag/intrinsic.json | 14 ++ .../arch/arm64/ampere/emag/memory.json | 29 +++ .../arch/arm64/ampere/emag/pipeline.json | 50 +++++ 10 files changed, 492 insertions(+), 32 deletions(-) create mode 100644 tools/perf/pmu-events/arch/arm64/ampere/emag/branch.json create mode 100644 tools/perf/pmu-events/arch/arm64/ampere/emag/bus.json create mode 100644 tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json create mode 100644 tools/perf/pmu-events/arch/arm64/ampere/emag/clock.json delete mode 100644 tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json create mode 100644 tools/perf/pmu-events/arch/arm64/ampere/emag/exception.json create mode 100644 tools/perf/pmu-events/arch/arm64/ampere/emag/instruction.json create mode 100644 tools/perf/pmu-events/arch/arm64/ampere/emag/intrinsic.json create mode 100644 tools/perf/pmu-events/arch/arm64/ampere/emag/memory.json create mode 100644 tools/perf/pmu-events/arch/arm64/ampere/emag/pipeline.json diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/branch.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/branch.json new file mode 100644 index 000000000000..abc98b018446 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/branch.json @@ -0,0 +1,23 @@ +[ + { + "ArchStdEvent": "BR_IMMED_SPEC", + }, + { + "ArchStdEvent": "BR_RETURN_SPEC", + }, + { + "ArchStdEvent": "BR_INDIRECT_SPEC", + }, + { + "PublicDescription": "Mispredicted or not predicted branch speculatively executed", + "EventCode": "0x10", + "EventName": "BR_MIS_PRED", + "BriefDescription": "Branch mispredicted" + }, + { + "PublicDescription": "Predictable branch speculatively executed", + "EventCode": "0x12", + "EventName": "BR_PRED", + "BriefDescription": "Predictable branch" + }, +] diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/bus.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/bus.json new file mode 100644 index 000000000000..687b2629e1d1 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/bus.json @@ -0,0 +1,26 @@ +[ + { + "ArchStdEvent": "BUS_ACCESS_RD", + }, + { + "ArchStdEvent": "BUS_ACCESS_WR", + }, + { + "ArchStdEvent": "BUS_ACCESS_SHARED", + }, + { + "ArchStdEvent": "BUS_ACCESS_NOT_SHARED", + }, + { + "ArchStdEvent": "BUS_ACCESS_NORMAL", + }, + { + "ArchStdEvent": "BUS_ACCESS_PERIPH", + }, + { + "PublicDescription": "Bus access", + "EventCode": "0x19", + "EventName": "BUS_ACCESS", + "BriefDescription": "Bus access" + }, +] diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json new file mode 100644 index 000000000000..df9201434cb6 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json @@ -0,0 +1,191 @@ +[ + { + "ArchStdEvent": "L1D_CACHE_RD", + }, + { + "ArchStdEvent": "L1D_CACHE_WR", + }, + { + "ArchStdEvent": "L1D_CACHE_REFILL_RD", + }, + { + "ArchStdEvent": "L1D_CACHE_INVAL", + }, + { + "ArchStdEvent": "L1D_TLB_REFILL_RD", + }, + { + "ArchStdEvent": "L1D_TLB_REFILL_WR", + }, + { + "ArchStdEvent": "L2D_CACHE_RD", + }, + { + "ArchStdEvent": "L2D_CACHE_WR", + }, + { + "ArchStdEvent": "L2D_CACHE_REFILL_RD", + }, + { + "ArchStdEvent": "L2D_CACHE_REFILL_WR", + }, + { + "ArchStdEvent": "L2D_CACHE_WB_VICTIM", + }, + { + "ArchStdEvent": "L2D_CACHE_WB_CLEAN", + }, + { + "ArchStdEvent": "L2D_CACHE_INVAL", + }, + { + "PublicDescription": "Level 1 instruction cache refill", + "EventCode": "0x01", + "EventName": "L1I_CACHE_REFILL", + "BriefDescription": "L1I cache refill" + }, + { + "PublicDescription": "Level 1 instruction TLB refill", + "EventCode": "0x02", + "EventName": "L1I_TLB_REFILL", + "BriefDescription": "L1I TLB refill" + }, + { + "PublicDescription": "Level 1 data cache refill", + "EventCode": "0x03", + "EventName": "L1D_CACHE_REFILL", + "BriefDescription": "L1D cache refill" + }, + { + "PublicDescription": "Level 1 data cache access", + "EventCode": "0x04", + "EventName": "L1D_CACHE_ACCESS", + "BriefDescription": "L1D cache access" + }, + { + "PublicDescription": "Level 1 data TLB refill", + "EventCode": "0x05", + "EventName": "L1D_TLB_REFILL", + "BriefDescription": "L1D TLB refill" + }, + { + "PublicDescription": "Level 1 instruction cache access", + "EventCode": "0x14", + "EventName": "L1I_CACHE_ACCESS", + "BriefDescription": "L1I cache access" + }, + { + "PublicDescription": "Level 2 data cache access", + "EventCode": "0x16", + "EventName": "L2D_CACHE_ACCESS", + "BriefDescription": "L2D cache access" + }, + { + "PublicDescription": "Level 2 data refill", + "EventCode": "0x17", + "EventName": "L2D_CACHE_REFILL", + "BriefDescription": "L2D cache refill" + }, + { + "PublicDescription": "Level 2 data cache, Write-Back", + "EventCode": "0x18", + "EventName": "L2D_CACHE_WB", + "BriefDescription": "L2D cache Write-Back" + }, + { + "PublicDescription": "Level 1 data TLB access. This event counts any load or store operation which accesses the data L1 TLB", + "EventCode": "0x25", + "EventName": "L1D_TLB_ACCESS", + "BriefDescription": "L1D TLB access" + }, + { + "PublicDescription": "Level 1 instruction TLB access. This event counts any instruction fetch which accesses the instruction L1 TLB", + "EventCode": "0x26", + "EventName": "L1I_TLB_ACCESS", + "BriefDescription": "L1I TLB access" + }, + { + "PublicDescription": "Level 2 access to data TLB that caused a page table walk. This event counts on any data access which causes L2D_TLB_REFILL to count", + "EventCode": "0x34", + "EventName": "L2D_TLB_ACCESS", + "BriefDescription": "L2D TLB access" + }, + { + "PublicDescription": "Level 2 access to instruciton TLB that caused a page table walk. This event counts on any instruciton access which causes L2I_TLB_REFILL to count", + "EventCode": "0x35", + "EventName": "L2I_TLB_ACCESS", + "BriefDescription": "L2D TLB access" + }, + { + "PublicDescription": "Branch target buffer misprediction", + "EventCode": "0x102", + "EventName": "BTB_MIS_PRED", + "BriefDescription": "BTB misprediction" + }, + { + "PublicDescription": "ITB miss", + "EventCode": "0x103", + "EventName": "ITB_MISS", + "BriefDescription": "ITB miss" + }, + { + "PublicDescription": "DTB miss", + "EventCode": "0x104", + "EventName": "DTB_MISS", + "BriefDescription": "DTB miss" + }, + { + "PublicDescription": "Level 1 data cache late miss", + "EventCode": "0x105", + "EventName": "L1D_CACHE_LATE_MISS", + "BriefDescription": "L1D cache late miss" + }, + { + "PublicDescription": "Level 1 data cache prefetch request", + "EventCode": "0x106", + "EventName": "L1D_CACHE_PREFETCH", + "BriefDescription": "L1D cache prefetch" + }, + { + "PublicDescription": "Level 2 data cache prefetch request", + "EventCode": "0x107", + "EventName": "L2D_CACHE_PREFETCH", + "BriefDescription": "L2D cache prefetch" + }, + { + "PublicDescription": "Level 1 stage 2 TLB refill", + "EventCode": "0x111", + "EventName": "L1_STAGE2_TLB_REFILL", + "BriefDescription": "L1 stage 2 TLB refill" + }, + { + "PublicDescription": "Page walk cache level-0 stage-1 hit", + "EventCode": "0x112", + "EventName": "PAGE_WALK_L0_STAGE1_HIT", + "BriefDescription": "Page walk, L0 stage-1 hit" + }, + { + "PublicDescription": "Page walk cache level-1 stage-1 hit", + "EventCode": "0x113", + "EventName": "PAGE_WALK_L1_STAGE1_HIT", + "BriefDescription": "Page walk, L1 stage-1 hit" + }, + { + "PublicDescription": "Page walk cache level-2 stage-1 hit", + "EventCode": "0x114", + "EventName": "PAGE_WALK_L2_STAGE1_HIT", + "BriefDescription": "Page walk, L2 stage-1 hit" + }, + { + "PublicDescription": "Page walk cache level-1 stage-2 hit", + "EventCode": "0x115", + "EventName": "PAGE_WALK_L1_STAGE2_HIT", + "BriefDescription": "Page walk, L1 stage-2 hit" + }, + { + "PublicDescription": "Page walk cache level-2 stage-2 hit", + "EventCode": "0x116", + "EventName": "PAGE_WALK_L2_STAGE2_HIT", + "BriefDescription": "Page walk, L2 stage-2 hit" + }, +] diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/clock.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/clock.json new file mode 100644 index 000000000000..38cd1f1a70dc --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/clock.json @@ -0,0 +1,20 @@ +[ + { + "PublicDescription": "The number of core clock cycles", + "EventCode": "0x11", + "EventName": "CPU_CYCLES", + "BriefDescription": "Clock cycles" + }, + { + "PublicDescription": "FSU clocking gated off cycle", + "EventCode": "0x101", + "EventName": "FSU_CLOCK_OFF_CYCLES", + "BriefDescription": "FSU clocking gated off cycle" + }, + { + "PublicDescription": "Wait state cycle", + "EventCode": "0x110", + "EventName": "Wait_CYCLES", + "BriefDescription": "Wait state cycle" + }, +] diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json deleted file mode 100644 index bc03c06c3918..000000000000 --- a/tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "ArchStdEvent": "L1D_CACHE_RD", - }, - { - "ArchStdEvent": "L1D_CACHE_WR", - }, - { - "ArchStdEvent": "L1D_CACHE_REFILL_RD", - }, - { - "ArchStdEvent": "L1D_CACHE_REFILL_WR", - }, - { - "ArchStdEvent": "L1D_TLB_REFILL_RD", - }, - { - "ArchStdEvent": "L1D_TLB_REFILL_WR", - }, - { - "ArchStdEvent": "L1D_TLB_RD", - }, - { - "ArchStdEvent": "L1D_TLB_WR", - }, - { - "ArchStdEvent": "BUS_ACCESS_RD", - }, - { - "ArchStdEvent": "BUS_ACCESS_WR", - } -] diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/exception.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/exception.json new file mode 100644 index 000000000000..3720dc28a15f --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/exception.json @@ -0,0 +1,50 @@ +[ + { + "ArchStdEvent": "EXC_UNDEF", + }, + { + "ArchStdEvent": "EXC_SVC", + }, + { + "ArchStdEvent": "EXC_PABORT", + }, + { + "ArchStdEvent": "EXC_DABORT", + }, + { + "ArchStdEvent": "EXC_IRQ", + }, + { + "ArchStdEvent": "EXC_FIQ", + }, + { + "ArchStdEvent": "EXC_HVC", + }, + { + "ArchStdEvent": "EXC_TRAP_PABORT", + }, + { + "ArchStdEvent": "EXC_TRAP_DABORT", + }, + { + "ArchStdEvent": "EXC_TRAP_OTHER", + }, + { + "ArchStdEvent": "EXC_TRAP_IRQ", + }, + { + "ArchStdEvent": "EXC_TRAP_FIQ", + }, + { + "PublicDescription": "Exception taken", + "EventCode": "0x09", + "EventName": "EXC_TAKEN", + "BriefDescription": "Exception taken" + }, + { + "PublicDescription": "Instruction architecturally executed, condition check pass, exception return", + "EventCode": "0x0a", + "EventName": "EXC_RETURN", + "BriefDescription": "Exception return" + }, +] diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/instruction.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/instruction.json new file mode 100644 index 000000000000..82cf753e6472 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/instruction.json @@ -0,0 +1,89 @@ +[ + { + "ArchStdEvent": "LD_SPEC", + }, + { + "ArchStdEvent": "ST_SPEC", + }, + { + "ArchStdEvent": "LDST_SPEC", + }, + { + "ArchStdEvent": "DP_SPEC", + }, + { + "ArchStdEvent": "ASE_SPEC", + }, + { + "ArchStdEvent": "VFP_SPEC", + }, + { + "ArchStdEvent": "PC_WRITE_SPEC", + }, + { + "ArchStdEvent": "CRYPTO_SPEC", + }, + { + "ArchStdEvent": "ISB_SPEC", + }, + { + "ArchStdEvent": "DSB_SPEC", + }, + { + "ArchStdEvent": "DMB_SPEC", + }, + { + "ArchStdEvent": "RC_LD_SPEC", + }, + { + "ArchStdEvent": "RC_ST_SPEC", + }, + { + "PublicDescription": "Instruction architecturally executed, software increment", + "EventCode": "0x00", + "EventName": "SW_INCR", + "BriefDescription": "Software increment" + }, + { + "PublicDescription": "Instruction architecturally executed", + "EventCode": "0x08", + "EventName": "INST_RETIRED", + "BriefDescription": "Instruction retired" + }, + { + "PublicDescription": "Instruction architecturally executed, condition code check pass, write to CONTEXTIDR", + "EventCode": "0x0b", + "EventName": "CID_WRITE_RETIRED", + "BriefDescription": "Write to CONTEXTIDR" + }, + { + "PublicDescription": "Operation speculatively executed", + "EventCode": "0x1b", + "EventName": "INST_SPEC", + "BriefDescription": "Speculatively executed" + }, + { + "PublicDescription": "Instruction architecturally executed (condition check pass), write to TTBR", + "EventCode": "0x1c", + "EventName": "TTBR_WRITE_RETIRED", + "BriefDescription": "Instruction executed, TTBR write" + }, + { + "PublicDescription": "Instruction architecturally executed, branch. This event counts all branches, taken or not. This excludes exception entries, debug entries and CCFAIL branches", + "EventCode": "0x21", + "EventName": "BR_RETIRED", + "BriefDescription": "Branch retired" + }, + { + "PublicDescription": "Instruction architecturally executed, mispredicted branch. This event counts any branch counted by BR_RETIRED which is not correctly predicted and causes a pipeline flush", + "EventCode": "0x22", + "EventName": "BR_MISPRED_RETIRED", + "BriefDescription": "Mispredicted branch retired" + }, + { + "PublicDescription": "Operation speculatively executed, NOP", + "EventCode": "0x100", + "EventName": "NOP_SPEC", + "BriefDescription": "Speculatively executed, NOP" + }, +] diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/intrinsic.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/intrinsic.json new file mode 100644 index 000000000000..2aecc5c2347d --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/intrinsic.json @@ -0,0 +1,14 @@ +[ + { + "ArchStdEvent": "LDREX_SPEC", + }, + { + "ArchStdEvent": "STREX_PASS_SPEC", + }, + { + "ArchStdEvent": "STREX_FAIL_SPEC", + }, + { + "ArchStdEvent": "STREX_SPEC", + }, +] diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/memory.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/memory.json new file mode 100644 index 000000000000..08508697b318 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/memory.json @@ -0,0 +1,29 @@ +[ + { + "ArchStdEvent": "MEM_ACCESS_RD", + }, + { + "ArchStdEvent": "MEM_ACCESS_WR", + }, + { + "ArchStdEvent": "UNALIGNED_LD_SPEC", + }, + { + "ArchStdEvent": "UNALIGNED_ST_SPEC", + }, + { + "ArchStdEvent": "UNALIGNED_LDST_SPEC", + }, + { + "PublicDescription": "Data memory access", + "EventCode": "0x13", + "EventName": "MEM_ACCESS", + "BriefDescription": "Memory access" + }, + { + "PublicDescription": "Local memory error. This event counts any correctable or uncorrectable memory error (ECC or parity) in the protected core RAMs", + "EventCode": "0x1a", + "EventName": "MEM_ERROR", + "BriefDescription": "Memory error" + }, +] diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/pipeline.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/pipeline.json new file mode 100644 index 000000000000..e2087de586bf --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/pipeline.json @@ -0,0 +1,50 @@ +[ + { + "PublicDescription": "Decode starved for instruction cycle", + "EventCode": "0x108", + "EventName": "DECODE_STALL", + "BriefDescription": "Decode starved" + }, + { + "PublicDescription": "Op dispatch stalled cycle", + "EventCode": "0x109", + "EventName": "DISPATCH_STALL", + "BriefDescription": "Dispatch stalled" + }, + { + "PublicDescription": "IXA Op non-issue", + "EventCode": "0x10a", + "EventName": "IXA_STALL", + "BriefDescription": "IXA stalled" + }, + { + "PublicDescription": "IXB Op non-issue", + "EventCode": "0x10b", + "EventName": "IXB_STALL", + "BriefDescription": "IXB stalled" + }, + { + "PublicDescription": "BX Op non-issue", + "EventCode": "0x10c", + "EventName": "BX_STALL", + "BriefDescription": "BX stalled" + }, + { + "PublicDescription": "LX Op non-issue", + "EventCode": "0x10d", + "EventName": "LX_STALL", + "BriefDescription": "LX stalled" + }, + { + "PublicDescription": "SX Op non-issue", + "EventCode": "0x10e", + "EventName": "SX_STALL", + "BriefDescription": "SX stalled" + }, + { + "PublicDescription": "FX Op non-issue", + "EventCode": "0x10f", + "EventName": "FX_STALL", + "BriefDescription": "FX stalled" + }, +] From 1182a49529edde899be4b4f0e1ab76e626976eb6 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Wed, 19 Sep 2018 10:29:07 -0700 Subject: [PATCH 125/155] perf/x86: Add helper to obtain performance counter index perf_event_read_local() is the safest way to obtain measurements associated with performance events. In some cases the overhead introduced by perf_event_read_local() affects the measurements and the use of rdpmcl() is needed. rdpmcl() requires the index of the performance counter used so a helper is introduced to determine the index used by a provided performance event. The index used by a performance event may change when interrupts are enabled. A check is added to ensure that the index is only accessed with interrupts disabled. Even with this check the use of this counter needs to be done with care to ensure it is queried and used within the same disabled interrupts section. This change introduces a new checkpatch warning: CHECK: extern prototypes should be avoided in .h files +extern int x86_perf_rdpmc_index(struct perf_event *event); This warning was discussed and designated as a false positive in http://lkml.kernel.org/r/20180919091759.GZ24124@hirez.programming.kicks-ass.net Suggested-by: Peter Zijlstra Signed-off-by: Reinette Chatre Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Cc: fenghua.yu@intel.com Cc: tony.luck@intel.com Cc: acme@kernel.org Cc: gavin.hindman@intel.com Cc: jithu.joseph@intel.com Cc: dave.hansen@intel.com Cc: hpa@zytor.com Link: https://lkml.kernel.org/r/b277ffa78a51254f5414f7b1bc1923826874566e.1537377064.git.reinette.chatre@intel.com --- arch/x86/events/core.c | 21 +++++++++++++++++++++ arch/x86/include/asm/perf_event.h | 1 + 2 files changed, 22 insertions(+) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index dfb2f7c0d019..3550d800b030 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -1033,6 +1033,27 @@ static inline void x86_assign_hw_event(struct perf_event *event, } } +/** + * x86_perf_rdpmc_index - Return PMC counter used for event + * @event: the perf_event to which the PMC counter was assigned + * + * The counter assigned to this performance event may change if interrupts + * are enabled. This counter should thus never be used while interrupts are + * enabled. Before this function is used to obtain the assigned counter the + * event should be checked for validity using, for example, + * perf_event_read_local(), within the same interrupt disabled section in + * which this counter is planned to be used. + * + * Return: The index of the performance monitoring counter assigned to + * @perf_event. + */ +int x86_perf_rdpmc_index(struct perf_event *event) +{ + lockdep_assert_irqs_disabled(); + + return event->hw.event_base_rdpmc; +} + static inline int match_prev_assignment(struct hw_perf_event *hwc, struct cpu_hw_events *cpuc, int i) diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index 12f54082f4c8..b2cf84c35a6d 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -270,6 +270,7 @@ struct perf_guest_switch_msr { extern struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr); extern void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap); extern void perf_check_microcode(void); +extern int x86_perf_rdpmc_index(struct perf_event *event); #else static inline struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr) { From b5e4274ef7f00a03ce8d728701409a6e2c99146b Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Wed, 19 Sep 2018 10:29:08 -0700 Subject: [PATCH 126/155] x86/intel_rdt: Remove local register variables Local register variables were used in an effort to improve the accuracy of the measurement of cache residency of a pseudo-locked region. This was done to ensure that only the cache residency of the memory is measured and not the cache residency of the variables used to perform the measurement. While local register variables do accomplish the goal they do require significant care since different architectures have different registers available. Local register variables also cannot be used with valuable developer tools like KASAN. Significant testing has shown that similar accuracy in measurement results can be obtained by replacing local register variables with regular local variables. Make use of local variables in the critical code but do so with READ_ONCE() to prevent the compiler from merging or refetching reads. Ensure these variables are initialized before the measurement starts, and ensure it is only the local variables that are accessed during the measurement. With the removal of the local register variables and using READ_ONCE() there is no longer a motivation for using a direct wrmsr call (that avoids the additional tracing code that may clobber the local register variables). Signed-off-by: Reinette Chatre Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Cc: fenghua.yu@intel.com Cc: tony.luck@intel.com Cc: acme@kernel.org Cc: gavin.hindman@intel.com Cc: jithu.joseph@intel.com Cc: dave.hansen@intel.com Cc: hpa@zytor.com Link: https://lkml.kernel.org/r/f430f57347414e0691765d92b144758ab93d8407.1537377064.git.reinette.chatre@intel.com --- arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c | 53 ++++----------------- 1 file changed, 9 insertions(+), 44 deletions(-) diff --git a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c index 40f3903ae5d9..8ad83eb3fc89 100644 --- a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c +++ b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c @@ -886,31 +886,14 @@ static int measure_cycles_lat_fn(void *_plr) struct pseudo_lock_region *plr = _plr; unsigned long i; u64 start, end; -#ifdef CONFIG_KASAN - /* - * The registers used for local register variables are also used - * when KASAN is active. When KASAN is active we use a regular - * variable to ensure we always use a valid pointer to access memory. - * The cost is that accessing this pointer, which could be in - * cache, will be included in the measurement of memory read latency. - */ void *mem_r; -#else -#ifdef CONFIG_X86_64 - register void *mem_r asm("rbx"); -#else - register void *mem_r asm("ebx"); -#endif /* CONFIG_X86_64 */ -#endif /* CONFIG_KASAN */ local_irq_disable(); /* - * The wrmsr call may be reordered with the assignment below it. - * Call wrmsr as directly as possible to avoid tracing clobbering - * local register variable used for memory pointer. + * Disable hardware prefetchers. */ - __wrmsr(MSR_MISC_FEATURE_CONTROL, prefetch_disable_bits, 0x0); - mem_r = plr->kmem; + wrmsr(MSR_MISC_FEATURE_CONTROL, prefetch_disable_bits, 0x0); + mem_r = READ_ONCE(plr->kmem); /* * Dummy execute of the time measurement to load the needed * instructions into the L1 instruction cache. @@ -939,26 +922,10 @@ static int measure_cycles_perf_fn(void *_plr) struct pseudo_lock_region *plr = _plr; unsigned long long l2_hits, l2_miss; u64 l2_hit_bits, l2_miss_bits; - unsigned long i; -#ifdef CONFIG_KASAN - /* - * The registers used for local register variables are also used - * when KASAN is active. When KASAN is active we use regular variables - * at the cost of including cache access latency to these variables - * in the measurements. - */ unsigned int line_size; unsigned int size; + unsigned long i; void *mem_r; -#else - register unsigned int line_size asm("esi"); - register unsigned int size asm("edi"); -#ifdef CONFIG_X86_64 - register void *mem_r asm("rbx"); -#else - register void *mem_r asm("ebx"); -#endif /* CONFIG_X86_64 */ -#endif /* CONFIG_KASAN */ /* * Non-architectural event for the Goldmont Microarchitecture @@ -1011,11 +978,9 @@ static int measure_cycles_perf_fn(void *_plr) local_irq_disable(); /* - * Call wrmsr direcly to avoid the local register variables from - * being overwritten due to reordering of their assignment with - * the wrmsr calls. + * Disable hardware prefetchers. */ - __wrmsr(MSR_MISC_FEATURE_CONTROL, prefetch_disable_bits, 0x0); + wrmsr(MSR_MISC_FEATURE_CONTROL, prefetch_disable_bits, 0x0); /* Disable events and reset counters */ pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0, 0x0); pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0 + 1, 0x0); @@ -1028,6 +993,9 @@ static int measure_cycles_perf_fn(void *_plr) pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_PERFCTR0 + 3, 0x0); } /* Set and enable the L2 counters */ + mem_r = READ_ONCE(plr->kmem); + size = READ_ONCE(plr->size); + line_size = READ_ONCE(plr->line_size); pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0, l2_hit_bits); pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0 + 1, l2_miss_bits); if (l3_hit_bits > 0) { @@ -1036,9 +1004,6 @@ static int measure_cycles_perf_fn(void *_plr) pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0 + 3, l3_miss_bits); } - mem_r = plr->kmem; - size = plr->size; - line_size = plr->line_size; for (i = 0; i < size; i += line_size) { asm volatile("mov (%0,%1,1), %%eax\n\t" : From 0a701c9dd5351cbaef1677a0c8d37950e158cd55 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Wed, 19 Sep 2018 10:29:09 -0700 Subject: [PATCH 127/155] x86/intel_rdt: Create required perf event attributes A perf event has many attributes that are maintained in a separate structure that should be provided when a new perf_event is created. In preparation for the transition to perf_events the required attribute structures are created for all the events that may be used in the measurements. Most attributes for all the events are identical. The actual configuration, what specifies what needs to be measured, is what will be different between the events used. This configuration needs to be done with X86_CONFIG that cannot be used as part of the designated initializers used here, this will be introduced later. Although they do look identical at this time the attribute structures needs to be maintained separately since a perf_event will maintain a pointer to its unique attributes. In support of patch testing the new structs are given the unused attribute until their use in later patches. Signed-off-by: Reinette Chatre Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Cc: fenghua.yu@intel.com Cc: tony.luck@intel.com Cc: acme@kernel.org Cc: gavin.hindman@intel.com Cc: jithu.joseph@intel.com Cc: dave.hansen@intel.com Cc: hpa@zytor.com Link: https://lkml.kernel.org/r/1822f6164e221a497648d108913d056ab675d5d0.1537377064.git.reinette.chatre@intel.com --- arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c index 8ad83eb3fc89..33d7968f152a 100644 --- a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c +++ b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -915,6 +916,31 @@ static int measure_cycles_lat_fn(void *_plr) return 0; } +/* + * Create a perf_event_attr for the hit and miss perf events that will + * be used during the performance measurement. A perf_event maintains + * a pointer to its perf_event_attr so a unique attribute structure is + * created for each perf_event. + * + * The actual configuration of the event is set right before use in order + * to use the X86_CONFIG macro. + */ +static struct perf_event_attr __attribute__((unused)) perf_miss_attr = { + .type = PERF_TYPE_RAW, + .size = sizeof(struct perf_event_attr), + .pinned = 1, + .disabled = 0, + .exclude_user = 1, +}; + +static struct perf_event_attr __attribute__((unused)) perf_hit_attr = { + .type = PERF_TYPE_RAW, + .size = sizeof(struct perf_event_attr), + .pinned = 1, + .disabled = 0, + .exclude_user = 1, +}; + static int measure_cycles_perf_fn(void *_plr) { unsigned long long l3_hits = 0, l3_miss = 0; From dd45407c0b2445bc2aa0ecfea744d5af3a146577 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Thu, 20 Sep 2018 12:02:11 -0700 Subject: [PATCH 128/155] x86/intel_rdt: Use perf infrastructure for measurements The success of a cache pseudo-locked region is measured using performance monitoring events that are programmed directly at the time the user requests a measurement. Modifying the performance event registers directly is not appropriate since it circumvents the in-kernel perf infrastructure that exists to manage these resources and provide resource arbitration to the performance monitoring hardware. The cache pseudo-locking measurements are modified to use the in-kernel perf infrastructure. Performance events are created and validated with the appropriate perf API. The performance counters are still read as directly as possible to avoid the additional cache hits. This is done safely by first ensuring with the perf API that the counters have been programmed correctly and only accessing the counters in an interrupt disabled section where they are not able to be moved. As part of the transition to the in-kernel perf infrastructure the L2 and L3 measurements are split into two separate measurements that can be triggered independently. This separation prevents additional cache misses incurred during the extra testing code used to decide if a L2 and/or L3 measurement should be made. Signed-off-by: Reinette Chatre Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Cc: fenghua.yu@intel.com Cc: tony.luck@intel.com Cc: peterz@infradead.org Cc: acme@kernel.org Cc: gavin.hindman@intel.com Cc: jithu.joseph@intel.com Cc: dave.hansen@intel.com Cc: hpa@zytor.com Link: https://lkml.kernel.org/r/fc24e728b446404f42c78573c506e98cd0599873.1537468643.git.reinette.chatre@intel.com --- Documentation/x86/intel_rdt_ui.txt | 22 +- arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c | 308 ++++++++++++-------- 2 files changed, 205 insertions(+), 125 deletions(-) diff --git a/Documentation/x86/intel_rdt_ui.txt b/Documentation/x86/intel_rdt_ui.txt index f662d3c530e5..52b10945ff75 100644 --- a/Documentation/x86/intel_rdt_ui.txt +++ b/Documentation/x86/intel_rdt_ui.txt @@ -520,18 +520,24 @@ the pseudo-locked region: 2) Cache hit and miss measurements using model specific precision counters if available. Depending on the levels of cache on the system the pseudo_lock_l2 and pseudo_lock_l3 tracepoints are available. - WARNING: triggering this measurement uses from two (for just L2 - measurements) to four (for L2 and L3 measurements) precision counters on - the system, if any other measurements are in progress the counters and - their corresponding event registers will be clobbered. When a pseudo-locked region is created a new debugfs directory is created for it in debugfs as /sys/kernel/debug/resctrl/. A single write-only file, pseudo_lock_measure, is present in this directory. The -measurement on the pseudo-locked region depends on the number, 1 or 2, -written to this debugfs file. Since the measurements are recorded with the -tracing infrastructure the relevant tracepoints need to be enabled before the -measurement is triggered. +measurement of the pseudo-locked region depends on the number written to this +debugfs file: +1 - writing "1" to the pseudo_lock_measure file will trigger the latency + measurement captured in the pseudo_lock_mem_latency tracepoint. See + example below. +2 - writing "2" to the pseudo_lock_measure file will trigger the L2 cache + residency (cache hits and misses) measurement captured in the + pseudo_lock_l2 tracepoint. See example below. +3 - writing "3" to the pseudo_lock_measure file will trigger the L3 cache + residency (cache hits and misses) measurement captured in the + pseudo_lock_l3 tracepoint. + +All measurements are recorded with the tracing infrastructure. This requires +the relevant tracepoints to be enabled before the measurement is triggered. Example of latency debugging interface: In this example a pseudo-locked region named "newlock" was created. Here is diff --git a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c index 33d7968f152a..d68836139cf9 100644 --- a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c +++ b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c @@ -27,6 +27,7 @@ #include #include +#include "../../events/perf_event.h" /* For X86_CONFIG() */ #include "intel_rdt.h" #define CREATE_TRACE_POINTS @@ -107,16 +108,6 @@ static u64 get_prefetch_disable_bits(void) return 0; } -/* - * Helper to write 64bit value to MSR without tracing. Used when - * use of the cache should be restricted and use of registers used - * for local variables avoided. - */ -static inline void pseudo_wrmsrl_notrace(unsigned int msr, u64 val) -{ - __wrmsr(msr, (u32)(val & 0xffffffffULL), (u32)(val >> 32)); -} - /** * pseudo_lock_minor_get - Obtain available minor number * @minor: Pointer to where new minor number will be stored @@ -925,7 +916,7 @@ static int measure_cycles_lat_fn(void *_plr) * The actual configuration of the event is set right before use in order * to use the X86_CONFIG macro. */ -static struct perf_event_attr __attribute__((unused)) perf_miss_attr = { +static struct perf_event_attr perf_miss_attr = { .type = PERF_TYPE_RAW, .size = sizeof(struct perf_event_attr), .pinned = 1, @@ -933,7 +924,7 @@ static struct perf_event_attr __attribute__((unused)) perf_miss_attr = { .exclude_user = 1, }; -static struct perf_event_attr __attribute__((unused)) perf_hit_attr = { +static struct perf_event_attr perf_hit_attr = { .type = PERF_TYPE_RAW, .size = sizeof(struct perf_event_attr), .pinned = 1, @@ -941,139 +932,215 @@ static struct perf_event_attr __attribute__((unused)) perf_hit_attr = { .exclude_user = 1, }; -static int measure_cycles_perf_fn(void *_plr) +struct residency_counts { + u64 miss_before, hits_before; + u64 miss_after, hits_after; +}; + +static int measure_residency_fn(struct perf_event_attr *miss_attr, + struct perf_event_attr *hit_attr, + struct pseudo_lock_region *plr, + struct residency_counts *counts) { - unsigned long long l3_hits = 0, l3_miss = 0; - u64 l3_hit_bits = 0, l3_miss_bits = 0; - struct pseudo_lock_region *plr = _plr; - unsigned long long l2_hits, l2_miss; - u64 l2_hit_bits, l2_miss_bits; + u64 hits_before = 0, hits_after = 0, miss_before = 0, miss_after = 0; + struct perf_event *miss_event, *hit_event; + int hit_pmcnum, miss_pmcnum; unsigned int line_size; unsigned int size; unsigned long i; void *mem_r; + u64 tmp; - /* - * Non-architectural event for the Goldmont Microarchitecture - * from Intel x86 Architecture Software Developer Manual (SDM): - * MEM_LOAD_UOPS_RETIRED D1H (event number) - * Umask values: - * L1_HIT 01H - * L2_HIT 02H - * L1_MISS 08H - * L2_MISS 10H - * - * On Broadwell Microarchitecture the MEM_LOAD_UOPS_RETIRED event - * has two "no fix" errata associated with it: BDM35 and BDM100. On - * this platform we use the following events instead: - * L2_RQSTS 24H (Documented in https://download.01.org/perfmon/BDW/) - * REFERENCES FFH - * MISS 3FH - * LONGEST_LAT_CACHE 2EH (Documented in SDM) - * REFERENCE 4FH - * MISS 41H - */ - - /* - * Start by setting flags for IA32_PERFEVTSELx: - * OS (Operating system mode) 0x2 - * INT (APIC interrupt enable) 0x10 - * EN (Enable counter) 0x40 - * - * Then add the Umask value and event number to select performance - * event. - */ - - switch (boot_cpu_data.x86_model) { - case INTEL_FAM6_ATOM_GOLDMONT: - case INTEL_FAM6_ATOM_GEMINI_LAKE: - l2_hit_bits = (0x52ULL << 16) | (0x2 << 8) | 0xd1; - l2_miss_bits = (0x52ULL << 16) | (0x10 << 8) | 0xd1; - break; - case INTEL_FAM6_BROADWELL_X: - /* On BDW the l2_hit_bits count references, not hits */ - l2_hit_bits = (0x52ULL << 16) | (0xff << 8) | 0x24; - l2_miss_bits = (0x52ULL << 16) | (0x3f << 8) | 0x24; - /* On BDW the l3_hit_bits count references, not hits */ - l3_hit_bits = (0x52ULL << 16) | (0x4f << 8) | 0x2e; - l3_miss_bits = (0x52ULL << 16) | (0x41 << 8) | 0x2e; - break; - default: + miss_event = perf_event_create_kernel_counter(miss_attr, plr->cpu, + NULL, NULL, NULL); + if (IS_ERR(miss_event)) goto out; - } + + hit_event = perf_event_create_kernel_counter(hit_attr, plr->cpu, + NULL, NULL, NULL); + if (IS_ERR(hit_event)) + goto out_miss; local_irq_disable(); + /* + * Check any possible error state of events used by performing + * one local read. + */ + if (perf_event_read_local(miss_event, &tmp, NULL, NULL)) { + local_irq_enable(); + goto out_hit; + } + if (perf_event_read_local(hit_event, &tmp, NULL, NULL)) { + local_irq_enable(); + goto out_hit; + } + /* * Disable hardware prefetchers. */ wrmsr(MSR_MISC_FEATURE_CONTROL, prefetch_disable_bits, 0x0); - /* Disable events and reset counters */ - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0, 0x0); - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0 + 1, 0x0); - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_PERFCTR0, 0x0); - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_PERFCTR0 + 1, 0x0); - if (l3_hit_bits > 0) { - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0 + 2, 0x0); - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0 + 3, 0x0); - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_PERFCTR0 + 2, 0x0); - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_PERFCTR0 + 3, 0x0); - } - /* Set and enable the L2 counters */ + + /* Initialize rest of local variables */ + /* + * Performance event has been validated right before this with + * interrupts disabled - it is thus safe to read the counter index. + */ + miss_pmcnum = x86_perf_rdpmc_index(miss_event); + hit_pmcnum = x86_perf_rdpmc_index(hit_event); + line_size = READ_ONCE(plr->line_size); mem_r = READ_ONCE(plr->kmem); size = READ_ONCE(plr->size); - line_size = READ_ONCE(plr->line_size); - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0, l2_hit_bits); - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0 + 1, l2_miss_bits); - if (l3_hit_bits > 0) { - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0 + 2, - l3_hit_bits); - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0 + 3, - l3_miss_bits); - } + + /* + * Read counter variables twice - first to load the instructions + * used in L1 cache, second to capture accurate value that does not + * include cache misses incurred because of instruction loads. + */ + rdpmcl(hit_pmcnum, hits_before); + rdpmcl(miss_pmcnum, miss_before); + /* + * From SDM: Performing back-to-back fast reads are not guaranteed + * to be monotonic. + * Use LFENCE to ensure all previous instructions are retired + * before proceeding. + */ + rmb(); + rdpmcl(hit_pmcnum, hits_before); + rdpmcl(miss_pmcnum, miss_before); + /* + * Use LFENCE to ensure all previous instructions are retired + * before proceeding. + */ + rmb(); for (i = 0; i < size; i += line_size) { + /* + * Add a barrier to prevent speculative execution of this + * loop reading beyond the end of the buffer. + */ + rmb(); asm volatile("mov (%0,%1,1), %%eax\n\t" : : "r" (mem_r), "r" (i) : "%eax", "memory"); } /* - * Call wrmsr directly (no tracing) to not influence - * the cache access counters as they are disabled. + * Use LFENCE to ensure all previous instructions are retired + * before proceeding. */ - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0, - l2_hit_bits & ~(0x40ULL << 16)); - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0 + 1, - l2_miss_bits & ~(0x40ULL << 16)); - if (l3_hit_bits > 0) { - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0 + 2, - l3_hit_bits & ~(0x40ULL << 16)); - pseudo_wrmsrl_notrace(MSR_ARCH_PERFMON_EVENTSEL0 + 3, - l3_miss_bits & ~(0x40ULL << 16)); - } - l2_hits = native_read_pmc(0); - l2_miss = native_read_pmc(1); - if (l3_hit_bits > 0) { - l3_hits = native_read_pmc(2); - l3_miss = native_read_pmc(3); - } + rmb(); + rdpmcl(hit_pmcnum, hits_after); + rdpmcl(miss_pmcnum, miss_after); + /* + * Use LFENCE to ensure all previous instructions are retired + * before proceeding. + */ + rmb(); + /* Re-enable hardware prefetchers */ wrmsr(MSR_MISC_FEATURE_CONTROL, 0x0, 0x0); local_irq_enable(); +out_hit: + perf_event_release_kernel(hit_event); +out_miss: + perf_event_release_kernel(miss_event); +out: /* - * On BDW we count references and misses, need to adjust. Sometimes - * the "hits" counter is a bit more than the references, for - * example, x references but x + 1 hits. To not report invalid - * hit values in this case we treat that as misses eaqual to - * references. + * All counts will be zero on failure. */ - if (boot_cpu_data.x86_model == INTEL_FAM6_BROADWELL_X) - l2_hits -= (l2_miss > l2_hits ? l2_hits : l2_miss); - trace_pseudo_lock_l2(l2_hits, l2_miss); - if (l3_hit_bits > 0) { - if (boot_cpu_data.x86_model == INTEL_FAM6_BROADWELL_X) - l3_hits -= (l3_miss > l3_hits ? l3_hits : l3_miss); - trace_pseudo_lock_l3(l3_hits, l3_miss); + counts->miss_before = miss_before; + counts->hits_before = hits_before; + counts->miss_after = miss_after; + counts->hits_after = hits_after; + return 0; +} + +static int measure_l2_residency(void *_plr) +{ + struct pseudo_lock_region *plr = _plr; + struct residency_counts counts = {0}; + + /* + * Non-architectural event for the Goldmont Microarchitecture + * from Intel x86 Architecture Software Developer Manual (SDM): + * MEM_LOAD_UOPS_RETIRED D1H (event number) + * Umask values: + * L2_HIT 02H + * L2_MISS 10H + */ + switch (boot_cpu_data.x86_model) { + case INTEL_FAM6_ATOM_GOLDMONT: + case INTEL_FAM6_ATOM_GEMINI_LAKE: + perf_miss_attr.config = X86_CONFIG(.event = 0xd1, + .umask = 0x10); + perf_hit_attr.config = X86_CONFIG(.event = 0xd1, + .umask = 0x2); + break; + default: + goto out; } + measure_residency_fn(&perf_miss_attr, &perf_hit_attr, plr, &counts); + /* + * If a failure prevented the measurements from succeeding + * tracepoints will still be written and all counts will be zero. + */ + trace_pseudo_lock_l2(counts.hits_after - counts.hits_before, + counts.miss_after - counts.miss_before); +out: + plr->thread_done = 1; + wake_up_interruptible(&plr->lock_thread_wq); + return 0; +} + +static int measure_l3_residency(void *_plr) +{ + struct pseudo_lock_region *plr = _plr; + struct residency_counts counts = {0}; + + /* + * On Broadwell Microarchitecture the MEM_LOAD_UOPS_RETIRED event + * has two "no fix" errata associated with it: BDM35 and BDM100. On + * this platform the following events are used instead: + * LONGEST_LAT_CACHE 2EH (Documented in SDM) + * REFERENCE 4FH + * MISS 41H + */ + + switch (boot_cpu_data.x86_model) { + case INTEL_FAM6_BROADWELL_X: + /* On BDW the hit event counts references, not hits */ + perf_hit_attr.config = X86_CONFIG(.event = 0x2e, + .umask = 0x4f); + perf_miss_attr.config = X86_CONFIG(.event = 0x2e, + .umask = 0x41); + break; + default: + goto out; + } + + measure_residency_fn(&perf_miss_attr, &perf_hit_attr, plr, &counts); + /* + * If a failure prevented the measurements from succeeding + * tracepoints will still be written and all counts will be zero. + */ + + counts.miss_after -= counts.miss_before; + if (boot_cpu_data.x86_model == INTEL_FAM6_BROADWELL_X) { + /* + * On BDW references and misses are counted, need to adjust. + * Sometimes the "hits" counter is a bit more than the + * references, for example, x references but x + 1 hits. + * To not report invalid hit values in this case we treat + * that as misses equal to references. + */ + /* First compute the number of cache references measured */ + counts.hits_after -= counts.hits_before; + /* Next convert references to cache hits */ + counts.hits_after -= min(counts.miss_after, counts.hits_after); + } else { + counts.hits_after -= counts.hits_before; + } + + trace_pseudo_lock_l3(counts.hits_after, counts.miss_after); out: plr->thread_done = 1; wake_up_interruptible(&plr->lock_thread_wq); @@ -1112,13 +1179,20 @@ static int pseudo_lock_measure_cycles(struct rdtgroup *rdtgrp, int sel) goto out; } + plr->cpu = cpu; + if (sel == 1) thread = kthread_create_on_node(measure_cycles_lat_fn, plr, cpu_to_node(cpu), "pseudo_lock_measure/%u", cpu); else if (sel == 2) - thread = kthread_create_on_node(measure_cycles_perf_fn, plr, + thread = kthread_create_on_node(measure_l2_residency, plr, + cpu_to_node(cpu), + "pseudo_lock_measure/%u", + cpu); + else if (sel == 3) + thread = kthread_create_on_node(measure_l3_residency, plr, cpu_to_node(cpu), "pseudo_lock_measure/%u", cpu); From ba12d20edc5caf9835006d8f3efd4ed18465c75b Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Wed, 8 Aug 2018 00:12:06 -0700 Subject: [PATCH 129/155] perf/x86/intel: Factor out common code of PMI handler The Arch Perfmon v4 PMI handler is substantially different than the older PMI handler. Instead of adding more and more ifs cleanly fork the new handler into a new function, with the main common code factored out into a common function. Fix complaint from checkpatch.pl by removing "false" from "static bool warned". No functional change. Based-on-code-from: Andi Kleen Signed-off-by: Kan Liang Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: acme@kernel.org Link: http://lkml.kernel.org/r/1533712328-2834-1-git-send-email-kan.liang@linux.intel.com Signed-off-by: Ingo Molnar --- arch/x86/events/intel/core.c | 109 +++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 49 deletions(-) diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 035c37481f57..9b320a51f82f 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -2200,59 +2200,15 @@ static void intel_pmu_reset(void) local_irq_restore(flags); } -/* - * This handler is triggered by the local APIC, so the APIC IRQ handling - * rules apply: - */ -static int intel_pmu_handle_irq(struct pt_regs *regs) +static int handle_pmi_common(struct pt_regs *regs, u64 status) { struct perf_sample_data data; - struct cpu_hw_events *cpuc; - int bit, loops; - u64 status; - int handled; - int pmu_enabled; - - cpuc = this_cpu_ptr(&cpu_hw_events); - - /* - * Save the PMU state. - * It needs to be restored when leaving the handler. - */ - pmu_enabled = cpuc->enabled; - /* - * No known reason to not always do late ACK, - * but just in case do it opt-in. - */ - if (!x86_pmu.late_ack) - apic_write(APIC_LVTPC, APIC_DM_NMI); - intel_bts_disable_local(); - cpuc->enabled = 0; - __intel_pmu_disable_all(); - handled = intel_pmu_drain_bts_buffer(); - handled += intel_bts_interrupt(); - status = intel_pmu_get_status(); - if (!status) - goto done; - - loops = 0; -again: - intel_pmu_lbr_read(); - intel_pmu_ack_status(status); - if (++loops > 100) { - static bool warned = false; - if (!warned) { - WARN(1, "perfevents: irq loop stuck!\n"); - perf_event_print_debug(); - warned = true; - } - intel_pmu_reset(); - goto done; - } + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); + int bit; + int handled = 0; inc_irq_stat(apic_perf_irqs); - /* * Ignore a range of extra bits in status that do not indicate * overflow by themselves. @@ -2261,7 +2217,7 @@ again: GLOBAL_STATUS_ASIF | GLOBAL_STATUS_LBRS_FROZEN); if (!status) - goto done; + return 0; /* * In case multiple PEBS events are sampled at the same time, * it is possible to have GLOBAL_STATUS bit 62 set indicating @@ -2331,6 +2287,61 @@ again: x86_pmu_stop(event, 0); } + return handled; +} + +/* + * This handler is triggered by the local APIC, so the APIC IRQ handling + * rules apply: + */ +static int intel_pmu_handle_irq(struct pt_regs *regs) +{ + struct cpu_hw_events *cpuc; + int loops; + u64 status; + int handled; + int pmu_enabled; + + cpuc = this_cpu_ptr(&cpu_hw_events); + + /* + * Save the PMU state. + * It needs to be restored when leaving the handler. + */ + pmu_enabled = cpuc->enabled; + /* + * No known reason to not always do late ACK, + * but just in case do it opt-in. + */ + if (!x86_pmu.late_ack) + apic_write(APIC_LVTPC, APIC_DM_NMI); + intel_bts_disable_local(); + cpuc->enabled = 0; + __intel_pmu_disable_all(); + handled = intel_pmu_drain_bts_buffer(); + handled += intel_bts_interrupt(); + status = intel_pmu_get_status(); + if (!status) + goto done; + + loops = 0; +again: + intel_pmu_lbr_read(); + intel_pmu_ack_status(status); + if (++loops > 100) { + static bool warned; + + if (!warned) { + WARN(1, "perfevents: irq loop stuck!\n"); + perf_event_print_debug(); + warned = true; + } + intel_pmu_reset(); + goto done; + } + + handled += handle_pmi_common(regs, status); + /* * Repeat if there is more work to be done: */ From af3bdb991a5cb57c189d34aadbd3aa88995e0d9f Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 8 Aug 2018 00:12:07 -0700 Subject: [PATCH 130/155] perf/x86/intel: Add a separate Arch Perfmon v4 PMI handler Implements counter freezing for Arch Perfmon v4 (Skylake and newer). This allows to speed up the PMI handler by avoiding unnecessary MSR writes and make it more accurate. The Arch Perfmon v4 PMI handler is substantially different than the older PMI handler. Differences to the old handler: - It relies on counter freezing, which eliminates several MSR writes from the PMI handler and lowers the overhead significantly. It makes the PMI handler more accurate, as all counters get frozen atomically as soon as any counter overflows. So there is much less counting of the PMI handler itself. With the freezing we don't need to disable or enable counters or PEBS. Only BTS which does not support auto-freezing still needs to be explicitly managed. - The PMU acking is done at the end, not the beginning. This makes it possible to avoid manual enabling/disabling of the PMU, instead we just rely on the freezing/acking. - The APIC is acked before reenabling the PMU, which avoids problems with LBRs occasionally not getting unfreezed on Skylake. - Looping is only needed to workaround a corner case which several PMIs are very close to each other. For common cases, the counters are freezed during PMI handler. It doesn't need to do re-check. This patch: - Adds code to enable v4 counter freezing - Fork <=v3 and >=v4 PMI handlers into separate functions. - Add kernel parameter to disable counter freezing. It took some time to debug counter freezing, so in case there are new problems we added an option to turn it off. Would not expect this to be used until there are new bugs. - Only for big core. The patch for small core will be posted later separately. Performance: When profiling a kernel build on Kabylake with different perf options, measuring the length of all NMI handlers using the nmi handler trace point: V3 is without counter freezing. V4 is with counter freezing. The value is the average cost of the PMI handler. (lower is better) perf options ` V3(ns) V4(ns) delta -c 100000 1088 894 -18% -g -c 100000 1862 1646 -12% --call-graph lbr -c 100000 3649 3367 -8% --c.g. dwarf -c 100000 2248 1982 -12% Signed-off-by: Andi Kleen Signed-off-by: Kan Liang Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: acme@kernel.org Link: http://lkml.kernel.org/r/1533712328-2834-2-git-send-email-kan.liang@linux.intel.com Signed-off-by: Ingo Molnar --- .../admin-guide/kernel-parameters.txt | 5 + arch/x86/events/intel/core.c | 113 ++++++++++++++++++ arch/x86/events/perf_event.h | 4 +- arch/x86/include/asm/msr-index.h | 1 + 4 files changed, 122 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 92eb1f42240d..6795dedcbd1e 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -856,6 +856,11 @@ causing system reset or hang due to sending INIT from AP to BSP. + disable_counter_freezing [HW] + Disable Intel PMU counter freezing feature. + The feature only exists starting from + Arch Perfmon v4 (Skylake and newer). + disable_ddw [PPC/PSERIES] Disable Dynamic DMA Window support. Use this if to workaround buggy firmware. diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 9b320a51f82f..bd3b8f3600b2 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -1995,6 +1995,18 @@ static void intel_pmu_nhm_enable_all(int added) intel_pmu_enable_all(added); } +static void enable_counter_freeze(void) +{ + update_debugctlmsr(get_debugctlmsr() | + DEBUGCTLMSR_FREEZE_PERFMON_ON_PMI); +} + +static void disable_counter_freeze(void) +{ + update_debugctlmsr(get_debugctlmsr() & + ~DEBUGCTLMSR_FREEZE_PERFMON_ON_PMI); +} + static inline u64 intel_pmu_get_status(void) { u64 status; @@ -2290,6 +2302,91 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status) return handled; } +static bool disable_counter_freezing; +static int __init intel_perf_counter_freezing_setup(char *s) +{ + disable_counter_freezing = true; + pr_info("Intel PMU Counter freezing feature disabled\n"); + return 1; +} +__setup("disable_counter_freezing", intel_perf_counter_freezing_setup); + +/* + * Simplified handler for Arch Perfmon v4: + * - We rely on counter freezing/unfreezing to enable/disable the PMU. + * This is done automatically on PMU ack. + * - Ack the PMU only after the APIC. + */ + +static int intel_pmu_handle_irq_v4(struct pt_regs *regs) +{ + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); + int handled = 0; + bool bts = false; + u64 status; + int pmu_enabled = cpuc->enabled; + int loops = 0; + + /* PMU has been disabled because of counter freezing */ + cpuc->enabled = 0; + if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask)) { + bts = true; + intel_bts_disable_local(); + handled = intel_pmu_drain_bts_buffer(); + handled += intel_bts_interrupt(); + } + status = intel_pmu_get_status(); + if (!status) + goto done; +again: + intel_pmu_lbr_read(); + if (++loops > 100) { + static bool warned; + + if (!warned) { + WARN(1, "perfevents: irq loop stuck!\n"); + perf_event_print_debug(); + warned = true; + } + intel_pmu_reset(); + goto done; + } + + + handled += handle_pmi_common(regs, status); +done: + /* Ack the PMI in the APIC */ + apic_write(APIC_LVTPC, APIC_DM_NMI); + + /* + * The counters start counting immediately while ack the status. + * Make it as close as possible to IRET. This avoids bogus + * freezing on Skylake CPUs. + */ + if (status) { + intel_pmu_ack_status(status); + } else { + /* + * CPU may issues two PMIs very close to each other. + * When the PMI handler services the first one, the + * GLOBAL_STATUS is already updated to reflect both. + * When it IRETs, the second PMI is immediately + * handled and it sees clear status. At the meantime, + * there may be a third PMI, because the freezing bit + * isn't set since the ack in first PMI handlers. + * Double check if there is more work to be done. + */ + status = intel_pmu_get_status(); + if (status) + goto again; + } + + if (bts) + intel_bts_enable_local(); + cpuc->enabled = pmu_enabled; + return handled; +} + /* * This handler is triggered by the local APIC, so the APIC IRQ handling * rules apply: @@ -3361,6 +3458,9 @@ static void intel_pmu_cpu_starting(int cpu) if (x86_pmu.version > 1) flip_smm_bit(&x86_pmu.attr_freeze_on_smi); + if (x86_pmu.counter_freezing) + enable_counter_freeze(); + if (!cpuc->shared_regs) return; @@ -3432,6 +3532,9 @@ static void intel_pmu_cpu_dying(int cpu) free_excl_cntrs(cpu); fini_debug_store_on_cpu(cpu); + + if (x86_pmu.counter_freezing) + disable_counter_freeze(); } static void intel_pmu_sched_task(struct perf_event_context *ctx, @@ -3946,6 +4049,9 @@ __init int intel_pmu_init(void) max((int)edx.split.num_counters_fixed, assume); } + if (version >= 4) + x86_pmu.counter_freezing = !disable_counter_freezing; + if (boot_cpu_has(X86_FEATURE_PDCM)) { u64 capabilities; @@ -4442,6 +4548,13 @@ __init int intel_pmu_init(void) pr_cont("full-width counters, "); } + /* + * For arch perfmon 4 use counter freezing to avoid + * several MSR accesses in the PMI. + */ + if (x86_pmu.counter_freezing) + x86_pmu.handle_irq = intel_pmu_handle_irq_v4; + kfree(to_free); return 0; } diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index 156286335351..adae087cecdd 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -560,9 +560,11 @@ struct x86_pmu { struct event_constraint *event_constraints; struct x86_pmu_quirk *quirks; int perfctr_second_write; - bool late_ack; u64 (*limit_period)(struct perf_event *event, u64 l); + /* PMI handler bits */ + unsigned int late_ack :1, + counter_freezing :1; /* * sysfs attrs */ diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 4731f0cf97c5..80f4a4f38c79 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -164,6 +164,7 @@ #define DEBUGCTLMSR_BTS_OFF_OS (1UL << 9) #define DEBUGCTLMSR_BTS_OFF_USR (1UL << 10) #define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11) +#define DEBUGCTLMSR_FREEZE_PERFMON_ON_PMI (1UL << 12) #define DEBUGCTLMSR_FREEZE_IN_SMM_BIT 14 #define DEBUGCTLMSR_FREEZE_IN_SMM (1UL << DEBUGCTLMSR_FREEZE_IN_SMM_BIT) From f2c4db1bd80720cd8cb2a5aa220d9bc9f374f04e Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 7 Aug 2018 10:17:27 -0700 Subject: [PATCH 131/155] x86/cpu: Sanitize FAM6_ATOM naming Going primarily by: https://en.wikipedia.org/wiki/List_of_Intel_Atom_microprocessors with additional information gleaned from other related pages; notably: - Bonnell shrink was called Saltwell - Moorefield is the Merriefield refresh which makes it Airmont The general naming scheme is: FAM6_ATOM_UARCH_SOCTYPE for i in `git grep -l FAM6_ATOM` ; do sed -i -e 's/ATOM_PINEVIEW/ATOM_BONNELL/g' \ -e 's/ATOM_LINCROFT/ATOM_BONNELL_MID/' \ -e 's/ATOM_PENWELL/ATOM_SALTWELL_MID/g' \ -e 's/ATOM_CLOVERVIEW/ATOM_SALTWELL_TABLET/g' \ -e 's/ATOM_CEDARVIEW/ATOM_SALTWELL/g' \ -e 's/ATOM_SILVERMONT1/ATOM_SILVERMONT/g' \ -e 's/ATOM_SILVERMONT2/ATOM_SILVERMONT_X/g' \ -e 's/ATOM_MERRIFIELD/ATOM_SILVERMONT_MID/g' \ -e 's/ATOM_MOOREFIELD/ATOM_AIRMONT_MID/g' \ -e 's/ATOM_DENVERTON/ATOM_GOLDMONT_X/g' \ -e 's/ATOM_GEMINI_LAKE/ATOM_GOLDMONT_PLUS/g' ${i} done Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: dave.hansen@linux.intel.com Cc: len.brown@intel.com Signed-off-by: Ingo Molnar --- arch/x86/events/intel/core.c | 20 ++++---- arch/x86/events/intel/cstate.c | 8 ++-- arch/x86/events/intel/rapl.c | 4 +- arch/x86/events/msr.c | 8 ++-- arch/x86/include/asm/intel-family.h | 33 ++++++------- arch/x86/kernel/cpu/common.c | 28 +++++------ arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c | 4 +- arch/x86/kernel/tsc.c | 2 +- arch/x86/kernel/tsc_msr.c | 10 ++-- arch/x86/platform/atom/punit_atom_debug.c | 4 +- .../intel-mid/device_libs/platform_bt.c | 2 +- drivers/acpi/acpi_lpss.c | 2 +- drivers/acpi/x86/utils.c | 2 +- drivers/cpufreq/intel_pstate.c | 4 +- drivers/edac/pnd2_edac.c | 2 +- drivers/idle/intel_idle.c | 18 ++++---- drivers/mmc/host/sdhci-acpi.c | 2 +- drivers/pci/pci-mid.c | 4 +- drivers/platform/x86/intel_int0002_vgpio.c | 2 +- drivers/platform/x86/intel_mid_powerbtn.c | 4 +- .../platform/x86/intel_telemetry_debugfs.c | 2 +- drivers/platform/x86/intel_telemetry_pltdrv.c | 2 +- drivers/powercap/intel_rapl.c | 10 ++-- drivers/thermal/intel_soc_dts_thermal.c | 2 +- sound/soc/intel/boards/bytcr_rt5651.c | 2 +- tools/power/x86/turbostat/turbostat.c | 46 +++++++++---------- 26 files changed, 115 insertions(+), 112 deletions(-) diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index bd3b8f3600b2..f17cf6c3ec6f 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -4121,11 +4121,11 @@ __init int intel_pmu_init(void) name = "nehalem"; break; - case INTEL_FAM6_ATOM_PINEVIEW: - case INTEL_FAM6_ATOM_LINCROFT: - case INTEL_FAM6_ATOM_PENWELL: - case INTEL_FAM6_ATOM_CLOVERVIEW: - case INTEL_FAM6_ATOM_CEDARVIEW: + case INTEL_FAM6_ATOM_BONNELL: + case INTEL_FAM6_ATOM_BONNELL_MID: + case INTEL_FAM6_ATOM_SALTWELL: + case INTEL_FAM6_ATOM_SALTWELL_MID: + case INTEL_FAM6_ATOM_SALTWELL_TABLET: memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, sizeof(hw_cache_event_ids)); @@ -4138,9 +4138,11 @@ __init int intel_pmu_init(void) name = "bonnell"; break; - case INTEL_FAM6_ATOM_SILVERMONT1: - case INTEL_FAM6_ATOM_SILVERMONT2: + case INTEL_FAM6_ATOM_SILVERMONT: + case INTEL_FAM6_ATOM_SILVERMONT_X: + case INTEL_FAM6_ATOM_SILVERMONT_MID: case INTEL_FAM6_ATOM_AIRMONT: + case INTEL_FAM6_ATOM_AIRMONT_MID: memcpy(hw_cache_event_ids, slm_hw_cache_event_ids, sizeof(hw_cache_event_ids)); memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs, @@ -4159,7 +4161,7 @@ __init int intel_pmu_init(void) break; case INTEL_FAM6_ATOM_GOLDMONT: - case INTEL_FAM6_ATOM_DENVERTON: + case INTEL_FAM6_ATOM_GOLDMONT_X: memcpy(hw_cache_event_ids, glm_hw_cache_event_ids, sizeof(hw_cache_event_ids)); memcpy(hw_cache_extra_regs, glm_hw_cache_extra_regs, @@ -4185,7 +4187,7 @@ __init int intel_pmu_init(void) name = "goldmont"; break; - case INTEL_FAM6_ATOM_GEMINI_LAKE: + case INTEL_FAM6_ATOM_GOLDMONT_PLUS: memcpy(hw_cache_event_ids, glp_hw_cache_event_ids, sizeof(hw_cache_event_ids)); memcpy(hw_cache_extra_regs, glp_hw_cache_extra_regs, diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c index 9f8084f18d58..d2e780705c5a 100644 --- a/arch/x86/events/intel/cstate.c +++ b/arch/x86/events/intel/cstate.c @@ -559,8 +559,8 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = { X86_CSTATES_MODEL(INTEL_FAM6_HASWELL_ULT, hswult_cstates), - X86_CSTATES_MODEL(INTEL_FAM6_ATOM_SILVERMONT1, slm_cstates), - X86_CSTATES_MODEL(INTEL_FAM6_ATOM_SILVERMONT2, slm_cstates), + X86_CSTATES_MODEL(INTEL_FAM6_ATOM_SILVERMONT, slm_cstates), + X86_CSTATES_MODEL(INTEL_FAM6_ATOM_SILVERMONT_X, slm_cstates), X86_CSTATES_MODEL(INTEL_FAM6_ATOM_AIRMONT, slm_cstates), X86_CSTATES_MODEL(INTEL_FAM6_BROADWELL_CORE, snb_cstates), @@ -581,9 +581,9 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = { X86_CSTATES_MODEL(INTEL_FAM6_XEON_PHI_KNM, knl_cstates), X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT, glm_cstates), - X86_CSTATES_MODEL(INTEL_FAM6_ATOM_DENVERTON, glm_cstates), + X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT_X, glm_cstates), - X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GEMINI_LAKE, glm_cstates), + X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT_PLUS, glm_cstates), { }, }; MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match); diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c index 32f3e9423e99..91039ffed633 100644 --- a/arch/x86/events/intel/rapl.c +++ b/arch/x86/events/intel/rapl.c @@ -777,9 +777,9 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = { X86_RAPL_MODEL_MATCH(INTEL_FAM6_CANNONLAKE_MOBILE, skl_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT, hsw_rapl_init), - X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_DENVERTON, hsw_rapl_init), + X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT_X, hsw_rapl_init), - X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GEMINI_LAKE, hsw_rapl_init), + X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT_PLUS, hsw_rapl_init), {}, }; diff --git a/arch/x86/events/msr.c b/arch/x86/events/msr.c index b4771a6ddbc1..1b9f85abf9bc 100644 --- a/arch/x86/events/msr.c +++ b/arch/x86/events/msr.c @@ -69,14 +69,14 @@ static bool test_intel(int idx) case INTEL_FAM6_BROADWELL_GT3E: case INTEL_FAM6_BROADWELL_X: - case INTEL_FAM6_ATOM_SILVERMONT1: - case INTEL_FAM6_ATOM_SILVERMONT2: + case INTEL_FAM6_ATOM_SILVERMONT: + case INTEL_FAM6_ATOM_SILVERMONT_X: case INTEL_FAM6_ATOM_AIRMONT: case INTEL_FAM6_ATOM_GOLDMONT: - case INTEL_FAM6_ATOM_DENVERTON: + case INTEL_FAM6_ATOM_GOLDMONT_X: - case INTEL_FAM6_ATOM_GEMINI_LAKE: + case INTEL_FAM6_ATOM_GOLDMONT_PLUS: case INTEL_FAM6_XEON_PHI_KNL: case INTEL_FAM6_XEON_PHI_KNM: diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h index 7ed08a7c3398..0dd6b0f4000e 100644 --- a/arch/x86/include/asm/intel-family.h +++ b/arch/x86/include/asm/intel-family.h @@ -8,9 +8,6 @@ * The "_X" parts are generally the EP and EX Xeons, or the * "Extreme" ones, like Broadwell-E. * - * Things ending in "2" are usually because we have no better - * name for them. There's no processor called "SILVERMONT2". - * * While adding a new CPUID for a new microarchitecture, add a new * group to keep logically sorted out in chronological order. Within * that group keep the CPUID for the variants sorted by model number. @@ -57,19 +54,23 @@ /* "Small Core" Processors (Atom) */ -#define INTEL_FAM6_ATOM_PINEVIEW 0x1C -#define INTEL_FAM6_ATOM_LINCROFT 0x26 -#define INTEL_FAM6_ATOM_PENWELL 0x27 -#define INTEL_FAM6_ATOM_CLOVERVIEW 0x35 -#define INTEL_FAM6_ATOM_CEDARVIEW 0x36 -#define INTEL_FAM6_ATOM_SILVERMONT1 0x37 /* BayTrail/BYT / Valleyview */ -#define INTEL_FAM6_ATOM_SILVERMONT2 0x4D /* Avaton/Rangely */ -#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* CherryTrail / Braswell */ -#define INTEL_FAM6_ATOM_MERRIFIELD 0x4A /* Tangier */ -#define INTEL_FAM6_ATOM_MOOREFIELD 0x5A /* Anniedale */ -#define INTEL_FAM6_ATOM_GOLDMONT 0x5C -#define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */ -#define INTEL_FAM6_ATOM_GEMINI_LAKE 0x7A +#define INTEL_FAM6_ATOM_BONNELL 0x1C /* Diamondville, Pineview */ +#define INTEL_FAM6_ATOM_BONNELL_MID 0x26 /* Silverthorne, Lincroft */ + +#define INTEL_FAM6_ATOM_SALTWELL 0x36 /* Cedarview */ +#define INTEL_FAM6_ATOM_SALTWELL_MID 0x27 /* Penwell */ +#define INTEL_FAM6_ATOM_SALTWELL_TABLET 0x35 /* Cloverview */ + +#define INTEL_FAM6_ATOM_SILVERMONT 0x37 /* Bay Trail, Valleyview */ +#define INTEL_FAM6_ATOM_SILVERMONT_X 0x4D /* Avaton, Rangely */ +#define INTEL_FAM6_ATOM_SILVERMONT_MID 0x4A /* Merriefield */ + +#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* Cherry Trail, Braswell */ +#define INTEL_FAM6_ATOM_AIRMONT_MID 0x5A /* Moorefield */ + +#define INTEL_FAM6_ATOM_GOLDMONT 0x5C /* Apollo Lake */ +#define INTEL_FAM6_ATOM_GOLDMONT_X 0x5F /* Denverton */ +#define INTEL_FAM6_ATOM_GOLDMONT_PLUS 0x7A /* Gemini Lake */ /* Xeon Phi */ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 44c4ef3d989b..10e5ccfa9278 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -949,11 +949,11 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c) } static const __initconst struct x86_cpu_id cpu_no_speculation[] = { - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_CEDARVIEW, X86_FEATURE_ANY }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_CLOVERVIEW, X86_FEATURE_ANY }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_LINCROFT, X86_FEATURE_ANY }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_PENWELL, X86_FEATURE_ANY }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_PINEVIEW, X86_FEATURE_ANY }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL, X86_FEATURE_ANY }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL_TABLET, X86_FEATURE_ANY }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_BONNELL_MID, X86_FEATURE_ANY }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL_MID, X86_FEATURE_ANY }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_BONNELL, X86_FEATURE_ANY }, { X86_VENDOR_CENTAUR, 5 }, { X86_VENDOR_INTEL, 5 }, { X86_VENDOR_NSC, 5 }, @@ -968,10 +968,10 @@ static const __initconst struct x86_cpu_id cpu_no_meltdown[] = { /* Only list CPUs which speculate but are non susceptible to SSB */ static const __initconst struct x86_cpu_id cpu_no_spec_store_bypass[] = { - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT }, { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT2 }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MERRIFIELD }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_X }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_MID }, { X86_VENDOR_INTEL, 6, INTEL_FAM6_CORE_YONAH }, { X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL }, { X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM }, @@ -984,14 +984,14 @@ static const __initconst struct x86_cpu_id cpu_no_spec_store_bypass[] = { static const __initconst struct x86_cpu_id cpu_no_l1tf[] = { /* in addition to cpu_no_speculation */ - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT2 }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_X }, { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MERRIFIELD }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MOOREFIELD }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_MID }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT_MID }, { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_DENVERTON }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GEMINI_LAKE }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT_X }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT_PLUS }, { X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL }, { X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM }, {} diff --git a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c index d68836139cf9..676c8a3ecdb2 100644 --- a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c +++ b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c @@ -93,7 +93,7 @@ static u64 get_prefetch_disable_bits(void) */ return 0xF; case INTEL_FAM6_ATOM_GOLDMONT: - case INTEL_FAM6_ATOM_GEMINI_LAKE: + case INTEL_FAM6_ATOM_GOLDMONT_PLUS: /* * SDM defines bits of MSR_MISC_FEATURE_CONTROL register * as: @@ -1068,7 +1068,7 @@ static int measure_l2_residency(void *_plr) */ switch (boot_cpu_data.x86_model) { case INTEL_FAM6_ATOM_GOLDMONT: - case INTEL_FAM6_ATOM_GEMINI_LAKE: + case INTEL_FAM6_ATOM_GOLDMONT_PLUS: perf_miss_attr.config = X86_CONFIG(.event = 0xd1, .umask = 0x10); perf_hit_attr.config = X86_CONFIG(.event = 0xd1, diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 6490f618e096..dd6b564f65e3 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -635,7 +635,7 @@ unsigned long native_calibrate_tsc(void) case INTEL_FAM6_KABYLAKE_DESKTOP: crystal_khz = 24000; /* 24.0 MHz */ break; - case INTEL_FAM6_ATOM_DENVERTON: + case INTEL_FAM6_ATOM_GOLDMONT_X: crystal_khz = 25000; /* 25.0 MHz */ break; case INTEL_FAM6_ATOM_GOLDMONT: diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c index 27ef714d886c..3d0e9aeea7c8 100644 --- a/arch/x86/kernel/tsc_msr.c +++ b/arch/x86/kernel/tsc_msr.c @@ -59,12 +59,12 @@ static const struct freq_desc freq_desc_ann = { }; static const struct x86_cpu_id tsc_msr_cpu_ids[] = { - INTEL_CPU_FAM6(ATOM_PENWELL, freq_desc_pnw), - INTEL_CPU_FAM6(ATOM_CLOVERVIEW, freq_desc_clv), - INTEL_CPU_FAM6(ATOM_SILVERMONT1, freq_desc_byt), + INTEL_CPU_FAM6(ATOM_SALTWELL_MID, freq_desc_pnw), + INTEL_CPU_FAM6(ATOM_SALTWELL_TABLET, freq_desc_clv), + INTEL_CPU_FAM6(ATOM_SILVERMONT, freq_desc_byt), + INTEL_CPU_FAM6(ATOM_SILVERMONT_MID, freq_desc_tng), INTEL_CPU_FAM6(ATOM_AIRMONT, freq_desc_cht), - INTEL_CPU_FAM6(ATOM_MERRIFIELD, freq_desc_tng), - INTEL_CPU_FAM6(ATOM_MOOREFIELD, freq_desc_ann), + INTEL_CPU_FAM6(ATOM_AIRMONT_MID, freq_desc_ann), {} }; diff --git a/arch/x86/platform/atom/punit_atom_debug.c b/arch/x86/platform/atom/punit_atom_debug.c index 034813d4ab1e..41dae0f0d898 100644 --- a/arch/x86/platform/atom/punit_atom_debug.c +++ b/arch/x86/platform/atom/punit_atom_debug.c @@ -143,8 +143,8 @@ static void punit_dbgfs_unregister(void) (kernel_ulong_t)&drv_data } static const struct x86_cpu_id intel_punit_cpu_ids[] = { - ICPU(INTEL_FAM6_ATOM_SILVERMONT1, punit_device_byt), - ICPU(INTEL_FAM6_ATOM_MERRIFIELD, punit_device_tng), + ICPU(INTEL_FAM6_ATOM_SILVERMONT, punit_device_byt), + ICPU(INTEL_FAM6_ATOM_SILVERMONT_MID, punit_device_tng), ICPU(INTEL_FAM6_ATOM_AIRMONT, punit_device_cht), {} }; diff --git a/arch/x86/platform/intel-mid/device_libs/platform_bt.c b/arch/x86/platform/intel-mid/device_libs/platform_bt.c index 5a0483e7bf66..31dce781364c 100644 --- a/arch/x86/platform/intel-mid/device_libs/platform_bt.c +++ b/arch/x86/platform/intel-mid/device_libs/platform_bt.c @@ -68,7 +68,7 @@ static struct bt_sfi_data tng_bt_sfi_data __initdata = { { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (kernel_ulong_t)&ddata } static const struct x86_cpu_id bt_sfi_cpu_ids[] = { - ICPU(INTEL_FAM6_ATOM_MERRIFIELD, tng_bt_sfi_data), + ICPU(INTEL_FAM6_ATOM_SILVERMONT_MID, tng_bt_sfi_data), {} }; diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index bf64cfa30feb..9efa3a588620 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -292,7 +292,7 @@ static const struct lpss_device_desc bsw_spi_dev_desc = { #define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, } static const struct x86_cpu_id lpss_cpu_ids[] = { - ICPU(INTEL_FAM6_ATOM_SILVERMONT1), /* Valleyview, Bay Trail */ + ICPU(INTEL_FAM6_ATOM_SILVERMONT), /* Valleyview, Bay Trail */ ICPU(INTEL_FAM6_ATOM_AIRMONT), /* Braswell, Cherry Trail */ {} }; diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index 06c31ec3cc70..9a8e286dd86f 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -54,7 +54,7 @@ static const struct always_present_id always_present_ids[] = { * Bay / Cherry Trail PWM directly poked by GPU driver in win10, * but Linux uses a separate PWM driver, harmless if not used. */ - ENTRY("80860F09", "1", ICPU(INTEL_FAM6_ATOM_SILVERMONT1), {}), + ENTRY("80860F09", "1", ICPU(INTEL_FAM6_ATOM_SILVERMONT), {}), ENTRY("80862288", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {}), /* * The INT0002 device is necessary to clear wakeup interrupt sources diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index b6a1aadaff9f..75140dd07037 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -1778,7 +1778,7 @@ static const struct pstate_funcs knl_funcs = { static const struct x86_cpu_id intel_pstate_cpu_ids[] = { ICPU(INTEL_FAM6_SANDYBRIDGE, core_funcs), ICPU(INTEL_FAM6_SANDYBRIDGE_X, core_funcs), - ICPU(INTEL_FAM6_ATOM_SILVERMONT1, silvermont_funcs), + ICPU(INTEL_FAM6_ATOM_SILVERMONT, silvermont_funcs), ICPU(INTEL_FAM6_IVYBRIDGE, core_funcs), ICPU(INTEL_FAM6_HASWELL_CORE, core_funcs), ICPU(INTEL_FAM6_BROADWELL_CORE, core_funcs), @@ -1795,7 +1795,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = { ICPU(INTEL_FAM6_XEON_PHI_KNL, knl_funcs), ICPU(INTEL_FAM6_XEON_PHI_KNM, knl_funcs), ICPU(INTEL_FAM6_ATOM_GOLDMONT, core_funcs), - ICPU(INTEL_FAM6_ATOM_GEMINI_LAKE, core_funcs), + ICPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS, core_funcs), ICPU(INTEL_FAM6_SKYLAKE_X, core_funcs), {} }; diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c index df28b65358d2..903a4f1fadcc 100644 --- a/drivers/edac/pnd2_edac.c +++ b/drivers/edac/pnd2_edac.c @@ -1541,7 +1541,7 @@ static struct dunit_ops dnv_ops = { static const struct x86_cpu_id pnd2_cpuids[] = { { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT, 0, (kernel_ulong_t)&apl_ops }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_DENVERTON, 0, (kernel_ulong_t)&dnv_ops }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT_X, 0, (kernel_ulong_t)&dnv_ops }, { } }; MODULE_DEVICE_TABLE(x86cpu, pnd2_cpuids); diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index b2ccce5fb071..c4bb67ed8da3 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -1076,14 +1076,14 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { ICPU(INTEL_FAM6_WESTMERE, idle_cpu_nehalem), ICPU(INTEL_FAM6_WESTMERE_EP, idle_cpu_nehalem), ICPU(INTEL_FAM6_NEHALEM_EX, idle_cpu_nehalem), - ICPU(INTEL_FAM6_ATOM_PINEVIEW, idle_cpu_atom), - ICPU(INTEL_FAM6_ATOM_LINCROFT, idle_cpu_lincroft), + ICPU(INTEL_FAM6_ATOM_BONNELL, idle_cpu_atom), + ICPU(INTEL_FAM6_ATOM_BONNELL_MID, idle_cpu_lincroft), ICPU(INTEL_FAM6_WESTMERE_EX, idle_cpu_nehalem), ICPU(INTEL_FAM6_SANDYBRIDGE, idle_cpu_snb), ICPU(INTEL_FAM6_SANDYBRIDGE_X, idle_cpu_snb), - ICPU(INTEL_FAM6_ATOM_CEDARVIEW, idle_cpu_atom), - ICPU(INTEL_FAM6_ATOM_SILVERMONT1, idle_cpu_byt), - ICPU(INTEL_FAM6_ATOM_MERRIFIELD, idle_cpu_tangier), + ICPU(INTEL_FAM6_ATOM_SALTWELL, idle_cpu_atom), + ICPU(INTEL_FAM6_ATOM_SILVERMONT, idle_cpu_byt), + ICPU(INTEL_FAM6_ATOM_SILVERMONT_MID, idle_cpu_tangier), ICPU(INTEL_FAM6_ATOM_AIRMONT, idle_cpu_cht), ICPU(INTEL_FAM6_IVYBRIDGE, idle_cpu_ivb), ICPU(INTEL_FAM6_IVYBRIDGE_X, idle_cpu_ivt), @@ -1091,7 +1091,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { ICPU(INTEL_FAM6_HASWELL_X, idle_cpu_hsw), ICPU(INTEL_FAM6_HASWELL_ULT, idle_cpu_hsw), ICPU(INTEL_FAM6_HASWELL_GT3E, idle_cpu_hsw), - ICPU(INTEL_FAM6_ATOM_SILVERMONT2, idle_cpu_avn), + ICPU(INTEL_FAM6_ATOM_SILVERMONT_X, idle_cpu_avn), ICPU(INTEL_FAM6_BROADWELL_CORE, idle_cpu_bdw), ICPU(INTEL_FAM6_BROADWELL_GT3E, idle_cpu_bdw), ICPU(INTEL_FAM6_BROADWELL_X, idle_cpu_bdw), @@ -1104,8 +1104,8 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { ICPU(INTEL_FAM6_XEON_PHI_KNL, idle_cpu_knl), ICPU(INTEL_FAM6_XEON_PHI_KNM, idle_cpu_knl), ICPU(INTEL_FAM6_ATOM_GOLDMONT, idle_cpu_bxt), - ICPU(INTEL_FAM6_ATOM_GEMINI_LAKE, idle_cpu_bxt), - ICPU(INTEL_FAM6_ATOM_DENVERTON, idle_cpu_dnv), + ICPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS, idle_cpu_bxt), + ICPU(INTEL_FAM6_ATOM_GOLDMONT_X, idle_cpu_dnv), {} }; @@ -1322,7 +1322,7 @@ static void intel_idle_state_table_update(void) ivt_idle_state_table_update(); break; case INTEL_FAM6_ATOM_GOLDMONT: - case INTEL_FAM6_ATOM_GEMINI_LAKE: + case INTEL_FAM6_ATOM_GOLDMONT_PLUS: bxt_idle_state_table_update(); break; case INTEL_FAM6_SKYLAKE_DESKTOP: diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 32321bd596d8..cca6cde1b7e8 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -246,7 +246,7 @@ static const struct sdhci_acpi_chip sdhci_acpi_chip_int = { static bool sdhci_acpi_byt(void) { static const struct x86_cpu_id byt[] = { - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT }, {} }; diff --git a/drivers/pci/pci-mid.c b/drivers/pci/pci-mid.c index 314e135014dc..30fbe2ea6eab 100644 --- a/drivers/pci/pci-mid.c +++ b/drivers/pci/pci-mid.c @@ -62,8 +62,8 @@ static const struct pci_platform_pm_ops mid_pci_platform_pm = { * arch/x86/platform/intel-mid/pwr.c. */ static const struct x86_cpu_id lpss_cpu_ids[] = { - ICPU(INTEL_FAM6_ATOM_PENWELL), - ICPU(INTEL_FAM6_ATOM_MERRIFIELD), + ICPU(INTEL_FAM6_ATOM_SALTWELL_MID), + ICPU(INTEL_FAM6_ATOM_SILVERMONT_MID), {} }; diff --git a/drivers/platform/x86/intel_int0002_vgpio.c b/drivers/platform/x86/intel_int0002_vgpio.c index a473dc51b18d..e89ad4964dc1 100644 --- a/drivers/platform/x86/intel_int0002_vgpio.c +++ b/drivers/platform/x86/intel_int0002_vgpio.c @@ -60,7 +60,7 @@ static const struct x86_cpu_id int0002_cpu_ids[] = { /* * Limit ourselves to Cherry Trail for now, until testing shows we * need to handle the INT0002 device on Baytrail too. - * ICPU(INTEL_FAM6_ATOM_SILVERMONT1), * Valleyview, Bay Trail * + * ICPU(INTEL_FAM6_ATOM_SILVERMONT), * Valleyview, Bay Trail * */ ICPU(INTEL_FAM6_ATOM_AIRMONT), /* Braswell, Cherry Trail */ {} diff --git a/drivers/platform/x86/intel_mid_powerbtn.c b/drivers/platform/x86/intel_mid_powerbtn.c index d79fbf924b13..5ad44204a9c3 100644 --- a/drivers/platform/x86/intel_mid_powerbtn.c +++ b/drivers/platform/x86/intel_mid_powerbtn.c @@ -125,8 +125,8 @@ static const struct mid_pb_ddata mrfld_ddata = { { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (kernel_ulong_t)&ddata } static const struct x86_cpu_id mid_pb_cpu_ids[] = { - ICPU(INTEL_FAM6_ATOM_PENWELL, mfld_ddata), - ICPU(INTEL_FAM6_ATOM_MERRIFIELD, mrfld_ddata), + ICPU(INTEL_FAM6_ATOM_SALTWELL_MID, mfld_ddata), + ICPU(INTEL_FAM6_ATOM_SILVERMONT_MID, mrfld_ddata), {} }; diff --git a/drivers/platform/x86/intel_telemetry_debugfs.c b/drivers/platform/x86/intel_telemetry_debugfs.c index ffd0474b0531..cee08f236292 100644 --- a/drivers/platform/x86/intel_telemetry_debugfs.c +++ b/drivers/platform/x86/intel_telemetry_debugfs.c @@ -320,7 +320,7 @@ static struct telemetry_debugfs_conf telem_apl_debugfs_conf = { static const struct x86_cpu_id telemetry_debugfs_cpu_ids[] = { TELEM_DEBUGFS_CPU(INTEL_FAM6_ATOM_GOLDMONT, telem_apl_debugfs_conf), - TELEM_DEBUGFS_CPU(INTEL_FAM6_ATOM_GEMINI_LAKE, telem_apl_debugfs_conf), + TELEM_DEBUGFS_CPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS, telem_apl_debugfs_conf), {} }; diff --git a/drivers/platform/x86/intel_telemetry_pltdrv.c b/drivers/platform/x86/intel_telemetry_pltdrv.c index 2f889d6c270e..fcc6bee51a42 100644 --- a/drivers/platform/x86/intel_telemetry_pltdrv.c +++ b/drivers/platform/x86/intel_telemetry_pltdrv.c @@ -192,7 +192,7 @@ static struct telemetry_plt_config telem_glk_config = { static const struct x86_cpu_id telemetry_cpu_ids[] = { TELEM_CPU(INTEL_FAM6_ATOM_GOLDMONT, telem_apl_config), - TELEM_CPU(INTEL_FAM6_ATOM_GEMINI_LAKE, telem_glk_config), + TELEM_CPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS, telem_glk_config), {} }; diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c index 295d8dcba48c..8cbfcce57a06 100644 --- a/drivers/powercap/intel_rapl.c +++ b/drivers/powercap/intel_rapl.c @@ -1164,13 +1164,13 @@ static const struct x86_cpu_id rapl_ids[] __initconst = { RAPL_CPU(INTEL_FAM6_KABYLAKE_DESKTOP, rapl_defaults_core), RAPL_CPU(INTEL_FAM6_CANNONLAKE_MOBILE, rapl_defaults_core), - RAPL_CPU(INTEL_FAM6_ATOM_SILVERMONT1, rapl_defaults_byt), + RAPL_CPU(INTEL_FAM6_ATOM_SILVERMONT, rapl_defaults_byt), RAPL_CPU(INTEL_FAM6_ATOM_AIRMONT, rapl_defaults_cht), - RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD, rapl_defaults_tng), - RAPL_CPU(INTEL_FAM6_ATOM_MOOREFIELD, rapl_defaults_ann), + RAPL_CPU(INTEL_FAM6_ATOM_SILVERMONT_MID, rapl_defaults_tng), + RAPL_CPU(INTEL_FAM6_ATOM_AIRMONT_MID, rapl_defaults_ann), RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT, rapl_defaults_core), - RAPL_CPU(INTEL_FAM6_ATOM_GEMINI_LAKE, rapl_defaults_core), - RAPL_CPU(INTEL_FAM6_ATOM_DENVERTON, rapl_defaults_core), + RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS, rapl_defaults_core), + RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT_X, rapl_defaults_core), RAPL_CPU(INTEL_FAM6_XEON_PHI_KNL, rapl_defaults_hsw_server), RAPL_CPU(INTEL_FAM6_XEON_PHI_KNM, rapl_defaults_hsw_server), diff --git a/drivers/thermal/intel_soc_dts_thermal.c b/drivers/thermal/intel_soc_dts_thermal.c index 1e47511a6bd5..d748527d7a38 100644 --- a/drivers/thermal/intel_soc_dts_thermal.c +++ b/drivers/thermal/intel_soc_dts_thermal.c @@ -45,7 +45,7 @@ static irqreturn_t soc_irq_thread_fn(int irq, void *dev_data) } static const struct x86_cpu_id soc_thermal_ids[] = { - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1, 0, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT, 0, BYT_SOC_DTS_APIC_IRQ}, {} }; diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index f8a68bdb3885..6af02bf879ac 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -787,7 +787,7 @@ static struct snd_soc_card byt_rt5651_card = { }; static const struct x86_cpu_id baytrail_cpu_ids[] = { - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 }, /* Valleyview */ + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT }, /* Valleyview */ {} }; diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 980bd9d20646..328f62e6ea02 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -2082,7 +2082,7 @@ int has_turbo_ratio_group_limits(int family, int model) switch (model) { case INTEL_FAM6_ATOM_GOLDMONT: case INTEL_FAM6_SKYLAKE_X: - case INTEL_FAM6_ATOM_DENVERTON: + case INTEL_FAM6_ATOM_GOLDMONT_X: return 1; } return 0; @@ -3149,9 +3149,9 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) pkg_cstate_limits = skx_pkg_cstate_limits; has_misc_feature_control = 1; break; - case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */ + case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ no_MSR_MISC_PWR_MGMT = 1; - case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */ + case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */ pkg_cstate_limits = slv_pkg_cstate_limits; break; case INTEL_FAM6_ATOM_AIRMONT: /* AMT */ @@ -3163,8 +3163,8 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) pkg_cstate_limits = phi_pkg_cstate_limits; break; case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ - case INTEL_FAM6_ATOM_GEMINI_LAKE: - case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ + case INTEL_FAM6_ATOM_GOLDMONT_PLUS: + case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */ pkg_cstate_limits = bxt_pkg_cstate_limits; break; default: @@ -3193,9 +3193,9 @@ int has_slv_msrs(unsigned int family, unsigned int model) return 0; switch (model) { - case INTEL_FAM6_ATOM_SILVERMONT1: - case INTEL_FAM6_ATOM_MERRIFIELD: - case INTEL_FAM6_ATOM_MOOREFIELD: + case INTEL_FAM6_ATOM_SILVERMONT: + case INTEL_FAM6_ATOM_SILVERMONT_MID: + case INTEL_FAM6_ATOM_AIRMONT_MID: return 1; } return 0; @@ -3207,7 +3207,7 @@ int is_dnv(unsigned int family, unsigned int model) return 0; switch (model) { - case INTEL_FAM6_ATOM_DENVERTON: + case INTEL_FAM6_ATOM_GOLDMONT_X: return 1; } return 0; @@ -3724,8 +3724,8 @@ double get_tdp(unsigned int model) return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units; switch (model) { - case INTEL_FAM6_ATOM_SILVERMONT1: - case INTEL_FAM6_ATOM_SILVERMONT2: + case INTEL_FAM6_ATOM_SILVERMONT: + case INTEL_FAM6_ATOM_SILVERMONT_X: return 30.0; default: return 135.0; @@ -3791,7 +3791,7 @@ void rapl_probe(unsigned int family, unsigned int model) } break; case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ - case INTEL_FAM6_ATOM_GEMINI_LAKE: + case INTEL_FAM6_ATOM_GOLDMONT_PLUS: do_rapl = RAPL_PKG | RAPL_PKG_POWER_INFO; if (rapl_joules) BIC_PRESENT(BIC_Pkg_J); @@ -3850,8 +3850,8 @@ void rapl_probe(unsigned int family, unsigned int model) BIC_PRESENT(BIC_RAMWatt); } break; - case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */ - case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */ + case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ + case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */ do_rapl = RAPL_PKG | RAPL_CORES; if (rapl_joules) { BIC_PRESENT(BIC_Pkg_J); @@ -3861,7 +3861,7 @@ void rapl_probe(unsigned int family, unsigned int model) BIC_PRESENT(BIC_CorWatt); } break; - case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ + case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */ do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO | RAPL_CORES_ENERGY_STATUS; BIC_PRESENT(BIC_PKG__); BIC_PRESENT(BIC_RAM__); @@ -3884,7 +3884,7 @@ void rapl_probe(unsigned int family, unsigned int model) return; rapl_power_units = 1.0 / (1 << (msr & 0xF)); - if (model == INTEL_FAM6_ATOM_SILVERMONT1) + if (model == INTEL_FAM6_ATOM_SILVERMONT) rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000; else rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F)); @@ -4141,8 +4141,8 @@ int has_snb_msrs(unsigned int family, unsigned int model) case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */ case INTEL_FAM6_SKYLAKE_X: /* SKX */ case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ - case INTEL_FAM6_ATOM_GEMINI_LAKE: - case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ + case INTEL_FAM6_ATOM_GOLDMONT_PLUS: + case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */ return 1; } return 0; @@ -4174,7 +4174,7 @@ int has_hsw_msrs(unsigned int family, unsigned int model) case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */ case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ - case INTEL_FAM6_ATOM_GEMINI_LAKE: + case INTEL_FAM6_ATOM_GOLDMONT_PLUS: return 1; } return 0; @@ -4209,8 +4209,8 @@ int is_slm(unsigned int family, unsigned int model) if (!genuine_intel) return 0; switch (model) { - case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */ - case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */ + case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ + case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */ return 1; } return 0; @@ -4581,11 +4581,11 @@ void process_cpuid() case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ crystal_hz = 24000000; /* 24.0 MHz */ break; - case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ + case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */ crystal_hz = 25000000; /* 25.0 MHz */ break; case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ - case INTEL_FAM6_ATOM_GEMINI_LAKE: + case INTEL_FAM6_ATOM_GOLDMONT_PLUS: crystal_hz = 19200000; /* 19.2 MHz */ break; default: From 7c5314b88da6d5af98239786772a1c44cc5eb67d Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Wed, 8 Aug 2018 00:12:08 -0700 Subject: [PATCH 132/155] perf/x86/intel: Add quirk for Goldmont Plus A ucode patch is needed for Goldmont Plus while counter freezing feature is enabled. Otherwise, there will be some issues, e.g. PMI flood with some events. Add a quirk to check microcode version. If the system starts with the wrong ucode, leave the counter-freezing feature permanently disabled. Signed-off-by: Kan Liang Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: acme@kernel.org Link: http://lkml.kernel.org/r/1533712328-2834-3-git-send-email-kan.liang@linux.intel.com Signed-off-by: Ingo Molnar --- arch/x86/events/intel/core.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index f17cf6c3ec6f..ab01ef9ddd77 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -3839,6 +3839,40 @@ static __init void intel_nehalem_quirk(void) } } +static bool intel_glp_counter_freezing_broken(int cpu) +{ + u32 rev = UINT_MAX; /* default to broken for unknown stepping */ + + switch (cpu_data(cpu).x86_stepping) { + case 1: + rev = 0x28; + break; + case 8: + rev = 0x6; + break; + } + + return (cpu_data(cpu).microcode < rev); +} + +static __init void intel_glp_counter_freezing_quirk(void) +{ + /* Check if it's already disabled */ + if (disable_counter_freezing) + return; + + /* + * If the system starts with the wrong ucode, leave the + * counter-freezing feature permanently disabled. + */ + if (intel_glp_counter_freezing_broken(raw_smp_processor_id())) { + pr_info("PMU counter freezing disabled due to CPU errata," + "please upgrade microcode\n"); + x86_pmu.counter_freezing = false; + x86_pmu.handle_irq = intel_pmu_handle_irq; + } +} + /* * enable software workaround for errata: * SNB: BJ122 @@ -4188,6 +4222,7 @@ __init int intel_pmu_init(void) break; case INTEL_FAM6_ATOM_GOLDMONT_PLUS: + x86_add_quirk(intel_glp_counter_freezing_quirk); memcpy(hw_cache_event_ids, glp_hw_cache_event_ids, sizeof(hw_cache_event_ids)); memcpy(hw_cache_extra_regs, glp_hw_cache_extra_regs, From 53ed74af05517cf5fe83d87c4bb7ab998adfd631 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Wed, 19 Sep 2018 10:29:11 -0700 Subject: [PATCH 133/155] x86/intel_rdt: Re-enable pseudo-lock measurements Commit 4a7a54a55e72 ("x86/intel_rdt: Disable PMU access") disabled measurements of pseudo-locked regions because of incorrect usage of the performance monitoring hardware. Cache pseudo-locking measurements are now done correctly with the in-kernel perf API and its use can be re-enabled at this time. The adjustment to the in-kernel perf API also separated the L2 and L3 measurements that can be triggered separately from user space. The re-enabling of the measurements is thus not a simple revert of the original disable in order to accommodate the additional parameter possible. Signed-off-by: Reinette Chatre Signed-off-by: Thomas Gleixner Cc: fenghua.yu@intel.com Cc: tony.luck@intel.com Cc: peterz@infradead.org Cc: acme@kernel.org Cc: gavin.hindman@intel.com Cc: jithu.joseph@intel.com Cc: dave.hansen@intel.com Cc: hpa@zytor.com Link: https://lkml.kernel.org/r/bfb9fc31692e0c62d9ca39062e55eceb6a0635b5.1537377064.git.reinette.chatre@intel.com --- arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c index d68836139cf9..30e6c9f5a0ad 100644 --- a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c +++ b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c @@ -1236,7 +1236,7 @@ static ssize_t pseudo_lock_measure_trigger(struct file *file, buf[buf_size] = '\0'; ret = kstrtoint(buf, 10, &sel); if (ret == 0) { - if (sel != 1) + if (sel != 1 && sel != 2 && sel != 3) return -EINVAL; ret = debugfs_file_get(file->f_path.dentry); if (ret) From 82159876d32b7959c0b0ea8fe12c428f41502a6f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 Aug 2018 14:50:39 +0300 Subject: [PATCH 134/155] x86/intel_rdt: Switch to bitmap_zalloc() Switch to bitmap_zalloc() to show clearly what is allocated. Besides that it returns a pointer of bitmap type instead of opaque void *. Signed-off-by: Andy Shevchenko Signed-off-by: Thomas Gleixner Acked-by: Fenghua Yu Cc: "H. Peter Anvin" Link: https://lkml.kernel.org/r/20180830115039.63430-1-andriy.shevchenko@linux.intel.com --- arch/x86/kernel/cpu/intel_rdt.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index abb71ac70443..1214f3f7ec6d 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -485,9 +485,7 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d) size_t tsize; if (is_llc_occupancy_enabled()) { - d->rmid_busy_llc = kcalloc(BITS_TO_LONGS(r->num_rmid), - sizeof(unsigned long), - GFP_KERNEL); + d->rmid_busy_llc = bitmap_zalloc(r->num_rmid, GFP_KERNEL); if (!d->rmid_busy_llc) return -ENOMEM; INIT_DELAYED_WORK(&d->cqm_limbo, cqm_handle_limbo); @@ -496,7 +494,7 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d) tsize = sizeof(*d->mbm_total); d->mbm_total = kcalloc(r->num_rmid, tsize, GFP_KERNEL); if (!d->mbm_total) { - kfree(d->rmid_busy_llc); + bitmap_free(d->rmid_busy_llc); return -ENOMEM; } } @@ -504,7 +502,7 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d) tsize = sizeof(*d->mbm_local); d->mbm_local = kcalloc(r->num_rmid, tsize, GFP_KERNEL); if (!d->mbm_local) { - kfree(d->rmid_busy_llc); + bitmap_free(d->rmid_busy_llc); kfree(d->mbm_total); return -ENOMEM; } @@ -612,7 +610,7 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r) kfree(d->ctrl_val); kfree(d->mbps_val); - kfree(d->rmid_busy_llc); + bitmap_free(d->rmid_busy_llc); kfree(d->mbm_total); kfree(d->mbm_local); kfree(d); From 2cc81c6992248ea37d0241bc325977bab310bc3b Mon Sep 17 00:00:00 2001 From: Xiaochen Shen Date: Wed, 12 Sep 2018 16:48:38 -0700 Subject: [PATCH 135/155] x86/intel_rdt: Show missing resctrl mount options In resctrl filesystem, mount options exist to enable L3/L2 CDP and MBA Software Controller features if the platform supports them: mount -t resctrl resctrl [-o cdp[,cdpl2][,mba_MBps]] /sys/fs/resctrl But currently only "cdp" option is displayed in /proc/mounts. "cdpl2" and "mba_MBps" options are not shown even when they are active. Before: # mount -t resctrl resctrl -o cdp,mba_MBps /sys/fs/resctrl # grep resctrl /proc/mounts /sys/fs/resctrl /sys/fs/resctrl resctrl rw,relatime,cdp 0 0 After: # mount -t resctrl resctrl -o cdp,mba_MBps /sys/fs/resctrl # grep resctrl /proc/mounts /sys/fs/resctrl /sys/fs/resctrl resctrl rw,relatime,cdp,mba_MBps 0 0 Signed-off-by: Xiaochen Shen Signed-off-by: Fenghua Yu Signed-off-by: Thomas Gleixner Cc: "H Peter Anvin" Cc: "Tony Luck" Link: https://lkml.kernel.org/r/1536796118-60135-1-git-send-email-fenghua.yu@intel.com --- arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c index 1b8e86a5d5e1..82a487840eb2 100644 --- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c @@ -2795,6 +2795,13 @@ static int rdtgroup_show_options(struct seq_file *seq, struct kernfs_root *kf) { if (rdt_resources_all[RDT_RESOURCE_L3DATA].alloc_enabled) seq_puts(seq, ",cdp"); + + if (rdt_resources_all[RDT_RESOURCE_L2DATA].alloc_enabled) + seq_puts(seq, ",cdpl2"); + + if (is_mba_sc(&rdt_resources_all[RDT_RESOURCE_MBA])) + seq_puts(seq, ",mba_MBps"); + return 0; } From ba4aa02b417f08a0bee5e7b8ed70cac788a7c854 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Sep 2018 10:55:59 -0300 Subject: [PATCH 136/155] tools include: Adopt linux/bits.h So that we reduce the difference of tools/include/linux/bitops.h to the original kernel file, include/linux/bitops.h, trying to remove the need to define BITS_PER_LONG, to avoid clashes with asm/bitsperlong.h. And the things removed from tools/include/linux/bitops.h are really in linux/bits.h, so that we can have a copy and then tools/perf/check_headers.sh will tell us when new stuff gets added to linux/bits.h so that we can check if it is useful and if any adjustment needs to be done to the tools/{include,arch}/ copies. Cc: Adrian Hunter Cc: Alexander Sverdlin Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-y1sqyydvfzo0bjjoj4zsl562@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/linux/bitops.h | 7 ++----- tools/include/linux/bits.h | 26 ++++++++++++++++++++++++++ tools/perf/check-headers.sh | 1 + 3 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 tools/include/linux/bits.h diff --git a/tools/include/linux/bitops.h b/tools/include/linux/bitops.h index acc704bd3998..0b0ef3abc966 100644 --- a/tools/include/linux/bitops.h +++ b/tools/include/linux/bitops.h @@ -3,8 +3,6 @@ #define _TOOLS_LINUX_BITOPS_H_ #include -#include - #ifndef __WORDSIZE #define __WORDSIZE (__SIZEOF_LONG__ * 8) #endif @@ -12,10 +10,9 @@ #ifndef BITS_PER_LONG # define BITS_PER_LONG __WORDSIZE #endif +#include +#include -#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) -#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) -#define BITS_PER_BYTE 8 #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) #define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64)) #define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32)) diff --git a/tools/include/linux/bits.h b/tools/include/linux/bits.h new file mode 100644 index 000000000000..2b7b532c1d51 --- /dev/null +++ b/tools/include/linux/bits.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_BITS_H +#define __LINUX_BITS_H +#include + +#define BIT(nr) (1UL << (nr)) +#define BIT_ULL(nr) (1ULL << (nr)) +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) +#define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG)) +#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG) +#define BITS_PER_BYTE 8 + +/* + * Create a contiguous bitmask starting at bit position @l and ending at + * position @h. For example + * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000. + */ +#define GENMASK(h, l) \ + (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) + +#define GENMASK_ULL(h, l) \ + (((~0ULL) - (1ULL << (l)) + 1) & \ + (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h)))) + +#endif /* __LINUX_BITS_H */ diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh index 466540ee8ea7..c72cc73a6b09 100755 --- a/tools/perf/check-headers.sh +++ b/tools/perf/check-headers.sh @@ -14,6 +14,7 @@ include/uapi/linux/sched.h include/uapi/linux/stat.h include/uapi/linux/vhost.h include/uapi/sound/asound.h +include/linux/bits.h include/linux/hash.h include/uapi/linux/hw_breakpoint.h arch/x86/include/asm/disabled-features.h From 291ed51deee49ff35d0824fb7050538b449964d6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Sep 2018 11:52:10 -0300 Subject: [PATCH 137/155] perf auxtrace: Include missing asm/bitsperlong.h to get BITS_PER_LONG The auxtrace.h header references BITS_PER_LONG without including the header where it is defined, getting it by luck from some other header, fix it. Cc: Adrian Hunter Cc: Alexander Sverdlin Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-v04ydmbh7tvpcctf3zld9j9s@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/auxtrace.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index 0a6ce9c4fc11..d88f6e9eb461 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "../perf.h" #include "event.h" From 0e24147d69c9357b1ccb54a9bc028eb9a9f9ed1a Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Fri, 28 Sep 2018 12:53:35 +0200 Subject: [PATCH 138/155] perf test: S390 does not support watchpoints in test 22 S390 does not support the perf_event_open system call for attribute type PERF_TYPE_BREAKPOINT. This results in test failure for test 22: [root@s8360046 perf]# ./perf test 22 22: Watchpoint : 22.1: Read Only Watchpoint : FAILED! 22.2: Write Only Watchpoint : FAILED! 22.3: Read / Write Watchpoint : FAILED! 22.4: Modify Watchpoint : FAILED! [root@s8360046 perf]# Add s390 support to avoid these tests being executed on s390 platform: [root@s8360046 perf]# ./perf test 22 [root@s8360046 perf]# ./perf test -v 22 22: Watchpoint : Disabled [root@s8360046 perf]# Signed-off-by: Thomas Richter Reviewed-by: Ravi Bangoria Cc: Heiko Carstens Cc: Hendrik Brueckner Cc: Martin Schwidefsky Link: http://lkml.kernel.org/r/20180928105335.67179-1-tmricht@linux.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/builtin-test.c | 1 + tools/perf/tests/tests.h | 1 + tools/perf/tests/wp.c | 12 ++++++++++++ 3 files changed, 14 insertions(+) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 54ca7d87236f..12c09e0ece71 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -123,6 +123,7 @@ static struct test generic_tests[] = { { .desc = "Watchpoint", .func = test__wp, + .is_supported = test__wp_is_supported, .subtest = { .skip_if_fail = false, .get_nr = test__wp_subtest_get_nr, diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 8e26a4148f30..b82f55fcc294 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -109,6 +109,7 @@ int test__unit_number__scnprint(struct test *test, int subtest); int test__mem2node(struct test *t, int subtest); bool test__bp_signal_is_supported(void); +bool test__wp_is_supported(void); #if defined(__arm__) || defined(__aarch64__) #ifdef HAVE_DWARF_UNWIND_SUPPORT diff --git a/tools/perf/tests/wp.c b/tools/perf/tests/wp.c index 017a99317f94..f89e6806557b 100644 --- a/tools/perf/tests/wp.c +++ b/tools/perf/tests/wp.c @@ -227,3 +227,15 @@ int test__wp(struct test *test __maybe_unused, int i) return !wp_testcase_table[i].target_func() ? TEST_OK : TEST_FAIL; } + +/* The s390 so far does not have support for + * instruction breakpoint using the perf_event_open() system call. + */ +bool test__wp_is_supported(void) +{ +#if defined(__s390x__) + return false; +#else + return true; +#endif +} From ce49d8436cffa9b7a6a5f110879d53e89dbc6746 Mon Sep 17 00:00:00 2001 From: Sanskriti Sharma Date: Tue, 2 Oct 2018 10:29:10 -0400 Subject: [PATCH 139/155] perf strbuf: Match va_{add,copy} with va_end Ensure that all code paths in strbuf_addv() call va_end() on the ap_saved copy that was made. Fixes the following coverity complaint: Error: VARARGS (CWE-237): [#def683] tools/perf/util/strbuf.c:106: missing_va_end: va_end was not called for "ap_saved". Signed-off-by: Sanskriti Sharma Reviewed-by: Jiri Olsa Cc: Joe Lawrence Link: http://lkml.kernel.org/r/1538490554-8161-2-git-send-email-sansharm@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/strbuf.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index 3d1cf5bf7f18..9005fbe0780e 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c @@ -98,19 +98,25 @@ static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap) va_copy(ap_saved, ap); len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); - if (len < 0) + if (len < 0) { + va_end(ap_saved); return len; + } if (len > strbuf_avail(sb)) { ret = strbuf_grow(sb, len); - if (ret) + if (ret) { + va_end(ap_saved); return ret; + } len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved); va_end(ap_saved); if (len > strbuf_avail(sb)) { pr_debug("this should not happen, your vsnprintf is broken"); + va_end(ap_saved); return -EINVAL; } } + va_end(ap_saved); return strbuf_setlen(sb, sb->len + len); } From faedbf3fd19f2511a39397f76359e4cc6ee93072 Mon Sep 17 00:00:00 2001 From: Sanskriti Sharma Date: Tue, 2 Oct 2018 10:29:11 -0400 Subject: [PATCH 140/155] perf tools: Cleanup trace-event-info 'tdata' leak Free tracing_data structure in tracing_data_get() error paths. Fixes the following coverity complaint: Error: RESOURCE_LEAK (CWE-772): leaked_storage: Variable "tdata" going out of scope leaks the storage Signed-off-by: Sanskriti Sharma Reviewed-by: Jiri Olsa Cc: Joe Lawrence Link: http://lkml.kernel.org/r/1538490554-8161-3-git-send-email-sansharm@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event-info.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 7b0ca7cbb7de..8ad8e755127b 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -531,12 +531,14 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs, "/tmp/perf-XXXXXX"); if (!mkstemp(tdata->temp_file)) { pr_debug("Can't make temp file"); + free(tdata); return NULL; } temp_fd = open(tdata->temp_file, O_RDWR); if (temp_fd < 0) { pr_debug("Can't read '%s'", tdata->temp_file); + free(tdata); return NULL; } From 9c8a182e5a73e01afd11742a2ab887bf338fdafd Mon Sep 17 00:00:00 2001 From: Sanskriti Sharma Date: Tue, 2 Oct 2018 10:29:12 -0400 Subject: [PATCH 141/155] perf tools: Free 'printk' string in parse_ftrace_printk() parse_ftrace_printk() tokenizes and parses a line, calling strdup() each iteration. Add code to free this temporary format string duplicate. Fixes the following coverity complaints: Error: RESOURCE_LEAK (CWE-772): tools/perf/util/trace-event-parse.c:158: overwrite_var: Overwriting "printk" in "printk = strdup(fmt + 1)" leaks the storage that "printk" points to. tools/perf/util/trace-event-parse.c:162: leaked_storage: Variable "printk" going out of scope leaks the storage it points to. Signed-off-by: Sanskriti Sharma Reviewed-by: Jiri Olsa Cc: Joe Lawrence Link: http://lkml.kernel.org/r/1538490554-8161-4-git-send-email-sansharm@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event-parse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index a4d7de1c96d1..02f97f5dd588 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -158,6 +158,7 @@ void parse_ftrace_printk(struct tep_handle *pevent, printk = strdup(fmt+1); line = strtok_r(NULL, "\n", &next); tep_register_print_string(pevent, printk, addr); + free(printk); } } From 470c8f7c88de013d266e1b61044efe8937728b7f Mon Sep 17 00:00:00 2001 From: Sanskriti Sharma Date: Tue, 2 Oct 2018 10:29:13 -0400 Subject: [PATCH 142/155] perf tools: Avoid double free in read_event_file() The temporary 'buf' buffer allocated in read_event_file() may be freed twice. Move the free() call to the common function exit point. Fixes the following coverity complaints: Error: USE_AFTER_FREE (CWE-825): tools/perf/util/trace-event-read.c:309: double_free: Calling "free" frees pointer "buf" which has already been freed. Signed-off-by: Sanskriti Sharma Reviewed-by: Jiri Olsa Cc: Joe Lawrence Link: http://lkml.kernel.org/r/1538490554-8161-5-git-send-email-sansharm@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event-read.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index b98ee2a2eb44..a278e1eee5f5 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -297,10 +297,8 @@ static int read_event_file(struct tep_handle *pevent, char *sys, } ret = do_read(buf, size); - if (ret < 0) { - free(buf); + if (ret < 0) goto out; - } ret = parse_event_file(pevent, buf, size, sys); if (ret < 0) From 1e44224fb0528b4c0cc176bde2bb31e9127eb14b Mon Sep 17 00:00:00 2001 From: Sanskriti Sharma Date: Tue, 2 Oct 2018 10:29:14 -0400 Subject: [PATCH 143/155] perf tools: Free temporary 'sys' string in read_event_files() For each system in a given pevent, read_event_files() reads in a temporary 'sys' string. Be sure to free this string before moving onto to the next system and/or leaving read_event_files(). Fixes the following coverity complaints: Error: RESOURCE_LEAK (CWE-772): tools/perf/util/trace-event-read.c:343: overwrite_var: Overwriting "sys" in "sys = read_string()" leaks the storage that "sys" points to. tools/perf/util/trace-event-read.c:353: leaked_storage: Variable "sys" going out of scope leaks the storage it points to. Signed-off-by: Sanskriti Sharma Reviewed-by: Jiri Olsa Cc: Joe Lawrence Link: http://lkml.kernel.org/r/1538490554-8161-6-git-send-email-sansharm@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event-read.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index a278e1eee5f5..add8441de579 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -347,9 +347,12 @@ static int read_event_files(struct tep_handle *pevent) for (x=0; x < count; x++) { size = read8(pevent); ret = read_event_file(pevent, sys, size); - if (ret) + if (ret) { + free(sys); return ret; + } } + free(sys); } return 0; } From e13a5d69c31d35538e80176d54d95b6addf4dcbf Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 5 Oct 2018 17:40:57 -0300 Subject: [PATCH 144/155] perf python: Make clang_has_option() work on Python 3 Use a bytes literal so it works with Python 3's version of Popen(). Note that the b"..." syntax requires Python 2.6+. Signed-off-by: Eduardo Habkost Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/r/20181005204058.7966-2-ehabkost@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py index 1942f6dd24f6..261a55e7e1b2 100644 --- a/tools/perf/util/setup.py +++ b/tools/perf/util/setup.py @@ -5,7 +5,7 @@ from subprocess import Popen, PIPE from re import sub def clang_has_option(option): - return [o for o in Popen(['clang', option], stderr=PIPE).stderr.readlines() if "unknown argument" in o] == [ ] + return [o for o in Popen(['clang', option], stderr=PIPE).stderr.readlines() if b"unknown argument" in o] == [ ] cc = getenv("CC") if cc == "clang": From 8b2f245faa6238e28a1d801e8633515251d1acfc Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 5 Oct 2018 17:40:58 -0300 Subject: [PATCH 145/155] perf python: More portable way to make CFLAGS work with clang The existing code that tries to make CFLAGS compatible with clang doesn't work with Python 3. Instead of trying to touch _sysconfigdata.build_time_vars directly, change the dictionary returned by disutils.sysconfig.get_config_vars(). This works on both Python 2 and Python 3. Signed-off-by: Eduardo Habkost Reported-by: Arnaldo Carvalho de Melo Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/r/20181005204058.7966-3-ehabkost@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/setup.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py index 261a55e7e1b2..63f758c655d5 100644 --- a/tools/perf/util/setup.py +++ b/tools/perf/util/setup.py @@ -9,12 +9,14 @@ def clang_has_option(option): cc = getenv("CC") if cc == "clang": - from _sysconfigdata import build_time_vars - build_time_vars["CFLAGS"] = sub("-specs=[^ ]+", "", build_time_vars["CFLAGS"]) - if not clang_has_option("-mcet"): - build_time_vars["CFLAGS"] = sub("-mcet", "", build_time_vars["CFLAGS"]) - if not clang_has_option("-fcf-protection"): - build_time_vars["CFLAGS"] = sub("-fcf-protection", "", build_time_vars["CFLAGS"]) + from distutils.sysconfig import get_config_vars + vars = get_config_vars() + for var in ('CFLAGS', 'OPT'): + vars[var] = sub("-specs=[^ ]+", "", vars[var]) + if not clang_has_option("-mcet"): + vars[var] = sub("-mcet", "", vars[var]) + if not clang_has_option("-fcf-protection"): + vars[var] = sub("-fcf-protection", "", vars[var]) from distutils.core import setup, Extension From bbbab191c2c474d183e93799d008b412e97f5936 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Fri, 5 Oct 2018 12:18:16 -0400 Subject: [PATCH 146/155] tools lib traceevent: Separate out tep_strerror() for strerror_r() issues While working on having PowerTop use libtracevent as a shared object library, Tzvetomir hit "str_error_r not defined". This was added by commit c3cec9e68f12d ("tools lib traceevent: Use str_error_r()") because strerror_r() has two definitions, where one is GNU specific, and the other is XSI complient. The strerror_r() is in a wrapper str_error_r() to keep the code from having to worry about which compiler is being used. The problem is that str_error_r() is external to libtraceevent, and not part of the library. If it is used as a shared object then the tools using it will need to define that function. I do not want that function defined in libtraceevent itself, as it is out of scope for that library. As there's only a single instance of this call, and its in the traceevent library's own tep_strerror() function, we can copy what was done in perf, and create yet another external file that undefs _GNU_SOURCE to use the more portable version of the function. We don't need to worry about the errors that strerror_r() returns. If the buffer isn't big enough, we simply truncate it. Reported-by: Tzvetomir Stoyanov Signed-off-by: Steven Rostedt (VMware) Cc: Jiri Olsa Cc: Namhyung Kim Cc: Tzvetomir Stoyanov (VMware) Cc: linux trace devel Link: http://lkml.kernel.org/r/20181005121816.484e654f@gandalf.local.home Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Build | 1 + tools/lib/traceevent/event-parse.c | 30 ---------------- tools/lib/traceevent/tep_strerror.c | 53 +++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 30 deletions(-) create mode 100644 tools/lib/traceevent/tep_strerror.c diff --git a/tools/lib/traceevent/Build b/tools/lib/traceevent/Build index c681d0575d16..0050c145d806 100644 --- a/tools/lib/traceevent/Build +++ b/tools/lib/traceevent/Build @@ -4,6 +4,7 @@ libtraceevent-y += trace-seq.o libtraceevent-y += parse-filter.o libtraceevent-y += parse-utils.o libtraceevent-y += kbuffer-parse.o +libtraceevent-y += tep_strerror.o plugin_jbd2-y += plugin_jbd2.o plugin_hrtimer-y += plugin_hrtimer.o diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 7980fc6c3bac..233179a712d6 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -6201,35 +6200,6 @@ enum tep_errno tep_parse_event(struct tep_handle *pevent, const char *buf, return __parse_event(pevent, &event, buf, size, sys); } -#undef _PE -#define _PE(code, str) str -static const char * const tep_error_str[] = { - TEP_ERRORS -}; -#undef _PE - -int tep_strerror(struct tep_handle *pevent __maybe_unused, - enum tep_errno errnum, char *buf, size_t buflen) -{ - int idx; - const char *msg; - - if (errnum >= 0) { - str_error_r(errnum, buf, buflen); - return 0; - } - - if (errnum <= __TEP_ERRNO__START || - errnum >= __TEP_ERRNO__END) - return -1; - - idx = errnum - __TEP_ERRNO__START - 1; - msg = tep_error_str[idx]; - snprintf(buf, buflen, "%s", msg); - - return 0; -} - int get_field_val(struct trace_seq *s, struct tep_format_field *field, const char *name, struct tep_record *record, unsigned long long *val, int err) diff --git a/tools/lib/traceevent/tep_strerror.c b/tools/lib/traceevent/tep_strerror.c new file mode 100644 index 000000000000..4ac26445b2f6 --- /dev/null +++ b/tools/lib/traceevent/tep_strerror.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: LGPL-2.1 +#undef _GNU_SOURCE +#include +#include + +#include "event-parse.h" + +#undef _PE +#define _PE(code, str) str +static const char * const tep_error_str[] = { + TEP_ERRORS +}; +#undef _PE + +/* + * The tools so far have been using the strerror_r() GNU variant, that returns + * a string, be it the buffer passed or something else. + * + * But that, besides being tricky in cases where we expect that the function + * using strerror_r() returns the error formatted in a provided buffer (we have + * to check if it returned something else and copy that instead), breaks the + * build on systems not using glibc, like Alpine Linux, where musl libc is + * used. + * + * So, introduce yet another wrapper, str_error_r(), that has the GNU + * interface, but uses the portable XSI variant of strerror_r(), so that users + * rest asured that the provided buffer is used and it is what is returned. + */ +int tep_strerror(struct tep_handle *tep __maybe_unused, + enum tep_errno errnum, char *buf, size_t buflen) +{ + const char *msg; + int idx; + + if (!buflen) + return 0; + + if (errnum >= 0) { + int err = strerror_r(errnum, buf, buflen); + buf[buflen - 1] = 0; + return err; + } + + if (errnum <= __TEP_ERRNO__START || + errnum >= __TEP_ERRNO__END) + return -1; + + idx = errnum - __TEP_ERRNO__START - 1; + msg = tep_error_str[idx]; + snprintf(buf, buflen, "%s", msg); + + return 0; +} From bb3dd7e7c4d5e024d607c0ec06c2a2fb9408cc99 Mon Sep 17 00:00:00 2001 From: Tzvetomir Stoyanov Date: Fri, 5 Oct 2018 12:22:25 -0400 Subject: [PATCH 147/155] tools lib traceevent, perf tools: Move struct tep_handler definition in a local header file As traceevent is going to be transferred into a proper library, its local data should be protected from the library users. This patch encapsulates struct tep_handler into a local header, not visible outside of the library. It implements also a bunch of new APIs, which library users can use to access tep_handler members. Signed-off-by: Tzvetomir Stoyanov Cc: Jiri Olsa Cc: Namhyung Kim Cc: linux trace devel Cc: tzvetomir stoyanov Link: http://lkml.kernel.org/r/20181005122225.522155df@gandalf.local.home Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Build | 1 + tools/lib/traceevent/event-parse-api.c | 275 +++++++++++++++++++++++ tools/lib/traceevent/event-parse-local.h | 92 ++++++++ tools/lib/traceevent/event-parse.c | 2 + tools/lib/traceevent/event-parse.h | 228 +++---------------- tools/lib/traceevent/event-plugin.c | 1 + tools/lib/traceevent/parse-filter.c | 1 + tools/perf/util/trace-event-parse.c | 25 ++- tools/perf/util/trace-event-read.c | 2 +- 9 files changed, 416 insertions(+), 211 deletions(-) create mode 100644 tools/lib/traceevent/event-parse-api.c create mode 100644 tools/lib/traceevent/event-parse-local.h diff --git a/tools/lib/traceevent/Build b/tools/lib/traceevent/Build index 0050c145d806..ba54bfce0b0b 100644 --- a/tools/lib/traceevent/Build +++ b/tools/lib/traceevent/Build @@ -5,6 +5,7 @@ libtraceevent-y += parse-filter.o libtraceevent-y += parse-utils.o libtraceevent-y += kbuffer-parse.o libtraceevent-y += tep_strerror.o +libtraceevent-y += event-parse-api.o plugin_jbd2-y += plugin_jbd2.o plugin_hrtimer-y += plugin_hrtimer.o diff --git a/tools/lib/traceevent/event-parse-api.c b/tools/lib/traceevent/event-parse-api.c new file mode 100644 index 000000000000..61f7149085ee --- /dev/null +++ b/tools/lib/traceevent/event-parse-api.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt + * + */ + +#include "event-parse.h" +#include "event-parse-local.h" +#include "event-utils.h" + +/** + * tep_get_first_event - returns the first event in the events array + * @tep: a handle to the tep_handle + * + * This returns pointer to the first element of the events array + * If @tep is NULL, NULL is returned. + */ +struct tep_event_format *tep_get_first_event(struct tep_handle *tep) +{ + if (tep && tep->events) + return tep->events[0]; + + return NULL; +} + +/** + * tep_get_events_count - get the number of defined events + * @tep: a handle to the tep_handle + * + * This returns number of elements in event array + * If @tep is NULL, 0 is returned. + */ +int tep_get_events_count(struct tep_handle *tep) +{ + if(tep) + return tep->nr_events; + return 0; +} + +/** + * tep_set_flag - set event parser flag + * @tep: a handle to the tep_handle + * @flag: flag, or combination of flags to be set + * can be any combination from enum tep_flag + * + * This sets a flag or mbination of flags from enum tep_flag + */ +void tep_set_flag(struct tep_handle *tep, int flag) +{ + if(tep) + tep->flags |= flag; +} + +unsigned short __tep_data2host2(struct tep_handle *pevent, unsigned short data) +{ + unsigned short swap; + + if (!pevent || pevent->host_bigendian == pevent->file_bigendian) + return data; + + swap = ((data & 0xffULL) << 8) | + ((data & (0xffULL << 8)) >> 8); + + return swap; +} + +unsigned int __tep_data2host4(struct tep_handle *pevent, unsigned int data) +{ + unsigned int swap; + + if (!pevent || pevent->host_bigendian == pevent->file_bigendian) + return data; + + swap = ((data & 0xffULL) << 24) | + ((data & (0xffULL << 8)) << 8) | + ((data & (0xffULL << 16)) >> 8) | + ((data & (0xffULL << 24)) >> 24); + + return swap; +} + +unsigned long long +__tep_data2host8(struct tep_handle *pevent, unsigned long long data) +{ + unsigned long long swap; + + if (!pevent || pevent->host_bigendian == pevent->file_bigendian) + return data; + + swap = ((data & 0xffULL) << 56) | + ((data & (0xffULL << 8)) << 40) | + ((data & (0xffULL << 16)) << 24) | + ((data & (0xffULL << 24)) << 8) | + ((data & (0xffULL << 32)) >> 8) | + ((data & (0xffULL << 40)) >> 24) | + ((data & (0xffULL << 48)) >> 40) | + ((data & (0xffULL << 56)) >> 56); + + return swap; +} + +/** + * tep_get_header_page_size - get size of the header page + * @pevent: a handle to the tep_handle + * + * This returns size of the header page + * If @pevent is NULL, 0 is returned. + */ +int tep_get_header_page_size(struct tep_handle *pevent) +{ + if(pevent) + return pevent->header_page_size_size; + return 0; +} + +/** + * tep_get_cpus - get the number of CPUs + * @pevent: a handle to the tep_handle + * + * This returns the number of CPUs + * If @pevent is NULL, 0 is returned. + */ +int tep_get_cpus(struct tep_handle *pevent) +{ + if(pevent) + return pevent->cpus; + return 0; +} + +/** + * tep_set_cpus - set the number of CPUs + * @pevent: a handle to the tep_handle + * + * This sets the number of CPUs + */ +void tep_set_cpus(struct tep_handle *pevent, int cpus) +{ + if(pevent) + pevent->cpus = cpus; +} + +/** + * tep_get_long_size - get the size of a long integer on the current machine + * @pevent: a handle to the tep_handle + * + * This returns the size of a long integer on the current machine + * If @pevent is NULL, 0 is returned. + */ +int tep_get_long_size(struct tep_handle *pevent) +{ + if(pevent) + return pevent->long_size; + return 0; +} + +/** + * tep_set_long_size - set the size of a long integer on the current machine + * @pevent: a handle to the tep_handle + * @size: size, in bytes, of a long integer + * + * This sets the size of a long integer on the current machine + */ +void tep_set_long_size(struct tep_handle *pevent, int long_size) +{ + if(pevent) + pevent->long_size = long_size; +} + +/** + * tep_get_page_size - get the size of a memory page on the current machine + * @pevent: a handle to the tep_handle + * + * This returns the size of a memory page on the current machine + * If @pevent is NULL, 0 is returned. + */ +int tep_get_page_size(struct tep_handle *pevent) +{ + if(pevent) + return pevent->page_size; + return 0; +} + +/** + * tep_set_page_size - set the size of a memory page on the current machine + * @pevent: a handle to the tep_handle + * @_page_size: size of a memory page, in bytes + * + * This sets the size of a memory page on the current machine + */ +void tep_set_page_size(struct tep_handle *pevent, int _page_size) +{ + if(pevent) + pevent->page_size = _page_size; +} + +/** + * tep_is_file_bigendian - get if the file is in big endian order + * @pevent: a handle to the tep_handle + * + * This returns if the file is in big endian order + * If @pevent is NULL, 0 is returned. + */ +int tep_is_file_bigendian(struct tep_handle *pevent) +{ + if(pevent) + return pevent->file_bigendian; + return 0; +} + +/** + * tep_set_file_bigendian - set if the file is in big endian order + * @pevent: a handle to the tep_handle + * @endian: non zero, if the file is in big endian order + * + * This sets if the file is in big endian order + */ +void tep_set_file_bigendian(struct tep_handle *pevent, enum tep_endian endian) +{ + if(pevent) + pevent->file_bigendian = endian; +} + +/** + * tep_is_host_bigendian - get if the order of the current host is big endian + * @pevent: a handle to the tep_handle + * + * This gets if the order of the current host is big endian + * If @pevent is NULL, 0 is returned. + */ +int tep_is_host_bigendian(struct tep_handle *pevent) +{ + if(pevent) + return pevent->host_bigendian; + return 0; +} + +/** + * tep_set_host_bigendian - set the order of the local host + * @pevent: a handle to the tep_handle + * @endian: non zero, if the local host has big endian order + * + * This sets the order of the local host + */ +void tep_set_host_bigendian(struct tep_handle *pevent, enum tep_endian endian) +{ + if(pevent) + pevent->host_bigendian = endian; +} + +/** + * tep_is_latency_format - get if the latency output format is configured + * @pevent: a handle to the tep_handle + * + * This gets if the latency output format is configured + * If @pevent is NULL, 0 is returned. + */ +int tep_is_latency_format(struct tep_handle *pevent) +{ + if(pevent) + return pevent->latency_format; + return 0; +} + +/** + * tep_set_latency_format - set the latency output format + * @pevent: a handle to the tep_handle + * @lat: non zero for latency output format + * + * This sets the latency output format + */ +void tep_set_latency_format(struct tep_handle *pevent, int lat) +{ + if(pevent) + pevent->latency_format = lat; +} diff --git a/tools/lib/traceevent/event-parse-local.h b/tools/lib/traceevent/event-parse-local.h new file mode 100644 index 000000000000..b9bddde577f8 --- /dev/null +++ b/tools/lib/traceevent/event-parse-local.h @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt + * + */ + +#ifndef _PARSE_EVENTS_INT_H +#define _PARSE_EVENTS_INT_H + +struct cmdline; +struct cmdline_list; +struct func_map; +struct func_list; +struct event_handler; +struct func_resolver; + +struct tep_handle { + int ref_count; + + int header_page_ts_offset; + int header_page_ts_size; + int header_page_size_offset; + int header_page_size_size; + int header_page_data_offset; + int header_page_data_size; + int header_page_overwrite; + + enum tep_endian file_bigendian; + enum tep_endian host_bigendian; + + int latency_format; + + int old_format; + + int cpus; + int long_size; + int page_size; + + struct cmdline *cmdlines; + struct cmdline_list *cmdlist; + int cmdline_count; + + struct func_map *func_map; + struct func_resolver *func_resolver; + struct func_list *funclist; + unsigned int func_count; + + struct printk_map *printk_map; + struct printk_list *printklist; + unsigned int printk_count; + + + struct tep_event_format **events; + int nr_events; + struct tep_event_format **sort_events; + enum tep_event_sort_type last_type; + + int type_offset; + int type_size; + + int pid_offset; + int pid_size; + + int pc_offset; + int pc_size; + + int flags_offset; + int flags_size; + + int ld_offset; + int ld_size; + + int print_raw; + + int test_filters; + + int flags; + + struct tep_format_field *bprint_ip_field; + struct tep_format_field *bprint_fmt_field; + struct tep_format_field *bprint_buf_field; + + struct event_handler *handlers; + struct tep_function_handler *func_handlers; + + /* cache */ + struct tep_event_format *last_event; + + char *trace_clock; +}; + +#endif /* _PARSE_EVENTS_INT_H */ diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 233179a712d6..3692f29fee46 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -22,6 +22,8 @@ #include #include "event-parse.h" + +#include "event-parse-local.h" #include "event-utils.h" #include "trace-seq.h" diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 9c29a5f7aa39..16bf4c890b6f 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -405,149 +405,18 @@ void tep_print_plugins(struct trace_seq *s, const char *prefix, const char *suffix, const struct tep_plugin_list *list); -struct cmdline; -struct cmdline_list; -struct func_map; -struct func_list; -struct event_handler; -struct func_resolver; - +/* tep_handle */ typedef char *(tep_func_resolver_t)(void *priv, unsigned long long *addrp, char **modp); +void tep_set_flag(struct tep_handle *tep, int flag); +unsigned short __tep_data2host2(struct tep_handle *pevent, unsigned short data); +unsigned int __tep_data2host4(struct tep_handle *pevent, unsigned int data); +unsigned long long +__tep_data2host8(struct tep_handle *pevent, unsigned long long data); -struct tep_handle { - int ref_count; - - int header_page_ts_offset; - int header_page_ts_size; - int header_page_size_offset; - int header_page_size_size; - int header_page_data_offset; - int header_page_data_size; - int header_page_overwrite; - - int file_bigendian; - int host_bigendian; - - int latency_format; - - int old_format; - - int cpus; - int long_size; - int page_size; - - struct cmdline *cmdlines; - struct cmdline_list *cmdlist; - int cmdline_count; - - struct func_map *func_map; - struct func_resolver *func_resolver; - struct func_list *funclist; - unsigned int func_count; - - struct printk_map *printk_map; - struct printk_list *printklist; - unsigned int printk_count; - - - struct tep_event_format **events; - int nr_events; - struct tep_event_format **sort_events; - enum tep_event_sort_type last_type; - - int type_offset; - int type_size; - - int pid_offset; - int pid_size; - - int pc_offset; - int pc_size; - - int flags_offset; - int flags_size; - - int ld_offset; - int ld_size; - - int print_raw; - - int test_filters; - - int flags; - - struct tep_format_field *bprint_ip_field; - struct tep_format_field *bprint_fmt_field; - struct tep_format_field *bprint_buf_field; - - struct event_handler *handlers; - struct tep_function_handler *func_handlers; - - /* cache */ - struct tep_event_format *last_event; - - char *trace_clock; -}; - -static inline void tep_set_flag(struct tep_handle *pevent, int flag) -{ - pevent->flags |= flag; -} - -static inline unsigned short -__tep_data2host2(struct tep_handle *pevent, unsigned short data) -{ - unsigned short swap; - - if (pevent->host_bigendian == pevent->file_bigendian) - return data; - - swap = ((data & 0xffULL) << 8) | - ((data & (0xffULL << 8)) >> 8); - - return swap; -} - -static inline unsigned int -__tep_data2host4(struct tep_handle *pevent, unsigned int data) -{ - unsigned int swap; - - if (pevent->host_bigendian == pevent->file_bigendian) - return data; - - swap = ((data & 0xffULL) << 24) | - ((data & (0xffULL << 8)) << 8) | - ((data & (0xffULL << 16)) >> 8) | - ((data & (0xffULL << 24)) >> 24); - - return swap; -} - -static inline unsigned long long -__tep_data2host8(struct tep_handle *pevent, unsigned long long data) -{ - unsigned long long swap; - - if (pevent->host_bigendian == pevent->file_bigendian) - return data; - - swap = ((data & 0xffULL) << 56) | - ((data & (0xffULL << 8)) << 40) | - ((data & (0xffULL << 16)) << 24) | - ((data & (0xffULL << 24)) << 8) | - ((data & (0xffULL << 32)) >> 8) | - ((data & (0xffULL << 40)) >> 24) | - ((data & (0xffULL << 48)) >> 40) | - ((data & (0xffULL << 56)) >> 56); - - return swap; -} - -#define tep_data2host2(pevent, ptr) __tep_data2host2(pevent, *(unsigned short *)(ptr)) -#define tep_data2host4(pevent, ptr) __tep_data2host4(pevent, *(unsigned int *)(ptr)) -#define tep_data2host8(pevent, ptr) \ +#define tep_data2host2(pevent, ptr) __tep_data2host2(pevent, *(unsigned short *)(ptr)) +#define tep_data2host4(pevent, ptr) __tep_data2host4(pevent, *(unsigned int *)(ptr)) +#define tep_data2host8(pevent, ptr) \ ({ \ unsigned long long __val; \ \ @@ -655,11 +524,12 @@ unsigned long long tep_read_number(struct tep_handle *pevent, const void *ptr, i int tep_read_number_field(struct tep_format_field *field, const void *data, unsigned long long *value); +struct tep_event_format *tep_get_first_event(struct tep_handle *tep); +int tep_get_events_count(struct tep_handle *tep); struct tep_event_format *tep_find_event(struct tep_handle *pevent, int id); struct tep_event_format * tep_find_event_by_name(struct tep_handle *pevent, const char *sys, const char *name); - struct tep_event_format * tep_find_event_by_record(struct tep_handle *pevent, struct tep_record *record); @@ -689,65 +559,23 @@ struct tep_event_format **tep_list_events(struct tep_handle *pevent, enum tep_ev struct tep_format_field **tep_event_common_fields(struct tep_event_format *event); struct tep_format_field **tep_event_fields(struct tep_event_format *event); -static inline int tep_get_cpus(struct tep_handle *pevent) -{ - return pevent->cpus; -} - -static inline void tep_set_cpus(struct tep_handle *pevent, int cpus) -{ - pevent->cpus = cpus; -} - -static inline int tep_get_long_size(struct tep_handle *pevent) -{ - return pevent->long_size; -} - -static inline void tep_set_long_size(struct tep_handle *pevent, int long_size) -{ - pevent->long_size = long_size; -} - -static inline int tep_get_page_size(struct tep_handle *pevent) -{ - return pevent->page_size; -} - -static inline void tep_set_page_size(struct tep_handle *pevent, int _page_size) -{ - pevent->page_size = _page_size; -} - -static inline int tep_is_file_bigendian(struct tep_handle *pevent) -{ - return pevent->file_bigendian; -} - -static inline void tep_set_file_bigendian(struct tep_handle *pevent, int endian) -{ - pevent->file_bigendian = endian; -} - -static inline int tep_is_host_bigendian(struct tep_handle *pevent) -{ - return pevent->host_bigendian; -} - -static inline void tep_set_host_bigendian(struct tep_handle *pevent, int endian) -{ - pevent->host_bigendian = endian; -} - -static inline int tep_is_latency_format(struct tep_handle *pevent) -{ - return pevent->latency_format; -} - -static inline void tep_set_latency_format(struct tep_handle *pevent, int lat) -{ - pevent->latency_format = lat; -} +enum tep_endian { + TEP_LITTLE_ENDIAN = 0, + TEP_BIG_ENDIAN +}; +int tep_get_cpus(struct tep_handle *pevent); +void tep_set_cpus(struct tep_handle *pevent, int cpus); +int tep_get_long_size(struct tep_handle *pevent); +void tep_set_long_size(struct tep_handle *pevent, int long_size); +int tep_get_page_size(struct tep_handle *pevent); +void tep_set_page_size(struct tep_handle *pevent, int _page_size); +int tep_is_file_bigendian(struct tep_handle *pevent); +void tep_set_file_bigendian(struct tep_handle *pevent, enum tep_endian endian); +int tep_is_host_bigendian(struct tep_handle *pevent); +void tep_set_host_bigendian(struct tep_handle *pevent, enum tep_endian endian); +int tep_is_latency_format(struct tep_handle *pevent); +void tep_set_latency_format(struct tep_handle *pevent, int lat); +int tep_get_header_page_size(struct tep_handle *pevent); struct tep_handle *tep_alloc(void); void tep_free(struct tep_handle *pevent); diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index 46eb64eb0c2e..e74f16c88398 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -14,6 +14,7 @@ #include #include #include "event-parse.h" +#include "event-parse-local.h" #include "event-utils.h" #include "trace-seq.h" diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index d64b6128fa7d..ed87cb56713d 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -11,6 +11,7 @@ #include #include "event-parse.h" +#include "event-parse-local.h" #include "event-utils.h" #define COMM "COMM" diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 02f97f5dd588..32e558a65af3 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -37,10 +37,11 @@ static int get_common_field(struct scripting_context *context, struct tep_format_field *field; if (!*size) { - if (!pevent->events) + + event = tep_get_first_event(pevent); + if (!event) return 0; - event = pevent->events[0]; field = tep_find_common_field(event, type); if (!field) return 0; @@ -193,25 +194,29 @@ struct tep_event_format *trace_find_next_event(struct tep_handle *pevent, struct tep_event_format *event) { static int idx; + int events_count; + struct tep_event_format *all_events; - if (!pevent || !pevent->events) + all_events = tep_get_first_event(pevent); + events_count = tep_get_events_count(pevent); + if (!pevent || !all_events || events_count < 1) return NULL; if (!event) { idx = 0; - return pevent->events[0]; + return all_events; } - if (idx < pevent->nr_events && event == pevent->events[idx]) { + if (idx < events_count && event == (all_events + idx)) { idx++; - if (idx == pevent->nr_events) + if (idx == events_count) return NULL; - return pevent->events[idx]; + return (all_events + idx); } - for (idx = 1; idx < pevent->nr_events; idx++) { - if (event == pevent->events[idx - 1]) - return pevent->events[idx]; + for (idx = 1; idx < events_count; idx++) { + if (event == (all_events + (idx - 1))) + return (all_events + idx); } return NULL; } diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index add8441de579..76f12c705ef9 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -241,7 +241,7 @@ static int read_header_files(struct tep_handle *pevent) * The commit field in the page is of type long, * use that instead, since it represents the kernel. */ - tep_set_long_size(pevent, pevent->header_page_size_size); + tep_set_long_size(pevent, tep_get_header_page_size(pevent)); } free(header_page); From 521348b011d64cf3febb10b64ba5b472681bef94 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Wed, 3 Oct 2018 15:17:01 -0700 Subject: [PATCH 148/155] x86/intel_rdt: Introduce utility to obtain CDP peer Introduce a utility that, when provided with a RDT resource and an instance of this RDT resource (a RDT domain), would return pointers to the RDT resource and RDT domain that share the same hardware. This is specific to the CDP resources that share the same hardware. For example, if a pointer to the RDT_RESOURCE_L2DATA resource (struct rdt_resource) and a pointer to an instance of this resource (struct rdt_domain) is provided, then it will return a pointer to the RDT_RESOURCE_L2CODE resource as well as the specific instance that shares the same hardware as the provided rdt_domain. This utility is created in support of the "exclusive" resource group mode where overlap of resource allocation between resource groups need to be avoided. The overlap test need to consider not just the matching resources, but also the resources that share the same hardware. Temporarily mark it as unused in support of patch testing to avoid compile warnings until it is used. Fixes: 49f7b4efa110 ("x86/intel_rdt: Enable setting of exclusive mode") Signed-off-by: Reinette Chatre Signed-off-by: Thomas Gleixner Tested-by: Jithu Joseph Acked-by: Fenghua Yu Cc: tony.luck@intel.com Cc: gavin.hindman@intel.com Cc: dave.hansen@intel.com Cc: hpa@zytor.com Link: https://lkml.kernel.org/r/9b4bc4d59ba2e903b6a3eb17e16ef41a8e7b7c3e.1538603665.git.reinette.chatre@intel.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 72 ++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c index 643670fb8943..9d59ee1c444e 100644 --- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c @@ -960,6 +960,78 @@ static int rdtgroup_mode_show(struct kernfs_open_file *of, return 0; } +/** + * rdt_cdp_peer_get - Retrieve CDP peer if it exists + * @r: RDT resource to which RDT domain @d belongs + * @d: Cache instance for which a CDP peer is requested + * @r_cdp: RDT resource that shares hardware with @r (RDT resource peer) + * Used to return the result. + * @d_cdp: RDT domain that shares hardware with @d (RDT domain peer) + * Used to return the result. + * + * RDT resources are managed independently and by extension the RDT domains + * (RDT resource instances) are managed independently also. The Code and + * Data Prioritization (CDP) RDT resources, while managed independently, + * could refer to the same underlying hardware. For example, + * RDT_RESOURCE_L2CODE and RDT_RESOURCE_L2DATA both refer to the L2 cache. + * + * When provided with an RDT resource @r and an instance of that RDT + * resource @d rdt_cdp_peer_get() will return if there is a peer RDT + * resource and the exact instance that shares the same hardware. + * + * Return: 0 if a CDP peer was found, <0 on error or if no CDP peer exists. + * If a CDP peer was found, @r_cdp will point to the peer RDT resource + * and @d_cdp will point to the peer RDT domain. + */ +static int __attribute__((unused)) rdt_cdp_peer_get(struct rdt_resource *r, + struct rdt_domain *d, + struct rdt_resource **r_cdp, + struct rdt_domain **d_cdp) +{ + struct rdt_resource *_r_cdp = NULL; + struct rdt_domain *_d_cdp = NULL; + int ret = 0; + + switch (r->rid) { + case RDT_RESOURCE_L3DATA: + _r_cdp = &rdt_resources_all[RDT_RESOURCE_L3CODE]; + break; + case RDT_RESOURCE_L3CODE: + _r_cdp = &rdt_resources_all[RDT_RESOURCE_L3DATA]; + break; + case RDT_RESOURCE_L2DATA: + _r_cdp = &rdt_resources_all[RDT_RESOURCE_L2CODE]; + break; + case RDT_RESOURCE_L2CODE: + _r_cdp = &rdt_resources_all[RDT_RESOURCE_L2DATA]; + break; + default: + ret = -ENOENT; + goto out; + } + + /* + * When a new CPU comes online and CDP is enabled then the new + * RDT domains (if any) associated with both CDP RDT resources + * are added in the same CPU online routine while the + * rdtgroup_mutex is held. It should thus not happen for one + * RDT domain to exist and be associated with its RDT CDP + * resource but there is no RDT domain associated with the + * peer RDT CDP resource. Hence the WARN. + */ + _d_cdp = rdt_find_domain(_r_cdp, d->id, NULL); + if (WARN_ON(!_d_cdp)) { + _r_cdp = NULL; + ret = -EINVAL; + } + +out: + *r_cdp = _r_cdp; + *d_cdp = _d_cdp; + + return ret; +} + /** * rdtgroup_cbm_overlaps - Does CBM for intended closid overlap with other * @r: Resource to which domain instance @d belongs. From e5f3530c391105fdd6174852e3ea6136d073b45a Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Wed, 3 Oct 2018 15:17:02 -0700 Subject: [PATCH 149/155] x86/intel_rdt: CBM overlap should also check for overlap with CDP peer The CBM overlap test is used to manage the allocations of RDT resources where overlap is possible between resource groups. When a resource group is in exclusive mode then there should be no overlap between resource groups. The current overlap test only considers overlap between the same resources, for example, that usage of a RDT_RESOURCE_L2DATA resource in one resource group does not overlap with usage of a RDT_RESOURCE_L2DATA resource in another resource group. The problem with this is that it allows overlap between a RDT_RESOURCE_L2DATA resource in one resource group with a RDT_RESOURCE_L2CODE resource in another resource group - even if both resource groups are in exclusive mode. This is a problem because even though these appear to be different resources they end up sharing the same underlying hardware and thus does not fulfill the user's request for exclusive use of hardware resources. Fix this by including the CDP peer (if there is one) in every CBM overlap test. This does not impact the overlap between resources within the same exclusive resource group that is allowed. Fixes: 49f7b4efa110 ("x86/intel_rdt: Enable setting of exclusive mode") Reported-by: Jithu Joseph Signed-off-by: Reinette Chatre Signed-off-by: Thomas Gleixner Tested-by: Jithu Joseph Acked-by: Fenghua Yu Cc: tony.luck@intel.com Cc: gavin.hindman@intel.com Cc: dave.hansen@intel.com Cc: hpa@zytor.com Link: https://lkml.kernel.org/r/e538b7f56f7ca15963dce2e00ac3be8edb8a68e1.1538603665.git.reinette.chatre@intel.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 48 ++++++++++++++++++++---- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c index 9d59ee1c444e..49c479822844 100644 --- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c @@ -983,10 +983,9 @@ static int rdtgroup_mode_show(struct kernfs_open_file *of, * If a CDP peer was found, @r_cdp will point to the peer RDT resource * and @d_cdp will point to the peer RDT domain. */ -static int __attribute__((unused)) rdt_cdp_peer_get(struct rdt_resource *r, - struct rdt_domain *d, - struct rdt_resource **r_cdp, - struct rdt_domain **d_cdp) +static int rdt_cdp_peer_get(struct rdt_resource *r, struct rdt_domain *d, + struct rdt_resource **r_cdp, + struct rdt_domain **d_cdp) { struct rdt_resource *_r_cdp = NULL; struct rdt_domain *_d_cdp = NULL; @@ -1033,7 +1032,7 @@ out: } /** - * rdtgroup_cbm_overlaps - Does CBM for intended closid overlap with other + * __rdtgroup_cbm_overlaps - Does CBM for intended closid overlap with other * @r: Resource to which domain instance @d belongs. * @d: The domain instance for which @closid is being tested. * @cbm: Capacity bitmask being tested. @@ -1052,8 +1051,8 @@ out: * * Return: false if CBM does not overlap, true if it does. */ -bool rdtgroup_cbm_overlaps(struct rdt_resource *r, struct rdt_domain *d, - unsigned long cbm, int closid, bool exclusive) +static bool __rdtgroup_cbm_overlaps(struct rdt_resource *r, struct rdt_domain *d, + unsigned long cbm, int closid, bool exclusive) { enum rdtgrp_mode mode; unsigned long ctrl_b; @@ -1088,6 +1087,41 @@ bool rdtgroup_cbm_overlaps(struct rdt_resource *r, struct rdt_domain *d, return false; } +/** + * rdtgroup_cbm_overlaps - Does CBM overlap with other use of hardware + * @r: Resource to which domain instance @d belongs. + * @d: The domain instance for which @closid is being tested. + * @cbm: Capacity bitmask being tested. + * @closid: Intended closid for @cbm. + * @exclusive: Only check if overlaps with exclusive resource groups + * + * Resources that can be allocated using a CBM can use the CBM to control + * the overlap of these allocations. rdtgroup_cmb_overlaps() is the test + * for overlap. Overlap test is not limited to the specific resource for + * which the CBM is intended though - when dealing with CDP resources that + * share the underlying hardware the overlap check should be performed on + * the CDP resource sharing the hardware also. + * + * Refer to description of __rdtgroup_cbm_overlaps() for the details of the + * overlap test. + * + * Return: true if CBM overlap detected, false if there is no overlap + */ +bool rdtgroup_cbm_overlaps(struct rdt_resource *r, struct rdt_domain *d, + unsigned long cbm, int closid, bool exclusive) +{ + struct rdt_resource *r_cdp; + struct rdt_domain *d_cdp; + + if (__rdtgroup_cbm_overlaps(r, d, cbm, closid, exclusive)) + return true; + + if (rdt_cdp_peer_get(r, d, &r_cdp, &d_cdp) < 0) + return false; + + return __rdtgroup_cbm_overlaps(r_cdp, d_cdp, cbm, closid, exclusive); +} + /** * rdtgroup_mode_test_exclusive - Test if this resource group can be exclusive * From 2a7adf6ce643fdeec051dc88e5250b08c83bbb67 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Wed, 3 Oct 2018 15:17:03 -0700 Subject: [PATCH 150/155] x86/intel_rdt: Fix initial allocation to consider CDP When a new resource group is created it is initialized with a default allocation that considers which portions of cache are currently available for sharing across all resource groups or which portions of cache are currently unused. If a CDP allocation forms part of a resource group that is in exclusive mode then it should be ensured that no new allocation overlaps with any resource that shares the underlying hardware. The current initial allocation does not take this sharing of hardware into account and a new allocation in a resource that shares the same hardware would affect the exclusive resource group. Fix this by considering the allocation of a peer RDT domain - a RDT domain sharing the same hardware - as part of the test to determine which portion of cache is in use and available for use. Fixes: 95f0b77efa57 ("x86/intel_rdt: Initialize new resource group with sane defaults") Signed-off-by: Reinette Chatre Signed-off-by: Thomas Gleixner Acked-by: Fenghua Yu Cc: tony.luck@intel.com Cc: jithu.joseph@intel.com Cc: gavin.hindman@intel.com Cc: dave.hansen@intel.com Cc: hpa@zytor.com Link: https://lkml.kernel.org/r/b1f7ec08b1695be067de416a4128466d49684317.1538603665.git.reinette.chatre@intel.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c index 49c479822844..dbc7fc98b60a 100644 --- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c @@ -2460,14 +2460,16 @@ static void cbm_ensure_valid(u32 *_val, struct rdt_resource *r) */ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp) { + struct rdt_resource *r_cdp = NULL; + struct rdt_domain *d_cdp = NULL; u32 used_b = 0, unused_b = 0; u32 closid = rdtgrp->closid; struct rdt_resource *r; unsigned long tmp_cbm; enum rdtgrp_mode mode; struct rdt_domain *d; + u32 peer_ctl, *ctrl; int i, ret; - u32 *ctrl; for_each_alloc_enabled_rdt_resource(r) { /* @@ -2477,6 +2479,7 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp) if (r->rid == RDT_RESOURCE_MBA) continue; list_for_each_entry(d, &r->domains, list) { + rdt_cdp_peer_get(r, d, &r_cdp, &d_cdp); d->have_new_ctrl = false; d->new_ctrl = r->cache.shareable_bits; used_b = r->cache.shareable_bits; @@ -2486,9 +2489,19 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp) mode = rdtgroup_mode_by_closid(i); if (mode == RDT_MODE_PSEUDO_LOCKSETUP) break; - used_b |= *ctrl; + /* + * If CDP is active include peer + * domain's usage to ensure there + * is no overlap with an exclusive + * group. + */ + if (d_cdp) + peer_ctl = d_cdp->ctrl_val[i]; + else + peer_ctl = 0; + used_b |= *ctrl | peer_ctl; if (mode == RDT_MODE_SHAREABLE) - d->new_ctrl |= *ctrl; + d->new_ctrl |= *ctrl | peer_ctl; } } if (d->plr && d->plr->cbm > 0) From f703fd374ef8fb06e46713b326d255e20d6278ad Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 12 Oct 2018 10:40:22 +0000 Subject: [PATCH 151/155] x86/cpu: Drop pointless static qualifier in punit_dev_state_show() There is no need to have the 'struct dentry *dev_state' variable static since new value always be assigned before use it. Signed-off-by: YueHaibing Cc: Andy Shevchenko Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: kernel-janitors@vger.kernel.org Link: http://lkml.kernel.org/r/1539340822-117563-1-git-send-email-yuehaibing@huawei.com Signed-off-by: Ingo Molnar --- arch/x86/platform/atom/punit_atom_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/platform/atom/punit_atom_debug.c b/arch/x86/platform/atom/punit_atom_debug.c index 41dae0f0d898..6cb6076223ba 100644 --- a/arch/x86/platform/atom/punit_atom_debug.c +++ b/arch/x86/platform/atom/punit_atom_debug.c @@ -115,7 +115,7 @@ static struct dentry *punit_dbg_file; static int punit_dbgfs_register(struct punit_device *punit_device) { - static struct dentry *dev_state; + struct dentry *dev_state; punit_dbg_file = debugfs_create_dir("punit_atom", NULL); if (!punit_dbg_file) From d4ae552982de39417d17f823df1f06b1cbc3686c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 6 Sep 2018 15:57:48 +0200 Subject: [PATCH 152/155] perf/x86/intel: Export mem events only if there's PEBS support Memory events depends on PEBS support and access to LDLAT MSR, but we display them in /sys/devices/cpu/events even if the CPU does not provide those, like for KVM guests. That brings the false assumption that those events should be available, while they fail event to open. Separating the mem-* events attributes and merging them with cpu_events only if there's PEBS support detected. We could also check if LDLAT MSR is available, but the PEBS check seems to cover the need now. Suggested-by: Peter Zijlstra Signed-off-by: Jiri Olsa Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Michael Petlan Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Link: http://lkml.kernel.org/r/20180906135748.GC9577@krava Signed-off-by: Ingo Molnar --- arch/x86/events/core.c | 8 ++--- arch/x86/events/intel/core.c | 69 +++++++++++++++++++++++++++--------- 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 06b708494898..de32741d041a 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -1652,9 +1652,9 @@ __init struct attribute **merge_attr(struct attribute **a, struct attribute **b) struct attribute **new; int j, i; - for (j = 0; a[j]; j++) + for (j = 0; a && a[j]; j++) ; - for (i = 0; b[i]; i++) + for (i = 0; b && b[i]; i++) j++; j++; @@ -1663,9 +1663,9 @@ __init struct attribute **merge_attr(struct attribute **a, struct attribute **b) return NULL; j = 0; - for (i = 0; a[i]; i++) + for (i = 0; a && a[i]; i++) new[j++] = a[i]; - for (i = 0; b[i]; i++) + for (i = 0; b && b[i]; i++) new[j++] = b[i]; new[j] = NULL; diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index ab01ef9ddd77..0fb8659b20d8 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -242,7 +242,7 @@ EVENT_ATTR_STR(mem-loads, mem_ld_nhm, "event=0x0b,umask=0x10,ldlat=3"); EVENT_ATTR_STR(mem-loads, mem_ld_snb, "event=0xcd,umask=0x1,ldlat=3"); EVENT_ATTR_STR(mem-stores, mem_st_snb, "event=0xcd,umask=0x2"); -static struct attribute *nhm_events_attrs[] = { +static struct attribute *nhm_mem_events_attrs[] = { EVENT_PTR(mem_ld_nhm), NULL, }; @@ -278,8 +278,6 @@ EVENT_ATTR_STR_HT(topdown-recovery-bubbles.scale, td_recovery_bubbles_scale, "4", "2"); static struct attribute *snb_events_attrs[] = { - EVENT_PTR(mem_ld_snb), - EVENT_PTR(mem_st_snb), EVENT_PTR(td_slots_issued), EVENT_PTR(td_slots_retired), EVENT_PTR(td_fetch_bubbles), @@ -290,6 +288,12 @@ static struct attribute *snb_events_attrs[] = { NULL, }; +static struct attribute *snb_mem_events_attrs[] = { + EVENT_PTR(mem_ld_snb), + EVENT_PTR(mem_st_snb), + NULL, +}; + static struct event_constraint intel_hsw_event_constraints[] = { FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ @@ -3912,8 +3916,6 @@ EVENT_ATTR_STR(cycles-t, cycles_t, "event=0x3c,in_tx=1"); EVENT_ATTR_STR(cycles-ct, cycles_ct, "event=0x3c,in_tx=1,in_tx_cp=1"); static struct attribute *hsw_events_attrs[] = { - EVENT_PTR(mem_ld_hsw), - EVENT_PTR(mem_st_hsw), EVENT_PTR(td_slots_issued), EVENT_PTR(td_slots_retired), EVENT_PTR(td_fetch_bubbles), @@ -3924,6 +3926,12 @@ static struct attribute *hsw_events_attrs[] = { NULL }; +static struct attribute *hsw_mem_events_attrs[] = { + EVENT_PTR(mem_ld_hsw), + EVENT_PTR(mem_st_hsw), + NULL, +}; + static struct attribute *hsw_tsx_events_attrs[] = { EVENT_PTR(tx_start), EVENT_PTR(tx_commit), @@ -3940,13 +3948,6 @@ static struct attribute *hsw_tsx_events_attrs[] = { NULL }; -static __init struct attribute **get_hsw_events_attrs(void) -{ - return boot_cpu_has(X86_FEATURE_RTM) ? - merge_attr(hsw_events_attrs, hsw_tsx_events_attrs) : - hsw_events_attrs; -} - static ssize_t freeze_on_smi_show(struct device *cdev, struct device_attribute *attr, char *buf) @@ -4023,9 +4024,32 @@ static struct attribute *intel_pmu_attrs[] = { NULL, }; +static __init struct attribute ** +get_events_attrs(struct attribute **base, + struct attribute **mem, + struct attribute **tsx) +{ + struct attribute **attrs = base; + struct attribute **old; + + if (mem && x86_pmu.pebs) + attrs = merge_attr(attrs, mem); + + if (tsx && boot_cpu_has(X86_FEATURE_RTM)) { + old = attrs; + attrs = merge_attr(attrs, tsx); + if (old != base) + kfree(old); + } + + return attrs; +} + __init int intel_pmu_init(void) { struct attribute **extra_attr = NULL; + struct attribute **mem_attr = NULL; + struct attribute **tsx_attr = NULL; struct attribute **to_free = NULL; union cpuid10_edx edx; union cpuid10_eax eax; @@ -4137,7 +4161,7 @@ __init int intel_pmu_init(void) x86_pmu.enable_all = intel_pmu_nhm_enable_all; x86_pmu.extra_regs = intel_nehalem_extra_regs; - x86_pmu.cpu_events = nhm_events_attrs; + mem_attr = nhm_mem_events_attrs; /* UOPS_ISSUED.STALLED_CYCLES */ intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = @@ -4266,7 +4290,7 @@ __init int intel_pmu_init(void) x86_pmu.extra_regs = intel_westmere_extra_regs; x86_pmu.flags |= PMU_FL_HAS_RSP_1; - x86_pmu.cpu_events = nhm_events_attrs; + mem_attr = nhm_mem_events_attrs; /* UOPS_ISSUED.STALLED_CYCLES */ intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = @@ -4306,6 +4330,7 @@ __init int intel_pmu_init(void) x86_pmu.flags |= PMU_FL_NO_HT_SHARING; x86_pmu.cpu_events = snb_events_attrs; + mem_attr = snb_mem_events_attrs; /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */ intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = @@ -4346,6 +4371,7 @@ __init int intel_pmu_init(void) x86_pmu.flags |= PMU_FL_NO_HT_SHARING; x86_pmu.cpu_events = snb_events_attrs; + mem_attr = snb_mem_events_attrs; /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */ intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = @@ -4380,10 +4406,12 @@ __init int intel_pmu_init(void) x86_pmu.hw_config = hsw_hw_config; x86_pmu.get_event_constraints = hsw_get_event_constraints; - x86_pmu.cpu_events = get_hsw_events_attrs(); + x86_pmu.cpu_events = hsw_events_attrs; x86_pmu.lbr_double_abort = true; extra_attr = boot_cpu_has(X86_FEATURE_RTM) ? hsw_format_attr : nhm_format_attr; + mem_attr = hsw_mem_events_attrs; + tsx_attr = hsw_tsx_events_attrs; pr_cont("Haswell events, "); name = "haswell"; break; @@ -4419,10 +4447,12 @@ __init int intel_pmu_init(void) x86_pmu.hw_config = hsw_hw_config; x86_pmu.get_event_constraints = hsw_get_event_constraints; - x86_pmu.cpu_events = get_hsw_events_attrs(); + x86_pmu.cpu_events = hsw_events_attrs; x86_pmu.limit_period = bdw_limit_period; extra_attr = boot_cpu_has(X86_FEATURE_RTM) ? hsw_format_attr : nhm_format_attr; + mem_attr = hsw_mem_events_attrs; + tsx_attr = hsw_tsx_events_attrs; pr_cont("Broadwell events, "); name = "broadwell"; break; @@ -4478,7 +4508,9 @@ __init int intel_pmu_init(void) hsw_format_attr : nhm_format_attr; extra_attr = merge_attr(extra_attr, skl_format_attr); to_free = extra_attr; - x86_pmu.cpu_events = get_hsw_events_attrs(); + x86_pmu.cpu_events = hsw_events_attrs; + mem_attr = hsw_mem_events_attrs; + tsx_attr = hsw_tsx_events_attrs; intel_pmu_pebs_data_source_skl( boot_cpu_data.x86_model == INTEL_FAM6_SKYLAKE_X); pr_cont("Skylake events, "); @@ -4511,6 +4543,9 @@ __init int intel_pmu_init(void) WARN_ON(!x86_pmu.format_attrs); } + x86_pmu.cpu_events = get_events_attrs(x86_pmu.cpu_events, + mem_attr, tsx_attr); + if (x86_pmu.num_counters > INTEL_PMC_MAX_GENERIC) { WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!", x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC); From c2712b858187f5bcd7b042fe4daa3ba3a12635c0 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 17 Oct 2018 16:59:51 -0400 Subject: [PATCH 153/155] kprobes, x86/ptrace.h: Make regs_get_kernel_stack_nth() not fault on bad stack Andy had some concerns about using regs_get_kernel_stack_nth() in a new function regs_get_kernel_argument() as if there's any error in the stack code, it could cause a bad memory access. To be on the safe side, call probe_kernel_read() on the stack address to be extra careful in accessing the memory. A helper function, regs_get_kernel_stack_nth_addr(), was added to just return the stack address (or NULL if not on the stack), that will be used to find the address (and could be used by other functions) and read the address with kernel_probe_read(). Requested-by: Andy Lutomirski Signed-off-by: Steven Rostedt (VMware) Reviewed-by: Joel Fernandes (Google) Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Masami Hiramatsu Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20181017165951.09119177@gandalf.local.home Signed-off-by: Ingo Molnar --- arch/x86/include/asm/ptrace.h | 42 +++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index 6de1fd3d0097..ee696efec99f 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h @@ -236,24 +236,52 @@ static inline int regs_within_kernel_stack(struct pt_regs *regs, (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); } +/** + * regs_get_kernel_stack_nth_addr() - get the address of the Nth entry on stack + * @regs: pt_regs which contains kernel stack pointer. + * @n: stack entry number. + * + * regs_get_kernel_stack_nth() returns the address of the @n th entry of the + * kernel stack which is specified by @regs. If the @n th entry is NOT in + * the kernel stack, this returns NULL. + */ +static inline unsigned long *regs_get_kernel_stack_nth_addr(struct pt_regs *regs, unsigned int n) +{ + unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); + + addr += n; + if (regs_within_kernel_stack(regs, (unsigned long)addr)) + return addr; + else + return NULL; +} + +/* To avoid include hell, we can't include uaccess.h */ +extern long probe_kernel_read(void *dst, const void *src, size_t size); + /** * regs_get_kernel_stack_nth() - get Nth entry of the stack * @regs: pt_regs which contains kernel stack pointer. * @n: stack entry number. * * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which - * is specified by @regs. If the @n th entry is NOT in the kernel stack, + * is specified by @regs. If the @n th entry is NOT in the kernel stack * this returns 0. */ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) { - unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); - addr += n; - if (regs_within_kernel_stack(regs, (unsigned long)addr)) - return *addr; - else - return 0; + unsigned long *addr; + unsigned long val; + long ret; + + addr = regs_get_kernel_stack_nth_addr(regs, n); + if (addr) { + ret = probe_kernel_read(&val, addr, sizeof(val)); + if (!ret) + return val; + } + return 0; } #define arch_has_single_step() (1) From b61b8bba18fe2b63d38fdaf9b83de25e2d787dfe Mon Sep 17 00:00:00 2001 From: Jithu Joseph Date: Fri, 12 Oct 2018 15:51:01 -0700 Subject: [PATCH 154/155] x86/intel_rdt: Prevent pseudo-locking from using stale pointers When the last CPU in an rdt_domain goes offline, its rdt_domain struct gets freed. Current pseudo-locking code is unaware of this scenario and tries to dereference the freed structure in a few places. Add checks to prevent pseudo-locking code from doing this. While further work is needed to seamlessly restore resource groups (not just pseudo-locking) to their configuration when the domain is brought back online, the immediate issue of invalid pointers is addressed here. Fixes: f4e80d67a5274 ("x86/intel_rdt: Resctrl files reflect pseudo-locked information") Fixes: 443810fe61605 ("x86/intel_rdt: Create debugfs files for pseudo-locking testing") Fixes: 746e08590b864 ("x86/intel_rdt: Create character device exposing pseudo-locked region") Fixes: 33dc3e410a0d9 ("x86/intel_rdt: Make CPU information accessible for pseudo-locked regions") Signed-off-by: Jithu Joseph Signed-off-by: Reinette Chatre Signed-off-by: Thomas Gleixner Cc: fenghua.yu@intel.com Cc: tony.luck@intel.com Cc: gavin.hindman@intel.com Cc: hpa@zytor.com Link: https://lkml.kernel.org/r/231f742dbb7b00a31cc104416860e27dba6b072d.1539384145.git.reinette.chatre@intel.com --- arch/x86/kernel/cpu/intel_rdt.c | 7 ++++ arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c | 12 +++++-- arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c | 10 ++++++ arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 38 +++++++++++++++------ 4 files changed, 55 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 1214f3f7ec6d..44272b7107ad 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -608,6 +608,13 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r) cancel_delayed_work(&d->cqm_limbo); } + /* + * rdt_domain "d" is going to be freed below, so clear + * its pointer from pseudo_lock_region struct. + */ + if (d->plr) + d->plr->d = NULL; + kfree(d->ctrl_val); kfree(d->mbps_val); bitmap_free(d->rmid_busy_llc); diff --git a/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c b/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c index 0f53049719cd..27937458c231 100644 --- a/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c +++ b/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c @@ -404,8 +404,16 @@ int rdtgroup_schemata_show(struct kernfs_open_file *of, for_each_alloc_enabled_rdt_resource(r) seq_printf(s, "%s:uninitialized\n", r->name); } else if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) { - seq_printf(s, "%s:%d=%x\n", rdtgrp->plr->r->name, - rdtgrp->plr->d->id, rdtgrp->plr->cbm); + if (!rdtgrp->plr->d) { + rdt_last_cmd_clear(); + rdt_last_cmd_puts("Cache domain offline\n"); + ret = -ENODEV; + } else { + seq_printf(s, "%s:%d=%x\n", + rdtgrp->plr->r->name, + rdtgrp->plr->d->id, + rdtgrp->plr->cbm); + } } else { closid = rdtgrp->closid; for_each_alloc_enabled_rdt_resource(r) { diff --git a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c index 41aeb431e834..966ac0c20d67 100644 --- a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c +++ b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c @@ -1174,6 +1174,11 @@ static int pseudo_lock_measure_cycles(struct rdtgroup *rdtgrp, int sel) goto out; } + if (!plr->d) { + ret = -ENODEV; + goto out; + } + plr->thread_done = 0; cpu = cpumask_first(&plr->d->cpu_mask); if (!cpu_online(cpu)) { @@ -1494,6 +1499,11 @@ static int pseudo_lock_dev_mmap(struct file *filp, struct vm_area_struct *vma) plr = rdtgrp->plr; + if (!plr->d) { + mutex_unlock(&rdtgroup_mutex); + return -ENODEV; + } + /* * Task is required to run with affinity to the cpus associated * with the pseudo-locked region. If this is not the case the task diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c index dbc7fc98b60a..f27b8115ffa2 100644 --- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c @@ -268,17 +268,27 @@ static int rdtgroup_cpus_show(struct kernfs_open_file *of, struct seq_file *s, void *v) { struct rdtgroup *rdtgrp; + struct cpumask *mask; int ret = 0; rdtgrp = rdtgroup_kn_lock_live(of->kn); if (rdtgrp) { - if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) - seq_printf(s, is_cpu_list(of) ? "%*pbl\n" : "%*pb\n", - cpumask_pr_args(&rdtgrp->plr->d->cpu_mask)); - else + if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) { + if (!rdtgrp->plr->d) { + rdt_last_cmd_clear(); + rdt_last_cmd_puts("Cache domain offline\n"); + ret = -ENODEV; + } else { + mask = &rdtgrp->plr->d->cpu_mask; + seq_printf(s, is_cpu_list(of) ? + "%*pbl\n" : "%*pb\n", + cpumask_pr_args(mask)); + } + } else { seq_printf(s, is_cpu_list(of) ? "%*pbl\n" : "%*pb\n", cpumask_pr_args(&rdtgrp->cpu_mask)); + } } else { ret = -ENOENT; } @@ -1282,6 +1292,7 @@ static int rdtgroup_size_show(struct kernfs_open_file *of, struct rdt_resource *r; struct rdt_domain *d; unsigned int size; + int ret = 0; bool sep; u32 ctrl; @@ -1292,11 +1303,18 @@ static int rdtgroup_size_show(struct kernfs_open_file *of, } if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) { - seq_printf(s, "%*s:", max_name_width, rdtgrp->plr->r->name); - size = rdtgroup_cbm_to_size(rdtgrp->plr->r, - rdtgrp->plr->d, - rdtgrp->plr->cbm); - seq_printf(s, "%d=%u\n", rdtgrp->plr->d->id, size); + if (!rdtgrp->plr->d) { + rdt_last_cmd_clear(); + rdt_last_cmd_puts("Cache domain offline\n"); + ret = -ENODEV; + } else { + seq_printf(s, "%*s:", max_name_width, + rdtgrp->plr->r->name); + size = rdtgroup_cbm_to_size(rdtgrp->plr->r, + rdtgrp->plr->d, + rdtgrp->plr->cbm); + seq_printf(s, "%d=%u\n", rdtgrp->plr->d->id, size); + } goto out; } @@ -1326,7 +1344,7 @@ static int rdtgroup_size_show(struct kernfs_open_file *of, out: rdtgroup_kn_unlock(of->kn); - return 0; + return ret; } /* rdtgroup information files for one cache resource. */ From 2e62024c265aa69315ed02835623740030435380 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Sat, 20 Oct 2018 18:47:53 +0900 Subject: [PATCH 155/155] kprobes/x86: Use preempt_enable() in optimized_callback() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The following commit: a19b2e3d7839 ("kprobes/x86: Remove IRQ disabling from ftrace-based/optimized kprobes”) removed local_irq_save/restore() from optimized_callback(), the handler might be interrupted by the rescheduling interrupt and might be rescheduled - so we must not use the preempt_enable_no_resched() macro. Use preempt_enable() instead, to not lose preemption events. [ mingo: Improved the changelog. ] Reported-by: Nadav Amit Signed-off-by: Masami Hiramatsu Acked-by: Peter Zijlstra (Intel) Cc: Cc: Alexei Starovoitov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Thomas Gleixner Cc: dwmw@amazon.co.uk Fixes: a19b2e3d7839 ("kprobes/x86: Remove IRQ disabling from ftrace-based/optimized kprobes”) Link: http://lkml.kernel.org/r/154002887331.7627.10194920925792947001.stgit@devbox Signed-off-by: Ingo Molnar --- arch/x86/kernel/kprobes/opt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index eaf02f2e7300..40b16b270656 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c @@ -179,7 +179,7 @@ optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs) opt_pre_handler(&op->kp, regs); __this_cpu_write(current_kprobe, NULL); } - preempt_enable_no_resched(); + preempt_enable(); } NOKPROBE_SYMBOL(optimized_callback);