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 char *kvm_exit_reason = "ret";
151218838dSSergey Senozhatsky const char *kvm_entry_trace = "kvm:kvm_entry";
161218838dSSergey Senozhatsky const char *kvm_exit_trace = "kvm:kvm_exit";
171218838dSSergey Senozhatsky
181218838dSSergey Senozhatsky const char *kvm_events_tp[] = {
191218838dSSergey Senozhatsky "kvm:kvm_entry",
201218838dSSergey Senozhatsky "kvm:kvm_exit",
211218838dSSergey Senozhatsky NULL,
221218838dSSergey Senozhatsky };
231218838dSSergey Senozhatsky
event_get_key(struct evsel * evsel,struct perf_sample * sample,struct event_key * key)241218838dSSergey Senozhatsky static void event_get_key(struct evsel *evsel,
251218838dSSergey Senozhatsky struct perf_sample *sample,
261218838dSSergey Senozhatsky struct event_key *key)
271218838dSSergey Senozhatsky {
281218838dSSergey Senozhatsky key->info = 0;
291218838dSSergey Senozhatsky key->key = evsel__intval(evsel, sample, kvm_exit_reason);
301218838dSSergey Senozhatsky key->exit_reasons = arm64_exit_reasons;
311218838dSSergey Senozhatsky
321218838dSSergey Senozhatsky /*
331218838dSSergey Senozhatsky * TRAP exceptions carry exception class info in esr_ec field
341218838dSSergey Senozhatsky * and, hence, we need to use a different exit_reasons table to
351218838dSSergey Senozhatsky * properly decode event's est_ec.
361218838dSSergey Senozhatsky */
371218838dSSergey Senozhatsky if (key->key == ARM_EXCEPTION_TRAP) {
381218838dSSergey Senozhatsky key->key = evsel__intval(evsel, sample, kvm_trap_exit_reason);
391218838dSSergey Senozhatsky key->exit_reasons = arm64_trap_exit_reasons;
401218838dSSergey Senozhatsky }
411218838dSSergey Senozhatsky }
421218838dSSergey Senozhatsky
event_begin(struct evsel * evsel,struct perf_sample * sample __maybe_unused,struct event_key * key __maybe_unused)431218838dSSergey Senozhatsky static bool event_begin(struct evsel *evsel,
441218838dSSergey Senozhatsky struct perf_sample *sample __maybe_unused,
451218838dSSergey Senozhatsky struct event_key *key __maybe_unused)
461218838dSSergey Senozhatsky {
47*ce1d3bc2SArnaldo Carvalho de Melo return evsel__name_is(evsel, kvm_entry_trace);
481218838dSSergey Senozhatsky }
491218838dSSergey Senozhatsky
event_end(struct evsel * evsel,struct perf_sample * sample,struct event_key * key)501218838dSSergey Senozhatsky static bool event_end(struct evsel *evsel,
511218838dSSergey Senozhatsky struct perf_sample *sample,
521218838dSSergey Senozhatsky struct event_key *key)
531218838dSSergey Senozhatsky {
54*ce1d3bc2SArnaldo Carvalho de Melo if (evsel__name_is(evsel, kvm_exit_trace)) {
551218838dSSergey Senozhatsky event_get_key(evsel, sample, key);
561218838dSSergey Senozhatsky return true;
571218838dSSergey Senozhatsky }
581218838dSSergey Senozhatsky return false;
591218838dSSergey Senozhatsky }
601218838dSSergey Senozhatsky
611218838dSSergey Senozhatsky static struct kvm_events_ops exit_events = {
621218838dSSergey Senozhatsky .is_begin_event = event_begin,
631218838dSSergey Senozhatsky .is_end_event = event_end,
641218838dSSergey Senozhatsky .decode_key = exit_event_decode_key,
651218838dSSergey Senozhatsky .name = "VM-EXIT"
661218838dSSergey Senozhatsky };
671218838dSSergey Senozhatsky
681218838dSSergey Senozhatsky struct kvm_reg_events_ops kvm_reg_events_ops[] = {
691218838dSSergey Senozhatsky {
701218838dSSergey Senozhatsky .name = "vmexit",
711218838dSSergey Senozhatsky .ops = &exit_events,
721218838dSSergey Senozhatsky },
73a00b7e39SMasami Hiramatsu { NULL, NULL },
741218838dSSergey Senozhatsky };
751218838dSSergey Senozhatsky
761218838dSSergey Senozhatsky const char * const kvm_skip_events[] = {
771218838dSSergey Senozhatsky NULL,
781218838dSSergey Senozhatsky };
791218838dSSergey Senozhatsky
cpu_isa_init(struct perf_kvm_stat * kvm,const char * cpuid __maybe_unused)801218838dSSergey Senozhatsky int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid __maybe_unused)
811218838dSSergey Senozhatsky {
821218838dSSergey Senozhatsky kvm->exit_reasons_isa = "arm64";
831218838dSSergey Senozhatsky return 0;
841218838dSSergey Senozhatsky }
85