From b295c3e39c1383e06ba1db4dd836018502e2ff3a Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 18 Sep 2019 16:34:07 +0300 Subject: tools lib traceevent: Convert remaining %p[fF] users to %p[sS] There are no in-kernel %p[fF] users left. Convert the traceevent tool, too, to align with the kernel. Signed-off-by: Sakari Ailus Cc: Andy Shevchenko Cc: devicetree@vger.kernel.org Cc: Heikki Krogerus Cc: Jiri Olsa Cc: Joe Perches Cc: linux-acpi@vger.kernel.org Cc: linux-trace-devel@vger.kernel.org Cc: Namhyung Kim Cc: Petr Mladek Cc: Rafael J. Wysocki Cc: Rob Herring Cc: Steven Rostedt (VMware) Cc: Tzvetomir Stoyanov Link: http://lore.kernel.org/lkml/20190918133419.7969-2-sakari.ailus@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- .../Documentation/libtraceevent-func_apis.txt | 10 +++++----- tools/lib/traceevent/event-parse.c | 18 ++++++++++++++---- 2 files changed, 19 insertions(+), 9 deletions(-) (limited to 'tools/lib/traceevent') diff --git a/tools/lib/traceevent/Documentation/libtraceevent-func_apis.txt b/tools/lib/traceevent/Documentation/libtraceevent-func_apis.txt index 38bfea30a5f6..f6aca0df2151 100644 --- a/tools/lib/traceevent/Documentation/libtraceevent-func_apis.txt +++ b/tools/lib/traceevent/Documentation/libtraceevent-func_apis.txt @@ -59,12 +59,12 @@ parser context. The _tep_register_function()_ function registers a function name mapped to an address and (optional) module. This mapping is used in case the function tracer -or events have "%pF" or "%pS" parameter in its format string. It is common to -pass in the kallsyms function names with their corresponding addresses with this +or events have "%pS" parameter in its format string. It is common to pass in +the kallsyms function names with their corresponding addresses with this function. The _tep_ argument is the trace event parser context. The _name_ is -the name of the function, the string is copied internally. The _addr_ is -the start address of the function. The _mod_ is the kernel module -the function may be in (NULL for none). +the name of the function, the string is copied internally. The _addr_ is the +start address of the function. The _mod_ is the kernel module the function may +be in (NULL for none). The _tep_register_print_string()_ function registers a string by the address it was stored in the kernel. Some strings internal to the kernel with static diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index bb22238debfe..6f842af4550b 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -4367,10 +4367,20 @@ static struct tep_print_arg *make_bprint_args(char *fmt, void *data, int size, s switch (*ptr) { case 's': case 'S': - case 'f': - case 'F': case 'x': break; + case 'f': + case 'F': + /* + * Pre-5.5 kernels use %pf and + * %pF for printing symbols + * while kernels since 5.5 use + * %pfw for fwnodes. So check + * %p[fF] isn't followed by 'w'. + */ + if (ptr[1] != 'w') + break; + /* fall through */ default: /* * Older kernels do not process @@ -4487,12 +4497,12 @@ get_bprint_format(void *data, int size __maybe_unused, printk = find_printk(tep, addr); if (!printk) { - if (asprintf(&format, "%%pf: (NO FORMAT FOUND at %llx)\n", addr) < 0) + if (asprintf(&format, "%%ps: (NO FORMAT FOUND at %llx)\n", addr) < 0) return NULL; return format; } - if (asprintf(&format, "%s: %s", "%pf", printk->printk) < 0) + if (asprintf(&format, "%s: %s", "%ps", printk->printk) < 0) return NULL; return format; -- cgit v1.2.3 From 5c8da72dc21eff32deb00638e547e2c247ebbfb0 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Thu, 19 Sep 2019 16:51:19 -0400 Subject: libtraceevent: Round up in tep_print_event() time precision When testing the output of the old trace-cmd compared to the one that uses the updated tep_print_event() logic, it was different in that the time stamp precision in the old format would round up to the nearest precision, where as the new logic truncates. Bring back the old method of rounding up. Signed-off-by: Steven Rostedt (VMware) Cc: Jiri Olsa Cc: Tzvetomir Stoyanov Cc: linux trace devel Link: http://lore.kernel.org/lkml/20190919165119.5efa5de6@gandalf.local.home Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tools/lib/traceevent') diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 6f842af4550b..d948475585ce 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -5527,8 +5527,10 @@ static void print_event_time(struct tep_handle *tep, struct trace_seq *s, if (divstr && isdigit(*(divstr + 1))) div = atoi(divstr + 1); time = record->ts; - if (div) + if (div) { + time += div / 2; time /= div; + } pr = prec; while (pr--) p10 *= 10; -- cgit v1.2.3 From 4ab91deacc9b8611fdae9055f926c8f99dde8411 Mon Sep 17 00:00:00 2001 From: Tzvetomir Stoyanov Date: Thu, 19 Sep 2019 17:23:36 -0400 Subject: libtraceevent: Man pages for libtraceevent event print related API Added new man page, describing tep_print_event() libtraceevent API. Signed-off-by: Tzvetomir Stoyanov Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: linux-trace-devel@vger.kernel.org Link: http://lore.kernel.org/linux-trace-devel/20190801075012.22098-1-tz.stoyanov@gmail.com Link: http://lore.kernel.org/lkml/20190919212541.553160178@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- .../Documentation/libtraceevent-event_print.txt | 130 +++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 tools/lib/traceevent/Documentation/libtraceevent-event_print.txt (limited to 'tools/lib/traceevent') diff --git a/tools/lib/traceevent/Documentation/libtraceevent-event_print.txt b/tools/lib/traceevent/Documentation/libtraceevent-event_print.txt new file mode 100644 index 000000000000..2c6a61811118 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-event_print.txt @@ -0,0 +1,130 @@ +libtraceevent(3) +================ + +NAME +---- +tep_print_event - Writes event information into a trace sequence. + +SYNOPSIS +-------- +[verse] +-- +*#include * +*#include * + +void *tep_print_event*(struct tep_handle pass:[*]_tep_, struct trace_seqpass:[*]_s_, struct tep_record pass:[*]_record_, const char pass:[*]_fmt_, _..._) +-- + +DESCRIPTION +----------- + +The _tep_print_event()_ function parses the event information of the given +_record_ and writes it into the trace sequence _s_, according to the format +string _fmt_. The desired information is specified after the format string. +The _fmt_ is printf-like format string, following arguments are supported: +[verse] +-- + TEP_PRINT_PID, "%d" - PID of the event. + TEP_PRINT_CPU, "%d" - Event CPU. + TEP_PRINT_COMM, "%s" - Event command string. + TEP_PRINT_NAME, "%s" - Event name. + TEP_PRINT_LATENCY, "%s" - Latency of the event. It prints 4 or more + fields - interrupt state, scheduling state, + current context, and preemption count. + Field 1 is the interrupt enabled state: + d : Interrupts are disabled + . : Interrupts are enabled + X : The architecture does not support this + information + Field 2 is the "need resched" state. + N : The task is set to call the scheduler when + possible, as another higher priority task + may need to be scheduled in. + . : The task is not set to call the scheduler. + Field 3 is the context state. + . : Normal context + s : Soft interrupt context + h : Hard interrupt context + H : Hard interrupt context which triggered + during soft interrupt context. + z : NMI context + Z : NMI context which triggered during hard + interrupt context + Field 4 is the preemption count. + . : The preempt count is zero. + On preemptible kernels (where the task can be scheduled + out in arbitrary locations while in kernel context), the + preempt count, when non zero, will prevent the kernel + from scheduling out the current task. The preempt count + number is displayed when it is not zero. + Depending on the kernel, it may show other fields + (lock depth, or migration disabled, which are unique to + specialized kernels). + TEP_PRINT_TIME, %d - event time stamp. A divisor and precision can be + specified as part of this format string: + "%precision.divisord". Example: + "%3.1000d" - divide the time by 1000 and print the first + 3 digits before the dot. Thus, the time stamp + "123456000" will be printed as "123.456" + TEP_PRINT_INFO, "%s" - event information. + TEP_PRINT_INFO_RAW, "%s" - event information, in raw format. + +-- +EXAMPLE +------- +[source,c] +-- +#include +#include +... +struct trace_seq seq; +trace_seq_init(&seq); +struct tep_handle *tep = tep_alloc(); +... +void print_my_event(struct tep_record *record) +{ + trace_seq_reset(&seq); + tep_print_event(tep, s, record, "%16s-%-5d [%03d] %s %6.1000d %s %s", + TEP_PRINT_COMM, TEP_PRINT_PID, TEP_PRINT_CPU, + TEP_PRINT_LATENCY, TEP_PRINT_TIME, TEP_PRINT_NAME, + TEP_PRINT_INFO); +} +... +-- + +FILES +----- +[verse] +-- +*event-parse.h* + Header file to include in order to have access to the library APIs. +*trace-seq.h* + Header file to include in order to have access to trace sequences related APIs. + Trace sequences are used to allow a function to call several other functions + to create a string of data to use. +*-ltraceevent* + Linker switch to add when building a program that uses the library. +-- + +SEE ALSO +-------- +_libtraceevent(3)_, _trace-cmd(1)_ + +AUTHOR +------ +[verse] +-- +*Steven Rostedt* , author of *libtraceevent*. +*Tzvetomir Stoyanov* , author of this man page. +-- +REPORTING BUGS +-------------- +Report bugs to + +LICENSE +------- +libtraceevent is Free Software licensed under the GNU LGPL 2.1 + +RESOURCES +--------- +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git -- cgit v1.2.3 From 38f76c31368b7a8b88659c178f9e620b02660a70 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Thu, 19 Sep 2019 17:23:37 -0400 Subject: libtraceevent: Man pages fix, rename tep_ref_get() to tep_get_ref() The tep_ref_get() was renamed to tep_get_ref(), to be more consistent with the other tep_ref_* APIs. However, in the man pages the API is still with the old name. The documentation is fixed to reflect the actual name of the API. 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://lore.kernel.org/linux-trace-devel/20190808113636.13299-2-tz.stoyanov@gmail.com Link: http://lore.kernel.org/lkml/20190919212541.697034573@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Documentation/libtraceevent-handle.txt | 8 ++++---- tools/lib/traceevent/Documentation/libtraceevent.txt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'tools/lib/traceevent') diff --git a/tools/lib/traceevent/Documentation/libtraceevent-handle.txt b/tools/lib/traceevent/Documentation/libtraceevent-handle.txt index 8d568316847d..45b20172e262 100644 --- a/tools/lib/traceevent/Documentation/libtraceevent-handle.txt +++ b/tools/lib/traceevent/Documentation/libtraceevent-handle.txt @@ -3,7 +3,7 @@ libtraceevent(3) NAME ---- -tep_alloc, tep_free,tep_ref, tep_unref,tep_ref_get - Create, destroy, manage +tep_alloc, tep_free,tep_ref, tep_unref,tep_get_ref - Create, destroy, manage references of trace event parser context. SYNOPSIS @@ -16,7 +16,7 @@ struct tep_handle pass:[*]*tep_alloc*(void); void *tep_free*(struct tep_handle pass:[*]_tep_); void *tep_ref*(struct tep_handle pass:[*]_tep_); void *tep_unref*(struct tep_handle pass:[*]_tep_); -int *tep_ref_get*(struct tep_handle pass:[*]_tep_); +int *tep_get_ref*(struct tep_handle pass:[*]_tep_); -- DESCRIPTION @@ -57,9 +57,9 @@ EXAMPLE ... struct tep_handle *tep = tep_alloc(); ... -int ref = tep_ref_get(tep); +int ref = tep_get_ref(tep); tep_ref(tep); -if ( (ref+1) != tep_ref_get(tep)) { +if ( (ref+1) != tep_get_ref(tep)) { /* Something wrong happened, the counter is not incremented by 1 */ } tep_unref(tep); diff --git a/tools/lib/traceevent/Documentation/libtraceevent.txt b/tools/lib/traceevent/Documentation/libtraceevent.txt index fbd977b47de1..00519503c8de 100644 --- a/tools/lib/traceevent/Documentation/libtraceevent.txt +++ b/tools/lib/traceevent/Documentation/libtraceevent.txt @@ -16,7 +16,7 @@ Management of tep handler data structure and access of its members: void *tep_free*(struct tep_handle pass:[*]_tep_); void *tep_ref*(struct tep_handle pass:[*]_tep_); void *tep_unref*(struct tep_handle pass:[*]_tep_); - int *tep_ref_get*(struct tep_handle pass:[*]_tep_); + int *tep_get_ref*(struct tep_handle pass:[*]_tep_); void *tep_set_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); void *tep_clear_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); bool *tep_test_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flags_); -- cgit v1.2.3 From f8d16387fffba1c7c88b5570b09891ba8a26cfd5 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Thu, 19 Sep 2019 17:23:38 -0400 Subject: libtraceevent: Man pages fix, changes in event printing APIs APIs for printing various trace event information were redesigned to be more simple. However, the main libtraceevent man page was not updated with those changes. The documentation is updated to describe the new event print API. 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://lore.kernel.org/linux-trace-devel/20190808113636.13299-3-tz.stoyanov@gmail.com Link: http://lore.kernel.org/lkml/20190919212541.869643036@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Documentation/libtraceevent.txt | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'tools/lib/traceevent') diff --git a/tools/lib/traceevent/Documentation/libtraceevent.txt b/tools/lib/traceevent/Documentation/libtraceevent.txt index 00519503c8de..d530a7ce8fb2 100644 --- a/tools/lib/traceevent/Documentation/libtraceevent.txt +++ b/tools/lib/traceevent/Documentation/libtraceevent.txt @@ -26,15 +26,12 @@ Management of tep handler data structure and access of its members: void *tep_set_long_size*(struct tep_handle pass:[*]_tep_, int _long_size_); int *tep_get_page_size*(struct tep_handle pass:[*]_tep_); void *tep_set_page_size*(struct tep_handle pass:[*]_tep_, int _page_size_); - bool *tep_is_latency_format*(struct tep_handle pass:[*]_tep_); - void *tep_set_latency_format*(struct tep_handle pass:[*]_tep_, int _lat_); int *tep_get_header_page_size*(struct tep_handle pass:[*]_tep_); int *tep_get_header_timestamp_size*(struct tep_handle pass:[*]_tep_); bool *tep_is_old_format*(struct tep_handle pass:[*]_tep_); int *tep_strerror*(struct tep_handle pass:[*]_tep_, enum tep_errno _errnum_, char pass:[*]_buf_, size_t _buflen_); Register / unregister APIs: - int *tep_register_trace_clock*(struct tep_handle pass:[*]_tep_, const char pass:[*]_trace_clock_); int *tep_register_function*(struct tep_handle pass:[*]_tep_, char pass:[*]_name_, unsigned long long _addr_, char pass:[*]_mod_); int *tep_register_event_handler*(struct tep_handle pass:[*]_tep_, int _id_, const char pass:[*]_sys_name_, const char pass:[*]_event_name_, tep_event_handler_func _func_, void pass:[*]_context_); int *tep_unregister_event_handler*(struct tep_handle pass:[*]tep, int id, const char pass:[*]sys_name, const char pass:[*]event_name, tep_event_handler_func func, void pass:[*]_context_); @@ -57,14 +54,7 @@ Event related APIs: int *tep_get_events_count*(struct tep_handle pass:[*]_tep_); struct tep_event pass:[*]pass:[*]*tep_list_events*(struct tep_handle pass:[*]_tep_, enum tep_event_sort_type _sort_type_); struct tep_event pass:[*]pass:[*]*tep_list_events_copy*(struct tep_handle pass:[*]_tep_, enum tep_event_sort_type _sort_type_); - -Event printing: - void *tep_print_event*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_record pass:[*]_record_, bool _use_trace_clock_); - void *tep_print_event_data*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]_record_); - void *tep_event_info*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]_record_); - void *tep_print_event_task*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]_record_); - void *tep_print_event_time*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]record, bool _use_trace_clock_); - void *tep_set_print_raw*(struct tep_handle pass:[*]_tep_, int _print_raw_); + void *tep_print_event*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_record pass:[*]_record_, const char pass:[*]_fmt_, _..._); Event finding: struct tep_event pass:[*]*tep_find_event*(struct tep_handle pass:[*]_tep_, int _id_); @@ -116,7 +106,6 @@ Filter management: int *tep_filter_compare*(struct tep_event_filter pass:[*]_filter1_, struct tep_event_filter pass:[*]_filter2_); Parsing various data from the records: - void *tep_data_latency_format*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_record pass:[*]_record_); int *tep_data_type*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); int *tep_data_pid*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); int *tep_data_preempt_count*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); -- cgit v1.2.3 From d69094f364d012f6d0be712969e6a6a355b69e84 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Thu, 19 Sep 2019 17:23:39 -0400 Subject: libtraceevent: Add tep_get_event() in event-parse.h The tep_get_event() function is an official libtracevent API, described in the library man pages. However, it cannot be used by the library users because it is not declared in the event-parse.h file, where all libtracevent APIs are. The function declaration is added in event-parse.h file. 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://lore.kernel.org/linux-trace-devel/20190808113721.13539-1-tz.stoyanov@gmail.com Link: http://lore.kernel.org/lkml/20190919212542.058025937@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tools/lib/traceevent') diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index d438ee44289f..b77837f75a0d 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -441,6 +441,8 @@ int tep_register_print_string(struct tep_handle *tep, const char *fmt, unsigned long long addr); bool tep_is_pid_registered(struct tep_handle *tep, int pid); +struct tep_event *tep_get_event(struct tep_handle *tep, int index); + #define TEP_PRINT_INFO "INFO" #define TEP_PRINT_INFO_RAW "INFO_RAW" #define TEP_PRINT_COMM "COMM" -- cgit v1.2.3 From 077faf3dc7cc13c3bd784613304bf38696b591da Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Thu, 19 Sep 2019 17:23:41 -0400 Subject: libtraceevent: Move traceevent plugins in its own subdirectory All traceevent plugins code is moved to tools/lib/traceevent/plugins subdirectory. It makes traceevent implementation in trace-cmd and in kernel tree consistent. There is no changes in the way libtraceevent and plugins are compiled and installed. Committer notes: Applied fixup provided by Steven, fixing the tools/perf/Makefile.perf target for the plugin dynamic list file. Problem noticed when cross building to aarch64 from a Ubuntu 19.04 container. Suggested-by: Steven Rostedt (VMware) 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://lore.kernel.org/lkml/20190923115929.453b68f1@oasis.local.home Link: http://lore.kernel.org/lkml/20190919212542.377333393@goodmis.org Link: http://lore.kernel.org/linux-trace-devel/20190917105055.18983-1-tz.stoyanov@gmail.com Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Build | 11 - tools/lib/traceevent/Makefile | 94 +--- tools/lib/traceevent/plugin_cfg80211.c | 43 -- tools/lib/traceevent/plugin_function.c | 195 -------- tools/lib/traceevent/plugin_hrtimer.c | 89 ---- tools/lib/traceevent/plugin_jbd2.c | 76 --- tools/lib/traceevent/plugin_kmem.c | 95 ---- tools/lib/traceevent/plugin_kvm.c | 523 --------------------- tools/lib/traceevent/plugin_mac80211.c | 103 ---- tools/lib/traceevent/plugin_sched_switch.c | 161 ------- tools/lib/traceevent/plugin_scsi.c | 434 ----------------- tools/lib/traceevent/plugin_xen.c | 138 ------ tools/lib/traceevent/plugins/Build | 10 + tools/lib/traceevent/plugins/Makefile | 222 +++++++++ tools/lib/traceevent/plugins/plugin_cfg80211.c | 43 ++ tools/lib/traceevent/plugins/plugin_function.c | 195 ++++++++ tools/lib/traceevent/plugins/plugin_hrtimer.c | 89 ++++ tools/lib/traceevent/plugins/plugin_jbd2.c | 76 +++ tools/lib/traceevent/plugins/plugin_kmem.c | 95 ++++ tools/lib/traceevent/plugins/plugin_kvm.c | 523 +++++++++++++++++++++ tools/lib/traceevent/plugins/plugin_mac80211.c | 103 ++++ tools/lib/traceevent/plugins/plugin_sched_switch.c | 161 +++++++ tools/lib/traceevent/plugins/plugin_scsi.c | 434 +++++++++++++++++ tools/lib/traceevent/plugins/plugin_xen.c | 138 ++++++ tools/perf/Makefile.perf | 4 +- 25 files changed, 2107 insertions(+), 1948 deletions(-) delete mode 100644 tools/lib/traceevent/plugin_cfg80211.c delete mode 100644 tools/lib/traceevent/plugin_function.c delete mode 100644 tools/lib/traceevent/plugin_hrtimer.c delete mode 100644 tools/lib/traceevent/plugin_jbd2.c delete mode 100644 tools/lib/traceevent/plugin_kmem.c delete mode 100644 tools/lib/traceevent/plugin_kvm.c delete mode 100644 tools/lib/traceevent/plugin_mac80211.c delete mode 100644 tools/lib/traceevent/plugin_sched_switch.c delete mode 100644 tools/lib/traceevent/plugin_scsi.c delete mode 100644 tools/lib/traceevent/plugin_xen.c create mode 100644 tools/lib/traceevent/plugins/Build create mode 100644 tools/lib/traceevent/plugins/Makefile create mode 100644 tools/lib/traceevent/plugins/plugin_cfg80211.c create mode 100644 tools/lib/traceevent/plugins/plugin_function.c create mode 100644 tools/lib/traceevent/plugins/plugin_hrtimer.c create mode 100644 tools/lib/traceevent/plugins/plugin_jbd2.c create mode 100644 tools/lib/traceevent/plugins/plugin_kmem.c create mode 100644 tools/lib/traceevent/plugins/plugin_kvm.c create mode 100644 tools/lib/traceevent/plugins/plugin_mac80211.c create mode 100644 tools/lib/traceevent/plugins/plugin_sched_switch.c create mode 100644 tools/lib/traceevent/plugins/plugin_scsi.c create mode 100644 tools/lib/traceevent/plugins/plugin_xen.c (limited to 'tools/lib/traceevent') diff --git a/tools/lib/traceevent/Build b/tools/lib/traceevent/Build index ba54bfce0b0b..f9a5d79578f5 100644 --- a/tools/lib/traceevent/Build +++ b/tools/lib/traceevent/Build @@ -6,14 +6,3 @@ 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 -plugin_kmem-y += plugin_kmem.o -plugin_kvm-y += plugin_kvm.o -plugin_mac80211-y += plugin_mac80211.o -plugin_sched_switch-y += plugin_sched_switch.o -plugin_function-y += plugin_function.o -plugin_xen-y += plugin_xen.o -plugin_scsi-y += plugin_scsi.o -plugin_cfg80211-y += plugin_cfg80211.o diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index a39cdd0d890d..5315f3787f8d 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -58,30 +58,6 @@ export man_dir man_dir_SQ INSTALL export DESTDIR DESTDIR_SQ export EVENT_PARSE_VERSION -set_plugin_dir := 1 - -# Set plugin_dir to preffered global plugin location -# If we install under $HOME directory we go under -# $(HOME)/.local/lib/traceevent/plugins -# -# We dont set PLUGIN_DIR in case we install under $HOME -# directory, because by default the code looks under: -# $(HOME)/.local/lib/traceevent/plugins by default. -# -ifeq ($(plugin_dir),) -ifeq ($(prefix),$(HOME)) -override plugin_dir = $(HOME)/.local/lib/traceevent/plugins -set_plugin_dir := 0 -else -override plugin_dir = $(libdir)/traceevent/plugins -endif -endif - -ifeq ($(set_plugin_dir),1) -PLUGIN_DIR = -DPLUGIN_DIR="$(plugin_dir)" -PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))' -endif - include ../../scripts/Makefile.include # copy a bit from Linux kbuild @@ -105,7 +81,6 @@ export prefix libdir src obj # Shell quotes libdir_SQ = $(subst ','\'',$(libdir)) libdir_relative_SQ = $(subst ','\'',$(libdir_relative)) -plugin_dir_SQ = $(subst ','\'',$(plugin_dir)) CONFIG_INCLUDES = CONFIG_LIBS = @@ -151,29 +126,14 @@ MAKEOVERRIDES= export srctree OUTPUT CC LD CFLAGS V build := -f $(srctree)/tools/build/Makefile.build dir=. obj -PLUGINS = plugin_jbd2.so -PLUGINS += plugin_hrtimer.so -PLUGINS += plugin_kmem.so -PLUGINS += plugin_kvm.so -PLUGINS += plugin_mac80211.so -PLUGINS += plugin_sched_switch.so -PLUGINS += plugin_function.so -PLUGINS += plugin_xen.so -PLUGINS += plugin_scsi.so -PLUGINS += plugin_cfg80211.so - -PLUGINS := $(addprefix $(OUTPUT),$(PLUGINS)) -PLUGINS_IN := $(PLUGINS:.so=-in.o) - TE_IN := $(OUTPUT)libtraceevent-in.o LIB_TARGET := $(addprefix $(OUTPUT),$(LIB_TARGET)) -DYNAMIC_LIST_FILE := $(OUTPUT)libtraceevent-dynamic-list -CMD_TARGETS = $(LIB_TARGET) $(PLUGINS) $(DYNAMIC_LIST_FILE) +CMD_TARGETS = $(LIB_TARGET) TARGETS = $(CMD_TARGETS) -all: all_cmd +all: all_cmd plugins all_cmd: $(CMD_TARGETS) @@ -188,17 +148,6 @@ $(OUTPUT)libtraceevent.so.$(EVENT_PARSE_VERSION): $(TE_IN) $(OUTPUT)libtraceevent.a: $(TE_IN) $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ -$(OUTPUT)libtraceevent-dynamic-list: $(PLUGINS) - $(QUIET_GEN)$(call do_generate_dynamic_list_file, $(PLUGINS), $@) - -plugins: $(PLUGINS) - -__plugin_obj = $(notdir $@) - plugin_obj = $(__plugin_obj:-in.o=) - -$(PLUGINS_IN): force - $(Q)$(MAKE) $(build)=$(plugin_obj) - $(OUTPUT)%.so: $(OUTPUT)%-in.o $(QUIET_LINK)$(CC) $(CFLAGS) -shared $(LDFLAGS) -nostartfiles -o $@ $^ @@ -258,25 +207,6 @@ define do_install $(INSTALL) $(if $3,-m $3,) $1 '$(DESTDIR_SQ)$2' endef -define do_install_plugins - for plugin in $1; do \ - $(call do_install,$$plugin,$(plugin_dir_SQ)); \ - done -endef - -define do_generate_dynamic_list_file - symbol_type=`$(NM) -u -D $1 | awk 'NF>1 {print $$1}' | \ - xargs echo "U w W" | tr 'w ' 'W\n' | sort -u | xargs echo`;\ - if [ "$$symbol_type" = "U W" ];then \ - (echo '{'; \ - $(NM) -u -D $1 | awk 'NF>1 {print "\t"$$2";"}' | sort -u;\ - echo '};'; \ - ) > $2; \ - else \ - (echo Either missing one of [$1] or bad version of $(NM)) 1>&2;\ - fi -endef - PKG_CONFIG_FILE = libtraceevent.pc define do_install_pkgconfig_file if [ -n "${pkgconfig_dir}" ]; then \ @@ -296,10 +226,6 @@ install_lib: all_cmd install_plugins install_headers install_pkgconfig $(call do_install_mkdir,$(libdir_SQ)); \ cp -fpR $(LIB_INSTALL) $(DESTDIR)$(libdir_SQ) -install_plugins: $(PLUGINS) - $(call QUIET_INSTALL, trace_plugins) \ - $(call do_install_plugins, $(PLUGINS)) - install_pkgconfig: $(call QUIET_INSTALL, $(PKG_CONFIG_FILE)) \ $(call do_install_pkgconfig_file,$(prefix)) @@ -313,7 +239,7 @@ install_headers: install: install_lib -clean: +clean: clean_plugins $(call QUIET_CLEAN, libtraceevent) \ $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d .*.cmd; \ $(RM) TRACEEVENT-CFLAGS tags TAGS; \ @@ -351,7 +277,19 @@ help: @echo ' doc-install - install the man pages' @echo ' doc-uninstall - uninstall the man pages' @echo'' -PHONY += force plugins + +PHONY += plugins +plugins: + $(call descend,plugins) + +PHONY += install_plugins +install_plugins: + $(call descend,plugins,install) + +PHONY += clean_plugins +clean_plugins: + $(call descend,plugins,clean) + force: # Declare the contents of the .PHONY variable as phony. We keep that diff --git a/tools/lib/traceevent/plugin_cfg80211.c b/tools/lib/traceevent/plugin_cfg80211.c deleted file mode 100644 index 3d43b56a6c98..000000000000 --- a/tools/lib/traceevent/plugin_cfg80211.c +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include "event-parse.h" - -/* - * From glibc endian.h, for older systems where it is not present, e.g.: RHEL5, - * Fedora6. - */ -#ifndef le16toh -# if __BYTE_ORDER == __LITTLE_ENDIAN -# define le16toh(x) (x) -# else -# define le16toh(x) __bswap_16 (x) -# endif -#endif - - -static unsigned long long -process___le16_to_cpup(struct trace_seq *s, unsigned long long *args) -{ - uint16_t *val = (uint16_t *) (unsigned long) args[0]; - return val ? (long long) le16toh(*val) : 0; -} - -int TEP_PLUGIN_LOADER(struct tep_handle *tep) -{ - tep_register_print_function(tep, - process___le16_to_cpup, - TEP_FUNC_ARG_INT, - "__le16_to_cpup", - TEP_FUNC_ARG_PTR, - TEP_FUNC_ARG_VOID); - return 0; -} - -void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) -{ - tep_unregister_print_function(tep, process___le16_to_cpup, - "__le16_to_cpup"); -} diff --git a/tools/lib/traceevent/plugin_function.c b/tools/lib/traceevent/plugin_function.c deleted file mode 100644 index 7770fcb78e0f..000000000000 --- a/tools/lib/traceevent/plugin_function.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License (not later!) - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include -#include -#include - -#include "event-parse.h" -#include "event-utils.h" -#include "trace-seq.h" - -static struct func_stack { - int size; - char **stack; -} *fstack; - -static int cpus = -1; - -#define STK_BLK 10 - -struct tep_plugin_option plugin_options[] = -{ - { - .name = "parent", - .plugin_alias = "ftrace", - .description = - "Print parent of functions for function events", - }, - { - .name = "indent", - .plugin_alias = "ftrace", - .description = - "Try to show function call indents, based on parents", - .set = 1, - }, - { - .name = NULL, - } -}; - -static struct tep_plugin_option *ftrace_parent = &plugin_options[0]; -static struct tep_plugin_option *ftrace_indent = &plugin_options[1]; - -static void add_child(struct func_stack *stack, const char *child, int pos) -{ - int i; - - if (!child) - return; - - if (pos < stack->size) - free(stack->stack[pos]); - else { - char **ptr; - - ptr = realloc(stack->stack, sizeof(char *) * - (stack->size + STK_BLK)); - if (!ptr) { - warning("could not allocate plugin memory\n"); - return; - } - - stack->stack = ptr; - - for (i = stack->size; i < stack->size + STK_BLK; i++) - stack->stack[i] = NULL; - stack->size += STK_BLK; - } - - stack->stack[pos] = strdup(child); -} - -static int add_and_get_index(const char *parent, const char *child, int cpu) -{ - int i; - - if (cpu < 0) - return 0; - - if (cpu > cpus) { - struct func_stack *ptr; - - ptr = realloc(fstack, sizeof(*fstack) * (cpu + 1)); - if (!ptr) { - warning("could not allocate plugin memory\n"); - return 0; - } - - fstack = ptr; - - /* Account for holes in the cpu count */ - for (i = cpus + 1; i <= cpu; i++) - memset(&fstack[i], 0, sizeof(fstack[i])); - cpus = cpu; - } - - for (i = 0; i < fstack[cpu].size && fstack[cpu].stack[i]; i++) { - if (strcmp(parent, fstack[cpu].stack[i]) == 0) { - add_child(&fstack[cpu], child, i+1); - return i; - } - } - - /* Not found */ - add_child(&fstack[cpu], parent, 0); - add_child(&fstack[cpu], child, 1); - return 0; -} - -static int function_handler(struct trace_seq *s, struct tep_record *record, - struct tep_event *event, void *context) -{ - struct tep_handle *tep = event->tep; - unsigned long long function; - unsigned long long pfunction; - const char *func; - const char *parent; - int index = 0; - - if (tep_get_field_val(s, event, "ip", record, &function, 1)) - return trace_seq_putc(s, '!'); - - func = tep_find_function(tep, function); - - if (tep_get_field_val(s, event, "parent_ip", record, &pfunction, 1)) - return trace_seq_putc(s, '!'); - - parent = tep_find_function(tep, pfunction); - - if (parent && ftrace_indent->set) - index = add_and_get_index(parent, func, record->cpu); - - trace_seq_printf(s, "%*s", index*3, ""); - - if (func) - trace_seq_printf(s, "%s", func); - else - trace_seq_printf(s, "0x%llx", function); - - if (ftrace_parent->set) { - trace_seq_printf(s, " <-- "); - if (parent) - trace_seq_printf(s, "%s", parent); - else - trace_seq_printf(s, "0x%llx", pfunction); - } - - return 0; -} - -int TEP_PLUGIN_LOADER(struct tep_handle *tep) -{ - tep_register_event_handler(tep, -1, "ftrace", "function", - function_handler, NULL); - - tep_plugin_add_options("ftrace", plugin_options); - - return 0; -} - -void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) -{ - int i, x; - - tep_unregister_event_handler(tep, -1, "ftrace", "function", - function_handler, NULL); - - for (i = 0; i <= cpus; i++) { - for (x = 0; x < fstack[i].size && fstack[i].stack[x]; x++) - free(fstack[i].stack[x]); - free(fstack[i].stack); - } - - tep_plugin_remove_options(plugin_options); - - free(fstack); - fstack = NULL; - cpus = -1; -} diff --git a/tools/lib/traceevent/plugin_hrtimer.c b/tools/lib/traceevent/plugin_hrtimer.c deleted file mode 100644 index bb434e0ed03a..000000000000 --- a/tools/lib/traceevent/plugin_hrtimer.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2009 Red Hat Inc, Steven Rostedt - * Copyright (C) 2009 Johannes Berg - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License (not later!) - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include -#include -#include - -#include "event-parse.h" -#include "trace-seq.h" - -static int timer_expire_handler(struct trace_seq *s, - struct tep_record *record, - struct tep_event *event, void *context) -{ - trace_seq_printf(s, "hrtimer="); - - if (tep_print_num_field(s, "0x%llx", event, "timer", - record, 0) == -1) - tep_print_num_field(s, "0x%llx", event, "hrtimer", - record, 1); - - trace_seq_printf(s, " now="); - - tep_print_num_field(s, "%llu", event, "now", record, 1); - - tep_print_func_field(s, " function=%s", event, "function", - record, 0); - return 0; -} - -static int timer_start_handler(struct trace_seq *s, - struct tep_record *record, - struct tep_event *event, void *context) -{ - trace_seq_printf(s, "hrtimer="); - - if (tep_print_num_field(s, "0x%llx", event, "timer", - record, 0) == -1) - tep_print_num_field(s, "0x%llx", event, "hrtimer", - record, 1); - - tep_print_func_field(s, " function=%s", event, "function", - record, 0); - - trace_seq_printf(s, " expires="); - tep_print_num_field(s, "%llu", event, "expires", record, 1); - - trace_seq_printf(s, " softexpires="); - tep_print_num_field(s, "%llu", event, "softexpires", record, 1); - return 0; -} - -int TEP_PLUGIN_LOADER(struct tep_handle *tep) -{ - tep_register_event_handler(tep, -1, - "timer", "hrtimer_expire_entry", - timer_expire_handler, NULL); - - tep_register_event_handler(tep, -1, "timer", "hrtimer_start", - timer_start_handler, NULL); - return 0; -} - -void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) -{ - tep_unregister_event_handler(tep, -1, - "timer", "hrtimer_expire_entry", - timer_expire_handler, NULL); - - tep_unregister_event_handler(tep, -1, "timer", "hrtimer_start", - timer_start_handler, NULL); -} diff --git a/tools/lib/traceevent/plugin_jbd2.c b/tools/lib/traceevent/plugin_jbd2.c deleted file mode 100644 index 04fc125f38cb..000000000000 --- a/tools/lib/traceevent/plugin_jbd2.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2010 Red Hat Inc, Steven Rostedt - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License (not later!) - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include -#include -#include - -#include "event-parse.h" -#include "trace-seq.h" - -#define MINORBITS 20 -#define MINORMASK ((1U << MINORBITS) - 1) - -#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS)) -#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) - -static unsigned long long -process_jbd2_dev_to_name(struct trace_seq *s, unsigned long long *args) -{ - unsigned int dev = args[0]; - - trace_seq_printf(s, "%d:%d", MAJOR(dev), MINOR(dev)); - return 0; -} - -static unsigned long long -process_jiffies_to_msecs(struct trace_seq *s, unsigned long long *args) -{ - unsigned long long jiffies = args[0]; - - trace_seq_printf(s, "%lld", jiffies); - return jiffies; -} - -int TEP_PLUGIN_LOADER(struct tep_handle *tep) -{ - tep_register_print_function(tep, - process_jbd2_dev_to_name, - TEP_FUNC_ARG_STRING, - "jbd2_dev_to_name", - TEP_FUNC_ARG_INT, - TEP_FUNC_ARG_VOID); - - tep_register_print_function(tep, - process_jiffies_to_msecs, - TEP_FUNC_ARG_LONG, - "jiffies_to_msecs", - TEP_FUNC_ARG_LONG, - TEP_FUNC_ARG_VOID); - return 0; -} - -void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) -{ - tep_unregister_print_function(tep, process_jbd2_dev_to_name, - "jbd2_dev_to_name"); - - tep_unregister_print_function(tep, process_jiffies_to_msecs, - "jiffies_to_msecs"); -} diff --git a/tools/lib/traceevent/plugin_kmem.c b/tools/lib/traceevent/plugin_kmem.c deleted file mode 100644 index edaec5d962c3..000000000000 --- a/tools/lib/traceevent/plugin_kmem.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2009 Red Hat Inc, Steven Rostedt - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License (not later!) - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include -#include -#include - -#include "event-parse.h" -#include "trace-seq.h" - -static int call_site_handler(struct trace_seq *s, struct tep_record *record, - struct tep_event *event, void *context) -{ - struct tep_format_field *field; - unsigned long long val, addr; - void *data = record->data; - const char *func; - - field = tep_find_field(event, "call_site"); - if (!field) - return 1; - - if (tep_read_number_field(field, data, &val)) - return 1; - - func = tep_find_function(event->tep, val); - if (!func) - return 1; - - addr = tep_find_function_address(event->tep, val); - - trace_seq_printf(s, "(%s+0x%x) ", func, (int)(val - addr)); - return 1; -} - -int TEP_PLUGIN_LOADER(struct tep_handle *tep) -{ - tep_register_event_handler(tep, -1, "kmem", "kfree", - call_site_handler, NULL); - - tep_register_event_handler(tep, -1, "kmem", "kmalloc", - call_site_handler, NULL); - - tep_register_event_handler(tep, -1, "kmem", "kmalloc_node", - call_site_handler, NULL); - - tep_register_event_handler(tep, -1, "kmem", "kmem_cache_alloc", - call_site_handler, NULL); - - tep_register_event_handler(tep, -1, "kmem", - "kmem_cache_alloc_node", - call_site_handler, NULL); - - tep_register_event_handler(tep, -1, "kmem", "kmem_cache_free", - call_site_handler, NULL); - return 0; -} - -void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) -{ - tep_unregister_event_handler(tep, -1, "kmem", "kfree", - call_site_handler, NULL); - - tep_unregister_event_handler(tep, -1, "kmem", "kmalloc", - call_site_handler, NULL); - - tep_unregister_event_handler(tep, -1, "kmem", "kmalloc_node", - call_site_handler, NULL); - - tep_unregister_event_handler(tep, -1, "kmem", "kmem_cache_alloc", - call_site_handler, NULL); - - tep_unregister_event_handler(tep, -1, "kmem", - "kmem_cache_alloc_node", - call_site_handler, NULL); - - tep_unregister_event_handler(tep, -1, "kmem", "kmem_cache_free", - call_site_handler, NULL); -} diff --git a/tools/lib/traceevent/plugin_kvm.c b/tools/lib/traceevent/plugin_kvm.c deleted file mode 100644 index c8e623065a7e..000000000000 --- a/tools/lib/traceevent/plugin_kvm.c +++ /dev/null @@ -1,523 +0,0 @@ -/* - * Copyright (C) 2009 Red Hat Inc, Steven Rostedt - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License (not later!) - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include -#include -#include -#include - -#include "event-parse.h" -#include "trace-seq.h" - -#ifdef HAVE_UDIS86 - -#include - -static ud_t ud; - -static void init_disassembler(void) -{ - ud_init(&ud); - ud_set_syntax(&ud, UD_SYN_ATT); -} - -static const char *disassemble(unsigned char *insn, int len, uint64_t rip, - int cr0_pe, int eflags_vm, - int cs_d, int cs_l) -{ - int mode; - - if (!cr0_pe) - mode = 16; - else if (eflags_vm) - mode = 16; - else if (cs_l) - mode = 64; - else if (cs_d) - mode = 32; - else - mode = 16; - - ud_set_pc(&ud, rip); - ud_set_mode(&ud, mode); - ud_set_input_buffer(&ud, insn, len); - ud_disassemble(&ud); - return ud_insn_asm(&ud); -} - -#else - -static void init_disassembler(void) -{ -} - -static const char *disassemble(unsigned char *insn, int len, uint64_t rip, - int cr0_pe, int eflags_vm, - int cs_d, int cs_l) -{ - static char out[15*3+1]; - int i; - - for (i = 0; i < len; ++i) - sprintf(out + i * 3, "%02x ", insn[i]); - out[len*3-1] = '\0'; - return out; -} - -#endif - - -#define VMX_EXIT_REASONS \ - _ER(EXCEPTION_NMI, 0) \ - _ER(EXTERNAL_INTERRUPT, 1) \ - _ER(TRIPLE_FAULT, 2) \ - _ER(PENDING_INTERRUPT, 7) \ - _ER(NMI_WINDOW, 8) \ - _ER(TASK_SWITCH, 9) \ - _ER(CPUID, 10) \ - _ER(HLT, 12) \ - _ER(INVD, 13) \ - _ER(INVLPG, 14) \ - _ER(RDPMC, 15) \ - _ER(RDTSC, 16) \ - _ER(VMCALL, 18) \ - _ER(VMCLEAR, 19) \ - _ER(VMLAUNCH, 20) \ - _ER(VMPTRLD, 21) \ - _ER(VMPTRST, 22) \ - _ER(VMREAD, 23) \ - _ER(VMRESUME, 24) \ - _ER(VMWRITE, 25) \ - _ER(VMOFF, 26) \ - _ER(VMON, 27) \ - _ER(CR_ACCESS, 28) \ - _ER(DR_ACCESS, 29) \ - _ER(IO_INSTRUCTION, 30) \ - _ER(MSR_READ, 31) \ - _ER(MSR_WRITE, 32) \ - _ER(MWAIT_INSTRUCTION, 36) \ - _ER(MONITOR_INSTRUCTION, 39) \ - _ER(PAUSE_INSTRUCTION, 40) \ - _ER(MCE_DURING_VMENTRY, 41) \ - _ER(TPR_BELOW_THRESHOLD, 43) \ - _ER(APIC_ACCESS, 44) \ - _ER(EOI_INDUCED, 45) \ - _ER(EPT_VIOLATION, 48) \ - _ER(EPT_MISCONFIG, 49) \ - _ER(INVEPT, 50) \ - _ER(PREEMPTION_TIMER, 52) \ - _ER(WBINVD, 54) \ - _ER(XSETBV, 55) \ - _ER(APIC_WRITE, 56) \ - _ER(INVPCID, 58) \ - _ER(PML_FULL, 62) \ - _ER(XSAVES, 63) \ - _ER(XRSTORS, 64) - -#define SVM_EXIT_REASONS \ - _ER(EXIT_READ_CR0, 0x000) \ - _ER(EXIT_READ_CR3, 0x003) \ - _ER(EXIT_READ_CR4, 0x004) \ - _ER(EXIT_READ_CR8, 0x008) \ - _ER(EXIT_WRITE_CR0, 0x010) \ - _ER(EXIT_WRITE_CR3, 0x013) \ - _ER(EXIT_WRITE_CR4, 0x014) \ - _ER(EXIT_WRITE_CR8, 0x018) \ - _ER(EXIT_READ_DR0, 0x020) \ - _ER(EXIT_READ_DR1, 0x021) \ - _ER(EXIT_READ_DR2, 0x022) \ - _ER(EXIT_READ_DR3, 0x023) \ - _ER(EXIT_READ_DR4, 0x024) \ - _ER(EXIT_READ_DR5, 0x025) \ - _ER(EXIT_READ_DR6, 0x026) \ - _ER(EXIT_READ_DR7, 0x027) \ - _ER(EXIT_WRITE_DR0, 0x030) \ - _ER(EXIT_WRITE_DR1, 0x031) \ - _ER(EXIT_WRITE_DR2, 0x032) \ - _ER(EXIT_WRITE_DR3, 0x033) \ - _ER(EXIT_WRITE_DR4, 0x034) \ - _ER(EXIT_WRITE_DR5, 0x035) \ - _ER(EXIT_WRITE_DR6, 0x036) \ - _ER(EXIT_WRITE_DR7, 0x037) \ - _ER(EXIT_EXCP_BASE, 0x040) \ - _ER(EXIT_INTR, 0x060) \ - _ER(EXIT_NMI, 0x061) \ - _ER(EXIT_SMI, 0x062) \ - _ER(EXIT_INIT, 0x063) \ - _ER(EXIT_VINTR, 0x064) \ - _ER(EXIT_CR0_SEL_WRITE, 0x065) \ - _ER(EXIT_IDTR_READ, 0x066) \ - _ER(EXIT_GDTR_READ, 0x067) \ - _ER(EXIT_LDTR_READ, 0x068) \ - _ER(EXIT_TR_READ, 0x069) \ - _ER(EXIT_IDTR_WRITE, 0x06a) \ - _ER(EXIT_GDTR_WRITE, 0x06b) \ - _ER(EXIT_LDTR_WRITE, 0x06c) \ - _ER(EXIT_TR_WRITE, 0x06d) \ - _ER(EXIT_RDTSC, 0x06e) \ - _ER(EXIT_RDPMC, 0x06f) \ - _ER(EXIT_PUSHF, 0x070) \ - _ER(EXIT_POPF, 0x071) \ - _ER(EXIT_CPUID, 0x072) \ - _ER(EXIT_RSM, 0x073) \ - _ER(EXIT_IRET, 0x074) \ - _ER(EXIT_SWINT, 0x075) \ - _ER(EXIT_INVD, 0x076) \ - _ER(EXIT_PAUSE, 0x077) \ - _ER(EXIT_HLT, 0x078) \ - _ER(EXIT_INVLPG, 0x079) \ - _ER(EXIT_INVLPGA, 0x07a) \ - _ER(EXIT_IOIO, 0x07b) \ - _ER(EXIT_MSR, 0x07c) \ - _ER(EXIT_TASK_SWITCH, 0x07d) \ - _ER(EXIT_FERR_FREEZE, 0x07e) \ - _ER(EXIT_SHUTDOWN, 0x07f) \ - _ER(EXIT_VMRUN, 0x080) \ - _ER(EXIT_VMMCALL, 0x081) \ - _ER(EXIT_VMLOAD, 0x082) \ - _ER(EXIT_VMSAVE, 0x083) \ - _ER(EXIT_STGI, 0x084) \ - _ER(EXIT_CLGI, 0x085) \ - _ER(EXIT_SKINIT, 0x086) \ - _ER(EXIT_RDTSCP, 0x087) \ - _ER(EXIT_ICEBP, 0x088) \ - _ER(EXIT_WBINVD, 0x089) \ - _ER(EXIT_MONITOR, 0x08a) \ - _ER(EXIT_MWAIT, 0x08b) \ - _ER(EXIT_MWAIT_COND, 0x08c) \ - _ER(EXIT_NPF, 0x400) \ - _ER(EXIT_ERR, -1) - -#define _ER(reason, val) { #reason, val }, -struct str_values { - const char *str; - int val; -}; - -static struct str_values vmx_exit_reasons[] = { - VMX_EXIT_REASONS - { NULL, -1} -}; - -static struct str_values svm_exit_reasons[] = { - SVM_EXIT_REASONS - { NULL, -1} -}; - -static struct isa_exit_reasons { - unsigned isa; - struct str_values *strings; -} isa_exit_reasons[] = { - { .isa = 1, .strings = vmx_exit_reasons }, - { .isa = 2, .strings = svm_exit_reasons }, - { } -}; - -static const char *find_exit_reason(unsigned isa, int val) -{ - struct str_values *strings = NULL; - int i; - - for (i = 0; isa_exit_reasons[i].strings; ++i) - if (isa_exit_reasons[i].isa == isa) { - strings = isa_exit_reasons[i].strings; - break; - } - if (!strings) - return "UNKNOWN-ISA"; - for (i = 0; strings[i].val >= 0; i++) - if (strings[i].val == val) - break; - - return strings[i].str; -} - -static int print_exit_reason(struct trace_seq *s, struct tep_record *record, - struct tep_event *event, const char *field) -{ - unsigned long long isa; - unsigned long long val; - const char *reason; - - if (tep_get_field_val(s, event, field, record, &val, 1) < 0) - return -1; - - if (tep_get_field_val(s, event, "isa", record, &isa, 0) < 0) - isa = 1; - - reason = find_exit_reason(isa, val); - if (reason) - trace_seq_printf(s, "reason %s", reason); - else - trace_seq_printf(s, "reason UNKNOWN (%llu)", val); - return 0; -} - -static int kvm_exit_handler(struct trace_seq *s, struct tep_record *record, - struct tep_event *event, void *context) -{ - unsigned long long info1 = 0, info2 = 0; - - if (print_exit_reason(s, record, event, "exit_reason") < 0) - return -1; - - tep_print_num_field(s, " rip 0x%lx", event, "guest_rip", record, 1); - - if (tep_get_field_val(s, event, "info1", record, &info1, 0) >= 0 - && tep_get_field_val(s, event, "info2", record, &info2, 0) >= 0) - trace_seq_printf(s, " info %llx %llx", info1, info2); - - return 0; -} - -#define KVM_EMUL_INSN_F_CR0_PE (1 << 0) -#define KVM_EMUL_INSN_F_EFL_VM (1 << 1) -#define KVM_EMUL_INSN_F_CS_D (1 << 2) -#define KVM_EMUL_INSN_F_CS_L (1 << 3) - -static int kvm_emulate_insn_handler(struct trace_seq *s, - struct tep_record *record, - struct tep_event *event, void *context) -{ - unsigned long long rip, csbase, len, flags, failed; - int llen; - uint8_t *insn; - const char *disasm; - - if (tep_get_field_val(s, event, "rip", record, &rip, 1) < 0) - return -1; - - if (tep_get_field_val(s, event, "csbase", record, &csbase, 1) < 0) - return -1; - - if (tep_get_field_val(s, event, "len", record, &len, 1) < 0) - return -1; - - if (tep_get_field_val(s, event, "flags", record, &flags, 1) < 0) - return -1; - - if (tep_get_field_val(s, event, "failed", record, &failed, 1) < 0) - return -1; - - insn = tep_get_field_raw(s, event, "insn", record, &llen, 1); - if (!insn) - return -1; - - disasm = disassemble(insn, len, rip, - flags & KVM_EMUL_INSN_F_CR0_PE, - flags & KVM_EMUL_INSN_F_EFL_VM, - flags & KVM_EMUL_INSN_F_CS_D, - flags & KVM_EMUL_INSN_F_CS_L); - - trace_seq_printf(s, "%llx:%llx: %s%s", csbase, rip, disasm, - failed ? " FAIL" : ""); - return 0; -} - - -static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct tep_record *record, - struct tep_event *event, void *context) -{ - if (print_exit_reason(s, record, event, "exit_code") < 0) - return -1; - - tep_print_num_field(s, " info1 %llx", event, "exit_info1", record, 1); - tep_print_num_field(s, " info2 %llx", event, "exit_info2", record, 1); - tep_print_num_field(s, " int_info %llx", event, "exit_int_info", record, 1); - tep_print_num_field(s, " int_info_err %llx", event, "exit_int_info_err", record, 1); - - return 0; -} - -static int kvm_nested_vmexit_handler(struct trace_seq *s, struct tep_record *record, - struct tep_event *event, void *context) -{ - tep_print_num_field(s, "rip %llx ", event, "rip", record, 1); - - return kvm_nested_vmexit_inject_handler(s, record, event, context); -} - -union kvm_mmu_page_role { - unsigned word; - struct { - unsigned level:4; - unsigned cr4_pae:1; - unsigned quadrant:2; - unsigned direct:1; - unsigned access:3; - unsigned invalid:1; - unsigned nxe:1; - unsigned cr0_wp:1; - unsigned smep_and_not_wp:1; - unsigned smap_and_not_wp:1; - unsigned pad_for_nice_hex_output:8; - unsigned smm:8; - }; -}; - -static int kvm_mmu_print_role(struct trace_seq *s, struct tep_record *record, - struct tep_event *event, void *context) -{ - unsigned long long val; - static const char *access_str[] = { - "---", "--x", "w--", "w-x", "-u-", "-ux", "wu-", "wux" - }; - union kvm_mmu_page_role role; - - if (tep_get_field_val(s, event, "role", record, &val, 1) < 0) - return -1; - - role.word = (int)val; - - /* - * We can only use the structure if file is of the same - * endianness. - */ - if (tep_is_file_bigendian(event->tep) == - tep_is_local_bigendian(event->tep)) { - - trace_seq_printf(s, "%u q%u%s %s%s %spae %snxe %swp%s%s%s", - role.level, - role.quadrant, - role.direct ? " direct" : "", - access_str[role.access], - role.invalid ? " invalid" : "", - role.cr4_pae ? "" : "!", - role.nxe ? "" : "!", - role.cr0_wp ? "" : "!", - role.smep_and_not_wp ? " smep" : "", - role.smap_and_not_wp ? " smap" : "", - role.smm ? " smm" : ""); - } else - trace_seq_printf(s, "WORD: %08x", role.word); - - tep_print_num_field(s, " root %u ", event, - "root_count", record, 1); - - if (tep_get_field_val(s, event, "unsync", record, &val, 1) < 0) - return -1; - - trace_seq_printf(s, "%s%c", val ? "unsync" : "sync", 0); - return 0; -} - -static int kvm_mmu_get_page_handler(struct trace_seq *s, - struct tep_record *record, - struct tep_event *event, void *context) -{ - unsigned long long val; - - if (tep_get_field_val(s, event, "created", record, &val, 1) < 0) - return -1; - - trace_seq_printf(s, "%s ", val ? "new" : "existing"); - - if (tep_get_field_val(s, event, "gfn", record, &val, 1) < 0) - return -1; - - trace_seq_printf(s, "sp gfn %llx ", val); - return kvm_mmu_print_role(s, record, event, context); -} - -#define PT_WRITABLE_SHIFT 1 -#define PT_WRITABLE_MASK (1ULL << PT_WRITABLE_SHIFT) - -static unsigned long long -process_is_writable_pte(struct trace_seq *s, unsigned long long *args) -{ - unsigned long pte = args[0]; - return pte & PT_WRITABLE_MASK; -} - -int TEP_PLUGIN_LOADER(struct tep_handle *tep) -{ - init_disassembler(); - - tep_register_event_handler(tep, -1, "kvm", "kvm_exit", - kvm_exit_handler, NULL); - - tep_register_event_handler(tep, -1, "kvm", "kvm_emulate_insn", - kvm_emulate_insn_handler, NULL); - - tep_register_event_handler(tep, -1, "kvm", "kvm_nested_vmexit", - kvm_nested_vmexit_handler, NULL); - - tep_register_event_handler(tep, -1, "kvm", "kvm_nested_vmexit_inject", - kvm_nested_vmexit_inject_handler, NULL); - - tep_register_event_handler(tep, -1, "kvmmmu", "kvm_mmu_get_page", - kvm_mmu_get_page_handler, NULL); - - tep_register_event_handler(tep, -1, "kvmmmu", "kvm_mmu_sync_page", - kvm_mmu_print_role, NULL); - - tep_register_event_handler(tep, -1, - "kvmmmu", "kvm_mmu_unsync_page", - kvm_mmu_print_role, NULL); - - tep_register_event_handler(tep, -1, "kvmmmu", "kvm_mmu_zap_page", - kvm_mmu_print_role, NULL); - - tep_register_event_handler(tep, -1, "kvmmmu", - "kvm_mmu_prepare_zap_page", kvm_mmu_print_role, - NULL); - - tep_register_print_function(tep, - process_is_writable_pte, - TEP_FUNC_ARG_INT, - "is_writable_pte", - TEP_FUNC_ARG_LONG, - TEP_FUNC_ARG_VOID); - return 0; -} - -void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) -{ - tep_unregister_event_handler(tep, -1, "kvm", "kvm_exit", - kvm_exit_handler, NULL); - - tep_unregister_event_handler(tep, -1, "kvm", "kvm_emulate_insn", - kvm_emulate_insn_handler, NULL); - - tep_unregister_event_handler(tep, -1, "kvm", "kvm_nested_vmexit", - kvm_nested_vmexit_handler, NULL); - - tep_unregister_event_handler(tep, -1, "kvm", "kvm_nested_vmexit_inject", - kvm_nested_vmexit_inject_handler, NULL); - - tep_unregister_event_handler(tep, -1, "kvmmmu", "kvm_mmu_get_page", - kvm_mmu_get_page_handler, NULL); - - tep_unregister_event_handler(tep, -1, "kvmmmu", "kvm_mmu_sync_page", - kvm_mmu_print_role, NULL); - - tep_unregister_event_handler(tep, -1, - "kvmmmu", "kvm_mmu_unsync_page", - kvm_mmu_print_role, NULL); - - tep_unregister_event_handler(tep, -1, "kvmmmu", "kvm_mmu_zap_page", - kvm_mmu_print_role, NULL); - - tep_unregister_event_handler(tep, -1, "kvmmmu", - "kvm_mmu_prepare_zap_page", kvm_mmu_print_role, - NULL); - - tep_unregister_print_function(tep, process_is_writable_pte, - "is_writable_pte"); -} diff --git a/tools/lib/traceevent/plugin_mac80211.c b/tools/lib/traceevent/plugin_mac80211.c deleted file mode 100644 index 884303c26b5c..000000000000 --- a/tools/lib/traceevent/plugin_mac80211.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2009 Johannes Berg - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License (not later!) - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include -#include -#include - -#include "event-parse.h" -#include "trace-seq.h" - -#define INDENT 65 - -static void print_string(struct trace_seq *s, struct tep_event *event, - const char *name, const void *data) -{ - struct tep_format_field *f = tep_find_field(event, name); - int offset; - int length; - - if (!f) { - trace_seq_printf(s, "NOTFOUND:%s", name); - return; - } - - offset = f->offset; - length = f->size; - - if (!strncmp(f->type, "__data_loc", 10)) { - unsigned long long v; - if (tep_read_number_field(f, data, &v)) { - trace_seq_printf(s, "invalid_data_loc"); - return; - } - offset = v & 0xffff; - length = v >> 16; - } - - trace_seq_printf(s, "%.*s", length, (char *)data + offset); -} - -#define SF(fn) tep_print_num_field(s, fn ":%d", event, fn, record, 0) -#define SFX(fn) tep_print_num_field(s, fn ":%#x", event, fn, record, 0) -#define SP() trace_seq_putc(s, ' ') - -static int drv_bss_info_changed(struct trace_seq *s, - struct tep_record *record, - struct tep_event *event, void *context) -{ - void *data = record->data; - - print_string(s, event, "wiphy_name", data); - trace_seq_printf(s, " vif:"); - print_string(s, event, "vif_name", data); - tep_print_num_field(s, "(%d)", event, "vif_type", record, 1); - - trace_seq_printf(s, "\n%*s", INDENT, ""); - SF("assoc"); SP(); - SF("aid"); SP(); - SF("cts"); SP(); - SF("shortpre"); SP(); - SF("shortslot"); SP(); - SF("dtimper"); SP(); - trace_seq_printf(s, "\n%*s", INDENT, ""); - SF("bcnint"); SP(); - SFX("assoc_cap"); SP(); - SFX("basic_rates"); SP(); - SF("enable_beacon"); - trace_seq_printf(s, "\n%*s", INDENT, ""); - SF("ht_operation_mode"); - - return 0; -} - -int TEP_PLUGIN_LOADER(struct tep_handle *tep) -{ - tep_register_event_handler(tep, -1, "mac80211", - "drv_bss_info_changed", - drv_bss_info_changed, NULL); - return 0; -} - -void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) -{ - tep_unregister_event_handler(tep, -1, "mac80211", - "drv_bss_info_changed", - drv_bss_info_changed, NULL); -} diff --git a/tools/lib/traceevent/plugin_sched_switch.c b/tools/lib/traceevent/plugin_sched_switch.c deleted file mode 100644 index 957389a0ff7a..000000000000 --- a/tools/lib/traceevent/plugin_sched_switch.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License (not later!) - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include -#include -#include - -#include "event-parse.h" -#include "trace-seq.h" - -static void write_state(struct trace_seq *s, int val) -{ - const char states[] = "SDTtZXxW"; - int found = 0; - int i; - - for (i = 0; i < (sizeof(states) - 1); i++) { - if (!(val & (1 << i))) - continue; - - if (found) - trace_seq_putc(s, '|'); - - found = 1; - trace_seq_putc(s, states[i]); - } - - if (!found) - trace_seq_putc(s, 'R'); -} - -static void write_and_save_comm(struct tep_format_field *field, - struct tep_record *record, - struct trace_seq *s, int pid) -{ - const char *comm; - int len; - - comm = (char *)(record->data + field->offset); - len = s->len; - trace_seq_printf(s, "%.*s", - field->size, comm); - - /* make sure the comm has a \0 at the end. */ - trace_seq_terminate(s); - comm = &s->buffer[len]; - - /* Help out the comm to ids. This will handle dups */ - tep_register_comm(field->event->tep, comm, pid); -} - -static int sched_wakeup_handler(struct trace_seq *s, - struct tep_record *record, - struct tep_event *event, void *context) -{ - struct tep_format_field *field; - unsigned long long val; - - if (tep_get_field_val(s, event, "pid", record, &val, 1)) - return trace_seq_putc(s, '!'); - - field = tep_find_any_field(event, "comm"); - if (field) { - write_and_save_comm(field, record, s, val); - trace_seq_putc(s, ':'); - } - trace_seq_printf(s, "%lld", val); - - if (tep_get_field_val(s, event, "prio", record, &val, 0) == 0) - trace_seq_printf(s, " [%lld]", val); - - if (tep_get_field_val(s, event, "success", record, &val, 1) == 0) - trace_seq_printf(s, " success=%lld", val); - - if (tep_get_field_val(s, event, "target_cpu", record, &val, 0) == 0) - trace_seq_printf(s, " CPU:%03llu", val); - - return 0; -} - -static int sched_switch_handler(struct trace_seq *s, - struct tep_record *record, - struct tep_event *event, void *context) -{ - struct tep_format_field *field; - unsigned long long val; - - if (tep_get_field_val(s, event, "prev_pid", record, &val, 1)) - return trace_seq_putc(s, '!'); - - field = tep_find_any_field(event, "prev_comm"); - if (field) { - write_and_save_comm(field, record, s, val); - trace_seq_putc(s, ':'); - } - trace_seq_printf(s, "%lld ", val); - - if (tep_get_field_val(s, event, "prev_prio", record, &val, 0) == 0) - trace_seq_printf(s, "[%d] ", (int) val); - - if (tep_get_field_val(s, event, "prev_state", record, &val, 0) == 0) - write_state(s, val); - - trace_seq_puts(s, " ==> "); - - if (tep_get_field_val(s, event, "next_pid", record, &val, 1)) - return trace_seq_putc(s, '!'); - - field = tep_find_any_field(event, "next_comm"); - if (field) { - write_and_save_comm(field, record, s, val); - trace_seq_putc(s, ':'); - } - trace_seq_printf(s, "%lld", val); - - if (tep_get_field_val(s, event, "next_prio", record, &val, 0) == 0) - trace_seq_printf(s, " [%d]", (int) val); - - return 0; -} - -int TEP_PLUGIN_LOADER(struct tep_handle *tep) -{ - tep_register_event_handler(tep, -1, "sched", "sched_switch", - sched_switch_handler, NULL); - - tep_register_event_handler(tep, -1, "sched", "sched_wakeup", - sched_wakeup_handler, NULL); - - tep_register_event_handler(tep, -1, "sched", "sched_wakeup_new", - sched_wakeup_handler, NULL); - return 0; -} - -void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) -{ - tep_unregister_event_handler(tep, -1, "sched", "sched_switch", - sched_switch_handler, NULL); - - tep_unregister_event_handler(tep, -1, "sched", "sched_wakeup", - sched_wakeup_handler, NULL); - - tep_unregister_event_handler(tep, -1, "sched", "sched_wakeup_new", - sched_wakeup_handler, NULL); -} diff --git a/tools/lib/traceevent/plugin_scsi.c b/tools/lib/traceevent/plugin_scsi.c deleted file mode 100644 index 5d0387a4b65a..000000000000 --- a/tools/lib/traceevent/plugin_scsi.c +++ /dev/null @@ -1,434 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include "event-parse.h" -#include "trace-seq.h" - -typedef unsigned long sector_t; -typedef uint64_t u64; -typedef unsigned int u32; - -/* - * SCSI opcodes - */ -#define TEST_UNIT_READY 0x00 -#define REZERO_UNIT 0x01 -#define REQUEST_SENSE 0x03 -#define FORMAT_UNIT 0x04 -#define READ_BLOCK_LIMITS 0x05 -#define REASSIGN_BLOCKS 0x07 -#define INITIALIZE_ELEMENT_STATUS 0x07 -#define READ_6 0x08 -#define WRITE_6 0x0a -#define SEEK_6 0x0b -#define READ_REVERSE 0x0f -#define WRITE_FILEMARKS 0x10 -#define SPACE 0x11 -#define INQUIRY 0x12 -#define RECOVER_BUFFERED_DATA 0x14 -#define MODE_SELECT 0x15 -#define RESERVE 0x16 -#define RELEASE 0x17 -#define COPY 0x18 -#define ERASE 0x19 -#define MODE_SENSE 0x1a -#define START_STOP 0x1b -#define RECEIVE_DIAGNOSTIC 0x1c -#define SEND_DIAGNOSTIC 0x1d -#define ALLOW_MEDIUM_REMOVAL 0x1e - -#define READ_FORMAT_CAPACITIES 0x23 -#define SET_WINDOW 0x24 -#define READ_CAPACITY 0x25 -#define READ_10 0x28 -#define WRITE_10 0x2a -#define SEEK_10 0x2b -#define POSITION_TO_ELEMENT 0x2b -#define WRITE_VERIFY 0x2e -#define VERIFY 0x2f -#define SEARCH_HIGH 0x30 -#define SEARCH_EQUAL 0x31 -#define SEARCH_LOW 0x32 -#define SET_LIMITS 0x33 -#define PRE_FETCH 0x34 -#define READ_POSITION 0x34 -#define SYNCHRONIZE_CACHE 0x35 -#define LOCK_UNLOCK_CACHE 0x36 -#define READ_DEFECT_DATA 0x37 -#define MEDIUM_SCAN 0x38 -#define COMPARE 0x39 -#define COPY_VERIFY 0x3a -#define WRITE_BUFFER 0x3b -#define READ_BUFFER 0x3c -#define UPDATE_BLOCK 0x3d -#define READ_LONG 0x3e -#define WRITE_LONG 0x3f -#define CHANGE_DEFINITION 0x40 -#define WRITE_SAME 0x41 -#define UNMAP 0x42 -#define READ_TOC 0x43 -#define READ_HEADER 0x44 -#define GET_EVENT_STATUS_NOTIFICATION 0x4a -#define LOG_SELECT 0x4c -#define LOG_SENSE 0x4d -#define XDWRITEREAD_10 0x53 -#define MODE_SELECT_10 0x55 -#define RESERVE_10 0x56 -#define RELEASE_10 0x57 -#define MODE_SENSE_10 0x5a -#define PERSISTENT_RESERVE_IN 0x5e -#define PERSISTENT_RESERVE_OUT 0x5f -#define VARIABLE_LENGTH_CMD 0x7f -#define REPORT_LUNS 0xa0 -#define SECURITY_PROTOCOL_IN 0xa2 -#define MAINTENANCE_IN 0xa3 -#define MAINTENANCE_OUT 0xa4 -#define MOVE_MEDIUM 0xa5 -#define EXCHANGE_MEDIUM 0xa6 -#define READ_12 0xa8 -#define SERVICE_ACTION_OUT_12 0xa9 -#define WRITE_12 0xaa -#define SERVICE_ACTION_IN_12 0xab -#define WRITE_VERIFY_12 0xae -#define VERIFY_12 0xaf -#define SEARCH_HIGH_12 0xb0 -#define SEARCH_EQUAL_12 0xb1 -#define SEARCH_LOW_12 0xb2 -#define SECURITY_PROTOCOL_OUT 0xb5 -#define READ_ELEMENT_STATUS 0xb8 -#define SEND_VOLUME_TAG 0xb6 -#define WRITE_LONG_2 0xea -#define EXTENDED_COPY 0x83 -#define RECEIVE_COPY_RESULTS 0x84 -#define ACCESS_CONTROL_IN 0x86 -#define ACCESS_CONTROL_OUT 0x87 -#define READ_16 0x88 -#define WRITE_16 0x8a -#define READ_ATTRIBUTE 0x8c -#define WRITE_ATTRIBUTE 0x8d -#define VERIFY_16 0x8f -#define SYNCHRONIZE_CACHE_16 0x91 -#define WRITE_SAME_16 0x93 -#define SERVICE_ACTION_BIDIRECTIONAL 0x9d -#define SERVICE_ACTION_IN_16 0x9e -#define SERVICE_ACTION_OUT_16 0x9f -/* values for service action in */ -#define SAI_READ_CAPACITY_16 0x10 -#define SAI_GET_LBA_STATUS 0x12 -/* values for VARIABLE_LENGTH_CMD service action codes - * see spc4r17 Section D.3.5, table D.7 and D.8 */ -#define VLC_SA_RECEIVE_CREDENTIAL 0x1800 -/* values for maintenance in */ -#define MI_REPORT_IDENTIFYING_INFORMATION 0x05 -#define MI_REPORT_TARGET_PGS 0x0a -#define MI_REPORT_ALIASES 0x0b -#define MI_REPORT_SUPPORTED_OPERATION_CODES 0x0c -#define MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS 0x0d -#define MI_REPORT_PRIORITY 0x0e -#define MI_REPORT_TIMESTAMP 0x0f -#define MI_MANAGEMENT_PROTOCOL_IN 0x10 -/* value for MI_REPORT_TARGET_PGS ext header */ -#define MI_EXT_HDR_PARAM_FMT 0x20 -/* values for maintenance out */ -#define MO_SET_IDENTIFYING_INFORMATION 0x06 -#define MO_SET_TARGET_PGS 0x0a -#define MO_CHANGE_ALIASES 0x0b -#define MO_SET_PRIORITY 0x0e -#define MO_SET_TIMESTAMP 0x0f -#define MO_MANAGEMENT_PROTOCOL_OUT 0x10 -/* values for variable length command */ -#define XDREAD_32 0x03 -#define XDWRITE_32 0x04 -#define XPWRITE_32 0x06 -#define XDWRITEREAD_32 0x07 -#define READ_32 0x09 -#define VERIFY_32 0x0a -#define WRITE_32 0x0b -#define WRITE_SAME_32 0x0d - -#define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f) -#define SERVICE_ACTION32(cdb) ((cdb[8] << 8) | cdb[9]) - -static const char * -scsi_trace_misc(struct trace_seq *, unsigned char *, int); - -static const char * -scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len) -{ - const char *ret = p->buffer + p->len; - sector_t lba = 0, txlen = 0; - - lba |= ((cdb[1] & 0x1F) << 16); - lba |= (cdb[2] << 8); - lba |= cdb[3]; - txlen = cdb[4]; - - trace_seq_printf(p, "lba=%llu txlen=%llu", - (unsigned long long)lba, (unsigned long long)txlen); - trace_seq_putc(p, 0); - return ret; -} - -static const char * -scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len) -{ - const char *ret = p->buffer + p->len; - sector_t lba = 0, txlen = 0; - - lba |= (cdb[2] << 24); - lba |= (cdb[3] << 16); - lba |= (cdb[4] << 8); - lba |= cdb[5]; - txlen |= (cdb[7] << 8); - txlen |= cdb[8]; - - trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", - (unsigned long long)lba, (unsigned long long)txlen, - cdb[1] >> 5); - - if (cdb[0] == WRITE_SAME) - trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1); - - trace_seq_putc(p, 0); - return ret; -} - -static const char * -scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len) -{ - const char *ret = p->buffer + p->len; - sector_t lba = 0, txlen = 0; - - lba |= (cdb[2] << 24); - lba |= (cdb[3] << 16); - lba |= (cdb[4] << 8); - lba |= cdb[5]; - txlen |= (cdb[6] << 24); - txlen |= (cdb[7] << 16); - txlen |= (cdb[8] << 8); - txlen |= cdb[9]; - - trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", - (unsigned long long)lba, (unsigned long long)txlen, - cdb[1] >> 5); - trace_seq_putc(p, 0); - return ret; -} - -static const char * -scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len) -{ - const char *ret = p->buffer + p->len; - sector_t lba = 0, txlen = 0; - - lba |= ((u64)cdb[2] << 56); - lba |= ((u64)cdb[3] << 48); - lba |= ((u64)cdb[4] << 40); - lba |= ((u64)cdb[5] << 32); - lba |= (cdb[6] << 24); - lba |= (cdb[7] << 16); - lba |= (cdb[8] << 8); - lba |= cdb[9]; - txlen |= (cdb[10] << 24); - txlen |= (cdb[11] << 16); - txlen |= (cdb[12] << 8); - txlen |= cdb[13]; - - trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", - (unsigned long long)lba, (unsigned long long)txlen, - cdb[1] >> 5); - - if (cdb[0] == WRITE_SAME_16) - trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1); - - trace_seq_putc(p, 0); - return ret; -} - -static const char * -scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len) -{ - const char *ret = p->buffer + p->len, *cmd; - sector_t lba = 0, txlen = 0; - u32 ei_lbrt = 0; - - switch (SERVICE_ACTION32(cdb)) { - case READ_32: - cmd = "READ"; - break; - case VERIFY_32: - cmd = "VERIFY"; - break; - case WRITE_32: - cmd = "WRITE"; - break; - case WRITE_SAME_32: - cmd = "WRITE_SAME"; - break; - default: - trace_seq_printf(p, "UNKNOWN"); - goto out; - } - - lba |= ((u64)cdb[12] << 56); - lba |= ((u64)cdb[13] << 48); - lba |= ((u64)cdb[14] << 40); - lba |= ((u64)cdb[15] << 32); - lba |= (cdb[16] << 24); - lba |= (cdb[17] << 16); - lba |= (cdb[18] << 8); - lba |= cdb[19]; - ei_lbrt |= (cdb[20] << 24); - ei_lbrt |= (cdb[21] << 16); - ei_lbrt |= (cdb[22] << 8); - ei_lbrt |= cdb[23]; - txlen |= (cdb[28] << 24); - txlen |= (cdb[29] << 16); - txlen |= (cdb[30] << 8); - txlen |= cdb[31]; - - trace_seq_printf(p, "%s_32 lba=%llu txlen=%llu protect=%u ei_lbrt=%u", - cmd, (unsigned long long)lba, - (unsigned long long)txlen, cdb[10] >> 5, ei_lbrt); - - if (SERVICE_ACTION32(cdb) == WRITE_SAME_32) - trace_seq_printf(p, " unmap=%u", cdb[10] >> 3 & 1); - -out: - trace_seq_putc(p, 0); - return ret; -} - -static const char * -scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len) -{ - const char *ret = p->buffer + p->len; - unsigned int regions = cdb[7] << 8 | cdb[8]; - - trace_seq_printf(p, "regions=%u", (regions - 8) / 16); - trace_seq_putc(p, 0); - return ret; -} - -static const char * -scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len) -{ - const char *ret = p->buffer + p->len, *cmd; - sector_t lba = 0; - u32 alloc_len = 0; - - switch (SERVICE_ACTION16(cdb)) { - case SAI_READ_CAPACITY_16: - cmd = "READ_CAPACITY_16"; - break; - case SAI_GET_LBA_STATUS: - cmd = "GET_LBA_STATUS"; - break; - default: - trace_seq_printf(p, "UNKNOWN"); - goto out; - } - - lba |= ((u64)cdb[2] << 56); - lba |= ((u64)cdb[3] << 48); - lba |= ((u64)cdb[4] << 40); - lba |= ((u64)cdb[5] << 32); - lba |= (cdb[6] << 24); - lba |= (cdb[7] << 16); - lba |= (cdb[8] << 8); - lba |= cdb[9]; - alloc_len |= (cdb[10] << 24); - alloc_len |= (cdb[11] << 16); - alloc_len |= (cdb[12] << 8); - alloc_len |= cdb[13]; - - trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd, - (unsigned long long)lba, alloc_len); - -out: - trace_seq_putc(p, 0); - return ret; -} - -static const char * -scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len) -{ - switch (SERVICE_ACTION32(cdb)) { - case READ_32: - case VERIFY_32: - case WRITE_32: - case WRITE_SAME_32: - return scsi_trace_rw32(p, cdb, len); - default: - return scsi_trace_misc(p, cdb, len); - } -} - -static const char * -scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len) -{ - const char *ret = p->buffer + p->len; - - trace_seq_printf(p, "-"); - trace_seq_putc(p, 0); - return ret; -} - -const char * -scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len) -{ - switch (cdb[0]) { - case READ_6: - case WRITE_6: - return scsi_trace_rw6(p, cdb, len); - case READ_10: - case VERIFY: - case WRITE_10: - case WRITE_SAME: - return scsi_trace_rw10(p, cdb, len); - case READ_12: - case VERIFY_12: - case WRITE_12: - return scsi_trace_rw12(p, cdb, len); - case READ_16: - case VERIFY_16: - case WRITE_16: - case WRITE_SAME_16: - return scsi_trace_rw16(p, cdb, len); - case UNMAP: - return scsi_trace_unmap(p, cdb, len); - case SERVICE_ACTION_IN_16: - return scsi_trace_service_action_in(p, cdb, len); - case VARIABLE_LENGTH_CMD: - return scsi_trace_varlen(p, cdb, len); - default: - return scsi_trace_misc(p, cdb, len); - } -} - -unsigned long long process_scsi_trace_parse_cdb(struct trace_seq *s, - unsigned long long *args) -{ - scsi_trace_parse_cdb(s, (unsigned char *) (unsigned long) args[1], args[2]); - return 0; -} - -int TEP_PLUGIN_LOADER(struct tep_handle *tep) -{ - tep_register_print_function(tep, - process_scsi_trace_parse_cdb, - TEP_FUNC_ARG_STRING, - "scsi_trace_parse_cdb", - TEP_FUNC_ARG_PTR, - TEP_FUNC_ARG_PTR, - TEP_FUNC_ARG_INT, - TEP_FUNC_ARG_VOID); - return 0; -} - -void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) -{ - tep_unregister_print_function(tep, process_scsi_trace_parse_cdb, - "scsi_trace_parse_cdb"); -} diff --git a/tools/lib/traceevent/plugin_xen.c b/tools/lib/traceevent/plugin_xen.c deleted file mode 100644 index 993b208d0323..000000000000 --- a/tools/lib/traceevent/plugin_xen.c +++ /dev/null @@ -1,138 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include "event-parse.h" -#include "trace-seq.h" - -#define __HYPERVISOR_set_trap_table 0 -#define __HYPERVISOR_mmu_update 1 -#define __HYPERVISOR_set_gdt 2 -#define __HYPERVISOR_stack_switch 3 -#define __HYPERVISOR_set_callbacks 4 -#define __HYPERVISOR_fpu_taskswitch 5 -#define __HYPERVISOR_sched_op_compat 6 -#define __HYPERVISOR_dom0_op 7 -#define __HYPERVISOR_set_debugreg 8 -#define __HYPERVISOR_get_debugreg 9 -#define __HYPERVISOR_update_descriptor 10 -#define __HYPERVISOR_memory_op 12 -#define __HYPERVISOR_multicall 13 -#define __HYPERVISOR_update_va_mapping 14 -#define __HYPERVISOR_set_timer_op 15 -#define __HYPERVISOR_event_channel_op_compat 16 -#define __HYPERVISOR_xen_version 17 -#define __HYPERVISOR_console_io 18 -#define __HYPERVISOR_physdev_op_compat 19 -#define __HYPERVISOR_grant_table_op 20 -#define __HYPERVISOR_vm_assist 21 -#define __HYPERVISOR_update_va_mapping_otherdomain 22 -#define __HYPERVISOR_iret 23 /* x86 only */ -#define __HYPERVISOR_vcpu_op 24 -#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */ -#define __HYPERVISOR_mmuext_op 26 -#define __HYPERVISOR_acm_op 27 -#define __HYPERVISOR_nmi_op 28 -#define __HYPERVISOR_sched_op 29 -#define __HYPERVISOR_callback_op 30 -#define __HYPERVISOR_xenoprof_op 31 -#define __HYPERVISOR_event_channel_op 32 -#define __HYPERVISOR_physdev_op 33 -#define __HYPERVISOR_hvm_op 34 -#define __HYPERVISOR_tmem_op 38 - -/* Architecture-specific hypercall definitions. */ -#define __HYPERVISOR_arch_0 48 -#define __HYPERVISOR_arch_1 49 -#define __HYPERVISOR_arch_2 50 -#define __HYPERVISOR_arch_3 51 -#define __HYPERVISOR_arch_4 52 -#define __HYPERVISOR_arch_5 53 -#define __HYPERVISOR_arch_6 54 -#define __HYPERVISOR_arch_7 55 - -#define N(x) [__HYPERVISOR_##x] = "("#x")" -static const char *xen_hypercall_names[] = { - N(set_trap_table), - N(mmu_update), - N(set_gdt), - N(stack_switch), - N(set_callbacks), - N(fpu_taskswitch), - N(sched_op_compat), - N(dom0_op), - N(set_debugreg), - N(get_debugreg), - N(update_descriptor), - N(memory_op), - N(multicall), - N(update_va_mapping), - N(set_timer_op), - N(event_channel_op_compat), - N(xen_version), - N(console_io), - N(physdev_op_compat), - N(grant_table_op), - N(vm_assist), - N(update_va_mapping_otherdomain), - N(iret), - N(vcpu_op), - N(set_segment_base), - N(mmuext_op), - N(acm_op), - N(nmi_op), - N(sched_op), - N(callback_op), - N(xenoprof_op), - N(event_channel_op), - N(physdev_op), - N(hvm_op), - -/* Architecture-specific hypercall definitions. */ - N(arch_0), - N(arch_1), - N(arch_2), - N(arch_3), - N(arch_4), - N(arch_5), - N(arch_6), - N(arch_7), -}; -#undef N - -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - -static const char *xen_hypercall_name(unsigned op) -{ - if (op < ARRAY_SIZE(xen_hypercall_names) && - xen_hypercall_names[op] != NULL) - return xen_hypercall_names[op]; - - return ""; -} - -unsigned long long process_xen_hypercall_name(struct trace_seq *s, - unsigned long long *args) -{ - unsigned int op = args[0]; - - trace_seq_printf(s, "%s", xen_hypercall_name(op)); - return 0; -} - -int TEP_PLUGIN_LOADER(struct tep_handle *tep) -{ - tep_register_print_function(tep, - process_xen_hypercall_name, - TEP_FUNC_ARG_STRING, - "xen_hypercall_name", - TEP_FUNC_ARG_INT, - TEP_FUNC_ARG_VOID); - return 0; -} - -void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) -{ - tep_unregister_print_function(tep, process_xen_hypercall_name, - "xen_hypercall_name"); -} diff --git a/tools/lib/traceevent/plugins/Build b/tools/lib/traceevent/plugins/Build new file mode 100644 index 000000000000..210d26910613 --- /dev/null +++ b/tools/lib/traceevent/plugins/Build @@ -0,0 +1,10 @@ +plugin_jbd2-y += plugin_jbd2.o +plugin_hrtimer-y += plugin_hrtimer.o +plugin_kmem-y += plugin_kmem.o +plugin_kvm-y += plugin_kvm.o +plugin_mac80211-y += plugin_mac80211.o +plugin_sched_switch-y += plugin_sched_switch.o +plugin_function-y += plugin_function.o +plugin_xen-y += plugin_xen.o +plugin_scsi-y += plugin_scsi.o +plugin_cfg80211-y += plugin_cfg80211.o diff --git a/tools/lib/traceevent/plugins/Makefile b/tools/lib/traceevent/plugins/Makefile new file mode 100644 index 000000000000..f440989fa55e --- /dev/null +++ b/tools/lib/traceevent/plugins/Makefile @@ -0,0 +1,222 @@ +# SPDX-License-Identifier: GPL-2.0 + +#MAKEFLAGS += --no-print-directory + + +# Makefiles suck: This macro sets a default value of $(2) for the +# variable named by $(1), unless the variable has been set by +# environment or command line. This is necessary for CC and AR +# because make sets default values, so the simpler ?= approach +# won't work as expected. +define allow-override + $(if $(or $(findstring environment,$(origin $(1))),\ + $(findstring command line,$(origin $(1)))),,\ + $(eval $(1) = $(2))) +endef + +# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix. +$(call allow-override,CC,$(CROSS_COMPILE)gcc) +$(call allow-override,AR,$(CROSS_COMPILE)ar) +$(call allow-override,NM,$(CROSS_COMPILE)nm) +$(call allow-override,PKG_CONFIG,pkg-config) + +EXT = -std=gnu99 +INSTALL = install + +# Use DESTDIR for installing into a different root directory. +# This is useful for building a package. The program will be +# installed in this directory as if it was the root directory. +# Then the build tool can move it later. +DESTDIR ?= +DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))' + +LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) +ifeq ($(LP64), 1) + libdir_relative = lib64 +else + libdir_relative = lib +endif + +prefix ?= /usr/local +libdir = $(prefix)/$(libdir_relative) + +set_plugin_dir := 1 + +# Set plugin_dir to preffered global plugin location +# If we install under $HOME directory we go under +# $(HOME)/.local/lib/traceevent/plugins +# +# We dont set PLUGIN_DIR in case we install under $HOME +# directory, because by default the code looks under: +# $(HOME)/.local/lib/traceevent/plugins by default. +# +ifeq ($(plugin_dir),) +ifeq ($(prefix),$(HOME)) +override plugin_dir = $(HOME)/.local/lib/traceevent/plugins +set_plugin_dir := 0 +else +override plugin_dir = $(libdir)/traceevent/plugins +endif +endif + +ifeq ($(set_plugin_dir),1) +PLUGIN_DIR = -DPLUGIN_DIR="$(plugin_dir)" +PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))' +endif + +include ../../../scripts/Makefile.include + +# copy a bit from Linux kbuild + +ifeq ("$(origin V)", "command line") + VERBOSE = $(V) +endif +ifndef VERBOSE + VERBOSE = 0 +endif + +ifeq ($(srctree),) +srctree := $(patsubst %/,%,$(dir $(CURDIR))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +#$(info Determined 'srctree' to be $(srctree)) +endif + +export prefix libdir src obj + +# Shell quotes +plugin_dir_SQ = $(subst ','\'',$(plugin_dir)) + +CONFIG_INCLUDES = +CONFIG_LIBS = +CONFIG_FLAGS = + +OBJ = $@ +N = + +INCLUDES = -I. -I.. -I $(srctree)/tools/include $(CONFIG_INCLUDES) + +# Set compile option CFLAGS +ifdef EXTRA_CFLAGS + CFLAGS := $(EXTRA_CFLAGS) +else + CFLAGS := -g -Wall +endif + +# Append required CFLAGS +override CFLAGS += -fPIC +override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) +override CFLAGS += $(udis86-flags) -D_GNU_SOURCE + +ifeq ($(VERBOSE),1) + Q = +else + Q = @ +endif + +# Disable command line variables (CFLAGS) override from top +# level Makefile (perf), otherwise build Makefile will get +# the same command line setup. +MAKEOVERRIDES= + +export srctree OUTPUT CC LD CFLAGS V + +build := -f $(srctree)/tools/build/Makefile.build dir=. obj + +DYNAMIC_LIST_FILE := $(OUTPUT)libtraceevent-dynamic-list + +PLUGINS = plugin_jbd2.so +PLUGINS += plugin_hrtimer.so +PLUGINS += plugin_kmem.so +PLUGINS += plugin_kvm.so +PLUGINS += plugin_mac80211.so +PLUGINS += plugin_sched_switch.so +PLUGINS += plugin_function.so +PLUGINS += plugin_xen.so +PLUGINS += plugin_scsi.so +PLUGINS += plugin_cfg80211.so + +PLUGINS := $(addprefix $(OUTPUT),$(PLUGINS)) +PLUGINS_IN := $(PLUGINS:.so=-in.o) + +plugins: $(PLUGINS) $(DYNAMIC_LIST_FILE) + +__plugin_obj = $(notdir $@) + plugin_obj = $(__plugin_obj:-in.o=) + +$(PLUGINS_IN): force + $(Q)$(MAKE) $(build)=$(plugin_obj) + +$(OUTPUT)libtraceevent-dynamic-list: $(PLUGINS) + $(QUIET_GEN)$(call do_generate_dynamic_list_file, $(PLUGINS), $@) + +$(OUTPUT)%.so: $(OUTPUT)%-in.o + $(QUIET_LINK)$(CC) $(CFLAGS) -shared $(LDFLAGS) -nostartfiles -o $@ $^ + +define update_dir + (echo $1 > $@.tmp; \ + if [ -r $@ ] && cmp -s $@ $@.tmp; then \ + rm -f $@.tmp; \ + else \ + echo ' UPDATE $@'; \ + mv -f $@.tmp $@; \ + fi); +endef + +tags: force + $(RM) tags + find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ + --regex-c++='/_PE\(([^,)]*).*/TEP_ERRNO__\1/' + +TAGS: force + $(RM) TAGS + find . -name '*.[ch]' | xargs etags \ + --regex='/_PE(\([^,)]*\).*/TEP_ERRNO__\1/' + +define do_install_mkdir + if [ ! -d '$(DESTDIR_SQ)$1' ]; then \ + $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$1'; \ + fi +endef + +define do_install + $(call do_install_mkdir,$2); \ + $(INSTALL) $(if $3,-m $3,) $1 '$(DESTDIR_SQ)$2' +endef + +define do_install_plugins + for plugin in $1; do \ + $(call do_install,$$plugin,$(plugin_dir_SQ)); \ + done +endef + +define do_generate_dynamic_list_file + symbol_type=`$(NM) -u -D $1 | awk 'NF>1 {print $$1}' | \ + xargs echo "U w W" | tr 'w ' 'W\n' | sort -u | xargs echo`;\ + if [ "$$symbol_type" = "U W" ];then \ + (echo '{'; \ + $(NM) -u -D $1 | awk 'NF>1 {print "\t"$$2";"}' | sort -u;\ + echo '};'; \ + ) > $2; \ + else \ + (echo Either missing one of [$1] or bad version of $(NM)) 1>&2;\ + fi +endef + +install: $(PLUGINS) + $(call QUIET_INSTALL, trace_plugins) \ + $(call do_install_plugins, $(PLUGINS)) + +clean: + $(call QUIET_CLEAN, trace_plugins) \ + $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d .*.cmd; \ + $(RM) $(OUTPUT)libtraceevent-dynamic-list \ + $(RM) TRACEEVENT-CFLAGS tags TAGS; + +PHONY += force plugins +force: + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable so we can use it in if_changed and friends. +.PHONY: $(PHONY) diff --git a/tools/lib/traceevent/plugins/plugin_cfg80211.c b/tools/lib/traceevent/plugins/plugin_cfg80211.c new file mode 100644 index 000000000000..3d43b56a6c98 --- /dev/null +++ b/tools/lib/traceevent/plugins/plugin_cfg80211.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include "event-parse.h" + +/* + * From glibc endian.h, for older systems where it is not present, e.g.: RHEL5, + * Fedora6. + */ +#ifndef le16toh +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define le16toh(x) (x) +# else +# define le16toh(x) __bswap_16 (x) +# endif +#endif + + +static unsigned long long +process___le16_to_cpup(struct trace_seq *s, unsigned long long *args) +{ + uint16_t *val = (uint16_t *) (unsigned long) args[0]; + return val ? (long long) le16toh(*val) : 0; +} + +int TEP_PLUGIN_LOADER(struct tep_handle *tep) +{ + tep_register_print_function(tep, + process___le16_to_cpup, + TEP_FUNC_ARG_INT, + "__le16_to_cpup", + TEP_FUNC_ARG_PTR, + TEP_FUNC_ARG_VOID); + return 0; +} + +void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) +{ + tep_unregister_print_function(tep, process___le16_to_cpup, + "__le16_to_cpup"); +} diff --git a/tools/lib/traceevent/plugins/plugin_function.c b/tools/lib/traceevent/plugins/plugin_function.c new file mode 100644 index 000000000000..7770fcb78e0f --- /dev/null +++ b/tools/lib/traceevent/plugins/plugin_function.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License (not later!) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "event-parse.h" +#include "event-utils.h" +#include "trace-seq.h" + +static struct func_stack { + int size; + char **stack; +} *fstack; + +static int cpus = -1; + +#define STK_BLK 10 + +struct tep_plugin_option plugin_options[] = +{ + { + .name = "parent", + .plugin_alias = "ftrace", + .description = + "Print parent of functions for function events", + }, + { + .name = "indent", + .plugin_alias = "ftrace", + .description = + "Try to show function call indents, based on parents", + .set = 1, + }, + { + .name = NULL, + } +}; + +static struct tep_plugin_option *ftrace_parent = &plugin_options[0]; +static struct tep_plugin_option *ftrace_indent = &plugin_options[1]; + +static void add_child(struct func_stack *stack, const char *child, int pos) +{ + int i; + + if (!child) + return; + + if (pos < stack->size) + free(stack->stack[pos]); + else { + char **ptr; + + ptr = realloc(stack->stack, sizeof(char *) * + (stack->size + STK_BLK)); + if (!ptr) { + warning("could not allocate plugin memory\n"); + return; + } + + stack->stack = ptr; + + for (i = stack->size; i < stack->size + STK_BLK; i++) + stack->stack[i] = NULL; + stack->size += STK_BLK; + } + + stack->stack[pos] = strdup(child); +} + +static int add_and_get_index(const char *parent, const char *child, int cpu) +{ + int i; + + if (cpu < 0) + return 0; + + if (cpu > cpus) { + struct func_stack *ptr; + + ptr = realloc(fstack, sizeof(*fstack) * (cpu + 1)); + if (!ptr) { + warning("could not allocate plugin memory\n"); + return 0; + } + + fstack = ptr; + + /* Account for holes in the cpu count */ + for (i = cpus + 1; i <= cpu; i++) + memset(&fstack[i], 0, sizeof(fstack[i])); + cpus = cpu; + } + + for (i = 0; i < fstack[cpu].size && fstack[cpu].stack[i]; i++) { + if (strcmp(parent, fstack[cpu].stack[i]) == 0) { + add_child(&fstack[cpu], child, i+1); + return i; + } + } + + /* Not found */ + add_child(&fstack[cpu], parent, 0); + add_child(&fstack[cpu], child, 1); + return 0; +} + +static int function_handler(struct trace_seq *s, struct tep_record *record, + struct tep_event *event, void *context) +{ + struct tep_handle *tep = event->tep; + unsigned long long function; + unsigned long long pfunction; + const char *func; + const char *parent; + int index = 0; + + if (tep_get_field_val(s, event, "ip", record, &function, 1)) + return trace_seq_putc(s, '!'); + + func = tep_find_function(tep, function); + + if (tep_get_field_val(s, event, "parent_ip", record, &pfunction, 1)) + return trace_seq_putc(s, '!'); + + parent = tep_find_function(tep, pfunction); + + if (parent && ftrace_indent->set) + index = add_and_get_index(parent, func, record->cpu); + + trace_seq_printf(s, "%*s", index*3, ""); + + if (func) + trace_seq_printf(s, "%s", func); + else + trace_seq_printf(s, "0x%llx", function); + + if (ftrace_parent->set) { + trace_seq_printf(s, " <-- "); + if (parent) + trace_seq_printf(s, "%s", parent); + else + trace_seq_printf(s, "0x%llx", pfunction); + } + + return 0; +} + +int TEP_PLUGIN_LOADER(struct tep_handle *tep) +{ + tep_register_event_handler(tep, -1, "ftrace", "function", + function_handler, NULL); + + tep_plugin_add_options("ftrace", plugin_options); + + return 0; +} + +void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) +{ + int i, x; + + tep_unregister_event_handler(tep, -1, "ftrace", "function", + function_handler, NULL); + + for (i = 0; i <= cpus; i++) { + for (x = 0; x < fstack[i].size && fstack[i].stack[x]; x++) + free(fstack[i].stack[x]); + free(fstack[i].stack); + } + + tep_plugin_remove_options(plugin_options); + + free(fstack); + fstack = NULL; + cpus = -1; +} diff --git a/tools/lib/traceevent/plugins/plugin_hrtimer.c b/tools/lib/traceevent/plugins/plugin_hrtimer.c new file mode 100644 index 000000000000..bb434e0ed03a --- /dev/null +++ b/tools/lib/traceevent/plugins/plugin_hrtimer.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2009 Red Hat Inc, Steven Rostedt + * Copyright (C) 2009 Johannes Berg + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License (not later!) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "event-parse.h" +#include "trace-seq.h" + +static int timer_expire_handler(struct trace_seq *s, + struct tep_record *record, + struct tep_event *event, void *context) +{ + trace_seq_printf(s, "hrtimer="); + + if (tep_print_num_field(s, "0x%llx", event, "timer", + record, 0) == -1) + tep_print_num_field(s, "0x%llx", event, "hrtimer", + record, 1); + + trace_seq_printf(s, " now="); + + tep_print_num_field(s, "%llu", event, "now", record, 1); + + tep_print_func_field(s, " function=%s", event, "function", + record, 0); + return 0; +} + +static int timer_start_handler(struct trace_seq *s, + struct tep_record *record, + struct tep_event *event, void *context) +{ + trace_seq_printf(s, "hrtimer="); + + if (tep_print_num_field(s, "0x%llx", event, "timer", + record, 0) == -1) + tep_print_num_field(s, "0x%llx", event, "hrtimer", + record, 1); + + tep_print_func_field(s, " function=%s", event, "function", + record, 0); + + trace_seq_printf(s, " expires="); + tep_print_num_field(s, "%llu", event, "expires", record, 1); + + trace_seq_printf(s, " softexpires="); + tep_print_num_field(s, "%llu", event, "softexpires", record, 1); + return 0; +} + +int TEP_PLUGIN_LOADER(struct tep_handle *tep) +{ + tep_register_event_handler(tep, -1, + "timer", "hrtimer_expire_entry", + timer_expire_handler, NULL); + + tep_register_event_handler(tep, -1, "timer", "hrtimer_start", + timer_start_handler, NULL); + return 0; +} + +void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) +{ + tep_unregister_event_handler(tep, -1, + "timer", "hrtimer_expire_entry", + timer_expire_handler, NULL); + + tep_unregister_event_handler(tep, -1, "timer", "hrtimer_start", + timer_start_handler, NULL); +} diff --git a/tools/lib/traceevent/plugins/plugin_jbd2.c b/tools/lib/traceevent/plugins/plugin_jbd2.c new file mode 100644 index 000000000000..04fc125f38cb --- /dev/null +++ b/tools/lib/traceevent/plugins/plugin_jbd2.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010 Red Hat Inc, Steven Rostedt + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License (not later!) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "event-parse.h" +#include "trace-seq.h" + +#define MINORBITS 20 +#define MINORMASK ((1U << MINORBITS) - 1) + +#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS)) +#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) + +static unsigned long long +process_jbd2_dev_to_name(struct trace_seq *s, unsigned long long *args) +{ + unsigned int dev = args[0]; + + trace_seq_printf(s, "%d:%d", MAJOR(dev), MINOR(dev)); + return 0; +} + +static unsigned long long +process_jiffies_to_msecs(struct trace_seq *s, unsigned long long *args) +{ + unsigned long long jiffies = args[0]; + + trace_seq_printf(s, "%lld", jiffies); + return jiffies; +} + +int TEP_PLUGIN_LOADER(struct tep_handle *tep) +{ + tep_register_print_function(tep, + process_jbd2_dev_to_name, + TEP_FUNC_ARG_STRING, + "jbd2_dev_to_name", + TEP_FUNC_ARG_INT, + TEP_FUNC_ARG_VOID); + + tep_register_print_function(tep, + process_jiffies_to_msecs, + TEP_FUNC_ARG_LONG, + "jiffies_to_msecs", + TEP_FUNC_ARG_LONG, + TEP_FUNC_ARG_VOID); + return 0; +} + +void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) +{ + tep_unregister_print_function(tep, process_jbd2_dev_to_name, + "jbd2_dev_to_name"); + + tep_unregister_print_function(tep, process_jiffies_to_msecs, + "jiffies_to_msecs"); +} diff --git a/tools/lib/traceevent/plugins/plugin_kmem.c b/tools/lib/traceevent/plugins/plugin_kmem.c new file mode 100644 index 000000000000..edaec5d962c3 --- /dev/null +++ b/tools/lib/traceevent/plugins/plugin_kmem.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2009 Red Hat Inc, Steven Rostedt + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License (not later!) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "event-parse.h" +#include "trace-seq.h" + +static int call_site_handler(struct trace_seq *s, struct tep_record *record, + struct tep_event *event, void *context) +{ + struct tep_format_field *field; + unsigned long long val, addr; + void *data = record->data; + const char *func; + + field = tep_find_field(event, "call_site"); + if (!field) + return 1; + + if (tep_read_number_field(field, data, &val)) + return 1; + + func = tep_find_function(event->tep, val); + if (!func) + return 1; + + addr = tep_find_function_address(event->tep, val); + + trace_seq_printf(s, "(%s+0x%x) ", func, (int)(val - addr)); + return 1; +} + +int TEP_PLUGIN_LOADER(struct tep_handle *tep) +{ + tep_register_event_handler(tep, -1, "kmem", "kfree", + call_site_handler, NULL); + + tep_register_event_handler(tep, -1, "kmem", "kmalloc", + call_site_handler, NULL); + + tep_register_event_handler(tep, -1, "kmem", "kmalloc_node", + call_site_handler, NULL); + + tep_register_event_handler(tep, -1, "kmem", "kmem_cache_alloc", + call_site_handler, NULL); + + tep_register_event_handler(tep, -1, "kmem", + "kmem_cache_alloc_node", + call_site_handler, NULL); + + tep_register_event_handler(tep, -1, "kmem", "kmem_cache_free", + call_site_handler, NULL); + return 0; +} + +void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) +{ + tep_unregister_event_handler(tep, -1, "kmem", "kfree", + call_site_handler, NULL); + + tep_unregister_event_handler(tep, -1, "kmem", "kmalloc", + call_site_handler, NULL); + + tep_unregister_event_handler(tep, -1, "kmem", "kmalloc_node", + call_site_handler, NULL); + + tep_unregister_event_handler(tep, -1, "kmem", "kmem_cache_alloc", + call_site_handler, NULL); + + tep_unregister_event_handler(tep, -1, "kmem", + "kmem_cache_alloc_node", + call_site_handler, NULL); + + tep_unregister_event_handler(tep, -1, "kmem", "kmem_cache_free", + call_site_handler, NULL); +} diff --git a/tools/lib/traceevent/plugins/plugin_kvm.c b/tools/lib/traceevent/plugins/plugin_kvm.c new file mode 100644 index 000000000000..c8e623065a7e --- /dev/null +++ b/tools/lib/traceevent/plugins/plugin_kvm.c @@ -0,0 +1,523 @@ +/* + * Copyright (C) 2009 Red Hat Inc, Steven Rostedt + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License (not later!) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include +#include + +#include "event-parse.h" +#include "trace-seq.h" + +#ifdef HAVE_UDIS86 + +#include + +static ud_t ud; + +static void init_disassembler(void) +{ + ud_init(&ud); + ud_set_syntax(&ud, UD_SYN_ATT); +} + +static const char *disassemble(unsigned char *insn, int len, uint64_t rip, + int cr0_pe, int eflags_vm, + int cs_d, int cs_l) +{ + int mode; + + if (!cr0_pe) + mode = 16; + else if (eflags_vm) + mode = 16; + else if (cs_l) + mode = 64; + else if (cs_d) + mode = 32; + else + mode = 16; + + ud_set_pc(&ud, rip); + ud_set_mode(&ud, mode); + ud_set_input_buffer(&ud, insn, len); + ud_disassemble(&ud); + return ud_insn_asm(&ud); +} + +#else + +static void init_disassembler(void) +{ +} + +static const char *disassemble(unsigned char *insn, int len, uint64_t rip, + int cr0_pe, int eflags_vm, + int cs_d, int cs_l) +{ + static char out[15*3+1]; + int i; + + for (i = 0; i < len; ++i) + sprintf(out + i * 3, "%02x ", insn[i]); + out[len*3-1] = '\0'; + return out; +} + +#endif + + +#define VMX_EXIT_REASONS \ + _ER(EXCEPTION_NMI, 0) \ + _ER(EXTERNAL_INTERRUPT, 1) \ + _ER(TRIPLE_FAULT, 2) \ + _ER(PENDING_INTERRUPT, 7) \ + _ER(NMI_WINDOW, 8) \ + _ER(TASK_SWITCH, 9) \ + _ER(CPUID, 10) \ + _ER(HLT, 12) \ + _ER(INVD, 13) \ + _ER(INVLPG, 14) \ + _ER(RDPMC, 15) \ + _ER(RDTSC, 16) \ + _ER(VMCALL, 18) \ + _ER(VMCLEAR, 19) \ + _ER(VMLAUNCH, 20) \ + _ER(VMPTRLD, 21) \ + _ER(VMPTRST, 22) \ + _ER(VMREAD, 23) \ + _ER(VMRESUME, 24) \ + _ER(VMWRITE, 25) \ + _ER(VMOFF, 26) \ + _ER(VMON, 27) \ + _ER(CR_ACCESS, 28) \ + _ER(DR_ACCESS, 29) \ + _ER(IO_INSTRUCTION, 30) \ + _ER(MSR_READ, 31) \ + _ER(MSR_WRITE, 32) \ + _ER(MWAIT_INSTRUCTION, 36) \ + _ER(MONITOR_INSTRUCTION, 39) \ + _ER(PAUSE_INSTRUCTION, 40) \ + _ER(MCE_DURING_VMENTRY, 41) \ + _ER(TPR_BELOW_THRESHOLD, 43) \ + _ER(APIC_ACCESS, 44) \ + _ER(EOI_INDUCED, 45) \ + _ER(EPT_VIOLATION, 48) \ + _ER(EPT_MISCONFIG, 49) \ + _ER(INVEPT, 50) \ + _ER(PREEMPTION_TIMER, 52) \ + _ER(WBINVD, 54) \ + _ER(XSETBV, 55) \ + _ER(APIC_WRITE, 56) \ + _ER(INVPCID, 58) \ + _ER(PML_FULL, 62) \ + _ER(XSAVES, 63) \ + _ER(XRSTORS, 64) + +#define SVM_EXIT_REASONS \ + _ER(EXIT_READ_CR0, 0x000) \ + _ER(EXIT_READ_CR3, 0x003) \ + _ER(EXIT_READ_CR4, 0x004) \ + _ER(EXIT_READ_CR8, 0x008) \ + _ER(EXIT_WRITE_CR0, 0x010) \ + _ER(EXIT_WRITE_CR3, 0x013) \ + _ER(EXIT_WRITE_CR4, 0x014) \ + _ER(EXIT_WRITE_CR8, 0x018) \ + _ER(EXIT_READ_DR0, 0x020) \ + _ER(EXIT_READ_DR1, 0x021) \ + _ER(EXIT_READ_DR2, 0x022) \ + _ER(EXIT_READ_DR3, 0x023) \ + _ER(EXIT_READ_DR4, 0x024) \ + _ER(EXIT_READ_DR5, 0x025) \ + _ER(EXIT_READ_DR6, 0x026) \ + _ER(EXIT_READ_DR7, 0x027) \ + _ER(EXIT_WRITE_DR0, 0x030) \ + _ER(EXIT_WRITE_DR1, 0x031) \ + _ER(EXIT_WRITE_DR2, 0x032) \ + _ER(EXIT_WRITE_DR3, 0x033) \ + _ER(EXIT_WRITE_DR4, 0x034) \ + _ER(EXIT_WRITE_DR5, 0x035) \ + _ER(EXIT_WRITE_DR6, 0x036) \ + _ER(EXIT_WRITE_DR7, 0x037) \ + _ER(EXIT_EXCP_BASE, 0x040) \ + _ER(EXIT_INTR, 0x060) \ + _ER(EXIT_NMI, 0x061) \ + _ER(EXIT_SMI, 0x062) \ + _ER(EXIT_INIT, 0x063) \ + _ER(EXIT_VINTR, 0x064) \ + _ER(EXIT_CR0_SEL_WRITE, 0x065) \ + _ER(EXIT_IDTR_READ, 0x066) \ + _ER(EXIT_GDTR_READ, 0x067) \ + _ER(EXIT_LDTR_READ, 0x068) \ + _ER(EXIT_TR_READ, 0x069) \ + _ER(EXIT_IDTR_WRITE, 0x06a) \ + _ER(EXIT_GDTR_WRITE, 0x06b) \ + _ER(EXIT_LDTR_WRITE, 0x06c) \ + _ER(EXIT_TR_WRITE, 0x06d) \ + _ER(EXIT_RDTSC, 0x06e) \ + _ER(EXIT_RDPMC, 0x06f) \ + _ER(EXIT_PUSHF, 0x070) \ + _ER(EXIT_POPF, 0x071) \ + _ER(EXIT_CPUID, 0x072) \ + _ER(EXIT_RSM, 0x073) \ + _ER(EXIT_IRET, 0x074) \ + _ER(EXIT_SWINT, 0x075) \ + _ER(EXIT_INVD, 0x076) \ + _ER(EXIT_PAUSE, 0x077) \ + _ER(EXIT_HLT, 0x078) \ + _ER(EXIT_INVLPG, 0x079) \ + _ER(EXIT_INVLPGA, 0x07a) \ + _ER(EXIT_IOIO, 0x07b) \ + _ER(EXIT_MSR, 0x07c) \ + _ER(EXIT_TASK_SWITCH, 0x07d) \ + _ER(EXIT_FERR_FREEZE, 0x07e) \ + _ER(EXIT_SHUTDOWN, 0x07f) \ + _ER(EXIT_VMRUN, 0x080) \ + _ER(EXIT_VMMCALL, 0x081) \ + _ER(EXIT_VMLOAD, 0x082) \ + _ER(EXIT_VMSAVE, 0x083) \ + _ER(EXIT_STGI, 0x084) \ + _ER(EXIT_CLGI, 0x085) \ + _ER(EXIT_SKINIT, 0x086) \ + _ER(EXIT_RDTSCP, 0x087) \ + _ER(EXIT_ICEBP, 0x088) \ + _ER(EXIT_WBINVD, 0x089) \ + _ER(EXIT_MONITOR, 0x08a) \ + _ER(EXIT_MWAIT, 0x08b) \ + _ER(EXIT_MWAIT_COND, 0x08c) \ + _ER(EXIT_NPF, 0x400) \ + _ER(EXIT_ERR, -1) + +#define _ER(reason, val) { #reason, val }, +struct str_values { + const char *str; + int val; +}; + +static struct str_values vmx_exit_reasons[] = { + VMX_EXIT_REASONS + { NULL, -1} +}; + +static struct str_values svm_exit_reasons[] = { + SVM_EXIT_REASONS + { NULL, -1} +}; + +static struct isa_exit_reasons { + unsigned isa; + struct str_values *strings; +} isa_exit_reasons[] = { + { .isa = 1, .strings = vmx_exit_reasons }, + { .isa = 2, .strings = svm_exit_reasons }, + { } +}; + +static const char *find_exit_reason(unsigned isa, int val) +{ + struct str_values *strings = NULL; + int i; + + for (i = 0; isa_exit_reasons[i].strings; ++i) + if (isa_exit_reasons[i].isa == isa) { + strings = isa_exit_reasons[i].strings; + break; + } + if (!strings) + return "UNKNOWN-ISA"; + for (i = 0; strings[i].val >= 0; i++) + if (strings[i].val == val) + break; + + return strings[i].str; +} + +static int print_exit_reason(struct trace_seq *s, struct tep_record *record, + struct tep_event *event, const char *field) +{ + unsigned long long isa; + unsigned long long val; + const char *reason; + + if (tep_get_field_val(s, event, field, record, &val, 1) < 0) + return -1; + + if (tep_get_field_val(s, event, "isa", record, &isa, 0) < 0) + isa = 1; + + reason = find_exit_reason(isa, val); + if (reason) + trace_seq_printf(s, "reason %s", reason); + else + trace_seq_printf(s, "reason UNKNOWN (%llu)", val); + return 0; +} + +static int kvm_exit_handler(struct trace_seq *s, struct tep_record *record, + struct tep_event *event, void *context) +{ + unsigned long long info1 = 0, info2 = 0; + + if (print_exit_reason(s, record, event, "exit_reason") < 0) + return -1; + + tep_print_num_field(s, " rip 0x%lx", event, "guest_rip", record, 1); + + if (tep_get_field_val(s, event, "info1", record, &info1, 0) >= 0 + && tep_get_field_val(s, event, "info2", record, &info2, 0) >= 0) + trace_seq_printf(s, " info %llx %llx", info1, info2); + + return 0; +} + +#define KVM_EMUL_INSN_F_CR0_PE (1 << 0) +#define KVM_EMUL_INSN_F_EFL_VM (1 << 1) +#define KVM_EMUL_INSN_F_CS_D (1 << 2) +#define KVM_EMUL_INSN_F_CS_L (1 << 3) + +static int kvm_emulate_insn_handler(struct trace_seq *s, + struct tep_record *record, + struct tep_event *event, void *context) +{ + unsigned long long rip, csbase, len, flags, failed; + int llen; + uint8_t *insn; + const char *disasm; + + if (tep_get_field_val(s, event, "rip", record, &rip, 1) < 0) + return -1; + + if (tep_get_field_val(s, event, "csbase", record, &csbase, 1) < 0) + return -1; + + if (tep_get_field_val(s, event, "len", record, &len, 1) < 0) + return -1; + + if (tep_get_field_val(s, event, "flags", record, &flags, 1) < 0) + return -1; + + if (tep_get_field_val(s, event, "failed", record, &failed, 1) < 0) + return -1; + + insn = tep_get_field_raw(s, event, "insn", record, &llen, 1); + if (!insn) + return -1; + + disasm = disassemble(insn, len, rip, + flags & KVM_EMUL_INSN_F_CR0_PE, + flags & KVM_EMUL_INSN_F_EFL_VM, + flags & KVM_EMUL_INSN_F_CS_D, + flags & KVM_EMUL_INSN_F_CS_L); + + trace_seq_printf(s, "%llx:%llx: %s%s", csbase, rip, disasm, + failed ? " FAIL" : ""); + return 0; +} + + +static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct tep_record *record, + struct tep_event *event, void *context) +{ + if (print_exit_reason(s, record, event, "exit_code") < 0) + return -1; + + tep_print_num_field(s, " info1 %llx", event, "exit_info1", record, 1); + tep_print_num_field(s, " info2 %llx", event, "exit_info2", record, 1); + tep_print_num_field(s, " int_info %llx", event, "exit_int_info", record, 1); + tep_print_num_field(s, " int_info_err %llx", event, "exit_int_info_err", record, 1); + + return 0; +} + +static int kvm_nested_vmexit_handler(struct trace_seq *s, struct tep_record *record, + struct tep_event *event, void *context) +{ + tep_print_num_field(s, "rip %llx ", event, "rip", record, 1); + + return kvm_nested_vmexit_inject_handler(s, record, event, context); +} + +union kvm_mmu_page_role { + unsigned word; + struct { + unsigned level:4; + unsigned cr4_pae:1; + unsigned quadrant:2; + unsigned direct:1; + unsigned access:3; + unsigned invalid:1; + unsigned nxe:1; + unsigned cr0_wp:1; + unsigned smep_and_not_wp:1; + unsigned smap_and_not_wp:1; + unsigned pad_for_nice_hex_output:8; + unsigned smm:8; + }; +}; + +static int kvm_mmu_print_role(struct trace_seq *s, struct tep_record *record, + struct tep_event *event, void *context) +{ + unsigned long long val; + static const char *access_str[] = { + "---", "--x", "w--", "w-x", "-u-", "-ux", "wu-", "wux" + }; + union kvm_mmu_page_role role; + + if (tep_get_field_val(s, event, "role", record, &val, 1) < 0) + return -1; + + role.word = (int)val; + + /* + * We can only use the structure if file is of the same + * endianness. + */ + if (tep_is_file_bigendian(event->tep) == + tep_is_local_bigendian(event->tep)) { + + trace_seq_printf(s, "%u q%u%s %s%s %spae %snxe %swp%s%s%s", + role.level, + role.quadrant, + role.direct ? " direct" : "", + access_str[role.access], + role.invalid ? " invalid" : "", + role.cr4_pae ? "" : "!", + role.nxe ? "" : "!", + role.cr0_wp ? "" : "!", + role.smep_and_not_wp ? " smep" : "", + role.smap_and_not_wp ? " smap" : "", + role.smm ? " smm" : ""); + } else + trace_seq_printf(s, "WORD: %08x", role.word); + + tep_print_num_field(s, " root %u ", event, + "root_count", record, 1); + + if (tep_get_field_val(s, event, "unsync", record, &val, 1) < 0) + return -1; + + trace_seq_printf(s, "%s%c", val ? "unsync" : "sync", 0); + return 0; +} + +static int kvm_mmu_get_page_handler(struct trace_seq *s, + struct tep_record *record, + struct tep_event *event, void *context) +{ + unsigned long long val; + + if (tep_get_field_val(s, event, "created", record, &val, 1) < 0) + return -1; + + trace_seq_printf(s, "%s ", val ? "new" : "existing"); + + if (tep_get_field_val(s, event, "gfn", record, &val, 1) < 0) + return -1; + + trace_seq_printf(s, "sp gfn %llx ", val); + return kvm_mmu_print_role(s, record, event, context); +} + +#define PT_WRITABLE_SHIFT 1 +#define PT_WRITABLE_MASK (1ULL << PT_WRITABLE_SHIFT) + +static unsigned long long +process_is_writable_pte(struct trace_seq *s, unsigned long long *args) +{ + unsigned long pte = args[0]; + return pte & PT_WRITABLE_MASK; +} + +int TEP_PLUGIN_LOADER(struct tep_handle *tep) +{ + init_disassembler(); + + tep_register_event_handler(tep, -1, "kvm", "kvm_exit", + kvm_exit_handler, NULL); + + tep_register_event_handler(tep, -1, "kvm", "kvm_emulate_insn", + kvm_emulate_insn_handler, NULL); + + tep_register_event_handler(tep, -1, "kvm", "kvm_nested_vmexit", + kvm_nested_vmexit_handler, NULL); + + tep_register_event_handler(tep, -1, "kvm", "kvm_nested_vmexit_inject", + kvm_nested_vmexit_inject_handler, NULL); + + tep_register_event_handler(tep, -1, "kvmmmu", "kvm_mmu_get_page", + kvm_mmu_get_page_handler, NULL); + + tep_register_event_handler(tep, -1, "kvmmmu", "kvm_mmu_sync_page", + kvm_mmu_print_role, NULL); + + tep_register_event_handler(tep, -1, + "kvmmmu", "kvm_mmu_unsync_page", + kvm_mmu_print_role, NULL); + + tep_register_event_handler(tep, -1, "kvmmmu", "kvm_mmu_zap_page", + kvm_mmu_print_role, NULL); + + tep_register_event_handler(tep, -1, "kvmmmu", + "kvm_mmu_prepare_zap_page", kvm_mmu_print_role, + NULL); + + tep_register_print_function(tep, + process_is_writable_pte, + TEP_FUNC_ARG_INT, + "is_writable_pte", + TEP_FUNC_ARG_LONG, + TEP_FUNC_ARG_VOID); + return 0; +} + +void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) +{ + tep_unregister_event_handler(tep, -1, "kvm", "kvm_exit", + kvm_exit_handler, NULL); + + tep_unregister_event_handler(tep, -1, "kvm", "kvm_emulate_insn", + kvm_emulate_insn_handler, NULL); + + tep_unregister_event_handler(tep, -1, "kvm", "kvm_nested_vmexit", + kvm_nested_vmexit_handler, NULL); + + tep_unregister_event_handler(tep, -1, "kvm", "kvm_nested_vmexit_inject", + kvm_nested_vmexit_inject_handler, NULL); + + tep_unregister_event_handler(tep, -1, "kvmmmu", "kvm_mmu_get_page", + kvm_mmu_get_page_handler, NULL); + + tep_unregister_event_handler(tep, -1, "kvmmmu", "kvm_mmu_sync_page", + kvm_mmu_print_role, NULL); + + tep_unregister_event_handler(tep, -1, + "kvmmmu", "kvm_mmu_unsync_page", + kvm_mmu_print_role, NULL); + + tep_unregister_event_handler(tep, -1, "kvmmmu", "kvm_mmu_zap_page", + kvm_mmu_print_role, NULL); + + tep_unregister_event_handler(tep, -1, "kvmmmu", + "kvm_mmu_prepare_zap_page", kvm_mmu_print_role, + NULL); + + tep_unregister_print_function(tep, process_is_writable_pte, + "is_writable_pte"); +} diff --git a/tools/lib/traceevent/plugins/plugin_mac80211.c b/tools/lib/traceevent/plugins/plugin_mac80211.c new file mode 100644 index 000000000000..884303c26b5c --- /dev/null +++ b/tools/lib/traceevent/plugins/plugin_mac80211.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2009 Johannes Berg + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License (not later!) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "event-parse.h" +#include "trace-seq.h" + +#define INDENT 65 + +static void print_string(struct trace_seq *s, struct tep_event *event, + const char *name, const void *data) +{ + struct tep_format_field *f = tep_find_field(event, name); + int offset; + int length; + + if (!f) { + trace_seq_printf(s, "NOTFOUND:%s", name); + return; + } + + offset = f->offset; + length = f->size; + + if (!strncmp(f->type, "__data_loc", 10)) { + unsigned long long v; + if (tep_read_number_field(f, data, &v)) { + trace_seq_printf(s, "invalid_data_loc"); + return; + } + offset = v & 0xffff; + length = v >> 16; + } + + trace_seq_printf(s, "%.*s", length, (char *)data + offset); +} + +#define SF(fn) tep_print_num_field(s, fn ":%d", event, fn, record, 0) +#define SFX(fn) tep_print_num_field(s, fn ":%#x", event, fn, record, 0) +#define SP() trace_seq_putc(s, ' ') + +static int drv_bss_info_changed(struct trace_seq *s, + struct tep_record *record, + struct tep_event *event, void *context) +{ + void *data = record->data; + + print_string(s, event, "wiphy_name", data); + trace_seq_printf(s, " vif:"); + print_string(s, event, "vif_name", data); + tep_print_num_field(s, "(%d)", event, "vif_type", record, 1); + + trace_seq_printf(s, "\n%*s", INDENT, ""); + SF("assoc"); SP(); + SF("aid"); SP(); + SF("cts"); SP(); + SF("shortpre"); SP(); + SF("shortslot"); SP(); + SF("dtimper"); SP(); + trace_seq_printf(s, "\n%*s", INDENT, ""); + SF("bcnint"); SP(); + SFX("assoc_cap"); SP(); + SFX("basic_rates"); SP(); + SF("enable_beacon"); + trace_seq_printf(s, "\n%*s", INDENT, ""); + SF("ht_operation_mode"); + + return 0; +} + +int TEP_PLUGIN_LOADER(struct tep_handle *tep) +{ + tep_register_event_handler(tep, -1, "mac80211", + "drv_bss_info_changed", + drv_bss_info_changed, NULL); + return 0; +} + +void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) +{ + tep_unregister_event_handler(tep, -1, "mac80211", + "drv_bss_info_changed", + drv_bss_info_changed, NULL); +} diff --git a/tools/lib/traceevent/plugins/plugin_sched_switch.c b/tools/lib/traceevent/plugins/plugin_sched_switch.c new file mode 100644 index 000000000000..957389a0ff7a --- /dev/null +++ b/tools/lib/traceevent/plugins/plugin_sched_switch.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License (not later!) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "event-parse.h" +#include "trace-seq.h" + +static void write_state(struct trace_seq *s, int val) +{ + const char states[] = "SDTtZXxW"; + int found = 0; + int i; + + for (i = 0; i < (sizeof(states) - 1); i++) { + if (!(val & (1 << i))) + continue; + + if (found) + trace_seq_putc(s, '|'); + + found = 1; + trace_seq_putc(s, states[i]); + } + + if (!found) + trace_seq_putc(s, 'R'); +} + +static void write_and_save_comm(struct tep_format_field *field, + struct tep_record *record, + struct trace_seq *s, int pid) +{ + const char *comm; + int len; + + comm = (char *)(record->data + field->offset); + len = s->len; + trace_seq_printf(s, "%.*s", + field->size, comm); + + /* make sure the comm has a \0 at the end. */ + trace_seq_terminate(s); + comm = &s->buffer[len]; + + /* Help out the comm to ids. This will handle dups */ + tep_register_comm(field->event->tep, comm, pid); +} + +static int sched_wakeup_handler(struct trace_seq *s, + struct tep_record *record, + struct tep_event *event, void *context) +{ + struct tep_format_field *field; + unsigned long long val; + + if (tep_get_field_val(s, event, "pid", record, &val, 1)) + return trace_seq_putc(s, '!'); + + field = tep_find_any_field(event, "comm"); + if (field) { + write_and_save_comm(field, record, s, val); + trace_seq_putc(s, ':'); + } + trace_seq_printf(s, "%lld", val); + + if (tep_get_field_val(s, event, "prio", record, &val, 0) == 0) + trace_seq_printf(s, " [%lld]", val); + + if (tep_get_field_val(s, event, "success", record, &val, 1) == 0) + trace_seq_printf(s, " success=%lld", val); + + if (tep_get_field_val(s, event, "target_cpu", record, &val, 0) == 0) + trace_seq_printf(s, " CPU:%03llu", val); + + return 0; +} + +static int sched_switch_handler(struct trace_seq *s, + struct tep_record *record, + struct tep_event *event, void *context) +{ + struct tep_format_field *field; + unsigned long long val; + + if (tep_get_field_val(s, event, "prev_pid", record, &val, 1)) + return trace_seq_putc(s, '!'); + + field = tep_find_any_field(event, "prev_comm"); + if (field) { + write_and_save_comm(field, record, s, val); + trace_seq_putc(s, ':'); + } + trace_seq_printf(s, "%lld ", val); + + if (tep_get_field_val(s, event, "prev_prio", record, &val, 0) == 0) + trace_seq_printf(s, "[%d] ", (int) val); + + if (tep_get_field_val(s, event, "prev_state", record, &val, 0) == 0) + write_state(s, val); + + trace_seq_puts(s, " ==> "); + + if (tep_get_field_val(s, event, "next_pid", record, &val, 1)) + return trace_seq_putc(s, '!'); + + field = tep_find_any_field(event, "next_comm"); + if (field) { + write_and_save_comm(field, record, s, val); + trace_seq_putc(s, ':'); + } + trace_seq_printf(s, "%lld", val); + + if (tep_get_field_val(s, event, "next_prio", record, &val, 0) == 0) + trace_seq_printf(s, " [%d]", (int) val); + + return 0; +} + +int TEP_PLUGIN_LOADER(struct tep_handle *tep) +{ + tep_register_event_handler(tep, -1, "sched", "sched_switch", + sched_switch_handler, NULL); + + tep_register_event_handler(tep, -1, "sched", "sched_wakeup", + sched_wakeup_handler, NULL); + + tep_register_event_handler(tep, -1, "sched", "sched_wakeup_new", + sched_wakeup_handler, NULL); + return 0; +} + +void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) +{ + tep_unregister_event_handler(tep, -1, "sched", "sched_switch", + sched_switch_handler, NULL); + + tep_unregister_event_handler(tep, -1, "sched", "sched_wakeup", + sched_wakeup_handler, NULL); + + tep_unregister_event_handler(tep, -1, "sched", "sched_wakeup_new", + sched_wakeup_handler, NULL); +} diff --git a/tools/lib/traceevent/plugins/plugin_scsi.c b/tools/lib/traceevent/plugins/plugin_scsi.c new file mode 100644 index 000000000000..5d0387a4b65a --- /dev/null +++ b/tools/lib/traceevent/plugins/plugin_scsi.c @@ -0,0 +1,434 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include "event-parse.h" +#include "trace-seq.h" + +typedef unsigned long sector_t; +typedef uint64_t u64; +typedef unsigned int u32; + +/* + * SCSI opcodes + */ +#define TEST_UNIT_READY 0x00 +#define REZERO_UNIT 0x01 +#define REQUEST_SENSE 0x03 +#define FORMAT_UNIT 0x04 +#define READ_BLOCK_LIMITS 0x05 +#define REASSIGN_BLOCKS 0x07 +#define INITIALIZE_ELEMENT_STATUS 0x07 +#define READ_6 0x08 +#define WRITE_6 0x0a +#define SEEK_6 0x0b +#define READ_REVERSE 0x0f +#define WRITE_FILEMARKS 0x10 +#define SPACE 0x11 +#define INQUIRY 0x12 +#define RECOVER_BUFFERED_DATA 0x14 +#define MODE_SELECT 0x15 +#define RESERVE 0x16 +#define RELEASE 0x17 +#define COPY 0x18 +#define ERASE 0x19 +#define MODE_SENSE 0x1a +#define START_STOP 0x1b +#define RECEIVE_DIAGNOSTIC 0x1c +#define SEND_DIAGNOSTIC 0x1d +#define ALLOW_MEDIUM_REMOVAL 0x1e + +#define READ_FORMAT_CAPACITIES 0x23 +#define SET_WINDOW 0x24 +#define READ_CAPACITY 0x25 +#define READ_10 0x28 +#define WRITE_10 0x2a +#define SEEK_10 0x2b +#define POSITION_TO_ELEMENT 0x2b +#define WRITE_VERIFY 0x2e +#define VERIFY 0x2f +#define SEARCH_HIGH 0x30 +#define SEARCH_EQUAL 0x31 +#define SEARCH_LOW 0x32 +#define SET_LIMITS 0x33 +#define PRE_FETCH 0x34 +#define READ_POSITION 0x34 +#define SYNCHRONIZE_CACHE 0x35 +#define LOCK_UNLOCK_CACHE 0x36 +#define READ_DEFECT_DATA 0x37 +#define MEDIUM_SCAN 0x38 +#define COMPARE 0x39 +#define COPY_VERIFY 0x3a +#define WRITE_BUFFER 0x3b +#define READ_BUFFER 0x3c +#define UPDATE_BLOCK 0x3d +#define READ_LONG 0x3e +#define WRITE_LONG 0x3f +#define CHANGE_DEFINITION 0x40 +#define WRITE_SAME 0x41 +#define UNMAP 0x42 +#define READ_TOC 0x43 +#define READ_HEADER 0x44 +#define GET_EVENT_STATUS_NOTIFICATION 0x4a +#define LOG_SELECT 0x4c +#define LOG_SENSE 0x4d +#define XDWRITEREAD_10 0x53 +#define MODE_SELECT_10 0x55 +#define RESERVE_10 0x56 +#define RELEASE_10 0x57 +#define MODE_SENSE_10 0x5a +#define PERSISTENT_RESERVE_IN 0x5e +#define PERSISTENT_RESERVE_OUT 0x5f +#define VARIABLE_LENGTH_CMD 0x7f +#define REPORT_LUNS 0xa0 +#define SECURITY_PROTOCOL_IN 0xa2 +#define MAINTENANCE_IN 0xa3 +#define MAINTENANCE_OUT 0xa4 +#define MOVE_MEDIUM 0xa5 +#define EXCHANGE_MEDIUM 0xa6 +#define READ_12 0xa8 +#define SERVICE_ACTION_OUT_12 0xa9 +#define WRITE_12 0xaa +#define SERVICE_ACTION_IN_12 0xab +#define WRITE_VERIFY_12 0xae +#define VERIFY_12 0xaf +#define SEARCH_HIGH_12 0xb0 +#define SEARCH_EQUAL_12 0xb1 +#define SEARCH_LOW_12 0xb2 +#define SECURITY_PROTOCOL_OUT 0xb5 +#define READ_ELEMENT_STATUS 0xb8 +#define SEND_VOLUME_TAG 0xb6 +#define WRITE_LONG_2 0xea +#define EXTENDED_COPY 0x83 +#define RECEIVE_COPY_RESULTS 0x84 +#define ACCESS_CONTROL_IN 0x86 +#define ACCESS_CONTROL_OUT 0x87 +#define READ_16 0x88 +#define WRITE_16 0x8a +#define READ_ATTRIBUTE 0x8c +#define WRITE_ATTRIBUTE 0x8d +#define VERIFY_16 0x8f +#define SYNCHRONIZE_CACHE_16 0x91 +#define WRITE_SAME_16 0x93 +#define SERVICE_ACTION_BIDIRECTIONAL 0x9d +#define SERVICE_ACTION_IN_16 0x9e +#define SERVICE_ACTION_OUT_16 0x9f +/* values for service action in */ +#define SAI_READ_CAPACITY_16 0x10 +#define SAI_GET_LBA_STATUS 0x12 +/* values for VARIABLE_LENGTH_CMD service action codes + * see spc4r17 Section D.3.5, table D.7 and D.8 */ +#define VLC_SA_RECEIVE_CREDENTIAL 0x1800 +/* values for maintenance in */ +#define MI_REPORT_IDENTIFYING_INFORMATION 0x05 +#define MI_REPORT_TARGET_PGS 0x0a +#define MI_REPORT_ALIASES 0x0b +#define MI_REPORT_SUPPORTED_OPERATION_CODES 0x0c +#define MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS 0x0d +#define MI_REPORT_PRIORITY 0x0e +#define MI_REPORT_TIMESTAMP 0x0f +#define MI_MANAGEMENT_PROTOCOL_IN 0x10 +/* value for MI_REPORT_TARGET_PGS ext header */ +#define MI_EXT_HDR_PARAM_FMT 0x20 +/* values for maintenance out */ +#define MO_SET_IDENTIFYING_INFORMATION 0x06 +#define MO_SET_TARGET_PGS 0x0a +#define MO_CHANGE_ALIASES 0x0b +#define MO_SET_PRIORITY 0x0e +#define MO_SET_TIMESTAMP 0x0f +#define MO_MANAGEMENT_PROTOCOL_OUT 0x10 +/* values for variable length command */ +#define XDREAD_32 0x03 +#define XDWRITE_32 0x04 +#define XPWRITE_32 0x06 +#define XDWRITEREAD_32 0x07 +#define READ_32 0x09 +#define VERIFY_32 0x0a +#define WRITE_32 0x0b +#define WRITE_SAME_32 0x0d + +#define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f) +#define SERVICE_ACTION32(cdb) ((cdb[8] << 8) | cdb[9]) + +static const char * +scsi_trace_misc(struct trace_seq *, unsigned char *, int); + +static const char * +scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len; + sector_t lba = 0, txlen = 0; + + lba |= ((cdb[1] & 0x1F) << 16); + lba |= (cdb[2] << 8); + lba |= cdb[3]; + txlen = cdb[4]; + + trace_seq_printf(p, "lba=%llu txlen=%llu", + (unsigned long long)lba, (unsigned long long)txlen); + trace_seq_putc(p, 0); + return ret; +} + +static const char * +scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len; + sector_t lba = 0, txlen = 0; + + lba |= (cdb[2] << 24); + lba |= (cdb[3] << 16); + lba |= (cdb[4] << 8); + lba |= cdb[5]; + txlen |= (cdb[7] << 8); + txlen |= cdb[8]; + + trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", + (unsigned long long)lba, (unsigned long long)txlen, + cdb[1] >> 5); + + if (cdb[0] == WRITE_SAME) + trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1); + + trace_seq_putc(p, 0); + return ret; +} + +static const char * +scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len; + sector_t lba = 0, txlen = 0; + + lba |= (cdb[2] << 24); + lba |= (cdb[3] << 16); + lba |= (cdb[4] << 8); + lba |= cdb[5]; + txlen |= (cdb[6] << 24); + txlen |= (cdb[7] << 16); + txlen |= (cdb[8] << 8); + txlen |= cdb[9]; + + trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", + (unsigned long long)lba, (unsigned long long)txlen, + cdb[1] >> 5); + trace_seq_putc(p, 0); + return ret; +} + +static const char * +scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len; + sector_t lba = 0, txlen = 0; + + lba |= ((u64)cdb[2] << 56); + lba |= ((u64)cdb[3] << 48); + lba |= ((u64)cdb[4] << 40); + lba |= ((u64)cdb[5] << 32); + lba |= (cdb[6] << 24); + lba |= (cdb[7] << 16); + lba |= (cdb[8] << 8); + lba |= cdb[9]; + txlen |= (cdb[10] << 24); + txlen |= (cdb[11] << 16); + txlen |= (cdb[12] << 8); + txlen |= cdb[13]; + + trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", + (unsigned long long)lba, (unsigned long long)txlen, + cdb[1] >> 5); + + if (cdb[0] == WRITE_SAME_16) + trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1); + + trace_seq_putc(p, 0); + return ret; +} + +static const char * +scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len, *cmd; + sector_t lba = 0, txlen = 0; + u32 ei_lbrt = 0; + + switch (SERVICE_ACTION32(cdb)) { + case READ_32: + cmd = "READ"; + break; + case VERIFY_32: + cmd = "VERIFY"; + break; + case WRITE_32: + cmd = "WRITE"; + break; + case WRITE_SAME_32: + cmd = "WRITE_SAME"; + break; + default: + trace_seq_printf(p, "UNKNOWN"); + goto out; + } + + lba |= ((u64)cdb[12] << 56); + lba |= ((u64)cdb[13] << 48); + lba |= ((u64)cdb[14] << 40); + lba |= ((u64)cdb[15] << 32); + lba |= (cdb[16] << 24); + lba |= (cdb[17] << 16); + lba |= (cdb[18] << 8); + lba |= cdb[19]; + ei_lbrt |= (cdb[20] << 24); + ei_lbrt |= (cdb[21] << 16); + ei_lbrt |= (cdb[22] << 8); + ei_lbrt |= cdb[23]; + txlen |= (cdb[28] << 24); + txlen |= (cdb[29] << 16); + txlen |= (cdb[30] << 8); + txlen |= cdb[31]; + + trace_seq_printf(p, "%s_32 lba=%llu txlen=%llu protect=%u ei_lbrt=%u", + cmd, (unsigned long long)lba, + (unsigned long long)txlen, cdb[10] >> 5, ei_lbrt); + + if (SERVICE_ACTION32(cdb) == WRITE_SAME_32) + trace_seq_printf(p, " unmap=%u", cdb[10] >> 3 & 1); + +out: + trace_seq_putc(p, 0); + return ret; +} + +static const char * +scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len; + unsigned int regions = cdb[7] << 8 | cdb[8]; + + trace_seq_printf(p, "regions=%u", (regions - 8) / 16); + trace_seq_putc(p, 0); + return ret; +} + +static const char * +scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len, *cmd; + sector_t lba = 0; + u32 alloc_len = 0; + + switch (SERVICE_ACTION16(cdb)) { + case SAI_READ_CAPACITY_16: + cmd = "READ_CAPACITY_16"; + break; + case SAI_GET_LBA_STATUS: + cmd = "GET_LBA_STATUS"; + break; + default: + trace_seq_printf(p, "UNKNOWN"); + goto out; + } + + lba |= ((u64)cdb[2] << 56); + lba |= ((u64)cdb[3] << 48); + lba |= ((u64)cdb[4] << 40); + lba |= ((u64)cdb[5] << 32); + lba |= (cdb[6] << 24); + lba |= (cdb[7] << 16); + lba |= (cdb[8] << 8); + lba |= cdb[9]; + alloc_len |= (cdb[10] << 24); + alloc_len |= (cdb[11] << 16); + alloc_len |= (cdb[12] << 8); + alloc_len |= cdb[13]; + + trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd, + (unsigned long long)lba, alloc_len); + +out: + trace_seq_putc(p, 0); + return ret; +} + +static const char * +scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len) +{ + switch (SERVICE_ACTION32(cdb)) { + case READ_32: + case VERIFY_32: + case WRITE_32: + case WRITE_SAME_32: + return scsi_trace_rw32(p, cdb, len); + default: + return scsi_trace_misc(p, cdb, len); + } +} + +static const char * +scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len; + + trace_seq_printf(p, "-"); + trace_seq_putc(p, 0); + return ret; +} + +const char * +scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len) +{ + switch (cdb[0]) { + case READ_6: + case WRITE_6: + return scsi_trace_rw6(p, cdb, len); + case READ_10: + case VERIFY: + case WRITE_10: + case WRITE_SAME: + return scsi_trace_rw10(p, cdb, len); + case READ_12: + case VERIFY_12: + case WRITE_12: + return scsi_trace_rw12(p, cdb, len); + case READ_16: + case VERIFY_16: + case WRITE_16: + case WRITE_SAME_16: + return scsi_trace_rw16(p, cdb, len); + case UNMAP: + return scsi_trace_unmap(p, cdb, len); + case SERVICE_ACTION_IN_16: + return scsi_trace_service_action_in(p, cdb, len); + case VARIABLE_LENGTH_CMD: + return scsi_trace_varlen(p, cdb, len); + default: + return scsi_trace_misc(p, cdb, len); + } +} + +unsigned long long process_scsi_trace_parse_cdb(struct trace_seq *s, + unsigned long long *args) +{ + scsi_trace_parse_cdb(s, (unsigned char *) (unsigned long) args[1], args[2]); + return 0; +} + +int TEP_PLUGIN_LOADER(struct tep_handle *tep) +{ + tep_register_print_function(tep, + process_scsi_trace_parse_cdb, + TEP_FUNC_ARG_STRING, + "scsi_trace_parse_cdb", + TEP_FUNC_ARG_PTR, + TEP_FUNC_ARG_PTR, + TEP_FUNC_ARG_INT, + TEP_FUNC_ARG_VOID); + return 0; +} + +void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) +{ + tep_unregister_print_function(tep, process_scsi_trace_parse_cdb, + "scsi_trace_parse_cdb"); +} diff --git a/tools/lib/traceevent/plugins/plugin_xen.c b/tools/lib/traceevent/plugins/plugin_xen.c new file mode 100644 index 000000000000..993b208d0323 --- /dev/null +++ b/tools/lib/traceevent/plugins/plugin_xen.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include "event-parse.h" +#include "trace-seq.h" + +#define __HYPERVISOR_set_trap_table 0 +#define __HYPERVISOR_mmu_update 1 +#define __HYPERVISOR_set_gdt 2 +#define __HYPERVISOR_stack_switch 3 +#define __HYPERVISOR_set_callbacks 4 +#define __HYPERVISOR_fpu_taskswitch 5 +#define __HYPERVISOR_sched_op_compat 6 +#define __HYPERVISOR_dom0_op 7 +#define __HYPERVISOR_set_debugreg 8 +#define __HYPERVISOR_get_debugreg 9 +#define __HYPERVISOR_update_descriptor 10 +#define __HYPERVISOR_memory_op 12 +#define __HYPERVISOR_multicall 13 +#define __HYPERVISOR_update_va_mapping 14 +#define __HYPERVISOR_set_timer_op 15 +#define __HYPERVISOR_event_channel_op_compat 16 +#define __HYPERVISOR_xen_version 17 +#define __HYPERVISOR_console_io 18 +#define __HYPERVISOR_physdev_op_compat 19 +#define __HYPERVISOR_grant_table_op 20 +#define __HYPERVISOR_vm_assist 21 +#define __HYPERVISOR_update_va_mapping_otherdomain 22 +#define __HYPERVISOR_iret 23 /* x86 only */ +#define __HYPERVISOR_vcpu_op 24 +#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */ +#define __HYPERVISOR_mmuext_op 26 +#define __HYPERVISOR_acm_op 27 +#define __HYPERVISOR_nmi_op 28 +#define __HYPERVISOR_sched_op 29 +#define __HYPERVISOR_callback_op 30 +#define __HYPERVISOR_xenoprof_op 31 +#define __HYPERVISOR_event_channel_op 32 +#define __HYPERVISOR_physdev_op 33 +#define __HYPERVISOR_hvm_op 34 +#define __HYPERVISOR_tmem_op 38 + +/* Architecture-specific hypercall definitions. */ +#define __HYPERVISOR_arch_0 48 +#define __HYPERVISOR_arch_1 49 +#define __HYPERVISOR_arch_2 50 +#define __HYPERVISOR_arch_3 51 +#define __HYPERVISOR_arch_4 52 +#define __HYPERVISOR_arch_5 53 +#define __HYPERVISOR_arch_6 54 +#define __HYPERVISOR_arch_7 55 + +#define N(x) [__HYPERVISOR_##x] = "("#x")" +static const char *xen_hypercall_names[] = { + N(set_trap_table), + N(mmu_update), + N(set_gdt), + N(stack_switch), + N(set_callbacks), + N(fpu_taskswitch), + N(sched_op_compat), + N(dom0_op), + N(set_debugreg), + N(get_debugreg), + N(update_descriptor), + N(memory_op), + N(multicall), + N(update_va_mapping), + N(set_timer_op), + N(event_channel_op_compat), + N(xen_version), + N(console_io), + N(physdev_op_compat), + N(grant_table_op), + N(vm_assist), + N(update_va_mapping_otherdomain), + N(iret), + N(vcpu_op), + N(set_segment_base), + N(mmuext_op), + N(acm_op), + N(nmi_op), + N(sched_op), + N(callback_op), + N(xenoprof_op), + N(event_channel_op), + N(physdev_op), + N(hvm_op), + +/* Architecture-specific hypercall definitions. */ + N(arch_0), + N(arch_1), + N(arch_2), + N(arch_3), + N(arch_4), + N(arch_5), + N(arch_6), + N(arch_7), +}; +#undef N + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +static const char *xen_hypercall_name(unsigned op) +{ + if (op < ARRAY_SIZE(xen_hypercall_names) && + xen_hypercall_names[op] != NULL) + return xen_hypercall_names[op]; + + return ""; +} + +unsigned long long process_xen_hypercall_name(struct trace_seq *s, + unsigned long long *args) +{ + unsigned int op = args[0]; + + trace_seq_printf(s, "%s", xen_hypercall_name(op)); + return 0; +} + +int TEP_PLUGIN_LOADER(struct tep_handle *tep) +{ + tep_register_print_function(tep, + process_xen_hypercall_name, + TEP_FUNC_ARG_STRING, + "xen_hypercall_name", + TEP_FUNC_ARG_INT, + TEP_FUNC_ARG_VOID); + return 0; +} + +void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) +{ + tep_unregister_print_function(tep, process_xen_hypercall_name, + "xen_hypercall_name"); +} diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 2ccc12f3730b..902c792f326a 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -292,7 +292,7 @@ endif LIBTRACEEVENT = $(TE_PATH)libtraceevent.a export LIBTRACEEVENT -LIBTRACEEVENT_DYNAMIC_LIST = $(TE_PATH)libtraceevent-dynamic-list +LIBTRACEEVENT_DYNAMIC_LIST = $(TE_PATH)plugins/libtraceevent-dynamic-list # # The static build has no dynsym table, so this does not work for @@ -737,7 +737,7 @@ libtraceevent_plugins: FORCE $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) plugins $(LIBTRACEEVENT_DYNAMIC_LIST): libtraceevent_plugins - $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent-dynamic-list + $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)plugins/libtraceevent-dynamic-list $(LIBTRACEEVENT)-clean: $(call QUIET_CLEAN, libtraceevent) -- cgit v1.2.3 From 33c96400dcd34d572299b8106e1b0460a1b8bae9 Mon Sep 17 00:00:00 2001 From: Tzvetomir Stoyanov Date: Thu, 19 Sep 2019 17:23:40 -0400 Subject: libtraceevent: Man pages for tep plugins APIs Create man pages for libtraceevent APIs: tep_load_plugins(), tep_unload_plugin() Signed-off-by: Tzvetomir Stoyanov Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: linux-trace-devel@vger.kernel.org Link: http://lore.kernel.org/linux-trace-devel/20190903133434.30417-1-tz.stoyanov@gmail.com Link: http://lore.kernel.org/lkml/20190919212542.216189588@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- .../Documentation/libtraceevent-plugins.txt | 99 ++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 tools/lib/traceevent/Documentation/libtraceevent-plugins.txt (limited to 'tools/lib/traceevent') diff --git a/tools/lib/traceevent/Documentation/libtraceevent-plugins.txt b/tools/lib/traceevent/Documentation/libtraceevent-plugins.txt new file mode 100644 index 000000000000..596032ade31f --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-plugins.txt @@ -0,0 +1,99 @@ +libtraceevent(3) +================ + +NAME +---- +tep_load_plugins, tep_unload_plugins - Load / unload traceevent plugins. + +SYNOPSIS +-------- +[verse] +-- +*#include * + +struct tep_plugin_list pass:[*]*tep_load_plugins*(struct tep_handle pass:[*]_tep_); +void *tep_unload_plugins*(struct tep_plugin_list pass:[*]_plugin_list_, struct tep_handle pass:[*]_tep_); +-- + +DESCRIPTION +----------- +The _tep_load_plugins()_ function loads all plugins, located in the plugin +directories. The _tep_ argument is trace event parser context. +The plugin directories are : +[verse] +-- + - System's plugin directory, defined at the library compile time. It + depends on the library installation prefix and usually is + _(install_preffix)/lib/traceevent/plugins_ + - Directory, defined by the environment variable _TRACEEVENT_PLUGIN_DIR_ + - User's plugin directory, located at _~/.local/lib/traceevent/plugins_ +-- +Loading of plugins can be controlled by the _tep_flags_, using the +_tep_set_flag()_ API: +[verse] +-- + _TEP_DISABLE_SYS_PLUGINS_ - do not load plugins, located in + the system's plugin directory. + _TEP_DISABLE_PLUGINS_ - do not load any plugins. +-- +The _tep_set_flag()_ API needs to be called before _tep_load_plugins()_, if +loading of all plugins is not the desired case. + +The _tep_unload_plugins()_ function unloads the plugins, previously loaded by +_tep_load_plugins()_. The _tep_ argument is trace event parser context. The +_plugin_list_ is the list of loaded plugins, returned by +the _tep_load_plugins()_ function. + +RETURN VALUE +------------ +The _tep_load_plugins()_ function returns a list of successfully loaded plugins, +or NULL in case no plugins are loaded. + +EXAMPLE +------- +[source,c] +-- +#include +... +struct tep_handle *tep = tep_alloc(); +... +struct tep_plugin_list *plugins = tep_load_plugins(tep); +if (plugins == NULL) { + /* no plugins are loaded */ +} +... +tep_unload_plugins(plugins, tep); +-- + +FILES +----- +[verse] +-- +*event-parse.h* + Header file to include in order to have access to the library APIs. +*-ltraceevent* + Linker switch to add when building a program that uses the library. +-- + +SEE ALSO +-------- +_libtraceevent(3)_, _trace-cmd(1)_, _tep_set_flag(3)_ + +AUTHOR +------ +[verse] +-- +*Steven Rostedt* , author of *libtraceevent*. +*Tzvetomir Stoyanov* , author of this man page. +-- +REPORTING BUGS +-------------- +Report bugs to + +LICENSE +------- +libtraceevent is Free Software licensed under the GNU LGPL 2.1 + +RESOURCES +--------- +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git -- cgit v1.2.3