Linux-Trace-Devel Archive on lore.kernel.org
 help / color / Atom feed
From: Stefano De Venuto <stefano.devenuto99@gmail.com>
To: rostedt@goodmis.org
Cc: linux-trace-devel@vger.kernel.org, dfaggioli@suse.com,
	Stefano De Venuto <stefano.devenuto99@gmail.com>
Subject: [RFC] Simple tool for VMEnters/VMExits matching and trace validation
Date: Fri, 16 Apr 2021 18:46:53 +0200
Message-ID: <20210416164653.2949-1-stefano.devenuto99@gmail.com> (raw)

Add a tool in examples/ that scans a merged host + guest trace and
search for host events that are inside a vmentry/vmexit block (and
vice-versa for guest events ouside the block) and report the found
ones.

It can be useful as a starting point for identifying issues of for
checking the effectiveness of host/guest traces synchronization, or
even for improving the placing of the tracepoints in the kernel.

Signed-off-by: Stefano De Venuto <stefano.devenuto99@gmail.com>
---
 examples/checker.c | 202 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 202 insertions(+)
 create mode 100644 examples/checker.c

diff --git a/examples/checker.c b/examples/checker.c
new file mode 100644
index 0000000..0b04343
--- /dev/null
+++ b/examples/checker.c
@@ -0,0 +1,202 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libkshark.h"
+#include "libkshark-tepdata.h"
+
+#define KVM_ENTRY "kvm/kvm_entry"
+#define KVM_EXIT "kvm/kvm_exit"
+
+struct custom_stream
+{
+	struct kshark_data_stream* original_stream;
+	int* cpus;
+};
+
+int is_guest(int stream_id,
+	      struct kshark_host_guest_map* mapping,
+	      int n_mapping, int* host)
+{
+	for (int i = 0; i < n_mapping; i++) {
+		if (mapping[i].guest_id == stream_id) {
+			*host = mapping[i].host_id;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+void print_entry(struct kshark_entry* entry)
+{
+	struct kshark_data_stream* stream;
+	char* event_name;
+	int stream_id;
+
+	stream = kshark_get_stream_from_entry(entry);
+	event_name = kshark_get_event_name(entry);
+
+	stream_id = stream->stream_id;
+	printf("%d: %s-%d, %lld [%03d]:%s\t%s\n",
+		stream->stream_id,
+		kshark_get_task(entry),
+		kshark_get_pid(entry),
+		entry->ts,
+		entry->cpu,
+		event_name,
+		kshark_get_info(entry));
+
+}
+
+void print_entries(struct kshark_entry **entries, ssize_t n_entries)
+{
+	for (int i = 0; i < n_entries; ++i
+		print_entry(entries[i]);
+}
+
+void free_data(struct kshark_context *kshark_ctx,
+	       struct custom_stream** custom_streams,
+	       struct kshark_entry** entries, int n_entries,
+	       struct kshark_host_guest_map* host_guest_mapping,
+	       int n_guest)
+{
+	struct custom_stream* custom_stream;
+
+	for (int i = 0; i < kshark_ctx->n_streams; i++) {
+		custom_stream = custom_streams[i];
+
+		free(custom_stream->cpus);
+		free(custom_stream);
+	}
+	free(custom_streams);
+
+	for (int i = 0; i < n_entries; i++)
+		free(entries[i]);
+	free(entries);
+
+	kshark_tracecmd_free_hostguest_map(host_guest_mapping, n_guest);
+
+	kshark_close_all(kshark_ctx);
+	kshark_free(kshark_ctx);
+}
+
+int main(int argc, char **argv)
+{
+
+	struct kshark_host_guest_map* host_guest_mapping;
+	struct custom_stream** custom_streams;
+	struct custom_stream* custom_stream;
+	struct custom_stream* host_stream;
+	struct kshark_data_stream* stream;
+	struct kshark_context* kshark_ctx;
+	struct kshark_entry** entries;
+	struct kshark_entry* current;
+	ssize_t n_entries;
+	char* event_name;
+	char* token;
+	int n_guest;
+	char* info;
+	int host;
+	int v_i;
+	int sd;
+
+	kshark_ctx = NULL;
+	if (!kshark_instance(&kshark_ctx))
+		return 1;
+
+	custom_streams = malloc(sizeof(*custom_streams) * (argc-1));
+
+	for (int i = 1; i < argc; i++) {
+		sd = kshark_open(kshark_ctx, argv[i]);
+		if (sd < 0) {
+			kshark_free(kshark_ctx);
+			return 1;
+		}
+
+		kshark_tep_init_all_buffers(kshark_ctx, sd);
+
+		custom_stream = malloc(sizeof(*custom_stream));
+		custom_stream->original_stream = kshark_get_data_stream(kshark_ctx, sd);
+		custom_stream->cpus = malloc(custom_stream->original_stream->n_cpus * sizeof(int));
+		memset(custom_stream->cpus, -1, custom_stream->original_stream->n_cpus * sizeof(int));
+
+		custom_streams[i-1] = custom_stream;
+	}
+
+	host_guest_mapping = NULL;
+	n_guest = kshark_tracecmd_get_hostguest_mapping(&host_guest_mapping);
+	if (n_guest < 0) {
+	  printf("Failed mapping: %d\n", n_guest);
+	  return 1;
+	}
+
+	entries = NULL;
+	n_entries = kshark_load_all_entries(kshark_ctx, &entries);
+
+	for (int i = 0; i < n_entries; ++i) {
+		current = entries[i];
+
+		stream = kshark_get_stream_from_entry(current);
+		event_name = kshark_get_event_name(current);
+
+		custom_stream = custom_streams[stream->stream_id];
+
+		if (!strcmp(event_name, KVM_ENTRY) || !strcmp(event_name, KVM_EXIT)) {
+			if (!strcmp(event_name, KVM_ENTRY)) {
+
+				/*
+				 * The recovering process of the vCPU field of the kvm_entry event
+				 * is done by splitting the info field.
+				 */
+				info = kshark_get_info(current);
+
+				token = strtok(info, " ");
+				token = strtok(NULL, " ");
+
+				/* Removing the last comma */
+				token[strlen(token) - 1] = '\0';
+
+				custom_stream->cpus[current->cpu] = atoi(token);
+
+				free(info);
+			} else {
+				custom_stream->cpus[current->cpu] = -1;
+			}
+
+		} else {
+
+			/*
+			 * If the event comes from a guest, recover the pCPU where the event was executed
+			 * and check if it's NOT OUTSIDE a kvm_entry/kvm_exit block.
+			 */
+			if (is_guest(stream->stream_id, host_guest_mapping, n_guest, &host)) {
+				host_stream = custom_streams[host];
+
+				for (v_i = 0; v_i < host_stream->original_stream->n_cpus; v_i++) {
+					if (current->cpu == host_stream->cpus[v_i])
+					break;
+				}
+
+				if (v_i == host_stream->original_stream->n_cpus) {
+					printf("%d G out:\t", i);
+					print_entry(entries[i]);
+				}
+
+			/*
+			* If the event comes from a host, recover the CPU that executed the event
+			* and check if it's NOT INSIDE a kvm_entry/kvm_exit block.
+			*/
+			} else {
+				if (custom_stream->cpus[current->cpu] != -1) {
+					printf("%d H in:\t", i);
+					print_entry(entries[i]);
+				}
+			}
+		}
+	}
+
+	free_data(kshark_ctx, custom_streams, entries, n_entries, host_guest_mapping, n_guest);
+}
-- 
2.30.2


             reply index

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-16 16:46 Stefano De Venuto [this message]
2021-04-16 17:47 ` Dario Faggioli
2021-04-16 20:48   ` Stefano De Venuto
2021-04-16 21:32     ` Steven Rostedt
2021-04-17  6:43       ` Dario Faggioli
2021-04-20  8:12 ` Yordan Karadzhov
2021-04-21  2:17   ` Steven Rostedt
2021-04-21  9:14     ` Yordan Karadzhov
2021-05-01  6:11     ` Stefano De Venuto
2021-05-01  6:11   ` Stefano De Venuto

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=20210416164653.2949-1-stefano.devenuto99@gmail.com \
    --to=stefano.devenuto99@gmail.com \
    --cc=dfaggioli@suse.com \
    --cc=linux-trace-devel@vger.kernel.org \
    --cc=rostedt@goodmis.org \
    /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

Linux-Trace-Devel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-trace-devel/0 linux-trace-devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-trace-devel linux-trace-devel/ https://lore.kernel.org/linux-trace-devel \
		linux-trace-devel@vger.kernel.org
	public-inbox-index linux-trace-devel

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-trace-devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git