Linux Perf
builtin-kvm.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0
2 #include "builtin.h"
3 #include "perf.h"
4 
5 #include "util/evsel.h"
6 #include "util/evlist.h"
7 #include "util/term.h"
8 #include "util/util.h"
9 #include "util/cache.h"
10 #include "util/symbol.h"
11 #include "util/thread.h"
12 #include "util/header.h"
13 #include "util/session.h"
14 #include "util/intlist.h"
15 #include <subcmd/parse-options.h>
16 #include "util/trace-event.h"
17 #include "util/debug.h"
18 #include "util/tool.h"
19 #include "util/stat.h"
20 #include "util/top.h"
21 #include "util/data.h"
22 #include "util/ordered-events.h"
23 
24 #include <sys/prctl.h>
25 #ifdef HAVE_TIMERFD_SUPPORT
26 #include <sys/timerfd.h>
27 #endif
28 #include <sys/time.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 
33 #include <linux/kernel.h>
34 #include <linux/time64.h>
35 #include <errno.h>
36 #include <inttypes.h>
37 #include <poll.h>
38 #include <termios.h>
39 #include <semaphore.h>
40 #include <signal.h>
41 #include <math.h>
42 
43 static const char *get_filename_for_perf_kvm(void)
44 {
45  const char *filename;
46 
47  if (perf_host && !perf_guest)
48  filename = strdup("perf.data.host");
49  else if (!perf_host && perf_guest)
50  filename = strdup("perf.data.guest");
51  else
52  filename = strdup("perf.data.kvm");
53 
54  return filename;
55 }
56 
57 #ifdef HAVE_KVM_STAT_SUPPORT
58 #include "util/kvm-stat.h"
59 
60 void exit_event_get_key(struct perf_evsel *evsel,
61  struct perf_sample *sample,
62  struct event_key *key)
63 {
64  key->info = 0;
65  key->key = perf_evsel__intval(evsel, sample, kvm_exit_reason);
66 }
67 
68 bool kvm_exit_event(struct perf_evsel *evsel)
69 {
70  return !strcmp(evsel->name, kvm_exit_trace);
71 }
72 
73 bool exit_event_begin(struct perf_evsel *evsel,
74  struct perf_sample *sample, struct event_key *key)
75 {
76  if (kvm_exit_event(evsel)) {
77  exit_event_get_key(evsel, sample, key);
78  return true;
79  }
80 
81  return false;
82 }
83 
84 bool kvm_entry_event(struct perf_evsel *evsel)
85 {
86  return !strcmp(evsel->name, kvm_entry_trace);
87 }
88 
89 bool exit_event_end(struct perf_evsel *evsel,
90  struct perf_sample *sample __maybe_unused,
91  struct event_key *key __maybe_unused)
92 {
93  return kvm_entry_event(evsel);
94 }
95 
96 static const char *get_exit_reason(struct perf_kvm_stat *kvm,
97  struct exit_reasons_table *tbl,
98  u64 exit_code)
99 {
100  while (tbl->reason != NULL) {
101  if (tbl->exit_code == exit_code)
102  return tbl->reason;
103  tbl++;
104  }
105 
106  pr_err("unknown kvm exit code:%lld on %s\n",
107  (unsigned long long)exit_code, kvm->exit_reasons_isa);
108  return "UNKNOWN";
109 }
110 
111 void exit_event_decode_key(struct perf_kvm_stat *kvm,
112  struct event_key *key,
113  char *decode)
114 {
115  const char *exit_reason = get_exit_reason(kvm, key->exit_reasons,
116  key->key);
117 
118  scnprintf(decode, decode_str_len, "%s", exit_reason);
119 }
120 
121 static bool register_kvm_events_ops(struct perf_kvm_stat *kvm)
122 {
123  struct kvm_reg_events_ops *events_ops = kvm_reg_events_ops;
124 
125  for (events_ops = kvm_reg_events_ops; events_ops->name; events_ops++) {
126  if (!strcmp(events_ops->name, kvm->report_event)) {
127  kvm->events_ops = events_ops->ops;
128  return true;
129  }
130  }
131 
132  return false;
133 }
134 
135 struct vcpu_event_record {
136  int vcpu_id;
137  u64 start_time;
138  struct kvm_event *last_event;
139 };
140 
141 
142 static void init_kvm_event_record(struct perf_kvm_stat *kvm)
143 {
144  unsigned int i;
145 
146  for (i = 0; i < EVENTS_CACHE_SIZE; i++)
147  INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
148 }
149 
150 #ifdef HAVE_TIMERFD_SUPPORT
151 static void clear_events_cache_stats(struct list_head *kvm_events_cache)
152 {
153  struct list_head *head;
154  struct kvm_event *event;
155  unsigned int i;
156  int j;
157 
158  for (i = 0; i < EVENTS_CACHE_SIZE; i++) {
159  head = &kvm_events_cache[i];
160  list_for_each_entry(event, head, hash_entry) {
161  /* reset stats for event */
162  event->total.time = 0;
163  init_stats(&event->total.stats);
164 
165  for (j = 0; j < event->max_vcpu; ++j) {
166  event->vcpu[j].time = 0;
167  init_stats(&event->vcpu[j].stats);
168  }
169  }
170  }
171 }
172 #endif
173 
174 static int kvm_events_hash_fn(u64 key)
175 {
176  return key & (EVENTS_CACHE_SIZE - 1);
177 }
178 
179 static bool kvm_event_expand(struct kvm_event *event, int vcpu_id)
180 {
181  int old_max_vcpu = event->max_vcpu;
182  void *prev;
183 
184  if (vcpu_id < event->max_vcpu)
185  return true;
186 
187  while (event->max_vcpu <= vcpu_id)
188  event->max_vcpu += DEFAULT_VCPU_NUM;
189 
190  prev = event->vcpu;
191  event->vcpu = realloc(event->vcpu,
192  event->max_vcpu * sizeof(*event->vcpu));
193  if (!event->vcpu) {
194  free(prev);
195  pr_err("Not enough memory\n");
196  return false;
197  }
198 
199  memset(event->vcpu + old_max_vcpu, 0,
200  (event->max_vcpu - old_max_vcpu) * sizeof(*event->vcpu));
201  return true;
202 }
203 
204 static struct kvm_event *kvm_alloc_init_event(struct event_key *key)
205 {
206  struct kvm_event *event;
207 
208  event = zalloc(sizeof(*event));
209  if (!event) {
210  pr_err("Not enough memory\n");
211  return NULL;
212  }
213 
214  event->key = *key;
215  init_stats(&event->total.stats);
216  return event;
217 }
218 
219 static struct kvm_event *find_create_kvm_event(struct perf_kvm_stat *kvm,
220  struct event_key *key)
221 {
222  struct kvm_event *event;
223  struct list_head *head;
224 
225  BUG_ON(key->key == INVALID_KEY);
226 
227  head = &kvm->kvm_events_cache[kvm_events_hash_fn(key->key)];
228  list_for_each_entry(event, head, hash_entry) {
229  if (event->key.key == key->key && event->key.info == key->info)
230  return event;
231  }
232 
233  event = kvm_alloc_init_event(key);
234  if (!event)
235  return NULL;
236 
237  list_add(&event->hash_entry, head);
238  return event;
239 }
240 
241 static bool handle_begin_event(struct perf_kvm_stat *kvm,
242  struct vcpu_event_record *vcpu_record,
243  struct event_key *key, u64 timestamp)
244 {
245  struct kvm_event *event = NULL;
246 
247  if (key->key != INVALID_KEY)
248  event = find_create_kvm_event(kvm, key);
249 
250  vcpu_record->last_event = event;
251  vcpu_record->start_time = timestamp;
252  return true;
253 }
254 
255 static void
256 kvm_update_event_stats(struct kvm_event_stats *kvm_stats, u64 time_diff)
257 {
258  kvm_stats->time += time_diff;
259  update_stats(&kvm_stats->stats, time_diff);
260 }
261 
262 static double kvm_event_rel_stddev(int vcpu_id, struct kvm_event *event)
263 {
264  struct kvm_event_stats *kvm_stats = &event->total;
265 
266  if (vcpu_id != -1)
267  kvm_stats = &event->vcpu[vcpu_id];
268 
269  return rel_stddev_stats(stddev_stats(&kvm_stats->stats),
270  avg_stats(&kvm_stats->stats));
271 }
272 
273 static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
274  u64 time_diff)
275 {
276  if (vcpu_id == -1) {
277  kvm_update_event_stats(&event->total, time_diff);
278  return true;
279  }
280 
281  if (!kvm_event_expand(event, vcpu_id))
282  return false;
283 
284  kvm_update_event_stats(&event->vcpu[vcpu_id], time_diff);
285  return true;
286 }
287 
288 static bool is_child_event(struct perf_kvm_stat *kvm,
289  struct perf_evsel *evsel,
290  struct perf_sample *sample,
291  struct event_key *key)
292 {
293  struct child_event_ops *child_ops;
294 
295  child_ops = kvm->events_ops->child_ops;
296 
297  if (!child_ops)
298  return false;
299 
300  for (; child_ops->name; child_ops++) {
301  if (!strcmp(evsel->name, child_ops->name)) {
302  child_ops->get_key(evsel, sample, key);
303  return true;
304  }
305  }
306 
307  return false;
308 }
309 
310 static bool handle_child_event(struct perf_kvm_stat *kvm,
311  struct vcpu_event_record *vcpu_record,
312  struct event_key *key,
313  struct perf_sample *sample __maybe_unused)
314 {
315  struct kvm_event *event = NULL;
316 
317  if (key->key != INVALID_KEY)
318  event = find_create_kvm_event(kvm, key);
319 
320  vcpu_record->last_event = event;
321 
322  return true;
323 }
324 
325 static bool skip_event(const char *event)
326 {
327  const char * const *skip_events;
328 
329  for (skip_events = kvm_skip_events; *skip_events; skip_events++)
330  if (!strcmp(event, *skip_events))
331  return true;
332 
333  return false;
334 }
335 
336 static bool handle_end_event(struct perf_kvm_stat *kvm,
337  struct vcpu_event_record *vcpu_record,
338  struct event_key *key,
339  struct perf_sample *sample)
340 {
341  struct kvm_event *event;
342  u64 time_begin, time_diff;
343  int vcpu;
344 
345  if (kvm->trace_vcpu == -1)
346  vcpu = -1;
347  else
348  vcpu = vcpu_record->vcpu_id;
349 
350  event = vcpu_record->last_event;
351  time_begin = vcpu_record->start_time;
352 
353  /* The begin event is not caught. */
354  if (!time_begin)
355  return true;
356 
357  /*
358  * In some case, the 'begin event' only records the start timestamp,
359  * the actual event is recognized in the 'end event' (e.g. mmio-event).
360  */
361 
362  /* Both begin and end events did not get the key. */
363  if (!event && key->key == INVALID_KEY)
364  return true;
365 
366  if (!event)
367  event = find_create_kvm_event(kvm, key);
368 
369  if (!event)
370  return false;
371 
372  vcpu_record->last_event = NULL;
373  vcpu_record->start_time = 0;
374 
375  /* seems to happen once in a while during live mode */
376  if (sample->time < time_begin) {
377  pr_debug("End time before begin time; skipping event.\n");
378  return true;
379  }
380 
381  time_diff = sample->time - time_begin;
382 
383  if (kvm->duration && time_diff > kvm->duration) {
384  char decode[decode_str_len];
385 
386  kvm->events_ops->decode_key(kvm, &event->key, decode);
387  if (!skip_event(decode)) {
388  pr_info("%" PRIu64 " VM %d, vcpu %d: %s event took %" PRIu64 "usec\n",
389  sample->time, sample->pid, vcpu_record->vcpu_id,
390  decode, time_diff / NSEC_PER_USEC);
391  }
392  }
393 
394  return update_kvm_event(event, vcpu, time_diff);
395 }
396 
397 static
398 struct vcpu_event_record *per_vcpu_record(struct thread *thread,
399  struct perf_evsel *evsel,
400  struct perf_sample *sample)
401 {
402  /* Only kvm_entry records vcpu id. */
403  if (!thread__priv(thread) && kvm_entry_event(evsel)) {
404  struct vcpu_event_record *vcpu_record;
405 
406  vcpu_record = zalloc(sizeof(*vcpu_record));
407  if (!vcpu_record) {
408  pr_err("%s: Not enough memory\n", __func__);
409  return NULL;
410  }
411 
412  vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample,
413  vcpu_id_str);
414  thread__set_priv(thread, vcpu_record);
415  }
416 
417  return thread__priv(thread);
418 }
419 
420 static bool handle_kvm_event(struct perf_kvm_stat *kvm,
421  struct thread *thread,
422  struct perf_evsel *evsel,
423  struct perf_sample *sample)
424 {
425  struct vcpu_event_record *vcpu_record;
426  struct event_key key = { .key = INVALID_KEY,
427  .exit_reasons = kvm->exit_reasons };
428 
429  vcpu_record = per_vcpu_record(thread, evsel, sample);
430  if (!vcpu_record)
431  return true;
432 
433  /* only process events for vcpus user cares about */
434  if ((kvm->trace_vcpu != -1) &&
435  (kvm->trace_vcpu != vcpu_record->vcpu_id))
436  return true;
437 
438  if (kvm->events_ops->is_begin_event(evsel, sample, &key))
439  return handle_begin_event(kvm, vcpu_record, &key, sample->time);
440 
441  if (is_child_event(kvm, evsel, sample, &key))
442  return handle_child_event(kvm, vcpu_record, &key, sample);
443 
444  if (kvm->events_ops->is_end_event(evsel, sample, &key))
445  return handle_end_event(kvm, vcpu_record, &key, sample);
446 
447  return true;
448 }
449 
450 #define GET_EVENT_KEY(func, field) \
451 static u64 get_event_ ##func(struct kvm_event *event, int vcpu) \
452 { \
453  if (vcpu == -1) \
454  return event->total.field; \
455  \
456  if (vcpu >= event->max_vcpu) \
457  return 0; \
458  \
459  return event->vcpu[vcpu].field; \
460 }
461 
462 #define COMPARE_EVENT_KEY(func, field) \
463 GET_EVENT_KEY(func, field) \
464 static int compare_kvm_event_ ## func(struct kvm_event *one, \
465  struct kvm_event *two, int vcpu)\
466 { \
467  return get_event_ ##func(one, vcpu) > \
468  get_event_ ##func(two, vcpu); \
469 }
470 
471 GET_EVENT_KEY(time, time);
472 COMPARE_EVENT_KEY(count, stats.n);
473 COMPARE_EVENT_KEY(mean, stats.mean);
474 GET_EVENT_KEY(max, stats.max);
475 GET_EVENT_KEY(min, stats.min);
476 
477 #define DEF_SORT_NAME_KEY(name, compare_key) \
478  { #name, compare_kvm_event_ ## compare_key }
479 
480 static struct kvm_event_key keys[] = {
481  DEF_SORT_NAME_KEY(sample, count),
482  DEF_SORT_NAME_KEY(time, mean),
483  { NULL, NULL }
484 };
485 
486 static bool select_key(struct perf_kvm_stat *kvm)
487 {
488  int i;
489 
490  for (i = 0; keys[i].name; i++) {
491  if (!strcmp(keys[i].name, kvm->sort_key)) {
492  kvm->compare = keys[i].key;
493  return true;
494  }
495  }
496 
497  pr_err("Unknown compare key:%s\n", kvm->sort_key);
498  return false;
499 }
500 
501 static void insert_to_result(struct rb_root *result, struct kvm_event *event,
502  key_cmp_fun bigger, int vcpu)
503 {
504  struct rb_node **rb = &result->rb_node;
505  struct rb_node *parent = NULL;
506  struct kvm_event *p;
507 
508  while (*rb) {
509  p = container_of(*rb, struct kvm_event, rb);
510  parent = *rb;
511 
512  if (bigger(event, p, vcpu))
513  rb = &(*rb)->rb_left;
514  else
515  rb = &(*rb)->rb_right;
516  }
517 
518  rb_link_node(&event->rb, parent, rb);
519  rb_insert_color(&event->rb, result);
520 }
521 
522 static void
523 update_total_count(struct perf_kvm_stat *kvm, struct kvm_event *event)
524 {
525  int vcpu = kvm->trace_vcpu;
526 
527  kvm->total_count += get_event_count(event, vcpu);
528  kvm->total_time += get_event_time(event, vcpu);
529 }
530 
531 static bool event_is_valid(struct kvm_event *event, int vcpu)
532 {
533  return !!get_event_count(event, vcpu);
534 }
535 
536 static void sort_result(struct perf_kvm_stat *kvm)
537 {
538  unsigned int i;
539  int vcpu = kvm->trace_vcpu;
540  struct kvm_event *event;
541 
542  for (i = 0; i < EVENTS_CACHE_SIZE; i++) {
543  list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry) {
544  if (event_is_valid(event, vcpu)) {
545  update_total_count(kvm, event);
546  insert_to_result(&kvm->result, event,
547  kvm->compare, vcpu);
548  }
549  }
550  }
551 }
552 
553 /* returns left most element of result, and erase it */
554 static struct kvm_event *pop_from_result(struct rb_root *result)
555 {
556  struct rb_node *node = rb_first(result);
557 
558  if (!node)
559  return NULL;
560 
561  rb_erase(node, result);
562  return container_of(node, struct kvm_event, rb);
563 }
564 
565 static void print_vcpu_info(struct perf_kvm_stat *kvm)
566 {
567  int vcpu = kvm->trace_vcpu;
568 
569  pr_info("Analyze events for ");
570 
571  if (kvm->opts.target.system_wide)
572  pr_info("all VMs, ");
573  else if (kvm->opts.target.pid)
574  pr_info("pid(s) %s, ", kvm->opts.target.pid);
575  else
576  pr_info("dazed and confused on what is monitored, ");
577 
578  if (vcpu == -1)
579  pr_info("all VCPUs:\n\n");
580  else
581  pr_info("VCPU %d:\n\n", vcpu);
582 }
583 
584 static void show_timeofday(void)
585 {
586  char date[64];
587  struct timeval tv;
588  struct tm ltime;
589 
590  gettimeofday(&tv, NULL);
591  if (localtime_r(&tv.tv_sec, &ltime)) {
592  strftime(date, sizeof(date), "%H:%M:%S", &ltime);
593  pr_info("%s.%06ld", date, tv.tv_usec);
594  } else
595  pr_info("00:00:00.000000");
596 
597  return;
598 }
599 
600 static void print_result(struct perf_kvm_stat *kvm)
601 {
602  char decode[decode_str_len];
603  struct kvm_event *event;
604  int vcpu = kvm->trace_vcpu;
605 
606  if (kvm->live) {
607  puts(CONSOLE_CLEAR);
608  show_timeofday();
609  }
610 
611  pr_info("\n\n");
612  print_vcpu_info(kvm);
613  pr_info("%*s ", decode_str_len, kvm->events_ops->name);
614  pr_info("%10s ", "Samples");
615  pr_info("%9s ", "Samples%");
616 
617  pr_info("%9s ", "Time%");
618  pr_info("%11s ", "Min Time");
619  pr_info("%11s ", "Max Time");
620  pr_info("%16s ", "Avg time");
621  pr_info("\n\n");
622 
623  while ((event = pop_from_result(&kvm->result))) {
624  u64 ecount, etime, max, min;
625 
626  ecount = get_event_count(event, vcpu);
627  etime = get_event_time(event, vcpu);
628  max = get_event_max(event, vcpu);
629  min = get_event_min(event, vcpu);
630 
631  kvm->events_ops->decode_key(kvm, &event->key, decode);
632  pr_info("%*s ", decode_str_len, decode);
633  pr_info("%10llu ", (unsigned long long)ecount);
634  pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
635  pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
636  pr_info("%9.2fus ", (double)min / NSEC_PER_USEC);
637  pr_info("%9.2fus ", (double)max / NSEC_PER_USEC);
638  pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount / NSEC_PER_USEC,
639  kvm_event_rel_stddev(vcpu, event));
640  pr_info("\n");
641  }
642 
643  pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n",
644  kvm->total_count, kvm->total_time / (double)NSEC_PER_USEC);
645 
646  if (kvm->lost_events)
647  pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events);
648 }
649 
650 #ifdef HAVE_TIMERFD_SUPPORT
651 static int process_lost_event(struct perf_tool *tool,
652  union perf_event *event __maybe_unused,
653  struct perf_sample *sample __maybe_unused,
654  struct machine *machine __maybe_unused)
655 {
656  struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat, tool);
657 
658  kvm->lost_events++;
659  return 0;
660 }
661 #endif
662 
663 static bool skip_sample(struct perf_kvm_stat *kvm,
664  struct perf_sample *sample)
665 {
666  if (kvm->pid_list && intlist__find(kvm->pid_list, sample->pid) == NULL)
667  return true;
668 
669  return false;
670 }
671 
672 static int process_sample_event(struct perf_tool *tool,
673  union perf_event *event,
674  struct perf_sample *sample,
675  struct perf_evsel *evsel,
676  struct machine *machine)
677 {
678  int err = 0;
679  struct thread *thread;
680  struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat,
681  tool);
682 
683  if (skip_sample(kvm, sample))
684  return 0;
685 
686  thread = machine__findnew_thread(machine, sample->pid, sample->tid);
687  if (thread == NULL) {
688  pr_debug("problem processing %d event, skipping it.\n",
689  event->header.type);
690  return -1;
691  }
692 
693  if (!handle_kvm_event(kvm, thread, evsel, sample))
694  err = -1;
695 
696  thread__put(thread);
697  return err;
698 }
699 
700 static int cpu_isa_config(struct perf_kvm_stat *kvm)
701 {
702  char buf[64], *cpuid;
703  int err;
704 
705  if (kvm->live) {
706  err = get_cpuid(buf, sizeof(buf));
707  if (err != 0) {
708  pr_err("Failed to look up CPU type\n");
709  return err;
710  }
711  cpuid = buf;
712  } else
713  cpuid = kvm->session->header.env.cpuid;
714 
715  if (!cpuid) {
716  pr_err("Failed to look up CPU type\n");
717  return -EINVAL;
718  }
719 
720  err = cpu_isa_init(kvm, cpuid);
721  if (err == -ENOTSUP)
722  pr_err("CPU %s is not supported.\n", cpuid);
723 
724  return err;
725 }
726 
727 static bool verify_vcpu(int vcpu)
728 {
729  if (vcpu != -1 && vcpu < 0) {
730  pr_err("Invalid vcpu:%d.\n", vcpu);
731  return false;
732  }
733 
734  return true;
735 }
736 
737 #ifdef HAVE_TIMERFD_SUPPORT
738 /* keeping the max events to a modest level to keep
739  * the processing of samples per mmap smooth.
740  */
741 #define PERF_KVM__MAX_EVENTS_PER_MMAP 25
742 
743 static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
744  u64 *mmap_time)
745 {
746  struct perf_evlist *evlist = kvm->evlist;
747  union perf_event *event;
748  struct perf_mmap *md;
749  u64 timestamp;
750  s64 n = 0;
751  int err;
752 
753  *mmap_time = ULLONG_MAX;
754  md = &evlist->mmap[idx];
755  err = perf_mmap__read_init(md);
756  if (err < 0)
757  return (err == -EAGAIN) ? 0 : -1;
758 
759  while ((event = perf_mmap__read_event(md)) != NULL) {
760  err = perf_evlist__parse_sample_timestamp(evlist, event, &timestamp);
761  if (err) {
762  perf_mmap__consume(md);
763  pr_err("Failed to parse sample\n");
764  return -1;
765  }
766 
767  err = perf_session__queue_event(kvm->session, event, timestamp, 0);
768  /*
769  * FIXME: Here we can't consume the event, as perf_session__queue_event will
770  * point to it, and it'll get possibly overwritten by the kernel.
771  */
772  perf_mmap__consume(md);
773 
774  if (err) {
775  pr_err("Failed to enqueue sample: %d\n", err);
776  return -1;
777  }
778 
779  /* save time stamp of our first sample for this mmap */
780  if (n == 0)
781  *mmap_time = timestamp;
782 
783  /* limit events per mmap handled all at once */
784  n++;
785  if (n == PERF_KVM__MAX_EVENTS_PER_MMAP)
786  break;
787  }
788 
790  return n;
791 }
792 
793 static int perf_kvm__mmap_read(struct perf_kvm_stat *kvm)
794 {
795  int i, err, throttled = 0;
796  s64 n, ntotal = 0;
797  u64 flush_time = ULLONG_MAX, mmap_time;
798 
799  for (i = 0; i < kvm->evlist->nr_mmaps; i++) {
800  n = perf_kvm__mmap_read_idx(kvm, i, &mmap_time);
801  if (n < 0)
802  return -1;
803 
804  /* flush time is going to be the minimum of all the individual
805  * mmap times. Essentially, we flush all the samples queued up
806  * from the last pass under our minimal start time -- that leaves
807  * a very small race for samples to come in with a lower timestamp.
808  * The ioctl to return the perf_clock timestamp should close the
809  * race entirely.
810  */
811  if (mmap_time < flush_time)
812  flush_time = mmap_time;
813 
814  ntotal += n;
815  if (n == PERF_KVM__MAX_EVENTS_PER_MMAP)
816  throttled = 1;
817  }
818 
819  /* flush queue after each round in which we processed events */
820  if (ntotal) {
821  struct ordered_events *oe = &kvm->session->ordered_events;
822 
823  oe->next_flush = flush_time;
825  if (err) {
826  if (kvm->lost_events)
827  pr_info("\nLost events: %" PRIu64 "\n\n",
828  kvm->lost_events);
829  return err;
830  }
831  }
832 
833  return throttled;
834 }
835 
836 static volatile int done;
837 
838 static void sig_handler(int sig __maybe_unused)
839 {
840  done = 1;
841 }
842 
843 static int perf_kvm__timerfd_create(struct perf_kvm_stat *kvm)
844 {
845  struct itimerspec new_value;
846  int rc = -1;
847 
848  kvm->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
849  if (kvm->timerfd < 0) {
850  pr_err("timerfd_create failed\n");
851  goto out;
852  }
853 
854  new_value.it_value.tv_sec = kvm->display_time;
855  new_value.it_value.tv_nsec = 0;
856  new_value.it_interval.tv_sec = kvm->display_time;
857  new_value.it_interval.tv_nsec = 0;
858 
859  if (timerfd_settime(kvm->timerfd, 0, &new_value, NULL) != 0) {
860  pr_err("timerfd_settime failed: %d\n", errno);
861  close(kvm->timerfd);
862  goto out;
863  }
864 
865  rc = 0;
866 out:
867  return rc;
868 }
869 
870 static int perf_kvm__handle_timerfd(struct perf_kvm_stat *kvm)
871 {
872  uint64_t c;
873  int rc;
874 
875  rc = read(kvm->timerfd, &c, sizeof(uint64_t));
876  if (rc < 0) {
877  if (errno == EAGAIN)
878  return 0;
879 
880  pr_err("Failed to read timer fd: %d\n", errno);
881  return -1;
882  }
883 
884  if (rc != sizeof(uint64_t)) {
885  pr_err("Error reading timer fd - invalid size returned\n");
886  return -1;
887  }
888 
889  if (c != 1)
890  pr_debug("Missed timer beats: %" PRIu64 "\n", c-1);
891 
892  /* update display */
893  sort_result(kvm);
894  print_result(kvm);
895 
896  /* reset counts */
897  clear_events_cache_stats(kvm->kvm_events_cache);
898  kvm->total_count = 0;
899  kvm->total_time = 0;
900  kvm->lost_events = 0;
901 
902  return 0;
903 }
904 
905 static int fd_set_nonblock(int fd)
906 {
907  long arg = 0;
908 
909  arg = fcntl(fd, F_GETFL);
910  if (arg < 0) {
911  pr_err("Failed to get current flags for fd %d\n", fd);
912  return -1;
913  }
914 
915  if (fcntl(fd, F_SETFL, arg | O_NONBLOCK) < 0) {
916  pr_err("Failed to set non-block option on fd %d\n", fd);
917  return -1;
918  }
919 
920  return 0;
921 }
922 
923 static int perf_kvm__handle_stdin(void)
924 {
925  int c;
926 
927  c = getc(stdin);
928  if (c == 'q')
929  return 1;
930 
931  return 0;
932 }
933 
934 static int kvm_events_live_report(struct perf_kvm_stat *kvm)
935 {
936  int nr_stdin, ret, err = -EINVAL;
937  struct termios save;
938 
939  /* live flag must be set first */
940  kvm->live = true;
941 
942  ret = cpu_isa_config(kvm);
943  if (ret < 0)
944  return ret;
945 
946  if (!verify_vcpu(kvm->trace_vcpu) ||
947  !select_key(kvm) ||
948  !register_kvm_events_ops(kvm)) {
949  goto out;
950  }
951 
952  set_term_quiet_input(&save);
953  init_kvm_event_record(kvm);
954 
955  signal(SIGINT, sig_handler);
956  signal(SIGTERM, sig_handler);
957 
958  /* add timer fd */
959  if (perf_kvm__timerfd_create(kvm) < 0) {
960  err = -1;
961  goto out;
962  }
963 
964  if (perf_evlist__add_pollfd(kvm->evlist, kvm->timerfd) < 0)
965  goto out;
966 
967  nr_stdin = perf_evlist__add_pollfd(kvm->evlist, fileno(stdin));
968  if (nr_stdin < 0)
969  goto out;
970 
971  if (fd_set_nonblock(fileno(stdin)) != 0)
972  goto out;
973 
974  /* everything is good - enable the events and process */
976 
977  while (!done) {
978  struct fdarray *fda = &kvm->evlist->pollfd;
979  int rc;
980 
981  rc = perf_kvm__mmap_read(kvm);
982  if (rc < 0)
983  break;
984 
985  err = perf_kvm__handle_timerfd(kvm);
986  if (err)
987  goto out;
988 
989  if (fda->entries[nr_stdin].revents & POLLIN)
990  done = perf_kvm__handle_stdin();
991 
992  if (!rc && !done)
993  err = fdarray__poll(fda, 100);
994  }
995 
997 
998  if (err == 0) {
999  sort_result(kvm);
1000  print_result(kvm);
1001  }
1002 
1003 out:
1004  if (kvm->timerfd >= 0)
1005  close(kvm->timerfd);
1006 
1007  tcsetattr(0, TCSAFLUSH, &save);
1008  return err;
1009 }
1010 
1011 static int kvm_live_open_events(struct perf_kvm_stat *kvm)
1012 {
1013  int err, rc = -1;
1014  struct perf_evsel *pos;
1015  struct perf_evlist *evlist = kvm->evlist;
1016  char sbuf[STRERR_BUFSIZE];
1017 
1018  perf_evlist__config(evlist, &kvm->opts, NULL);
1019 
1020  /*
1021  * Note: exclude_{guest,host} do not apply here.
1022  * This command processes KVM tracepoints from host only
1023  */
1024  evlist__for_each_entry(evlist, pos) {
1025  struct perf_event_attr *attr = &pos->attr;
1026 
1027  /* make sure these *are* set */
1028  perf_evsel__set_sample_bit(pos, TID);
1029  perf_evsel__set_sample_bit(pos, TIME);
1031  perf_evsel__set_sample_bit(pos, RAW);
1032  /* make sure these are *not*; want as small a sample as possible */
1033  perf_evsel__reset_sample_bit(pos, PERIOD);
1035  perf_evsel__reset_sample_bit(pos, CALLCHAIN);
1036  perf_evsel__reset_sample_bit(pos, ADDR);
1037  perf_evsel__reset_sample_bit(pos, READ);
1038  attr->mmap = 0;
1039  attr->comm = 0;
1040  attr->task = 0;
1041 
1042  attr->sample_period = 1;
1043 
1044  attr->watermark = 0;
1045  attr->wakeup_events = 1000;
1046 
1047  /* will enable all once we are ready */
1048  attr->disabled = 1;
1049  }
1050 
1051  err = perf_evlist__open(evlist);
1052  if (err < 0) {
1053  printf("Couldn't create the events: %s\n",
1054  str_error_r(errno, sbuf, sizeof(sbuf)));
1055  goto out;
1056  }
1057 
1058  if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages) < 0) {
1059  ui__error("Failed to mmap the events: %s\n",
1060  str_error_r(errno, sbuf, sizeof(sbuf)));
1061  perf_evlist__close(evlist);
1062  goto out;
1063  }
1064 
1065  rc = 0;
1066 
1067 out:
1068  return rc;
1069 }
1070 #endif
1071 
1072 static int read_events(struct perf_kvm_stat *kvm)
1073 {
1074  int ret;
1075 
1076  struct perf_tool eops = {
1078  .comm = perf_event__process_comm,
1079  .namespaces = perf_event__process_namespaces,
1080  .ordered_events = true,
1081  };
1082  struct perf_data file = {
1083  .file = {
1084  .path = kvm->file_name,
1085  },
1086  .mode = PERF_DATA_MODE_READ,
1087  .force = kvm->force,
1088  };
1089 
1090  kvm->tool = eops;
1091  kvm->session = perf_session__new(&file, false, &kvm->tool);
1092  if (!kvm->session) {
1093  pr_err("Initializing perf session failed\n");
1094  return -1;
1095  }
1096 
1097  symbol__init(&kvm->session->header.env);
1098 
1099  if (!perf_session__has_traces(kvm->session, "kvm record")) {
1100  ret = -EINVAL;
1101  goto out_delete;
1102  }
1103 
1104  /*
1105  * Do not use 'isa' recorded in kvm_exit tracepoint since it is not
1106  * traced in the old kernel.
1107  */
1108  ret = cpu_isa_config(kvm);
1109  if (ret < 0)
1110  goto out_delete;
1111 
1113 
1114 out_delete:
1116  return ret;
1117 }
1118 
1119 static int parse_target_str(struct perf_kvm_stat *kvm)
1120 {
1121  if (kvm->opts.target.pid) {
1122  kvm->pid_list = intlist__new(kvm->opts.target.pid);
1123  if (kvm->pid_list == NULL) {
1124  pr_err("Error parsing process id string\n");
1125  return -EINVAL;
1126  }
1127  }
1128 
1129  return 0;
1130 }
1131 
1132 static int kvm_events_report_vcpu(struct perf_kvm_stat *kvm)
1133 {
1134  int ret = -EINVAL;
1135  int vcpu = kvm->trace_vcpu;
1136 
1137  if (parse_target_str(kvm) != 0)
1138  goto exit;
1139 
1140  if (!verify_vcpu(vcpu))
1141  goto exit;
1142 
1143  if (!select_key(kvm))
1144  goto exit;
1145 
1146  if (!register_kvm_events_ops(kvm))
1147  goto exit;
1148 
1149  init_kvm_event_record(kvm);
1150  setup_pager();
1151 
1152  ret = read_events(kvm);
1153  if (ret)
1154  goto exit;
1155 
1156  sort_result(kvm);
1157  print_result(kvm);
1158 
1159 exit:
1160  return ret;
1161 }
1162 
1163 #define STRDUP_FAIL_EXIT(s) \
1164  ({ char *_p; \
1165  _p = strdup(s); \
1166  if (!_p) \
1167  return -ENOMEM; \
1168  _p; \
1169  })
1170 
1171 int __weak setup_kvm_events_tp(struct perf_kvm_stat *kvm __maybe_unused)
1172 {
1173  return 0;
1174 }
1175 
1176 static int
1177 kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
1178 {
1179  unsigned int rec_argc, i, j, events_tp_size;
1180  const char **rec_argv;
1181  const char * const record_args[] = {
1182  "record",
1183  "-R",
1184  "-m", "1024",
1185  "-c", "1",
1186  };
1187  const char * const kvm_stat_record_usage[] = {
1188  "perf kvm stat record [<options>]",
1189  NULL
1190  };
1191  const char * const *events_tp;
1192  int ret;
1193 
1194  events_tp_size = 0;
1195  ret = setup_kvm_events_tp(kvm);
1196  if (ret < 0) {
1197  pr_err("Unable to setup the kvm tracepoints\n");
1198  return ret;
1199  }
1200 
1201  for (events_tp = kvm_events_tp; *events_tp; events_tp++)
1202  events_tp_size++;
1203 
1204  rec_argc = ARRAY_SIZE(record_args) + argc + 2 +
1205  2 * events_tp_size;
1206  rec_argv = calloc(rec_argc + 1, sizeof(char *));
1207 
1208  if (rec_argv == NULL)
1209  return -ENOMEM;
1210 
1211  for (i = 0; i < ARRAY_SIZE(record_args); i++)
1212  rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
1213 
1214  for (j = 0; j < events_tp_size; j++) {
1215  rec_argv[i++] = "-e";
1216  rec_argv[i++] = STRDUP_FAIL_EXIT(kvm_events_tp[j]);
1217  }
1218 
1219  rec_argv[i++] = STRDUP_FAIL_EXIT("-o");
1220  rec_argv[i++] = STRDUP_FAIL_EXIT(kvm->file_name);
1221 
1222  for (j = 1; j < (unsigned int)argc; j++, i++)
1223  rec_argv[i] = argv[j];
1224 
1225  set_option_flag(record_options, 'e', "event", PARSE_OPT_HIDDEN);
1226  set_option_flag(record_options, 0, "filter", PARSE_OPT_HIDDEN);
1227  set_option_flag(record_options, 'R', "raw-samples", PARSE_OPT_HIDDEN);
1228 
1229  set_option_flag(record_options, 'F', "freq", PARSE_OPT_DISABLED);
1230  set_option_flag(record_options, 0, "group", PARSE_OPT_DISABLED);
1231  set_option_flag(record_options, 'g', NULL, PARSE_OPT_DISABLED);
1232  set_option_flag(record_options, 0, "call-graph", PARSE_OPT_DISABLED);
1233  set_option_flag(record_options, 'd', "data", PARSE_OPT_DISABLED);
1234  set_option_flag(record_options, 'T', "timestamp", PARSE_OPT_DISABLED);
1235  set_option_flag(record_options, 'P', "period", PARSE_OPT_DISABLED);
1236  set_option_flag(record_options, 'n', "no-samples", PARSE_OPT_DISABLED);
1237  set_option_flag(record_options, 'N', "no-buildid-cache", PARSE_OPT_DISABLED);
1238  set_option_flag(record_options, 'B', "no-buildid", PARSE_OPT_DISABLED);
1239  set_option_flag(record_options, 'G', "cgroup", PARSE_OPT_DISABLED);
1240  set_option_flag(record_options, 'b', "branch-any", PARSE_OPT_DISABLED);
1241  set_option_flag(record_options, 'j', "branch-filter", PARSE_OPT_DISABLED);
1242  set_option_flag(record_options, 'W', "weight", PARSE_OPT_DISABLED);
1243  set_option_flag(record_options, 0, "transaction", PARSE_OPT_DISABLED);
1244 
1245  record_usage = kvm_stat_record_usage;
1246  return cmd_record(i, rec_argv);
1247 }
1248 
1249 static int
1250 kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1251 {
1252  const struct option kvm_events_report_options[] = {
1253  OPT_STRING(0, "event", &kvm->report_event, "report event",
1254  "event for reporting: vmexit, "
1255  "mmio (x86 only), ioport (x86 only)"),
1256  OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu,
1257  "vcpu id to report"),
1258  OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
1259  "key for sorting: sample(sort by samples number)"
1260  " time (sort by avg time)"),
1261  OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
1262  "analyze events only for given process id(s)"),
1263  OPT_BOOLEAN('f', "force", &kvm->force, "don't complain, do it"),
1264  OPT_END()
1265  };
1266 
1267  const char * const kvm_events_report_usage[] = {
1268  "perf kvm stat report [<options>]",
1269  NULL
1270  };
1271 
1272  if (argc) {
1273  argc = parse_options(argc, argv,
1274  kvm_events_report_options,
1275  kvm_events_report_usage, 0);
1276  if (argc)
1277  usage_with_options(kvm_events_report_usage,
1278  kvm_events_report_options);
1279  }
1280 
1281  if (!kvm->opts.target.pid)
1282  kvm->opts.target.system_wide = true;
1283 
1284  return kvm_events_report_vcpu(kvm);
1285 }
1286 
1287 #ifdef HAVE_TIMERFD_SUPPORT
1288 static struct perf_evlist *kvm_live_event_list(void)
1289 {
1290  struct perf_evlist *evlist;
1291  char *tp, *name, *sys;
1292  int err = -1;
1293  const char * const *events_tp;
1294 
1295  evlist = perf_evlist__new();
1296  if (evlist == NULL)
1297  return NULL;
1298 
1299  for (events_tp = kvm_events_tp; *events_tp; events_tp++) {
1300 
1301  tp = strdup(*events_tp);
1302  if (tp == NULL)
1303  goto out;
1304 
1305  /* split tracepoint into subsystem and name */
1306  sys = tp;
1307  name = strchr(tp, ':');
1308  if (name == NULL) {
1309  pr_err("Error parsing %s tracepoint: subsystem delimiter not found\n",
1310  *events_tp);
1311  free(tp);
1312  goto out;
1313  }
1314  *name = '\0';
1315  name++;
1316 
1317  if (perf_evlist__add_newtp(evlist, sys, name, NULL)) {
1318  pr_err("Failed to add %s tracepoint to the list\n", *events_tp);
1319  free(tp);
1320  goto out;
1321  }
1322 
1323  free(tp);
1324  }
1325 
1326  err = 0;
1327 
1328 out:
1329  if (err) {
1330  perf_evlist__delete(evlist);
1331  evlist = NULL;
1332  }
1333 
1334  return evlist;
1335 }
1336 
1337 static int kvm_events_live(struct perf_kvm_stat *kvm,
1338  int argc, const char **argv)
1339 {
1340  char errbuf[BUFSIZ];
1341  int err;
1342 
1343  const struct option live_options[] = {
1344  OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
1345  "record events on existing process id"),
1346  OPT_CALLBACK('m', "mmap-pages", &kvm->opts.mmap_pages, "pages",
1347  "number of mmap data pages",
1349  OPT_INCR('v', "verbose", &verbose,
1350  "be more verbose (show counter open errors, etc)"),
1351  OPT_BOOLEAN('a', "all-cpus", &kvm->opts.target.system_wide,
1352  "system-wide collection from all CPUs"),
1353  OPT_UINTEGER('d', "display", &kvm->display_time,
1354  "time in seconds between display updates"),
1355  OPT_STRING(0, "event", &kvm->report_event, "report event",
1356  "event for reporting: "
1357  "vmexit, mmio (x86 only), ioport (x86 only)"),
1358  OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu,
1359  "vcpu id to report"),
1360  OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
1361  "key for sorting: sample(sort by samples number)"
1362  " time (sort by avg time)"),
1363  OPT_U64(0, "duration", &kvm->duration,
1364  "show events other than"
1365  " HLT (x86 only) or Wait state (s390 only)"
1366  " that take longer than duration usecs"),
1367  OPT_UINTEGER(0, "proc-map-timeout", &kvm->opts.proc_map_timeout,
1368  "per thread proc mmap processing timeout in ms"),
1369  OPT_END()
1370  };
1371  const char * const live_usage[] = {
1372  "perf kvm stat live [<options>]",
1373  NULL
1374  };
1375  struct perf_data data = {
1377  };
1378 
1379 
1380  /* event handling */
1385  kvm->tool.lost = process_lost_event;
1387  kvm->tool.ordered_events = true;
1389 
1390  /* set defaults */
1391  kvm->display_time = 1;
1392  kvm->opts.user_interval = 1;
1393  kvm->opts.mmap_pages = 512;
1394  kvm->opts.target.uses_mmap = false;
1395  kvm->opts.target.uid_str = NULL;
1396  kvm->opts.target.uid = UINT_MAX;
1397  kvm->opts.proc_map_timeout = 500;
1398 
1399  symbol__init(NULL);
1401 
1402  use_browser = 0;
1403 
1404  if (argc) {
1405  argc = parse_options(argc, argv, live_options,
1406  live_usage, 0);
1407  if (argc)
1408  usage_with_options(live_usage, live_options);
1409  }
1410 
1411  kvm->duration *= NSEC_PER_USEC; /* convert usec to nsec */
1412 
1413  /*
1414  * target related setups
1415  */
1416  err = target__validate(&kvm->opts.target);
1417  if (err) {
1418  target__strerror(&kvm->opts.target, err, errbuf, BUFSIZ);
1419  ui__warning("%s", errbuf);
1420  }
1421 
1422  if (target__none(&kvm->opts.target))
1423  kvm->opts.target.system_wide = true;
1424 
1425 
1426  /*
1427  * generate the event list
1428  */
1429  err = setup_kvm_events_tp(kvm);
1430  if (err < 0) {
1431  pr_err("Unable to setup the kvm tracepoints\n");
1432  return err;
1433  }
1434 
1435  kvm->evlist = kvm_live_event_list();
1436  if (kvm->evlist == NULL) {
1437  err = -1;
1438  goto out;
1439  }
1440 
1441  if (perf_evlist__create_maps(kvm->evlist, &kvm->opts.target) < 0)
1442  usage_with_options(live_usage, live_options);
1443 
1444  /*
1445  * perf session
1446  */
1447  kvm->session = perf_session__new(&data, false, &kvm->tool);
1448  if (kvm->session == NULL) {
1449  err = -1;
1450  goto out;
1451  }
1452  kvm->session->evlist = kvm->evlist;
1456  kvm->evlist->threads, false,
1457  kvm->opts.proc_map_timeout, 1);
1458  err = kvm_live_open_events(kvm);
1459  if (err)
1460  goto out;
1461 
1462  err = kvm_events_live_report(kvm);
1463 
1464 out:
1466  kvm->session = NULL;
1468 
1469  return err;
1470 }
1471 #endif
1472 
1473 static void print_kvm_stat_usage(void)
1474 {
1475  printf("Usage: perf kvm stat <command>\n\n");
1476 
1477  printf("# Available commands:\n");
1478  printf("\trecord: record kvm events\n");
1479  printf("\treport: report statistical data of kvm events\n");
1480  printf("\tlive: live reporting of statistical data of kvm events\n");
1481 
1482  printf("\nOtherwise, it is the alias of 'perf stat':\n");
1483 }
1484 
1485 static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
1486 {
1487  struct perf_kvm_stat kvm = {
1488  .file_name = file_name,
1489 
1490  .trace_vcpu = -1,
1491  .report_event = "vmexit",
1492  .sort_key = "sample",
1493 
1494  };
1495 
1496  if (argc == 1) {
1497  print_kvm_stat_usage();
1498  goto perf_stat;
1499  }
1500 
1501  if (!strncmp(argv[1], "rec", 3))
1502  return kvm_events_record(&kvm, argc - 1, argv + 1);
1503 
1504  if (!strncmp(argv[1], "rep", 3))
1505  return kvm_events_report(&kvm, argc - 1 , argv + 1);
1506 
1507 #ifdef HAVE_TIMERFD_SUPPORT
1508  if (!strncmp(argv[1], "live", 4))
1509  return kvm_events_live(&kvm, argc - 1 , argv + 1);
1510 #endif
1511 
1512 perf_stat:
1513  return cmd_stat(argc, argv);
1514 }
1515 #endif /* HAVE_KVM_STAT_SUPPORT */
1516 
1517 static int __cmd_record(const char *file_name, int argc, const char **argv)
1518 {
1519  int rec_argc, i = 0, j;
1520  const char **rec_argv;
1521 
1522  rec_argc = argc + 2;
1523  rec_argv = calloc(rec_argc + 1, sizeof(char *));
1524  rec_argv[i++] = strdup("record");
1525  rec_argv[i++] = strdup("-o");
1526  rec_argv[i++] = strdup(file_name);
1527  for (j = 1; j < argc; j++, i++)
1528  rec_argv[i] = argv[j];
1529 
1530  BUG_ON(i != rec_argc);
1531 
1532  return cmd_record(i, rec_argv);
1533 }
1534 
1535 static int __cmd_report(const char *file_name, int argc, const char **argv)
1536 {
1537  int rec_argc, i = 0, j;
1538  const char **rec_argv;
1539 
1540  rec_argc = argc + 2;
1541  rec_argv = calloc(rec_argc + 1, sizeof(char *));
1542  rec_argv[i++] = strdup("report");
1543  rec_argv[i++] = strdup("-i");
1544  rec_argv[i++] = strdup(file_name);
1545  for (j = 1; j < argc; j++, i++)
1546  rec_argv[i] = argv[j];
1547 
1548  BUG_ON(i != rec_argc);
1549 
1550  return cmd_report(i, rec_argv);
1551 }
1552 
1553 static int
1554 __cmd_buildid_list(const char *file_name, int argc, const char **argv)
1555 {
1556  int rec_argc, i = 0, j;
1557  const char **rec_argv;
1558 
1559  rec_argc = argc + 2;
1560  rec_argv = calloc(rec_argc + 1, sizeof(char *));
1561  rec_argv[i++] = strdup("buildid-list");
1562  rec_argv[i++] = strdup("-i");
1563  rec_argv[i++] = strdup(file_name);
1564  for (j = 1; j < argc; j++, i++)
1565  rec_argv[i] = argv[j];
1566 
1567  BUG_ON(i != rec_argc);
1568 
1569  return cmd_buildid_list(i, rec_argv);
1570 }
1571 
1572 int cmd_kvm(int argc, const char **argv)
1573 {
1574  const char *file_name = NULL;
1575  const struct option kvm_options[] = {
1576  OPT_STRING('i', "input", &file_name, "file",
1577  "Input file name"),
1578  OPT_STRING('o', "output", &file_name, "file",
1579  "Output file name"),
1580  OPT_BOOLEAN(0, "guest", &perf_guest,
1581  "Collect guest os data"),
1582  OPT_BOOLEAN(0, "host", &perf_host,
1583  "Collect host os data"),
1584  OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
1585  "guest mount directory under which every guest os"
1586  " instance has a subdir"),
1587  OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
1588  "file", "file saving guest os vmlinux"),
1589  OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
1590  "file", "file saving guest os /proc/kallsyms"),
1591  OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
1592  "file", "file saving guest os /proc/modules"),
1593  OPT_INCR('v', "verbose", &verbose,
1594  "be more verbose (show counter open errors, etc)"),
1595  OPT_END()
1596  };
1597 
1598  const char *const kvm_subcommands[] = { "top", "record", "report", "diff",
1599  "buildid-list", "stat", NULL };
1600  const char *kvm_usage[] = { NULL, NULL };
1601 
1602  perf_host = 0;
1603  perf_guest = 1;
1604 
1605  argc = parse_options_subcommand(argc, argv, kvm_options, kvm_subcommands, kvm_usage,
1606  PARSE_OPT_STOP_AT_NON_OPTION);
1607  if (!argc)
1608  usage_with_options(kvm_usage, kvm_options);
1609 
1610  if (!perf_host)
1611  perf_guest = 1;
1612 
1613  if (!file_name) {
1614  file_name = get_filename_for_perf_kvm();
1615 
1616  if (!file_name) {
1617  pr_err("Failed to allocate memory for filename\n");
1618  return -ENOMEM;
1619  }
1620  }
1621 
1622  if (!strncmp(argv[0], "rec", 3))
1623  return __cmd_record(file_name, argc, argv);
1624  else if (!strncmp(argv[0], "rep", 3))
1625  return __cmd_report(file_name, argc, argv);
1626  else if (!strncmp(argv[0], "diff", 4))
1627  return cmd_diff(argc, argv);
1628  else if (!strncmp(argv[0], "top", 3))
1629  return cmd_top(argc, argv);
1630  else if (!strncmp(argv[0], "buildid-list", 12))
1631  return __cmd_buildid_list(file_name, argc, argv);
1632 #ifdef HAVE_KVM_STAT_SUPPORT
1633  else if (!strncmp(argv[0], "stat", 4))
1634  return kvm_cmd_stat(file_name, argc, argv);
1635 #endif
1636  else
1637  usage_with_options(kvm_usage, kvm_options);
1638 
1639  return 0;
1640 }
bool perf_host
Definition: util.c:80
void perf_session__set_id_hdr_size(struct perf_session *session)
Definition: session.c:66
u64 user_interval
Definition: perf.h:74
int cmd_report(int argc, const char **argv)
int cmd_kvm(int argc, const char **argv)
Definition: builtin-kvm.c:1572
event_op lost
Definition: tool.h:47
void perf_mmap__consume(struct perf_mmap *map)
Definition: mmap.c:118
Definition: mem2node.c:7
enum perf_data_mode mode
Definition: data.h:22
u64 total_time
Definition: kvm-stat.h:91
bool(* is_end_event)(struct perf_evsel *evsel, struct perf_sample *sample, struct event_key *key)
Definition: kvm-stat.h:57
int get_cpuid(char *buffer, size_t sz)
Definition: header.c:20
double avg_stats(struct stats *stats)
Definition: stat.c:26
bool uses_mmap
Definition: target.h:15
struct perf_evlist * evlist
Definition: session.h:25
struct kvm_event_stats * vcpu
Definition: kvm-stat.h:34
const char * uid_str
Definition: target.h:12
static int __cmd_buildid_list(const char *file_name, int argc, const char **argv)
Definition: builtin-kvm.c:1554
struct rb_node rb
Definition: kvm-stat.h:26
void(* get_key)(struct perf_evsel *evsel, struct perf_sample *sample, struct event_key *key)
Definition: kvm-stat.h:47
struct rb_root result
Definition: kvm-stat.h:98
struct ordered_events ordered_events
Definition: session.h:35
const int decode_str_len
Definition: kvm-stat.c:13
int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
Definition: evlist.c:1066
u64 lost_events
Definition: kvm-stat.h:93
struct perf_mmap * mmap
Definition: evlist.h:45
int ui__error(const char *format,...)
Definition: util.c:32
struct child_event_ops * child_ops
Definition: kvm-stat.h:59
int cmd_record(int argc, const char **argv)
struct machine host
Definition: machine.h:136
#define CONSOLE_CLEAR
Definition: top.h:45
enum target_errno target__validate(struct target *target)
Definition: target.c:17
#define EVENTS_CACHE_SIZE
Definition: kvm-stat.h:71
static int select_key(void)
Definition: builtin-lock.c:265
const char * filename
Definition: hists_common.c:26
void disable_buildid_cache(void)
Definition: build-id.c:410
void perf_evlist__enable(struct perf_evlist *evlist)
Definition: evlist.c:369
const char * name
Definition: kvm-stat.h:50
struct exit_reasons_table * exit_reasons
Definition: kvm-stat.h:84
const char * default_guest_modules
Definition: symbol.h:127
static int machine__synthesize_threads(struct machine *machine, struct target *target, struct thread_map *threads, bool data_mmap, unsigned int proc_map_timeout, unsigned int nr_threads_synthesize)
Definition: machine.h:253
#define INVALID_KEY
Definition: kvm-stat.h:13
u64 total_count
Definition: kvm-stat.h:92
struct list_head kvm_events_cache[EVENTS_CACHE_SIZE]
Definition: kvm-stat.h:89
int ui__warning(const char *format,...)
Definition: util.c:44
static int process_sample_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine)
const char * sort_key
Definition: kvm-stat.h:81
int int err
Definition: 5sec.c:44
struct kvm_events_ops * ops
Definition: kvm-stat.h:108
static struct sched_atom * last_event(struct task_desc *task)
const char * name
Definition: kvm-stat.h:40
struct stats stats
Definition: kvm-stat.h:21
unsigned int proc_map_timeout
Definition: perf.h:81
struct perf_data_file file
Definition: data.h:18
struct perf_env env
Definition: header.h:82
int max_vcpu
Definition: kvm-stat.h:33
void perf_evlist__delete(struct perf_evlist *evlist)
Definition: evlist.c:133
static struct lock_stat * pop_from_result(void)
Definition: builtin-lock.c:303
void set_term_quiet_input(struct termios *old)
Definition: term.c:30
int perf_event__process_comm(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1273
const char * report_event
Definition: kvm-stat.h:80
#define perf_evsel__set_sample_bit(evsel, bit)
Definition: evsel.h:260
int perf_event__process_exit(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1416
struct kvm_events_ops * events_ops
Definition: kvm-stat.h:87
int perf_event__process_fork(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1408
#define DEFAULT_VCPU_NUM
Definition: kvm-stat.h:32
struct thread_map * threads
Definition: evlist.h:47
Definition: mmap.h:17
static int process_lost_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine)
const char * kvm_events_tp[NR_TPS+1]
Definition: kvm-stat.c:30
double stddev_stats(struct stats *stats)
Definition: stat.c:47
static bool target__none(struct target *target)
Definition: target.h:62
int perf_evlist__add_newtp(struct perf_evlist *evlist, const char *sys, const char *name, void *handler)
Definition: evlist.c:334
int setup_kvm_events_tp(struct perf_kvm_stat *kvm)
Definition: kvm-stat.c:156
static void sort_result(void)
bool perf_session__has_traces(struct perf_session *session, const char *msg)
Definition: session.c:1963
bool kvm_entry_event(struct perf_evsel *evsel)
x86 movsq based memset() in arch/x86/lib/memset_64.S") MEMSET_FN(memset_erms
#define pr_err(fmt,...)
Definition: json.h:21
const char * vcpu_id_str
Definition: kvm-stat.c:12
void perf_session__delete(struct perf_session *session)
Definition: session.c:187
#define min(x, y)
Definition: jevents.h:15
int use_browser
Definition: setup.c:12
struct record_opts opts
Definition: kvm-stat.h:75
int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, int unset __maybe_unused)
Definition: evlist.c:996
static void init_stats(struct stats *stats)
Definition: stat.h:103
int info
Definition: kvm-stat.h:15
const char * default_guest_vmlinux_name
Definition: symbol.h:127
struct target target
Definition: perf.h:38
u64 min
Definition: stat.h:12
static void insert_to_result(struct lock_stat *st, int(*bigger)(struct lock_stat *, struct lock_stat *))
Definition: builtin-lock.c:281
int target__strerror(struct target *target, int errnum, char *buf, size_t buflen)
Definition: target.c:116
const char * key
Definition: bpf-loader.c:196
struct int_node * intlist__find(struct intlist *ilist, int i)
Definition: intlist.c:81
static void print_result(struct perf_session *session)
int perf_mmap__read_init(struct perf_mmap *map)
Definition: mmap.c:271
Definition: thread.h:18
void(* decode_key)(struct perf_kvm_stat *kvm, struct event_key *key, char *decode)
Definition: kvm-stat.h:60
const char * name
bool system_wide
Definition: target.h:14
bool perf_guest
Definition: util.c:81
const char *const * record_usage
#define pr_debug(fmt,...)
Definition: json.h:27
Definition: tool.h:44
struct kvm_reg_events_ops kvm_reg_events_ops[]
Definition: kvm-stat.c:96
int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid __maybe_unused)
Definition: kvm-stat.c:161
void update_stats(struct stats *stats, u64 val)
Definition: stat.c:10
struct kvm_event_stats total
Definition: kvm-stat.h:30
int perf_evlist__open(struct perf_evlist *evlist)
Definition: evlist.c:1398
#define evlist__for_each_entry(evlist, evsel)
Definition: evlist.h:247
const char *const kvm_skip_events[]
Definition: kvm-stat.c:102
event_op exit
Definition: tool.h:47
static struct perf_tool tool
Definition: builtin-diff.c:362
struct exit_reasons_table * exit_reasons
Definition: kvm-stat.h:16
struct list_head hash_entry
Definition: kvm-stat.h:25
u32 pid
Definition: event.h:193
u32 tid
Definition: event.h:193
struct event_key key
Definition: kvm-stat.h:28
char * cpuid
Definition: env.h:44
struct perf_tool tool
Definition: kvm-stat.h:74
double rel_stddev_stats(double stddev, double avg)
Definition: stat.c:60
static const char * get_filename_for_perf_kvm(void)
Definition: builtin-kvm.c:43
unsigned int mmap_pages
Definition: perf.h:67
bool ordered_events
Definition: tool.h:76
int perf_evlist__parse_sample_timestamp(struct perf_evlist *evlist, union perf_event *event, u64 *timestamp)
Definition: evlist.c:1571
#define CPU(he)
#define event
u64 key
Definition: kvm-stat.h:14
u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, const char *name)
Definition: evsel.c:2722
void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts, struct callchain_param *callchain)
Definition: record.c:135
int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
Definition: evlist.c:471
const char * reason
Definition: kvm-stat.h:67
int ordered_events__flush(struct ordered_events *oe, enum oe_flush how)
const char * name
Definition: kvm-stat.h:107
int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages)
Definition: evlist.c:1061
Definition: data.h:17
int nr_mmaps
Definition: evlist.h:32
unsigned long exit_code
Definition: kvm-stat.h:66
int(* key_cmp_fun)(struct kvm_event *, struct kvm_event *, int)
Definition: kvm-stat.h:37
bool exit_event_begin(struct perf_evsel *evsel, struct perf_sample *sample, struct event_key *key)
static void ordered_events__set_copy_on_queue(struct ordered_events *oe, bool copy)
double mean
Definition: stat.h:11
double n
Definition: stat.h:11
void perf_mmap__read_done(struct perf_mmap *map)
Definition: mmap.c:329
struct perf_event_header header
Definition: event.h:624
struct intlist * intlist__new(const char *slist)
Definition: intlist.c:110
void exit_event_decode_key(struct perf_kvm_stat *kvm, struct event_key *key, char *decode)
bool(* is_begin_event)(struct perf_evsel *evsel, struct perf_sample *sample, struct event_key *key)
Definition: kvm-stat.h:54
struct option * record_options
struct perf_session * perf_session__new(struct perf_data *data, bool repipe, struct perf_tool *tool)
Definition: session.c:116
uid_t uid
Definition: target.h:13
key_cmp_fun compare
Definition: kvm-stat.h:88
const char * kvm_exit_reason
Definition: kvm-stat.c:31
int perf_session__queue_event(struct perf_session *s, union perf_event *event, u64 timestamp, u64 file_offset)
Definition: session.c:867
union perf_event * perf_mmap__read_event(struct perf_mmap *map)
Definition: mmap.c:78
void thread__put(struct thread *thread)
Definition: thread.c:119
bool kvm_exit_event(struct perf_evsel *evsel)
void perf_evlist__disable(struct perf_evlist *evlist)
Definition: evlist.c:356
u64 max
Definition: stat.h:12
int perf_session__process_events(struct perf_session *session)
Definition: session.c:1945
event_op namespaces
Definition: tool.h:47
unsigned int display_time
Definition: kvm-stat.h:101
Definition: stat.h:10
u64 duration
Definition: kvm-stat.h:94
const char * default_guest_kallsyms
Definition: symbol.h:127
u64 time
Definition: event.h:194
void exit_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample, struct event_key *key)
struct perf_header header
Definition: session.h:23
key_cmp_fun key
Definition: kvm-stat.h:41
event_op comm
Definition: tool.h:47
static void cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c, unsigned int *d)
Definition: header.c:11
int symbol__init(struct perf_env *env)
Definition: symbol.c:2112
struct fdarray pollfd
Definition: evlist.h:44
static int __cmd_report(const char *file_name, int argc, const char **argv)
Definition: builtin-kvm.c:1535
#define pr_info(fmt,...)
Definition: json.h:24
void perf_evlist__close(struct perf_evlist *evlist)
Definition: evlist.c:1359
#define STRERR_BUFSIZE
Definition: debug.h:43
void free(void *)
const char * exit_reasons_isa
Definition: kvm-stat.h:85
int cmd_stat(int argc, const char **argv)
static void sig_handler(int sig __maybe_unused)
const char * pid
Definition: target.h:9
struct perf_session * session
Definition: kvm-stat.h:77
const char * file_name
Definition: kvm-stat.h:79
#define perf_evsel__reset_sample_bit(evsel, bit)
Definition: evsel.h:263
static void thread__set_priv(struct thread *thread, void *p)
Definition: thread.h:109
const char * kvm_exit_trace
Definition: kvm-stat.c:15
int cmd_top(int argc, const char **argv)
Definition: builtin-top.c:1245
Definition: attr.py:1
int verbose
Definition: jevents.c:53
int trace_vcpu
Definition: kvm-stat.h:82
int cmd_diff(int argc, const char **argv)
char * name
Definition: evsel.h:102
event_op fork
Definition: tool.h:47
static struct perf_stat perf_stat
Definition: builtin-stat.c:196
int perf_event__process_namespaces(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1281
const char * kvm_entry_trace
Definition: kvm-stat.c:14
int cmd_buildid_list(int argc, const char **argv)
const char * name
Definition: kvm-stat.h:62
const char * guestmount
Definition: symbol.h:130
const char * path
Definition: data.h:13
struct machines machines
Definition: session.h:24
struct thread * machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid)
Definition: machine.c:492
static bool done
Definition: futex-hash.c:35
struct perf_evlist * evlist
Definition: kvm-stat.h:76
struct perf_evlist * perf_evlist__new(void)
Definition: evlist.c:54
struct perf_event_attr attr
Definition: evsel.h:93
void perf_tool__fill_defaults(struct perf_tool *tool)
Definition: session.c:360
static int __cmd_record(const char *file_name, int argc, const char **argv)
Definition: builtin-kvm.c:1517
bool exit_event_end(struct perf_evsel *evsel, struct perf_sample *sample, struct event_key *key)
struct intlist * pid_list
Definition: kvm-stat.h:96
event_sample sample
Definition: tool.h:45
static void * thread__priv(struct thread *thread)
Definition: thread.h:104
void static void * zalloc(size_t size)
Definition: util.h:20