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