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