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 "../../util/kvm-stat.h" 13 #include <asm/kvm_perf.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_evsel *evsel, 22 struct perf_sample *sample, 23 struct event_key *key) 24 { 25 unsigned long insn; 26 27 insn = perf_evsel__intval(evsel, sample, "instruction"); 28 key->key = icpt_insn_decoder(insn); 29 key->exit_reasons = sie_icpt_insn_codes; 30 } 31 32 static void event_sigp_get_key(struct perf_evsel *evsel, 33 struct perf_sample *sample, 34 struct event_key *key) 35 { 36 key->key = perf_evsel__intval(evsel, sample, "order_code"); 37 key->exit_reasons = sie_sigp_order_codes; 38 } 39 40 static void event_diag_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, "code"); 45 key->exit_reasons = sie_diagnose_codes; 46 } 47 48 static void event_icpt_prog_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_icpt_prog_codes; 54 } 55 56 static struct child_event_ops child_events[] = { 57 { .name = "kvm:kvm_s390_intercept_instruction", 58 .get_key = event_icpt_insn_get_key }, 59 { .name = "kvm:kvm_s390_handle_sigp", 60 .get_key = event_sigp_get_key }, 61 { .name = "kvm:kvm_s390_handle_diag", 62 .get_key = event_diag_get_key }, 63 { .name = "kvm:kvm_s390_intercept_prog", 64 .get_key = event_icpt_prog_get_key }, 65 { NULL, NULL }, 66 }; 67 68 static struct kvm_events_ops exit_events = { 69 .is_begin_event = exit_event_begin, 70 .is_end_event = exit_event_end, 71 .child_ops = child_events, 72 .decode_key = exit_event_decode_key, 73 .name = "VM-EXIT" 74 }; 75 76 const char * const kvm_events_tp[] = { 77 "kvm:kvm_s390_sie_enter", 78 "kvm:kvm_s390_sie_exit", 79 "kvm:kvm_s390_intercept_instruction", 80 "kvm:kvm_s390_handle_sigp", 81 "kvm:kvm_s390_handle_diag", 82 "kvm:kvm_s390_intercept_prog", 83 NULL, 84 }; 85 86 struct kvm_reg_events_ops kvm_reg_events_ops[] = { 87 { .name = "vmexit", .ops = &exit_events }, 88 { NULL, NULL }, 89 }; 90 91 const char * const kvm_skip_events[] = { 92 "Wait state", 93 NULL, 94 }; 95 96 int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid) 97 { 98 if (strstr(cpuid, "IBM/S390")) { 99 kvm->exit_reasons = sie_exit_reasons; 100 kvm->exit_reasons_isa = "SIE"; 101 } else 102 return -ENOTSUP; 103 104 return 0; 105 } 106