diff options
Diffstat (limited to 'tools/perf/builtin-kvm.c')
-rw-r--r-- | tools/perf/builtin-kvm.c | 113 |
1 files changed, 49 insertions, 64 deletions
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 43367eb00510..b65eb0507b38 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -376,7 +376,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread, | |||
376 | struct perf_sample *sample) | 376 | struct perf_sample *sample) |
377 | { | 377 | { |
378 | /* Only kvm_entry records vcpu id. */ | 378 | /* Only kvm_entry records vcpu id. */ |
379 | if (!thread->priv && kvm_entry_event(evsel)) { | 379 | if (!thread__priv(thread) && kvm_entry_event(evsel)) { |
380 | struct vcpu_event_record *vcpu_record; | 380 | struct vcpu_event_record *vcpu_record; |
381 | 381 | ||
382 | vcpu_record = zalloc(sizeof(*vcpu_record)); | 382 | vcpu_record = zalloc(sizeof(*vcpu_record)); |
@@ -386,10 +386,10 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread, | |||
386 | } | 386 | } |
387 | 387 | ||
388 | vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID); | 388 | vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID); |
389 | thread->priv = vcpu_record; | 389 | thread__set_priv(thread, vcpu_record); |
390 | } | 390 | } |
391 | 391 | ||
392 | return thread->priv; | 392 | return thread__priv(thread); |
393 | } | 393 | } |
394 | 394 | ||
395 | static bool handle_kvm_event(struct perf_kvm_stat *kvm, | 395 | static bool handle_kvm_event(struct perf_kvm_stat *kvm, |
@@ -543,14 +543,12 @@ static void print_vcpu_info(struct perf_kvm_stat *kvm) | |||
543 | 543 | ||
544 | pr_info("Analyze events for "); | 544 | pr_info("Analyze events for "); |
545 | 545 | ||
546 | if (kvm->live) { | 546 | if (kvm->opts.target.system_wide) |
547 | if (kvm->opts.target.system_wide) | 547 | pr_info("all VMs, "); |
548 | pr_info("all VMs, "); | 548 | else if (kvm->opts.target.pid) |
549 | else if (kvm->opts.target.pid) | 549 | pr_info("pid(s) %s, ", kvm->opts.target.pid); |
550 | pr_info("pid(s) %s, ", kvm->opts.target.pid); | 550 | else |
551 | else | 551 | pr_info("dazed and confused on what is monitored, "); |
552 | pr_info("dazed and confused on what is monitored, "); | ||
553 | } | ||
554 | 552 | ||
555 | if (vcpu == -1) | 553 | if (vcpu == -1) |
556 | pr_info("all VCPUs:\n\n"); | 554 | pr_info("all VCPUs:\n\n"); |
@@ -592,8 +590,8 @@ static void print_result(struct perf_kvm_stat *kvm) | |||
592 | pr_info("%9s ", "Samples%"); | 590 | pr_info("%9s ", "Samples%"); |
593 | 591 | ||
594 | pr_info("%9s ", "Time%"); | 592 | pr_info("%9s ", "Time%"); |
595 | pr_info("%10s ", "Min Time"); | 593 | pr_info("%11s ", "Min Time"); |
596 | pr_info("%10s ", "Max Time"); | 594 | pr_info("%11s ", "Max Time"); |
597 | pr_info("%16s ", "Avg time"); | 595 | pr_info("%16s ", "Avg time"); |
598 | pr_info("\n\n"); | 596 | pr_info("\n\n"); |
599 | 597 | ||
@@ -610,8 +608,8 @@ static void print_result(struct perf_kvm_stat *kvm) | |||
610 | pr_info("%10llu ", (unsigned long long)ecount); | 608 | pr_info("%10llu ", (unsigned long long)ecount); |
611 | pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100); | 609 | pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100); |
612 | pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100); | 610 | pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100); |
613 | pr_info("%8" PRIu64 "us ", min / 1000); | 611 | pr_info("%9.2fus ", (double)min / 1e3); |
614 | pr_info("%8" PRIu64 "us ", max / 1000); | 612 | pr_info("%9.2fus ", (double)max / 1e3); |
615 | pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3, | 613 | pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3, |
616 | kvm_event_rel_stddev(vcpu, event)); | 614 | kvm_event_rel_stddev(vcpu, event)); |
617 | pr_info("\n"); | 615 | pr_info("\n"); |
@@ -732,7 +730,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx, | |||
732 | return -1; | 730 | return -1; |
733 | } | 731 | } |
734 | 732 | ||
735 | err = perf_session_queue_event(kvm->session, event, &sample, 0); | 733 | err = perf_session_queue_event(kvm->session, event, &kvm->tool, &sample, 0); |
736 | /* | 734 | /* |
737 | * FIXME: Here we can't consume the event, as perf_session_queue_event will | 735 | * FIXME: Here we can't consume the event, as perf_session_queue_event will |
738 | * point to it, and it'll get possibly overwritten by the kernel. | 736 | * point to it, and it'll get possibly overwritten by the kernel. |
@@ -785,7 +783,7 @@ static int perf_kvm__mmap_read(struct perf_kvm_stat *kvm) | |||
785 | 783 | ||
786 | /* flush queue after each round in which we processed events */ | 784 | /* flush queue after each round in which we processed events */ |
787 | if (ntotal) { | 785 | if (ntotal) { |
788 | kvm->session->ordered_samples.next_flush = flush_time; | 786 | kvm->session->ordered_events.next_flush = flush_time; |
789 | err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session); | 787 | err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session); |
790 | if (err) { | 788 | if (err) { |
791 | if (kvm->lost_events) | 789 | if (kvm->lost_events) |
@@ -885,15 +883,11 @@ static int fd_set_nonblock(int fd) | |||
885 | return 0; | 883 | return 0; |
886 | } | 884 | } |
887 | 885 | ||
888 | static | 886 | static int perf_kvm__handle_stdin(void) |
889 | int perf_kvm__handle_stdin(struct termios *tc_now, struct termios *tc_save) | ||
890 | { | 887 | { |
891 | int c; | 888 | int c; |
892 | 889 | ||
893 | tcsetattr(0, TCSANOW, tc_now); | ||
894 | c = getc(stdin); | 890 | c = getc(stdin); |
895 | tcsetattr(0, TCSAFLUSH, tc_save); | ||
896 | |||
897 | if (c == 'q') | 891 | if (c == 'q') |
898 | return 1; | 892 | return 1; |
899 | 893 | ||
@@ -902,9 +896,8 @@ int perf_kvm__handle_stdin(struct termios *tc_now, struct termios *tc_save) | |||
902 | 896 | ||
903 | static int kvm_events_live_report(struct perf_kvm_stat *kvm) | 897 | static int kvm_events_live_report(struct perf_kvm_stat *kvm) |
904 | { | 898 | { |
905 | struct pollfd *pollfds = NULL; | 899 | int nr_stdin, ret, err = -EINVAL; |
906 | int nr_fds, nr_stdin, ret, err = -EINVAL; | 900 | struct termios save; |
907 | struct termios tc, save; | ||
908 | 901 | ||
909 | /* live flag must be set first */ | 902 | /* live flag must be set first */ |
910 | kvm->live = true; | 903 | kvm->live = true; |
@@ -919,41 +912,25 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm) | |||
919 | goto out; | 912 | goto out; |
920 | } | 913 | } |
921 | 914 | ||
915 | set_term_quiet_input(&save); | ||
922 | init_kvm_event_record(kvm); | 916 | init_kvm_event_record(kvm); |
923 | 917 | ||
924 | tcgetattr(0, &save); | ||
925 | tc = save; | ||
926 | tc.c_lflag &= ~(ICANON | ECHO); | ||
927 | tc.c_cc[VMIN] = 0; | ||
928 | tc.c_cc[VTIME] = 0; | ||
929 | |||
930 | signal(SIGINT, sig_handler); | 918 | signal(SIGINT, sig_handler); |
931 | signal(SIGTERM, sig_handler); | 919 | signal(SIGTERM, sig_handler); |
932 | 920 | ||
933 | /* copy pollfds -- need to add timerfd and stdin */ | ||
934 | nr_fds = kvm->evlist->nr_fds; | ||
935 | pollfds = zalloc(sizeof(struct pollfd) * (nr_fds + 2)); | ||
936 | if (!pollfds) { | ||
937 | err = -ENOMEM; | ||
938 | goto out; | ||
939 | } | ||
940 | memcpy(pollfds, kvm->evlist->pollfd, | ||
941 | sizeof(struct pollfd) * kvm->evlist->nr_fds); | ||
942 | |||
943 | /* add timer fd */ | 921 | /* add timer fd */ |
944 | if (perf_kvm__timerfd_create(kvm) < 0) { | 922 | if (perf_kvm__timerfd_create(kvm) < 0) { |
945 | err = -1; | 923 | err = -1; |
946 | goto out; | 924 | goto out; |
947 | } | 925 | } |
948 | 926 | ||
949 | pollfds[nr_fds].fd = kvm->timerfd; | 927 | if (perf_evlist__add_pollfd(kvm->evlist, kvm->timerfd) < 0) |
950 | pollfds[nr_fds].events = POLLIN; | 928 | goto out; |
951 | nr_fds++; | 929 | |
930 | nr_stdin = perf_evlist__add_pollfd(kvm->evlist, fileno(stdin)); | ||
931 | if (nr_stdin < 0) | ||
932 | goto out; | ||
952 | 933 | ||
953 | pollfds[nr_fds].fd = fileno(stdin); | ||
954 | pollfds[nr_fds].events = POLLIN; | ||
955 | nr_stdin = nr_fds; | ||
956 | nr_fds++; | ||
957 | if (fd_set_nonblock(fileno(stdin)) != 0) | 934 | if (fd_set_nonblock(fileno(stdin)) != 0) |
958 | goto out; | 935 | goto out; |
959 | 936 | ||
@@ -961,6 +938,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm) | |||
961 | perf_evlist__enable(kvm->evlist); | 938 | perf_evlist__enable(kvm->evlist); |
962 | 939 | ||
963 | while (!done) { | 940 | while (!done) { |
941 | struct fdarray *fda = &kvm->evlist->pollfd; | ||
964 | int rc; | 942 | int rc; |
965 | 943 | ||
966 | rc = perf_kvm__mmap_read(kvm); | 944 | rc = perf_kvm__mmap_read(kvm); |
@@ -971,11 +949,11 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm) | |||
971 | if (err) | 949 | if (err) |
972 | goto out; | 950 | goto out; |
973 | 951 | ||
974 | if (pollfds[nr_stdin].revents & POLLIN) | 952 | if (fda->entries[nr_stdin].revents & POLLIN) |
975 | done = perf_kvm__handle_stdin(&tc, &save); | 953 | done = perf_kvm__handle_stdin(); |
976 | 954 | ||
977 | if (!rc && !done) | 955 | if (!rc && !done) |
978 | err = poll(pollfds, nr_fds, 100); | 956 | err = fdarray__poll(fda, 100); |
979 | } | 957 | } |
980 | 958 | ||
981 | perf_evlist__disable(kvm->evlist); | 959 | perf_evlist__disable(kvm->evlist); |
@@ -989,7 +967,7 @@ out: | |||
989 | if (kvm->timerfd >= 0) | 967 | if (kvm->timerfd >= 0) |
990 | close(kvm->timerfd); | 968 | close(kvm->timerfd); |
991 | 969 | ||
992 | free(pollfds); | 970 | tcsetattr(0, TCSAFLUSH, &save); |
993 | return err; | 971 | return err; |
994 | } | 972 | } |
995 | 973 | ||
@@ -998,6 +976,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm) | |||
998 | int err, rc = -1; | 976 | int err, rc = -1; |
999 | struct perf_evsel *pos; | 977 | struct perf_evsel *pos; |
1000 | struct perf_evlist *evlist = kvm->evlist; | 978 | struct perf_evlist *evlist = kvm->evlist; |
979 | char sbuf[STRERR_BUFSIZE]; | ||
1001 | 980 | ||
1002 | perf_evlist__config(evlist, &kvm->opts); | 981 | perf_evlist__config(evlist, &kvm->opts); |
1003 | 982 | ||
@@ -1034,12 +1013,14 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm) | |||
1034 | 1013 | ||
1035 | err = perf_evlist__open(evlist); | 1014 | err = perf_evlist__open(evlist); |
1036 | if (err < 0) { | 1015 | if (err < 0) { |
1037 | printf("Couldn't create the events: %s\n", strerror(errno)); | 1016 | printf("Couldn't create the events: %s\n", |
1017 | strerror_r(errno, sbuf, sizeof(sbuf))); | ||
1038 | goto out; | 1018 | goto out; |
1039 | } | 1019 | } |
1040 | 1020 | ||
1041 | if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) { | 1021 | if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) { |
1042 | ui__error("Failed to mmap the events: %s\n", strerror(errno)); | 1022 | ui__error("Failed to mmap the events: %s\n", |
1023 | strerror_r(errno, sbuf, sizeof(sbuf))); | ||
1043 | perf_evlist__close(evlist); | 1024 | perf_evlist__close(evlist); |
1044 | goto out; | 1025 | goto out; |
1045 | } | 1026 | } |
@@ -1058,7 +1039,7 @@ static int read_events(struct perf_kvm_stat *kvm) | |||
1058 | struct perf_tool eops = { | 1039 | struct perf_tool eops = { |
1059 | .sample = process_sample_event, | 1040 | .sample = process_sample_event, |
1060 | .comm = perf_event__process_comm, | 1041 | .comm = perf_event__process_comm, |
1061 | .ordered_samples = true, | 1042 | .ordered_events = true, |
1062 | }; | 1043 | }; |
1063 | struct perf_data_file file = { | 1044 | struct perf_data_file file = { |
1064 | .path = kvm->file_name, | 1045 | .path = kvm->file_name, |
@@ -1069,9 +1050,11 @@ static int read_events(struct perf_kvm_stat *kvm) | |||
1069 | kvm->session = perf_session__new(&file, false, &kvm->tool); | 1050 | kvm->session = perf_session__new(&file, false, &kvm->tool); |
1070 | if (!kvm->session) { | 1051 | if (!kvm->session) { |
1071 | pr_err("Initializing perf session failed\n"); | 1052 | pr_err("Initializing perf session failed\n"); |
1072 | return -EINVAL; | 1053 | return -1; |
1073 | } | 1054 | } |
1074 | 1055 | ||
1056 | symbol__init(&kvm->session->header.env); | ||
1057 | |||
1075 | if (!perf_session__has_traces(kvm->session, "kvm record")) | 1058 | if (!perf_session__has_traces(kvm->session, "kvm record")) |
1076 | return -EINVAL; | 1059 | return -EINVAL; |
1077 | 1060 | ||
@@ -1088,8 +1071,8 @@ static int read_events(struct perf_kvm_stat *kvm) | |||
1088 | 1071 | ||
1089 | static int parse_target_str(struct perf_kvm_stat *kvm) | 1072 | static int parse_target_str(struct perf_kvm_stat *kvm) |
1090 | { | 1073 | { |
1091 | if (kvm->pid_str) { | 1074 | if (kvm->opts.target.pid) { |
1092 | kvm->pid_list = intlist__new(kvm->pid_str); | 1075 | kvm->pid_list = intlist__new(kvm->opts.target.pid); |
1093 | if (kvm->pid_list == NULL) { | 1076 | if (kvm->pid_list == NULL) { |
1094 | pr_err("Error parsing process id string\n"); | 1077 | pr_err("Error parsing process id string\n"); |
1095 | return -EINVAL; | 1078 | return -EINVAL; |
@@ -1191,7 +1174,7 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv) | |||
1191 | OPT_STRING('k', "key", &kvm->sort_key, "sort-key", | 1174 | OPT_STRING('k', "key", &kvm->sort_key, "sort-key", |
1192 | "key for sorting: sample(sort by samples number)" | 1175 | "key for sorting: sample(sort by samples number)" |
1193 | " time (sort by avg time)"), | 1176 | " time (sort by avg time)"), |
1194 | OPT_STRING('p', "pid", &kvm->pid_str, "pid", | 1177 | OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid", |
1195 | "analyze events only for given process id(s)"), | 1178 | "analyze events only for given process id(s)"), |
1196 | OPT_END() | 1179 | OPT_END() |
1197 | }; | 1180 | }; |
@@ -1201,8 +1184,6 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv) | |||
1201 | NULL | 1184 | NULL |
1202 | }; | 1185 | }; |
1203 | 1186 | ||
1204 | symbol__init(); | ||
1205 | |||
1206 | if (argc) { | 1187 | if (argc) { |
1207 | argc = parse_options(argc, argv, | 1188 | argc = parse_options(argc, argv, |
1208 | kvm_events_report_options, | 1189 | kvm_events_report_options, |
@@ -1212,6 +1193,9 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv) | |||
1212 | kvm_events_report_options); | 1193 | kvm_events_report_options); |
1213 | } | 1194 | } |
1214 | 1195 | ||
1196 | if (!kvm->opts.target.pid) | ||
1197 | kvm->opts.target.system_wide = true; | ||
1198 | |||
1215 | return kvm_events_report_vcpu(kvm); | 1199 | return kvm_events_report_vcpu(kvm); |
1216 | } | 1200 | } |
1217 | 1201 | ||
@@ -1311,7 +1295,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, | |||
1311 | kvm->tool.exit = perf_event__process_exit; | 1295 | kvm->tool.exit = perf_event__process_exit; |
1312 | kvm->tool.fork = perf_event__process_fork; | 1296 | kvm->tool.fork = perf_event__process_fork; |
1313 | kvm->tool.lost = process_lost_event; | 1297 | kvm->tool.lost = process_lost_event; |
1314 | kvm->tool.ordered_samples = true; | 1298 | kvm->tool.ordered_events = true; |
1315 | perf_tool__fill_defaults(&kvm->tool); | 1299 | perf_tool__fill_defaults(&kvm->tool); |
1316 | 1300 | ||
1317 | /* set defaults */ | 1301 | /* set defaults */ |
@@ -1322,7 +1306,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, | |||
1322 | kvm->opts.target.uid_str = NULL; | 1306 | kvm->opts.target.uid_str = NULL; |
1323 | kvm->opts.target.uid = UINT_MAX; | 1307 | kvm->opts.target.uid = UINT_MAX; |
1324 | 1308 | ||
1325 | symbol__init(); | 1309 | symbol__init(NULL); |
1326 | disable_buildid_cache(); | 1310 | disable_buildid_cache(); |
1327 | 1311 | ||
1328 | use_browser = 0; | 1312 | use_browser = 0; |
@@ -1369,11 +1353,12 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, | |||
1369 | */ | 1353 | */ |
1370 | kvm->session = perf_session__new(&file, false, &kvm->tool); | 1354 | kvm->session = perf_session__new(&file, false, &kvm->tool); |
1371 | if (kvm->session == NULL) { | 1355 | if (kvm->session == NULL) { |
1372 | err = -ENOMEM; | 1356 | err = -1; |
1373 | goto out; | 1357 | goto out; |
1374 | } | 1358 | } |
1375 | kvm->session->evlist = kvm->evlist; | 1359 | kvm->session->evlist = kvm->evlist; |
1376 | perf_session__set_id_hdr_size(kvm->session); | 1360 | perf_session__set_id_hdr_size(kvm->session); |
1361 | ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true); | ||
1377 | machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target, | 1362 | machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target, |
1378 | kvm->evlist->threads, false); | 1363 | kvm->evlist->threads, false); |
1379 | err = kvm_live_open_events(kvm); | 1364 | err = kvm_live_open_events(kvm); |