1a4e92590SAdrian Hunter /* 2a4e92590SAdrian Hunter * intel_pt_pkt_decoder.c: Intel Processor Trace support 3a4e92590SAdrian Hunter * Copyright (c) 2013-2014, Intel Corporation. 4a4e92590SAdrian Hunter * 5a4e92590SAdrian Hunter * This program is free software; you can redistribute it and/or modify it 6a4e92590SAdrian Hunter * under the terms and conditions of the GNU General Public License, 7a4e92590SAdrian Hunter * version 2, as published by the Free Software Foundation. 8a4e92590SAdrian Hunter * 9a4e92590SAdrian Hunter * This program is distributed in the hope it will be useful, but WITHOUT 10a4e92590SAdrian Hunter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11a4e92590SAdrian Hunter * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12a4e92590SAdrian Hunter * more details. 13a4e92590SAdrian Hunter * 14a4e92590SAdrian Hunter */ 15a4e92590SAdrian Hunter 16a4e92590SAdrian Hunter #include <stdio.h> 17a4e92590SAdrian Hunter #include <string.h> 18a4e92590SAdrian Hunter #include <endian.h> 19a4e92590SAdrian Hunter #include <byteswap.h> 20*7ea6856dSArnaldo Carvalho de Melo #include <linux/compiler.h> 21a4e92590SAdrian Hunter 22a4e92590SAdrian Hunter #include "intel-pt-pkt-decoder.h" 23a4e92590SAdrian Hunter 24a4e92590SAdrian Hunter #define BIT(n) (1 << (n)) 25a4e92590SAdrian Hunter 26a4e92590SAdrian Hunter #define BIT63 ((uint64_t)1 << 63) 27a4e92590SAdrian Hunter 283d498078SAdrian Hunter #define NR_FLAG BIT63 293d498078SAdrian Hunter 30a4e92590SAdrian Hunter #if __BYTE_ORDER == __BIG_ENDIAN 31a4e92590SAdrian Hunter #define le16_to_cpu bswap_16 32a4e92590SAdrian Hunter #define le32_to_cpu bswap_32 33a4e92590SAdrian Hunter #define le64_to_cpu bswap_64 34a4e92590SAdrian Hunter #define memcpy_le64(d, s, n) do { \ 35a4e92590SAdrian Hunter memcpy((d), (s), (n)); \ 36a4e92590SAdrian Hunter *(d) = le64_to_cpu(*(d)); \ 37a4e92590SAdrian Hunter } while (0) 38a4e92590SAdrian Hunter #else 39a4e92590SAdrian Hunter #define le16_to_cpu 40a4e92590SAdrian Hunter #define le32_to_cpu 41a4e92590SAdrian Hunter #define le64_to_cpu 42a4e92590SAdrian Hunter #define memcpy_le64 memcpy 43a4e92590SAdrian Hunter #endif 44a4e92590SAdrian Hunter 45a4e92590SAdrian Hunter static const char * const packet_name[] = { 46a4e92590SAdrian Hunter [INTEL_PT_BAD] = "Bad Packet!", 47a4e92590SAdrian Hunter [INTEL_PT_PAD] = "PAD", 48a4e92590SAdrian Hunter [INTEL_PT_TNT] = "TNT", 49a4e92590SAdrian Hunter [INTEL_PT_TIP_PGD] = "TIP.PGD", 50a4e92590SAdrian Hunter [INTEL_PT_TIP_PGE] = "TIP.PGE", 51a4e92590SAdrian Hunter [INTEL_PT_TSC] = "TSC", 523d498078SAdrian Hunter [INTEL_PT_TMA] = "TMA", 53a4e92590SAdrian Hunter [INTEL_PT_MODE_EXEC] = "MODE.Exec", 54a4e92590SAdrian Hunter [INTEL_PT_MODE_TSX] = "MODE.TSX", 553d498078SAdrian Hunter [INTEL_PT_MTC] = "MTC", 56a4e92590SAdrian Hunter [INTEL_PT_TIP] = "TIP", 57a4e92590SAdrian Hunter [INTEL_PT_FUP] = "FUP", 583d498078SAdrian Hunter [INTEL_PT_CYC] = "CYC", 593d498078SAdrian Hunter [INTEL_PT_VMCS] = "VMCS", 60a4e92590SAdrian Hunter [INTEL_PT_PSB] = "PSB", 61a4e92590SAdrian Hunter [INTEL_PT_PSBEND] = "PSBEND", 62a4e92590SAdrian Hunter [INTEL_PT_CBR] = "CBR", 633d498078SAdrian Hunter [INTEL_PT_TRACESTOP] = "TraceSTOP", 64a4e92590SAdrian Hunter [INTEL_PT_PIP] = "PIP", 65a4e92590SAdrian Hunter [INTEL_PT_OVF] = "OVF", 663d498078SAdrian Hunter [INTEL_PT_MNT] = "MNT", 67a4e92590SAdrian Hunter }; 68a4e92590SAdrian Hunter 69a4e92590SAdrian Hunter const char *intel_pt_pkt_name(enum intel_pt_pkt_type type) 70a4e92590SAdrian Hunter { 71a4e92590SAdrian Hunter return packet_name[type]; 72a4e92590SAdrian Hunter } 73a4e92590SAdrian Hunter 74a4e92590SAdrian Hunter static int intel_pt_get_long_tnt(const unsigned char *buf, size_t len, 75a4e92590SAdrian Hunter struct intel_pt_pkt *packet) 76a4e92590SAdrian Hunter { 77a4e92590SAdrian Hunter uint64_t payload; 78a4e92590SAdrian Hunter int count; 79a4e92590SAdrian Hunter 80a4e92590SAdrian Hunter if (len < 8) 81a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 82a4e92590SAdrian Hunter 83a4e92590SAdrian Hunter payload = le64_to_cpu(*(uint64_t *)buf); 84a4e92590SAdrian Hunter 85a4e92590SAdrian Hunter for (count = 47; count; count--) { 86a4e92590SAdrian Hunter if (payload & BIT63) 87a4e92590SAdrian Hunter break; 88a4e92590SAdrian Hunter payload <<= 1; 89a4e92590SAdrian Hunter } 90a4e92590SAdrian Hunter 91a4e92590SAdrian Hunter packet->type = INTEL_PT_TNT; 92a4e92590SAdrian Hunter packet->count = count; 93a4e92590SAdrian Hunter packet->payload = payload << 1; 94a4e92590SAdrian Hunter return 8; 95a4e92590SAdrian Hunter } 96a4e92590SAdrian Hunter 97a4e92590SAdrian Hunter static int intel_pt_get_pip(const unsigned char *buf, size_t len, 98a4e92590SAdrian Hunter struct intel_pt_pkt *packet) 99a4e92590SAdrian Hunter { 100a4e92590SAdrian Hunter uint64_t payload = 0; 101a4e92590SAdrian Hunter 102a4e92590SAdrian Hunter if (len < 8) 103a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 104a4e92590SAdrian Hunter 105a4e92590SAdrian Hunter packet->type = INTEL_PT_PIP; 106a4e92590SAdrian Hunter memcpy_le64(&payload, buf + 2, 6); 107a4e92590SAdrian Hunter packet->payload = payload >> 1; 1083d498078SAdrian Hunter if (payload & 1) 1093d498078SAdrian Hunter packet->payload |= NR_FLAG; 110a4e92590SAdrian Hunter 111a4e92590SAdrian Hunter return 8; 112a4e92590SAdrian Hunter } 113a4e92590SAdrian Hunter 1143d498078SAdrian Hunter static int intel_pt_get_tracestop(struct intel_pt_pkt *packet) 1153d498078SAdrian Hunter { 1163d498078SAdrian Hunter packet->type = INTEL_PT_TRACESTOP; 1173d498078SAdrian Hunter return 2; 1183d498078SAdrian Hunter } 1193d498078SAdrian Hunter 120a4e92590SAdrian Hunter static int intel_pt_get_cbr(const unsigned char *buf, size_t len, 121a4e92590SAdrian Hunter struct intel_pt_pkt *packet) 122a4e92590SAdrian Hunter { 123a4e92590SAdrian Hunter if (len < 4) 124a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 125a4e92590SAdrian Hunter packet->type = INTEL_PT_CBR; 126a4e92590SAdrian Hunter packet->payload = buf[2]; 127a4e92590SAdrian Hunter return 4; 128a4e92590SAdrian Hunter } 129a4e92590SAdrian Hunter 1303d498078SAdrian Hunter static int intel_pt_get_vmcs(const unsigned char *buf, size_t len, 1313d498078SAdrian Hunter struct intel_pt_pkt *packet) 1323d498078SAdrian Hunter { 1333d498078SAdrian Hunter unsigned int count = (52 - 5) >> 3; 1343d498078SAdrian Hunter 1353d498078SAdrian Hunter if (count < 1 || count > 7) 1363d498078SAdrian Hunter return INTEL_PT_BAD_PACKET; 1373d498078SAdrian Hunter 1383d498078SAdrian Hunter if (len < count + 2) 1393d498078SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 1403d498078SAdrian Hunter 1413d498078SAdrian Hunter packet->type = INTEL_PT_VMCS; 1423d498078SAdrian Hunter packet->count = count; 1433d498078SAdrian Hunter memcpy_le64(&packet->payload, buf + 2, count); 1443d498078SAdrian Hunter 1453d498078SAdrian Hunter return count + 2; 1463d498078SAdrian Hunter } 1473d498078SAdrian Hunter 148a4e92590SAdrian Hunter static int intel_pt_get_ovf(struct intel_pt_pkt *packet) 149a4e92590SAdrian Hunter { 150a4e92590SAdrian Hunter packet->type = INTEL_PT_OVF; 151a4e92590SAdrian Hunter return 2; 152a4e92590SAdrian Hunter } 153a4e92590SAdrian Hunter 154a4e92590SAdrian Hunter static int intel_pt_get_psb(const unsigned char *buf, size_t len, 155a4e92590SAdrian Hunter struct intel_pt_pkt *packet) 156a4e92590SAdrian Hunter { 157a4e92590SAdrian Hunter int i; 158a4e92590SAdrian Hunter 159a4e92590SAdrian Hunter if (len < 16) 160a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 161a4e92590SAdrian Hunter 162a4e92590SAdrian Hunter for (i = 2; i < 16; i += 2) { 163a4e92590SAdrian Hunter if (buf[i] != 2 || buf[i + 1] != 0x82) 164a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET; 165a4e92590SAdrian Hunter } 166a4e92590SAdrian Hunter 167a4e92590SAdrian Hunter packet->type = INTEL_PT_PSB; 168a4e92590SAdrian Hunter return 16; 169a4e92590SAdrian Hunter } 170a4e92590SAdrian Hunter 171a4e92590SAdrian Hunter static int intel_pt_get_psbend(struct intel_pt_pkt *packet) 172a4e92590SAdrian Hunter { 173a4e92590SAdrian Hunter packet->type = INTEL_PT_PSBEND; 174a4e92590SAdrian Hunter return 2; 175a4e92590SAdrian Hunter } 176a4e92590SAdrian Hunter 1773d498078SAdrian Hunter static int intel_pt_get_tma(const unsigned char *buf, size_t len, 1783d498078SAdrian Hunter struct intel_pt_pkt *packet) 1793d498078SAdrian Hunter { 1803d498078SAdrian Hunter if (len < 7) 1813d498078SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 1823d498078SAdrian Hunter 1833d498078SAdrian Hunter packet->type = INTEL_PT_TMA; 1843d498078SAdrian Hunter packet->payload = buf[2] | (buf[3] << 8); 1853d498078SAdrian Hunter packet->count = buf[5] | ((buf[6] & BIT(0)) << 8); 1863d498078SAdrian Hunter return 7; 1873d498078SAdrian Hunter } 1883d498078SAdrian Hunter 189a4e92590SAdrian Hunter static int intel_pt_get_pad(struct intel_pt_pkt *packet) 190a4e92590SAdrian Hunter { 191a4e92590SAdrian Hunter packet->type = INTEL_PT_PAD; 192a4e92590SAdrian Hunter return 1; 193a4e92590SAdrian Hunter } 194a4e92590SAdrian Hunter 1953d498078SAdrian Hunter static int intel_pt_get_mnt(const unsigned char *buf, size_t len, 1963d498078SAdrian Hunter struct intel_pt_pkt *packet) 1973d498078SAdrian Hunter { 1983d498078SAdrian Hunter if (len < 11) 1993d498078SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 2003d498078SAdrian Hunter packet->type = INTEL_PT_MNT; 2013d498078SAdrian Hunter memcpy_le64(&packet->payload, buf + 3, 8); 2023d498078SAdrian Hunter return 11 2033d498078SAdrian Hunter ; 2043d498078SAdrian Hunter } 2053d498078SAdrian Hunter 2063d498078SAdrian Hunter static int intel_pt_get_3byte(const unsigned char *buf, size_t len, 2073d498078SAdrian Hunter struct intel_pt_pkt *packet) 2083d498078SAdrian Hunter { 2093d498078SAdrian Hunter if (len < 3) 2103d498078SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 2113d498078SAdrian Hunter 2123d498078SAdrian Hunter switch (buf[2]) { 2133d498078SAdrian Hunter case 0x88: /* MNT */ 2143d498078SAdrian Hunter return intel_pt_get_mnt(buf, len, packet); 2153d498078SAdrian Hunter default: 2163d498078SAdrian Hunter return INTEL_PT_BAD_PACKET; 2173d498078SAdrian Hunter } 2183d498078SAdrian Hunter } 2193d498078SAdrian Hunter 220a4e92590SAdrian Hunter static int intel_pt_get_ext(const unsigned char *buf, size_t len, 221a4e92590SAdrian Hunter struct intel_pt_pkt *packet) 222a4e92590SAdrian Hunter { 223a4e92590SAdrian Hunter if (len < 2) 224a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 225a4e92590SAdrian Hunter 226a4e92590SAdrian Hunter switch (buf[1]) { 227a4e92590SAdrian Hunter case 0xa3: /* Long TNT */ 228a4e92590SAdrian Hunter return intel_pt_get_long_tnt(buf, len, packet); 229a4e92590SAdrian Hunter case 0x43: /* PIP */ 230a4e92590SAdrian Hunter return intel_pt_get_pip(buf, len, packet); 2313d498078SAdrian Hunter case 0x83: /* TraceStop */ 2323d498078SAdrian Hunter return intel_pt_get_tracestop(packet); 233a4e92590SAdrian Hunter case 0x03: /* CBR */ 234a4e92590SAdrian Hunter return intel_pt_get_cbr(buf, len, packet); 2353d498078SAdrian Hunter case 0xc8: /* VMCS */ 2363d498078SAdrian Hunter return intel_pt_get_vmcs(buf, len, packet); 237a4e92590SAdrian Hunter case 0xf3: /* OVF */ 238a4e92590SAdrian Hunter return intel_pt_get_ovf(packet); 239a4e92590SAdrian Hunter case 0x82: /* PSB */ 240a4e92590SAdrian Hunter return intel_pt_get_psb(buf, len, packet); 241a4e92590SAdrian Hunter case 0x23: /* PSBEND */ 242a4e92590SAdrian Hunter return intel_pt_get_psbend(packet); 2433d498078SAdrian Hunter case 0x73: /* TMA */ 2443d498078SAdrian Hunter return intel_pt_get_tma(buf, len, packet); 2453d498078SAdrian Hunter case 0xC3: /* 3-byte header */ 2463d498078SAdrian Hunter return intel_pt_get_3byte(buf, len, packet); 247a4e92590SAdrian Hunter default: 248a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET; 249a4e92590SAdrian Hunter } 250a4e92590SAdrian Hunter } 251a4e92590SAdrian Hunter 252a4e92590SAdrian Hunter static int intel_pt_get_short_tnt(unsigned int byte, 253a4e92590SAdrian Hunter struct intel_pt_pkt *packet) 254a4e92590SAdrian Hunter { 255a4e92590SAdrian Hunter int count; 256a4e92590SAdrian Hunter 257a4e92590SAdrian Hunter for (count = 6; count; count--) { 258a4e92590SAdrian Hunter if (byte & BIT(7)) 259a4e92590SAdrian Hunter break; 260a4e92590SAdrian Hunter byte <<= 1; 261a4e92590SAdrian Hunter } 262a4e92590SAdrian Hunter 263a4e92590SAdrian Hunter packet->type = INTEL_PT_TNT; 264a4e92590SAdrian Hunter packet->count = count; 265a4e92590SAdrian Hunter packet->payload = (uint64_t)byte << 57; 266a4e92590SAdrian Hunter 267a4e92590SAdrian Hunter return 1; 268a4e92590SAdrian Hunter } 269a4e92590SAdrian Hunter 2703d498078SAdrian Hunter static int intel_pt_get_cyc(unsigned int byte, const unsigned char *buf, 2713d498078SAdrian Hunter size_t len, struct intel_pt_pkt *packet) 2723d498078SAdrian Hunter { 2733d498078SAdrian Hunter unsigned int offs = 1, shift; 2743d498078SAdrian Hunter uint64_t payload = byte >> 3; 2753d498078SAdrian Hunter 2763d498078SAdrian Hunter byte >>= 2; 2773d498078SAdrian Hunter len -= 1; 2783d498078SAdrian Hunter for (shift = 5; byte & 1; shift += 7) { 2793d498078SAdrian Hunter if (offs > 9) 2803d498078SAdrian Hunter return INTEL_PT_BAD_PACKET; 2813d498078SAdrian Hunter if (len < offs) 2823d498078SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 2833d498078SAdrian Hunter byte = buf[offs++]; 2843d498078SAdrian Hunter payload |= (byte >> 1) << shift; 2853d498078SAdrian Hunter } 2863d498078SAdrian Hunter 2873d498078SAdrian Hunter packet->type = INTEL_PT_CYC; 2883d498078SAdrian Hunter packet->payload = payload; 2893d498078SAdrian Hunter return offs; 2903d498078SAdrian Hunter } 2913d498078SAdrian Hunter 292a4e92590SAdrian Hunter static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte, 293a4e92590SAdrian Hunter const unsigned char *buf, size_t len, 294a4e92590SAdrian Hunter struct intel_pt_pkt *packet) 295a4e92590SAdrian Hunter { 296e1717e04SAdrian Hunter int ip_len; 297e1717e04SAdrian Hunter 298e1717e04SAdrian Hunter packet->count = byte >> 5; 299e1717e04SAdrian Hunter 300e1717e04SAdrian Hunter switch (packet->count) { 301a4e92590SAdrian Hunter case 0: 302e1717e04SAdrian Hunter ip_len = 0; 303a4e92590SAdrian Hunter break; 304a4e92590SAdrian Hunter case 1: 305a4e92590SAdrian Hunter if (len < 3) 306a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 307e1717e04SAdrian Hunter ip_len = 2; 308a4e92590SAdrian Hunter packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1)); 309a4e92590SAdrian Hunter break; 310a4e92590SAdrian Hunter case 2: 311a4e92590SAdrian Hunter if (len < 5) 312a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 313e1717e04SAdrian Hunter ip_len = 4; 314a4e92590SAdrian Hunter packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1)); 315a4e92590SAdrian Hunter break; 316a4e92590SAdrian Hunter case 3: 317e1717e04SAdrian Hunter case 4: 318a4e92590SAdrian Hunter if (len < 7) 319a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 320e1717e04SAdrian Hunter ip_len = 6; 321a4e92590SAdrian Hunter memcpy_le64(&packet->payload, buf + 1, 6); 322a4e92590SAdrian Hunter break; 323e1717e04SAdrian Hunter case 6: 324e1717e04SAdrian Hunter if (len < 9) 325e1717e04SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 326e1717e04SAdrian Hunter ip_len = 8; 327e1717e04SAdrian Hunter packet->payload = le64_to_cpu(*(uint64_t *)(buf + 1)); 328e1717e04SAdrian Hunter break; 329a4e92590SAdrian Hunter default: 330a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET; 331a4e92590SAdrian Hunter } 332a4e92590SAdrian Hunter 333a4e92590SAdrian Hunter packet->type = type; 334a4e92590SAdrian Hunter 335e1717e04SAdrian Hunter return ip_len + 1; 336a4e92590SAdrian Hunter } 337a4e92590SAdrian Hunter 338a4e92590SAdrian Hunter static int intel_pt_get_mode(const unsigned char *buf, size_t len, 339a4e92590SAdrian Hunter struct intel_pt_pkt *packet) 340a4e92590SAdrian Hunter { 341a4e92590SAdrian Hunter if (len < 2) 342a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 343a4e92590SAdrian Hunter 344a4e92590SAdrian Hunter switch (buf[1] >> 5) { 345a4e92590SAdrian Hunter case 0: 346a4e92590SAdrian Hunter packet->type = INTEL_PT_MODE_EXEC; 347a4e92590SAdrian Hunter switch (buf[1] & 3) { 348a4e92590SAdrian Hunter case 0: 349a4e92590SAdrian Hunter packet->payload = 16; 350a4e92590SAdrian Hunter break; 351a4e92590SAdrian Hunter case 1: 352a4e92590SAdrian Hunter packet->payload = 64; 353a4e92590SAdrian Hunter break; 354a4e92590SAdrian Hunter case 2: 355a4e92590SAdrian Hunter packet->payload = 32; 356a4e92590SAdrian Hunter break; 357a4e92590SAdrian Hunter default: 358a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET; 359a4e92590SAdrian Hunter } 360a4e92590SAdrian Hunter break; 361a4e92590SAdrian Hunter case 1: 362a4e92590SAdrian Hunter packet->type = INTEL_PT_MODE_TSX; 363a4e92590SAdrian Hunter if ((buf[1] & 3) == 3) 364a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET; 365a4e92590SAdrian Hunter packet->payload = buf[1] & 3; 366a4e92590SAdrian Hunter break; 367a4e92590SAdrian Hunter default: 368a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET; 369a4e92590SAdrian Hunter } 370a4e92590SAdrian Hunter 371a4e92590SAdrian Hunter return 2; 372a4e92590SAdrian Hunter } 373a4e92590SAdrian Hunter 374a4e92590SAdrian Hunter static int intel_pt_get_tsc(const unsigned char *buf, size_t len, 375a4e92590SAdrian Hunter struct intel_pt_pkt *packet) 376a4e92590SAdrian Hunter { 377a4e92590SAdrian Hunter if (len < 8) 378a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 379a4e92590SAdrian Hunter packet->type = INTEL_PT_TSC; 380a4e92590SAdrian Hunter memcpy_le64(&packet->payload, buf + 1, 7); 381a4e92590SAdrian Hunter return 8; 382a4e92590SAdrian Hunter } 383a4e92590SAdrian Hunter 3843d498078SAdrian Hunter static int intel_pt_get_mtc(const unsigned char *buf, size_t len, 3853d498078SAdrian Hunter struct intel_pt_pkt *packet) 3863d498078SAdrian Hunter { 3873d498078SAdrian Hunter if (len < 2) 3883d498078SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 3893d498078SAdrian Hunter packet->type = INTEL_PT_MTC; 3903d498078SAdrian Hunter packet->payload = buf[1]; 3913d498078SAdrian Hunter return 2; 3923d498078SAdrian Hunter } 3933d498078SAdrian Hunter 394a4e92590SAdrian Hunter static int intel_pt_do_get_packet(const unsigned char *buf, size_t len, 395a4e92590SAdrian Hunter struct intel_pt_pkt *packet) 396a4e92590SAdrian Hunter { 397a4e92590SAdrian Hunter unsigned int byte; 398a4e92590SAdrian Hunter 399a4e92590SAdrian Hunter memset(packet, 0, sizeof(struct intel_pt_pkt)); 400a4e92590SAdrian Hunter 401a4e92590SAdrian Hunter if (!len) 402a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES; 403a4e92590SAdrian Hunter 404a4e92590SAdrian Hunter byte = buf[0]; 405a4e92590SAdrian Hunter if (!(byte & BIT(0))) { 406a4e92590SAdrian Hunter if (byte == 0) 407a4e92590SAdrian Hunter return intel_pt_get_pad(packet); 408a4e92590SAdrian Hunter if (byte == 2) 409a4e92590SAdrian Hunter return intel_pt_get_ext(buf, len, packet); 410a4e92590SAdrian Hunter return intel_pt_get_short_tnt(byte, packet); 411a4e92590SAdrian Hunter } 412a4e92590SAdrian Hunter 4133d498078SAdrian Hunter if ((byte & 2)) 4143d498078SAdrian Hunter return intel_pt_get_cyc(byte, buf, len, packet); 4153d498078SAdrian Hunter 416a4e92590SAdrian Hunter switch (byte & 0x1f) { 417a4e92590SAdrian Hunter case 0x0D: 418a4e92590SAdrian Hunter return intel_pt_get_ip(INTEL_PT_TIP, byte, buf, len, packet); 419a4e92590SAdrian Hunter case 0x11: 420a4e92590SAdrian Hunter return intel_pt_get_ip(INTEL_PT_TIP_PGE, byte, buf, len, 421a4e92590SAdrian Hunter packet); 422a4e92590SAdrian Hunter case 0x01: 423a4e92590SAdrian Hunter return intel_pt_get_ip(INTEL_PT_TIP_PGD, byte, buf, len, 424a4e92590SAdrian Hunter packet); 425a4e92590SAdrian Hunter case 0x1D: 426a4e92590SAdrian Hunter return intel_pt_get_ip(INTEL_PT_FUP, byte, buf, len, packet); 427a4e92590SAdrian Hunter case 0x19: 428a4e92590SAdrian Hunter switch (byte) { 429a4e92590SAdrian Hunter case 0x99: 430a4e92590SAdrian Hunter return intel_pt_get_mode(buf, len, packet); 431a4e92590SAdrian Hunter case 0x19: 432a4e92590SAdrian Hunter return intel_pt_get_tsc(buf, len, packet); 4333d498078SAdrian Hunter case 0x59: 4343d498078SAdrian Hunter return intel_pt_get_mtc(buf, len, packet); 435a4e92590SAdrian Hunter default: 436a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET; 437a4e92590SAdrian Hunter } 438a4e92590SAdrian Hunter default: 439a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET; 440a4e92590SAdrian Hunter } 441a4e92590SAdrian Hunter } 442a4e92590SAdrian Hunter 443a4e92590SAdrian Hunter int intel_pt_get_packet(const unsigned char *buf, size_t len, 444a4e92590SAdrian Hunter struct intel_pt_pkt *packet) 445a4e92590SAdrian Hunter { 446a4e92590SAdrian Hunter int ret; 447a4e92590SAdrian Hunter 448a4e92590SAdrian Hunter ret = intel_pt_do_get_packet(buf, len, packet); 449a4e92590SAdrian Hunter if (ret > 0) { 450a4e92590SAdrian Hunter while (ret < 8 && len > (size_t)ret && !buf[ret]) 451a4e92590SAdrian Hunter ret += 1; 452a4e92590SAdrian Hunter } 453a4e92590SAdrian Hunter return ret; 454a4e92590SAdrian Hunter } 455a4e92590SAdrian Hunter 456a4e92590SAdrian Hunter int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, 457a4e92590SAdrian Hunter size_t buf_len) 458a4e92590SAdrian Hunter { 4593d498078SAdrian Hunter int ret, i, nr; 460a4e92590SAdrian Hunter unsigned long long payload = packet->payload; 461a4e92590SAdrian Hunter const char *name = intel_pt_pkt_name(packet->type); 462a4e92590SAdrian Hunter 463a4e92590SAdrian Hunter switch (packet->type) { 464a4e92590SAdrian Hunter case INTEL_PT_BAD: 465a4e92590SAdrian Hunter case INTEL_PT_PAD: 466a4e92590SAdrian Hunter case INTEL_PT_PSB: 467a4e92590SAdrian Hunter case INTEL_PT_PSBEND: 4683d498078SAdrian Hunter case INTEL_PT_TRACESTOP: 469a4e92590SAdrian Hunter case INTEL_PT_OVF: 470a4e92590SAdrian Hunter return snprintf(buf, buf_len, "%s", name); 471a4e92590SAdrian Hunter case INTEL_PT_TNT: { 472a4e92590SAdrian Hunter size_t blen = buf_len; 473a4e92590SAdrian Hunter 474a4e92590SAdrian Hunter ret = snprintf(buf, blen, "%s ", name); 475a4e92590SAdrian Hunter if (ret < 0) 476a4e92590SAdrian Hunter return ret; 477a4e92590SAdrian Hunter buf += ret; 478a4e92590SAdrian Hunter blen -= ret; 479a4e92590SAdrian Hunter for (i = 0; i < packet->count; i++) { 480a4e92590SAdrian Hunter if (payload & BIT63) 481a4e92590SAdrian Hunter ret = snprintf(buf, blen, "T"); 482a4e92590SAdrian Hunter else 483a4e92590SAdrian Hunter ret = snprintf(buf, blen, "N"); 484a4e92590SAdrian Hunter if (ret < 0) 485a4e92590SAdrian Hunter return ret; 486a4e92590SAdrian Hunter buf += ret; 487a4e92590SAdrian Hunter blen -= ret; 488a4e92590SAdrian Hunter payload <<= 1; 489a4e92590SAdrian Hunter } 490a4e92590SAdrian Hunter ret = snprintf(buf, blen, " (%d)", packet->count); 491a4e92590SAdrian Hunter if (ret < 0) 492a4e92590SAdrian Hunter return ret; 493a4e92590SAdrian Hunter blen -= ret; 494a4e92590SAdrian Hunter return buf_len - blen; 495a4e92590SAdrian Hunter } 496a4e92590SAdrian Hunter case INTEL_PT_TIP_PGD: 497a4e92590SAdrian Hunter case INTEL_PT_TIP_PGE: 498a4e92590SAdrian Hunter case INTEL_PT_TIP: 499a4e92590SAdrian Hunter case INTEL_PT_FUP: 500a4e92590SAdrian Hunter if (!(packet->count)) 501a4e92590SAdrian Hunter return snprintf(buf, buf_len, "%s no ip", name); 502*7ea6856dSArnaldo Carvalho de Melo __fallthrough; 5033d498078SAdrian Hunter case INTEL_PT_CYC: 5043d498078SAdrian Hunter case INTEL_PT_VMCS: 5053d498078SAdrian Hunter case INTEL_PT_MTC: 5063d498078SAdrian Hunter case INTEL_PT_MNT: 507a4e92590SAdrian Hunter case INTEL_PT_CBR: 508a4e92590SAdrian Hunter case INTEL_PT_TSC: 5093d498078SAdrian Hunter return snprintf(buf, buf_len, "%s 0x%llx", name, payload); 5103d498078SAdrian Hunter case INTEL_PT_TMA: 5113d498078SAdrian Hunter return snprintf(buf, buf_len, "%s CTC 0x%x FC 0x%x", name, 5123d498078SAdrian Hunter (unsigned)payload, packet->count); 513a4e92590SAdrian Hunter case INTEL_PT_MODE_EXEC: 514a4e92590SAdrian Hunter return snprintf(buf, buf_len, "%s %lld", name, payload); 515a4e92590SAdrian Hunter case INTEL_PT_MODE_TSX: 516a4e92590SAdrian Hunter return snprintf(buf, buf_len, "%s TXAbort:%u InTX:%u", 517a4e92590SAdrian Hunter name, (unsigned)(payload >> 1) & 1, 518a4e92590SAdrian Hunter (unsigned)payload & 1); 519a4e92590SAdrian Hunter case INTEL_PT_PIP: 5203d498078SAdrian Hunter nr = packet->payload & NR_FLAG ? 1 : 0; 5213d498078SAdrian Hunter payload &= ~NR_FLAG; 5223d498078SAdrian Hunter ret = snprintf(buf, buf_len, "%s 0x%llx (NR=%d)", 5233d498078SAdrian Hunter name, payload, nr); 524a4e92590SAdrian Hunter return ret; 525a4e92590SAdrian Hunter default: 526a4e92590SAdrian Hunter break; 527a4e92590SAdrian Hunter } 528a4e92590SAdrian Hunter return snprintf(buf, buf_len, "%s 0x%llx (%d)", 529a4e92590SAdrian Hunter name, payload, packet->count); 530a4e92590SAdrian Hunter } 531