1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 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 15 define_exit_reasons_table(sie_exit_reasons, sie_intercept_code); 16 define_exit_reasons_table(sie_icpt_insn_codes, icpt_insn_codes); 17 define_exit_reasons_table(sie_sigp_order_codes, sigp_order_codes); 18 define_exit_reasons_table(sie_diagnose_codes, diagnose_codes); 19 define_exit_reasons_table(sie_icpt_prog_codes, icpt_prog_codes); 20 21 const char *vcpu_id_str = "id"; 22 const int decode_str_len = 40; 23 const char *kvm_exit_reason = "icptcode"; 24 const char *kvm_entry_trace = "kvm:kvm_s390_sie_enter"; 25 const char *kvm_exit_trace = "kvm:kvm_s390_sie_exit"; 26 27 static void event_icpt_insn_get_key(struct evsel *evsel, 28 struct perf_sample *sample, 29 struct event_key *key) 30 { 31 unsigned long insn; 32 33 insn = evsel__intval(evsel, sample, "instruction"); 34 key->key = icpt_insn_decoder(insn); 35 key->exit_reasons = sie_icpt_insn_codes; 36 } 37 38 static void event_sigp_get_key(struct evsel *evsel, 39 struct perf_sample *sample, 40 struct event_key *key) 41 { 42 key->key = evsel__intval(evsel, sample, "order_code"); 43 key->exit_reasons = sie_sigp_order_codes; 44 } 45 46 static void event_diag_get_key(struct evsel *evsel, 47 struct perf_sample *sample, 48 struct event_key *key) 49 { 50 key->key = evsel__intval(evsel, sample, "code"); 51 key->exit_reasons = sie_diagnose_codes; 52 } 53 54 static void event_icpt_prog_get_key(struct evsel *evsel, 55 struct perf_sample *sample, 56 struct event_key *key) 57 { 58 key->key = evsel__intval(evsel, sample, "code"); 59 key->exit_reasons = sie_icpt_prog_codes; 60 } 61 62 static struct child_event_ops child_events[] = { 63 { .name = "kvm:kvm_s390_intercept_instruction", 64 .get_key = event_icpt_insn_get_key }, 65 { .name = "kvm:kvm_s390_handle_sigp", 66 .get_key = event_sigp_get_key }, 67 { .name = "kvm:kvm_s390_handle_diag", 68 .get_key = event_diag_get_key }, 69 { .name = "kvm:kvm_s390_intercept_prog", 70 .get_key = event_icpt_prog_get_key }, 71 { NULL, NULL }, 72 }; 73 74 static struct kvm_events_ops exit_events = { 75 .is_begin_event = exit_event_begin, 76 .is_end_event = exit_event_end, 77 .child_ops = child_events, 78 .decode_key = exit_event_decode_key, 79 .name = "VM-EXIT" 80 }; 81 82 const char *kvm_events_tp[] = { 83 "kvm:kvm_s390_sie_enter", 84 "kvm:kvm_s390_sie_exit", 85 "kvm:kvm_s390_intercept_instruction", 86 "kvm:kvm_s390_handle_sigp", 87 "kvm:kvm_s390_handle_diag", 88 "kvm:kvm_s390_intercept_prog", 89 NULL, 90 }; 91 92 struct kvm_reg_events_ops kvm_reg_events_ops[] = { 93 { .name = "vmexit", .ops = &exit_events }, 94 { NULL, NULL }, 95 }; 96 97 const char * const kvm_skip_events[] = { 98 "Wait state", 99 NULL, 100 }; 101 102 int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid) 103 { 104 if (strstr(cpuid, "IBM")) { 105 kvm->exit_reasons = sie_exit_reasons; 106 kvm->exit_reasons_isa = "SIE"; 107 } else 108 return -ENOTSUP; 109 110 return 0; 111 } 112