All of lore.kernel.org
 help / color / mirror / Atom feed
From: Steven Rostedt <rostedt@goodmis.org>
To: Linux Trace Devel <linux-trace-devel@vger.kernel.org>
Cc: uekawa@google.com
Subject: trace-cmd report: Add callback for kvm plugin to show guest functions
Date: Wed, 21 Sep 2022 20:26:42 -0400	[thread overview]
Message-ID: <20220921202642.44fec719@gandalf.local.home> (raw)

From: "Steven Rostedt (Google)" <rostedt@goodmis.org>

Starting with libtraceevent 1.6.2, the kvm plugin will call a weak
function that can be overridden by the application (in this case
trace-cmd) called tep_plugin_kvm_get_func() that passes in the event, the
record, and an address to a value containing the address of the function
being requested. If the application has the guest mapping of addresses to
function names (usually taken from kallsyms), then it can define this
function to return the name of the function at the given address of the
guest.

Optionally, it can update the value holding the address, to the start of
the function such that the tep kvm plugin can print not only the function
name, but also the address offset of the original location and the
function itself.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 tracecmd/trace-read.c | 94 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)

diff --git a/tracecmd/trace-read.c b/tracecmd/trace-read.c
index db9bb2e5219f..b8931cf95543 100644
--- a/tracecmd/trace-read.c
+++ b/tracecmd/trace-read.c
@@ -1040,6 +1040,98 @@ static bool skip_record(struct handle_list *handles, struct tep_record *record,
 	return !found;
 }
 
+struct kvm_cpu_map {
+	struct tracecmd_input		*guest_handle;
+	int				guest_vcpu;
+	int				host_pid;
+};
+
+static struct kvm_cpu_map *vcpu_maps;
+static int nr_vcpu_maps;
+
+static int cmp_map(const void *A, const void *B)
+{
+	const struct kvm_cpu_map *a = A;
+	const struct kvm_cpu_map *b = B;
+
+	if (a->host_pid < b->host_pid)
+		return -1;
+	return a->host_pid > b->host_pid;
+}
+
+static void map_vcpus(struct tracecmd_input **handles, int nr_handles)
+{
+	struct tracecmd_input *host_handle = handles[0];
+	unsigned long long traceid;
+	struct kvm_cpu_map *map;
+	const int *cpu_pids;
+	const char *name;
+	int vcpu_count;
+	int ret;
+	int i, k;
+
+	for (i = 1; i < nr_handles; i++) {
+		traceid = tracecmd_get_traceid(handles[i]);
+		ret = tracecmd_get_guest_cpumap(host_handle, traceid,
+						&name, &vcpu_count, &cpu_pids);
+		if (ret)
+			continue;
+		map = realloc(vcpu_maps, sizeof(*map) * (nr_vcpu_maps + vcpu_count));
+		if (!map)
+			die("Could not allocate vcpu maps");
+
+		vcpu_maps = map;
+		map += nr_vcpu_maps;
+		nr_vcpu_maps += vcpu_count;
+
+		for (k = 0; k < vcpu_count; k++) {
+			map[k].guest_handle = handles[i];
+			map[k].guest_vcpu = k;
+			map[k].host_pid = cpu_pids[k];
+		}
+	}
+	if (!vcpu_maps)
+		return;
+
+	qsort(vcpu_maps, nr_vcpu_maps, sizeof(*map), cmp_map);
+}
+
+
+const char *tep_plugin_kvm_get_func(struct tep_event *event,
+				    struct tep_record *record,
+				    unsigned long long *val)
+{
+	struct tep_handle *tep;
+	struct kvm_cpu_map *map;
+	struct kvm_cpu_map key;
+	unsigned long long rip = *val;
+	const char *func;
+	int pid;
+
+	if (!vcpu_maps || !nr_vcpu_maps)
+		return NULL;
+
+	/*
+	 * A kvm event is referencing an address of the guest.
+	 * get the PID of this event, and then find which guest
+	 * it belongs to. Then return the function name from that guest's
+	 * handle.
+	 */
+	pid = tep_data_pid(event->tep, record);
+
+	key.host_pid = pid;
+	map = bsearch(&key, vcpu_maps, nr_vcpu_maps, sizeof(*vcpu_maps), cmp_map);
+
+	if (!map)
+		return NULL;
+
+	tep = tracecmd_get_tep(map->guest_handle);
+	func = tep_find_function(tep, rip);
+	if (func)
+		*val = tep_find_function_address(tep, rip);
+	return func;
+}
+
 static int process_record(struct tracecmd_input *handle, struct tep_record *record,
 			  int cpu, void *data)
 {
@@ -1192,6 +1284,8 @@ static void read_data_info(struct list_head *handle_list, enum output_type otype
 		handle_array[nr_handles++] = handles->handle;
 	}
 
+	map_vcpus(handle_array, nr_handles);
+
 	tracecmd_iterate_events_multi(handle_array, nr_handles,
 				      process_record, &last_timestamp);
 
-- 
2.35.1


             reply	other threads:[~2022-09-22  0:25 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-22  0:26 Steven Rostedt [this message]
     [not found] ` <CADgJSGEoELCWYYxsRJaMK9egCUhbRV7QWEqTga71tAC-GR8qeA@mail.gmail.com>
2022-09-28 12:17   ` trace-cmd report: Add callback for kvm plugin to show guest functions Steven Rostedt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220921202642.44fec719@gandalf.local.home \
    --to=rostedt@goodmis.org \
    --cc=linux-trace-devel@vger.kernel.org \
    --cc=uekawa@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.