111 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Arch specific functions for perf kvm stat.4 *5 * Copyright 2014 IBM Corp.6 * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com>7 */8 9#include <errno.h>10#include <string.h>11#include "../../util/kvm-stat.h"12#include "../../util/evsel.h"13#include <asm/sie.h>14 15define_exit_reasons_table(sie_exit_reasons, sie_intercept_code);16define_exit_reasons_table(sie_icpt_insn_codes, icpt_insn_codes);17define_exit_reasons_table(sie_sigp_order_codes, sigp_order_codes);18define_exit_reasons_table(sie_diagnose_codes, diagnose_codes);19define_exit_reasons_table(sie_icpt_prog_codes, icpt_prog_codes);20 21const char *vcpu_id_str = "id";22const char *kvm_exit_reason = "icptcode";23const char *kvm_entry_trace = "kvm:kvm_s390_sie_enter";24const char *kvm_exit_trace = "kvm:kvm_s390_sie_exit";25 26static void event_icpt_insn_get_key(struct evsel *evsel,27 struct perf_sample *sample,28 struct event_key *key)29{30 unsigned long insn;31 32 insn = evsel__intval(evsel, sample, "instruction");33 key->key = icpt_insn_decoder(insn);34 key->exit_reasons = sie_icpt_insn_codes;35}36 37static void event_sigp_get_key(struct evsel *evsel,38 struct perf_sample *sample,39 struct event_key *key)40{41 key->key = evsel__intval(evsel, sample, "order_code");42 key->exit_reasons = sie_sigp_order_codes;43}44 45static void event_diag_get_key(struct evsel *evsel,46 struct perf_sample *sample,47 struct event_key *key)48{49 key->key = evsel__intval(evsel, sample, "code");50 key->exit_reasons = sie_diagnose_codes;51}52 53static void event_icpt_prog_get_key(struct evsel *evsel,54 struct perf_sample *sample,55 struct event_key *key)56{57 key->key = evsel__intval(evsel, sample, "code");58 key->exit_reasons = sie_icpt_prog_codes;59}60 61static struct child_event_ops child_events[] = {62 { .name = "kvm:kvm_s390_intercept_instruction",63 .get_key = event_icpt_insn_get_key },64 { .name = "kvm:kvm_s390_handle_sigp",65 .get_key = event_sigp_get_key },66 { .name = "kvm:kvm_s390_handle_diag",67 .get_key = event_diag_get_key },68 { .name = "kvm:kvm_s390_intercept_prog",69 .get_key = event_icpt_prog_get_key },70 { NULL, NULL },71};72 73static struct kvm_events_ops exit_events = {74 .is_begin_event = exit_event_begin,75 .is_end_event = exit_event_end,76 .child_ops = child_events,77 .decode_key = exit_event_decode_key,78 .name = "VM-EXIT"79};80 81const char *kvm_events_tp[] = {82 "kvm:kvm_s390_sie_enter",83 "kvm:kvm_s390_sie_exit",84 "kvm:kvm_s390_intercept_instruction",85 "kvm:kvm_s390_handle_sigp",86 "kvm:kvm_s390_handle_diag",87 "kvm:kvm_s390_intercept_prog",88 NULL,89};90 91struct kvm_reg_events_ops kvm_reg_events_ops[] = {92 { .name = "vmexit", .ops = &exit_events },93 { NULL, NULL },94};95 96const char * const kvm_skip_events[] = {97 "Wait state",98 NULL,99};100 101int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid)102{103 if (strstr(cpuid, "IBM")) {104 kvm->exit_reasons = sie_exit_reasons;105 kvm->exit_reasons_isa = "SIE";106 } else107 return -ENOTSUP;108 109 return 0;110}111