hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/tools/perf/builtin-kvm.c
....@@ -2,24 +2,28 @@
22 #include "builtin.h"
33 #include "perf.h"
44
5
+#include "util/build-id.h"
56 #include "util/evsel.h"
67 #include "util/evlist.h"
8
+#include "util/mmap.h"
79 #include "util/term.h"
8
-#include "util/util.h"
9
-#include "util/cache.h"
1010 #include "util/symbol.h"
1111 #include "util/thread.h"
1212 #include "util/header.h"
1313 #include "util/session.h"
1414 #include "util/intlist.h"
15
+#include <subcmd/pager.h>
1516 #include <subcmd/parse-options.h>
1617 #include "util/trace-event.h"
1718 #include "util/debug.h"
1819 #include "util/tool.h"
1920 #include "util/stat.h"
21
+#include "util/synthetic-events.h"
2022 #include "util/top.h"
2123 #include "util/data.h"
2224 #include "util/ordered-events.h"
25
+#include "util/kvm-stat.h"
26
+#include "ui/ui.h"
2327
2428 #include <sys/prctl.h>
2529 #ifdef HAVE_TIMERFD_SUPPORT
....@@ -30,8 +34,11 @@
3034 #include <sys/stat.h>
3135 #include <fcntl.h>
3236
37
+#include <linux/err.h>
3338 #include <linux/kernel.h>
39
+#include <linux/string.h>
3440 #include <linux/time64.h>
41
+#include <linux/zalloc.h>
3542 #include <errno.h>
3643 #include <inttypes.h>
3744 #include <poll.h>
....@@ -39,6 +46,7 @@
3946 #include <semaphore.h>
4047 #include <signal.h>
4148 #include <math.h>
49
+#include <perf/mmap.h>
4250
4351 static const char *get_filename_for_perf_kvm(void)
4452 {
....@@ -55,22 +63,21 @@
5563 }
5664
5765 #ifdef HAVE_KVM_STAT_SUPPORT
58
-#include "util/kvm-stat.h"
5966
60
-void exit_event_get_key(struct perf_evsel *evsel,
67
+void exit_event_get_key(struct evsel *evsel,
6168 struct perf_sample *sample,
6269 struct event_key *key)
6370 {
6471 key->info = 0;
65
- key->key = perf_evsel__intval(evsel, sample, kvm_exit_reason);
72
+ key->key = evsel__intval(evsel, sample, kvm_exit_reason);
6673 }
6774
68
-bool kvm_exit_event(struct perf_evsel *evsel)
75
+bool kvm_exit_event(struct evsel *evsel)
6976 {
7077 return !strcmp(evsel->name, kvm_exit_trace);
7178 }
7279
73
-bool exit_event_begin(struct perf_evsel *evsel,
80
+bool exit_event_begin(struct evsel *evsel,
7481 struct perf_sample *sample, struct event_key *key)
7582 {
7683 if (kvm_exit_event(evsel)) {
....@@ -81,12 +88,12 @@
8188 return false;
8289 }
8390
84
-bool kvm_entry_event(struct perf_evsel *evsel)
91
+bool kvm_entry_event(struct evsel *evsel)
8592 {
8693 return !strcmp(evsel->name, kvm_entry_trace);
8794 }
8895
89
-bool exit_event_end(struct perf_evsel *evsel,
96
+bool exit_event_end(struct evsel *evsel,
9097 struct perf_sample *sample __maybe_unused,
9198 struct event_key *key __maybe_unused)
9299 {
....@@ -286,7 +293,7 @@
286293 }
287294
288295 static bool is_child_event(struct perf_kvm_stat *kvm,
289
- struct perf_evsel *evsel,
296
+ struct evsel *evsel,
290297 struct perf_sample *sample,
291298 struct event_key *key)
292299 {
....@@ -396,7 +403,7 @@
396403
397404 static
398405 struct vcpu_event_record *per_vcpu_record(struct thread *thread,
399
- struct perf_evsel *evsel,
406
+ struct evsel *evsel,
400407 struct perf_sample *sample)
401408 {
402409 /* Only kvm_entry records vcpu id. */
....@@ -409,8 +416,7 @@
409416 return NULL;
410417 }
411418
412
- vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample,
413
- vcpu_id_str);
419
+ vcpu_record->vcpu_id = evsel__intval(evsel, sample, vcpu_id_str);
414420 thread__set_priv(thread, vcpu_record);
415421 }
416422
....@@ -419,7 +425,7 @@
419425
420426 static bool handle_kvm_event(struct perf_kvm_stat *kvm,
421427 struct thread *thread,
422
- struct perf_evsel *evsel,
428
+ struct evsel *evsel,
423429 struct perf_sample *sample)
424430 {
425431 struct vcpu_event_record *vcpu_record;
....@@ -672,7 +678,7 @@
672678 static int process_sample_event(struct perf_tool *tool,
673679 union perf_event *event,
674680 struct perf_sample *sample,
675
- struct perf_evsel *evsel,
681
+ struct evsel *evsel,
676682 struct machine *machine)
677683 {
678684 int err = 0;
....@@ -744,23 +750,23 @@
744750 static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
745751 u64 *mmap_time)
746752 {
747
- struct perf_evlist *evlist = kvm->evlist;
753
+ struct evlist *evlist = kvm->evlist;
748754 union perf_event *event;
749
- struct perf_mmap *md;
755
+ struct mmap *md;
750756 u64 timestamp;
751757 s64 n = 0;
752758 int err;
753759
754760 *mmap_time = ULLONG_MAX;
755761 md = &evlist->mmap[idx];
756
- err = perf_mmap__read_init(md);
762
+ err = perf_mmap__read_init(&md->core);
757763 if (err < 0)
758764 return (err == -EAGAIN) ? 0 : -1;
759765
760
- while ((event = perf_mmap__read_event(md)) != NULL) {
766
+ while ((event = perf_mmap__read_event(&md->core)) != NULL) {
761767 err = perf_evlist__parse_sample_timestamp(evlist, event, &timestamp);
762768 if (err) {
763
- perf_mmap__consume(md);
769
+ perf_mmap__consume(&md->core);
764770 pr_err("Failed to parse sample\n");
765771 return -1;
766772 }
....@@ -770,7 +776,7 @@
770776 * FIXME: Here we can't consume the event, as perf_session__queue_event will
771777 * point to it, and it'll get possibly overwritten by the kernel.
772778 */
773
- perf_mmap__consume(md);
779
+ perf_mmap__consume(&md->core);
774780
775781 if (err) {
776782 pr_err("Failed to enqueue sample: %d\n", err);
....@@ -787,7 +793,7 @@
787793 break;
788794 }
789795
790
- perf_mmap__read_done(md);
796
+ perf_mmap__read_done(&md->core);
791797 return n;
792798 }
793799
....@@ -797,7 +803,7 @@
797803 s64 n, ntotal = 0;
798804 u64 flush_time = ULLONG_MAX, mmap_time;
799805
800
- for (i = 0; i < kvm->evlist->nr_mmaps; i++) {
806
+ for (i = 0; i < kvm->evlist->core.nr_mmaps; i++) {
801807 n = perf_kvm__mmap_read_idx(kvm, i, &mmap_time);
802808 if (n < 0)
803809 return -1;
....@@ -962,10 +968,10 @@
962968 goto out;
963969 }
964970
965
- if (perf_evlist__add_pollfd(kvm->evlist, kvm->timerfd) < 0)
971
+ if (evlist__add_pollfd(kvm->evlist, kvm->timerfd) < 0)
966972 goto out;
967973
968
- nr_stdin = perf_evlist__add_pollfd(kvm->evlist, fileno(stdin));
974
+ nr_stdin = evlist__add_pollfd(kvm->evlist, fileno(stdin));
969975 if (nr_stdin < 0)
970976 goto out;
971977
....@@ -973,10 +979,10 @@
973979 goto out;
974980
975981 /* everything is good - enable the events and process */
976
- perf_evlist__enable(kvm->evlist);
982
+ evlist__enable(kvm->evlist);
977983
978984 while (!done) {
979
- struct fdarray *fda = &kvm->evlist->pollfd;
985
+ struct fdarray *fda = &kvm->evlist->core.pollfd;
980986 int rc;
981987
982988 rc = perf_kvm__mmap_read(kvm);
....@@ -991,10 +997,10 @@
991997 done = perf_kvm__handle_stdin();
992998
993999 if (!rc && !done)
994
- err = fdarray__poll(fda, 100);
1000
+ err = evlist__poll(kvm->evlist, 100);
9951001 }
9961002
997
- perf_evlist__disable(kvm->evlist);
1003
+ evlist__disable(kvm->evlist);
9981004
9991005 if (err == 0) {
10001006 sort_result(kvm);
....@@ -1012,8 +1018,8 @@
10121018 static int kvm_live_open_events(struct perf_kvm_stat *kvm)
10131019 {
10141020 int err, rc = -1;
1015
- struct perf_evsel *pos;
1016
- struct perf_evlist *evlist = kvm->evlist;
1021
+ struct evsel *pos;
1022
+ struct evlist *evlist = kvm->evlist;
10171023 char sbuf[STRERR_BUFSIZE];
10181024
10191025 perf_evlist__config(evlist, &kvm->opts, NULL);
....@@ -1023,19 +1029,19 @@
10231029 * This command processes KVM tracepoints from host only
10241030 */
10251031 evlist__for_each_entry(evlist, pos) {
1026
- struct perf_event_attr *attr = &pos->attr;
1032
+ struct perf_event_attr *attr = &pos->core.attr;
10271033
10281034 /* make sure these *are* set */
1029
- perf_evsel__set_sample_bit(pos, TID);
1030
- perf_evsel__set_sample_bit(pos, TIME);
1031
- perf_evsel__set_sample_bit(pos, CPU);
1032
- perf_evsel__set_sample_bit(pos, RAW);
1035
+ evsel__set_sample_bit(pos, TID);
1036
+ evsel__set_sample_bit(pos, TIME);
1037
+ evsel__set_sample_bit(pos, CPU);
1038
+ evsel__set_sample_bit(pos, RAW);
10331039 /* make sure these are *not*; want as small a sample as possible */
1034
- perf_evsel__reset_sample_bit(pos, PERIOD);
1035
- perf_evsel__reset_sample_bit(pos, IP);
1036
- perf_evsel__reset_sample_bit(pos, CALLCHAIN);
1037
- perf_evsel__reset_sample_bit(pos, ADDR);
1038
- perf_evsel__reset_sample_bit(pos, READ);
1040
+ evsel__reset_sample_bit(pos, PERIOD);
1041
+ evsel__reset_sample_bit(pos, IP);
1042
+ evsel__reset_sample_bit(pos, CALLCHAIN);
1043
+ evsel__reset_sample_bit(pos, ADDR);
1044
+ evsel__reset_sample_bit(pos, READ);
10391045 attr->mmap = 0;
10401046 attr->comm = 0;
10411047 attr->task = 0;
....@@ -1049,17 +1055,17 @@
10491055 attr->disabled = 1;
10501056 }
10511057
1052
- err = perf_evlist__open(evlist);
1058
+ err = evlist__open(evlist);
10531059 if (err < 0) {
10541060 printf("Couldn't create the events: %s\n",
10551061 str_error_r(errno, sbuf, sizeof(sbuf)));
10561062 goto out;
10571063 }
10581064
1059
- if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages) < 0) {
1065
+ if (evlist__mmap(evlist, kvm->opts.mmap_pages) < 0) {
10601066 ui__error("Failed to mmap the events: %s\n",
10611067 str_error_r(errno, sbuf, sizeof(sbuf)));
1062
- perf_evlist__close(evlist);
1068
+ evlist__close(evlist);
10631069 goto out;
10641070 }
10651071
....@@ -1081,18 +1087,16 @@
10811087 .ordered_events = true,
10821088 };
10831089 struct perf_data file = {
1084
- .file = {
1085
- .path = kvm->file_name,
1086
- },
1087
- .mode = PERF_DATA_MODE_READ,
1088
- .force = kvm->force,
1090
+ .path = kvm->file_name,
1091
+ .mode = PERF_DATA_MODE_READ,
1092
+ .force = kvm->force,
10891093 };
10901094
10911095 kvm->tool = eops;
10921096 kvm->session = perf_session__new(&file, false, &kvm->tool);
1093
- if (!kvm->session) {
1097
+ if (IS_ERR(kvm->session)) {
10941098 pr_err("Initializing perf session failed\n");
1095
- return -1;
1099
+ return PTR_ERR(kvm->session);
10961100 }
10971101
10981102 symbol__init(&kvm->session->header.env);
....@@ -1286,14 +1290,14 @@
12861290 }
12871291
12881292 #ifdef HAVE_TIMERFD_SUPPORT
1289
-static struct perf_evlist *kvm_live_event_list(void)
1293
+static struct evlist *kvm_live_event_list(void)
12901294 {
1291
- struct perf_evlist *evlist;
1295
+ struct evlist *evlist;
12921296 char *tp, *name, *sys;
12931297 int err = -1;
12941298 const char * const *events_tp;
12951299
1296
- evlist = perf_evlist__new();
1300
+ evlist = evlist__new();
12971301 if (evlist == NULL)
12981302 return NULL;
12991303
....@@ -1315,7 +1319,7 @@
13151319 *name = '\0';
13161320 name++;
13171321
1318
- if (perf_evlist__add_newtp(evlist, sys, name, NULL)) {
1322
+ if (evlist__add_newtp(evlist, sys, name, NULL)) {
13191323 pr_err("Failed to add %s tracepoint to the list\n", *events_tp);
13201324 free(tp);
13211325 goto out;
....@@ -1328,7 +1332,7 @@
13281332
13291333 out:
13301334 if (err) {
1331
- perf_evlist__delete(evlist);
1335
+ evlist__delete(evlist);
13321336 evlist = NULL;
13331337 }
13341338
....@@ -1365,7 +1369,7 @@
13651369 "show events other than"
13661370 " HLT (x86 only) or Wait state (s390 only)"
13671371 " that take longer than duration usecs"),
1368
- OPT_UINTEGER(0, "proc-map-timeout", &kvm->opts.proc_map_timeout,
1372
+ OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout,
13691373 "per thread proc mmap processing timeout in ms"),
13701374 OPT_END()
13711375 };
....@@ -1395,7 +1399,6 @@
13951399 kvm->opts.target.uses_mmap = false;
13961400 kvm->opts.target.uid_str = NULL;
13971401 kvm->opts.target.uid = UINT_MAX;
1398
- kvm->opts.proc_map_timeout = 500;
13991402
14001403 symbol__init(NULL);
14011404 disable_buildid_cache();
....@@ -1446,16 +1449,15 @@
14461449 * perf session
14471450 */
14481451 kvm->session = perf_session__new(&data, false, &kvm->tool);
1449
- if (kvm->session == NULL) {
1450
- err = -1;
1452
+ if (IS_ERR(kvm->session)) {
1453
+ err = PTR_ERR(kvm->session);
14511454 goto out;
14521455 }
14531456 kvm->session->evlist = kvm->evlist;
14541457 perf_session__set_id_hdr_size(kvm->session);
14551458 ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true);
14561459 machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target,
1457
- kvm->evlist->threads, false,
1458
- kvm->opts.proc_map_timeout, 1);
1460
+ kvm->evlist->core.threads, false, 1);
14591461 err = kvm_live_open_events(kvm);
14601462 if (err)
14611463 goto out;
....@@ -1465,7 +1467,7 @@
14651467 out:
14661468 perf_session__delete(kvm->session);
14671469 kvm->session = NULL;
1468
- perf_evlist__delete(kvm->evlist);
1470
+ evlist__delete(kvm->evlist);
14691471
14701472 return err;
14711473 }
....@@ -1515,11 +1517,21 @@
15151517 }
15161518 #endif /* HAVE_KVM_STAT_SUPPORT */
15171519
1520
+int __weak kvm_add_default_arch_event(int *argc __maybe_unused,
1521
+ const char **argv __maybe_unused)
1522
+{
1523
+ return 0;
1524
+}
1525
+
15181526 static int __cmd_record(const char *file_name, int argc, const char **argv)
15191527 {
1520
- int rec_argc, i = 0, j;
1528
+ int rec_argc, i = 0, j, ret;
15211529 const char **rec_argv;
15221530
1531
+ ret = kvm_add_default_arch_event(&argc, argv);
1532
+ if (ret)
1533
+ return -EINVAL;
1534
+
15231535 rec_argc = argc + 2;
15241536 rec_argv = calloc(rec_argc + 1, sizeof(char *));
15251537 rec_argv[i++] = strdup("record");