aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-kvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-kvm.c')
-rw-r--r--tools/perf/builtin-kvm.c414
1 files changed, 121 insertions, 293 deletions
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 0f1e5a2f6ad7..43367eb00510 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -29,114 +29,25 @@
29#include <pthread.h> 29#include <pthread.h>
30#include <math.h> 30#include <math.h>
31 31
32#if defined(__i386__) || defined(__x86_64__) 32#ifdef HAVE_KVM_STAT_SUPPORT
33#include <asm/svm.h> 33#include <asm/kvm_perf.h>
34#include <asm/vmx.h> 34#include "util/kvm-stat.h"
35#include <asm/kvm.h>
36
37struct event_key {
38 #define INVALID_KEY (~0ULL)
39 u64 key;
40 int info;
41};
42
43struct kvm_event_stats {
44 u64 time;
45 struct stats stats;
46};
47
48struct kvm_event {
49 struct list_head hash_entry;
50 struct rb_node rb;
51
52 struct event_key key;
53
54 struct kvm_event_stats total;
55
56 #define DEFAULT_VCPU_NUM 8
57 int max_vcpu;
58 struct kvm_event_stats *vcpu;
59};
60
61typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
62
63struct kvm_event_key {
64 const char *name;
65 key_cmp_fun key;
66};
67
68
69struct perf_kvm_stat;
70
71struct kvm_events_ops {
72 bool (*is_begin_event)(struct perf_evsel *evsel,
73 struct perf_sample *sample,
74 struct event_key *key);
75 bool (*is_end_event)(struct perf_evsel *evsel,
76 struct perf_sample *sample, struct event_key *key);
77 void (*decode_key)(struct perf_kvm_stat *kvm, struct event_key *key,
78 char decode[20]);
79 const char *name;
80};
81
82struct exit_reasons_table {
83 unsigned long exit_code;
84 const char *reason;
85};
86 35
87#define EVENTS_BITS 12 36void exit_event_get_key(struct perf_evsel *evsel,
88#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS) 37 struct perf_sample *sample,
89 38 struct event_key *key)
90struct perf_kvm_stat {
91 struct perf_tool tool;
92 struct record_opts opts;
93 struct perf_evlist *evlist;
94 struct perf_session *session;
95
96 const char *file_name;
97 const char *report_event;
98 const char *sort_key;
99 int trace_vcpu;
100
101 struct exit_reasons_table *exit_reasons;
102 int exit_reasons_size;
103 const char *exit_reasons_isa;
104
105 struct kvm_events_ops *events_ops;
106 key_cmp_fun compare;
107 struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
108
109 u64 total_time;
110 u64 total_count;
111 u64 lost_events;
112 u64 duration;
113
114 const char *pid_str;
115 struct intlist *pid_list;
116
117 struct rb_root result;
118
119 int timerfd;
120 unsigned int display_time;
121 bool live;
122};
123
124
125static void exit_event_get_key(struct perf_evsel *evsel,
126 struct perf_sample *sample,
127 struct event_key *key)
128{ 39{
129 key->info = 0; 40 key->info = 0;
130 key->key = perf_evsel__intval(evsel, sample, "exit_reason"); 41 key->key = perf_evsel__intval(evsel, sample, KVM_EXIT_REASON);
131} 42}
132 43
133static bool kvm_exit_event(struct perf_evsel *evsel) 44bool kvm_exit_event(struct perf_evsel *evsel)
134{ 45{
135 return !strcmp(evsel->name, "kvm:kvm_exit"); 46 return !strcmp(evsel->name, KVM_EXIT_TRACE);
136} 47}
137 48
138static bool exit_event_begin(struct perf_evsel *evsel, 49bool exit_event_begin(struct perf_evsel *evsel,
139 struct perf_sample *sample, struct event_key *key) 50 struct perf_sample *sample, struct event_key *key)
140{ 51{
141 if (kvm_exit_event(evsel)) { 52 if (kvm_exit_event(evsel)) {
142 exit_event_get_key(evsel, sample, key); 53 exit_event_get_key(evsel, sample, key);
@@ -146,32 +57,23 @@ static bool exit_event_begin(struct perf_evsel *evsel,
146 return false; 57 return false;
147} 58}
148 59
149static bool kvm_entry_event(struct perf_evsel *evsel) 60bool kvm_entry_event(struct perf_evsel *evsel)
150{ 61{
151 return !strcmp(evsel->name, "kvm:kvm_entry"); 62 return !strcmp(evsel->name, KVM_ENTRY_TRACE);
152} 63}
153 64
154static bool exit_event_end(struct perf_evsel *evsel, 65bool exit_event_end(struct perf_evsel *evsel,
155 struct perf_sample *sample __maybe_unused, 66 struct perf_sample *sample __maybe_unused,
156 struct event_key *key __maybe_unused) 67 struct event_key *key __maybe_unused)
157{ 68{
158 return kvm_entry_event(evsel); 69 return kvm_entry_event(evsel);
159} 70}
160 71
161static struct exit_reasons_table vmx_exit_reasons[] = { 72static const char *get_exit_reason(struct perf_kvm_stat *kvm,
162 VMX_EXIT_REASONS 73 struct exit_reasons_table *tbl,
163}; 74 u64 exit_code)
164
165static struct exit_reasons_table svm_exit_reasons[] = {
166 SVM_EXIT_REASONS
167};
168
169static const char *get_exit_reason(struct perf_kvm_stat *kvm, u64 exit_code)
170{ 75{
171 int i = kvm->exit_reasons_size; 76 while (tbl->reason != NULL) {
172 struct exit_reasons_table *tbl = kvm->exit_reasons;
173
174 while (i--) {
175 if (tbl->exit_code == exit_code) 77 if (tbl->exit_code == exit_code)
176 return tbl->reason; 78 return tbl->reason;
177 tbl++; 79 tbl++;
@@ -182,148 +84,30 @@ static const char *get_exit_reason(struct perf_kvm_stat *kvm, u64 exit_code)
182 return "UNKNOWN"; 84 return "UNKNOWN";
183} 85}
184 86
185static void exit_event_decode_key(struct perf_kvm_stat *kvm, 87void exit_event_decode_key(struct perf_kvm_stat *kvm,
186 struct event_key *key, 88 struct event_key *key,
187 char decode[20]) 89 char *decode)
188{ 90{
189 const char *exit_reason = get_exit_reason(kvm, key->key); 91 const char *exit_reason = get_exit_reason(kvm, key->exit_reasons,
92 key->key);
190 93
191 scnprintf(decode, 20, "%s", exit_reason); 94 scnprintf(decode, DECODE_STR_LEN, "%s", exit_reason);
192} 95}
193 96
194static struct kvm_events_ops exit_events = { 97static bool register_kvm_events_ops(struct perf_kvm_stat *kvm)
195 .is_begin_event = exit_event_begin,
196 .is_end_event = exit_event_end,
197 .decode_key = exit_event_decode_key,
198 .name = "VM-EXIT"
199};
200
201/*
202 * For the mmio events, we treat:
203 * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
204 * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...).
205 */
206static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample,
207 struct event_key *key)
208{
209 key->key = perf_evsel__intval(evsel, sample, "gpa");
210 key->info = perf_evsel__intval(evsel, sample, "type");
211}
212
213#define KVM_TRACE_MMIO_READ_UNSATISFIED 0
214#define KVM_TRACE_MMIO_READ 1
215#define KVM_TRACE_MMIO_WRITE 2
216
217static bool mmio_event_begin(struct perf_evsel *evsel,
218 struct perf_sample *sample, struct event_key *key)
219{
220 /* MMIO read begin event in kernel. */
221 if (kvm_exit_event(evsel))
222 return true;
223
224 /* MMIO write begin event in kernel. */
225 if (!strcmp(evsel->name, "kvm:kvm_mmio") &&
226 perf_evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_WRITE) {
227 mmio_event_get_key(evsel, sample, key);
228 return true;
229 }
230
231 return false;
232}
233
234static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample,
235 struct event_key *key)
236{
237 /* MMIO write end event in kernel. */
238 if (kvm_entry_event(evsel))
239 return true;
240
241 /* MMIO read end event in kernel.*/
242 if (!strcmp(evsel->name, "kvm:kvm_mmio") &&
243 perf_evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_READ) {
244 mmio_event_get_key(evsel, sample, key);
245 return true;
246 }
247
248 return false;
249}
250
251static void mmio_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
252 struct event_key *key,
253 char decode[20])
254{
255 scnprintf(decode, 20, "%#lx:%s", (unsigned long)key->key,
256 key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R");
257}
258
259static struct kvm_events_ops mmio_events = {
260 .is_begin_event = mmio_event_begin,
261 .is_end_event = mmio_event_end,
262 .decode_key = mmio_event_decode_key,
263 .name = "MMIO Access"
264};
265
266 /* The time of emulation pio access is from kvm_pio to kvm_entry. */
267static void ioport_event_get_key(struct perf_evsel *evsel,
268 struct perf_sample *sample,
269 struct event_key *key)
270{ 98{
271 key->key = perf_evsel__intval(evsel, sample, "port"); 99 struct kvm_reg_events_ops *events_ops = kvm_reg_events_ops;
272 key->info = perf_evsel__intval(evsel, sample, "rw");
273}
274 100
275static bool ioport_event_begin(struct perf_evsel *evsel, 101 for (events_ops = kvm_reg_events_ops; events_ops->name; events_ops++) {
276 struct perf_sample *sample, 102 if (!strcmp(events_ops->name, kvm->report_event)) {
277 struct event_key *key) 103 kvm->events_ops = events_ops->ops;
278{ 104 return true;
279 if (!strcmp(evsel->name, "kvm:kvm_pio")) { 105 }
280 ioport_event_get_key(evsel, sample, key);
281 return true;
282 } 106 }
283 107
284 return false; 108 return false;
285} 109}
286 110
287static bool ioport_event_end(struct perf_evsel *evsel,
288 struct perf_sample *sample __maybe_unused,
289 struct event_key *key __maybe_unused)
290{
291 return kvm_entry_event(evsel);
292}
293
294static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
295 struct event_key *key,
296 char decode[20])
297{
298 scnprintf(decode, 20, "%#llx:%s", (unsigned long long)key->key,
299 key->info ? "POUT" : "PIN");
300}
301
302static struct kvm_events_ops ioport_events = {
303 .is_begin_event = ioport_event_begin,
304 .is_end_event = ioport_event_end,
305 .decode_key = ioport_event_decode_key,
306 .name = "IO Port Access"
307};
308
309static bool register_kvm_events_ops(struct perf_kvm_stat *kvm)
310{
311 bool ret = true;
312
313 if (!strcmp(kvm->report_event, "vmexit"))
314 kvm->events_ops = &exit_events;
315 else if (!strcmp(kvm->report_event, "mmio"))
316 kvm->events_ops = &mmio_events;
317 else if (!strcmp(kvm->report_event, "ioport"))
318 kvm->events_ops = &ioport_events;
319 else {
320 pr_err("Unknown report event:%s\n", kvm->report_event);
321 ret = false;
322 }
323
324 return ret;
325}
326
327struct vcpu_event_record { 111struct vcpu_event_record {
328 int vcpu_id; 112 int vcpu_id;
329 u64 start_time; 113 u64 start_time;
@@ -477,6 +261,54 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
477 return true; 261 return true;
478} 262}
479 263
264static bool is_child_event(struct perf_kvm_stat *kvm,
265 struct perf_evsel *evsel,
266 struct perf_sample *sample,
267 struct event_key *key)
268{
269 struct child_event_ops *child_ops;
270
271 child_ops = kvm->events_ops->child_ops;
272
273 if (!child_ops)
274 return false;
275
276 for (; child_ops->name; child_ops++) {
277 if (!strcmp(evsel->name, child_ops->name)) {
278 child_ops->get_key(evsel, sample, key);
279 return true;
280 }
281 }
282
283 return false;
284}
285
286static bool handle_child_event(struct perf_kvm_stat *kvm,
287 struct vcpu_event_record *vcpu_record,
288 struct event_key *key,
289 struct perf_sample *sample __maybe_unused)
290{
291 struct kvm_event *event = NULL;
292
293 if (key->key != INVALID_KEY)
294 event = find_create_kvm_event(kvm, key);
295
296 vcpu_record->last_event = event;
297
298 return true;
299}
300
301static bool skip_event(const char *event)
302{
303 const char * const *skip_events;
304
305 for (skip_events = kvm_skip_events; *skip_events; skip_events++)
306 if (!strcmp(event, *skip_events))
307 return true;
308
309 return false;
310}
311
480static bool handle_end_event(struct perf_kvm_stat *kvm, 312static bool handle_end_event(struct perf_kvm_stat *kvm,
481 struct vcpu_event_record *vcpu_record, 313 struct vcpu_event_record *vcpu_record,
482 struct event_key *key, 314 struct event_key *key,
@@ -525,10 +357,10 @@ static bool handle_end_event(struct perf_kvm_stat *kvm,
525 time_diff = sample->time - time_begin; 357 time_diff = sample->time - time_begin;
526 358
527 if (kvm->duration && time_diff > kvm->duration) { 359 if (kvm->duration && time_diff > kvm->duration) {
528 char decode[32]; 360 char decode[DECODE_STR_LEN];
529 361
530 kvm->events_ops->decode_key(kvm, &event->key, decode); 362 kvm->events_ops->decode_key(kvm, &event->key, decode);
531 if (strcmp(decode, "HLT")) { 363 if (!skip_event(decode)) {
532 pr_info("%" PRIu64 " VM %d, vcpu %d: %s event took %" PRIu64 "usec\n", 364 pr_info("%" PRIu64 " VM %d, vcpu %d: %s event took %" PRIu64 "usec\n",
533 sample->time, sample->pid, vcpu_record->vcpu_id, 365 sample->time, sample->pid, vcpu_record->vcpu_id,
534 decode, time_diff/1000); 366 decode, time_diff/1000);
@@ -553,7 +385,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
553 return NULL; 385 return NULL;
554 } 386 }
555 387
556 vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, "vcpu_id"); 388 vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID);
557 thread->priv = vcpu_record; 389 thread->priv = vcpu_record;
558 } 390 }
559 391
@@ -566,7 +398,8 @@ static bool handle_kvm_event(struct perf_kvm_stat *kvm,
566 struct perf_sample *sample) 398 struct perf_sample *sample)
567{ 399{
568 struct vcpu_event_record *vcpu_record; 400 struct vcpu_event_record *vcpu_record;
569 struct event_key key = {.key = INVALID_KEY}; 401 struct event_key key = { .key = INVALID_KEY,
402 .exit_reasons = kvm->exit_reasons };
570 403
571 vcpu_record = per_vcpu_record(thread, evsel, sample); 404 vcpu_record = per_vcpu_record(thread, evsel, sample);
572 if (!vcpu_record) 405 if (!vcpu_record)
@@ -580,6 +413,9 @@ static bool handle_kvm_event(struct perf_kvm_stat *kvm,
580 if (kvm->events_ops->is_begin_event(evsel, sample, &key)) 413 if (kvm->events_ops->is_begin_event(evsel, sample, &key))
581 return handle_begin_event(kvm, vcpu_record, &key, sample->time); 414 return handle_begin_event(kvm, vcpu_record, &key, sample->time);
582 415
416 if (is_child_event(kvm, evsel, sample, &key))
417 return handle_child_event(kvm, vcpu_record, &key, sample);
418
583 if (kvm->events_ops->is_end_event(evsel, sample, &key)) 419 if (kvm->events_ops->is_end_event(evsel, sample, &key))
584 return handle_end_event(kvm, vcpu_record, &key, sample); 420 return handle_end_event(kvm, vcpu_record, &key, sample);
585 421
@@ -740,7 +576,7 @@ static void show_timeofday(void)
740 576
741static void print_result(struct perf_kvm_stat *kvm) 577static void print_result(struct perf_kvm_stat *kvm)
742{ 578{
743 char decode[20]; 579 char decode[DECODE_STR_LEN];
744 struct kvm_event *event; 580 struct kvm_event *event;
745 int vcpu = kvm->trace_vcpu; 581 int vcpu = kvm->trace_vcpu;
746 582
@@ -751,7 +587,7 @@ static void print_result(struct perf_kvm_stat *kvm)
751 587
752 pr_info("\n\n"); 588 pr_info("\n\n");
753 print_vcpu_info(kvm); 589 print_vcpu_info(kvm);
754 pr_info("%20s ", kvm->events_ops->name); 590 pr_info("%*s ", DECODE_STR_LEN, kvm->events_ops->name);
755 pr_info("%10s ", "Samples"); 591 pr_info("%10s ", "Samples");
756 pr_info("%9s ", "Samples%"); 592 pr_info("%9s ", "Samples%");
757 593
@@ -770,7 +606,7 @@ static void print_result(struct perf_kvm_stat *kvm)
770 min = get_event_min(event, vcpu); 606 min = get_event_min(event, vcpu);
771 607
772 kvm->events_ops->decode_key(kvm, &event->key, decode); 608 kvm->events_ops->decode_key(kvm, &event->key, decode);
773 pr_info("%20s ", decode); 609 pr_info("%*s ", DECODE_STR_LEN, decode);
774 pr_info("%10llu ", (unsigned long long)ecount); 610 pr_info("%10llu ", (unsigned long long)ecount);
775 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100); 611 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
776 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100); 612 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
@@ -839,34 +675,28 @@ static int process_sample_event(struct perf_tool *tool,
839static int cpu_isa_config(struct perf_kvm_stat *kvm) 675static int cpu_isa_config(struct perf_kvm_stat *kvm)
840{ 676{
841 char buf[64], *cpuid; 677 char buf[64], *cpuid;
842 int err, isa; 678 int err;
843 679
844 if (kvm->live) { 680 if (kvm->live) {
845 err = get_cpuid(buf, sizeof(buf)); 681 err = get_cpuid(buf, sizeof(buf));
846 if (err != 0) { 682 if (err != 0) {
847 pr_err("Failed to look up CPU type (Intel or AMD)\n"); 683 pr_err("Failed to look up CPU type\n");
848 return err; 684 return err;
849 } 685 }
850 cpuid = buf; 686 cpuid = buf;
851 } else 687 } else
852 cpuid = kvm->session->header.env.cpuid; 688 cpuid = kvm->session->header.env.cpuid;
853 689
854 if (strstr(cpuid, "Intel")) 690 if (!cpuid) {
855 isa = 1; 691 pr_err("Failed to look up CPU type\n");
856 else if (strstr(cpuid, "AMD")) 692 return -EINVAL;
857 isa = 0;
858 else {
859 pr_err("CPU %s is not supported.\n", cpuid);
860 return -ENOTSUP;
861 } 693 }
862 694
863 if (isa == 1) { 695 err = cpu_isa_init(kvm, cpuid);
864 kvm->exit_reasons = vmx_exit_reasons; 696 if (err == -ENOTSUP)
865 kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons); 697 pr_err("CPU %s is not supported.\n", cpuid);
866 kvm->exit_reasons_isa = "VMX";
867 }
868 698
869 return 0; 699 return err;
870} 700}
871 701
872static bool verify_vcpu(int vcpu) 702static bool verify_vcpu(int vcpu)
@@ -1300,13 +1130,6 @@ exit:
1300 return ret; 1130 return ret;
1301} 1131}
1302 1132
1303static const char * const kvm_events_tp[] = {
1304 "kvm:kvm_entry",
1305 "kvm:kvm_exit",
1306 "kvm:kvm_mmio",
1307 "kvm:kvm_pio",
1308};
1309
1310#define STRDUP_FAIL_EXIT(s) \ 1133#define STRDUP_FAIL_EXIT(s) \
1311 ({ char *_p; \ 1134 ({ char *_p; \
1312 _p = strdup(s); \ 1135 _p = strdup(s); \
@@ -1318,7 +1141,7 @@ static const char * const kvm_events_tp[] = {
1318static int 1141static int
1319kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv) 1142kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
1320{ 1143{
1321 unsigned int rec_argc, i, j; 1144 unsigned int rec_argc, i, j, events_tp_size;
1322 const char **rec_argv; 1145 const char **rec_argv;
1323 const char * const record_args[] = { 1146 const char * const record_args[] = {
1324 "record", 1147 "record",
@@ -1326,9 +1149,14 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
1326 "-m", "1024", 1149 "-m", "1024",
1327 "-c", "1", 1150 "-c", "1",
1328 }; 1151 };
1152 const char * const *events_tp;
1153 events_tp_size = 0;
1154
1155 for (events_tp = kvm_events_tp; *events_tp; events_tp++)
1156 events_tp_size++;
1329 1157
1330 rec_argc = ARRAY_SIZE(record_args) + argc + 2 + 1158 rec_argc = ARRAY_SIZE(record_args) + argc + 2 +
1331 2 * ARRAY_SIZE(kvm_events_tp); 1159 2 * events_tp_size;
1332 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1160 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1333 1161
1334 if (rec_argv == NULL) 1162 if (rec_argv == NULL)
@@ -1337,7 +1165,7 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
1337 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1165 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1338 rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]); 1166 rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
1339 1167
1340 for (j = 0; j < ARRAY_SIZE(kvm_events_tp); j++) { 1168 for (j = 0; j < events_tp_size; j++) {
1341 rec_argv[i++] = "-e"; 1169 rec_argv[i++] = "-e";
1342 rec_argv[i++] = STRDUP_FAIL_EXIT(kvm_events_tp[j]); 1170 rec_argv[i++] = STRDUP_FAIL_EXIT(kvm_events_tp[j]);
1343 } 1171 }
@@ -1356,7 +1184,8 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1356{ 1184{
1357 const struct option kvm_events_report_options[] = { 1185 const struct option kvm_events_report_options[] = {
1358 OPT_STRING(0, "event", &kvm->report_event, "report event", 1186 OPT_STRING(0, "event", &kvm->report_event, "report event",
1359 "event for reporting: vmexit, mmio, ioport"), 1187 "event for reporting: vmexit, "
1188 "mmio (x86 only), ioport (x86 only)"),
1360 OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu, 1189 OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu,
1361 "vcpu id to report"), 1190 "vcpu id to report"),
1362 OPT_STRING('k', "key", &kvm->sort_key, "sort-key", 1191 OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
@@ -1391,16 +1220,16 @@ static struct perf_evlist *kvm_live_event_list(void)
1391{ 1220{
1392 struct perf_evlist *evlist; 1221 struct perf_evlist *evlist;
1393 char *tp, *name, *sys; 1222 char *tp, *name, *sys;
1394 unsigned int j;
1395 int err = -1; 1223 int err = -1;
1224 const char * const *events_tp;
1396 1225
1397 evlist = perf_evlist__new(); 1226 evlist = perf_evlist__new();
1398 if (evlist == NULL) 1227 if (evlist == NULL)
1399 return NULL; 1228 return NULL;
1400 1229
1401 for (j = 0; j < ARRAY_SIZE(kvm_events_tp); j++) { 1230 for (events_tp = kvm_events_tp; *events_tp; events_tp++) {
1402 1231
1403 tp = strdup(kvm_events_tp[j]); 1232 tp = strdup(*events_tp);
1404 if (tp == NULL) 1233 if (tp == NULL)
1405 goto out; 1234 goto out;
1406 1235
@@ -1409,7 +1238,7 @@ static struct perf_evlist *kvm_live_event_list(void)
1409 name = strchr(tp, ':'); 1238 name = strchr(tp, ':');
1410 if (name == NULL) { 1239 if (name == NULL) {
1411 pr_err("Error parsing %s tracepoint: subsystem delimiter not found\n", 1240 pr_err("Error parsing %s tracepoint: subsystem delimiter not found\n",
1412 kvm_events_tp[j]); 1241 *events_tp);
1413 free(tp); 1242 free(tp);
1414 goto out; 1243 goto out;
1415 } 1244 }
@@ -1417,7 +1246,7 @@ static struct perf_evlist *kvm_live_event_list(void)
1417 name++; 1246 name++;
1418 1247
1419 if (perf_evlist__add_newtp(evlist, sys, name, NULL)) { 1248 if (perf_evlist__add_newtp(evlist, sys, name, NULL)) {
1420 pr_err("Failed to add %s tracepoint to the list\n", kvm_events_tp[j]); 1249 pr_err("Failed to add %s tracepoint to the list\n", *events_tp);
1421 free(tp); 1250 free(tp);
1422 goto out; 1251 goto out;
1423 } 1252 }
@@ -1462,7 +1291,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1462 "key for sorting: sample(sort by samples number)" 1291 "key for sorting: sample(sort by samples number)"
1463 " time (sort by avg time)"), 1292 " time (sort by avg time)"),
1464 OPT_U64(0, "duration", &kvm->duration, 1293 OPT_U64(0, "duration", &kvm->duration,
1465 "show events other than HALT that take longer than duration usecs"), 1294 "show events other than"
1295 " HLT (x86 only) or Wait state (s390 only)"
1296 " that take longer than duration usecs"),
1466 OPT_END() 1297 OPT_END()
1467 }; 1298 };
1468 const char * const live_usage[] = { 1299 const char * const live_usage[] = {
@@ -1585,9 +1416,6 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
1585 .report_event = "vmexit", 1416 .report_event = "vmexit",
1586 .sort_key = "sample", 1417 .sort_key = "sample",
1587 1418
1588 .exit_reasons = svm_exit_reasons,
1589 .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons),
1590 .exit_reasons_isa = "SVM",
1591 }; 1419 };
1592 1420
1593 if (argc == 1) { 1421 if (argc == 1) {
@@ -1609,7 +1437,7 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
1609perf_stat: 1437perf_stat:
1610 return cmd_stat(argc, argv, NULL); 1438 return cmd_stat(argc, argv, NULL);
1611} 1439}
1612#endif 1440#endif /* HAVE_KVM_STAT_SUPPORT */
1613 1441
1614static int __cmd_record(const char *file_name, int argc, const char **argv) 1442static int __cmd_record(const char *file_name, int argc, const char **argv)
1615{ 1443{
@@ -1726,7 +1554,7 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
1726 return cmd_top(argc, argv, NULL); 1554 return cmd_top(argc, argv, NULL);
1727 else if (!strncmp(argv[0], "buildid-list", 12)) 1555 else if (!strncmp(argv[0], "buildid-list", 12))
1728 return __cmd_buildid_list(file_name, argc, argv); 1556 return __cmd_buildid_list(file_name, argc, argv);
1729#if defined(__i386__) || defined(__x86_64__) 1557#ifdef HAVE_KVM_STAT_SUPPORT
1730 else if (!strncmp(argv[0], "stat", 4)) 1558 else if (!strncmp(argv[0], "stat", 4))
1731 return kvm_cmd_stat(file_name, argc, argv); 1559 return kvm_cmd_stat(file_name, argc, argv);
1732#endif 1560#endif