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