| @@ -1,5 +1,6 @@ |
| 1 | | −# intel-pt-events.py: Print Intel PT Power Events and PTWRITE |
| 2 | | −# Copyright (c) 2017, Intel Corporation. |
| 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. |
| 3 | 4 | # |
| 4 | 5 | # This program is free software; you can redistribute it and/or modify it |
| 5 | 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 | 24 | #from perf_trace_context import * |
| 24 | 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 | 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 | 58 | def trace_end(): |
| 30 | 59 | print("End") |
| @@ -77,58 +106,110 @@ def print_pwrx(raw_buf): · 46 unmodified lines |
| 77 | 106 | print("deepest cstate: %u last cstate: %u wake reason: %#x" % |
| 78 | 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 | 114 | def print_common_start(comm, sample, name): |
| 81 | 115 | ts = sample["time"] |
| 82 | 116 | cpu = sample["cpu"] |
| 83 | 117 | pid = sample["pid"] |
| 84 | 118 | tid = sample["tid"] |
| 85 | | − print("%16s %5u/%-5u [%03u] %9u.%09u %7s:" % |
| 86 | | − (comm, pid, tid, cpu, ts / 1000000000, ts %1000000000, name), |
| 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), |
| 87 | 128 | end=' ') |
| 88 | 129 | |
| 89 | | −def print_common_ip(sample, symbol, dso): |
| 90 | | − ip = sample["ip"] |
| 91 | | − print("%16x %s (%s)" % (ip, symbol, dso)) |
| 130 | +def 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() |
| 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 | 148 | event_attr = param_dict["attr"] |
| 95 | | − sample = param_dict["sample"] |
| 96 | | − raw_buf = param_dict["raw_buf"] |
| 149 | + sample = param_dict["sample"] |
| 150 | + raw_buf = param_dict["raw_buf"] |
| 97 | 151 | comm = param_dict["comm"] |
| 98 | 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 | 158 | # Symbol and dso info are not always resolved |
| 101 | | − if "dso" in param_dict: |
| 102 | | − dso = param_dict["dso"] |
| 103 | | − else: |
| 104 | | − dso = "[unknown]" |
| 159 | + dso = get_optional(param_dict, "dso") |
| 160 | + symbol = get_optional(param_dict, "symbol") |
| 105 | 161 | |
| 106 | | − if "symbol" in param_dict: |
| 107 | | − symbol = param_dict["symbol"] |
| 108 | | − else: |
| 109 | | − symbol = "[unknown]" |
| 162 | + print_common_start(comm, sample, name) |
| 110 | 163 | |
| 111 | 164 | if name == "ptwrite": |
| 112 | | − print_common_start(comm, sample, name) |
| 113 | 165 | print_ptwrite(raw_buf) |
| 114 | | − print_common_ip(sample, symbol, dso) |
| 115 | 166 | elif name == "cbr": |
| 116 | | − print_common_start(comm, sample, name) |
| 117 | 167 | print_cbr(raw_buf) |
| 118 | | − print_common_ip(sample, symbol, dso) |
| 119 | 168 | elif name == "mwait": |
| 120 | | − print_common_start(comm, sample, name) |
| 121 | 169 | print_mwait(raw_buf) |
| 122 | | − print_common_ip(sample, symbol, dso) |
| 123 | 170 | elif name == "pwre": |
| 124 | | − print_common_start(comm, sample, name) |
| 125 | 171 | print_pwre(raw_buf) |
| 126 | | − print_common_ip(sample, symbol, dso) |
| 127 | 172 | elif name == "exstop": |
| 128 | | − print_common_start(comm, sample, name) |
| 129 | 173 | print_exstop(raw_buf) |
| 130 | | − print_common_ip(sample, symbol, dso) |
| 131 | 174 | elif name == "pwrx": |
| 132 | | − print_common_start(comm, sample, name) |
| 133 | 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 |