// SPDX-License-Identifier: GPL-2.0
#include "builtin.h"
#include "perf.h"
#include "util/build-id.h"
#include "util/evsel.h"
#include "util/evlist.h"
#include "util/mmap.h"
#include "util/term.h"
#include "util/symbol.h"
#include "util/thread.h"
#include "util/header.h"
#include "util/session.h"
#include "util/intlist.h"
#include <subcmd/pager.h>
#include <subcmd/parse-options.h>
#include "util/trace-event.h"
#include "util/debug.h"
#include "util/tool.h"
#include "util/stat.h"
#include "util/synthetic-events.h"
#include "util/top.h"
#include "util/data.h"
#include "util/ordered-events.h"
#include "util/kvm-stat.h"
#include "ui/ui.h"
#include "util/string2.h"
#include <sys/prctl.h>
#ifdef HAVE_TIMERFD_SUPPORT
#include <sys/timerfd.h>
#endif
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/time64.h>
#include <linux/zalloc.h>
#include <errno.h>
#include <inttypes.h>
#include <poll.h>
#include <termios.h>
#include <semaphore.h>
#include <signal.h>
#include <math.h>
#include <perf/mmap.h>
static const char *get_filename_for_perf_kvm(void)
{
const char *filename;
if (perf_host && !perf_guest)
filename = strdup("perf.data.host");
else if (!perf_host && perf_guest)
filename = strdup("perf.data.guest");
else
filename = strdup("perf.data.kvm");
return filename;
}
#ifdef HAVE_KVM_STAT_SUPPORT
void exit_event_get_key(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
key->info = 0;
key->key = evsel__intval(evsel, sample, kvm_exit_reason);
}
bool kvm_exit_event(struct evsel *evsel)
{
return !strcmp(evsel->name, kvm_exit_trace);
}
bool exit_event_begin(struct evsel *evsel,
struct perf_sample *sample, struct event_key *key)
{
if (kvm_exit_event(evsel)) {
exit_event_get_key(evsel, sample, key);
return true;
}
return false;
}
bool kvm_entry_event(struct evsel *evsel)
{
return !strcmp(evsel->name, kvm_entry_trace);
}
bool exit_event_end(struct evsel *evsel,
struct perf_sample *sample __maybe_unused,
struct event_key *key __maybe_unused)
{
return kvm_entry_event(evsel);
}
static const char *get_exit_reason(struct perf_kvm_stat *kvm,
struct exit_reasons_table *tbl,
u64 exit_code)
{
while (tbl->reason != NULL) {
if (tbl->exit_code == exit_code)
return tbl->reason;
tbl++;
}
pr_err("unknown kvm exit code:%lld on %s\n",
(unsigned long long)exit_code, kvm->exit_reasons_isa);
return "UNKNOWN";
}
void exit_event_decode_key(struct perf_kvm_stat *kvm,
struct event_key *key,
char *decode)
{
const char *exit_reason = get_exit_reason(kvm, key->exit_reasons,
key->key);
scnprintf(decode, decode_str_len, "%s", exit_reason);
}
static bool register_kvm_events_ops(struct perf_kvm_stat *kvm)
{
struct kvm_reg_events_ops *events_ops = kvm_reg_events_ops;
for (events_ops = kvm_reg_events_ops; events_ops->name; events_ops++) {
if (!strcmp(events_ops->name, kvm->report_event)) {
kvm->events_ops = events_ops->ops;
return true;
}
}
return false;
|