162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * intel_pt_decoder.h: Intel Processor Trace support 462306a36Sopenharmony_ci * Copyright (c) 2013-2014, Intel Corporation. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#ifndef INCLUDE__INTEL_PT_DECODER_H__ 862306a36Sopenharmony_ci#define INCLUDE__INTEL_PT_DECODER_H__ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <stdint.h> 1162306a36Sopenharmony_ci#include <stddef.h> 1262306a36Sopenharmony_ci#include <stdbool.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/rbtree.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "intel-pt-insn-decoder.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define INTEL_PT_IN_TX (1 << 0) 1962306a36Sopenharmony_ci#define INTEL_PT_ABORT_TX (1 << 1) 2062306a36Sopenharmony_ci#define INTEL_PT_IFLAG (1 << 2) 2162306a36Sopenharmony_ci#define INTEL_PT_ASYNC (1 << 2) 2262306a36Sopenharmony_ci#define INTEL_PT_FUP_IP (1 << 3) 2362306a36Sopenharmony_ci#define INTEL_PT_SAMPLE_IPC (1 << 4) 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cienum intel_pt_sample_type { 2662306a36Sopenharmony_ci INTEL_PT_BRANCH = 1 << 0, 2762306a36Sopenharmony_ci INTEL_PT_INSTRUCTION = 1 << 1, 2862306a36Sopenharmony_ci INTEL_PT_TRANSACTION = 1 << 2, 2962306a36Sopenharmony_ci INTEL_PT_PTW = 1 << 3, 3062306a36Sopenharmony_ci INTEL_PT_MWAIT_OP = 1 << 4, 3162306a36Sopenharmony_ci INTEL_PT_PWR_ENTRY = 1 << 5, 3262306a36Sopenharmony_ci INTEL_PT_EX_STOP = 1 << 6, 3362306a36Sopenharmony_ci INTEL_PT_PWR_EXIT = 1 << 7, 3462306a36Sopenharmony_ci INTEL_PT_CBR_CHG = 1 << 8, 3562306a36Sopenharmony_ci INTEL_PT_TRACE_BEGIN = 1 << 9, 3662306a36Sopenharmony_ci INTEL_PT_TRACE_END = 1 << 10, 3762306a36Sopenharmony_ci INTEL_PT_BLK_ITEMS = 1 << 11, 3862306a36Sopenharmony_ci INTEL_PT_PSB_EVT = 1 << 12, 3962306a36Sopenharmony_ci INTEL_PT_EVT = 1 << 13, 4062306a36Sopenharmony_ci INTEL_PT_IFLAG_CHG = 1 << 14, 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cienum intel_pt_period_type { 4462306a36Sopenharmony_ci INTEL_PT_PERIOD_NONE, 4562306a36Sopenharmony_ci INTEL_PT_PERIOD_INSTRUCTIONS, 4662306a36Sopenharmony_ci INTEL_PT_PERIOD_TICKS, 4762306a36Sopenharmony_ci INTEL_PT_PERIOD_MTC, 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cienum { 5162306a36Sopenharmony_ci INTEL_PT_ERR_NOMEM = 1, 5262306a36Sopenharmony_ci INTEL_PT_ERR_INTERN, 5362306a36Sopenharmony_ci INTEL_PT_ERR_BADPKT, 5462306a36Sopenharmony_ci INTEL_PT_ERR_NODATA, 5562306a36Sopenharmony_ci INTEL_PT_ERR_NOINSN, 5662306a36Sopenharmony_ci INTEL_PT_ERR_MISMAT, 5762306a36Sopenharmony_ci INTEL_PT_ERR_OVR, 5862306a36Sopenharmony_ci INTEL_PT_ERR_LOST, 5962306a36Sopenharmony_ci INTEL_PT_ERR_UNK, 6062306a36Sopenharmony_ci INTEL_PT_ERR_NELOOP, 6162306a36Sopenharmony_ci INTEL_PT_ERR_EPTW, 6262306a36Sopenharmony_ci INTEL_PT_ERR_MAX, 6362306a36Sopenharmony_ci}; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cienum intel_pt_param_flags { 6662306a36Sopenharmony_ci /* 6762306a36Sopenharmony_ci * FUP packet can contain next linear instruction pointer instead of 6862306a36Sopenharmony_ci * current linear instruction pointer. 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_ci INTEL_PT_FUP_WITH_NLIP = 1 << 0, 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cienum intel_pt_blk_type { 7462306a36Sopenharmony_ci INTEL_PT_GP_REGS = 1, 7562306a36Sopenharmony_ci INTEL_PT_PEBS_BASIC = 4, 7662306a36Sopenharmony_ci INTEL_PT_PEBS_MEM = 5, 7762306a36Sopenharmony_ci INTEL_PT_LBR_0 = 8, 7862306a36Sopenharmony_ci INTEL_PT_LBR_1 = 9, 7962306a36Sopenharmony_ci INTEL_PT_LBR_2 = 10, 8062306a36Sopenharmony_ci INTEL_PT_XMM = 16, 8162306a36Sopenharmony_ci INTEL_PT_BLK_TYPE_MAX 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/* 8562306a36Sopenharmony_ci * The block type numbers are not sequential but here they are given sequential 8662306a36Sopenharmony_ci * positions to avoid wasting space for array placement. 8762306a36Sopenharmony_ci */ 8862306a36Sopenharmony_cienum intel_pt_blk_type_pos { 8962306a36Sopenharmony_ci INTEL_PT_GP_REGS_POS, 9062306a36Sopenharmony_ci INTEL_PT_PEBS_BASIC_POS, 9162306a36Sopenharmony_ci INTEL_PT_PEBS_MEM_POS, 9262306a36Sopenharmony_ci INTEL_PT_LBR_0_POS, 9362306a36Sopenharmony_ci INTEL_PT_LBR_1_POS, 9462306a36Sopenharmony_ci INTEL_PT_LBR_2_POS, 9562306a36Sopenharmony_ci INTEL_PT_XMM_POS, 9662306a36Sopenharmony_ci INTEL_PT_BLK_TYPE_CNT 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/* Get the array position for a block type */ 10062306a36Sopenharmony_cistatic inline int intel_pt_blk_type_pos(enum intel_pt_blk_type blk_type) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci#define BLK_TYPE(bt) [INTEL_PT_##bt] = INTEL_PT_##bt##_POS + 1 10362306a36Sopenharmony_ci const int map[INTEL_PT_BLK_TYPE_MAX] = { 10462306a36Sopenharmony_ci BLK_TYPE(GP_REGS), 10562306a36Sopenharmony_ci BLK_TYPE(PEBS_BASIC), 10662306a36Sopenharmony_ci BLK_TYPE(PEBS_MEM), 10762306a36Sopenharmony_ci BLK_TYPE(LBR_0), 10862306a36Sopenharmony_ci BLK_TYPE(LBR_1), 10962306a36Sopenharmony_ci BLK_TYPE(LBR_2), 11062306a36Sopenharmony_ci BLK_TYPE(XMM), 11162306a36Sopenharmony_ci }; 11262306a36Sopenharmony_ci#undef BLK_TYPE 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci return blk_type < INTEL_PT_BLK_TYPE_MAX ? map[blk_type] - 1 : -1; 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci#define INTEL_PT_BLK_ITEM_ID_CNT 32 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci/* 12062306a36Sopenharmony_ci * Use unions so that the block items can be accessed by name or by array index. 12162306a36Sopenharmony_ci * There is an array of 32-bit masks for each block type, which indicate which 12262306a36Sopenharmony_ci * values are present. Then arrays of 32 64-bit values for each block type. 12362306a36Sopenharmony_ci */ 12462306a36Sopenharmony_cistruct intel_pt_blk_items { 12562306a36Sopenharmony_ci union { 12662306a36Sopenharmony_ci uint32_t mask[INTEL_PT_BLK_TYPE_CNT]; 12762306a36Sopenharmony_ci struct { 12862306a36Sopenharmony_ci uint32_t has_rflags:1; 12962306a36Sopenharmony_ci uint32_t has_rip:1; 13062306a36Sopenharmony_ci uint32_t has_rax:1; 13162306a36Sopenharmony_ci uint32_t has_rcx:1; 13262306a36Sopenharmony_ci uint32_t has_rdx:1; 13362306a36Sopenharmony_ci uint32_t has_rbx:1; 13462306a36Sopenharmony_ci uint32_t has_rsp:1; 13562306a36Sopenharmony_ci uint32_t has_rbp:1; 13662306a36Sopenharmony_ci uint32_t has_rsi:1; 13762306a36Sopenharmony_ci uint32_t has_rdi:1; 13862306a36Sopenharmony_ci uint32_t has_r8:1; 13962306a36Sopenharmony_ci uint32_t has_r9:1; 14062306a36Sopenharmony_ci uint32_t has_r10:1; 14162306a36Sopenharmony_ci uint32_t has_r11:1; 14262306a36Sopenharmony_ci uint32_t has_r12:1; 14362306a36Sopenharmony_ci uint32_t has_r13:1; 14462306a36Sopenharmony_ci uint32_t has_r14:1; 14562306a36Sopenharmony_ci uint32_t has_r15:1; 14662306a36Sopenharmony_ci uint32_t has_unused_0:14; 14762306a36Sopenharmony_ci uint32_t has_ip:1; 14862306a36Sopenharmony_ci uint32_t has_applicable_counters:1; 14962306a36Sopenharmony_ci uint32_t has_timestamp:1; 15062306a36Sopenharmony_ci uint32_t has_unused_1:29; 15162306a36Sopenharmony_ci uint32_t has_mem_access_address:1; 15262306a36Sopenharmony_ci uint32_t has_mem_aux_info:1; 15362306a36Sopenharmony_ci uint32_t has_mem_access_latency:1; 15462306a36Sopenharmony_ci uint32_t has_tsx_aux_info:1; 15562306a36Sopenharmony_ci uint32_t has_unused_2:28; 15662306a36Sopenharmony_ci uint32_t has_lbr_0; 15762306a36Sopenharmony_ci uint32_t has_lbr_1; 15862306a36Sopenharmony_ci uint32_t has_lbr_2; 15962306a36Sopenharmony_ci uint32_t has_xmm; 16062306a36Sopenharmony_ci }; 16162306a36Sopenharmony_ci }; 16262306a36Sopenharmony_ci union { 16362306a36Sopenharmony_ci uint64_t val[INTEL_PT_BLK_TYPE_CNT][INTEL_PT_BLK_ITEM_ID_CNT]; 16462306a36Sopenharmony_ci struct { 16562306a36Sopenharmony_ci struct { 16662306a36Sopenharmony_ci uint64_t rflags; 16762306a36Sopenharmony_ci uint64_t rip; 16862306a36Sopenharmony_ci uint64_t rax; 16962306a36Sopenharmony_ci uint64_t rcx; 17062306a36Sopenharmony_ci uint64_t rdx; 17162306a36Sopenharmony_ci uint64_t rbx; 17262306a36Sopenharmony_ci uint64_t rsp; 17362306a36Sopenharmony_ci uint64_t rbp; 17462306a36Sopenharmony_ci uint64_t rsi; 17562306a36Sopenharmony_ci uint64_t rdi; 17662306a36Sopenharmony_ci uint64_t r8; 17762306a36Sopenharmony_ci uint64_t r9; 17862306a36Sopenharmony_ci uint64_t r10; 17962306a36Sopenharmony_ci uint64_t r11; 18062306a36Sopenharmony_ci uint64_t r12; 18162306a36Sopenharmony_ci uint64_t r13; 18262306a36Sopenharmony_ci uint64_t r14; 18362306a36Sopenharmony_ci uint64_t r15; 18462306a36Sopenharmony_ci uint64_t unused_0[INTEL_PT_BLK_ITEM_ID_CNT - 18]; 18562306a36Sopenharmony_ci }; 18662306a36Sopenharmony_ci struct { 18762306a36Sopenharmony_ci uint64_t ip; 18862306a36Sopenharmony_ci uint64_t applicable_counters; 18962306a36Sopenharmony_ci uint64_t timestamp; 19062306a36Sopenharmony_ci uint64_t unused_1[INTEL_PT_BLK_ITEM_ID_CNT - 3]; 19162306a36Sopenharmony_ci }; 19262306a36Sopenharmony_ci struct { 19362306a36Sopenharmony_ci uint64_t mem_access_address; 19462306a36Sopenharmony_ci uint64_t mem_aux_info; 19562306a36Sopenharmony_ci uint64_t mem_access_latency; 19662306a36Sopenharmony_ci uint64_t tsx_aux_info; 19762306a36Sopenharmony_ci uint64_t unused_2[INTEL_PT_BLK_ITEM_ID_CNT - 4]; 19862306a36Sopenharmony_ci }; 19962306a36Sopenharmony_ci uint64_t lbr_0[INTEL_PT_BLK_ITEM_ID_CNT]; 20062306a36Sopenharmony_ci uint64_t lbr_1[INTEL_PT_BLK_ITEM_ID_CNT]; 20162306a36Sopenharmony_ci uint64_t lbr_2[INTEL_PT_BLK_ITEM_ID_CNT]; 20262306a36Sopenharmony_ci uint64_t xmm[INTEL_PT_BLK_ITEM_ID_CNT]; 20362306a36Sopenharmony_ci }; 20462306a36Sopenharmony_ci }; 20562306a36Sopenharmony_ci bool is_32_bit; 20662306a36Sopenharmony_ci}; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistruct intel_pt_vmcs_info { 20962306a36Sopenharmony_ci struct rb_node rb_node; 21062306a36Sopenharmony_ci uint64_t vmcs; 21162306a36Sopenharmony_ci uint64_t tsc_offset; 21262306a36Sopenharmony_ci bool reliable; 21362306a36Sopenharmony_ci bool error_printed; 21462306a36Sopenharmony_ci}; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci/* 21762306a36Sopenharmony_ci * Maximum number of event trace data in one go, assuming at most 1 per type 21862306a36Sopenharmony_ci * and 6-bits of type in the EVD packet. 21962306a36Sopenharmony_ci */ 22062306a36Sopenharmony_ci#define INTEL_PT_MAX_EVDS 64 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci/* Event trace data from EVD packet */ 22362306a36Sopenharmony_cistruct intel_pt_evd { 22462306a36Sopenharmony_ci int type; 22562306a36Sopenharmony_ci uint64_t payload; 22662306a36Sopenharmony_ci}; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistruct intel_pt_state { 22962306a36Sopenharmony_ci enum intel_pt_sample_type type; 23062306a36Sopenharmony_ci bool from_nr; 23162306a36Sopenharmony_ci bool to_nr; 23262306a36Sopenharmony_ci bool from_iflag; 23362306a36Sopenharmony_ci bool to_iflag; 23462306a36Sopenharmony_ci int err; 23562306a36Sopenharmony_ci uint64_t from_ip; 23662306a36Sopenharmony_ci uint64_t to_ip; 23762306a36Sopenharmony_ci uint64_t tot_insn_cnt; 23862306a36Sopenharmony_ci uint64_t tot_cyc_cnt; 23962306a36Sopenharmony_ci uint64_t cycles; 24062306a36Sopenharmony_ci uint64_t timestamp; 24162306a36Sopenharmony_ci uint64_t est_timestamp; 24262306a36Sopenharmony_ci uint64_t trace_nr; 24362306a36Sopenharmony_ci uint64_t ptw_payload; 24462306a36Sopenharmony_ci uint64_t mwait_payload; 24562306a36Sopenharmony_ci uint64_t pwre_payload; 24662306a36Sopenharmony_ci uint64_t pwrx_payload; 24762306a36Sopenharmony_ci uint64_t cbr_payload; 24862306a36Sopenharmony_ci uint64_t psb_offset; 24962306a36Sopenharmony_ci uint32_t cbr; 25062306a36Sopenharmony_ci uint32_t flags; 25162306a36Sopenharmony_ci enum intel_pt_insn_op insn_op; 25262306a36Sopenharmony_ci int insn_len; 25362306a36Sopenharmony_ci char insn[INTEL_PT_INSN_BUF_SZ]; 25462306a36Sopenharmony_ci struct intel_pt_blk_items items; 25562306a36Sopenharmony_ci int cfe_type; 25662306a36Sopenharmony_ci int cfe_vector; 25762306a36Sopenharmony_ci int evd_cnt; 25862306a36Sopenharmony_ci struct intel_pt_evd *evd; 25962306a36Sopenharmony_ci}; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistruct intel_pt_insn; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_cistruct intel_pt_buffer { 26462306a36Sopenharmony_ci const unsigned char *buf; 26562306a36Sopenharmony_ci size_t len; 26662306a36Sopenharmony_ci bool consecutive; 26762306a36Sopenharmony_ci uint64_t ref_timestamp; 26862306a36Sopenharmony_ci uint64_t trace_nr; 26962306a36Sopenharmony_ci}; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_citypedef int (*intel_pt_lookahead_cb_t)(struct intel_pt_buffer *, void *); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_cistruct intel_pt_params { 27462306a36Sopenharmony_ci int (*get_trace)(struct intel_pt_buffer *buffer, void *data); 27562306a36Sopenharmony_ci int (*walk_insn)(struct intel_pt_insn *intel_pt_insn, 27662306a36Sopenharmony_ci uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip, 27762306a36Sopenharmony_ci uint64_t max_insn_cnt, void *data); 27862306a36Sopenharmony_ci bool (*pgd_ip)(uint64_t ip, void *data); 27962306a36Sopenharmony_ci int (*lookahead)(void *data, intel_pt_lookahead_cb_t cb, void *cb_data); 28062306a36Sopenharmony_ci struct intel_pt_vmcs_info *(*findnew_vmcs_info)(void *data, uint64_t vmcs); 28162306a36Sopenharmony_ci void *data; 28262306a36Sopenharmony_ci bool return_compression; 28362306a36Sopenharmony_ci bool branch_enable; 28462306a36Sopenharmony_ci bool vm_time_correlation; 28562306a36Sopenharmony_ci bool vm_tm_corr_dry_run; 28662306a36Sopenharmony_ci uint64_t first_timestamp; 28762306a36Sopenharmony_ci uint64_t ctl; 28862306a36Sopenharmony_ci uint64_t period; 28962306a36Sopenharmony_ci enum intel_pt_period_type period_type; 29062306a36Sopenharmony_ci unsigned max_non_turbo_ratio; 29162306a36Sopenharmony_ci unsigned int mtc_period; 29262306a36Sopenharmony_ci uint32_t tsc_ctc_ratio_n; 29362306a36Sopenharmony_ci uint32_t tsc_ctc_ratio_d; 29462306a36Sopenharmony_ci enum intel_pt_param_flags flags; 29562306a36Sopenharmony_ci unsigned int quick; 29662306a36Sopenharmony_ci int max_loops; 29762306a36Sopenharmony_ci}; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistruct intel_pt_decoder; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_cistruct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params); 30262306a36Sopenharmony_civoid intel_pt_decoder_free(struct intel_pt_decoder *decoder); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ciconst struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ciint intel_pt_fast_forward(struct intel_pt_decoder *decoder, uint64_t timestamp); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ciunsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a, 30962306a36Sopenharmony_ci unsigned char *buf_b, size_t len_b, 31062306a36Sopenharmony_ci bool have_tsc, bool *consecutive, 31162306a36Sopenharmony_ci bool ooo_tsc); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ciint intel_pt__strerror(int code, char *buf, size_t buflen); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_civoid intel_pt_set_first_timestamp(struct intel_pt_decoder *decoder, 31662306a36Sopenharmony_ci uint64_t first_timestamp); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci#endif 319