1ceea279fSIan Rogers // SPDX-License-Identifier: GPL-2.0
2ceea279fSIan Rogers #include <errno.h>
3ceea279fSIan Rogers #include <memory.h>
4ceea279fSIan Rogers #include "../debug.h"
5ceea279fSIan Rogers #include "../evsel.h"
6ceea279fSIan Rogers #include "../kvm-stat.h"
7ceea279fSIan Rogers #include "arm64_exception_types.h"
8ceea279fSIan Rogers
9ceea279fSIan Rogers define_exit_reasons_table(arm64_exit_reasons, kvm_arm_exception_type);
10ceea279fSIan Rogers define_exit_reasons_table(arm64_trap_exit_reasons, kvm_arm_exception_class);
11ceea279fSIan Rogers
12ceea279fSIan Rogers static const char *kvm_trap_exit_reason = "esr_ec";
13ceea279fSIan Rogers
14ceea279fSIan Rogers static const char * const __kvm_events_tp[] = {
15ceea279fSIan Rogers "kvm:kvm_entry",
16ceea279fSIan Rogers "kvm:kvm_exit",
17ceea279fSIan Rogers NULL,
18ceea279fSIan Rogers };
19ceea279fSIan Rogers
event_get_key(struct evsel * evsel,struct perf_sample * sample,struct event_key * key)20ceea279fSIan Rogers static void event_get_key(struct evsel *evsel,
21ceea279fSIan Rogers struct perf_sample *sample,
22ceea279fSIan Rogers struct event_key *key)
23ceea279fSIan Rogers {
24ceea279fSIan Rogers key->info = 0;
25*43af5484SIan Rogers key->key = evsel__intval(evsel, sample, kvm_exit_reason(EM_AARCH64));
26ceea279fSIan Rogers key->exit_reasons = arm64_exit_reasons;
27ceea279fSIan Rogers
28ceea279fSIan Rogers /*
29ceea279fSIan Rogers * TRAP exceptions carry exception class info in esr_ec field
30ceea279fSIan Rogers * and, hence, we need to use a different exit_reasons table to
31ceea279fSIan Rogers * properly decode event's est_ec.
32ceea279fSIan Rogers */
33ceea279fSIan Rogers if (key->key == ARM_EXCEPTION_TRAP) {
34ceea279fSIan Rogers key->key = evsel__intval(evsel, sample, kvm_trap_exit_reason);
35ceea279fSIan Rogers key->exit_reasons = arm64_trap_exit_reasons;
36ceea279fSIan Rogers }
37ceea279fSIan Rogers }
38ceea279fSIan Rogers
event_begin(struct evsel * evsel,struct perf_sample * sample __maybe_unused,struct event_key * key __maybe_unused)39ceea279fSIan Rogers static bool event_begin(struct evsel *evsel,
40ceea279fSIan Rogers struct perf_sample *sample __maybe_unused,
41ceea279fSIan Rogers struct event_key *key __maybe_unused)
42ceea279fSIan Rogers {
43*43af5484SIan Rogers return evsel__name_is(evsel, kvm_entry_trace(EM_AARCH64));
44ceea279fSIan Rogers }
45ceea279fSIan Rogers
event_end(struct evsel * evsel,struct perf_sample * sample,struct event_key * key)46ceea279fSIan Rogers static bool event_end(struct evsel *evsel,
47ceea279fSIan Rogers struct perf_sample *sample,
48ceea279fSIan Rogers struct event_key *key)
49ceea279fSIan Rogers {
50*43af5484SIan Rogers if (evsel__name_is(evsel, kvm_exit_trace(EM_AARCH64))) {
51ceea279fSIan Rogers event_get_key(evsel, sample, key);
52ceea279fSIan Rogers return true;
53ceea279fSIan Rogers }
54ceea279fSIan Rogers return false;
55ceea279fSIan Rogers }
56ceea279fSIan Rogers
57ceea279fSIan Rogers static const struct kvm_events_ops exit_events = {
58ceea279fSIan Rogers .is_begin_event = event_begin,
59ceea279fSIan Rogers .is_end_event = event_end,
60ceea279fSIan Rogers .decode_key = exit_event_decode_key,
61ceea279fSIan Rogers .name = "VM-EXIT"
62ceea279fSIan Rogers };
63ceea279fSIan Rogers
64ceea279fSIan Rogers static const struct kvm_reg_events_ops __kvm_reg_events_ops[] = {
65ceea279fSIan Rogers {
66ceea279fSIan Rogers .name = "vmexit",
67ceea279fSIan Rogers .ops = &exit_events,
68ceea279fSIan Rogers },
69ceea279fSIan Rogers { NULL, NULL },
70ceea279fSIan Rogers };
71ceea279fSIan Rogers
72ceea279fSIan Rogers static const char * const __kvm_skip_events[] = {
73ceea279fSIan Rogers NULL,
74ceea279fSIan Rogers };
75ceea279fSIan Rogers
__cpu_isa_init_arm64(struct perf_kvm_stat * kvm)76ceea279fSIan Rogers int __cpu_isa_init_arm64(struct perf_kvm_stat *kvm)
77ceea279fSIan Rogers {
78ceea279fSIan Rogers kvm->exit_reasons_isa = "arm64";
79ceea279fSIan Rogers return 0;
80ceea279fSIan Rogers }
81ceea279fSIan Rogers
__kvm_events_tp_arm64(void)82ceea279fSIan Rogers const char * const *__kvm_events_tp_arm64(void)
83ceea279fSIan Rogers {
84ceea279fSIan Rogers return __kvm_events_tp;
85ceea279fSIan Rogers }
86ceea279fSIan Rogers
__kvm_reg_events_ops_arm64(void)87ceea279fSIan Rogers const struct kvm_reg_events_ops *__kvm_reg_events_ops_arm64(void)
88ceea279fSIan Rogers {
89ceea279fSIan Rogers return __kvm_reg_events_ops;
90ceea279fSIan Rogers }
91ceea279fSIan Rogers
__kvm_skip_events_arm64(void)92ceea279fSIan Rogers const char * const *__kvm_skip_events_arm64(void)
93ceea279fSIan Rogers {
94ceea279fSIan Rogers return __kvm_skip_events;
95ceea279fSIan Rogers }
96