xref: /linux/tools/perf/arch/arm64/util/kvm-stat.c (revision a00b7e39)
11218838dSSergey Senozhatsky // SPDX-License-Identifier: GPL-2.0
21218838dSSergey Senozhatsky #include <errno.h>
31218838dSSergey Senozhatsky #include <memory.h>
4b96da02bSIan Rogers #include "../../../util/evsel.h"
5b96da02bSIan Rogers #include "../../../util/kvm-stat.h"
61218838dSSergey Senozhatsky #include "arm64_exception_types.h"
71218838dSSergey Senozhatsky #include "debug.h"
81218838dSSergey Senozhatsky 
91218838dSSergey Senozhatsky define_exit_reasons_table(arm64_exit_reasons, kvm_arm_exception_type);
101218838dSSergey Senozhatsky define_exit_reasons_table(arm64_trap_exit_reasons, kvm_arm_exception_class);
111218838dSSergey Senozhatsky 
121218838dSSergey Senozhatsky const char *kvm_trap_exit_reason = "esr_ec";
131218838dSSergey Senozhatsky const char *vcpu_id_str = "id";
141218838dSSergey Senozhatsky const int decode_str_len = 20;
151218838dSSergey Senozhatsky const char *kvm_exit_reason = "ret";
161218838dSSergey Senozhatsky const char *kvm_entry_trace = "kvm:kvm_entry";
171218838dSSergey Senozhatsky const char *kvm_exit_trace = "kvm:kvm_exit";
181218838dSSergey Senozhatsky 
191218838dSSergey Senozhatsky const char *kvm_events_tp[] = {
201218838dSSergey Senozhatsky 	"kvm:kvm_entry",
211218838dSSergey Senozhatsky 	"kvm:kvm_exit",
221218838dSSergey Senozhatsky 	NULL,
231218838dSSergey Senozhatsky };
241218838dSSergey Senozhatsky 
251218838dSSergey Senozhatsky static void event_get_key(struct evsel *evsel,
261218838dSSergey Senozhatsky 			  struct perf_sample *sample,
271218838dSSergey Senozhatsky 			  struct event_key *key)
281218838dSSergey Senozhatsky {
291218838dSSergey Senozhatsky 	key->info = 0;
301218838dSSergey Senozhatsky 	key->key = evsel__intval(evsel, sample, kvm_exit_reason);
311218838dSSergey Senozhatsky 	key->exit_reasons = arm64_exit_reasons;
321218838dSSergey Senozhatsky 
331218838dSSergey Senozhatsky 	/*
341218838dSSergey Senozhatsky 	 * TRAP exceptions carry exception class info in esr_ec field
351218838dSSergey Senozhatsky 	 * and, hence, we need to use a different exit_reasons table to
361218838dSSergey Senozhatsky 	 * properly decode event's est_ec.
371218838dSSergey Senozhatsky 	 */
381218838dSSergey Senozhatsky 	if (key->key == ARM_EXCEPTION_TRAP) {
391218838dSSergey Senozhatsky 		key->key = evsel__intval(evsel, sample, kvm_trap_exit_reason);
401218838dSSergey Senozhatsky 		key->exit_reasons = arm64_trap_exit_reasons;
411218838dSSergey Senozhatsky 	}
421218838dSSergey Senozhatsky }
431218838dSSergey Senozhatsky 
441218838dSSergey Senozhatsky static bool event_begin(struct evsel *evsel,
451218838dSSergey Senozhatsky 			struct perf_sample *sample __maybe_unused,
461218838dSSergey Senozhatsky 			struct event_key *key __maybe_unused)
471218838dSSergey Senozhatsky {
481218838dSSergey Senozhatsky 	return !strcmp(evsel->name, kvm_entry_trace);
491218838dSSergey Senozhatsky }
501218838dSSergey Senozhatsky 
511218838dSSergey Senozhatsky static bool event_end(struct evsel *evsel,
521218838dSSergey Senozhatsky 		      struct perf_sample *sample,
531218838dSSergey Senozhatsky 		      struct event_key *key)
541218838dSSergey Senozhatsky {
551218838dSSergey Senozhatsky 	if (!strcmp(evsel->name, kvm_exit_trace)) {
561218838dSSergey Senozhatsky 		event_get_key(evsel, sample, key);
571218838dSSergey Senozhatsky 		return true;
581218838dSSergey Senozhatsky 	}
591218838dSSergey Senozhatsky 	return false;
601218838dSSergey Senozhatsky }
611218838dSSergey Senozhatsky 
621218838dSSergey Senozhatsky static struct kvm_events_ops exit_events = {
631218838dSSergey Senozhatsky 	.is_begin_event = event_begin,
641218838dSSergey Senozhatsky 	.is_end_event	= event_end,
651218838dSSergey Senozhatsky 	.decode_key	= exit_event_decode_key,
661218838dSSergey Senozhatsky 	.name		= "VM-EXIT"
671218838dSSergey Senozhatsky };
681218838dSSergey Senozhatsky 
691218838dSSergey Senozhatsky struct kvm_reg_events_ops kvm_reg_events_ops[] = {
701218838dSSergey Senozhatsky 	{
711218838dSSergey Senozhatsky 		.name	= "vmexit",
721218838dSSergey Senozhatsky 		.ops	= &exit_events,
731218838dSSergey Senozhatsky 	},
74*a00b7e39SMasami Hiramatsu 	{ NULL, NULL },
751218838dSSergey Senozhatsky };
761218838dSSergey Senozhatsky 
771218838dSSergey Senozhatsky const char * const kvm_skip_events[] = {
781218838dSSergey Senozhatsky 	NULL,
791218838dSSergey Senozhatsky };
801218838dSSergey Senozhatsky 
811218838dSSergey Senozhatsky int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid __maybe_unused)
821218838dSSergey Senozhatsky {
831218838dSSergey Senozhatsky 	kvm->exit_reasons_isa = "arm64";
841218838dSSergey Senozhatsky 	return 0;
851218838dSSergey Senozhatsky }
86