18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * intel_pt_decoder.h: Intel Processor Trace support 48c2ecf20Sopenharmony_ci * Copyright (c) 2013-2014, Intel Corporation. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#ifndef INCLUDE__INTEL_PT_DECODER_H__ 88c2ecf20Sopenharmony_ci#define INCLUDE__INTEL_PT_DECODER_H__ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <stdint.h> 118c2ecf20Sopenharmony_ci#include <stddef.h> 128c2ecf20Sopenharmony_ci#include <stdbool.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include "intel-pt-insn-decoder.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define INTEL_PT_IN_TX (1 << 0) 178c2ecf20Sopenharmony_ci#define INTEL_PT_ABORT_TX (1 << 1) 188c2ecf20Sopenharmony_ci#define INTEL_PT_ASYNC (1 << 2) 198c2ecf20Sopenharmony_ci#define INTEL_PT_FUP_IP (1 << 3) 208c2ecf20Sopenharmony_ci#define INTEL_PT_SAMPLE_IPC (1 << 4) 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cienum intel_pt_sample_type { 238c2ecf20Sopenharmony_ci INTEL_PT_BRANCH = 1 << 0, 248c2ecf20Sopenharmony_ci INTEL_PT_INSTRUCTION = 1 << 1, 258c2ecf20Sopenharmony_ci INTEL_PT_TRANSACTION = 1 << 2, 268c2ecf20Sopenharmony_ci INTEL_PT_PTW = 1 << 3, 278c2ecf20Sopenharmony_ci INTEL_PT_MWAIT_OP = 1 << 4, 288c2ecf20Sopenharmony_ci INTEL_PT_PWR_ENTRY = 1 << 5, 298c2ecf20Sopenharmony_ci INTEL_PT_EX_STOP = 1 << 6, 308c2ecf20Sopenharmony_ci INTEL_PT_PWR_EXIT = 1 << 7, 318c2ecf20Sopenharmony_ci INTEL_PT_CBR_CHG = 1 << 8, 328c2ecf20Sopenharmony_ci INTEL_PT_TRACE_BEGIN = 1 << 9, 338c2ecf20Sopenharmony_ci INTEL_PT_TRACE_END = 1 << 10, 348c2ecf20Sopenharmony_ci INTEL_PT_BLK_ITEMS = 1 << 11, 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cienum intel_pt_period_type { 388c2ecf20Sopenharmony_ci INTEL_PT_PERIOD_NONE, 398c2ecf20Sopenharmony_ci INTEL_PT_PERIOD_INSTRUCTIONS, 408c2ecf20Sopenharmony_ci INTEL_PT_PERIOD_TICKS, 418c2ecf20Sopenharmony_ci INTEL_PT_PERIOD_MTC, 428c2ecf20Sopenharmony_ci}; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cienum { 458c2ecf20Sopenharmony_ci INTEL_PT_ERR_NOMEM = 1, 468c2ecf20Sopenharmony_ci INTEL_PT_ERR_INTERN, 478c2ecf20Sopenharmony_ci INTEL_PT_ERR_BADPKT, 488c2ecf20Sopenharmony_ci INTEL_PT_ERR_NODATA, 498c2ecf20Sopenharmony_ci INTEL_PT_ERR_NOINSN, 508c2ecf20Sopenharmony_ci INTEL_PT_ERR_MISMAT, 518c2ecf20Sopenharmony_ci INTEL_PT_ERR_OVR, 528c2ecf20Sopenharmony_ci INTEL_PT_ERR_LOST, 538c2ecf20Sopenharmony_ci INTEL_PT_ERR_UNK, 548c2ecf20Sopenharmony_ci INTEL_PT_ERR_NELOOP, 558c2ecf20Sopenharmony_ci INTEL_PT_ERR_MAX, 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cienum intel_pt_param_flags { 598c2ecf20Sopenharmony_ci /* 608c2ecf20Sopenharmony_ci * FUP packet can contain next linear instruction pointer instead of 618c2ecf20Sopenharmony_ci * current linear instruction pointer. 628c2ecf20Sopenharmony_ci */ 638c2ecf20Sopenharmony_ci INTEL_PT_FUP_WITH_NLIP = 1 << 0, 648c2ecf20Sopenharmony_ci}; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cienum intel_pt_blk_type { 678c2ecf20Sopenharmony_ci INTEL_PT_GP_REGS = 1, 688c2ecf20Sopenharmony_ci INTEL_PT_PEBS_BASIC = 4, 698c2ecf20Sopenharmony_ci INTEL_PT_PEBS_MEM = 5, 708c2ecf20Sopenharmony_ci INTEL_PT_LBR_0 = 8, 718c2ecf20Sopenharmony_ci INTEL_PT_LBR_1 = 9, 728c2ecf20Sopenharmony_ci INTEL_PT_LBR_2 = 10, 738c2ecf20Sopenharmony_ci INTEL_PT_XMM = 16, 748c2ecf20Sopenharmony_ci INTEL_PT_BLK_TYPE_MAX 758c2ecf20Sopenharmony_ci}; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci/* 788c2ecf20Sopenharmony_ci * The block type numbers are not sequential but here they are given sequential 798c2ecf20Sopenharmony_ci * positions to avoid wasting space for array placement. 808c2ecf20Sopenharmony_ci */ 818c2ecf20Sopenharmony_cienum intel_pt_blk_type_pos { 828c2ecf20Sopenharmony_ci INTEL_PT_GP_REGS_POS, 838c2ecf20Sopenharmony_ci INTEL_PT_PEBS_BASIC_POS, 848c2ecf20Sopenharmony_ci INTEL_PT_PEBS_MEM_POS, 858c2ecf20Sopenharmony_ci INTEL_PT_LBR_0_POS, 868c2ecf20Sopenharmony_ci INTEL_PT_LBR_1_POS, 878c2ecf20Sopenharmony_ci INTEL_PT_LBR_2_POS, 888c2ecf20Sopenharmony_ci INTEL_PT_XMM_POS, 898c2ecf20Sopenharmony_ci INTEL_PT_BLK_TYPE_CNT 908c2ecf20Sopenharmony_ci}; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci/* Get the array position for a block type */ 938c2ecf20Sopenharmony_cistatic inline int intel_pt_blk_type_pos(enum intel_pt_blk_type blk_type) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci#define BLK_TYPE(bt) [INTEL_PT_##bt] = INTEL_PT_##bt##_POS + 1 968c2ecf20Sopenharmony_ci const int map[INTEL_PT_BLK_TYPE_MAX] = { 978c2ecf20Sopenharmony_ci BLK_TYPE(GP_REGS), 988c2ecf20Sopenharmony_ci BLK_TYPE(PEBS_BASIC), 998c2ecf20Sopenharmony_ci BLK_TYPE(PEBS_MEM), 1008c2ecf20Sopenharmony_ci BLK_TYPE(LBR_0), 1018c2ecf20Sopenharmony_ci BLK_TYPE(LBR_1), 1028c2ecf20Sopenharmony_ci BLK_TYPE(LBR_2), 1038c2ecf20Sopenharmony_ci BLK_TYPE(XMM), 1048c2ecf20Sopenharmony_ci }; 1058c2ecf20Sopenharmony_ci#undef BLK_TYPE 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci return blk_type < INTEL_PT_BLK_TYPE_MAX ? map[blk_type] - 1 : -1; 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci#define INTEL_PT_BLK_ITEM_ID_CNT 32 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/* 1138c2ecf20Sopenharmony_ci * Use unions so that the block items can be accessed by name or by array index. 1148c2ecf20Sopenharmony_ci * There is an array of 32-bit masks for each block type, which indicate which 1158c2ecf20Sopenharmony_ci * values are present. Then arrays of 32 64-bit values for each block type. 1168c2ecf20Sopenharmony_ci */ 1178c2ecf20Sopenharmony_cistruct intel_pt_blk_items { 1188c2ecf20Sopenharmony_ci union { 1198c2ecf20Sopenharmony_ci uint32_t mask[INTEL_PT_BLK_TYPE_CNT]; 1208c2ecf20Sopenharmony_ci struct { 1218c2ecf20Sopenharmony_ci uint32_t has_rflags:1; 1228c2ecf20Sopenharmony_ci uint32_t has_rip:1; 1238c2ecf20Sopenharmony_ci uint32_t has_rax:1; 1248c2ecf20Sopenharmony_ci uint32_t has_rcx:1; 1258c2ecf20Sopenharmony_ci uint32_t has_rdx:1; 1268c2ecf20Sopenharmony_ci uint32_t has_rbx:1; 1278c2ecf20Sopenharmony_ci uint32_t has_rsp:1; 1288c2ecf20Sopenharmony_ci uint32_t has_rbp:1; 1298c2ecf20Sopenharmony_ci uint32_t has_rsi:1; 1308c2ecf20Sopenharmony_ci uint32_t has_rdi:1; 1318c2ecf20Sopenharmony_ci uint32_t has_r8:1; 1328c2ecf20Sopenharmony_ci uint32_t has_r9:1; 1338c2ecf20Sopenharmony_ci uint32_t has_r10:1; 1348c2ecf20Sopenharmony_ci uint32_t has_r11:1; 1358c2ecf20Sopenharmony_ci uint32_t has_r12:1; 1368c2ecf20Sopenharmony_ci uint32_t has_r13:1; 1378c2ecf20Sopenharmony_ci uint32_t has_r14:1; 1388c2ecf20Sopenharmony_ci uint32_t has_r15:1; 1398c2ecf20Sopenharmony_ci uint32_t has_unused_0:14; 1408c2ecf20Sopenharmony_ci uint32_t has_ip:1; 1418c2ecf20Sopenharmony_ci uint32_t has_applicable_counters:1; 1428c2ecf20Sopenharmony_ci uint32_t has_timestamp:1; 1438c2ecf20Sopenharmony_ci uint32_t has_unused_1:29; 1448c2ecf20Sopenharmony_ci uint32_t has_mem_access_address:1; 1458c2ecf20Sopenharmony_ci uint32_t has_mem_aux_info:1; 1468c2ecf20Sopenharmony_ci uint32_t has_mem_access_latency:1; 1478c2ecf20Sopenharmony_ci uint32_t has_tsx_aux_info:1; 1488c2ecf20Sopenharmony_ci uint32_t has_unused_2:28; 1498c2ecf20Sopenharmony_ci uint32_t has_lbr_0; 1508c2ecf20Sopenharmony_ci uint32_t has_lbr_1; 1518c2ecf20Sopenharmony_ci uint32_t has_lbr_2; 1528c2ecf20Sopenharmony_ci uint32_t has_xmm; 1538c2ecf20Sopenharmony_ci }; 1548c2ecf20Sopenharmony_ci }; 1558c2ecf20Sopenharmony_ci union { 1568c2ecf20Sopenharmony_ci uint64_t val[INTEL_PT_BLK_TYPE_CNT][INTEL_PT_BLK_ITEM_ID_CNT]; 1578c2ecf20Sopenharmony_ci struct { 1588c2ecf20Sopenharmony_ci struct { 1598c2ecf20Sopenharmony_ci uint64_t rflags; 1608c2ecf20Sopenharmony_ci uint64_t rip; 1618c2ecf20Sopenharmony_ci uint64_t rax; 1628c2ecf20Sopenharmony_ci uint64_t rcx; 1638c2ecf20Sopenharmony_ci uint64_t rdx; 1648c2ecf20Sopenharmony_ci uint64_t rbx; 1658c2ecf20Sopenharmony_ci uint64_t rsp; 1668c2ecf20Sopenharmony_ci uint64_t rbp; 1678c2ecf20Sopenharmony_ci uint64_t rsi; 1688c2ecf20Sopenharmony_ci uint64_t rdi; 1698c2ecf20Sopenharmony_ci uint64_t r8; 1708c2ecf20Sopenharmony_ci uint64_t r9; 1718c2ecf20Sopenharmony_ci uint64_t r10; 1728c2ecf20Sopenharmony_ci uint64_t r11; 1738c2ecf20Sopenharmony_ci uint64_t r12; 1748c2ecf20Sopenharmony_ci uint64_t r13; 1758c2ecf20Sopenharmony_ci uint64_t r14; 1768c2ecf20Sopenharmony_ci uint64_t r15; 1778c2ecf20Sopenharmony_ci uint64_t unused_0[INTEL_PT_BLK_ITEM_ID_CNT - 18]; 1788c2ecf20Sopenharmony_ci }; 1798c2ecf20Sopenharmony_ci struct { 1808c2ecf20Sopenharmony_ci uint64_t ip; 1818c2ecf20Sopenharmony_ci uint64_t applicable_counters; 1828c2ecf20Sopenharmony_ci uint64_t timestamp; 1838c2ecf20Sopenharmony_ci uint64_t unused_1[INTEL_PT_BLK_ITEM_ID_CNT - 3]; 1848c2ecf20Sopenharmony_ci }; 1858c2ecf20Sopenharmony_ci struct { 1868c2ecf20Sopenharmony_ci uint64_t mem_access_address; 1878c2ecf20Sopenharmony_ci uint64_t mem_aux_info; 1888c2ecf20Sopenharmony_ci uint64_t mem_access_latency; 1898c2ecf20Sopenharmony_ci uint64_t tsx_aux_info; 1908c2ecf20Sopenharmony_ci uint64_t unused_2[INTEL_PT_BLK_ITEM_ID_CNT - 4]; 1918c2ecf20Sopenharmony_ci }; 1928c2ecf20Sopenharmony_ci uint64_t lbr_0[INTEL_PT_BLK_ITEM_ID_CNT]; 1938c2ecf20Sopenharmony_ci uint64_t lbr_1[INTEL_PT_BLK_ITEM_ID_CNT]; 1948c2ecf20Sopenharmony_ci uint64_t lbr_2[INTEL_PT_BLK_ITEM_ID_CNT]; 1958c2ecf20Sopenharmony_ci uint64_t xmm[INTEL_PT_BLK_ITEM_ID_CNT]; 1968c2ecf20Sopenharmony_ci }; 1978c2ecf20Sopenharmony_ci }; 1988c2ecf20Sopenharmony_ci bool is_32_bit; 1998c2ecf20Sopenharmony_ci}; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistruct intel_pt_state { 2028c2ecf20Sopenharmony_ci enum intel_pt_sample_type type; 2038c2ecf20Sopenharmony_ci int err; 2048c2ecf20Sopenharmony_ci uint64_t from_ip; 2058c2ecf20Sopenharmony_ci uint64_t to_ip; 2068c2ecf20Sopenharmony_ci uint64_t cr3; 2078c2ecf20Sopenharmony_ci uint64_t tot_insn_cnt; 2088c2ecf20Sopenharmony_ci uint64_t tot_cyc_cnt; 2098c2ecf20Sopenharmony_ci uint64_t timestamp; 2108c2ecf20Sopenharmony_ci uint64_t est_timestamp; 2118c2ecf20Sopenharmony_ci uint64_t trace_nr; 2128c2ecf20Sopenharmony_ci uint64_t ptw_payload; 2138c2ecf20Sopenharmony_ci uint64_t mwait_payload; 2148c2ecf20Sopenharmony_ci uint64_t pwre_payload; 2158c2ecf20Sopenharmony_ci uint64_t pwrx_payload; 2168c2ecf20Sopenharmony_ci uint64_t cbr_payload; 2178c2ecf20Sopenharmony_ci uint32_t cbr; 2188c2ecf20Sopenharmony_ci uint32_t flags; 2198c2ecf20Sopenharmony_ci enum intel_pt_insn_op insn_op; 2208c2ecf20Sopenharmony_ci int insn_len; 2218c2ecf20Sopenharmony_ci char insn[INTEL_PT_INSN_BUF_SZ]; 2228c2ecf20Sopenharmony_ci struct intel_pt_blk_items items; 2238c2ecf20Sopenharmony_ci}; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistruct intel_pt_insn; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistruct intel_pt_buffer { 2288c2ecf20Sopenharmony_ci const unsigned char *buf; 2298c2ecf20Sopenharmony_ci size_t len; 2308c2ecf20Sopenharmony_ci bool consecutive; 2318c2ecf20Sopenharmony_ci uint64_t ref_timestamp; 2328c2ecf20Sopenharmony_ci uint64_t trace_nr; 2338c2ecf20Sopenharmony_ci}; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_citypedef int (*intel_pt_lookahead_cb_t)(struct intel_pt_buffer *, void *); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cistruct intel_pt_params { 2388c2ecf20Sopenharmony_ci int (*get_trace)(struct intel_pt_buffer *buffer, void *data); 2398c2ecf20Sopenharmony_ci int (*walk_insn)(struct intel_pt_insn *intel_pt_insn, 2408c2ecf20Sopenharmony_ci uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip, 2418c2ecf20Sopenharmony_ci uint64_t max_insn_cnt, void *data); 2428c2ecf20Sopenharmony_ci bool (*pgd_ip)(uint64_t ip, void *data); 2438c2ecf20Sopenharmony_ci int (*lookahead)(void *data, intel_pt_lookahead_cb_t cb, void *cb_data); 2448c2ecf20Sopenharmony_ci void *data; 2458c2ecf20Sopenharmony_ci bool return_compression; 2468c2ecf20Sopenharmony_ci bool branch_enable; 2478c2ecf20Sopenharmony_ci uint64_t ctl; 2488c2ecf20Sopenharmony_ci uint64_t period; 2498c2ecf20Sopenharmony_ci enum intel_pt_period_type period_type; 2508c2ecf20Sopenharmony_ci unsigned max_non_turbo_ratio; 2518c2ecf20Sopenharmony_ci unsigned int mtc_period; 2528c2ecf20Sopenharmony_ci uint32_t tsc_ctc_ratio_n; 2538c2ecf20Sopenharmony_ci uint32_t tsc_ctc_ratio_d; 2548c2ecf20Sopenharmony_ci enum intel_pt_param_flags flags; 2558c2ecf20Sopenharmony_ci unsigned int quick; 2568c2ecf20Sopenharmony_ci}; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistruct intel_pt_decoder; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistruct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params); 2618c2ecf20Sopenharmony_civoid intel_pt_decoder_free(struct intel_pt_decoder *decoder); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ciconst struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder); 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ciint intel_pt_fast_forward(struct intel_pt_decoder *decoder, uint64_t timestamp); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ciunsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a, 2688c2ecf20Sopenharmony_ci unsigned char *buf_b, size_t len_b, 2698c2ecf20Sopenharmony_ci bool have_tsc, bool *consecutive); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ciint intel_pt__strerror(int code, char *buf, size_t buflen); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci#endif 274