xref: /linux/tools/perf/scripts/python/intel-pt-events.py (revision 4c62244e035e99a9e43d25a017cbe98f7562b21f)
1# SPDX-License-Identifier: GPL-2.0
2# intel-pt-events.py: Print Intel PT Events including Power Events and PTWRITE
3# Copyright (c) 2017-2021, Intel Corporation.
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms and conditions of the GNU General Public License,
7# version 2, as published by the Free Software Foundation.
8#
9# This program is distributed in the hope it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12# more details.
13
14from __future__ import print_function
15
16import os
17import sys
18import struct
19
20sys.path.append(os.environ['PERF_EXEC_PATH'] + \
21	'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
22
23# These perf imports are not used at present
24#from perf_trace_context import *
25#from Core import *
26
27try:
28	broken_pipe_exception = BrokenPipeError
29except:
30	broken_pipe_exception = IOError
31
32glb_switch_str = None
33glb_switch_printed = True
34
35def get_optional_null(perf_dict, field):
36	if field in perf_dict:
37		return perf_dict[field]
38	return ""
39
40def get_optional_zero(perf_dict, field):
41	if field in perf_dict:
42		return perf_dict[field]
43	return 0
44
45def get_optional(perf_dict, field):
46	if field in perf_dict:
47		return perf_dict[field]
48	return "[unknown]"
49
50def get_offset(perf_dict, field):
51	if field in perf_dict:
52		return "+%#x" % perf_dict[field]
53	return ""
54
55def trace_begin():
56	print("Intel PT Branch Trace, Power Events and PTWRITE")
57
58def trace_end():
59	print("End")
60
61def trace_unhandled(event_name, context, event_fields_dict):
62		print(' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]))
63
64def print_ptwrite(raw_buf):
65	data = struct.unpack_from("<IQ", raw_buf)
66	flags = data[0]
67	payload = data[1]
68	exact_ip = flags & 1
69	print("IP: %u payload: %#x" % (exact_ip, payload), end=' ')
70
71def print_cbr(raw_buf):
72	data = struct.unpack_from("<BBBBII", raw_buf)
73	cbr = data[0]
74	f = (data[4] + 500) / 1000
75	p = ((cbr * 1000 / data[2]) + 5) / 10
76	print("%3u  freq: %4u MHz  (%3u%%)" % (cbr, f, p), end=' ')
77
78def print_mwait(raw_buf):
79	data = struct.unpack_from("<IQ", raw_buf)
80	payload = data[1]
81	hints = payload & 0xff
82	extensions = (payload >> 32) & 0x3
83	print("hints: %#x extensions: %#x" % (hints, extensions), end=' ')
84
85def print_pwre(raw_buf):
86	data = struct.unpack_from("<IQ", raw_buf)
87	payload = data[1]
88	hw = (payload >> 7) & 1
89	cstate = (payload >> 12) & 0xf
90	subcstate = (payload >> 8) & 0xf
91	print("hw: %u cstate: %u sub-cstate: %u" % (hw, cstate, subcstate),
92		end=' ')
93
94def print_exstop(raw_buf):
95	data = struct.unpack_from("<I", raw_buf)
96	flags = data[0]
97	exact_ip = flags & 1
98	print("IP: %u" % (exact_ip), end=' ')
99
100def print_pwrx(raw_buf):
101	data = struct.unpack_from("<IQ", raw_buf)
102	payload = data[1]
103	deepest_cstate = payload & 0xf
104	last_cstate = (payload >> 4) & 0xf
105	wake_reason = (payload >> 8) & 0xf
106	print("deepest cstate: %u last cstate: %u wake reason: %#x" %
107		(deepest_cstate, last_cstate, wake_reason), end=' ')
108
109def print_psb(raw_buf):
110	data = struct.unpack_from("<IQ", raw_buf)
111	offset = data[1]
112	print("offset: %#x" % (offset), end=' ')
113
114def print_common_start(comm, sample, name):
115	ts = sample["time"]
116	cpu = sample["cpu"]
117	pid = sample["pid"]
118	tid = sample["tid"]
119	flags_disp = get_optional_null(sample, "flags_disp")
120	# Unused fields:
121	# period      = sample["period"]
122	# phys_addr   = sample["phys_addr"]
123	# weight      = sample["weight"]
124	# transaction = sample["transaction"]
125	# cpumode     = get_optional_zero(sample, "cpumode")
126	print("%16s %5u/%-5u [%03u] %9u.%09u  %7s  %19s" %
127		(comm, pid, tid, cpu, ts / 1000000000, ts %1000000000, name, flags_disp),
128		end=' ')
129
130def print_common_ip(param_dict, sample, symbol, dso):
131	ip   = sample["ip"]
132	offs = get_offset(param_dict, "symoff")
133	print("%16x %s%s (%s)" % (ip, symbol, offs, dso), end=' ')
134	if "addr_correlates_sym" in sample:
135		addr   = sample["addr"]
136		dso    = get_optional(sample, "addr_dso")
137		symbol = get_optional(sample, "addr_symbol")
138		offs   = get_offset(sample, "addr_symoff")
139		print("=> %x %s%s (%s)" % (addr, symbol, offs, dso))
140	else:
141		print()
142
143def do_process_event(param_dict):
144	global glb_switch_printed
145	if not glb_switch_printed:
146		print(glb_switch_str)
147		glb_switch_printed = True
148	event_attr = param_dict["attr"]
149	sample	   = param_dict["sample"]
150	raw_buf	   = param_dict["raw_buf"]
151	comm	   = param_dict["comm"]
152	name	   = param_dict["ev_name"]
153	# Unused fields:
154	# callchain  = param_dict["callchain"]
155	# brstack    = param_dict["brstack"]
156	# brstacksym = param_dict["brstacksym"]
157
158	# Symbol and dso info are not always resolved
159	dso    = get_optional(param_dict, "dso")
160	symbol = get_optional(param_dict, "symbol")
161
162	print_common_start(comm, sample, name)
163
164	if name == "ptwrite":
165		print_ptwrite(raw_buf)
166	elif name == "cbr":
167		print_cbr(raw_buf)
168	elif name == "mwait":
169		print_mwait(raw_buf)
170	elif name == "pwre":
171		print_pwre(raw_buf)
172	elif name == "exstop":
173		print_exstop(raw_buf)
174	elif name == "pwrx":
175		print_pwrx(raw_buf)
176	elif name == "psb":
177		print_psb(raw_buf)
178
179	print_common_ip(param_dict, sample, symbol, dso)
180
181def process_event(param_dict):
182	try:
183		do_process_event(param_dict)
184	except broken_pipe_exception:
185		# Stop python printing broken pipe errors and traceback
186		sys.stdout = open(os.devnull, 'w')
187		sys.exit(1)
188
189def auxtrace_error(typ, code, cpu, pid, tid, ip, ts, msg, cpumode, *x):
190	try:
191		print("%16s %5u/%-5u [%03u] %9u.%09u  error type %u code %u: %s ip 0x%16x" %
192			("Trace error", pid, tid, cpu, ts / 1000000000, ts %1000000000, typ, code, msg, ip))
193	except broken_pipe_exception:
194		# Stop python printing broken pipe errors and traceback
195		sys.stdout = open(os.devnull, 'w')
196		sys.exit(1)
197
198def context_switch(ts, cpu, pid, tid, np_pid, np_tid, machine_pid, out, out_preempt, *x):
199	global glb_switch_printed
200	global glb_switch_str
201	if out:
202		out_str = "Switch out "
203	else:
204		out_str = "Switch In  "
205	if out_preempt:
206		preempt_str = "preempt"
207	else:
208		preempt_str = ""
209	if machine_pid == -1:
210		machine_str = ""
211	else:
212		machine_str = "machine PID %d" % machine_pid
213	glb_switch_str = "%16s %5d/%-5d [%03u] %9u.%09u %5d/%-5d %s %s" % \
214		(out_str, pid, tid, cpu, ts / 1000000000, ts %1000000000, np_pid, np_tid, machine_str, preempt_str)
215	glb_switch_printed = False
216