xref: /linux/tools/perf/util/kvm-stat-arch/kvm-stat-arm64.c (revision fd7dd303c430bf230b2192eb06696a7361f19850)
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 
20 static void event_get_key(struct perf_sample *sample,
21 			  struct event_key *key)
22 {
23 	key->info = 0;
24 	key->key = perf_sample__intval(sample, kvm_exit_reason(EM_AARCH64));
25 	key->exit_reasons = arm64_exit_reasons;
26 
27 	/*
28 	 * TRAP exceptions carry exception class info in esr_ec field
29 	 * and, hence, we need to use a different exit_reasons table to
30 	 * properly decode event's est_ec.
31 	 */
32 	if (key->key == ARM_EXCEPTION_TRAP) {
33 		key->key = perf_sample__intval(sample, kvm_trap_exit_reason);
34 		key->exit_reasons = arm64_trap_exit_reasons;
35 	}
36 }
37 
38 static bool event_begin(struct perf_sample *sample,
39 			struct event_key *key __maybe_unused)
40 {
41 	return evsel__name_is(sample->evsel, kvm_entry_trace(EM_AARCH64));
42 }
43 
44 static bool event_end(struct perf_sample *sample,
45 		      struct event_key *key)
46 {
47 	if (evsel__name_is(sample->evsel, kvm_exit_trace(EM_AARCH64))) {
48 		event_get_key(sample, key);
49 		return true;
50 	}
51 	return false;
52 }
53 
54 static const struct kvm_events_ops exit_events = {
55 	.is_begin_event = event_begin,
56 	.is_end_event	= event_end,
57 	.decode_key	= exit_event_decode_key,
58 	.name		= "VM-EXIT"
59 };
60 
61 static const struct kvm_reg_events_ops __kvm_reg_events_ops[] = {
62 	{
63 		.name	= "vmexit",
64 		.ops	= &exit_events,
65 	},
66 	{ NULL, NULL },
67 };
68 
69 static const char * const __kvm_skip_events[] = {
70 	NULL,
71 };
72 
73 int __cpu_isa_init_arm64(struct perf_kvm_stat *kvm)
74 {
75 	kvm->exit_reasons_isa = "arm64";
76 	return 0;
77 }
78 
79 const char * const *__kvm_events_tp_arm64(void)
80 {
81 	return __kvm_events_tp;
82 }
83 
84 const struct kvm_reg_events_ops *__kvm_reg_events_ops_arm64(void)
85 {
86 	return __kvm_reg_events_ops;
87 }
88 
89 const char * const *__kvm_skip_events_arm64(void)
90 {
91 	return __kvm_skip_events;
92 }
93