xref: /linux/tools/perf/util/kvm-stat.c (revision 390d5ea26622f794c2d29cefd5a01ef116b4fe1d)
1 // SPDX-License-Identifier: GPL-2.0
2 #include "debug.h"
3 #include "evsel.h"
4 #include "kvm-stat.h"
5 #include <dwarf-regs.h>
6 
7 bool kvm_exit_event(struct evsel *evsel)
8 {
9 	uint16_t e_machine = evsel__e_machine(evsel, /*e_flags=*/NULL);
10 
11 	return evsel__name_is(evsel, kvm_exit_trace(e_machine));
12 }
13 
14 void exit_event_get_key(struct perf_sample *sample,
15 			struct event_key *key)
16 {
17 	uint16_t e_machine = evsel__e_machine(sample->evsel, /*e_flags=*/NULL);
18 
19 	key->info = 0;
20 	key->key  = perf_sample__intval(sample, kvm_exit_reason(e_machine));
21 }
22 
23 
24 bool exit_event_begin(struct perf_sample *sample, struct event_key *key)
25 {
26 	if (kvm_exit_event(sample->evsel)) {
27 		exit_event_get_key(sample, key);
28 		return true;
29 	}
30 
31 	return false;
32 }
33 
34 bool kvm_entry_event(struct evsel *evsel)
35 {
36 	uint16_t e_machine = evsel__e_machine(evsel, /*e_flags=*/NULL);
37 
38 	return evsel__name_is(evsel, kvm_entry_trace(e_machine));
39 }
40 
41 bool exit_event_end(struct perf_sample *sample,
42 		    struct event_key *key __maybe_unused)
43 {
44 	return kvm_entry_event(sample->evsel);
45 }
46 
47 static const char *get_exit_reason(struct perf_kvm_stat *kvm,
48 				   struct exit_reasons_table *tbl,
49 				   u64 exit_code)
50 {
51 	while (tbl->reason != NULL) {
52 		if (tbl->exit_code == exit_code)
53 			return tbl->reason;
54 		tbl++;
55 	}
56 
57 	pr_err("unknown kvm exit code:%lld on %s\n",
58 		(unsigned long long)exit_code, kvm->exit_reasons_isa);
59 	return "UNKNOWN";
60 }
61 
62 void exit_event_decode_key(struct perf_kvm_stat *kvm,
63 			   struct event_key *key,
64 			   char *decode)
65 {
66 	const char *exit_reason = get_exit_reason(kvm, key->exit_reasons,
67 						  key->key);
68 
69 	scnprintf(decode, KVM_EVENT_NAME_LEN, "%s", exit_reason);
70 }
71 
72 int setup_kvm_events_tp(struct perf_kvm_stat *kvm, uint16_t e_machine)
73 {
74 	switch (e_machine) {
75 	case EM_PPC:
76 	case EM_PPC64:
77 		return __setup_kvm_events_tp_powerpc(kvm);
78 	default:
79 		return 0;
80 	}
81 }
82 
83 int cpu_isa_init(struct perf_kvm_stat *kvm, uint16_t e_machine, const char *cpuid)
84 {
85 	switch (e_machine) {
86 	case EM_AARCH64:
87 		return __cpu_isa_init_arm64(kvm);
88 	case EM_LOONGARCH:
89 		return __cpu_isa_init_loongarch(kvm);
90 	case EM_PPC:
91 	case EM_PPC64:
92 		return __cpu_isa_init_powerpc(kvm);
93 	case EM_RISCV:
94 		return __cpu_isa_init_riscv(kvm);
95 	case EM_S390:
96 		return __cpu_isa_init_s390(kvm, cpuid);
97 	case EM_X86_64:
98 	case EM_386:
99 		return __cpu_isa_init_x86(kvm, cpuid);
100 	default:
101 		pr_err("Unsupported kvm-stat host %d\n", e_machine);
102 		return -1;
103 	}
104 }
105 
106 const char *vcpu_id_str(uint16_t e_machine)
107 {
108 	switch (e_machine) {
109 	case EM_AARCH64:
110 	case EM_RISCV:
111 	case EM_S390:
112 		return "id";
113 	case EM_LOONGARCH:
114 	case EM_PPC:
115 	case EM_PPC64:
116 	case EM_X86_64:
117 	case EM_386:
118 		return "vcpu_id";
119 	default:
120 		pr_err("Unsupported kvm-stat host %d\n", e_machine);
121 		return NULL;
122 	}
123 }
124 
125 const char *kvm_exit_reason(uint16_t e_machine)
126 {
127 	switch (e_machine) {
128 	case EM_AARCH64:
129 		return "ret";
130 	case EM_LOONGARCH:
131 		return "reason";
132 	case EM_PPC:
133 	case EM_PPC64:
134 		return "trap";
135 	case EM_RISCV:
136 		return "scause";
137 	case EM_S390:
138 		return "icptcode";
139 	case EM_X86_64:
140 	case EM_386:
141 		return "exit_reason";
142 	default:
143 		pr_err("Unsupported kvm-stat host %d\n", e_machine);
144 		return NULL;
145 	}
146 }
147 
148 const char *kvm_entry_trace(uint16_t e_machine)
149 {
150 	switch (e_machine) {
151 	case EM_AARCH64:
152 	case EM_RISCV:
153 	case EM_X86_64:
154 	case EM_386:
155 		return "kvm:kvm_entry";
156 	case EM_LOONGARCH:
157 		return "kvm:kvm_enter";
158 	case EM_PPC:
159 	case EM_PPC64:
160 		return "kvm_hv:kvm_guest_enter";
161 	case EM_S390:
162 		return "kvm:kvm_s390_sie_enter";
163 	default:
164 		pr_err("Unsupported kvm-stat host %d\n", e_machine);
165 		return NULL;
166 	}
167 }
168 
169 const char *kvm_exit_trace(uint16_t e_machine)
170 {
171 	switch (e_machine) {
172 	case EM_AARCH64:
173 	case EM_LOONGARCH:
174 	case EM_RISCV:
175 	case EM_X86_64:
176 	case EM_386:
177 		return "kvm:kvm_exit";
178 	case EM_PPC:
179 	case EM_PPC64:
180 		return "kvm_hv:kvm_guest_exit";
181 	case EM_S390:
182 		return "kvm:kvm_s390_sie_exit";
183 	default:
184 		pr_err("Unsupported kvm-stat host %d\n", e_machine);
185 		return NULL;
186 	}
187 }
188 
189 const char * const *kvm_events_tp(uint16_t e_machine)
190 {
191 	switch (e_machine) {
192 	case EM_AARCH64:
193 		return __kvm_events_tp_arm64();
194 	case EM_LOONGARCH:
195 		return __kvm_events_tp_loongarch();
196 	case EM_PPC:
197 	case EM_PPC64:
198 		return __kvm_events_tp_powerpc();
199 	case EM_RISCV:
200 		return __kvm_events_tp_riscv();
201 	case EM_S390:
202 		return __kvm_events_tp_s390();
203 	case EM_X86_64:
204 	case EM_386:
205 		return __kvm_events_tp_x86();
206 	default:
207 		pr_err("Unsupported kvm-stat host %d\n", e_machine);
208 		return NULL;
209 	}
210 }
211 
212 const struct kvm_reg_events_ops *kvm_reg_events_ops(uint16_t e_machine)
213 {
214 	switch (e_machine) {
215 	case EM_AARCH64:
216 		return __kvm_reg_events_ops_arm64();
217 	case EM_LOONGARCH:
218 		return __kvm_reg_events_ops_loongarch();
219 	case EM_PPC:
220 	case EM_PPC64:
221 		return __kvm_reg_events_ops_powerpc();
222 	case EM_RISCV:
223 		return __kvm_reg_events_ops_riscv();
224 	case EM_S390:
225 		return __kvm_reg_events_ops_s390();
226 	case EM_X86_64:
227 	case EM_386:
228 		return __kvm_reg_events_ops_x86();
229 	default:
230 		pr_err("Unsupported kvm-stat host %d\n", e_machine);
231 		return NULL;
232 	}
233 }
234 
235 const char * const *kvm_skip_events(uint16_t e_machine)
236 {
237 	switch (e_machine) {
238 	case EM_AARCH64:
239 		return __kvm_skip_events_arm64();
240 	case EM_LOONGARCH:
241 		return __kvm_skip_events_loongarch();
242 	case EM_PPC:
243 	case EM_PPC64:
244 		return __kvm_skip_events_powerpc();
245 	case EM_RISCV:
246 		return __kvm_skip_events_riscv();
247 	case EM_S390:
248 		return __kvm_skip_events_s390();
249 	case EM_X86_64:
250 	case EM_386:
251 		return __kvm_skip_events_x86();
252 	default:
253 		pr_err("Unsupported kvm-stat host %d\n", e_machine);
254 		return NULL;
255 	}
256 }
257 
258 int kvm_add_default_arch_event(uint16_t e_machine, int *argc, const char **argv)
259 {
260 	switch (e_machine) {
261 	case EM_PPC:
262 	case EM_PPC64:
263 		return __kvm_add_default_arch_event_powerpc(argc, argv);
264 	case EM_X86_64:
265 	case EM_386:
266 		return __kvm_add_default_arch_event_x86(argc, argv);
267 	default:
268 		return 0;
269 	}
270 }
271