Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tools kvm: Use "cycles" to sample guest for "kvm record" on Intel

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>

authored by

Dapeng Mi and committed by
Arnaldo Carvalho de Melo
c1afca10 0f53264d

+61 -10
+51
tools/perf/arch/x86/util/kvm-stat.c
··· 3 3 #include <string.h> 4 4 #include "../../../util/kvm-stat.h" 5 5 #include "../../../util/evsel.h" 6 + #include "../../../util/env.h" 6 7 #include <asm/svm.h> 7 8 #include <asm/vmx.h> 8 9 #include <asm/kvm.h> 10 + #include <subcmd/parse-options.h> 9 11 10 12 define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS); 11 13 define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS); ··· 212 210 return -ENOTSUP; 213 211 214 212 return 0; 213 + } 214 + 215 + /* 216 + * After KVM supports PEBS for guest on Intel platforms 217 + * (https://lore.kernel.org/all/20220411101946.20262-1-likexu@tencent.com/), 218 + * host loses the capability to sample guest with PEBS since all PEBS related 219 + * MSRs are switched to guest value after vm-entry, like IA32_DS_AREA MSR is 220 + * switched to guest GVA at vm-entry. This would lead to "perf kvm record" 221 + * fails to sample guest on Intel platforms since "cycles:P" event is used to 222 + * sample guest by default. 223 + * 224 + * So, to avoid this issue explicitly use "cycles" instead of "cycles:P" event 225 + * by default to sample guest on Intel platforms. 226 + */ 227 + int kvm_add_default_arch_event(int *argc, const char **argv) 228 + { 229 + const char **tmp; 230 + bool event = false; 231 + int ret = 0, i, j = *argc; 232 + 233 + const struct option event_options[] = { 234 + OPT_BOOLEAN('e', "event", &event, NULL), 235 + OPT_BOOLEAN(0, "pfm-events", &event, NULL), 236 + OPT_END() 237 + }; 238 + 239 + if (!x86__is_intel_cpu()) 240 + return 0; 241 + 242 + tmp = calloc(j + 1, sizeof(char *)); 243 + if (!tmp) 244 + return -ENOMEM; 245 + 246 + for (i = 0; i < j; i++) 247 + tmp[i] = argv[i]; 248 + 249 + parse_options(j, tmp, event_options, NULL, PARSE_OPT_KEEP_UNKNOWN); 250 + if (!event) { 251 + argv[j++] = STRDUP_FAIL_EXIT("-e"); 252 + argv[j++] = STRDUP_FAIL_EXIT("cycles"); 253 + *argc += 2; 254 + } 255 + 256 + free(tmp); 257 + return 0; 258 + 259 + EXIT: 260 + free(tmp); 261 + return ret; 215 262 }
-10
tools/perf/builtin-kvm.c
··· 1636 1636 return ret; 1637 1637 } 1638 1638 1639 - #define STRDUP_FAIL_EXIT(s) \ 1640 - ({ char *_p; \ 1641 - _p = strdup(s); \ 1642 - if (!_p) { \ 1643 - ret = -ENOMEM; \ 1644 - goto EXIT; \ 1645 - } \ 1646 - _p; \ 1647 - }) 1648 - 1649 1639 int __weak setup_kvm_events_tp(struct perf_kvm_stat *kvm __maybe_unused) 1650 1640 { 1651 1641 return 0;
+10
tools/perf/util/kvm-stat.h
··· 190 190 #define kvm_info__zput(ki) do { } while (0) 191 191 #endif /* HAVE_KVM_STAT_SUPPORT */ 192 192 193 + #define STRDUP_FAIL_EXIT(s) \ 194 + ({ char *_p; \ 195 + _p = strdup(s); \ 196 + if (!_p) { \ 197 + ret = -ENOMEM; \ 198 + goto EXIT; \ 199 + } \ 200 + _p; \ 201 + }) 202 + 193 203 extern int kvm_add_default_arch_event(int *argc, const char **argv); 194 204 #endif /* __PERF_KVM_STAT_H */