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