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 "../kvm-stat.h" 12 #include "../evsel.h" 13 #include "../../../arch/s390/include/uapi/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 static void event_icpt_insn_get_key(struct perf_sample *sample, 22 struct event_key *key) 23 { 24 u64 insn; 25 26 insn = perf_sample__intval(sample, "instruction"); 27 key->key = icpt_insn_decoder(insn); 28 key->exit_reasons = sie_icpt_insn_codes; 29 } 30 31 static void event_sigp_get_key(struct perf_sample *sample, 32 struct event_key *key) 33 { 34 key->key = perf_sample__intval(sample, "order_code"); 35 key->exit_reasons = sie_sigp_order_codes; 36 } 37 38 static void event_diag_get_key(struct perf_sample *sample, 39 struct event_key *key) 40 { 41 key->key = perf_sample__intval(sample, "code"); 42 key->exit_reasons = sie_diagnose_codes; 43 } 44 45 static void event_icpt_prog_get_key(struct perf_sample *sample, 46 struct event_key *key) 47 { 48 key->key = perf_sample__intval(sample, "code"); 49 key->exit_reasons = sie_icpt_prog_codes; 50 } 51 52 static const struct child_event_ops child_events[] = { 53 { .name = "kvm:kvm_s390_intercept_instruction", 54 .get_key = event_icpt_insn_get_key }, 55 { .name = "kvm:kvm_s390_handle_sigp", 56 .get_key = event_sigp_get_key }, 57 { .name = "kvm:kvm_s390_handle_diag", 58 .get_key = event_diag_get_key }, 59 { .name = "kvm:kvm_s390_intercept_prog", 60 .get_key = event_icpt_prog_get_key }, 61 { NULL, NULL }, 62 }; 63 64 static const struct kvm_events_ops exit_events = { 65 .is_begin_event = exit_event_begin, 66 .is_end_event = exit_event_end, 67 .child_ops = child_events, 68 .decode_key = exit_event_decode_key, 69 .name = "VM-EXIT" 70 }; 71 72 static const char * const __kvm_events_tp[] = { 73 "kvm:kvm_s390_sie_enter", 74 "kvm:kvm_s390_sie_exit", 75 "kvm:kvm_s390_intercept_instruction", 76 "kvm:kvm_s390_handle_sigp", 77 "kvm:kvm_s390_handle_diag", 78 "kvm:kvm_s390_intercept_prog", 79 NULL, 80 }; 81 82 static const struct kvm_reg_events_ops __kvm_reg_events_ops[] = { 83 { .name = "vmexit", .ops = &exit_events }, 84 { NULL, NULL }, 85 }; 86 87 static const char * const __kvm_skip_events[] = { 88 "Wait state", 89 NULL, 90 }; 91 92 int __cpu_isa_init_s390(struct perf_kvm_stat *kvm, const char *cpuid) 93 { 94 if (strstr(cpuid, "IBM")) { 95 kvm->exit_reasons = sie_exit_reasons; 96 kvm->exit_reasons_isa = "SIE"; 97 } else 98 return -ENOTSUP; 99 100 return 0; 101 } 102 103 const char * const *__kvm_events_tp_s390(void) 104 { 105 return __kvm_events_tp; 106 } 107 108 const struct kvm_reg_events_ops *__kvm_reg_events_ops_s390(void) 109 { 110 return __kvm_reg_events_ops; 111 } 112 113 const char * const *__kvm_skip_events_s390(void) 114 { 115 return __kvm_skip_events; 116 } 117