aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-kvm.c111
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
61struct perf_kvm; 61struct perf_kvm_stat;
62 62
63struct kvm_events_ops { 63struct 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
82struct perf_kvm { 82struct 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
149static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code) 149static 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
165static void exit_event_decode_key(struct perf_kvm *kvm, 165static 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
231static void mmio_event_decode_key(struct perf_kvm *kvm __maybe_unused, 231static 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
274static void ioport_event_decode_key(struct perf_kvm *kvm __maybe_unused, 274static 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
289static bool register_kvm_events_ops(struct perf_kvm *kvm) 289static 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
314static void init_kvm_event_record(struct perf_kvm *kvm) 314static 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
363static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm, 363static 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
384static bool handle_begin_event(struct perf_kvm *kvm, 384static 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
428static bool handle_end_event(struct perf_kvm *kvm, 428static 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
489static bool handle_kvm_event(struct perf_kvm *kvm, 489static 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
544static bool select_key(struct perf_kvm *kvm) 544static 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
580static void update_total_count(struct perf_kvm *kvm, struct kvm_event *event) 580static void
581update_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
593static void sort_result(struct perf_kvm *kvm) 594static 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
630static void print_result(struct perf_kvm *kvm) 631static 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
704static int read_events(struct perf_kvm *kvm) 706static 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
753static int kvm_events_report_vcpu(struct perf_kvm *kvm) 755static 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
801static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv) 803static int
804kvm_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
824static int kvm_events_report(struct perf_kvm *kvm, int argc, const char **argv) 827static int
828kvm_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
867static int kvm_cmd_stat(struct perf_kvm *kvm, int argc, const char **argv) 871static 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
880perf_stat: 896perf_stat:
881 return cmd_stat(argc, argv, NULL); 897 return cmd_stat(argc, argv, NULL);
882} 898}
883 899
884static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv) 900static 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
902static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv) 918static 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
920static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv) 936static 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
938int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) 955int 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