Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tools: Add Intel PT packet decoder

Add support for decoding Intel Processor Trace packets.

This essentially provides intel_pt_get_packet() which takes a buffer of
binary data and returns the decoded packet.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/1437150840-31811-3-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Adrian Hunter and committed by
Arnaldo Carvalho de Melo
a4e92590 55ea4ab4

+466
+1
tools/perf/util/Build
··· 78 78 libperf-y += cloexec.o 79 79 libperf-y += thread-stack.o 80 80 libperf-$(CONFIG_AUXTRACE) += auxtrace.o 81 + libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/ 81 82 libperf-y += parse-branch-options.o 82 83 83 84 libperf-$(CONFIG_LIBELF) += symbol-elf.o
+1
tools/perf/util/intel-pt-decoder/Build
··· 1 + libperf-$(CONFIG_AUXTRACE) += intel-pt-pkt-decoder.o
+400
tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
··· 1 + /* 2 + * intel_pt_pkt_decoder.c: Intel Processor Trace support 3 + * Copyright (c) 2013-2014, 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 + * 14 + */ 15 + 16 + #include <stdio.h> 17 + #include <string.h> 18 + #include <endian.h> 19 + #include <byteswap.h> 20 + 21 + #include "intel-pt-pkt-decoder.h" 22 + 23 + #define BIT(n) (1 << (n)) 24 + 25 + #define BIT63 ((uint64_t)1 << 63) 26 + 27 + #if __BYTE_ORDER == __BIG_ENDIAN 28 + #define le16_to_cpu bswap_16 29 + #define le32_to_cpu bswap_32 30 + #define le64_to_cpu bswap_64 31 + #define memcpy_le64(d, s, n) do { \ 32 + memcpy((d), (s), (n)); \ 33 + *(d) = le64_to_cpu(*(d)); \ 34 + } while (0) 35 + #else 36 + #define le16_to_cpu 37 + #define le32_to_cpu 38 + #define le64_to_cpu 39 + #define memcpy_le64 memcpy 40 + #endif 41 + 42 + static const char * const packet_name[] = { 43 + [INTEL_PT_BAD] = "Bad Packet!", 44 + [INTEL_PT_PAD] = "PAD", 45 + [INTEL_PT_TNT] = "TNT", 46 + [INTEL_PT_TIP_PGD] = "TIP.PGD", 47 + [INTEL_PT_TIP_PGE] = "TIP.PGE", 48 + [INTEL_PT_TSC] = "TSC", 49 + [INTEL_PT_MODE_EXEC] = "MODE.Exec", 50 + [INTEL_PT_MODE_TSX] = "MODE.TSX", 51 + [INTEL_PT_TIP] = "TIP", 52 + [INTEL_PT_FUP] = "FUP", 53 + [INTEL_PT_PSB] = "PSB", 54 + [INTEL_PT_PSBEND] = "PSBEND", 55 + [INTEL_PT_CBR] = "CBR", 56 + [INTEL_PT_PIP] = "PIP", 57 + [INTEL_PT_OVF] = "OVF", 58 + }; 59 + 60 + const char *intel_pt_pkt_name(enum intel_pt_pkt_type type) 61 + { 62 + return packet_name[type]; 63 + } 64 + 65 + static int intel_pt_get_long_tnt(const unsigned char *buf, size_t len, 66 + struct intel_pt_pkt *packet) 67 + { 68 + uint64_t payload; 69 + int count; 70 + 71 + if (len < 8) 72 + return INTEL_PT_NEED_MORE_BYTES; 73 + 74 + payload = le64_to_cpu(*(uint64_t *)buf); 75 + 76 + for (count = 47; count; count--) { 77 + if (payload & BIT63) 78 + break; 79 + payload <<= 1; 80 + } 81 + 82 + packet->type = INTEL_PT_TNT; 83 + packet->count = count; 84 + packet->payload = payload << 1; 85 + return 8; 86 + } 87 + 88 + static int intel_pt_get_pip(const unsigned char *buf, size_t len, 89 + struct intel_pt_pkt *packet) 90 + { 91 + uint64_t payload = 0; 92 + 93 + if (len < 8) 94 + return INTEL_PT_NEED_MORE_BYTES; 95 + 96 + packet->type = INTEL_PT_PIP; 97 + memcpy_le64(&payload, buf + 2, 6); 98 + packet->payload = payload >> 1; 99 + 100 + return 8; 101 + } 102 + 103 + static int intel_pt_get_cbr(const unsigned char *buf, size_t len, 104 + struct intel_pt_pkt *packet) 105 + { 106 + if (len < 4) 107 + return INTEL_PT_NEED_MORE_BYTES; 108 + packet->type = INTEL_PT_CBR; 109 + packet->payload = buf[2]; 110 + return 4; 111 + } 112 + 113 + static int intel_pt_get_ovf(struct intel_pt_pkt *packet) 114 + { 115 + packet->type = INTEL_PT_OVF; 116 + return 2; 117 + } 118 + 119 + static int intel_pt_get_psb(const unsigned char *buf, size_t len, 120 + struct intel_pt_pkt *packet) 121 + { 122 + int i; 123 + 124 + if (len < 16) 125 + return INTEL_PT_NEED_MORE_BYTES; 126 + 127 + for (i = 2; i < 16; i += 2) { 128 + if (buf[i] != 2 || buf[i + 1] != 0x82) 129 + return INTEL_PT_BAD_PACKET; 130 + } 131 + 132 + packet->type = INTEL_PT_PSB; 133 + return 16; 134 + } 135 + 136 + static int intel_pt_get_psbend(struct intel_pt_pkt *packet) 137 + { 138 + packet->type = INTEL_PT_PSBEND; 139 + return 2; 140 + } 141 + 142 + static int intel_pt_get_pad(struct intel_pt_pkt *packet) 143 + { 144 + packet->type = INTEL_PT_PAD; 145 + return 1; 146 + } 147 + 148 + static int intel_pt_get_ext(const unsigned char *buf, size_t len, 149 + struct intel_pt_pkt *packet) 150 + { 151 + if (len < 2) 152 + return INTEL_PT_NEED_MORE_BYTES; 153 + 154 + switch (buf[1]) { 155 + case 0xa3: /* Long TNT */ 156 + return intel_pt_get_long_tnt(buf, len, packet); 157 + case 0x43: /* PIP */ 158 + return intel_pt_get_pip(buf, len, packet); 159 + case 0x03: /* CBR */ 160 + return intel_pt_get_cbr(buf, len, packet); 161 + case 0xf3: /* OVF */ 162 + return intel_pt_get_ovf(packet); 163 + case 0x82: /* PSB */ 164 + return intel_pt_get_psb(buf, len, packet); 165 + case 0x23: /* PSBEND */ 166 + return intel_pt_get_psbend(packet); 167 + default: 168 + return INTEL_PT_BAD_PACKET; 169 + } 170 + } 171 + 172 + static int intel_pt_get_short_tnt(unsigned int byte, 173 + struct intel_pt_pkt *packet) 174 + { 175 + int count; 176 + 177 + for (count = 6; count; count--) { 178 + if (byte & BIT(7)) 179 + break; 180 + byte <<= 1; 181 + } 182 + 183 + packet->type = INTEL_PT_TNT; 184 + packet->count = count; 185 + packet->payload = (uint64_t)byte << 57; 186 + 187 + return 1; 188 + } 189 + 190 + static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte, 191 + const unsigned char *buf, size_t len, 192 + struct intel_pt_pkt *packet) 193 + { 194 + switch (byte >> 5) { 195 + case 0: 196 + packet->count = 0; 197 + break; 198 + case 1: 199 + if (len < 3) 200 + return INTEL_PT_NEED_MORE_BYTES; 201 + packet->count = 2; 202 + packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1)); 203 + break; 204 + case 2: 205 + if (len < 5) 206 + return INTEL_PT_NEED_MORE_BYTES; 207 + packet->count = 4; 208 + packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1)); 209 + break; 210 + case 3: 211 + case 6: 212 + if (len < 7) 213 + return INTEL_PT_NEED_MORE_BYTES; 214 + packet->count = 6; 215 + memcpy_le64(&packet->payload, buf + 1, 6); 216 + break; 217 + default: 218 + return INTEL_PT_BAD_PACKET; 219 + } 220 + 221 + packet->type = type; 222 + 223 + return packet->count + 1; 224 + } 225 + 226 + static int intel_pt_get_mode(const unsigned char *buf, size_t len, 227 + struct intel_pt_pkt *packet) 228 + { 229 + if (len < 2) 230 + return INTEL_PT_NEED_MORE_BYTES; 231 + 232 + switch (buf[1] >> 5) { 233 + case 0: 234 + packet->type = INTEL_PT_MODE_EXEC; 235 + switch (buf[1] & 3) { 236 + case 0: 237 + packet->payload = 16; 238 + break; 239 + case 1: 240 + packet->payload = 64; 241 + break; 242 + case 2: 243 + packet->payload = 32; 244 + break; 245 + default: 246 + return INTEL_PT_BAD_PACKET; 247 + } 248 + break; 249 + case 1: 250 + packet->type = INTEL_PT_MODE_TSX; 251 + if ((buf[1] & 3) == 3) 252 + return INTEL_PT_BAD_PACKET; 253 + packet->payload = buf[1] & 3; 254 + break; 255 + default: 256 + return INTEL_PT_BAD_PACKET; 257 + } 258 + 259 + return 2; 260 + } 261 + 262 + static int intel_pt_get_tsc(const unsigned char *buf, size_t len, 263 + struct intel_pt_pkt *packet) 264 + { 265 + if (len < 8) 266 + return INTEL_PT_NEED_MORE_BYTES; 267 + packet->type = INTEL_PT_TSC; 268 + memcpy_le64(&packet->payload, buf + 1, 7); 269 + return 8; 270 + } 271 + 272 + static int intel_pt_do_get_packet(const unsigned char *buf, size_t len, 273 + struct intel_pt_pkt *packet) 274 + { 275 + unsigned int byte; 276 + 277 + memset(packet, 0, sizeof(struct intel_pt_pkt)); 278 + 279 + if (!len) 280 + return INTEL_PT_NEED_MORE_BYTES; 281 + 282 + byte = buf[0]; 283 + if (!(byte & BIT(0))) { 284 + if (byte == 0) 285 + return intel_pt_get_pad(packet); 286 + if (byte == 2) 287 + return intel_pt_get_ext(buf, len, packet); 288 + return intel_pt_get_short_tnt(byte, packet); 289 + } 290 + 291 + switch (byte & 0x1f) { 292 + case 0x0D: 293 + return intel_pt_get_ip(INTEL_PT_TIP, byte, buf, len, packet); 294 + case 0x11: 295 + return intel_pt_get_ip(INTEL_PT_TIP_PGE, byte, buf, len, 296 + packet); 297 + case 0x01: 298 + return intel_pt_get_ip(INTEL_PT_TIP_PGD, byte, buf, len, 299 + packet); 300 + case 0x1D: 301 + return intel_pt_get_ip(INTEL_PT_FUP, byte, buf, len, packet); 302 + case 0x19: 303 + switch (byte) { 304 + case 0x99: 305 + return intel_pt_get_mode(buf, len, packet); 306 + case 0x19: 307 + return intel_pt_get_tsc(buf, len, packet); 308 + default: 309 + return INTEL_PT_BAD_PACKET; 310 + } 311 + default: 312 + return INTEL_PT_BAD_PACKET; 313 + } 314 + } 315 + 316 + int intel_pt_get_packet(const unsigned char *buf, size_t len, 317 + struct intel_pt_pkt *packet) 318 + { 319 + int ret; 320 + 321 + ret = intel_pt_do_get_packet(buf, len, packet); 322 + if (ret > 0) { 323 + while (ret < 8 && len > (size_t)ret && !buf[ret]) 324 + ret += 1; 325 + } 326 + return ret; 327 + } 328 + 329 + int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, 330 + size_t buf_len) 331 + { 332 + int ret, i; 333 + unsigned long long payload = packet->payload; 334 + const char *name = intel_pt_pkt_name(packet->type); 335 + 336 + switch (packet->type) { 337 + case INTEL_PT_BAD: 338 + case INTEL_PT_PAD: 339 + case INTEL_PT_PSB: 340 + case INTEL_PT_PSBEND: 341 + case INTEL_PT_OVF: 342 + return snprintf(buf, buf_len, "%s", name); 343 + case INTEL_PT_TNT: { 344 + size_t blen = buf_len; 345 + 346 + ret = snprintf(buf, blen, "%s ", name); 347 + if (ret < 0) 348 + return ret; 349 + buf += ret; 350 + blen -= ret; 351 + for (i = 0; i < packet->count; i++) { 352 + if (payload & BIT63) 353 + ret = snprintf(buf, blen, "T"); 354 + else 355 + ret = snprintf(buf, blen, "N"); 356 + if (ret < 0) 357 + return ret; 358 + buf += ret; 359 + blen -= ret; 360 + payload <<= 1; 361 + } 362 + ret = snprintf(buf, blen, " (%d)", packet->count); 363 + if (ret < 0) 364 + return ret; 365 + blen -= ret; 366 + return buf_len - blen; 367 + } 368 + case INTEL_PT_TIP_PGD: 369 + case INTEL_PT_TIP_PGE: 370 + case INTEL_PT_TIP: 371 + case INTEL_PT_FUP: 372 + if (!(packet->count)) 373 + return snprintf(buf, buf_len, "%s no ip", name); 374 + case INTEL_PT_CBR: 375 + return snprintf(buf, buf_len, "%s 0x%llx", name, payload); 376 + case INTEL_PT_TSC: 377 + if (packet->count) 378 + return snprintf(buf, buf_len, 379 + "%s 0x%llx CTC 0x%x FC 0x%x", 380 + name, payload, packet->count & 0xffff, 381 + (packet->count >> 16) & 0x1ff); 382 + else 383 + return snprintf(buf, buf_len, "%s 0x%llx", 384 + name, payload); 385 + case INTEL_PT_MODE_EXEC: 386 + return snprintf(buf, buf_len, "%s %lld", name, payload); 387 + case INTEL_PT_MODE_TSX: 388 + return snprintf(buf, buf_len, "%s TXAbort:%u InTX:%u", 389 + name, (unsigned)(payload >> 1) & 1, 390 + (unsigned)payload & 1); 391 + case INTEL_PT_PIP: 392 + ret = snprintf(buf, buf_len, "%s 0x%llx", 393 + name, payload); 394 + return ret; 395 + default: 396 + break; 397 + } 398 + return snprintf(buf, buf_len, "%s 0x%llx (%d)", 399 + name, payload, packet->count); 400 + }
+64
tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
··· 1 + /* 2 + * intel_pt_pkt_decoder.h: Intel Processor Trace support 3 + * Copyright (c) 2013-2014, 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 + * 14 + */ 15 + 16 + #ifndef INCLUDE__INTEL_PT_PKT_DECODER_H__ 17 + #define INCLUDE__INTEL_PT_PKT_DECODER_H__ 18 + 19 + #include <stddef.h> 20 + #include <stdint.h> 21 + 22 + #define INTEL_PT_PKT_DESC_MAX 256 23 + 24 + #define INTEL_PT_NEED_MORE_BYTES -1 25 + #define INTEL_PT_BAD_PACKET -2 26 + 27 + #define INTEL_PT_PSB_STR "\002\202\002\202\002\202\002\202" \ 28 + "\002\202\002\202\002\202\002\202" 29 + #define INTEL_PT_PSB_LEN 16 30 + 31 + #define INTEL_PT_PKT_MAX_SZ 16 32 + 33 + enum intel_pt_pkt_type { 34 + INTEL_PT_BAD, 35 + INTEL_PT_PAD, 36 + INTEL_PT_TNT, 37 + INTEL_PT_TIP_PGD, 38 + INTEL_PT_TIP_PGE, 39 + INTEL_PT_TSC, 40 + INTEL_PT_MODE_EXEC, 41 + INTEL_PT_MODE_TSX, 42 + INTEL_PT_TIP, 43 + INTEL_PT_FUP, 44 + INTEL_PT_PSB, 45 + INTEL_PT_PSBEND, 46 + INTEL_PT_CBR, 47 + INTEL_PT_PIP, 48 + INTEL_PT_OVF, 49 + }; 50 + 51 + struct intel_pt_pkt { 52 + enum intel_pt_pkt_type type; 53 + int count; 54 + uint64_t payload; 55 + }; 56 + 57 + const char *intel_pt_pkt_name(enum intel_pt_pkt_type); 58 + 59 + int intel_pt_get_packet(const unsigned char *buf, size_t len, 60 + struct intel_pt_pkt *packet); 61 + 62 + int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, size_t len); 63 + 64 + #endif