.. | .. |
---|
2 | 2 | #include "builtin.h" |
---|
3 | 3 | #include "perf.h" |
---|
4 | 4 | |
---|
| 5 | +#include "util/build-id.h" |
---|
5 | 6 | #include "util/evsel.h" |
---|
6 | 7 | #include "util/evlist.h" |
---|
| 8 | +#include "util/mmap.h" |
---|
7 | 9 | #include "util/term.h" |
---|
8 | | -#include "util/util.h" |
---|
9 | | -#include "util/cache.h" |
---|
10 | 10 | #include "util/symbol.h" |
---|
11 | 11 | #include "util/thread.h" |
---|
12 | 12 | #include "util/header.h" |
---|
13 | 13 | #include "util/session.h" |
---|
14 | 14 | #include "util/intlist.h" |
---|
| 15 | +#include <subcmd/pager.h> |
---|
15 | 16 | #include <subcmd/parse-options.h> |
---|
16 | 17 | #include "util/trace-event.h" |
---|
17 | 18 | #include "util/debug.h" |
---|
18 | 19 | #include "util/tool.h" |
---|
19 | 20 | #include "util/stat.h" |
---|
| 21 | +#include "util/synthetic-events.h" |
---|
20 | 22 | #include "util/top.h" |
---|
21 | 23 | #include "util/data.h" |
---|
22 | 24 | #include "util/ordered-events.h" |
---|
| 25 | +#include "util/kvm-stat.h" |
---|
| 26 | +#include "ui/ui.h" |
---|
23 | 27 | |
---|
24 | 28 | #include <sys/prctl.h> |
---|
25 | 29 | #ifdef HAVE_TIMERFD_SUPPORT |
---|
.. | .. |
---|
30 | 34 | #include <sys/stat.h> |
---|
31 | 35 | #include <fcntl.h> |
---|
32 | 36 | |
---|
| 37 | +#include <linux/err.h> |
---|
33 | 38 | #include <linux/kernel.h> |
---|
| 39 | +#include <linux/string.h> |
---|
34 | 40 | #include <linux/time64.h> |
---|
| 41 | +#include <linux/zalloc.h> |
---|
35 | 42 | #include <errno.h> |
---|
36 | 43 | #include <inttypes.h> |
---|
37 | 44 | #include <poll.h> |
---|
.. | .. |
---|
39 | 46 | #include <semaphore.h> |
---|
40 | 47 | #include <signal.h> |
---|
41 | 48 | #include <math.h> |
---|
| 49 | +#include <perf/mmap.h> |
---|
42 | 50 | |
---|
43 | 51 | static const char *get_filename_for_perf_kvm(void) |
---|
44 | 52 | { |
---|
.. | .. |
---|
55 | 63 | } |
---|
56 | 64 | |
---|
57 | 65 | #ifdef HAVE_KVM_STAT_SUPPORT |
---|
58 | | -#include "util/kvm-stat.h" |
---|
59 | 66 | |
---|
60 | | -void exit_event_get_key(struct perf_evsel *evsel, |
---|
| 67 | +void exit_event_get_key(struct evsel *evsel, |
---|
61 | 68 | struct perf_sample *sample, |
---|
62 | 69 | struct event_key *key) |
---|
63 | 70 | { |
---|
64 | 71 | key->info = 0; |
---|
65 | | - key->key = perf_evsel__intval(evsel, sample, kvm_exit_reason); |
---|
| 72 | + key->key = evsel__intval(evsel, sample, kvm_exit_reason); |
---|
66 | 73 | } |
---|
67 | 74 | |
---|
68 | | -bool kvm_exit_event(struct perf_evsel *evsel) |
---|
| 75 | +bool kvm_exit_event(struct evsel *evsel) |
---|
69 | 76 | { |
---|
70 | 77 | return !strcmp(evsel->name, kvm_exit_trace); |
---|
71 | 78 | } |
---|
72 | 79 | |
---|
73 | | -bool exit_event_begin(struct perf_evsel *evsel, |
---|
| 80 | +bool exit_event_begin(struct evsel *evsel, |
---|
74 | 81 | struct perf_sample *sample, struct event_key *key) |
---|
75 | 82 | { |
---|
76 | 83 | if (kvm_exit_event(evsel)) { |
---|
.. | .. |
---|
81 | 88 | return false; |
---|
82 | 89 | } |
---|
83 | 90 | |
---|
84 | | -bool kvm_entry_event(struct perf_evsel *evsel) |
---|
| 91 | +bool kvm_entry_event(struct evsel *evsel) |
---|
85 | 92 | { |
---|
86 | 93 | return !strcmp(evsel->name, kvm_entry_trace); |
---|
87 | 94 | } |
---|
88 | 95 | |
---|
89 | | -bool exit_event_end(struct perf_evsel *evsel, |
---|
| 96 | +bool exit_event_end(struct evsel *evsel, |
---|
90 | 97 | struct perf_sample *sample __maybe_unused, |
---|
91 | 98 | struct event_key *key __maybe_unused) |
---|
92 | 99 | { |
---|
.. | .. |
---|
286 | 293 | } |
---|
287 | 294 | |
---|
288 | 295 | static bool is_child_event(struct perf_kvm_stat *kvm, |
---|
289 | | - struct perf_evsel *evsel, |
---|
| 296 | + struct evsel *evsel, |
---|
290 | 297 | struct perf_sample *sample, |
---|
291 | 298 | struct event_key *key) |
---|
292 | 299 | { |
---|
.. | .. |
---|
396 | 403 | |
---|
397 | 404 | static |
---|
398 | 405 | struct vcpu_event_record *per_vcpu_record(struct thread *thread, |
---|
399 | | - struct perf_evsel *evsel, |
---|
| 406 | + struct evsel *evsel, |
---|
400 | 407 | struct perf_sample *sample) |
---|
401 | 408 | { |
---|
402 | 409 | /* Only kvm_entry records vcpu id. */ |
---|
.. | .. |
---|
409 | 416 | return NULL; |
---|
410 | 417 | } |
---|
411 | 418 | |
---|
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); |
---|
414 | 420 | thread__set_priv(thread, vcpu_record); |
---|
415 | 421 | } |
---|
416 | 422 | |
---|
.. | .. |
---|
419 | 425 | |
---|
420 | 426 | static bool handle_kvm_event(struct perf_kvm_stat *kvm, |
---|
421 | 427 | struct thread *thread, |
---|
422 | | - struct perf_evsel *evsel, |
---|
| 428 | + struct evsel *evsel, |
---|
423 | 429 | struct perf_sample *sample) |
---|
424 | 430 | { |
---|
425 | 431 | struct vcpu_event_record *vcpu_record; |
---|
.. | .. |
---|
672 | 678 | static int process_sample_event(struct perf_tool *tool, |
---|
673 | 679 | union perf_event *event, |
---|
674 | 680 | struct perf_sample *sample, |
---|
675 | | - struct perf_evsel *evsel, |
---|
| 681 | + struct evsel *evsel, |
---|
676 | 682 | struct machine *machine) |
---|
677 | 683 | { |
---|
678 | 684 | int err = 0; |
---|
.. | .. |
---|
744 | 750 | static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx, |
---|
745 | 751 | u64 *mmap_time) |
---|
746 | 752 | { |
---|
747 | | - struct perf_evlist *evlist = kvm->evlist; |
---|
| 753 | + struct evlist *evlist = kvm->evlist; |
---|
748 | 754 | union perf_event *event; |
---|
749 | | - struct perf_mmap *md; |
---|
| 755 | + struct mmap *md; |
---|
750 | 756 | u64 timestamp; |
---|
751 | 757 | s64 n = 0; |
---|
752 | 758 | int err; |
---|
753 | 759 | |
---|
754 | 760 | *mmap_time = ULLONG_MAX; |
---|
755 | 761 | md = &evlist->mmap[idx]; |
---|
756 | | - err = perf_mmap__read_init(md); |
---|
| 762 | + err = perf_mmap__read_init(&md->core); |
---|
757 | 763 | if (err < 0) |
---|
758 | 764 | return (err == -EAGAIN) ? 0 : -1; |
---|
759 | 765 | |
---|
760 | | - while ((event = perf_mmap__read_event(md)) != NULL) { |
---|
| 766 | + while ((event = perf_mmap__read_event(&md->core)) != NULL) { |
---|
761 | 767 | err = perf_evlist__parse_sample_timestamp(evlist, event, ×tamp); |
---|
762 | 768 | if (err) { |
---|
763 | | - perf_mmap__consume(md); |
---|
| 769 | + perf_mmap__consume(&md->core); |
---|
764 | 770 | pr_err("Failed to parse sample\n"); |
---|
765 | 771 | return -1; |
---|
766 | 772 | } |
---|
.. | .. |
---|
770 | 776 | * FIXME: Here we can't consume the event, as perf_session__queue_event will |
---|
771 | 777 | * point to it, and it'll get possibly overwritten by the kernel. |
---|
772 | 778 | */ |
---|
773 | | - perf_mmap__consume(md); |
---|
| 779 | + perf_mmap__consume(&md->core); |
---|
774 | 780 | |
---|
775 | 781 | if (err) { |
---|
776 | 782 | pr_err("Failed to enqueue sample: %d\n", err); |
---|
.. | .. |
---|
787 | 793 | break; |
---|
788 | 794 | } |
---|
789 | 795 | |
---|
790 | | - perf_mmap__read_done(md); |
---|
| 796 | + perf_mmap__read_done(&md->core); |
---|
791 | 797 | return n; |
---|
792 | 798 | } |
---|
793 | 799 | |
---|
.. | .. |
---|
797 | 803 | s64 n, ntotal = 0; |
---|
798 | 804 | u64 flush_time = ULLONG_MAX, mmap_time; |
---|
799 | 805 | |
---|
800 | | - for (i = 0; i < kvm->evlist->nr_mmaps; i++) { |
---|
| 806 | + for (i = 0; i < kvm->evlist->core.nr_mmaps; i++) { |
---|
801 | 807 | n = perf_kvm__mmap_read_idx(kvm, i, &mmap_time); |
---|
802 | 808 | if (n < 0) |
---|
803 | 809 | return -1; |
---|
.. | .. |
---|
962 | 968 | goto out; |
---|
963 | 969 | } |
---|
964 | 970 | |
---|
965 | | - if (perf_evlist__add_pollfd(kvm->evlist, kvm->timerfd) < 0) |
---|
| 971 | + if (evlist__add_pollfd(kvm->evlist, kvm->timerfd) < 0) |
---|
966 | 972 | goto out; |
---|
967 | 973 | |
---|
968 | | - nr_stdin = perf_evlist__add_pollfd(kvm->evlist, fileno(stdin)); |
---|
| 974 | + nr_stdin = evlist__add_pollfd(kvm->evlist, fileno(stdin)); |
---|
969 | 975 | if (nr_stdin < 0) |
---|
970 | 976 | goto out; |
---|
971 | 977 | |
---|
.. | .. |
---|
973 | 979 | goto out; |
---|
974 | 980 | |
---|
975 | 981 | /* everything is good - enable the events and process */ |
---|
976 | | - perf_evlist__enable(kvm->evlist); |
---|
| 982 | + evlist__enable(kvm->evlist); |
---|
977 | 983 | |
---|
978 | 984 | while (!done) { |
---|
979 | | - struct fdarray *fda = &kvm->evlist->pollfd; |
---|
| 985 | + struct fdarray *fda = &kvm->evlist->core.pollfd; |
---|
980 | 986 | int rc; |
---|
981 | 987 | |
---|
982 | 988 | rc = perf_kvm__mmap_read(kvm); |
---|
.. | .. |
---|
991 | 997 | done = perf_kvm__handle_stdin(); |
---|
992 | 998 | |
---|
993 | 999 | if (!rc && !done) |
---|
994 | | - err = fdarray__poll(fda, 100); |
---|
| 1000 | + err = evlist__poll(kvm->evlist, 100); |
---|
995 | 1001 | } |
---|
996 | 1002 | |
---|
997 | | - perf_evlist__disable(kvm->evlist); |
---|
| 1003 | + evlist__disable(kvm->evlist); |
---|
998 | 1004 | |
---|
999 | 1005 | if (err == 0) { |
---|
1000 | 1006 | sort_result(kvm); |
---|
.. | .. |
---|
1012 | 1018 | static int kvm_live_open_events(struct perf_kvm_stat *kvm) |
---|
1013 | 1019 | { |
---|
1014 | 1020 | 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; |
---|
1017 | 1023 | char sbuf[STRERR_BUFSIZE]; |
---|
1018 | 1024 | |
---|
1019 | 1025 | perf_evlist__config(evlist, &kvm->opts, NULL); |
---|
.. | .. |
---|
1023 | 1029 | * This command processes KVM tracepoints from host only |
---|
1024 | 1030 | */ |
---|
1025 | 1031 | evlist__for_each_entry(evlist, pos) { |
---|
1026 | | - struct perf_event_attr *attr = &pos->attr; |
---|
| 1032 | + struct perf_event_attr *attr = &pos->core.attr; |
---|
1027 | 1033 | |
---|
1028 | 1034 | /* 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); |
---|
1033 | 1039 | /* 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); |
---|
1039 | 1045 | attr->mmap = 0; |
---|
1040 | 1046 | attr->comm = 0; |
---|
1041 | 1047 | attr->task = 0; |
---|
.. | .. |
---|
1049 | 1055 | attr->disabled = 1; |
---|
1050 | 1056 | } |
---|
1051 | 1057 | |
---|
1052 | | - err = perf_evlist__open(evlist); |
---|
| 1058 | + err = evlist__open(evlist); |
---|
1053 | 1059 | if (err < 0) { |
---|
1054 | 1060 | printf("Couldn't create the events: %s\n", |
---|
1055 | 1061 | str_error_r(errno, sbuf, sizeof(sbuf))); |
---|
1056 | 1062 | goto out; |
---|
1057 | 1063 | } |
---|
1058 | 1064 | |
---|
1059 | | - if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages) < 0) { |
---|
| 1065 | + if (evlist__mmap(evlist, kvm->opts.mmap_pages) < 0) { |
---|
1060 | 1066 | ui__error("Failed to mmap the events: %s\n", |
---|
1061 | 1067 | str_error_r(errno, sbuf, sizeof(sbuf))); |
---|
1062 | | - perf_evlist__close(evlist); |
---|
| 1068 | + evlist__close(evlist); |
---|
1063 | 1069 | goto out; |
---|
1064 | 1070 | } |
---|
1065 | 1071 | |
---|
.. | .. |
---|
1081 | 1087 | .ordered_events = true, |
---|
1082 | 1088 | }; |
---|
1083 | 1089 | 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, |
---|
1089 | 1093 | }; |
---|
1090 | 1094 | |
---|
1091 | 1095 | kvm->tool = eops; |
---|
1092 | 1096 | kvm->session = perf_session__new(&file, false, &kvm->tool); |
---|
1093 | | - if (!kvm->session) { |
---|
| 1097 | + if (IS_ERR(kvm->session)) { |
---|
1094 | 1098 | pr_err("Initializing perf session failed\n"); |
---|
1095 | | - return -1; |
---|
| 1099 | + return PTR_ERR(kvm->session); |
---|
1096 | 1100 | } |
---|
1097 | 1101 | |
---|
1098 | 1102 | symbol__init(&kvm->session->header.env); |
---|
.. | .. |
---|
1286 | 1290 | } |
---|
1287 | 1291 | |
---|
1288 | 1292 | #ifdef HAVE_TIMERFD_SUPPORT |
---|
1289 | | -static struct perf_evlist *kvm_live_event_list(void) |
---|
| 1293 | +static struct evlist *kvm_live_event_list(void) |
---|
1290 | 1294 | { |
---|
1291 | | - struct perf_evlist *evlist; |
---|
| 1295 | + struct evlist *evlist; |
---|
1292 | 1296 | char *tp, *name, *sys; |
---|
1293 | 1297 | int err = -1; |
---|
1294 | 1298 | const char * const *events_tp; |
---|
1295 | 1299 | |
---|
1296 | | - evlist = perf_evlist__new(); |
---|
| 1300 | + evlist = evlist__new(); |
---|
1297 | 1301 | if (evlist == NULL) |
---|
1298 | 1302 | return NULL; |
---|
1299 | 1303 | |
---|
.. | .. |
---|
1315 | 1319 | *name = '\0'; |
---|
1316 | 1320 | name++; |
---|
1317 | 1321 | |
---|
1318 | | - if (perf_evlist__add_newtp(evlist, sys, name, NULL)) { |
---|
| 1322 | + if (evlist__add_newtp(evlist, sys, name, NULL)) { |
---|
1319 | 1323 | pr_err("Failed to add %s tracepoint to the list\n", *events_tp); |
---|
1320 | 1324 | free(tp); |
---|
1321 | 1325 | goto out; |
---|
.. | .. |
---|
1328 | 1332 | |
---|
1329 | 1333 | out: |
---|
1330 | 1334 | if (err) { |
---|
1331 | | - perf_evlist__delete(evlist); |
---|
| 1335 | + evlist__delete(evlist); |
---|
1332 | 1336 | evlist = NULL; |
---|
1333 | 1337 | } |
---|
1334 | 1338 | |
---|
.. | .. |
---|
1365 | 1369 | "show events other than" |
---|
1366 | 1370 | " HLT (x86 only) or Wait state (s390 only)" |
---|
1367 | 1371 | " 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, |
---|
1369 | 1373 | "per thread proc mmap processing timeout in ms"), |
---|
1370 | 1374 | OPT_END() |
---|
1371 | 1375 | }; |
---|
.. | .. |
---|
1395 | 1399 | kvm->opts.target.uses_mmap = false; |
---|
1396 | 1400 | kvm->opts.target.uid_str = NULL; |
---|
1397 | 1401 | kvm->opts.target.uid = UINT_MAX; |
---|
1398 | | - kvm->opts.proc_map_timeout = 500; |
---|
1399 | 1402 | |
---|
1400 | 1403 | symbol__init(NULL); |
---|
1401 | 1404 | disable_buildid_cache(); |
---|
.. | .. |
---|
1446 | 1449 | * perf session |
---|
1447 | 1450 | */ |
---|
1448 | 1451 | 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); |
---|
1451 | 1454 | goto out; |
---|
1452 | 1455 | } |
---|
1453 | 1456 | kvm->session->evlist = kvm->evlist; |
---|
1454 | 1457 | perf_session__set_id_hdr_size(kvm->session); |
---|
1455 | 1458 | ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true); |
---|
1456 | 1459 | 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); |
---|
1459 | 1461 | err = kvm_live_open_events(kvm); |
---|
1460 | 1462 | if (err) |
---|
1461 | 1463 | goto out; |
---|
.. | .. |
---|
1465 | 1467 | out: |
---|
1466 | 1468 | perf_session__delete(kvm->session); |
---|
1467 | 1469 | kvm->session = NULL; |
---|
1468 | | - perf_evlist__delete(kvm->evlist); |
---|
| 1470 | + evlist__delete(kvm->evlist); |
---|
1469 | 1471 | |
---|
1470 | 1472 | return err; |
---|
1471 | 1473 | } |
---|
.. | .. |
---|
1515 | 1517 | } |
---|
1516 | 1518 | #endif /* HAVE_KVM_STAT_SUPPORT */ |
---|
1517 | 1519 | |
---|
| 1520 | +int __weak kvm_add_default_arch_event(int *argc __maybe_unused, |
---|
| 1521 | + const char **argv __maybe_unused) |
---|
| 1522 | +{ |
---|
| 1523 | + return 0; |
---|
| 1524 | +} |
---|
| 1525 | + |
---|
1518 | 1526 | static int __cmd_record(const char *file_name, int argc, const char **argv) |
---|
1519 | 1527 | { |
---|
1520 | | - int rec_argc, i = 0, j; |
---|
| 1528 | + int rec_argc, i = 0, j, ret; |
---|
1521 | 1529 | const char **rec_argv; |
---|
1522 | 1530 | |
---|
| 1531 | + ret = kvm_add_default_arch_event(&argc, argv); |
---|
| 1532 | + if (ret) |
---|
| 1533 | + return -EINVAL; |
---|
| 1534 | + |
---|
1523 | 1535 | rec_argc = argc + 2; |
---|
1524 | 1536 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); |
---|
1525 | 1537 | rec_argv[i++] = strdup("record"); |
---|