diff options
-rw-r--r-- | tools/perf/builtin-kvm.c | 111 |
1 files changed, 60 insertions, 51 deletions
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index e013bdb5e24a..9fa45fa13bd6 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -58,7 +58,7 @@ struct kvm_event_key { | |||
58 | }; | 58 | }; |
59 | 59 | ||
60 | 60 | ||
61 | struct perf_kvm; | 61 | struct perf_kvm_stat; |
62 | 62 | ||
63 | struct kvm_events_ops { | 63 | struct kvm_events_ops { |
64 | bool (*is_begin_event)(struct perf_evsel *evsel, | 64 | bool (*is_begin_event)(struct perf_evsel *evsel, |
@@ -66,7 +66,7 @@ struct kvm_events_ops { | |||
66 | struct event_key *key); | 66 | struct event_key *key); |
67 | bool (*is_end_event)(struct perf_evsel *evsel, | 67 | bool (*is_end_event)(struct perf_evsel *evsel, |
68 | struct perf_sample *sample, struct event_key *key); | 68 | struct perf_sample *sample, struct event_key *key); |
69 | void (*decode_key)(struct perf_kvm *kvm, struct event_key *key, | 69 | void (*decode_key)(struct perf_kvm_stat *kvm, struct event_key *key, |
70 | char decode[20]); | 70 | char decode[20]); |
71 | const char *name; | 71 | const char *name; |
72 | }; | 72 | }; |
@@ -79,7 +79,7 @@ struct exit_reasons_table { | |||
79 | #define EVENTS_BITS 12 | 79 | #define EVENTS_BITS 12 |
80 | #define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS) | 80 | #define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS) |
81 | 81 | ||
82 | struct perf_kvm { | 82 | struct perf_kvm_stat { |
83 | struct perf_tool tool; | 83 | struct perf_tool tool; |
84 | struct perf_session *session; | 84 | struct perf_session *session; |
85 | 85 | ||
@@ -146,7 +146,7 @@ static struct exit_reasons_table svm_exit_reasons[] = { | |||
146 | SVM_EXIT_REASONS | 146 | SVM_EXIT_REASONS |
147 | }; | 147 | }; |
148 | 148 | ||
149 | static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code) | 149 | static const char *get_exit_reason(struct perf_kvm_stat *kvm, u64 exit_code) |
150 | { | 150 | { |
151 | int i = kvm->exit_reasons_size; | 151 | int i = kvm->exit_reasons_size; |
152 | struct exit_reasons_table *tbl = kvm->exit_reasons; | 152 | struct exit_reasons_table *tbl = kvm->exit_reasons; |
@@ -162,7 +162,7 @@ static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code) | |||
162 | return "UNKNOWN"; | 162 | return "UNKNOWN"; |
163 | } | 163 | } |
164 | 164 | ||
165 | static void exit_event_decode_key(struct perf_kvm *kvm, | 165 | static void exit_event_decode_key(struct perf_kvm_stat *kvm, |
166 | struct event_key *key, | 166 | struct event_key *key, |
167 | char decode[20]) | 167 | char decode[20]) |
168 | { | 168 | { |
@@ -228,7 +228,7 @@ static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample, | |||
228 | return false; | 228 | return false; |
229 | } | 229 | } |
230 | 230 | ||
231 | static void mmio_event_decode_key(struct perf_kvm *kvm __maybe_unused, | 231 | static void mmio_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, |
232 | struct event_key *key, | 232 | struct event_key *key, |
233 | char decode[20]) | 233 | char decode[20]) |
234 | { | 234 | { |
@@ -271,7 +271,7 @@ static bool ioport_event_end(struct perf_evsel *evsel, | |||
271 | return kvm_entry_event(evsel); | 271 | return kvm_entry_event(evsel); |
272 | } | 272 | } |
273 | 273 | ||
274 | static void ioport_event_decode_key(struct perf_kvm *kvm __maybe_unused, | 274 | static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, |
275 | struct event_key *key, | 275 | struct event_key *key, |
276 | char decode[20]) | 276 | char decode[20]) |
277 | { | 277 | { |
@@ -286,7 +286,7 @@ static struct kvm_events_ops ioport_events = { | |||
286 | .name = "IO Port Access" | 286 | .name = "IO Port Access" |
287 | }; | 287 | }; |
288 | 288 | ||
289 | static bool register_kvm_events_ops(struct perf_kvm *kvm) | 289 | static bool register_kvm_events_ops(struct perf_kvm_stat *kvm) |
290 | { | 290 | { |
291 | bool ret = true; | 291 | bool ret = true; |
292 | 292 | ||
@@ -311,7 +311,7 @@ struct vcpu_event_record { | |||
311 | }; | 311 | }; |
312 | 312 | ||
313 | 313 | ||
314 | static void init_kvm_event_record(struct perf_kvm *kvm) | 314 | static void init_kvm_event_record(struct perf_kvm_stat *kvm) |
315 | { | 315 | { |
316 | int i; | 316 | int i; |
317 | 317 | ||
@@ -360,7 +360,7 @@ static struct kvm_event *kvm_alloc_init_event(struct event_key *key) | |||
360 | return event; | 360 | return event; |
361 | } | 361 | } |
362 | 362 | ||
363 | static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm, | 363 | static struct kvm_event *find_create_kvm_event(struct perf_kvm_stat *kvm, |
364 | struct event_key *key) | 364 | struct event_key *key) |
365 | { | 365 | { |
366 | struct kvm_event *event; | 366 | struct kvm_event *event; |
@@ -381,7 +381,7 @@ static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm, | |||
381 | return event; | 381 | return event; |
382 | } | 382 | } |
383 | 383 | ||
384 | static bool handle_begin_event(struct perf_kvm *kvm, | 384 | static bool handle_begin_event(struct perf_kvm_stat *kvm, |
385 | struct vcpu_event_record *vcpu_record, | 385 | struct vcpu_event_record *vcpu_record, |
386 | struct event_key *key, u64 timestamp) | 386 | struct event_key *key, u64 timestamp) |
387 | { | 387 | { |
@@ -425,7 +425,7 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id, | |||
425 | return true; | 425 | return true; |
426 | } | 426 | } |
427 | 427 | ||
428 | static bool handle_end_event(struct perf_kvm *kvm, | 428 | static bool handle_end_event(struct perf_kvm_stat *kvm, |
429 | struct vcpu_event_record *vcpu_record, | 429 | struct vcpu_event_record *vcpu_record, |
430 | struct event_key *key, | 430 | struct event_key *key, |
431 | u64 timestamp) | 431 | u64 timestamp) |
@@ -486,7 +486,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread, | |||
486 | return thread->priv; | 486 | return thread->priv; |
487 | } | 487 | } |
488 | 488 | ||
489 | static bool handle_kvm_event(struct perf_kvm *kvm, | 489 | static bool handle_kvm_event(struct perf_kvm_stat *kvm, |
490 | struct thread *thread, | 490 | struct thread *thread, |
491 | struct perf_evsel *evsel, | 491 | struct perf_evsel *evsel, |
492 | struct perf_sample *sample) | 492 | struct perf_sample *sample) |
@@ -541,7 +541,7 @@ static struct kvm_event_key keys[] = { | |||
541 | { NULL, NULL } | 541 | { NULL, NULL } |
542 | }; | 542 | }; |
543 | 543 | ||
544 | static bool select_key(struct perf_kvm *kvm) | 544 | static bool select_key(struct perf_kvm_stat *kvm) |
545 | { | 545 | { |
546 | int i; | 546 | int i; |
547 | 547 | ||
@@ -577,7 +577,8 @@ static void insert_to_result(struct rb_root *result, struct kvm_event *event, | |||
577 | rb_insert_color(&event->rb, result); | 577 | rb_insert_color(&event->rb, result); |
578 | } | 578 | } |
579 | 579 | ||
580 | static void update_total_count(struct perf_kvm *kvm, struct kvm_event *event) | 580 | static void |
581 | update_total_count(struct perf_kvm_stat *kvm, struct kvm_event *event) | ||
581 | { | 582 | { |
582 | int vcpu = kvm->trace_vcpu; | 583 | int vcpu = kvm->trace_vcpu; |
583 | 584 | ||
@@ -590,7 +591,7 @@ static bool event_is_valid(struct kvm_event *event, int vcpu) | |||
590 | return !!get_event_count(event, vcpu); | 591 | return !!get_event_count(event, vcpu); |
591 | } | 592 | } |
592 | 593 | ||
593 | static void sort_result(struct perf_kvm *kvm) | 594 | static void sort_result(struct perf_kvm_stat *kvm) |
594 | { | 595 | { |
595 | unsigned int i; | 596 | unsigned int i; |
596 | int vcpu = kvm->trace_vcpu; | 597 | int vcpu = kvm->trace_vcpu; |
@@ -627,7 +628,7 @@ static void print_vcpu_info(int vcpu) | |||
627 | pr_info("VCPU %d:\n\n", vcpu); | 628 | pr_info("VCPU %d:\n\n", vcpu); |
628 | } | 629 | } |
629 | 630 | ||
630 | static void print_result(struct perf_kvm *kvm) | 631 | static void print_result(struct perf_kvm_stat *kvm) |
631 | { | 632 | { |
632 | char decode[20]; | 633 | char decode[20]; |
633 | struct kvm_event *event; | 634 | struct kvm_event *event; |
@@ -670,7 +671,8 @@ static int process_sample_event(struct perf_tool *tool, | |||
670 | struct machine *machine) | 671 | struct machine *machine) |
671 | { | 672 | { |
672 | struct thread *thread = machine__findnew_thread(machine, sample->tid); | 673 | struct thread *thread = machine__findnew_thread(machine, sample->tid); |
673 | struct perf_kvm *kvm = container_of(tool, struct perf_kvm, tool); | 674 | struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat, |
675 | tool); | ||
674 | 676 | ||
675 | if (thread == NULL) { | 677 | if (thread == NULL) { |
676 | pr_debug("problem processing %d event, skipping it.\n", | 678 | pr_debug("problem processing %d event, skipping it.\n", |
@@ -701,7 +703,7 @@ static int get_cpu_isa(struct perf_session *session) | |||
701 | return isa; | 703 | return isa; |
702 | } | 704 | } |
703 | 705 | ||
704 | static int read_events(struct perf_kvm *kvm) | 706 | static int read_events(struct perf_kvm_stat *kvm) |
705 | { | 707 | { |
706 | int ret; | 708 | int ret; |
707 | 709 | ||
@@ -750,7 +752,7 @@ static bool verify_vcpu(int vcpu) | |||
750 | return true; | 752 | return true; |
751 | } | 753 | } |
752 | 754 | ||
753 | static int kvm_events_report_vcpu(struct perf_kvm *kvm) | 755 | static int kvm_events_report_vcpu(struct perf_kvm_stat *kvm) |
754 | { | 756 | { |
755 | int ret = -EINVAL; | 757 | int ret = -EINVAL; |
756 | int vcpu = kvm->trace_vcpu; | 758 | int vcpu = kvm->trace_vcpu; |
@@ -798,7 +800,8 @@ static const char * const record_args[] = { | |||
798 | _p; \ | 800 | _p; \ |
799 | }) | 801 | }) |
800 | 802 | ||
801 | static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv) | 803 | static int |
804 | kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv) | ||
802 | { | 805 | { |
803 | unsigned int rec_argc, i, j; | 806 | unsigned int rec_argc, i, j; |
804 | const char **rec_argv; | 807 | const char **rec_argv; |
@@ -821,7 +824,8 @@ static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv) | |||
821 | return cmd_record(i, rec_argv, NULL); | 824 | return cmd_record(i, rec_argv, NULL); |
822 | } | 825 | } |
823 | 826 | ||
824 | static int kvm_events_report(struct perf_kvm *kvm, int argc, const char **argv) | 827 | static int |
828 | kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv) | ||
825 | { | 829 | { |
826 | const struct option kvm_events_report_options[] = { | 830 | const struct option kvm_events_report_options[] = { |
827 | OPT_STRING(0, "event", &kvm->report_event, "report event", | 831 | OPT_STRING(0, "event", &kvm->report_event, "report event", |
@@ -864,24 +868,36 @@ static void print_kvm_stat_usage(void) | |||
864 | printf("\nOtherwise, it is the alias of 'perf stat':\n"); | 868 | printf("\nOtherwise, it is the alias of 'perf stat':\n"); |
865 | } | 869 | } |
866 | 870 | ||
867 | static int kvm_cmd_stat(struct perf_kvm *kvm, int argc, const char **argv) | 871 | static int kvm_cmd_stat(const char *file_name, int argc, const char **argv) |
868 | { | 872 | { |
873 | struct perf_kvm_stat kvm = { | ||
874 | .file_name = file_name, | ||
875 | |||
876 | .trace_vcpu = -1, | ||
877 | .report_event = "vmexit", | ||
878 | .sort_key = "sample", | ||
879 | |||
880 | .exit_reasons = svm_exit_reasons, | ||
881 | .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons), | ||
882 | .exit_reasons_isa = "SVM", | ||
883 | }; | ||
884 | |||
869 | if (argc == 1) { | 885 | if (argc == 1) { |
870 | print_kvm_stat_usage(); | 886 | print_kvm_stat_usage(); |
871 | goto perf_stat; | 887 | goto perf_stat; |
872 | } | 888 | } |
873 | 889 | ||
874 | if (!strncmp(argv[1], "rec", 3)) | 890 | if (!strncmp(argv[1], "rec", 3)) |
875 | return kvm_events_record(kvm, argc - 1, argv + 1); | 891 | return kvm_events_record(&kvm, argc - 1, argv + 1); |
876 | 892 | ||
877 | if (!strncmp(argv[1], "rep", 3)) | 893 | if (!strncmp(argv[1], "rep", 3)) |
878 | return kvm_events_report(kvm, argc - 1 , argv + 1); | 894 | return kvm_events_report(&kvm, argc - 1 , argv + 1); |
879 | 895 | ||
880 | perf_stat: | 896 | perf_stat: |
881 | return cmd_stat(argc, argv, NULL); | 897 | return cmd_stat(argc, argv, NULL); |
882 | } | 898 | } |
883 | 899 | ||
884 | static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv) | 900 | static int __cmd_record(const char *file_name, int argc, const char **argv) |
885 | { | 901 | { |
886 | int rec_argc, i = 0, j; | 902 | int rec_argc, i = 0, j; |
887 | const char **rec_argv; | 903 | const char **rec_argv; |
@@ -890,7 +906,7 @@ static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv) | |||
890 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); | 906 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); |
891 | rec_argv[i++] = strdup("record"); | 907 | rec_argv[i++] = strdup("record"); |
892 | rec_argv[i++] = strdup("-o"); | 908 | rec_argv[i++] = strdup("-o"); |
893 | rec_argv[i++] = strdup(kvm->file_name); | 909 | rec_argv[i++] = strdup(file_name); |
894 | for (j = 1; j < argc; j++, i++) | 910 | for (j = 1; j < argc; j++, i++) |
895 | rec_argv[i] = argv[j]; | 911 | rec_argv[i] = argv[j]; |
896 | 912 | ||
@@ -899,7 +915,7 @@ static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv) | |||
899 | return cmd_record(i, rec_argv, NULL); | 915 | return cmd_record(i, rec_argv, NULL); |
900 | } | 916 | } |
901 | 917 | ||
902 | static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv) | 918 | static int __cmd_report(const char *file_name, int argc, const char **argv) |
903 | { | 919 | { |
904 | int rec_argc, i = 0, j; | 920 | int rec_argc, i = 0, j; |
905 | const char **rec_argv; | 921 | const char **rec_argv; |
@@ -908,7 +924,7 @@ static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv) | |||
908 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); | 924 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); |
909 | rec_argv[i++] = strdup("report"); | 925 | rec_argv[i++] = strdup("report"); |
910 | rec_argv[i++] = strdup("-i"); | 926 | rec_argv[i++] = strdup("-i"); |
911 | rec_argv[i++] = strdup(kvm->file_name); | 927 | rec_argv[i++] = strdup(file_name); |
912 | for (j = 1; j < argc; j++, i++) | 928 | for (j = 1; j < argc; j++, i++) |
913 | rec_argv[i] = argv[j]; | 929 | rec_argv[i] = argv[j]; |
914 | 930 | ||
@@ -917,7 +933,8 @@ static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv) | |||
917 | return cmd_report(i, rec_argv, NULL); | 933 | return cmd_report(i, rec_argv, NULL); |
918 | } | 934 | } |
919 | 935 | ||
920 | static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv) | 936 | static int |
937 | __cmd_buildid_list(const char *file_name, int argc, const char **argv) | ||
921 | { | 938 | { |
922 | int rec_argc, i = 0, j; | 939 | int rec_argc, i = 0, j; |
923 | const char **rec_argv; | 940 | const char **rec_argv; |
@@ -926,7 +943,7 @@ static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv) | |||
926 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); | 943 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); |
927 | rec_argv[i++] = strdup("buildid-list"); | 944 | rec_argv[i++] = strdup("buildid-list"); |
928 | rec_argv[i++] = strdup("-i"); | 945 | rec_argv[i++] = strdup("-i"); |
929 | rec_argv[i++] = strdup(kvm->file_name); | 946 | rec_argv[i++] = strdup(file_name); |
930 | for (j = 1; j < argc; j++, i++) | 947 | for (j = 1; j < argc; j++, i++) |
931 | rec_argv[i] = argv[j]; | 948 | rec_argv[i] = argv[j]; |
932 | 949 | ||
@@ -937,20 +954,12 @@ static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv) | |||
937 | 954 | ||
938 | int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) | 955 | int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) |
939 | { | 956 | { |
940 | struct perf_kvm kvm = { | 957 | const char *file_name; |
941 | .trace_vcpu = -1, | ||
942 | .report_event = "vmexit", | ||
943 | .sort_key = "sample", | ||
944 | |||
945 | .exit_reasons = svm_exit_reasons, | ||
946 | .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons), | ||
947 | .exit_reasons_isa = "SVM", | ||
948 | }; | ||
949 | 958 | ||
950 | const struct option kvm_options[] = { | 959 | const struct option kvm_options[] = { |
951 | OPT_STRING('i', "input", &kvm.file_name, "file", | 960 | OPT_STRING('i', "input", &file_name, "file", |
952 | "Input file name"), | 961 | "Input file name"), |
953 | OPT_STRING('o', "output", &kvm.file_name, "file", | 962 | OPT_STRING('o', "output", &file_name, "file", |
954 | "Output file name"), | 963 | "Output file name"), |
955 | OPT_BOOLEAN(0, "guest", &perf_guest, | 964 | OPT_BOOLEAN(0, "guest", &perf_guest, |
956 | "Collect guest os data"), | 965 | "Collect guest os data"), |
@@ -985,32 +994,32 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) | |||
985 | if (!perf_host) | 994 | if (!perf_host) |
986 | perf_guest = 1; | 995 | perf_guest = 1; |
987 | 996 | ||
988 | if (!kvm.file_name) { | 997 | if (!file_name) { |
989 | if (perf_host && !perf_guest) | 998 | if (perf_host && !perf_guest) |
990 | kvm.file_name = strdup("perf.data.host"); | 999 | file_name = strdup("perf.data.host"); |
991 | else if (!perf_host && perf_guest) | 1000 | else if (!perf_host && perf_guest) |
992 | kvm.file_name = strdup("perf.data.guest"); | 1001 | file_name = strdup("perf.data.guest"); |
993 | else | 1002 | else |
994 | kvm.file_name = strdup("perf.data.kvm"); | 1003 | file_name = strdup("perf.data.kvm"); |
995 | 1004 | ||
996 | if (!kvm.file_name) { | 1005 | if (!file_name) { |
997 | pr_err("Failed to allocate memory for filename\n"); | 1006 | pr_err("Failed to allocate memory for filename\n"); |
998 | return -ENOMEM; | 1007 | return -ENOMEM; |
999 | } | 1008 | } |
1000 | } | 1009 | } |
1001 | 1010 | ||
1002 | if (!strncmp(argv[0], "rec", 3)) | 1011 | if (!strncmp(argv[0], "rec", 3)) |
1003 | return __cmd_record(&kvm, argc, argv); | 1012 | return __cmd_record(file_name, argc, argv); |
1004 | else if (!strncmp(argv[0], "rep", 3)) | 1013 | else if (!strncmp(argv[0], "rep", 3)) |
1005 | return __cmd_report(&kvm, argc, argv); | 1014 | return __cmd_report(file_name, argc, argv); |
1006 | else if (!strncmp(argv[0], "diff", 4)) | 1015 | else if (!strncmp(argv[0], "diff", 4)) |
1007 | return cmd_diff(argc, argv, NULL); | 1016 | return cmd_diff(argc, argv, NULL); |
1008 | else if (!strncmp(argv[0], "top", 3)) | 1017 | else if (!strncmp(argv[0], "top", 3)) |
1009 | return cmd_top(argc, argv, NULL); | 1018 | return cmd_top(argc, argv, NULL); |
1010 | else if (!strncmp(argv[0], "buildid-list", 12)) | 1019 | else if (!strncmp(argv[0], "buildid-list", 12)) |
1011 | return __cmd_buildid_list(&kvm, argc, argv); | 1020 | return __cmd_buildid_list(file_name, argc, argv); |
1012 | else if (!strncmp(argv[0], "stat", 4)) | 1021 | else if (!strncmp(argv[0], "stat", 4)) |
1013 | return kvm_cmd_stat(&kvm, argc, argv); | 1022 | return kvm_cmd_stat(file_name, argc, argv); |
1014 | else | 1023 | else |
1015 | usage_with_options(kvm_usage, kvm_options); | 1024 | usage_with_options(kvm_usage, kvm_options); |
1016 | 1025 | ||