#include "builtin.h"
#include "perf.h"
+#include <dwarf-regs.h>
#include "util/build-id.h"
#include "util/evsel.h"
#include "util/evlist.h"
#if defined(HAVE_LIBTRACEEVENT)
-static bool register_kvm_events_ops(struct perf_kvm_stat *kvm)
+static bool register_kvm_events_ops(struct perf_kvm_stat *kvm, uint16_t e_machine)
{
const struct kvm_reg_events_ops *events_ops;
- for (events_ops = kvm_reg_events_ops(); events_ops->name; events_ops++) {
+ for (events_ops = kvm_reg_events_ops(e_machine); events_ops->name; events_ops++) {
if (!strcmp(events_ops->name, kvm->report_event)) {
kvm->events_ops = events_ops->ops;
return true;
return true;
}
-static bool skip_event(const char *event)
+static bool skip_event(uint16_t e_machine, const char *event)
{
const char * const *skip_events;
- for (skip_events = kvm_skip_events(); *skip_events; skip_events++)
+ for (skip_events = kvm_skip_events(e_machine); *skip_events; skip_events++)
if (!strcmp(event, *skip_events))
return true;
if (kvm->duration && time_diff > kvm->duration) {
char decode[KVM_EVENT_NAME_LEN];
+ uint16_t e_machine = perf_session__e_machine(kvm->session);
kvm->events_ops->decode_key(kvm, &event->key, decode);
- if (!skip_event(decode)) {
+ if (!skip_event(e_machine, decode)) {
pr_info("%" PRIu64 " VM %d, vcpu %d: %s event took %" PRIu64 "usec\n",
sample->time, sample->pid, vcpu_record->vcpu_id,
decode, time_diff / NSEC_PER_USEC);
/* Only kvm_entry records vcpu id. */
if (!thread__priv(thread) && kvm_entry_event(evsel)) {
struct vcpu_event_record *vcpu_record;
+ struct machine *machine = maps__machine(thread__maps(thread));
+ uint16_t e_machine = thread__e_machine(thread, machine, /*e_flags=*/NULL);
vcpu_record = zalloc(sizeof(*vcpu_record));
if (!vcpu_record) {
return NULL;
}
- vcpu_record->vcpu_id = evsel__intval(evsel, sample, vcpu_id_str());
+ vcpu_record->vcpu_id = evsel__intval(evsel, sample, vcpu_id_str(e_machine));
thread__set_priv(thread, vcpu_record);
}
{
char buf[128], *cpuid;
int err;
+ uint16_t e_machine;
if (kvm->live) {
struct perf_cpu cpu = {-1};
return -EINVAL;
}
- err = cpu_isa_init(kvm, cpuid);
+ e_machine = perf_session__e_machine(kvm->session);
+ err = cpu_isa_init(kvm, e_machine, cpuid);
if (err == -ENOTSUP)
pr_err("CPU %s is not supported.\n", cpuid);
if (!verify_vcpu(kvm->trace_vcpu) ||
!is_valid_key(kvm) ||
- !register_kvm_events_ops(kvm)) {
+ !register_kvm_events_ops(kvm, EM_HOST)) {
goto out;
}
goto out_delete;
}
+ if (!register_kvm_events_ops(kvm, perf_session__e_machine(kvm->session))) {
+ ret = -EINVAL;
+ goto out_delete;
+ }
+
/*
* Do not use 'isa' recorded in kvm_exit tracepoint since it is not
* traced in the old kernel.
if (!is_valid_key(kvm))
goto exit;
- if (!register_kvm_events_ops(kvm))
- goto exit;
-
if (kvm->use_stdio) {
use_browser = 0;
setup_pager();
};
const char * const *events_tp;
int ret;
+ uint16_t e_machine = EM_HOST;
events_tp_size = 0;
- ret = setup_kvm_events_tp(kvm);
+ ret = setup_kvm_events_tp(kvm, e_machine);
if (ret < 0) {
pr_err("Unable to setup the kvm tracepoints\n");
return ret;
}
- for (events_tp = kvm_events_tp(); *events_tp; events_tp++)
+ for (events_tp = kvm_events_tp(e_machine); *events_tp; events_tp++)
events_tp_size++;
rec_argc = ARRAY_SIZE(record_args) + argc + 2 +
for (j = 0; j < events_tp_size; j++) {
rec_argv[i++] = STRDUP_FAIL_EXIT("-e");
- rec_argv[i++] = STRDUP_FAIL_EXIT(kvm_events_tp()[j]);
+ rec_argv[i++] = STRDUP_FAIL_EXIT(kvm_events_tp(e_machine)[j]);
}
rec_argv[i++] = STRDUP_FAIL_EXIT("-o");
if (evlist == NULL)
return NULL;
- for (events_tp = kvm_events_tp(); *events_tp; events_tp++) {
+ for (events_tp = kvm_events_tp(EM_HOST); *events_tp; events_tp++) {
tp = strdup(*events_tp);
if (tp == NULL)
/*
* generate the event list
*/
- err = setup_kvm_events_tp(kvm);
+ err = setup_kvm_events_tp(kvm, EM_HOST);
if (err < 0) {
pr_err("Unable to setup the kvm tracepoints\n");
return err;
BUG_ON(i + 2 != rec_argc);
- ret = kvm_add_default_arch_event(&i, rec_argv);
+ ret = kvm_add_default_arch_event(EM_HOST, &i, rec_argv);
if (ret)
goto EXIT;
BUG_ON(i != argc);
- ret = kvm_add_default_arch_event(&i, rec_argv);
+ ret = kvm_add_default_arch_event(EM_HOST, &i, rec_argv);
if (ret)
goto EXIT;
return ret;
}
-static uint16_t evsel__e_machine(struct evsel *evsel)
+uint16_t evsel__e_machine(struct evsel *evsel)
{
struct perf_session *session = evsel__session(evsel);
struct perf_session *evsel__session(struct evsel *evsel);
struct perf_env *evsel__env(struct evsel *evsel);
+uint16_t evsel__e_machine(struct evsel *evsel);
int evsel__store_ids(struct evsel *evsel, struct evlist *evlist);
struct event_key *key)
{
key->info = 0;
- key->key = evsel__intval(evsel, sample, kvm_exit_reason());
+ key->key = evsel__intval(evsel, sample, kvm_exit_reason(EM_AARCH64));
key->exit_reasons = arm64_exit_reasons;
/*
struct perf_sample *sample __maybe_unused,
struct event_key *key __maybe_unused)
{
- return evsel__name_is(evsel, kvm_entry_trace());
+ return evsel__name_is(evsel, kvm_entry_trace(EM_AARCH64));
}
static bool event_end(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
- if (evsel__name_is(evsel, kvm_exit_trace())) {
+ if (evsel__name_is(evsel, kvm_exit_trace(EM_AARCH64))) {
event_get_key(evsel, sample, key);
return true;
}
// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
#include <memory.h>
+#include <dwarf-regs.h>
#include "../kvm-stat.h"
#include "../parse-events.h"
#include "../debug.h"
* kvm:kvm_enter means returning to vmm and then to guest
* kvm:kvm_reenter means returning to guest immediately
*/
- return evsel__name_is(evsel, kvm_entry_trace()) ||
+ return evsel__name_is(evsel, kvm_entry_trace(EM_LOONGARCH)) ||
evsel__name_is(evsel, kvm_reenter_trace);
}
int xlen = 64; // TODO: 32-bit support.
key->info = 0;
- key->key = evsel__intval(evsel, sample, kvm_exit_reason()) & ~CAUSE_IRQ_FLAG(xlen);
+ key->key = evsel__intval(evsel, sample, kvm_exit_reason(EM_RISCV)) & ~CAUSE_IRQ_FLAG(xlen);
key->exit_reasons = riscv_exit_reasons;
}
struct perf_sample *sample __maybe_unused,
struct event_key *key __maybe_unused)
{
- return evsel__name_is(evsel, kvm_entry_trace());
+ return evsel__name_is(evsel, kvm_entry_trace(EM_RISCV));
}
static bool event_end(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
- if (evsel__name_is(evsel, kvm_exit_trace())) {
+ if (evsel__name_is(evsel, kvm_exit_trace(EM_RISCV))) {
event_get_key(evsel, sample, key);
return true;
}
bool kvm_exit_event(struct evsel *evsel)
{
- return evsel__name_is(evsel, kvm_exit_trace());
+ return evsel__name_is(evsel, kvm_exit_trace(evsel__e_machine(evsel)));
}
void exit_event_get_key(struct evsel *evsel,
struct event_key *key)
{
key->info = 0;
- key->key = evsel__intval(evsel, sample, kvm_exit_reason());
+ key->key = evsel__intval(evsel, sample, kvm_exit_reason(evsel__e_machine(evsel)));
}
bool kvm_entry_event(struct evsel *evsel)
{
- return evsel__name_is(evsel, kvm_entry_trace());
+ return evsel__name_is(evsel, kvm_entry_trace(evsel__e_machine(evsel)));
}
bool exit_event_end(struct evsel *evsel,
scnprintf(decode, KVM_EVENT_NAME_LEN, "%s", exit_reason);
}
-int setup_kvm_events_tp(struct perf_kvm_stat *kvm)
+int setup_kvm_events_tp(struct perf_kvm_stat *kvm, uint16_t e_machine)
{
- switch (EM_HOST) {
+ switch (e_machine) {
case EM_PPC:
case EM_PPC64:
return __setup_kvm_events_tp_powerpc(kvm);
}
}
-int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid)
+int cpu_isa_init(struct perf_kvm_stat *kvm, uint16_t e_machine, const char *cpuid)
{
- switch (EM_HOST) {
+ switch (e_machine) {
case EM_AARCH64:
return __cpu_isa_init_arm64(kvm);
case EM_LOONGARCH:
case EM_386:
return __cpu_isa_init_x86(kvm, cpuid);
default:
- pr_err("Unsupported kvm-stat host %d\n", EM_HOST);
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
return -1;
}
}
-const char *vcpu_id_str(void)
+const char *vcpu_id_str(uint16_t e_machine)
{
- switch (EM_HOST) {
+ switch (e_machine) {
case EM_AARCH64:
case EM_RISCV:
case EM_S390:
case EM_386:
return "vcpu_id";
default:
- pr_err("Unsupported kvm-stat host %d\n", EM_HOST);
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
return NULL;
}
}
-const char *kvm_exit_reason(void)
+const char *kvm_exit_reason(uint16_t e_machine)
{
- switch (EM_HOST) {
+ switch (e_machine) {
case EM_AARCH64:
return "ret";
case EM_LOONGARCH:
case EM_386:
return "exit_reason";
default:
- pr_err("Unsupported kvm-stat host %d\n", EM_HOST);
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
return NULL;
}
}
-const char *kvm_entry_trace(void)
+const char *kvm_entry_trace(uint16_t e_machine)
{
- switch (EM_HOST) {
+ switch (e_machine) {
case EM_AARCH64:
case EM_RISCV:
case EM_X86_64:
case EM_S390:
return "kvm:kvm_s390_sie_enter";
default:
- pr_err("Unsupported kvm-stat host %d\n", EM_HOST);
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
return NULL;
}
}
-const char *kvm_exit_trace(void)
+const char *kvm_exit_trace(uint16_t e_machine)
{
- switch (EM_HOST) {
+ switch (e_machine) {
case EM_AARCH64:
case EM_LOONGARCH:
case EM_RISCV:
case EM_S390:
return "kvm:kvm_s390_sie_exit";
default:
- pr_err("Unsupported kvm-stat host %d\n", EM_HOST);
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
return NULL;
}
}
-const char * const *kvm_events_tp(void)
+const char * const *kvm_events_tp(uint16_t e_machine)
{
- switch (EM_HOST) {
+ switch (e_machine) {
case EM_AARCH64:
return __kvm_events_tp_arm64();
case EM_LOONGARCH:
case EM_386:
return __kvm_events_tp_x86();
default:
- pr_err("Unsupported kvm-stat host %d\n", EM_HOST);
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
return NULL;
}
}
-const struct kvm_reg_events_ops *kvm_reg_events_ops(void)
+const struct kvm_reg_events_ops *kvm_reg_events_ops(uint16_t e_machine)
{
- switch (EM_HOST) {
+ switch (e_machine) {
case EM_AARCH64:
return __kvm_reg_events_ops_arm64();
case EM_LOONGARCH:
case EM_386:
return __kvm_reg_events_ops_x86();
default:
- pr_err("Unsupported kvm-stat host %d\n", EM_HOST);
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
return NULL;
}
}
-const char * const *kvm_skip_events(void)
+const char * const *kvm_skip_events(uint16_t e_machine)
{
- switch (EM_HOST) {
+ switch (e_machine) {
case EM_AARCH64:
return __kvm_skip_events_arm64();
case EM_LOONGARCH:
case EM_386:
return __kvm_skip_events_x86();
default:
- pr_err("Unsupported kvm-stat host %d\n", EM_HOST);
+ pr_err("Unsupported kvm-stat host %d\n", e_machine);
return NULL;
}
}
-int kvm_add_default_arch_event(int *argc, const char **argv)
+int kvm_add_default_arch_event(uint16_t e_machine, int *argc, const char **argv)
{
- switch (EM_HOST) {
+ switch (e_machine) {
case EM_PPC:
case EM_PPC64:
return __kvm_add_default_arch_event_powerpc(argc, argv);
/*
* arch specific callbacks and data structures
*/
-int setup_kvm_events_tp(struct perf_kvm_stat *kvm);
+int setup_kvm_events_tp(struct perf_kvm_stat *kvm, uint16_t e_machine);
int __setup_kvm_events_tp_powerpc(struct perf_kvm_stat *kvm);
-int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid);
+int cpu_isa_init(struct perf_kvm_stat *kvm, uint16_t e_machine, const char *cpuid);
int __cpu_isa_init_arm64(struct perf_kvm_stat *kvm);
int __cpu_isa_init_loongarch(struct perf_kvm_stat *kvm);
int __cpu_isa_init_powerpc(struct perf_kvm_stat *kvm);
int __cpu_isa_init_s390(struct perf_kvm_stat *kvm, const char *cpuid);
int __cpu_isa_init_x86(struct perf_kvm_stat *kvm, const char *cpuid);
-const char *vcpu_id_str(void);
-const char *kvm_exit_reason(void);
-const char *kvm_entry_trace(void);
-const char *kvm_exit_trace(void);
+const char *vcpu_id_str(uint16_t e_machine);
+const char *kvm_exit_reason(uint16_t e_machine);
+const char *kvm_entry_trace(uint16_t e_machine);
+const char *kvm_exit_trace(uint16_t e_machine);
-const char * const *kvm_events_tp(void);
+const char * const *kvm_events_tp(uint16_t e_machine);
const char * const *__kvm_events_tp_arm64(void);
const char * const *__kvm_events_tp_loongarch(void);
const char * const *__kvm_events_tp_powerpc(void);
const char * const *__kvm_events_tp_s390(void);
const char * const *__kvm_events_tp_x86(void);
-const struct kvm_reg_events_ops *kvm_reg_events_ops(void);
+const struct kvm_reg_events_ops *kvm_reg_events_ops(uint16_t e_machine);
const struct kvm_reg_events_ops *__kvm_reg_events_ops_arm64(void);
const struct kvm_reg_events_ops *__kvm_reg_events_ops_loongarch(void);
const struct kvm_reg_events_ops *__kvm_reg_events_ops_powerpc(void);
const struct kvm_reg_events_ops *__kvm_reg_events_ops_s390(void);
const struct kvm_reg_events_ops *__kvm_reg_events_ops_x86(void);
-const char * const *kvm_skip_events(void);
+const char * const *kvm_skip_events(uint16_t e_machine);
const char * const *__kvm_skip_events_arm64(void);
const char * const *__kvm_skip_events_loongarch(void);
const char * const *__kvm_skip_events_powerpc(void);
const char * const *__kvm_skip_events_s390(void);
const char * const *__kvm_skip_events_x86(void);
-int kvm_add_default_arch_event(int *argc, const char **argv);
+int kvm_add_default_arch_event(uint16_t e_machine, int *argc, const char **argv);
int __kvm_add_default_arch_event_powerpc(int *argc, const char **argv);
int __kvm_add_default_arch_event_x86(int *argc, const char **argv);
#else /* !HAVE_LIBTRACEEVENT */
-static inline int kvm_add_default_arch_event(int *argc __maybe_unused,
+static inline int kvm_add_default_arch_event(uint16_t e_machine __maybe_unused,
+ int *argc __maybe_unused,
const char **argv __maybe_unused)
{
return 0;