xref: /linux/tools/perf/util/kvm-stat-arch/kvm-stat-s390.c (revision b2128290c29902315e632ea59e0504d6bc9e9b42)
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