diff options
Diffstat (limited to 'tools/perf/builtin-kvm.c')
-rw-r--r-- | tools/perf/builtin-kvm.c | 57 |
1 files changed, 37 insertions, 20 deletions
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 935d52216c89..f8bf5f244d77 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -17,9 +17,12 @@ | |||
17 | #include "util/tool.h" | 17 | #include "util/tool.h" |
18 | #include "util/stat.h" | 18 | #include "util/stat.h" |
19 | #include "util/top.h" | 19 | #include "util/top.h" |
20 | #include "util/data.h" | ||
20 | 21 | ||
21 | #include <sys/prctl.h> | 22 | #include <sys/prctl.h> |
23 | #ifdef HAVE_TIMERFD_SUPPORT | ||
22 | #include <sys/timerfd.h> | 24 | #include <sys/timerfd.h> |
25 | #endif | ||
23 | 26 | ||
24 | #include <termios.h> | 27 | #include <termios.h> |
25 | #include <semaphore.h> | 28 | #include <semaphore.h> |
@@ -336,6 +339,7 @@ static void init_kvm_event_record(struct perf_kvm_stat *kvm) | |||
336 | INIT_LIST_HEAD(&kvm->kvm_events_cache[i]); | 339 | INIT_LIST_HEAD(&kvm->kvm_events_cache[i]); |
337 | } | 340 | } |
338 | 341 | ||
342 | #ifdef HAVE_TIMERFD_SUPPORT | ||
339 | static void clear_events_cache_stats(struct list_head *kvm_events_cache) | 343 | static void clear_events_cache_stats(struct list_head *kvm_events_cache) |
340 | { | 344 | { |
341 | struct list_head *head; | 345 | struct list_head *head; |
@@ -357,6 +361,7 @@ static void clear_events_cache_stats(struct list_head *kvm_events_cache) | |||
357 | } | 361 | } |
358 | } | 362 | } |
359 | } | 363 | } |
364 | #endif | ||
360 | 365 | ||
361 | static int kvm_events_hash_fn(u64 key) | 366 | static int kvm_events_hash_fn(u64 key) |
362 | { | 367 | { |
@@ -782,6 +787,7 @@ static void print_result(struct perf_kvm_stat *kvm) | |||
782 | pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events); | 787 | pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events); |
783 | } | 788 | } |
784 | 789 | ||
790 | #ifdef HAVE_TIMERFD_SUPPORT | ||
785 | static int process_lost_event(struct perf_tool *tool, | 791 | static int process_lost_event(struct perf_tool *tool, |
786 | union perf_event *event __maybe_unused, | 792 | union perf_event *event __maybe_unused, |
787 | struct perf_sample *sample __maybe_unused, | 793 | struct perf_sample *sample __maybe_unused, |
@@ -792,6 +798,7 @@ static int process_lost_event(struct perf_tool *tool, | |||
792 | kvm->lost_events++; | 798 | kvm->lost_events++; |
793 | return 0; | 799 | return 0; |
794 | } | 800 | } |
801 | #endif | ||
795 | 802 | ||
796 | static bool skip_sample(struct perf_kvm_stat *kvm, | 803 | static bool skip_sample(struct perf_kvm_stat *kvm, |
797 | struct perf_sample *sample) | 804 | struct perf_sample *sample) |
@@ -871,6 +878,7 @@ static bool verify_vcpu(int vcpu) | |||
871 | return true; | 878 | return true; |
872 | } | 879 | } |
873 | 880 | ||
881 | #ifdef HAVE_TIMERFD_SUPPORT | ||
874 | /* keeping the max events to a modest level to keep | 882 | /* keeping the max events to a modest level to keep |
875 | * the processing of samples per mmap smooth. | 883 | * the processing of samples per mmap smooth. |
876 | */ | 884 | */ |
@@ -888,11 +896,18 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx, | |||
888 | while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) { | 896 | while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) { |
889 | err = perf_evlist__parse_sample(kvm->evlist, event, &sample); | 897 | err = perf_evlist__parse_sample(kvm->evlist, event, &sample); |
890 | if (err) { | 898 | if (err) { |
899 | perf_evlist__mmap_consume(kvm->evlist, idx); | ||
891 | pr_err("Failed to parse sample\n"); | 900 | pr_err("Failed to parse sample\n"); |
892 | return -1; | 901 | return -1; |
893 | } | 902 | } |
894 | 903 | ||
895 | err = perf_session_queue_event(kvm->session, event, &sample, 0); | 904 | err = perf_session_queue_event(kvm->session, event, &sample, 0); |
905 | /* | ||
906 | * FIXME: Here we can't consume the event, as perf_session_queue_event will | ||
907 | * point to it, and it'll get possibly overwritten by the kernel. | ||
908 | */ | ||
909 | perf_evlist__mmap_consume(kvm->evlist, idx); | ||
910 | |||
896 | if (err) { | 911 | if (err) { |
897 | pr_err("Failed to enqueue sample: %d\n", err); | 912 | pr_err("Failed to enqueue sample: %d\n", err); |
898 | return -1; | 913 | return -1; |
@@ -1205,6 +1220,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm) | |||
1205 | out: | 1220 | out: |
1206 | return rc; | 1221 | return rc; |
1207 | } | 1222 | } |
1223 | #endif | ||
1208 | 1224 | ||
1209 | static int read_events(struct perf_kvm_stat *kvm) | 1225 | static int read_events(struct perf_kvm_stat *kvm) |
1210 | { | 1226 | { |
@@ -1215,10 +1231,13 @@ static int read_events(struct perf_kvm_stat *kvm) | |||
1215 | .comm = perf_event__process_comm, | 1231 | .comm = perf_event__process_comm, |
1216 | .ordered_samples = true, | 1232 | .ordered_samples = true, |
1217 | }; | 1233 | }; |
1234 | struct perf_data_file file = { | ||
1235 | .path = input_name, | ||
1236 | .mode = PERF_DATA_MODE_READ, | ||
1237 | }; | ||
1218 | 1238 | ||
1219 | kvm->tool = eops; | 1239 | kvm->tool = eops; |
1220 | kvm->session = perf_session__new(kvm->file_name, O_RDONLY, 0, false, | 1240 | kvm->session = perf_session__new(&file, false, &kvm->tool); |
1221 | &kvm->tool); | ||
1222 | if (!kvm->session) { | 1241 | if (!kvm->session) { |
1223 | pr_err("Initializing perf session failed\n"); | 1242 | pr_err("Initializing perf session failed\n"); |
1224 | return -EINVAL; | 1243 | return -EINVAL; |
@@ -1368,6 +1387,7 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv) | |||
1368 | return kvm_events_report_vcpu(kvm); | 1387 | return kvm_events_report_vcpu(kvm); |
1369 | } | 1388 | } |
1370 | 1389 | ||
1390 | #ifdef HAVE_TIMERFD_SUPPORT | ||
1371 | static struct perf_evlist *kvm_live_event_list(void) | 1391 | static struct perf_evlist *kvm_live_event_list(void) |
1372 | { | 1392 | { |
1373 | struct perf_evlist *evlist; | 1393 | struct perf_evlist *evlist; |
@@ -1426,8 +1446,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, | |||
1426 | const struct option live_options[] = { | 1446 | const struct option live_options[] = { |
1427 | OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid", | 1447 | OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid", |
1428 | "record events on existing process id"), | 1448 | "record events on existing process id"), |
1429 | OPT_UINTEGER('m', "mmap-pages", &kvm->opts.mmap_pages, | 1449 | OPT_CALLBACK('m', "mmap-pages", &kvm->opts.mmap_pages, "pages", |
1430 | "number of mmap data pages"), | 1450 | "number of mmap data pages", |
1451 | perf_evlist__parse_mmap_pages), | ||
1431 | OPT_INCR('v', "verbose", &verbose, | 1452 | OPT_INCR('v', "verbose", &verbose, |
1432 | "be more verbose (show counter open errors, etc)"), | 1453 | "be more verbose (show counter open errors, etc)"), |
1433 | OPT_BOOLEAN('a', "all-cpus", &kvm->opts.target.system_wide, | 1454 | OPT_BOOLEAN('a', "all-cpus", &kvm->opts.target.system_wide, |
@@ -1449,6 +1470,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, | |||
1449 | "perf kvm stat live [<options>]", | 1470 | "perf kvm stat live [<options>]", |
1450 | NULL | 1471 | NULL |
1451 | }; | 1472 | }; |
1473 | struct perf_data_file file = { | ||
1474 | .mode = PERF_DATA_MODE_WRITE, | ||
1475 | }; | ||
1452 | 1476 | ||
1453 | 1477 | ||
1454 | /* event handling */ | 1478 | /* event handling */ |
@@ -1486,13 +1510,13 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, | |||
1486 | /* | 1510 | /* |
1487 | * target related setups | 1511 | * target related setups |
1488 | */ | 1512 | */ |
1489 | err = perf_target__validate(&kvm->opts.target); | 1513 | err = target__validate(&kvm->opts.target); |
1490 | if (err) { | 1514 | if (err) { |
1491 | perf_target__strerror(&kvm->opts.target, err, errbuf, BUFSIZ); | 1515 | target__strerror(&kvm->opts.target, err, errbuf, BUFSIZ); |
1492 | ui__warning("%s", errbuf); | 1516 | ui__warning("%s", errbuf); |
1493 | } | 1517 | } |
1494 | 1518 | ||
1495 | if (perf_target__none(&kvm->opts.target)) | 1519 | if (target__none(&kvm->opts.target)) |
1496 | kvm->opts.target.system_wide = true; | 1520 | kvm->opts.target.system_wide = true; |
1497 | 1521 | ||
1498 | 1522 | ||
@@ -1513,25 +1537,15 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, | |||
1513 | /* | 1537 | /* |
1514 | * perf session | 1538 | * perf session |
1515 | */ | 1539 | */ |
1516 | kvm->session = perf_session__new(NULL, O_WRONLY, false, false, &kvm->tool); | 1540 | kvm->session = perf_session__new(&file, false, &kvm->tool); |
1517 | if (kvm->session == NULL) { | 1541 | if (kvm->session == NULL) { |
1518 | err = -ENOMEM; | 1542 | err = -ENOMEM; |
1519 | goto out; | 1543 | goto out; |
1520 | } | 1544 | } |
1521 | kvm->session->evlist = kvm->evlist; | 1545 | kvm->session->evlist = kvm->evlist; |
1522 | perf_session__set_id_hdr_size(kvm->session); | 1546 | perf_session__set_id_hdr_size(kvm->session); |
1523 | 1547 | machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target, | |
1524 | 1548 | kvm->evlist->threads, false); | |
1525 | if (perf_target__has_task(&kvm->opts.target)) | ||
1526 | perf_event__synthesize_thread_map(&kvm->tool, | ||
1527 | kvm->evlist->threads, | ||
1528 | perf_event__process, | ||
1529 | &kvm->session->machines.host); | ||
1530 | else | ||
1531 | perf_event__synthesize_threads(&kvm->tool, perf_event__process, | ||
1532 | &kvm->session->machines.host); | ||
1533 | |||
1534 | |||
1535 | err = kvm_live_open_events(kvm); | 1549 | err = kvm_live_open_events(kvm); |
1536 | if (err) | 1550 | if (err) |
1537 | goto out; | 1551 | goto out; |
@@ -1551,6 +1565,7 @@ out: | |||
1551 | 1565 | ||
1552 | return err; | 1566 | return err; |
1553 | } | 1567 | } |
1568 | #endif | ||
1554 | 1569 | ||
1555 | static void print_kvm_stat_usage(void) | 1570 | static void print_kvm_stat_usage(void) |
1556 | { | 1571 | { |
@@ -1589,8 +1604,10 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv) | |||
1589 | if (!strncmp(argv[1], "rep", 3)) | 1604 | if (!strncmp(argv[1], "rep", 3)) |
1590 | return kvm_events_report(&kvm, argc - 1 , argv + 1); | 1605 | return kvm_events_report(&kvm, argc - 1 , argv + 1); |
1591 | 1606 | ||
1607 | #ifdef HAVE_TIMERFD_SUPPORT | ||
1592 | if (!strncmp(argv[1], "live", 4)) | 1608 | if (!strncmp(argv[1], "live", 4)) |
1593 | return kvm_events_live(&kvm, argc - 1 , argv + 1); | 1609 | return kvm_events_live(&kvm, argc - 1 , argv + 1); |
1610 | #endif | ||
1594 | 1611 | ||
1595 | perf_stat: | 1612 | perf_stat: |
1596 | return cmd_stat(argc, argv, NULL); | 1613 | return cmd_stat(argc, argv, NULL); |