18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Arch specific functions for perf kvm stat. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2014 IBM Corp. 68c2ecf20Sopenharmony_ci * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <errno.h> 108c2ecf20Sopenharmony_ci#include <string.h> 118c2ecf20Sopenharmony_ci#include "../../util/kvm-stat.h" 128c2ecf20Sopenharmony_ci#include "../../util/evsel.h" 138c2ecf20Sopenharmony_ci#include <asm/sie.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cidefine_exit_reasons_table(sie_exit_reasons, sie_intercept_code); 168c2ecf20Sopenharmony_cidefine_exit_reasons_table(sie_icpt_insn_codes, icpt_insn_codes); 178c2ecf20Sopenharmony_cidefine_exit_reasons_table(sie_sigp_order_codes, sigp_order_codes); 188c2ecf20Sopenharmony_cidefine_exit_reasons_table(sie_diagnose_codes, diagnose_codes); 198c2ecf20Sopenharmony_cidefine_exit_reasons_table(sie_icpt_prog_codes, icpt_prog_codes); 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ciconst char *vcpu_id_str = "id"; 228c2ecf20Sopenharmony_ciconst int decode_str_len = 40; 238c2ecf20Sopenharmony_ciconst char *kvm_exit_reason = "icptcode"; 248c2ecf20Sopenharmony_ciconst char *kvm_entry_trace = "kvm:kvm_s390_sie_enter"; 258c2ecf20Sopenharmony_ciconst char *kvm_exit_trace = "kvm:kvm_s390_sie_exit"; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic void event_icpt_insn_get_key(struct evsel *evsel, 288c2ecf20Sopenharmony_ci struct perf_sample *sample, 298c2ecf20Sopenharmony_ci struct event_key *key) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci unsigned long insn; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci insn = evsel__intval(evsel, sample, "instruction"); 348c2ecf20Sopenharmony_ci key->key = icpt_insn_decoder(insn); 358c2ecf20Sopenharmony_ci key->exit_reasons = sie_icpt_insn_codes; 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic void event_sigp_get_key(struct evsel *evsel, 398c2ecf20Sopenharmony_ci struct perf_sample *sample, 408c2ecf20Sopenharmony_ci struct event_key *key) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci key->key = evsel__intval(evsel, sample, "order_code"); 438c2ecf20Sopenharmony_ci key->exit_reasons = sie_sigp_order_codes; 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic void event_diag_get_key(struct evsel *evsel, 478c2ecf20Sopenharmony_ci struct perf_sample *sample, 488c2ecf20Sopenharmony_ci struct event_key *key) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci key->key = evsel__intval(evsel, sample, "code"); 518c2ecf20Sopenharmony_ci key->exit_reasons = sie_diagnose_codes; 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic void event_icpt_prog_get_key(struct evsel *evsel, 558c2ecf20Sopenharmony_ci struct perf_sample *sample, 568c2ecf20Sopenharmony_ci struct event_key *key) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci key->key = evsel__intval(evsel, sample, "code"); 598c2ecf20Sopenharmony_ci key->exit_reasons = sie_icpt_prog_codes; 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic struct child_event_ops child_events[] = { 638c2ecf20Sopenharmony_ci { .name = "kvm:kvm_s390_intercept_instruction", 648c2ecf20Sopenharmony_ci .get_key = event_icpt_insn_get_key }, 658c2ecf20Sopenharmony_ci { .name = "kvm:kvm_s390_handle_sigp", 668c2ecf20Sopenharmony_ci .get_key = event_sigp_get_key }, 678c2ecf20Sopenharmony_ci { .name = "kvm:kvm_s390_handle_diag", 688c2ecf20Sopenharmony_ci .get_key = event_diag_get_key }, 698c2ecf20Sopenharmony_ci { .name = "kvm:kvm_s390_intercept_prog", 708c2ecf20Sopenharmony_ci .get_key = event_icpt_prog_get_key }, 718c2ecf20Sopenharmony_ci { NULL, NULL }, 728c2ecf20Sopenharmony_ci}; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic struct kvm_events_ops exit_events = { 758c2ecf20Sopenharmony_ci .is_begin_event = exit_event_begin, 768c2ecf20Sopenharmony_ci .is_end_event = exit_event_end, 778c2ecf20Sopenharmony_ci .child_ops = child_events, 788c2ecf20Sopenharmony_ci .decode_key = exit_event_decode_key, 798c2ecf20Sopenharmony_ci .name = "VM-EXIT" 808c2ecf20Sopenharmony_ci}; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ciconst char *kvm_events_tp[] = { 838c2ecf20Sopenharmony_ci "kvm:kvm_s390_sie_enter", 848c2ecf20Sopenharmony_ci "kvm:kvm_s390_sie_exit", 858c2ecf20Sopenharmony_ci "kvm:kvm_s390_intercept_instruction", 868c2ecf20Sopenharmony_ci "kvm:kvm_s390_handle_sigp", 878c2ecf20Sopenharmony_ci "kvm:kvm_s390_handle_diag", 888c2ecf20Sopenharmony_ci "kvm:kvm_s390_intercept_prog", 898c2ecf20Sopenharmony_ci NULL, 908c2ecf20Sopenharmony_ci}; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistruct kvm_reg_events_ops kvm_reg_events_ops[] = { 938c2ecf20Sopenharmony_ci { .name = "vmexit", .ops = &exit_events }, 948c2ecf20Sopenharmony_ci { NULL, NULL }, 958c2ecf20Sopenharmony_ci}; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ciconst char * const kvm_skip_events[] = { 988c2ecf20Sopenharmony_ci "Wait state", 998c2ecf20Sopenharmony_ci NULL, 1008c2ecf20Sopenharmony_ci}; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ciint cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci if (strstr(cpuid, "IBM")) { 1058c2ecf20Sopenharmony_ci kvm->exit_reasons = sie_exit_reasons; 1068c2ecf20Sopenharmony_ci kvm->exit_reasons_isa = "SIE"; 1078c2ecf20Sopenharmony_ci } else 1088c2ecf20Sopenharmony_ci return -ENOTSUP; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci return 0; 1118c2ecf20Sopenharmony_ci} 112