0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <errno.h>
0010 #include <string.h>
0011 #include "../../util/kvm-stat.h"
0012 #include "../../util/evsel.h"
0013 #include <asm/sie.h>
0014
0015 define_exit_reasons_table(sie_exit_reasons, sie_intercept_code);
0016 define_exit_reasons_table(sie_icpt_insn_codes, icpt_insn_codes);
0017 define_exit_reasons_table(sie_sigp_order_codes, sigp_order_codes);
0018 define_exit_reasons_table(sie_diagnose_codes, diagnose_codes);
0019 define_exit_reasons_table(sie_icpt_prog_codes, icpt_prog_codes);
0020
0021 const char *vcpu_id_str = "id";
0022 const int decode_str_len = 40;
0023 const char *kvm_exit_reason = "icptcode";
0024 const char *kvm_entry_trace = "kvm:kvm_s390_sie_enter";
0025 const char *kvm_exit_trace = "kvm:kvm_s390_sie_exit";
0026
0027 static void event_icpt_insn_get_key(struct evsel *evsel,
0028 struct perf_sample *sample,
0029 struct event_key *key)
0030 {
0031 unsigned long insn;
0032
0033 insn = evsel__intval(evsel, sample, "instruction");
0034 key->key = icpt_insn_decoder(insn);
0035 key->exit_reasons = sie_icpt_insn_codes;
0036 }
0037
0038 static void event_sigp_get_key(struct evsel *evsel,
0039 struct perf_sample *sample,
0040 struct event_key *key)
0041 {
0042 key->key = evsel__intval(evsel, sample, "order_code");
0043 key->exit_reasons = sie_sigp_order_codes;
0044 }
0045
0046 static void event_diag_get_key(struct evsel *evsel,
0047 struct perf_sample *sample,
0048 struct event_key *key)
0049 {
0050 key->key = evsel__intval(evsel, sample, "code");
0051 key->exit_reasons = sie_diagnose_codes;
0052 }
0053
0054 static void event_icpt_prog_get_key(struct evsel *evsel,
0055 struct perf_sample *sample,
0056 struct event_key *key)
0057 {
0058 key->key = evsel__intval(evsel, sample, "code");
0059 key->exit_reasons = sie_icpt_prog_codes;
0060 }
0061
0062 static struct child_event_ops child_events[] = {
0063 { .name = "kvm:kvm_s390_intercept_instruction",
0064 .get_key = event_icpt_insn_get_key },
0065 { .name = "kvm:kvm_s390_handle_sigp",
0066 .get_key = event_sigp_get_key },
0067 { .name = "kvm:kvm_s390_handle_diag",
0068 .get_key = event_diag_get_key },
0069 { .name = "kvm:kvm_s390_intercept_prog",
0070 .get_key = event_icpt_prog_get_key },
0071 { NULL, NULL },
0072 };
0073
0074 static struct kvm_events_ops exit_events = {
0075 .is_begin_event = exit_event_begin,
0076 .is_end_event = exit_event_end,
0077 .child_ops = child_events,
0078 .decode_key = exit_event_decode_key,
0079 .name = "VM-EXIT"
0080 };
0081
0082 const char *kvm_events_tp[] = {
0083 "kvm:kvm_s390_sie_enter",
0084 "kvm:kvm_s390_sie_exit",
0085 "kvm:kvm_s390_intercept_instruction",
0086 "kvm:kvm_s390_handle_sigp",
0087 "kvm:kvm_s390_handle_diag",
0088 "kvm:kvm_s390_intercept_prog",
0089 NULL,
0090 };
0091
0092 struct kvm_reg_events_ops kvm_reg_events_ops[] = {
0093 { .name = "vmexit", .ops = &exit_events },
0094 { NULL, NULL },
0095 };
0096
0097 const char * const kvm_skip_events[] = {
0098 "Wait state",
0099 NULL,
0100 };
0101
0102 int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid)
0103 {
0104 if (strstr(cpuid, "IBM")) {
0105 kvm->exit_reasons = sie_exit_reasons;
0106 kvm->exit_reasons_isa = "SIE";
0107 } else
0108 return -ENOTSUP;
0109
0110 return 0;
0111 }