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