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 15define_exit_reasons_table(sie_exit_reasons, sie_intercept_code); 16define_exit_reasons_table(sie_icpt_insn_codes, icpt_insn_codes); 17define_exit_reasons_table(sie_sigp_order_codes, sigp_order_codes); 18define_exit_reasons_table(sie_diagnose_codes, diagnose_codes); 19define_exit_reasons_table(sie_icpt_prog_codes, icpt_prog_codes); 20 21static 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 32static 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 40static 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 48static 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 56static 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 68static 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 76const 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 86struct kvm_reg_events_ops kvm_reg_events_ops[] = { 87 { .name = "vmexit", .ops = &exit_events }, 88 { NULL, NULL }, 89}; 90 91const char * const kvm_skip_events[] = { 92 "Wait state", 93 NULL, 94}; 95 96int 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