summaryrefslogtreecommitdiffstats
path: root/tools/perf/util/kvm-stat.c
diff options
context:
space:
mode:
authorKees Cook <kees+treewide@kernel.org>2026-09-02 15:31:14 -0700
committerKees Cook <kees@kernel.org>2026-09-04 21:37:00 -0700
commit3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d (patch)
treec65086f9bdcd48c6360fb7cb4598bca084da1f32 /tools/perf/util/kvm-stat.c
downloadlinux-stable-3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d.tar.gz
linux-stable-3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d.zip
treewide: refresh kmalloc_obj() conversionsgrafted
This is another run of the Coccinelle script for converting kmalloc() family of allocations to kmalloc_obj() via the existing rules in scripts/coccinelle/api/kmalloc_objs.cocci This catches both the set of kmalloc() uses added since the first kmalloc_obj() conversions in v7.0 and adds a large group missed in the first pass due to Coccinelle not interacting well with the cleanup.h scoped_...() family of macros[1]. I worked around this with spatch's "--macro-file" argument to a file with all the scoped_...() macros mapped to Coccinelle's YACFE_ITERATOR[2] as that was the closest viable control flow indicator I could find. Build tested allmodconfig on x86, arm64, arm, loongarch, mips, powerpc, riscv, and s390 with no new warnings. Link: https://lore.kernel.org/lkml/202609021314.8A9C0B8@keescook/ [1] Link: https://github.com/coccinelle/coccinelle/blob/master/standard.h [2] Signed-off-by: Kees Cook <kees+treewide@kernel.org>
Diffstat (limited to 'tools/perf/util/kvm-stat.c')
-rw-r--r--tools/perf/util/kvm-stat.c311
1 files changed, 311 insertions, 0 deletions
diff --git a/tools/perf/util/kvm-stat.c b/tools/perf/util/kvm-stat.c
new file mode 100644
index 000000000..c571d2ed7
--- /dev/null
+++ b/tools/perf/util/kvm-stat.c
@@ -0,0 +1,311 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "debug.h"
+#include "env.h"
+#include "evsel.h"
+#include "kvm-stat.h"
+#include <dwarf-regs.h>
+#include <subcmd/parse-options.h>
+
+bool kvm_exit_event(struct evsel *evsel)
+{
+ uint16_t e_machine = evsel__e_machine(evsel, /*e_flags=*/NULL);
+
+ return evsel__name_is(evsel, kvm_exit_trace(e_machine));
+}
+
+void exit_event_get_key(struct perf_sample *sample,
+ struct event_key *key)
+{
+ uint16_t e_machine = evsel__e_machine(sample->evsel, /*e_flags=*/NULL);
+
+ key->info = 0;
+ key->key = perf_sample__intval(sample, kvm_exit_reason(e_machine));
+}
+
+
+bool exit_event_begin(struct perf_sample *sample, struct event_key *key)
+{
+ if (kvm_exit_event(sample->evsel)) {
+ exit_event_get_key(sample, key);
+ return true;
+ }
+
+ return false;
+}
+
+bool kvm_entry_event(struct evsel *evsel)
+{
+ uint16_t e_machine = evsel__e_machine(evsel, /*e_flags=*/NULL);
+
+ return evsel__name_is(evsel, kvm_entry_trace(e_machine));
+}
+
+bool exit_event_end(struct perf_sample *sample,
+ struct event_key *key __maybe_unused)
+{
+ return kvm_entry_event(sample->evsel);
+}
+
+static const char *get_exit_reason(struct perf_kvm_stat *kvm,
+ struct exit_reasons_table *tbl,
+ u64 exit_code)
+{
+ while (tbl->reason != NULL) {
+ if (tbl->exit_code == exit_code)
+ return tbl->reason;
+ tbl++;
+ }
+
+ pr_err("unknown kvm exit code:%lld on %s\n",
+ (unsigned long long)exit_code, kvm->exit_reasons_isa);
+ return "UNKNOWN";
+}
+
+void exit_event_decode_key(struct perf_kvm_stat *kvm,
+ struct event_key *key,
+ char *decode)
+{
+ const char *exit_reason = get_exit_reason(kvm, key->exit_reasons,
+ key->key);
+
+ scnprintf(decode, KVM_EVENT_NAME_LEN, "%s", exit_reason);
+}
+
+int setup_kvm_events_tp(struct perf_kvm_stat *kvm, uint16_t e_machine)
+{
+ switch (e_machine) {
+ case EM_PPC:
+ case EM_PPC64:
+ return __setup_kvm_events_tp_powerpc(kvm);
+ default:
+ return 0;
+ }
+}
+
+int cpu_isa_init(struct perf_kvm_stat *kvm, uint16_t e_machine, const char *cpuid)
+{
+ switch (e_machine) {
+ case EM_AARCH64:
+ return __cpu_isa_init_arm64(kvm);
+ case EM_LOONGARCH:
+ return __cpu_isa_init_loongarch(kvm);
+ case EM_PPC:
+ case EM_PPC64:
+ return __cpu_isa_init_powerpc(kvm);
+ case EM_RISCV:
+ return __cpu_isa_init_riscv(kvm);
+ case EM_S390:
+ return __cpu_isa_init_s390(kvm, cpuid);
+ case EM_X86_64:
+ case EM_386:
+ return __cpu_isa_init_x86(kvm, cpuid);
+ default:
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
+ return -1;
+ }
+}
+
+const char *vcpu_id_str(uint16_t e_machine)
+{
+ switch (e_machine) {
+ case EM_AARCH64:
+ case EM_RISCV:
+ case EM_S390:
+ return "id";
+ case EM_LOONGARCH:
+ case EM_PPC:
+ case EM_PPC64:
+ case EM_X86_64:
+ case EM_386:
+ return "vcpu_id";
+ default:
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
+ return NULL;
+ }
+}
+
+const char *kvm_exit_reason(uint16_t e_machine)
+{
+ switch (e_machine) {
+ case EM_AARCH64:
+ return "ret";
+ case EM_LOONGARCH:
+ return "reason";
+ case EM_PPC:
+ case EM_PPC64:
+ return "trap";
+ case EM_RISCV:
+ return "scause";
+ case EM_S390:
+ return "icptcode";
+ case EM_X86_64:
+ case EM_386:
+ return "exit_reason";
+ default:
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
+ return NULL;
+ }
+}
+
+const char *kvm_entry_trace(uint16_t e_machine)
+{
+ switch (e_machine) {
+ case EM_AARCH64:
+ case EM_RISCV:
+ case EM_X86_64:
+ case EM_386:
+ return "kvm:kvm_entry";
+ case EM_LOONGARCH:
+ return "kvm:kvm_enter";
+ case EM_PPC:
+ case EM_PPC64:
+ return "kvm_hv:kvm_guest_enter";
+ case EM_S390:
+ return "kvm:kvm_s390_sie_enter";
+ default:
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
+ return NULL;
+ }
+}
+
+const char *kvm_exit_trace(uint16_t e_machine)
+{
+ switch (e_machine) {
+ case EM_AARCH64:
+ case EM_LOONGARCH:
+ case EM_RISCV:
+ case EM_X86_64:
+ case EM_386:
+ return "kvm:kvm_exit";
+ case EM_PPC:
+ case EM_PPC64:
+ return "kvm_hv:kvm_guest_exit";
+ case EM_S390:
+ return "kvm:kvm_s390_sie_exit";
+ default:
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
+ return NULL;
+ }
+}
+
+const char * const *kvm_events_tp(uint16_t e_machine)
+{
+ switch (e_machine) {
+ case EM_AARCH64:
+ return __kvm_events_tp_arm64();
+ case EM_LOONGARCH:
+ return __kvm_events_tp_loongarch();
+ case EM_PPC:
+ case EM_PPC64:
+ return __kvm_events_tp_powerpc();
+ case EM_RISCV:
+ return __kvm_events_tp_riscv();
+ case EM_S390:
+ return __kvm_events_tp_s390();
+ case EM_X86_64:
+ case EM_386:
+ return __kvm_events_tp_x86();
+ default:
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
+ return NULL;
+ }
+}
+
+const struct kvm_reg_events_ops *kvm_reg_events_ops(uint16_t e_machine)
+{
+ switch (e_machine) {
+ case EM_AARCH64:
+ return __kvm_reg_events_ops_arm64();
+ case EM_LOONGARCH:
+ return __kvm_reg_events_ops_loongarch();
+ case EM_PPC:
+ case EM_PPC64:
+ return __kvm_reg_events_ops_powerpc();
+ case EM_RISCV:
+ return __kvm_reg_events_ops_riscv();
+ case EM_S390:
+ return __kvm_reg_events_ops_s390();
+ case EM_X86_64:
+ case EM_386:
+ return __kvm_reg_events_ops_x86();
+ default:
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
+ return NULL;
+ }
+}
+
+const char * const *kvm_skip_events(uint16_t e_machine)
+{
+ switch (e_machine) {
+ case EM_AARCH64:
+ return __kvm_skip_events_arm64();
+ case EM_LOONGARCH:
+ return __kvm_skip_events_loongarch();
+ case EM_PPC:
+ case EM_PPC64:
+ return __kvm_skip_events_powerpc();
+ case EM_RISCV:
+ return __kvm_skip_events_riscv();
+ case EM_S390:
+ return __kvm_skip_events_s390();
+ case EM_X86_64:
+ case EM_386:
+ return __kvm_skip_events_x86();
+ default:
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
+ return NULL;
+ }
+}
+
+int kvm_add_default_arch_event(uint16_t e_machine, int *argc, const char **argv)
+{
+ switch (e_machine) {
+ case EM_PPC:
+ case EM_PPC64:
+ return __kvm_add_default_arch_event_powerpc(argc, argv);
+ case EM_X86_64:
+ case EM_386:
+ return __kvm_add_default_arch_event_x86(argc, argv);
+ default:
+ return 0;
+ }
+}
+
+bool kvm_need_default_arch_event(uint16_t e_machine, int argc, const char **argv)
+{
+ const char **tmp_argv;
+ bool event = false;
+ int i;
+
+ const struct option event_options[] = {
+ OPT_BOOLEAN('e', "event", &event, NULL),
+ OPT_BOOLEAN(0, "pfm-events", &event, NULL),
+ OPT_END()
+ };
+
+ switch (e_machine) {
+ case EM_PPC:
+ case EM_PPC64:
+ break;
+ case EM_X86_64:
+ case EM_386:
+ if (!x86__is_intel_cpu())
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ /* parse_options() may change the argv, let's make a copy */
+ tmp_argv = calloc(argc + 1, sizeof(char *));
+ if (!tmp_argv)
+ return false;
+
+ for (i = 0; i < argc; i++)
+ tmp_argv[i] = argv[i];
+
+ parse_options(argc, tmp_argv, event_options, NULL, PARSE_OPT_KEEP_UNKNOWN);
+ free(tmp_argv);
+
+ return !event;
+}