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