kvm-stat.c 5.7 KB

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