| @@ -1,5 +1,6 @@ |
| 1 | # intel-pt-events.py: Print Intel PT Power Events and PTWRITE | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | # Copyright (c) 2017, Intel Corporation. | 2 | # intel-pt-events.py: Print Intel PT Events including Power Events and PTWRITE |
| | 3 | # Copyright (c) 2017-2021, Intel Corporation. |
| 3 | # | 4 | # |
| 4 | # This program is free software; you can redistribute it and/or modify it | 5 | # This program is free software; you can redistribute it and/or modify it |
| 5 | # under the terms and conditions of the GNU General Public License, | 6 | # under the terms and conditions of the GNU General Public License, |
| @@ -23,8 +24,36 @@ sys.path.append(os.environ['PERF_EXEC_PATH'] + \ · 17 unmodified lines |
| 23 | #from perf_trace_context import * | 24 | #from perf_trace_context import * |
| 24 | #from Core import * | 25 | #from Core import * |
| 25 | | 26 | |
| | 27 | try: |
| | 28 | broken_pipe_exception = BrokenPipeError |
| | 29 | except: |
| | 30 | broken_pipe_exception = IOError |
| | 31 | |
| | 32 | glb_switch_str = None |
| | 33 | glb_switch_printed = True |
| | 34 | |
| | 35 | def get_optional_null(perf_dict, field): |
| | 36 | if field in perf_dict: |
| | 37 | return perf_dict[field] |
| | 38 | return "" |
| | 39 | |
| | 40 | def get_optional_zero(perf_dict, field): |
| | 41 | if field in perf_dict: |
| | 42 | return perf_dict[field] |
| | 43 | return 0 |
| | 44 | |
| | 45 | def get_optional(perf_dict, field): |
| | 46 | if field in perf_dict: |
| | 47 | return perf_dict[field] |
| | 48 | return "[unknown]" |
| | 49 | |
| | 50 | def get_offset(perf_dict, field): |
| | 51 | if field in perf_dict: |
| | 52 | return "+%#x" % perf_dict[field] |
| | 53 | return "" |
| | 54 | |
| 26 | def trace_begin(): | 55 | def trace_begin(): |
| 27 | print("Intel PT Power Events and PTWRITE") | 56 | print("Intel PT Branch Trace, Power Events and PTWRITE") |
| 28 | | 57 | |
| 29 | def trace_end(): | 58 | def trace_end(): |
| 30 | print("End") | 59 | print("End") |
| @@ -77,58 +106,110 @@ def print_pwrx(raw_buf): · 46 unmodified lines |
| 77 | print("deepest cstate: %u last cstate: %u wake reason: %#x" % | 106 | print("deepest cstate: %u last cstate: %u wake reason: %#x" % |
| 78 | (deepest_cstate, last_cstate, wake_reason), end=' ') | 107 | (deepest_cstate, last_cstate, wake_reason), end=' ') |
| 79 | | 108 | |
| | 109 | def print_psb(raw_buf): |
| | 110 | data = struct.unpack_from("<IQ", raw_buf) |
| | 111 | offset = data[1] |
| | 112 | print("offset: %#x" % (offset), end=' ') |
| | 113 | |
| 80 | def print_common_start(comm, sample, name): | 114 | def print_common_start(comm, sample, name): |
| 81 | ts = sample["time"] | 115 | ts = sample["time"] |
| 82 | cpu = sample["cpu"] | 116 | cpu = sample["cpu"] |
| 83 | pid = sample["pid"] | 117 | pid = sample["pid"] |
| 84 | tid = sample["tid"] | 118 | tid = sample["tid"] |
| 85 | print("%16s %5u/%-5u [%03u] %9u.%09u %7s:" % | 119 | flags_disp = get_optional_null(sample, "flags_disp") |
| 86 | (comm, pid, tid, cpu, ts / 1000000000, ts %1000000000, name), | 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), |
| 87 | end=' ') | 128 | end=' ') |
| 88 | | 129 | |
| 89 | def print_common_ip(sample, symbol, dso): | 130 | def print_common_ip(param_dict, sample, symbol, dso): |
| 90 | ip = sample["ip"] | 131 | ip = sample["ip"] |
| 91 | print("%16x %s (%s)" % (ip, symbol, dso)) | 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() |
| 92 | | 142 | |
| 93 | def process_event(param_dict): | 143 | def 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 |
| 94 | event_attr = param_dict["attr"] | 148 | event_attr = param_dict["attr"] |
| 95 | sample = param_dict["sample"] | 149 | sample = param_dict["sample"] |
| 96 | raw_buf = param_dict["raw_buf"] | 150 | raw_buf = param_dict["raw_buf"] |
| 97 | comm = param_dict["comm"] | 151 | comm = param_dict["comm"] |
| 98 | name = param_dict["ev_name"] | 152 | name = param_dict["ev_name"] |
| | 153 | # Unused fields: |
| | 154 | # callchain = param_dict["callchain"] |
| | 155 | # brstack = param_dict["brstack"] |
| | 156 | # brstacksym = param_dict["brstacksym"] |
| 99 | | 157 | |
| 100 | # Symbol and dso info are not always resolved | 158 | # Symbol and dso info are not always resolved |
| 101 | if "dso" in param_dict: | 159 | dso = get_optional(param_dict, "dso") |
| 102 | dso = param_dict["dso"] | 160 | symbol = get_optional(param_dict, "symbol") |
| 103 | else: | | |
| 104 | dso = "[unknown]" | | |
| 105 | | 161 | |
| 106 | if "symbol" in param_dict: | 162 | print_common_start(comm, sample, name) |
| 107 | symbol = param_dict["symbol"] | | |
| 108 | else: | | |
| 109 | symbol = "[unknown]" | | |
| 110 | | 163 | |
| 111 | if name == "ptwrite": | 164 | if name == "ptwrite": |
| 112 | print_common_start(comm, sample, name) | | |
| 113 | print_ptwrite(raw_buf) | 165 | print_ptwrite(raw_buf) |
| 114 | print_common_ip(sample, symbol, dso) | | |
| 115 | elif name == "cbr": | 166 | elif name == "cbr": |
| 116 | print_common_start(comm, sample, name) | | |
| 117 | print_cbr(raw_buf) | 167 | print_cbr(raw_buf) |
| 118 | print_common_ip(sample, symbol, dso) | | |
| 119 | elif name == "mwait": | 168 | elif name == "mwait": |
| 120 | print_common_start(comm, sample, name) | | |
| 121 | print_mwait(raw_buf) | 169 | print_mwait(raw_buf) |
| 122 | print_common_ip(sample, symbol, dso) | | |
| 123 | elif name == "pwre": | 170 | elif name == "pwre": |
| 124 | print_common_start(comm, sample, name) | | |
| 125 | print_pwre(raw_buf) | 171 | print_pwre(raw_buf) |
| 126 | print_common_ip(sample, symbol, dso) | | |
| 127 | elif name == "exstop": | 172 | elif name == "exstop": |
| 128 | print_common_start(comm, sample, name) | | |
| 129 | print_exstop(raw_buf) | 173 | print_exstop(raw_buf) |
| 130 | print_common_ip(sample, symbol, dso) | | |
| 131 | elif name == "pwrx": | 174 | elif name == "pwrx": |
| 132 | print_common_start(comm, sample, name) | | |
| 133 | print_pwrx(raw_buf) | 175 | print_pwrx(raw_buf) |
| 134 | print_common_ip(sample, symbol, dso) | 176 | elif name == "psb": |
| | 177 | print_psb(raw_buf) |
| | 178 | |
| | 179 | print_common_ip(param_dict, sample, symbol, dso) |
| | 180 | |
| | 181 | def 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 | |
| | 189 | def 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 | |
| | 198 | def 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 |