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