xref: /linux/tools/perf/scripts/python/powerpc-hcalls.py (revision 473f6c8f437b049f8ec015d57cd59bb983b1d85c)
1# SPDX-License-Identifier: GPL-2.0+
2#
3# Copyright (C) 2018 Ravi Bangoria, IBM Corporation
4#
5# Hypervisor call statisics
6
7from __future__ import print_function
8
9import os
10import sys
11
12sys.path.append(os.environ['PERF_EXEC_PATH'] + \
13	'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
14
15from perf_trace_context import *
16from Core import *
17from Util import *
18
19# output: {
20#	opcode: {
21#		'min': minimum time nsec
22#		'max': maximum time nsec
23#		'time': average time nsec
24#		'cnt': counter
25#	} ...
26# }
27output = {}
28sort_key = 'count'
29
30# d_enter: {
31#	cpu: {
32#		opcode: nsec
33#	} ...
34# }
35d_enter = {}
36
37hcall_table = {
38	4: 'H_REMOVE',
39	8: 'H_ENTER',
40	12: 'H_READ',
41	16: 'H_CLEAR_MOD',
42	20: 'H_CLEAR_REF',
43	24: 'H_PROTECT',
44	28: 'H_GET_TCE',
45	32: 'H_PUT_TCE',
46	36: 'H_SET_SPRG0',
47	40: 'H_SET_DABR',
48	44: 'H_PAGE_INIT',
49	48: 'H_SET_ASR',
50	52: 'H_ASR_ON',
51	56: 'H_ASR_OFF',
52	60: 'H_LOGICAL_CI_LOAD',
53	64: 'H_LOGICAL_CI_STORE',
54	68: 'H_LOGICAL_CACHE_LOAD',
55	72: 'H_LOGICAL_CACHE_STORE',
56	76: 'H_LOGICAL_ICBI',
57	80: 'H_LOGICAL_DCBF',
58	84: 'H_GET_TERM_CHAR',
59	88: 'H_PUT_TERM_CHAR',
60	92: 'H_REAL_TO_LOGICAL',
61	96: 'H_HYPERVISOR_DATA',
62	100: 'H_EOI',
63	104: 'H_CPPR',
64	108: 'H_IPI',
65	112: 'H_IPOLL',
66	116: 'H_XIRR',
67	120: 'H_MIGRATE_DMA',
68	124: 'H_PERFMON',
69	220: 'H_REGISTER_VPA',
70	224: 'H_CEDE',
71	228: 'H_CONFER',
72	232: 'H_PROD',
73	236: 'H_GET_PPP',
74	240: 'H_SET_PPP',
75	244: 'H_PURR',
76	248: 'H_PIC',
77	252: 'H_REG_CRQ',
78	256: 'H_FREE_CRQ',
79	260: 'H_VIO_SIGNAL',
80	264: 'H_SEND_CRQ',
81	272: 'H_COPY_RDMA',
82	276: 'H_REGISTER_LOGICAL_LAN',
83	280: 'H_FREE_LOGICAL_LAN',
84	284: 'H_ADD_LOGICAL_LAN_BUFFER',
85	288: 'H_SEND_LOGICAL_LAN',
86	292: 'H_BULK_REMOVE',
87	304: 'H_MULTICAST_CTRL',
88	308: 'H_SET_XDABR',
89	312: 'H_STUFF_TCE',
90	316: 'H_PUT_TCE_INDIRECT',
91	332: 'H_CHANGE_LOGICAL_LAN_MAC',
92	336: 'H_VTERM_PARTNER_INFO',
93	340: 'H_REGISTER_VTERM',
94	344: 'H_FREE_VTERM',
95	348: 'H_RESET_EVENTS',
96	352: 'H_ALLOC_RESOURCE',
97	356: 'H_FREE_RESOURCE',
98	360: 'H_MODIFY_QP',
99	364: 'H_QUERY_QP',
100	368: 'H_REREGISTER_PMR',
101	372: 'H_REGISTER_SMR',
102	376: 'H_QUERY_MR',
103	380: 'H_QUERY_MW',
104	384: 'H_QUERY_HCA',
105	388: 'H_QUERY_PORT',
106	392: 'H_MODIFY_PORT',
107	396: 'H_DEFINE_AQP1',
108	400: 'H_GET_TRACE_BUFFER',
109	404: 'H_DEFINE_AQP0',
110	408: 'H_RESIZE_MR',
111	412: 'H_ATTACH_MCQP',
112	416: 'H_DETACH_MCQP',
113	420: 'H_CREATE_RPT',
114	424: 'H_REMOVE_RPT',
115	428: 'H_REGISTER_RPAGES',
116	432: 'H_DISABLE_AND_GET',
117	436: 'H_ERROR_DATA',
118	440: 'H_GET_HCA_INFO',
119	444: 'H_GET_PERF_COUNT',
120	448: 'H_MANAGE_TRACE',
121	456: 'H_GET_CPU_CHARACTERISTICS',
122	468: 'H_FREE_LOGICAL_LAN_BUFFER',
123	472: 'H_POLL_PENDING',
124	484: 'H_QUERY_INT_STATE',
125	580: 'H_ILLAN_ATTRIBUTES',
126	584: 'H_ADD_LOGICAL_LAN_BUFFERS',
127	592: 'H_MODIFY_HEA_QP',
128	596: 'H_QUERY_HEA_QP',
129	600: 'H_QUERY_HEA',
130	604: 'H_QUERY_HEA_PORT',
131	608: 'H_MODIFY_HEA_PORT',
132	612: 'H_REG_BCMC',
133	616: 'H_DEREG_BCMC',
134	620: 'H_REGISTER_HEA_RPAGES',
135	624: 'H_DISABLE_AND_GET_HEA',
136	628: 'H_GET_HEA_INFO',
137	632: 'H_ALLOC_HEA_RESOURCE',
138	644: 'H_ADD_CONN',
139	648: 'H_DEL_CONN',
140	664: 'H_JOIN',
141	672: 'H_VASI_SIGNAL',
142	676: 'H_VASI_STATE',
143	680: 'H_VIOCTL',
144	688: 'H_ENABLE_CRQ',
145	696: 'H_GET_EM_PARMS',
146	720: 'H_SET_MPP',
147	724: 'H_GET_MPP',
148	732: 'H_REG_SUB_CRQ',
149	736: 'H_FREE_SUB_CRQ',
150	740: 'H_SEND_SUB_CRQ',
151	744: 'H_SEND_SUB_CRQ_INDIRECT',
152	748: 'H_HOME_NODE_ASSOCIATIVITY',
153	756: 'H_BEST_ENERGY',
154	764: 'H_XIRR_X',
155	768: 'H_RANDOM',
156	772: 'H_COP',
157	788: 'H_GET_MPP_X',
158	796: 'H_SET_MODE',
159	808: 'H_BLOCK_REMOVE',
160	856: 'H_CLEAR_HPT',
161	864: 'H_REQUEST_VMC',
162	876: 'H_RESIZE_HPT_PREPARE',
163	880: 'H_RESIZE_HPT_COMMIT',
164	892: 'H_REGISTER_PROC_TBL',
165	896: 'H_SIGNAL_SYS_RESET',
166	904: 'H_ALLOCATE_VAS_WINDOW',
167	908: 'H_MODIFY_VAS_WINDOW',
168	912: 'H_DEALLOCATE_VAS_WINDOW',
169	916: 'H_QUERY_VAS_WINDOW',
170	920: 'H_QUERY_VAS_CAPABILITIES',
171	924: 'H_QUERY_NX_CAPABILITIES',
172	928: 'H_GET_NX_FAULT',
173	936: 'H_INT_GET_SOURCE_INFO',
174	940: 'H_INT_SET_SOURCE_CONFIG',
175	944: 'H_INT_GET_SOURCE_CONFIG',
176	948: 'H_INT_GET_QUEUE_INFO',
177	952: 'H_INT_SET_QUEUE_CONFIG',
178	956: 'H_INT_GET_QUEUE_CONFIG',
179	960: 'H_INT_SET_OS_REPORTING_LINE',
180	964: 'H_INT_GET_OS_REPORTING_LINE',
181	968: 'H_INT_ESB',
182	972: 'H_INT_SYNC',
183	976: 'H_INT_RESET',
184	996: 'H_SCM_READ_METADATA',
185	1000: 'H_SCM_WRITE_METADATA',
186	1004: 'H_SCM_BIND_MEM',
187	1008: 'H_SCM_UNBIND_MEM',
188	1012: 'H_SCM_QUERY_BLOCK_MEM_BINDING',
189	1016: 'H_SCM_QUERY_LOGICAL_MEM_BINDING',
190	1020: 'H_SCM_UNBIND_ALL',
191	1024: 'H_SCM_HEALTH',
192	1048: 'H_SCM_PERFORMANCE_STATS',
193	1052: 'H_PKS_GET_CONFIG',
194	1056: 'H_PKS_SET_PASSWORD',
195	1060: 'H_PKS_GEN_PASSWORD',
196	1068: 'H_PKS_WRITE_OBJECT',
197	1072: 'H_PKS_GEN_KEY',
198	1076: 'H_PKS_READ_OBJECT',
199	1080: 'H_PKS_REMOVE_OBJECT',
200	1084: 'H_PKS_CONFIRM_OBJECT_FLUSHED',
201	1096: 'H_RPT_INVALIDATE',
202	1100: 'H_SCM_FLUSH',
203	1104: 'H_GET_ENERGY_SCALE_INFO',
204	1108: 'H_PKS_SIGNED_UPDATE',
205	1112: 'H_HTM',
206	1116: 'H_WATCHDOG',
207	# Platform specific hcalls used by KVM on PowerVM
208	1120: 'H_GUEST_GET_CAPABILITIES',
209	1124: 'H_GUEST_SET_CAPABILITIES',
210	1136: 'H_GUEST_CREATE',
211	1140: 'H_GUEST_CREATE_VCPU',
212	1144: 'H_GUEST_GET_STATE',
213	1148: 'H_GUEST_SET_STATE',
214	1152: 'H_GUEST_RUN_VCPU',
215	1156: 'H_GUEST_COPY_MEMORY',
216	1160: 'H_GUEST_DELETE',
217	# Key wrapping hcalls
218	1168: 'H_PKS_WRAP_OBJECT',
219	1172: 'H_PKS_UNWRAP_OBJECT',
220	# Platform-specific hcalls used by the Ultravisor
221	61184: 'H_SVM_PAGE_IN',
222	61188: 'H_SVM_PAGE_OUT',
223	61192: 'H_SVM_INIT_START',
224	61196: 'H_SVM_INIT_DONE',
225	61204: 'H_SVM_INIT_ABORT',
226	# Platform specific hcalls used by KVM
227	61440: 'H_RTAS',
228	# Platform specific hcalls used by QEMU/SLOF
229	61441: 'H_LOGICAL_MEMOP',
230	61442: 'H_CAS',
231	61443: 'H_UPDATE_DT',
232	# Platform specific hcalls provided by PHYP
233	61560: 'H_GET_24X7_CATALOG_PAGE',
234	61564: 'H_GET_24X7_DATA',
235	61568: 'H_GET_PERF_COUNTER_INFO',
236	# Platform-specific hcalls used for nested HV KVM
237	63488: 'H_SET_PARTITION_TABLE',
238	63492: 'H_ENTER_NESTED',
239	63496: 'H_TLB_INVALIDATE',
240	63500: 'H_COPY_TOFROM_GUEST',
241}
242
243def hcall_table_lookup(opcode):
244	if (opcode in hcall_table):
245		return hcall_table[opcode]
246	else:
247		return opcode
248
249print_ptrn = '%-28s%10s%10s%10s%10s'
250
251def sort_output(opcode):
252	stats = output[opcode]
253
254	if sort_key == 'min':
255		return stats['min']
256	if sort_key == 'max':
257		return stats['max']
258	if sort_key == 'avg':
259		return stats['time'] // stats['cnt']
260
261	return stats['cnt']
262
263def trace_begin():
264	global sort_key
265
266	valid_sort_keys = ['count', 'min', 'max', 'avg']
267
268	i = 1
269	while i < len(sys.argv):
270		arg = sys.argv[i]
271
272		if arg == '-s' or arg == '--sort':
273			if i + 1 >= len(sys.argv):
274				print("Error: -s/--sort requires a sort key argument")
275				sys.exit(1)
276			sort_key = sys.argv[i + 1]
277			i += 2
278			continue
279
280		if arg.startswith('--sort='):
281			sort_key = arg.split('=', 1)[1]
282			i += 1
283			continue
284
285		i += 1
286
287	if sort_key not in valid_sort_keys:
288		print(f"Error: Invalid sort key '{sort_key}'. Valid options are: {', '.join(valid_sort_keys)}")
289		sys.exit(1)
290
291	print("SORT KEY =", sort_key)
292
293def trace_end():
294	print(print_ptrn % ('hcall', 'count', 'min(ns)', 'max(ns)', 'avg(ns)'))
295	print('-' * 68)
296	for opcode in sorted(output, key = sort_output,
297                            reverse=True):
298		h_name = hcall_table_lookup(opcode)
299		time = output[opcode]['time']
300		cnt = output[opcode]['cnt']
301		min_t = output[opcode]['min']
302		max_t = output[opcode]['max']
303
304		print(print_ptrn % (h_name, cnt, min_t, max_t, time//cnt))
305
306def powerpc__hcall_exit(name, context, cpu, sec, nsec, pid, comm, callchain,
307			opcode, retval):
308	if (cpu in d_enter and opcode in d_enter[cpu]):
309		diff = nsecs(sec, nsec) - d_enter[cpu][opcode]
310
311		if (opcode in output):
312			output[opcode]['time'] += diff
313			output[opcode]['cnt'] += 1
314			if (output[opcode]['min'] > diff):
315				output[opcode]['min'] = diff
316			if (output[opcode]['max'] < diff):
317				output[opcode]['max'] = diff
318		else:
319			output[opcode] = {
320				'time': diff,
321				'cnt': 1,
322				'min': diff,
323				'max': diff,
324			}
325
326		del d_enter[cpu][opcode]
327#	else:
328#		print("Can't find matching hcall_enter event. Ignoring sample")
329
330def powerpc__hcall_entry(event_name, context, cpu, sec, nsec, pid, comm,
331			 callchain, opcode):
332		if (cpu in d_enter):
333			d_enter[cpu][opcode] = nsecs(sec, nsec)
334		else:
335			d_enter[cpu] = {opcode: nsecs(sec, nsec)}
336