18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * intel_pt_pkt_decoder.c: Intel Processor Trace support 48c2ecf20Sopenharmony_ci * Copyright (c) 2013-2014, Intel Corporation. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <stdio.h> 88c2ecf20Sopenharmony_ci#include <string.h> 98c2ecf20Sopenharmony_ci#include <endian.h> 108c2ecf20Sopenharmony_ci#include <byteswap.h> 118c2ecf20Sopenharmony_ci#include <linux/compiler.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "intel-pt-pkt-decoder.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define BIT(n) (1 << (n)) 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#define BIT63 ((uint64_t)1 << 63) 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define NR_FLAG BIT63 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#if __BYTE_ORDER == __BIG_ENDIAN 228c2ecf20Sopenharmony_ci#define le16_to_cpu bswap_16 238c2ecf20Sopenharmony_ci#define le32_to_cpu bswap_32 248c2ecf20Sopenharmony_ci#define le64_to_cpu bswap_64 258c2ecf20Sopenharmony_ci#define memcpy_le64(d, s, n) do { \ 268c2ecf20Sopenharmony_ci memcpy((d), (s), (n)); \ 278c2ecf20Sopenharmony_ci *(d) = le64_to_cpu(*(d)); \ 288c2ecf20Sopenharmony_ci} while (0) 298c2ecf20Sopenharmony_ci#else 308c2ecf20Sopenharmony_ci#define le16_to_cpu 318c2ecf20Sopenharmony_ci#define le32_to_cpu 328c2ecf20Sopenharmony_ci#define le64_to_cpu 338c2ecf20Sopenharmony_ci#define memcpy_le64 memcpy 348c2ecf20Sopenharmony_ci#endif 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic const char * const packet_name[] = { 378c2ecf20Sopenharmony_ci [INTEL_PT_BAD] = "Bad Packet!", 388c2ecf20Sopenharmony_ci [INTEL_PT_PAD] = "PAD", 398c2ecf20Sopenharmony_ci [INTEL_PT_TNT] = "TNT", 408c2ecf20Sopenharmony_ci [INTEL_PT_TIP_PGD] = "TIP.PGD", 418c2ecf20Sopenharmony_ci [INTEL_PT_TIP_PGE] = "TIP.PGE", 428c2ecf20Sopenharmony_ci [INTEL_PT_TSC] = "TSC", 438c2ecf20Sopenharmony_ci [INTEL_PT_TMA] = "TMA", 448c2ecf20Sopenharmony_ci [INTEL_PT_MODE_EXEC] = "MODE.Exec", 458c2ecf20Sopenharmony_ci [INTEL_PT_MODE_TSX] = "MODE.TSX", 468c2ecf20Sopenharmony_ci [INTEL_PT_MTC] = "MTC", 478c2ecf20Sopenharmony_ci [INTEL_PT_TIP] = "TIP", 488c2ecf20Sopenharmony_ci [INTEL_PT_FUP] = "FUP", 498c2ecf20Sopenharmony_ci [INTEL_PT_CYC] = "CYC", 508c2ecf20Sopenharmony_ci [INTEL_PT_VMCS] = "VMCS", 518c2ecf20Sopenharmony_ci [INTEL_PT_PSB] = "PSB", 528c2ecf20Sopenharmony_ci [INTEL_PT_PSBEND] = "PSBEND", 538c2ecf20Sopenharmony_ci [INTEL_PT_CBR] = "CBR", 548c2ecf20Sopenharmony_ci [INTEL_PT_TRACESTOP] = "TraceSTOP", 558c2ecf20Sopenharmony_ci [INTEL_PT_PIP] = "PIP", 568c2ecf20Sopenharmony_ci [INTEL_PT_OVF] = "OVF", 578c2ecf20Sopenharmony_ci [INTEL_PT_MNT] = "MNT", 588c2ecf20Sopenharmony_ci [INTEL_PT_PTWRITE] = "PTWRITE", 598c2ecf20Sopenharmony_ci [INTEL_PT_PTWRITE_IP] = "PTWRITE", 608c2ecf20Sopenharmony_ci [INTEL_PT_EXSTOP] = "EXSTOP", 618c2ecf20Sopenharmony_ci [INTEL_PT_EXSTOP_IP] = "EXSTOP", 628c2ecf20Sopenharmony_ci [INTEL_PT_MWAIT] = "MWAIT", 638c2ecf20Sopenharmony_ci [INTEL_PT_PWRE] = "PWRE", 648c2ecf20Sopenharmony_ci [INTEL_PT_PWRX] = "PWRX", 658c2ecf20Sopenharmony_ci [INTEL_PT_BBP] = "BBP", 668c2ecf20Sopenharmony_ci [INTEL_PT_BIP] = "BIP", 678c2ecf20Sopenharmony_ci [INTEL_PT_BEP] = "BEP", 688c2ecf20Sopenharmony_ci [INTEL_PT_BEP_IP] = "BEP", 698c2ecf20Sopenharmony_ci}; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ciconst char *intel_pt_pkt_name(enum intel_pt_pkt_type type) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci return packet_name[type]; 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic int intel_pt_get_long_tnt(const unsigned char *buf, size_t len, 778c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci uint64_t payload; 808c2ecf20Sopenharmony_ci int count; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci if (len < 8) 838c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci payload = le64_to_cpu(*(uint64_t *)buf); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci for (count = 47; count; count--) { 888c2ecf20Sopenharmony_ci if (payload & BIT63) 898c2ecf20Sopenharmony_ci break; 908c2ecf20Sopenharmony_ci payload <<= 1; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci packet->type = INTEL_PT_TNT; 948c2ecf20Sopenharmony_ci packet->count = count; 958c2ecf20Sopenharmony_ci packet->payload = payload << 1; 968c2ecf20Sopenharmony_ci return 8; 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic int intel_pt_get_pip(const unsigned char *buf, size_t len, 1008c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci uint64_t payload = 0; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if (len < 8) 1058c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci packet->type = INTEL_PT_PIP; 1088c2ecf20Sopenharmony_ci memcpy_le64(&payload, buf + 2, 6); 1098c2ecf20Sopenharmony_ci packet->payload = payload >> 1; 1108c2ecf20Sopenharmony_ci if (payload & 1) 1118c2ecf20Sopenharmony_ci packet->payload |= NR_FLAG; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci return 8; 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic int intel_pt_get_tracestop(struct intel_pt_pkt *packet) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci packet->type = INTEL_PT_TRACESTOP; 1198c2ecf20Sopenharmony_ci return 2; 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistatic int intel_pt_get_cbr(const unsigned char *buf, size_t len, 1238c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci if (len < 4) 1268c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 1278c2ecf20Sopenharmony_ci packet->type = INTEL_PT_CBR; 1288c2ecf20Sopenharmony_ci packet->payload = le16_to_cpu(*(uint16_t *)(buf + 2)); 1298c2ecf20Sopenharmony_ci return 4; 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic int intel_pt_get_vmcs(const unsigned char *buf, size_t len, 1338c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci unsigned int count = (52 - 5) >> 3; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci if (count < 1 || count > 7) 1388c2ecf20Sopenharmony_ci return INTEL_PT_BAD_PACKET; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (len < count + 2) 1418c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci packet->type = INTEL_PT_VMCS; 1448c2ecf20Sopenharmony_ci packet->count = count; 1458c2ecf20Sopenharmony_ci memcpy_le64(&packet->payload, buf + 2, count); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci return count + 2; 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistatic int intel_pt_get_ovf(struct intel_pt_pkt *packet) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci packet->type = INTEL_PT_OVF; 1538c2ecf20Sopenharmony_ci return 2; 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic int intel_pt_get_psb(const unsigned char *buf, size_t len, 1578c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci int i; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci if (len < 16) 1628c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci for (i = 2; i < 16; i += 2) { 1658c2ecf20Sopenharmony_ci if (buf[i] != 2 || buf[i + 1] != 0x82) 1668c2ecf20Sopenharmony_ci return INTEL_PT_BAD_PACKET; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci packet->type = INTEL_PT_PSB; 1708c2ecf20Sopenharmony_ci return 16; 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic int intel_pt_get_psbend(struct intel_pt_pkt *packet) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci packet->type = INTEL_PT_PSBEND; 1768c2ecf20Sopenharmony_ci return 2; 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic int intel_pt_get_tma(const unsigned char *buf, size_t len, 1808c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 1818c2ecf20Sopenharmony_ci{ 1828c2ecf20Sopenharmony_ci if (len < 7) 1838c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci packet->type = INTEL_PT_TMA; 1868c2ecf20Sopenharmony_ci packet->payload = buf[2] | (buf[3] << 8); 1878c2ecf20Sopenharmony_ci packet->count = buf[5] | ((buf[6] & BIT(0)) << 8); 1888c2ecf20Sopenharmony_ci return 7; 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistatic int intel_pt_get_pad(struct intel_pt_pkt *packet) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci packet->type = INTEL_PT_PAD; 1948c2ecf20Sopenharmony_ci return 1; 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic int intel_pt_get_mnt(const unsigned char *buf, size_t len, 1988c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci if (len < 11) 2018c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 2028c2ecf20Sopenharmony_ci packet->type = INTEL_PT_MNT; 2038c2ecf20Sopenharmony_ci memcpy_le64(&packet->payload, buf + 3, 8); 2048c2ecf20Sopenharmony_ci return 11 2058c2ecf20Sopenharmony_ci; 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic int intel_pt_get_3byte(const unsigned char *buf, size_t len, 2098c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci if (len < 3) 2128c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci switch (buf[2]) { 2158c2ecf20Sopenharmony_ci case 0x88: /* MNT */ 2168c2ecf20Sopenharmony_ci return intel_pt_get_mnt(buf, len, packet); 2178c2ecf20Sopenharmony_ci default: 2188c2ecf20Sopenharmony_ci return INTEL_PT_BAD_PACKET; 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci} 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic int intel_pt_get_ptwrite(const unsigned char *buf, size_t len, 2238c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 2248c2ecf20Sopenharmony_ci{ 2258c2ecf20Sopenharmony_ci packet->count = (buf[1] >> 5) & 0x3; 2268c2ecf20Sopenharmony_ci packet->type = buf[1] & BIT(7) ? INTEL_PT_PTWRITE_IP : 2278c2ecf20Sopenharmony_ci INTEL_PT_PTWRITE; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci switch (packet->count) { 2308c2ecf20Sopenharmony_ci case 0: 2318c2ecf20Sopenharmony_ci if (len < 6) 2328c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 2338c2ecf20Sopenharmony_ci packet->payload = le32_to_cpu(*(uint32_t *)(buf + 2)); 2348c2ecf20Sopenharmony_ci return 6; 2358c2ecf20Sopenharmony_ci case 1: 2368c2ecf20Sopenharmony_ci if (len < 10) 2378c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 2388c2ecf20Sopenharmony_ci packet->payload = le64_to_cpu(*(uint64_t *)(buf + 2)); 2398c2ecf20Sopenharmony_ci return 10; 2408c2ecf20Sopenharmony_ci default: 2418c2ecf20Sopenharmony_ci return INTEL_PT_BAD_PACKET; 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic int intel_pt_get_exstop(struct intel_pt_pkt *packet) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci packet->type = INTEL_PT_EXSTOP; 2488c2ecf20Sopenharmony_ci return 2; 2498c2ecf20Sopenharmony_ci} 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_cistatic int intel_pt_get_exstop_ip(struct intel_pt_pkt *packet) 2528c2ecf20Sopenharmony_ci{ 2538c2ecf20Sopenharmony_ci packet->type = INTEL_PT_EXSTOP_IP; 2548c2ecf20Sopenharmony_ci return 2; 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_cistatic int intel_pt_get_mwait(const unsigned char *buf, size_t len, 2588c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci if (len < 10) 2618c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 2628c2ecf20Sopenharmony_ci packet->type = INTEL_PT_MWAIT; 2638c2ecf20Sopenharmony_ci packet->payload = le64_to_cpu(*(uint64_t *)(buf + 2)); 2648c2ecf20Sopenharmony_ci return 10; 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_cistatic int intel_pt_get_pwre(const unsigned char *buf, size_t len, 2688c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 2698c2ecf20Sopenharmony_ci{ 2708c2ecf20Sopenharmony_ci if (len < 4) 2718c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 2728c2ecf20Sopenharmony_ci packet->type = INTEL_PT_PWRE; 2738c2ecf20Sopenharmony_ci memcpy_le64(&packet->payload, buf + 2, 2); 2748c2ecf20Sopenharmony_ci return 4; 2758c2ecf20Sopenharmony_ci} 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistatic int intel_pt_get_pwrx(const unsigned char *buf, size_t len, 2788c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 2798c2ecf20Sopenharmony_ci{ 2808c2ecf20Sopenharmony_ci if (len < 7) 2818c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 2828c2ecf20Sopenharmony_ci packet->type = INTEL_PT_PWRX; 2838c2ecf20Sopenharmony_ci memcpy_le64(&packet->payload, buf + 2, 5); 2848c2ecf20Sopenharmony_ci return 7; 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistatic int intel_pt_get_bbp(const unsigned char *buf, size_t len, 2888c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci if (len < 3) 2918c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 2928c2ecf20Sopenharmony_ci packet->type = INTEL_PT_BBP; 2938c2ecf20Sopenharmony_ci packet->count = buf[2] >> 7; 2948c2ecf20Sopenharmony_ci packet->payload = buf[2] & 0x1f; 2958c2ecf20Sopenharmony_ci return 3; 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic int intel_pt_get_bip_4(const unsigned char *buf, size_t len, 2998c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci if (len < 5) 3028c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 3038c2ecf20Sopenharmony_ci packet->type = INTEL_PT_BIP; 3048c2ecf20Sopenharmony_ci packet->count = buf[0] >> 3; 3058c2ecf20Sopenharmony_ci memcpy_le64(&packet->payload, buf + 1, 4); 3068c2ecf20Sopenharmony_ci return 5; 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_cistatic int intel_pt_get_bip_8(const unsigned char *buf, size_t len, 3108c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci if (len < 9) 3138c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 3148c2ecf20Sopenharmony_ci packet->type = INTEL_PT_BIP; 3158c2ecf20Sopenharmony_ci packet->count = buf[0] >> 3; 3168c2ecf20Sopenharmony_ci memcpy_le64(&packet->payload, buf + 1, 8); 3178c2ecf20Sopenharmony_ci return 9; 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistatic int intel_pt_get_bep(size_t len, struct intel_pt_pkt *packet) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci if (len < 2) 3238c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 3248c2ecf20Sopenharmony_ci packet->type = INTEL_PT_BEP; 3258c2ecf20Sopenharmony_ci return 2; 3268c2ecf20Sopenharmony_ci} 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_cistatic int intel_pt_get_bep_ip(size_t len, struct intel_pt_pkt *packet) 3298c2ecf20Sopenharmony_ci{ 3308c2ecf20Sopenharmony_ci if (len < 2) 3318c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 3328c2ecf20Sopenharmony_ci packet->type = INTEL_PT_BEP_IP; 3338c2ecf20Sopenharmony_ci return 2; 3348c2ecf20Sopenharmony_ci} 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cistatic int intel_pt_get_ext(const unsigned char *buf, size_t len, 3378c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci if (len < 2) 3408c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci if ((buf[1] & 0x1f) == 0x12) 3438c2ecf20Sopenharmony_ci return intel_pt_get_ptwrite(buf, len, packet); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci switch (buf[1]) { 3468c2ecf20Sopenharmony_ci case 0xa3: /* Long TNT */ 3478c2ecf20Sopenharmony_ci return intel_pt_get_long_tnt(buf, len, packet); 3488c2ecf20Sopenharmony_ci case 0x43: /* PIP */ 3498c2ecf20Sopenharmony_ci return intel_pt_get_pip(buf, len, packet); 3508c2ecf20Sopenharmony_ci case 0x83: /* TraceStop */ 3518c2ecf20Sopenharmony_ci return intel_pt_get_tracestop(packet); 3528c2ecf20Sopenharmony_ci case 0x03: /* CBR */ 3538c2ecf20Sopenharmony_ci return intel_pt_get_cbr(buf, len, packet); 3548c2ecf20Sopenharmony_ci case 0xc8: /* VMCS */ 3558c2ecf20Sopenharmony_ci return intel_pt_get_vmcs(buf, len, packet); 3568c2ecf20Sopenharmony_ci case 0xf3: /* OVF */ 3578c2ecf20Sopenharmony_ci return intel_pt_get_ovf(packet); 3588c2ecf20Sopenharmony_ci case 0x82: /* PSB */ 3598c2ecf20Sopenharmony_ci return intel_pt_get_psb(buf, len, packet); 3608c2ecf20Sopenharmony_ci case 0x23: /* PSBEND */ 3618c2ecf20Sopenharmony_ci return intel_pt_get_psbend(packet); 3628c2ecf20Sopenharmony_ci case 0x73: /* TMA */ 3638c2ecf20Sopenharmony_ci return intel_pt_get_tma(buf, len, packet); 3648c2ecf20Sopenharmony_ci case 0xC3: /* 3-byte header */ 3658c2ecf20Sopenharmony_ci return intel_pt_get_3byte(buf, len, packet); 3668c2ecf20Sopenharmony_ci case 0x62: /* EXSTOP no IP */ 3678c2ecf20Sopenharmony_ci return intel_pt_get_exstop(packet); 3688c2ecf20Sopenharmony_ci case 0xE2: /* EXSTOP with IP */ 3698c2ecf20Sopenharmony_ci return intel_pt_get_exstop_ip(packet); 3708c2ecf20Sopenharmony_ci case 0xC2: /* MWAIT */ 3718c2ecf20Sopenharmony_ci return intel_pt_get_mwait(buf, len, packet); 3728c2ecf20Sopenharmony_ci case 0x22: /* PWRE */ 3738c2ecf20Sopenharmony_ci return intel_pt_get_pwre(buf, len, packet); 3748c2ecf20Sopenharmony_ci case 0xA2: /* PWRX */ 3758c2ecf20Sopenharmony_ci return intel_pt_get_pwrx(buf, len, packet); 3768c2ecf20Sopenharmony_ci case 0x63: /* BBP */ 3778c2ecf20Sopenharmony_ci return intel_pt_get_bbp(buf, len, packet); 3788c2ecf20Sopenharmony_ci case 0x33: /* BEP no IP */ 3798c2ecf20Sopenharmony_ci return intel_pt_get_bep(len, packet); 3808c2ecf20Sopenharmony_ci case 0xb3: /* BEP with IP */ 3818c2ecf20Sopenharmony_ci return intel_pt_get_bep_ip(len, packet); 3828c2ecf20Sopenharmony_ci default: 3838c2ecf20Sopenharmony_ci return INTEL_PT_BAD_PACKET; 3848c2ecf20Sopenharmony_ci } 3858c2ecf20Sopenharmony_ci} 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cistatic int intel_pt_get_short_tnt(unsigned int byte, 3888c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 3898c2ecf20Sopenharmony_ci{ 3908c2ecf20Sopenharmony_ci int count; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci for (count = 6; count; count--) { 3938c2ecf20Sopenharmony_ci if (byte & BIT(7)) 3948c2ecf20Sopenharmony_ci break; 3958c2ecf20Sopenharmony_ci byte <<= 1; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci packet->type = INTEL_PT_TNT; 3998c2ecf20Sopenharmony_ci packet->count = count; 4008c2ecf20Sopenharmony_ci packet->payload = (uint64_t)byte << 57; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci return 1; 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_cistatic int intel_pt_get_cyc(unsigned int byte, const unsigned char *buf, 4068c2ecf20Sopenharmony_ci size_t len, struct intel_pt_pkt *packet) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci unsigned int offs = 1, shift; 4098c2ecf20Sopenharmony_ci uint64_t payload = byte >> 3; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci byte >>= 2; 4128c2ecf20Sopenharmony_ci len -= 1; 4138c2ecf20Sopenharmony_ci for (shift = 5; byte & 1; shift += 7) { 4148c2ecf20Sopenharmony_ci if (offs > 9) 4158c2ecf20Sopenharmony_ci return INTEL_PT_BAD_PACKET; 4168c2ecf20Sopenharmony_ci if (len < offs) 4178c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 4188c2ecf20Sopenharmony_ci byte = buf[offs++]; 4198c2ecf20Sopenharmony_ci payload |= ((uint64_t)byte >> 1) << shift; 4208c2ecf20Sopenharmony_ci } 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci packet->type = INTEL_PT_CYC; 4238c2ecf20Sopenharmony_ci packet->payload = payload; 4248c2ecf20Sopenharmony_ci return offs; 4258c2ecf20Sopenharmony_ci} 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_cistatic int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte, 4288c2ecf20Sopenharmony_ci const unsigned char *buf, size_t len, 4298c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci int ip_len; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci packet->count = byte >> 5; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci switch (packet->count) { 4368c2ecf20Sopenharmony_ci case 0: 4378c2ecf20Sopenharmony_ci ip_len = 0; 4388c2ecf20Sopenharmony_ci break; 4398c2ecf20Sopenharmony_ci case 1: 4408c2ecf20Sopenharmony_ci if (len < 3) 4418c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 4428c2ecf20Sopenharmony_ci ip_len = 2; 4438c2ecf20Sopenharmony_ci packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1)); 4448c2ecf20Sopenharmony_ci break; 4458c2ecf20Sopenharmony_ci case 2: 4468c2ecf20Sopenharmony_ci if (len < 5) 4478c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 4488c2ecf20Sopenharmony_ci ip_len = 4; 4498c2ecf20Sopenharmony_ci packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1)); 4508c2ecf20Sopenharmony_ci break; 4518c2ecf20Sopenharmony_ci case 3: 4528c2ecf20Sopenharmony_ci case 4: 4538c2ecf20Sopenharmony_ci if (len < 7) 4548c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 4558c2ecf20Sopenharmony_ci ip_len = 6; 4568c2ecf20Sopenharmony_ci memcpy_le64(&packet->payload, buf + 1, 6); 4578c2ecf20Sopenharmony_ci break; 4588c2ecf20Sopenharmony_ci case 6: 4598c2ecf20Sopenharmony_ci if (len < 9) 4608c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 4618c2ecf20Sopenharmony_ci ip_len = 8; 4628c2ecf20Sopenharmony_ci packet->payload = le64_to_cpu(*(uint64_t *)(buf + 1)); 4638c2ecf20Sopenharmony_ci break; 4648c2ecf20Sopenharmony_ci default: 4658c2ecf20Sopenharmony_ci return INTEL_PT_BAD_PACKET; 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci packet->type = type; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci return ip_len + 1; 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_cistatic int intel_pt_get_mode(const unsigned char *buf, size_t len, 4748c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 4758c2ecf20Sopenharmony_ci{ 4768c2ecf20Sopenharmony_ci if (len < 2) 4778c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci switch (buf[1] >> 5) { 4808c2ecf20Sopenharmony_ci case 0: 4818c2ecf20Sopenharmony_ci packet->type = INTEL_PT_MODE_EXEC; 4828c2ecf20Sopenharmony_ci switch (buf[1] & 3) { 4838c2ecf20Sopenharmony_ci case 0: 4848c2ecf20Sopenharmony_ci packet->payload = 16; 4858c2ecf20Sopenharmony_ci break; 4868c2ecf20Sopenharmony_ci case 1: 4878c2ecf20Sopenharmony_ci packet->payload = 64; 4888c2ecf20Sopenharmony_ci break; 4898c2ecf20Sopenharmony_ci case 2: 4908c2ecf20Sopenharmony_ci packet->payload = 32; 4918c2ecf20Sopenharmony_ci break; 4928c2ecf20Sopenharmony_ci default: 4938c2ecf20Sopenharmony_ci return INTEL_PT_BAD_PACKET; 4948c2ecf20Sopenharmony_ci } 4958c2ecf20Sopenharmony_ci break; 4968c2ecf20Sopenharmony_ci case 1: 4978c2ecf20Sopenharmony_ci packet->type = INTEL_PT_MODE_TSX; 4988c2ecf20Sopenharmony_ci if ((buf[1] & 3) == 3) 4998c2ecf20Sopenharmony_ci return INTEL_PT_BAD_PACKET; 5008c2ecf20Sopenharmony_ci packet->payload = buf[1] & 3; 5018c2ecf20Sopenharmony_ci break; 5028c2ecf20Sopenharmony_ci default: 5038c2ecf20Sopenharmony_ci return INTEL_PT_BAD_PACKET; 5048c2ecf20Sopenharmony_ci } 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci return 2; 5078c2ecf20Sopenharmony_ci} 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_cistatic int intel_pt_get_tsc(const unsigned char *buf, size_t len, 5108c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 5118c2ecf20Sopenharmony_ci{ 5128c2ecf20Sopenharmony_ci if (len < 8) 5138c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 5148c2ecf20Sopenharmony_ci packet->type = INTEL_PT_TSC; 5158c2ecf20Sopenharmony_ci memcpy_le64(&packet->payload, buf + 1, 7); 5168c2ecf20Sopenharmony_ci return 8; 5178c2ecf20Sopenharmony_ci} 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_cistatic int intel_pt_get_mtc(const unsigned char *buf, size_t len, 5208c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet) 5218c2ecf20Sopenharmony_ci{ 5228c2ecf20Sopenharmony_ci if (len < 2) 5238c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 5248c2ecf20Sopenharmony_ci packet->type = INTEL_PT_MTC; 5258c2ecf20Sopenharmony_ci packet->payload = buf[1]; 5268c2ecf20Sopenharmony_ci return 2; 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_cistatic int intel_pt_do_get_packet(const unsigned char *buf, size_t len, 5308c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet, 5318c2ecf20Sopenharmony_ci enum intel_pt_pkt_ctx ctx) 5328c2ecf20Sopenharmony_ci{ 5338c2ecf20Sopenharmony_ci unsigned int byte; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci memset(packet, 0, sizeof(struct intel_pt_pkt)); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci if (!len) 5388c2ecf20Sopenharmony_ci return INTEL_PT_NEED_MORE_BYTES; 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci byte = buf[0]; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci switch (ctx) { 5438c2ecf20Sopenharmony_ci case INTEL_PT_NO_CTX: 5448c2ecf20Sopenharmony_ci break; 5458c2ecf20Sopenharmony_ci case INTEL_PT_BLK_4_CTX: 5468c2ecf20Sopenharmony_ci if ((byte & 0x7) == 4) 5478c2ecf20Sopenharmony_ci return intel_pt_get_bip_4(buf, len, packet); 5488c2ecf20Sopenharmony_ci break; 5498c2ecf20Sopenharmony_ci case INTEL_PT_BLK_8_CTX: 5508c2ecf20Sopenharmony_ci if ((byte & 0x7) == 4) 5518c2ecf20Sopenharmony_ci return intel_pt_get_bip_8(buf, len, packet); 5528c2ecf20Sopenharmony_ci break; 5538c2ecf20Sopenharmony_ci default: 5548c2ecf20Sopenharmony_ci break; 5558c2ecf20Sopenharmony_ci } 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci if (!(byte & BIT(0))) { 5588c2ecf20Sopenharmony_ci if (byte == 0) 5598c2ecf20Sopenharmony_ci return intel_pt_get_pad(packet); 5608c2ecf20Sopenharmony_ci if (byte == 2) 5618c2ecf20Sopenharmony_ci return intel_pt_get_ext(buf, len, packet); 5628c2ecf20Sopenharmony_ci return intel_pt_get_short_tnt(byte, packet); 5638c2ecf20Sopenharmony_ci } 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci if ((byte & 2)) 5668c2ecf20Sopenharmony_ci return intel_pt_get_cyc(byte, buf, len, packet); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci switch (byte & 0x1f) { 5698c2ecf20Sopenharmony_ci case 0x0D: 5708c2ecf20Sopenharmony_ci return intel_pt_get_ip(INTEL_PT_TIP, byte, buf, len, packet); 5718c2ecf20Sopenharmony_ci case 0x11: 5728c2ecf20Sopenharmony_ci return intel_pt_get_ip(INTEL_PT_TIP_PGE, byte, buf, len, 5738c2ecf20Sopenharmony_ci packet); 5748c2ecf20Sopenharmony_ci case 0x01: 5758c2ecf20Sopenharmony_ci return intel_pt_get_ip(INTEL_PT_TIP_PGD, byte, buf, len, 5768c2ecf20Sopenharmony_ci packet); 5778c2ecf20Sopenharmony_ci case 0x1D: 5788c2ecf20Sopenharmony_ci return intel_pt_get_ip(INTEL_PT_FUP, byte, buf, len, packet); 5798c2ecf20Sopenharmony_ci case 0x19: 5808c2ecf20Sopenharmony_ci switch (byte) { 5818c2ecf20Sopenharmony_ci case 0x99: 5828c2ecf20Sopenharmony_ci return intel_pt_get_mode(buf, len, packet); 5838c2ecf20Sopenharmony_ci case 0x19: 5848c2ecf20Sopenharmony_ci return intel_pt_get_tsc(buf, len, packet); 5858c2ecf20Sopenharmony_ci case 0x59: 5868c2ecf20Sopenharmony_ci return intel_pt_get_mtc(buf, len, packet); 5878c2ecf20Sopenharmony_ci default: 5888c2ecf20Sopenharmony_ci return INTEL_PT_BAD_PACKET; 5898c2ecf20Sopenharmony_ci } 5908c2ecf20Sopenharmony_ci default: 5918c2ecf20Sopenharmony_ci return INTEL_PT_BAD_PACKET; 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci} 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_civoid intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet, 5968c2ecf20Sopenharmony_ci enum intel_pt_pkt_ctx *ctx) 5978c2ecf20Sopenharmony_ci{ 5988c2ecf20Sopenharmony_ci switch (packet->type) { 5998c2ecf20Sopenharmony_ci case INTEL_PT_BAD: 6008c2ecf20Sopenharmony_ci case INTEL_PT_PAD: 6018c2ecf20Sopenharmony_ci case INTEL_PT_TSC: 6028c2ecf20Sopenharmony_ci case INTEL_PT_TMA: 6038c2ecf20Sopenharmony_ci case INTEL_PT_MTC: 6048c2ecf20Sopenharmony_ci case INTEL_PT_FUP: 6058c2ecf20Sopenharmony_ci case INTEL_PT_CYC: 6068c2ecf20Sopenharmony_ci case INTEL_PT_CBR: 6078c2ecf20Sopenharmony_ci case INTEL_PT_MNT: 6088c2ecf20Sopenharmony_ci case INTEL_PT_EXSTOP: 6098c2ecf20Sopenharmony_ci case INTEL_PT_EXSTOP_IP: 6108c2ecf20Sopenharmony_ci case INTEL_PT_PWRE: 6118c2ecf20Sopenharmony_ci case INTEL_PT_PWRX: 6128c2ecf20Sopenharmony_ci case INTEL_PT_BIP: 6138c2ecf20Sopenharmony_ci break; 6148c2ecf20Sopenharmony_ci case INTEL_PT_TNT: 6158c2ecf20Sopenharmony_ci case INTEL_PT_TIP: 6168c2ecf20Sopenharmony_ci case INTEL_PT_TIP_PGD: 6178c2ecf20Sopenharmony_ci case INTEL_PT_TIP_PGE: 6188c2ecf20Sopenharmony_ci case INTEL_PT_MODE_EXEC: 6198c2ecf20Sopenharmony_ci case INTEL_PT_MODE_TSX: 6208c2ecf20Sopenharmony_ci case INTEL_PT_PIP: 6218c2ecf20Sopenharmony_ci case INTEL_PT_OVF: 6228c2ecf20Sopenharmony_ci case INTEL_PT_VMCS: 6238c2ecf20Sopenharmony_ci case INTEL_PT_TRACESTOP: 6248c2ecf20Sopenharmony_ci case INTEL_PT_PSB: 6258c2ecf20Sopenharmony_ci case INTEL_PT_PSBEND: 6268c2ecf20Sopenharmony_ci case INTEL_PT_PTWRITE: 6278c2ecf20Sopenharmony_ci case INTEL_PT_PTWRITE_IP: 6288c2ecf20Sopenharmony_ci case INTEL_PT_MWAIT: 6298c2ecf20Sopenharmony_ci case INTEL_PT_BEP: 6308c2ecf20Sopenharmony_ci case INTEL_PT_BEP_IP: 6318c2ecf20Sopenharmony_ci *ctx = INTEL_PT_NO_CTX; 6328c2ecf20Sopenharmony_ci break; 6338c2ecf20Sopenharmony_ci case INTEL_PT_BBP: 6348c2ecf20Sopenharmony_ci if (packet->count) 6358c2ecf20Sopenharmony_ci *ctx = INTEL_PT_BLK_4_CTX; 6368c2ecf20Sopenharmony_ci else 6378c2ecf20Sopenharmony_ci *ctx = INTEL_PT_BLK_8_CTX; 6388c2ecf20Sopenharmony_ci break; 6398c2ecf20Sopenharmony_ci default: 6408c2ecf20Sopenharmony_ci break; 6418c2ecf20Sopenharmony_ci } 6428c2ecf20Sopenharmony_ci} 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ciint intel_pt_get_packet(const unsigned char *buf, size_t len, 6458c2ecf20Sopenharmony_ci struct intel_pt_pkt *packet, enum intel_pt_pkt_ctx *ctx) 6468c2ecf20Sopenharmony_ci{ 6478c2ecf20Sopenharmony_ci int ret; 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci ret = intel_pt_do_get_packet(buf, len, packet, *ctx); 6508c2ecf20Sopenharmony_ci if (ret > 0) { 6518c2ecf20Sopenharmony_ci while (ret < 8 && len > (size_t)ret && !buf[ret]) 6528c2ecf20Sopenharmony_ci ret += 1; 6538c2ecf20Sopenharmony_ci intel_pt_upd_pkt_ctx(packet, ctx); 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci return ret; 6568c2ecf20Sopenharmony_ci} 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ciint intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, 6598c2ecf20Sopenharmony_ci size_t buf_len) 6608c2ecf20Sopenharmony_ci{ 6618c2ecf20Sopenharmony_ci int ret, i, nr; 6628c2ecf20Sopenharmony_ci unsigned long long payload = packet->payload; 6638c2ecf20Sopenharmony_ci const char *name = intel_pt_pkt_name(packet->type); 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci switch (packet->type) { 6668c2ecf20Sopenharmony_ci case INTEL_PT_BAD: 6678c2ecf20Sopenharmony_ci case INTEL_PT_PAD: 6688c2ecf20Sopenharmony_ci case INTEL_PT_PSB: 6698c2ecf20Sopenharmony_ci case INTEL_PT_PSBEND: 6708c2ecf20Sopenharmony_ci case INTEL_PT_TRACESTOP: 6718c2ecf20Sopenharmony_ci case INTEL_PT_OVF: 6728c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s", name); 6738c2ecf20Sopenharmony_ci case INTEL_PT_TNT: { 6748c2ecf20Sopenharmony_ci size_t blen = buf_len; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci ret = snprintf(buf, blen, "%s ", name); 6778c2ecf20Sopenharmony_ci if (ret < 0) 6788c2ecf20Sopenharmony_ci return ret; 6798c2ecf20Sopenharmony_ci buf += ret; 6808c2ecf20Sopenharmony_ci blen -= ret; 6818c2ecf20Sopenharmony_ci for (i = 0; i < packet->count; i++) { 6828c2ecf20Sopenharmony_ci if (payload & BIT63) 6838c2ecf20Sopenharmony_ci ret = snprintf(buf, blen, "T"); 6848c2ecf20Sopenharmony_ci else 6858c2ecf20Sopenharmony_ci ret = snprintf(buf, blen, "N"); 6868c2ecf20Sopenharmony_ci if (ret < 0) 6878c2ecf20Sopenharmony_ci return ret; 6888c2ecf20Sopenharmony_ci buf += ret; 6898c2ecf20Sopenharmony_ci blen -= ret; 6908c2ecf20Sopenharmony_ci payload <<= 1; 6918c2ecf20Sopenharmony_ci } 6928c2ecf20Sopenharmony_ci ret = snprintf(buf, blen, " (%d)", packet->count); 6938c2ecf20Sopenharmony_ci if (ret < 0) 6948c2ecf20Sopenharmony_ci return ret; 6958c2ecf20Sopenharmony_ci blen -= ret; 6968c2ecf20Sopenharmony_ci return buf_len - blen; 6978c2ecf20Sopenharmony_ci } 6988c2ecf20Sopenharmony_ci case INTEL_PT_TIP_PGD: 6998c2ecf20Sopenharmony_ci case INTEL_PT_TIP_PGE: 7008c2ecf20Sopenharmony_ci case INTEL_PT_TIP: 7018c2ecf20Sopenharmony_ci case INTEL_PT_FUP: 7028c2ecf20Sopenharmony_ci if (!(packet->count)) 7038c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s no ip", name); 7048c2ecf20Sopenharmony_ci __fallthrough; 7058c2ecf20Sopenharmony_ci case INTEL_PT_CYC: 7068c2ecf20Sopenharmony_ci case INTEL_PT_VMCS: 7078c2ecf20Sopenharmony_ci case INTEL_PT_MTC: 7088c2ecf20Sopenharmony_ci case INTEL_PT_MNT: 7098c2ecf20Sopenharmony_ci case INTEL_PT_CBR: 7108c2ecf20Sopenharmony_ci case INTEL_PT_TSC: 7118c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s 0x%llx", name, payload); 7128c2ecf20Sopenharmony_ci case INTEL_PT_TMA: 7138c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s CTC 0x%x FC 0x%x", name, 7148c2ecf20Sopenharmony_ci (unsigned)payload, packet->count); 7158c2ecf20Sopenharmony_ci case INTEL_PT_MODE_EXEC: 7168c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s %lld", name, payload); 7178c2ecf20Sopenharmony_ci case INTEL_PT_MODE_TSX: 7188c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s TXAbort:%u InTX:%u", 7198c2ecf20Sopenharmony_ci name, (unsigned)(payload >> 1) & 1, 7208c2ecf20Sopenharmony_ci (unsigned)payload & 1); 7218c2ecf20Sopenharmony_ci case INTEL_PT_PIP: 7228c2ecf20Sopenharmony_ci nr = packet->payload & NR_FLAG ? 1 : 0; 7238c2ecf20Sopenharmony_ci payload &= ~NR_FLAG; 7248c2ecf20Sopenharmony_ci ret = snprintf(buf, buf_len, "%s 0x%llx (NR=%d)", 7258c2ecf20Sopenharmony_ci name, payload, nr); 7268c2ecf20Sopenharmony_ci return ret; 7278c2ecf20Sopenharmony_ci case INTEL_PT_PTWRITE: 7288c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s 0x%llx IP:0", name, payload); 7298c2ecf20Sopenharmony_ci case INTEL_PT_PTWRITE_IP: 7308c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s 0x%llx IP:1", name, payload); 7318c2ecf20Sopenharmony_ci case INTEL_PT_BEP: 7328c2ecf20Sopenharmony_ci case INTEL_PT_EXSTOP: 7338c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s IP:0", name); 7348c2ecf20Sopenharmony_ci case INTEL_PT_BEP_IP: 7358c2ecf20Sopenharmony_ci case INTEL_PT_EXSTOP_IP: 7368c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s IP:1", name); 7378c2ecf20Sopenharmony_ci case INTEL_PT_MWAIT: 7388c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s 0x%llx Hints 0x%x Extensions 0x%x", 7398c2ecf20Sopenharmony_ci name, payload, (unsigned int)(payload & 0xff), 7408c2ecf20Sopenharmony_ci (unsigned int)((payload >> 32) & 0x3)); 7418c2ecf20Sopenharmony_ci case INTEL_PT_PWRE: 7428c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s 0x%llx HW:%u CState:%u Sub-CState:%u", 7438c2ecf20Sopenharmony_ci name, payload, !!(payload & 0x80), 7448c2ecf20Sopenharmony_ci (unsigned int)((payload >> 12) & 0xf), 7458c2ecf20Sopenharmony_ci (unsigned int)((payload >> 8) & 0xf)); 7468c2ecf20Sopenharmony_ci case INTEL_PT_PWRX: 7478c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s 0x%llx Last CState:%u Deepest CState:%u Wake Reason 0x%x", 7488c2ecf20Sopenharmony_ci name, payload, 7498c2ecf20Sopenharmony_ci (unsigned int)((payload >> 4) & 0xf), 7508c2ecf20Sopenharmony_ci (unsigned int)(payload & 0xf), 7518c2ecf20Sopenharmony_ci (unsigned int)((payload >> 8) & 0xf)); 7528c2ecf20Sopenharmony_ci case INTEL_PT_BBP: 7538c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s SZ %s-byte Type 0x%llx", 7548c2ecf20Sopenharmony_ci name, packet->count ? "4" : "8", payload); 7558c2ecf20Sopenharmony_ci case INTEL_PT_BIP: 7568c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s ID 0x%02x Value 0x%llx", 7578c2ecf20Sopenharmony_ci name, packet->count, payload); 7588c2ecf20Sopenharmony_ci default: 7598c2ecf20Sopenharmony_ci break; 7608c2ecf20Sopenharmony_ci } 7618c2ecf20Sopenharmony_ci return snprintf(buf, buf_len, "%s 0x%llx (%d)", 7628c2ecf20Sopenharmony_ci name, payload, packet->count); 7638c2ecf20Sopenharmony_ci} 764