From d12a0135e8e87c04dce78060c9d0899233f7d80e Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 1 Jul 2026 12:41:48 -0700 Subject: [PATCH] perf kvm: Factor out kvm_need_default_arch_event() The kvm_add_default_arch_event() has a similar logic in each arch to check if there's an existing command line option for events. Let's check it in the generic code and remove the duplication. Tested-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/builtin-kvm.c | 17 +++++--- .../util/kvm-stat-arch/kvm-stat-powerpc.c | 31 +++----------- tools/perf/util/kvm-stat-arch/kvm-stat-x86.c | 32 ++------------- tools/perf/util/kvm-stat.c | 41 +++++++++++++++++++ tools/perf/util/kvm-stat.h | 8 ++++ 5 files changed, 69 insertions(+), 60 deletions(-) diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 2c6aef1e13a0..2f00cc1fd1c7 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -2014,9 +2015,11 @@ static int __cmd_record(const char *file_name, int argc, const char **argv) BUG_ON(i + 2 != rec_argc); - ret = kvm_add_default_arch_event(EM_HOST, &i, rec_argv); - if (ret) - goto EXIT; + if (kvm_need_default_arch_event(EM_HOST, argc, argv)) { + ret = kvm_add_default_arch_event(EM_HOST, &i, rec_argv); + if (ret) + goto EXIT; + } ret = cmd_record(i, rec_argv); @@ -2101,9 +2104,11 @@ static int __cmd_top(int argc, const char **argv) BUG_ON(i != argc); - ret = kvm_add_default_arch_event(EM_HOST, &i, rec_argv); - if (ret) - goto EXIT; + if (kvm_need_default_arch_event(EM_HOST, argc, argv)) { + ret = kvm_add_default_arch_event(EM_HOST, &i, rec_argv); + if (ret) + goto EXIT; + } ret = cmd_top(i, rec_argv); diff --git a/tools/perf/util/kvm-stat-arch/kvm-stat-powerpc.c b/tools/perf/util/kvm-stat-arch/kvm-stat-powerpc.c index 96d9c4ae0209..8d4133c35c12 100644 --- a/tools/perf/util/kvm-stat-arch/kvm-stat-powerpc.c +++ b/tools/perf/util/kvm-stat-arch/kvm-stat-powerpc.c @@ -9,7 +9,6 @@ #include "book3s_hv_exits.h" #include "book3s_hcalls.h" -#include #define NR_TPS 4 @@ -177,35 +176,15 @@ int __cpu_isa_init_powerpc(struct perf_kvm_stat *kvm) */ int __kvm_add_default_arch_event_powerpc(int *argc, const char **argv) { - const char **tmp; - bool event = false; - int i, j = *argc; + int j = *argc; - const struct option event_options[] = { - OPT_BOOLEAN('e', "event", &event, NULL), - OPT_END() - }; - - tmp = calloc(j + 1, sizeof(char *)); - if (!tmp) + if (!perf_pmus__have_event("trace_imc", "trace_cycles")) return -EINVAL; - for (i = 0; i < j; i++) - tmp[i] = argv[i]; + argv[j++] = strdup("-e"); + argv[j++] = strdup("trace_imc/trace_cycles/"); + *argc += 2; - parse_options(j, tmp, event_options, NULL, PARSE_OPT_KEEP_UNKNOWN); - if (!event) { - if (perf_pmus__have_event("trace_imc", "trace_cycles")) { - argv[j++] = strdup("-e"); - argv[j++] = strdup("trace_imc/trace_cycles/"); - *argc += 2; - } else { - free(tmp); - return -EINVAL; - } - } - - free(tmp); return 0; } diff --git a/tools/perf/util/kvm-stat-arch/kvm-stat-x86.c b/tools/perf/util/kvm-stat-arch/kvm-stat-x86.c index 788d216f0852..46f9a0adcb60 100644 --- a/tools/perf/util/kvm-stat-arch/kvm-stat-x86.c +++ b/tools/perf/util/kvm-stat-arch/kvm-stat-x86.c @@ -7,7 +7,6 @@ #include "../../../arch/x86/include/uapi/asm/svm.h" #include "../../../arch/x86/include/uapi/asm/vmx.h" #include "../../../arch/x86/include/uapi/asm/kvm.h" -#include define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS); define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS); @@ -211,38 +210,15 @@ int __cpu_isa_init_x86(struct perf_kvm_stat *kvm, const char *cpuid) */ int __kvm_add_default_arch_event_x86(int *argc, const char **argv) { - const char **tmp; - bool event = false; - int ret = 0, i, j = *argc; + int ret = 0, j = *argc; - const struct option event_options[] = { - OPT_BOOLEAN('e', "event", &event, NULL), - OPT_BOOLEAN(0, "pfm-events", &event, NULL), - OPT_END() - }; + argv[j++] = STRDUP_FAIL_EXIT("-e"); + argv[j++] = STRDUP_FAIL_EXIT("cycles"); + *argc += 2; - if (!x86__is_intel_cpu()) - return 0; - - tmp = calloc(j + 1, sizeof(char *)); - if (!tmp) - return -ENOMEM; - - for (i = 0; i < j; i++) - tmp[i] = argv[i]; - - parse_options(j, tmp, event_options, NULL, PARSE_OPT_KEEP_UNKNOWN); - if (!event) { - argv[j++] = STRDUP_FAIL_EXIT("-e"); - argv[j++] = STRDUP_FAIL_EXIT("cycles"); - *argc += 2; - } - - free(tmp); return 0; EXIT: - free(tmp); return ret; } diff --git a/tools/perf/util/kvm-stat.c b/tools/perf/util/kvm-stat.c index 755ab659a05c..c571d2ed711a 100644 --- a/tools/perf/util/kvm-stat.c +++ b/tools/perf/util/kvm-stat.c @@ -1,8 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 #include "debug.h" +#include "env.h" #include "evsel.h" #include "kvm-stat.h" #include +#include bool kvm_exit_event(struct evsel *evsel) { @@ -268,3 +270,42 @@ int kvm_add_default_arch_event(uint16_t e_machine, int *argc, const char **argv) 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; +} diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h index cdbd921a555f..04f9f3193555 100644 --- a/tools/perf/util/kvm-stat.h +++ b/tools/perf/util/kvm-stat.h @@ -174,12 +174,20 @@ const char * const *__kvm_skip_events_riscv(void); const char * const *__kvm_skip_events_s390(void); const char * const *__kvm_skip_events_x86(void); +bool kvm_need_default_arch_event(uint16_t e_machine, int argc, const char **argv); int kvm_add_default_arch_event(uint16_t e_machine, int *argc, const char **argv); int __kvm_add_default_arch_event_powerpc(int *argc, const char **argv); int __kvm_add_default_arch_event_x86(int *argc, const char **argv); #else /* !HAVE_LIBTRACEEVENT */ +static inline bool kvm_need_default_arch_event(uint16_t e_machine __maybe_unused, + int argc __maybe_unused, + const char **argv __maybe_unused) +{ + return false; +} + static inline int kvm_add_default_arch_event(uint16_t e_machine __maybe_unused, int *argc __maybe_unused, const char **argv __maybe_unused)