aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-kvm.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-12-08 09:25:06 -0500
committerIngo Molnar <mingo@kernel.org>2012-12-08 09:25:06 -0500
commitf0b9abfb044649bc452fb2fb975ff2fd599cc6a3 (patch)
tree7800081c5cb16a4dfee1e57a70f3be90f7b50d9a /tools/perf/builtin-kvm.c
parentadc1ef1e37358d3c17d1a74a58b2e104fc0bda15 (diff)
parent1b3c393cd43f22ead8a6a2f839efc6df8ebd7465 (diff)
Merge branch 'linus' into perf/core
Conflicts: tools/perf/Makefile tools/perf/builtin-test.c tools/perf/perf.h tools/perf/tests/parse-events.c tools/perf/util/evsel.h Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/builtin-kvm.c')
-rw-r--r--tools/perf/builtin-kvm.c121
1 files changed, 67 insertions, 54 deletions
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 836c82f01371..ca3f80ebc100 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -22,9 +22,10 @@
22#include <pthread.h> 22#include <pthread.h>
23#include <math.h> 23#include <math.h>
24 24
25#include "../../arch/x86/include/asm/svm.h" 25#if defined(__i386__) || defined(__x86_64__)
26#include "../../arch/x86/include/asm/vmx.h" 26#include <asm/svm.h>
27#include "../../arch/x86/include/asm/kvm.h" 27#include <asm/vmx.h>
28#include <asm/kvm.h>
28 29
29struct event_key { 30struct event_key {
30 #define INVALID_KEY (~0ULL) 31 #define INVALID_KEY (~0ULL)
@@ -58,7 +59,7 @@ struct kvm_event_key {
58}; 59};
59 60
60 61
61struct perf_kvm; 62struct perf_kvm_stat;
62 63
63struct kvm_events_ops { 64struct kvm_events_ops {
64 bool (*is_begin_event)(struct perf_evsel *evsel, 65 bool (*is_begin_event)(struct perf_evsel *evsel,
@@ -66,7 +67,7 @@ struct kvm_events_ops {
66 struct event_key *key); 67 struct event_key *key);
67 bool (*is_end_event)(struct perf_evsel *evsel, 68 bool (*is_end_event)(struct perf_evsel *evsel,
68 struct perf_sample *sample, struct event_key *key); 69 struct perf_sample *sample, struct event_key *key);
69 void (*decode_key)(struct perf_kvm *kvm, struct event_key *key, 70 void (*decode_key)(struct perf_kvm_stat *kvm, struct event_key *key,
70 char decode[20]); 71 char decode[20]);
71 const char *name; 72 const char *name;
72}; 73};
@@ -79,7 +80,7 @@ struct exit_reasons_table {
79#define EVENTS_BITS 12 80#define EVENTS_BITS 12
80#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS) 81#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS)
81 82
82struct perf_kvm { 83struct perf_kvm_stat {
83 struct perf_tool tool; 84 struct perf_tool tool;
84 struct perf_session *session; 85 struct perf_session *session;
85 86
@@ -146,7 +147,7 @@ static struct exit_reasons_table svm_exit_reasons[] = {
146 SVM_EXIT_REASONS 147 SVM_EXIT_REASONS
147}; 148};
148 149
149static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code) 150static const char *get_exit_reason(struct perf_kvm_stat *kvm, u64 exit_code)
150{ 151{
151 int i = kvm->exit_reasons_size; 152 int i = kvm->exit_reasons_size;
152 struct exit_reasons_table *tbl = kvm->exit_reasons; 153 struct exit_reasons_table *tbl = kvm->exit_reasons;
@@ -162,7 +163,7 @@ static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code)
162 return "UNKNOWN"; 163 return "UNKNOWN";
163} 164}
164 165
165static void exit_event_decode_key(struct perf_kvm *kvm, 166static void exit_event_decode_key(struct perf_kvm_stat *kvm,
166 struct event_key *key, 167 struct event_key *key,
167 char decode[20]) 168 char decode[20])
168{ 169{
@@ -228,7 +229,7 @@ static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample,
228 return false; 229 return false;
229} 230}
230 231
231static void mmio_event_decode_key(struct perf_kvm *kvm __maybe_unused, 232static void mmio_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
232 struct event_key *key, 233 struct event_key *key,
233 char decode[20]) 234 char decode[20])
234{ 235{
@@ -271,7 +272,7 @@ static bool ioport_event_end(struct perf_evsel *evsel,
271 return kvm_entry_event(evsel); 272 return kvm_entry_event(evsel);
272} 273}
273 274
274static void ioport_event_decode_key(struct perf_kvm *kvm __maybe_unused, 275static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
275 struct event_key *key, 276 struct event_key *key,
276 char decode[20]) 277 char decode[20])
277{ 278{
@@ -286,7 +287,7 @@ static struct kvm_events_ops ioport_events = {
286 .name = "IO Port Access" 287 .name = "IO Port Access"
287}; 288};
288 289
289static bool register_kvm_events_ops(struct perf_kvm *kvm) 290static bool register_kvm_events_ops(struct perf_kvm_stat *kvm)
290{ 291{
291 bool ret = true; 292 bool ret = true;
292 293
@@ -311,7 +312,7 @@ struct vcpu_event_record {
311}; 312};
312 313
313 314
314static void init_kvm_event_record(struct perf_kvm *kvm) 315static void init_kvm_event_record(struct perf_kvm_stat *kvm)
315{ 316{
316 unsigned int i; 317 unsigned int i;
317 318
@@ -360,7 +361,7 @@ static struct kvm_event *kvm_alloc_init_event(struct event_key *key)
360 return event; 361 return event;
361} 362}
362 363
363static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm, 364static struct kvm_event *find_create_kvm_event(struct perf_kvm_stat *kvm,
364 struct event_key *key) 365 struct event_key *key)
365{ 366{
366 struct kvm_event *event; 367 struct kvm_event *event;
@@ -382,7 +383,7 @@ static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
382 return event; 383 return event;
383} 384}
384 385
385static bool handle_begin_event(struct perf_kvm *kvm, 386static bool handle_begin_event(struct perf_kvm_stat *kvm,
386 struct vcpu_event_record *vcpu_record, 387 struct vcpu_event_record *vcpu_record,
387 struct event_key *key, u64 timestamp) 388 struct event_key *key, u64 timestamp)
388{ 389{
@@ -429,7 +430,7 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
429 return true; 430 return true;
430} 431}
431 432
432static bool handle_end_event(struct perf_kvm *kvm, 433static bool handle_end_event(struct perf_kvm_stat *kvm,
433 struct vcpu_event_record *vcpu_record, 434 struct vcpu_event_record *vcpu_record,
434 struct event_key *key, 435 struct event_key *key,
435 u64 timestamp) 436 u64 timestamp)
@@ -496,7 +497,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
496 return thread->priv; 497 return thread->priv;
497} 498}
498 499
499static bool handle_kvm_event(struct perf_kvm *kvm, 500static bool handle_kvm_event(struct perf_kvm_stat *kvm,
500 struct thread *thread, 501 struct thread *thread,
501 struct perf_evsel *evsel, 502 struct perf_evsel *evsel,
502 struct perf_sample *sample) 503 struct perf_sample *sample)
@@ -556,7 +557,7 @@ static struct kvm_event_key keys[] = {
556 { NULL, NULL } 557 { NULL, NULL }
557}; 558};
558 559
559static bool select_key(struct perf_kvm *kvm) 560static bool select_key(struct perf_kvm_stat *kvm)
560{ 561{
561 int i; 562 int i;
562 563
@@ -592,7 +593,8 @@ static void insert_to_result(struct rb_root *result, struct kvm_event *event,
592 rb_insert_color(&event->rb, result); 593 rb_insert_color(&event->rb, result);
593} 594}
594 595
595static void update_total_count(struct perf_kvm *kvm, struct kvm_event *event) 596static void
597update_total_count(struct perf_kvm_stat *kvm, struct kvm_event *event)
596{ 598{
597 int vcpu = kvm->trace_vcpu; 599 int vcpu = kvm->trace_vcpu;
598 600
@@ -605,7 +607,7 @@ static bool event_is_valid(struct kvm_event *event, int vcpu)
605 return !!get_event_count(event, vcpu); 607 return !!get_event_count(event, vcpu);
606} 608}
607 609
608static void sort_result(struct perf_kvm *kvm) 610static void sort_result(struct perf_kvm_stat *kvm)
609{ 611{
610 unsigned int i; 612 unsigned int i;
611 int vcpu = kvm->trace_vcpu; 613 int vcpu = kvm->trace_vcpu;
@@ -644,7 +646,7 @@ static void print_vcpu_info(int vcpu)
644 pr_info("VCPU %d:\n\n", vcpu); 646 pr_info("VCPU %d:\n\n", vcpu);
645} 647}
646 648
647static void print_result(struct perf_kvm *kvm) 649static void print_result(struct perf_kvm_stat *kvm)
648{ 650{
649 char decode[20]; 651 char decode[20];
650 struct kvm_event *event; 652 struct kvm_event *event;
@@ -687,7 +689,8 @@ static int process_sample_event(struct perf_tool *tool,
687 struct machine *machine) 689 struct machine *machine)
688{ 690{
689 struct thread *thread = machine__findnew_thread(machine, sample->tid); 691 struct thread *thread = machine__findnew_thread(machine, sample->tid);
690 struct perf_kvm *kvm = container_of(tool, struct perf_kvm, tool); 692 struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat,
693 tool);
691 694
692 if (thread == NULL) { 695 if (thread == NULL) {
693 pr_debug("problem processing %d event, skipping it.\n", 696 pr_debug("problem processing %d event, skipping it.\n",
@@ -718,7 +721,7 @@ static int get_cpu_isa(struct perf_session *session)
718 return isa; 721 return isa;
719} 722}
720 723
721static int read_events(struct perf_kvm *kvm) 724static int read_events(struct perf_kvm_stat *kvm)
722{ 725{
723 int ret; 726 int ret;
724 727
@@ -767,7 +770,7 @@ static bool verify_vcpu(int vcpu)
767 return true; 770 return true;
768} 771}
769 772
770static int kvm_events_report_vcpu(struct perf_kvm *kvm) 773static int kvm_events_report_vcpu(struct perf_kvm_stat *kvm)
771{ 774{
772 int ret = -EINVAL; 775 int ret = -EINVAL;
773 int vcpu = kvm->trace_vcpu; 776 int vcpu = kvm->trace_vcpu;
@@ -815,7 +818,8 @@ static const char * const record_args[] = {
815 _p; \ 818 _p; \
816 }) 819 })
817 820
818static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv) 821static int
822kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
819{ 823{
820 unsigned int rec_argc, i, j; 824 unsigned int rec_argc, i, j;
821 const char **rec_argv; 825 const char **rec_argv;
@@ -838,7 +842,8 @@ static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv)
838 return cmd_record(i, rec_argv, NULL); 842 return cmd_record(i, rec_argv, NULL);
839} 843}
840 844
841static int kvm_events_report(struct perf_kvm *kvm, int argc, const char **argv) 845static int
846kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
842{ 847{
843 const struct option kvm_events_report_options[] = { 848 const struct option kvm_events_report_options[] = {
844 OPT_STRING(0, "event", &kvm->report_event, "report event", 849 OPT_STRING(0, "event", &kvm->report_event, "report event",
@@ -881,24 +886,37 @@ static void print_kvm_stat_usage(void)
881 printf("\nOtherwise, it is the alias of 'perf stat':\n"); 886 printf("\nOtherwise, it is the alias of 'perf stat':\n");
882} 887}
883 888
884static int kvm_cmd_stat(struct perf_kvm *kvm, int argc, const char **argv) 889static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
885{ 890{
891 struct perf_kvm_stat kvm = {
892 .file_name = file_name,
893
894 .trace_vcpu = -1,
895 .report_event = "vmexit",
896 .sort_key = "sample",
897
898 .exit_reasons = svm_exit_reasons,
899 .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons),
900 .exit_reasons_isa = "SVM",
901 };
902
886 if (argc == 1) { 903 if (argc == 1) {
887 print_kvm_stat_usage(); 904 print_kvm_stat_usage();
888 goto perf_stat; 905 goto perf_stat;
889 } 906 }
890 907
891 if (!strncmp(argv[1], "rec", 3)) 908 if (!strncmp(argv[1], "rec", 3))
892 return kvm_events_record(kvm, argc - 1, argv + 1); 909 return kvm_events_record(&kvm, argc - 1, argv + 1);
893 910
894 if (!strncmp(argv[1], "rep", 3)) 911 if (!strncmp(argv[1], "rep", 3))
895 return kvm_events_report(kvm, argc - 1 , argv + 1); 912 return kvm_events_report(&kvm, argc - 1 , argv + 1);
896 913
897perf_stat: 914perf_stat:
898 return cmd_stat(argc, argv, NULL); 915 return cmd_stat(argc, argv, NULL);
899} 916}
917#endif
900 918
901static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv) 919static int __cmd_record(const char *file_name, int argc, const char **argv)
902{ 920{
903 int rec_argc, i = 0, j; 921 int rec_argc, i = 0, j;
904 const char **rec_argv; 922 const char **rec_argv;
@@ -907,7 +925,7 @@ static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv)
907 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 925 rec_argv = calloc(rec_argc + 1, sizeof(char *));
908 rec_argv[i++] = strdup("record"); 926 rec_argv[i++] = strdup("record");
909 rec_argv[i++] = strdup("-o"); 927 rec_argv[i++] = strdup("-o");
910 rec_argv[i++] = strdup(kvm->file_name); 928 rec_argv[i++] = strdup(file_name);
911 for (j = 1; j < argc; j++, i++) 929 for (j = 1; j < argc; j++, i++)
912 rec_argv[i] = argv[j]; 930 rec_argv[i] = argv[j];
913 931
@@ -916,7 +934,7 @@ static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv)
916 return cmd_record(i, rec_argv, NULL); 934 return cmd_record(i, rec_argv, NULL);
917} 935}
918 936
919static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv) 937static int __cmd_report(const char *file_name, int argc, const char **argv)
920{ 938{
921 int rec_argc, i = 0, j; 939 int rec_argc, i = 0, j;
922 const char **rec_argv; 940 const char **rec_argv;
@@ -925,7 +943,7 @@ static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv)
925 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 943 rec_argv = calloc(rec_argc + 1, sizeof(char *));
926 rec_argv[i++] = strdup("report"); 944 rec_argv[i++] = strdup("report");
927 rec_argv[i++] = strdup("-i"); 945 rec_argv[i++] = strdup("-i");
928 rec_argv[i++] = strdup(kvm->file_name); 946 rec_argv[i++] = strdup(file_name);
929 for (j = 1; j < argc; j++, i++) 947 for (j = 1; j < argc; j++, i++)
930 rec_argv[i] = argv[j]; 948 rec_argv[i] = argv[j];
931 949
@@ -934,7 +952,8 @@ static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv)
934 return cmd_report(i, rec_argv, NULL); 952 return cmd_report(i, rec_argv, NULL);
935} 953}
936 954
937static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv) 955static int
956__cmd_buildid_list(const char *file_name, int argc, const char **argv)
938{ 957{
939 int rec_argc, i = 0, j; 958 int rec_argc, i = 0, j;
940 const char **rec_argv; 959 const char **rec_argv;
@@ -943,7 +962,7 @@ static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv)
943 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 962 rec_argv = calloc(rec_argc + 1, sizeof(char *));
944 rec_argv[i++] = strdup("buildid-list"); 963 rec_argv[i++] = strdup("buildid-list");
945 rec_argv[i++] = strdup("-i"); 964 rec_argv[i++] = strdup("-i");
946 rec_argv[i++] = strdup(kvm->file_name); 965 rec_argv[i++] = strdup(file_name);
947 for (j = 1; j < argc; j++, i++) 966 for (j = 1; j < argc; j++, i++)
948 rec_argv[i] = argv[j]; 967 rec_argv[i] = argv[j];
949 968
@@ -954,20 +973,12 @@ static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv)
954 973
955int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) 974int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
956{ 975{
957 struct perf_kvm kvm = { 976 const char *file_name;
958 .trace_vcpu = -1,
959 .report_event = "vmexit",
960 .sort_key = "sample",
961
962 .exit_reasons = svm_exit_reasons,
963 .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons),
964 .exit_reasons_isa = "SVM",
965 };
966 977
967 const struct option kvm_options[] = { 978 const struct option kvm_options[] = {
968 OPT_STRING('i', "input", &kvm.file_name, "file", 979 OPT_STRING('i', "input", &file_name, "file",
969 "Input file name"), 980 "Input file name"),
970 OPT_STRING('o', "output", &kvm.file_name, "file", 981 OPT_STRING('o', "output", &file_name, "file",
971 "Output file name"), 982 "Output file name"),
972 OPT_BOOLEAN(0, "guest", &perf_guest, 983 OPT_BOOLEAN(0, "guest", &perf_guest,
973 "Collect guest os data"), 984 "Collect guest os data"),
@@ -1002,32 +1013,34 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
1002 if (!perf_host) 1013 if (!perf_host)
1003 perf_guest = 1; 1014 perf_guest = 1;
1004 1015
1005 if (!kvm.file_name) { 1016 if (!file_name) {
1006 if (perf_host && !perf_guest) 1017 if (perf_host && !perf_guest)
1007 kvm.file_name = strdup("perf.data.host"); 1018 file_name = strdup("perf.data.host");
1008 else if (!perf_host && perf_guest) 1019 else if (!perf_host && perf_guest)
1009 kvm.file_name = strdup("perf.data.guest"); 1020 file_name = strdup("perf.data.guest");
1010 else 1021 else
1011 kvm.file_name = strdup("perf.data.kvm"); 1022 file_name = strdup("perf.data.kvm");
1012 1023
1013 if (!kvm.file_name) { 1024 if (!file_name) {
1014 pr_err("Failed to allocate memory for filename\n"); 1025 pr_err("Failed to allocate memory for filename\n");
1015 return -ENOMEM; 1026 return -ENOMEM;
1016 } 1027 }
1017 } 1028 }
1018 1029
1019 if (!strncmp(argv[0], "rec", 3)) 1030 if (!strncmp(argv[0], "rec", 3))
1020 return __cmd_record(&kvm, argc, argv); 1031 return __cmd_record(file_name, argc, argv);
1021 else if (!strncmp(argv[0], "rep", 3)) 1032 else if (!strncmp(argv[0], "rep", 3))
1022 return __cmd_report(&kvm, argc, argv); 1033 return __cmd_report(file_name, argc, argv);
1023 else if (!strncmp(argv[0], "diff", 4)) 1034 else if (!strncmp(argv[0], "diff", 4))
1024 return cmd_diff(argc, argv, NULL); 1035 return cmd_diff(argc, argv, NULL);
1025 else if (!strncmp(argv[0], "top", 3)) 1036 else if (!strncmp(argv[0], "top", 3))
1026 return cmd_top(argc, argv, NULL); 1037 return cmd_top(argc, argv, NULL);
1027 else if (!strncmp(argv[0], "buildid-list", 12)) 1038 else if (!strncmp(argv[0], "buildid-list", 12))
1028 return __cmd_buildid_list(&kvm, argc, argv); 1039 return __cmd_buildid_list(file_name, argc, argv);
1040#if defined(__i386__) || defined(__x86_64__)
1029 else if (!strncmp(argv[0], "stat", 4)) 1041 else if (!strncmp(argv[0], "stat", 4))
1030 return kvm_cmd_stat(&kvm, argc, argv); 1042 return kvm_cmd_stat(file_name, argc, argv);
1043#endif
1031 else 1044 else
1032 usage_with_options(kvm_usage, kvm_options); 1045 usage_with_options(kvm_usage, kvm_options);
1033 1046