]> www.infradead.org Git - users/hch/misc.git/commitdiff
perf tools kvm: Use "cycles" to sample guest for "kvm record" on Intel
authorDapeng Mi <dapeng1.mi@linux.intel.com>
Fri, 19 Sep 2025 02:16:58 +0000 (10:16 +0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 2 Oct 2025 18:31:39 +0000 (15:31 -0300)
After KVM supports PEBS for guest on Intel platforms
(https://lore.kernel.org/all/20220411101946.20262-1-likexu@tencent.com/),
host loses the capability to sample guest with PEBS since all PEBS related
MSRs are switched to guest value after vm-entry, like IA32_DS_AREA MSR is
switched to guest GVA at vm-entry. This would lead to "perf kvm record"
fails to sample guest on Intel platforms since "cycles:P" event is used to
sample guest by default as below case shows.

sudo perf kvm record -a
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.787 MB perf.data.guest ]

So to ensure guest record can be sampled successfully, use "cycles"
instead of "cycles:P" to sample guest record by default on Intel
platforms. With this patch, the guest record can be sampled
successfully.

sudo perf kvm record -a
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.783 MB perf.data.guest (23 samples) ]

Fixes: cf8e55fe50df0c02 ("KVM: x86/pmu: Expose CPUIDs feature bits PDCM, DS, DTES64")
Reported-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Like Xu <likexu@tencent.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/arch/x86/util/kvm-stat.c
tools/perf/builtin-kvm.c
tools/perf/util/kvm-stat.h

index 424716518b755915b27a49bd565d468878221a6e..bff36f9345eac1407749c0c461c5643bfdb2ecf8 100644 (file)
@@ -3,9 +3,11 @@
 #include <string.h>
 #include "../../../util/kvm-stat.h"
 #include "../../../util/evsel.h"
+#include "../../../util/env.h"
 #include <asm/svm.h>
 #include <asm/vmx.h>
 #include <asm/kvm.h>
+#include <subcmd/parse-options.h>
 
 define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS);
 define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS);
@@ -211,3 +213,52 @@ int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid)
 
        return 0;
 }
+
+/*
+ * After KVM supports PEBS for guest on Intel platforms
+ * (https://lore.kernel.org/all/20220411101946.20262-1-likexu@tencent.com/),
+ * host loses the capability to sample guest with PEBS since all PEBS related
+ * MSRs are switched to guest value after vm-entry, like IA32_DS_AREA MSR is
+ * switched to guest GVA at vm-entry. This would lead to "perf kvm record"
+ * fails to sample guest on Intel platforms since "cycles:P" event is used to
+ * sample guest by default.
+ *
+ * So, to avoid this issue explicitly use "cycles" instead of "cycles:P" event
+ * by default to sample guest on Intel platforms.
+ */
+int kvm_add_default_arch_event(int *argc, const char **argv)
+{
+       const char **tmp;
+       bool event = false;
+       int ret = 0, i, j = *argc;
+
+       const struct option event_options[] = {
+               OPT_BOOLEAN('e', "event", &event, NULL),
+               OPT_BOOLEAN(0, "pfm-events", &event, NULL),
+               OPT_END()
+       };
+
+       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;
+}
index d297a7b2c088a6eb145ae0098f4d4beb91f53aa3..c0d62add499642f12115b2d91dbc83025a3154f3 100644 (file)
@@ -1636,16 +1636,6 @@ exit:
        return ret;
 }
 
-#define STRDUP_FAIL_EXIT(s)            \
-       ({      char *_p;               \
-               _p = strdup(s);         \
-               if (!_p) {              \
-                       ret = -ENOMEM;  \
-                       goto EXIT;      \
-               }                       \
-               _p;                     \
-       })
-
 int __weak setup_kvm_events_tp(struct perf_kvm_stat *kvm __maybe_unused)
 {
        return 0;
index 4249542544bbad312848d0e29351dd27036fea75..53db3d56108bd6e89faa526a8790f7bf9f349060 100644 (file)
@@ -190,5 +190,15 @@ static inline struct kvm_info *kvm_info__new(void)
 #define kvm_info__zput(ki) do { } while (0)
 #endif /* HAVE_KVM_STAT_SUPPORT */
 
+#define STRDUP_FAIL_EXIT(s)            \
+       ({      char *_p;               \
+               _p = strdup(s);         \
+               if (!_p) {              \
+                       ret = -ENOMEM;  \
+                       goto EXIT;      \
+               }                       \
+               _p;                     \
+       })
+
 extern int kvm_add_default_arch_event(int *argc, const char **argv);
 #endif /* __PERF_KVM_STAT_H */