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