12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2f4aa0819SAdrian Hunter /*
3f4aa0819SAdrian Hunter  * intel_pt_decoder.c: Intel Processor Trace support
4f4aa0819SAdrian Hunter  * Copyright (c) 2013-2014, Intel Corporation.
5f4aa0819SAdrian Hunter  */
6f4aa0819SAdrian Hunter 
7f4aa0819SAdrian Hunter #ifndef _GNU_SOURCE
8f4aa0819SAdrian Hunter #define _GNU_SOURCE
9f4aa0819SAdrian Hunter #endif
10f4aa0819SAdrian Hunter #include <stdlib.h>
11f4aa0819SAdrian Hunter #include <stdbool.h>
12f4aa0819SAdrian Hunter #include <string.h>
13f4aa0819SAdrian Hunter #include <errno.h>
14f4aa0819SAdrian Hunter #include <stdint.h>
15f4aa0819SAdrian Hunter #include <inttypes.h>
167ea6856dSArnaldo Carvalho de Melo #include <linux/compiler.h>
17fa0d9846SArnaldo Carvalho de Melo #include <linux/string.h>
187f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.h>
19f4aa0819SAdrian Hunter 
205a99d99eSAdrian Hunter #include "../auxtrace.h"
21f4aa0819SAdrian Hunter 
22f4aa0819SAdrian Hunter #include "intel-pt-insn-decoder.h"
23f4aa0819SAdrian Hunter #include "intel-pt-pkt-decoder.h"
24f4aa0819SAdrian Hunter #include "intel-pt-decoder.h"
25f4aa0819SAdrian Hunter #include "intel-pt-log.h"
26f4aa0819SAdrian Hunter 
276af4b600SAdrian Hunter #define BITULL(x) (1ULL << (x))
286af4b600SAdrian Hunter 
296af4b600SAdrian Hunter /* IA32_RTIT_CTL MSR bits */
306af4b600SAdrian Hunter #define INTEL_PT_CYC_ENABLE		BITULL(1)
316af4b600SAdrian Hunter #define INTEL_PT_CYC_THRESHOLD		(BITULL(22) | BITULL(21) | BITULL(20) | BITULL(19))
326af4b600SAdrian Hunter #define INTEL_PT_CYC_THRESHOLD_SHIFT	19
336af4b600SAdrian Hunter 
34f4aa0819SAdrian Hunter #define INTEL_PT_BLK_SIZE 1024
35f4aa0819SAdrian Hunter 
36f4aa0819SAdrian Hunter #define BIT63 (((uint64_t)1 << 63))
37f4aa0819SAdrian Hunter 
38fa8f949dSAdrian Hunter #define SEVEN_BYTES 0xffffffffffffffULL
39fa8f949dSAdrian Hunter 
40fa8f949dSAdrian Hunter #define NO_VMCS 0xffffffffffULL
41fa8f949dSAdrian Hunter 
42f4aa0819SAdrian Hunter #define INTEL_PT_RETURN 1
43f4aa0819SAdrian Hunter 
44b4b046ffSAdrian Hunter /*
45b4b046ffSAdrian Hunter  * Default maximum number of loops with no packets consumed i.e. stuck in a
46b4b046ffSAdrian Hunter  * loop.
47b4b046ffSAdrian Hunter  */
48b4b046ffSAdrian Hunter #define INTEL_PT_MAX_LOOPS 100000
49f4aa0819SAdrian Hunter 
50f4aa0819SAdrian Hunter struct intel_pt_blk {
51f4aa0819SAdrian Hunter 	struct intel_pt_blk *prev;
52f4aa0819SAdrian Hunter 	uint64_t ip[INTEL_PT_BLK_SIZE];
53f4aa0819SAdrian Hunter };
54f4aa0819SAdrian Hunter 
55f4aa0819SAdrian Hunter struct intel_pt_stack {
56f4aa0819SAdrian Hunter 	struct intel_pt_blk *blk;
57f4aa0819SAdrian Hunter 	struct intel_pt_blk *spare;
58f4aa0819SAdrian Hunter 	int pos;
59f4aa0819SAdrian Hunter };
60f4aa0819SAdrian Hunter 
61fa8f949dSAdrian Hunter enum intel_pt_p_once {
62fa8f949dSAdrian Hunter 	INTEL_PT_PRT_ONCE_UNK_VMCS,
63fa8f949dSAdrian Hunter 	INTEL_PT_PRT_ONCE_ERANGE,
64fa8f949dSAdrian Hunter };
65fa8f949dSAdrian Hunter 
66f4aa0819SAdrian Hunter enum intel_pt_pkt_state {
67f4aa0819SAdrian Hunter 	INTEL_PT_STATE_NO_PSB,
68f4aa0819SAdrian Hunter 	INTEL_PT_STATE_NO_IP,
69f4aa0819SAdrian Hunter 	INTEL_PT_STATE_ERR_RESYNC,
70f4aa0819SAdrian Hunter 	INTEL_PT_STATE_IN_SYNC,
7161b6e08dSAdrian Hunter 	INTEL_PT_STATE_TNT_CONT,
72f4aa0819SAdrian Hunter 	INTEL_PT_STATE_TNT,
73f4aa0819SAdrian Hunter 	INTEL_PT_STATE_TIP,
74f4aa0819SAdrian Hunter 	INTEL_PT_STATE_TIP_PGD,
75f4aa0819SAdrian Hunter 	INTEL_PT_STATE_FUP,
76f4aa0819SAdrian Hunter 	INTEL_PT_STATE_FUP_NO_TIP,
77c840cbfeSAdrian Hunter 	INTEL_PT_STATE_FUP_IN_PSB,
787c1b16baSAdrian Hunter 	INTEL_PT_STATE_RESAMPLE,
79fa8f949dSAdrian Hunter 	INTEL_PT_STATE_VM_TIME_CORRELATION,
80f4aa0819SAdrian Hunter };
81f4aa0819SAdrian Hunter 
intel_pt_sample_time(enum intel_pt_pkt_state pkt_state)823f04d98eSAdrian Hunter static inline bool intel_pt_sample_time(enum intel_pt_pkt_state pkt_state)
833f04d98eSAdrian Hunter {
843f04d98eSAdrian Hunter 	switch (pkt_state) {
853f04d98eSAdrian Hunter 	case INTEL_PT_STATE_NO_PSB:
863f04d98eSAdrian Hunter 	case INTEL_PT_STATE_NO_IP:
873f04d98eSAdrian Hunter 	case INTEL_PT_STATE_ERR_RESYNC:
883f04d98eSAdrian Hunter 	case INTEL_PT_STATE_IN_SYNC:
8961b6e08dSAdrian Hunter 	case INTEL_PT_STATE_TNT_CONT:
907c1b16baSAdrian Hunter 	case INTEL_PT_STATE_RESAMPLE:
91fa8f949dSAdrian Hunter 	case INTEL_PT_STATE_VM_TIME_CORRELATION:
923f04d98eSAdrian Hunter 		return true;
9361b6e08dSAdrian Hunter 	case INTEL_PT_STATE_TNT:
943f04d98eSAdrian Hunter 	case INTEL_PT_STATE_TIP:
953f04d98eSAdrian Hunter 	case INTEL_PT_STATE_TIP_PGD:
963f04d98eSAdrian Hunter 	case INTEL_PT_STATE_FUP:
973f04d98eSAdrian Hunter 	case INTEL_PT_STATE_FUP_NO_TIP:
98c840cbfeSAdrian Hunter 	case INTEL_PT_STATE_FUP_IN_PSB:
993f04d98eSAdrian Hunter 		return false;
1003f04d98eSAdrian Hunter 	default:
1013f04d98eSAdrian Hunter 		return true;
1023f04d98eSAdrian Hunter 	};
1033f04d98eSAdrian Hunter }
1043f04d98eSAdrian Hunter 
105f4aa0819SAdrian Hunter #ifdef INTEL_PT_STRICT
106f4aa0819SAdrian Hunter #define INTEL_PT_STATE_ERR1	INTEL_PT_STATE_NO_PSB
107f4aa0819SAdrian Hunter #define INTEL_PT_STATE_ERR2	INTEL_PT_STATE_NO_PSB
108f4aa0819SAdrian Hunter #define INTEL_PT_STATE_ERR3	INTEL_PT_STATE_NO_PSB
109f4aa0819SAdrian Hunter #define INTEL_PT_STATE_ERR4	INTEL_PT_STATE_NO_PSB
110f4aa0819SAdrian Hunter #else
111f4aa0819SAdrian Hunter #define INTEL_PT_STATE_ERR1	(decoder->pkt_state)
112f4aa0819SAdrian Hunter #define INTEL_PT_STATE_ERR2	INTEL_PT_STATE_NO_IP
113f4aa0819SAdrian Hunter #define INTEL_PT_STATE_ERR3	INTEL_PT_STATE_ERR_RESYNC
114f4aa0819SAdrian Hunter #define INTEL_PT_STATE_ERR4	INTEL_PT_STATE_IN_SYNC
115f4aa0819SAdrian Hunter #endif
116f4aa0819SAdrian Hunter 
117f4aa0819SAdrian Hunter struct intel_pt_decoder {
118f4aa0819SAdrian Hunter 	int (*get_trace)(struct intel_pt_buffer *buffer, void *data);
119f4aa0819SAdrian Hunter 	int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,
120f4aa0819SAdrian Hunter 			 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip,
121f4aa0819SAdrian Hunter 			 uint64_t max_insn_cnt, void *data);
1229f1d122bSAdrian Hunter 	bool (*pgd_ip)(uint64_t ip, void *data);
1234d678e90SAdrian Hunter 	int (*lookahead)(void *data, intel_pt_lookahead_cb_t cb, void *cb_data);
1240fc9d338SAdrian Hunter 	struct intel_pt_vmcs_info *(*findnew_vmcs_info)(void *data, uint64_t vmcs);
125f4aa0819SAdrian Hunter 	void *data;
126f4aa0819SAdrian Hunter 	struct intel_pt_state state;
127f4aa0819SAdrian Hunter 	const unsigned char *buf;
128f4aa0819SAdrian Hunter 	size_t len;
129f4aa0819SAdrian Hunter 	bool return_compression;
13083959817SAdrian Hunter 	bool branch_enable;
13179b58424SAdrian Hunter 	bool mtc_insn;
132f4aa0819SAdrian Hunter 	bool pge;
13379b58424SAdrian Hunter 	bool have_tma;
134cc336186SAdrian Hunter 	bool have_cyc;
1353bccbe20SAdrian Hunter 	bool fixup_last_mtc;
136ee14ac0eSAdrian Hunter 	bool have_last_ip;
1379bc668e3SAdrian Hunter 	bool in_psb;
1387c1b16baSAdrian Hunter 	bool hop;
139347a7389SAdrian Hunter 	bool leap;
140d7015e50SAdrian Hunter 	bool emulated_ptwrite;
141fa8f949dSAdrian Hunter 	bool vm_time_correlation;
142fa8f949dSAdrian Hunter 	bool vm_tm_corr_dry_run;
143fa8f949dSAdrian Hunter 	bool vm_tm_corr_reliable;
144fa8f949dSAdrian Hunter 	bool vm_tm_corr_same_buf;
145fa8f949dSAdrian Hunter 	bool vm_tm_corr_continuous;
14680a03886SAdrian Hunter 	bool nr;
14780a03886SAdrian Hunter 	bool next_nr;
148cf0c98e2SAdrian Hunter 	bool iflag;
149cf0c98e2SAdrian Hunter 	bool next_iflag;
1509fb52336SAdrian Hunter 	enum intel_pt_param_flags flags;
151f4aa0819SAdrian Hunter 	uint64_t pos;
152f4aa0819SAdrian Hunter 	uint64_t last_ip;
153f4aa0819SAdrian Hunter 	uint64_t ip;
15490af7555SAdrian Hunter 	uint64_t pip_payload;
155f4aa0819SAdrian Hunter 	uint64_t timestamp;
156f4aa0819SAdrian Hunter 	uint64_t tsc_timestamp;
157f4aa0819SAdrian Hunter 	uint64_t ref_timestamp;
158a7fa19f5SAdrian Hunter 	uint64_t buf_timestamp;
1593f04d98eSAdrian Hunter 	uint64_t sample_timestamp;
160f4aa0819SAdrian Hunter 	uint64_t ret_addr;
16179b58424SAdrian Hunter 	uint64_t ctc_timestamp;
16279b58424SAdrian Hunter 	uint64_t ctc_delta;
163cc336186SAdrian Hunter 	uint64_t cycle_cnt;
164cc336186SAdrian Hunter 	uint64_t cyc_ref_timestamp;
1655ac35d77SAdrian Hunter 	uint64_t first_timestamp;
166fa8f949dSAdrian Hunter 	uint64_t last_reliable_timestamp;
167fa8f949dSAdrian Hunter 	uint64_t vmcs;
168fa8f949dSAdrian Hunter 	uint64_t print_once;
169fa8f949dSAdrian Hunter 	uint64_t last_ctc;
17079b58424SAdrian Hunter 	uint32_t last_mtc;
17179b58424SAdrian Hunter 	uint32_t tsc_ctc_ratio_n;
17279b58424SAdrian Hunter 	uint32_t tsc_ctc_ratio_d;
17379b58424SAdrian Hunter 	uint32_t tsc_ctc_mult;
17479b58424SAdrian Hunter 	uint32_t tsc_slip;
17579b58424SAdrian Hunter 	uint32_t ctc_rem_mask;
17679b58424SAdrian Hunter 	int mtc_shift;
177f4aa0819SAdrian Hunter 	struct intel_pt_stack stack;
178f4aa0819SAdrian Hunter 	enum intel_pt_pkt_state pkt_state;
179edff7809SAdrian Hunter 	enum intel_pt_pkt_ctx pkt_ctx;
1804c35595eSAdrian Hunter 	enum intel_pt_pkt_ctx prev_pkt_ctx;
1814c35595eSAdrian Hunter 	enum intel_pt_blk_type blk_type;
1824c35595eSAdrian Hunter 	int blk_type_pos;
183f4aa0819SAdrian Hunter 	struct intel_pt_pkt packet;
184f4aa0819SAdrian Hunter 	struct intel_pt_pkt tnt;
185f4aa0819SAdrian Hunter 	int pkt_step;
186f4aa0819SAdrian Hunter 	int pkt_len;
187cc336186SAdrian Hunter 	int last_packet_type;
188f4aa0819SAdrian Hunter 	unsigned int cbr;
1890a7c700dSAdrian Hunter 	unsigned int cbr_seen;
190f4aa0819SAdrian Hunter 	unsigned int max_non_turbo_ratio;
191cc336186SAdrian Hunter 	double max_non_turbo_ratio_fp;
192cc336186SAdrian Hunter 	double cbr_cyc_to_tsc;
193cc336186SAdrian Hunter 	double calc_cyc_to_tsc;
194cc336186SAdrian Hunter 	bool have_calc_cyc_to_tsc;
195f4aa0819SAdrian Hunter 	int exec_mode;
196f4aa0819SAdrian Hunter 	unsigned int insn_bytes;
197f4aa0819SAdrian Hunter 	uint64_t period;
198f4aa0819SAdrian Hunter 	enum intel_pt_period_type period_type;
1992a21d036SAdrian Hunter 	uint64_t tot_insn_cnt;
200f4aa0819SAdrian Hunter 	uint64_t period_insn_cnt;
201f4aa0819SAdrian Hunter 	uint64_t period_mask;
202f4aa0819SAdrian Hunter 	uint64_t period_ticks;
203f4aa0819SAdrian Hunter 	uint64_t last_masked_timestamp;
2047b4b4f83SAdrian Hunter 	uint64_t tot_cyc_cnt;
2057b4b4f83SAdrian Hunter 	uint64_t sample_tot_cyc_cnt;
2063f055167SAdrian Hunter 	uint64_t base_cyc_cnt;
2073f055167SAdrian Hunter 	uint64_t cyc_cnt_timestamp;
2086af4b600SAdrian Hunter 	uint64_t ctl;
2096af4b600SAdrian Hunter 	uint64_t cyc_threshold;
2103f055167SAdrian Hunter 	double tsc_to_cyc;
211f4aa0819SAdrian Hunter 	bool continuous_period;
212f4aa0819SAdrian Hunter 	bool overflow;
213f4aa0819SAdrian Hunter 	bool set_fup_tx_flags;
214a472e65fSAdrian Hunter 	bool set_fup_ptw;
215a472e65fSAdrian Hunter 	bool set_fup_mwait;
216a472e65fSAdrian Hunter 	bool set_fup_pwre;
217a472e65fSAdrian Hunter 	bool set_fup_exstop;
2184c35595eSAdrian Hunter 	bool set_fup_bep;
2193733a98bSAdrian Hunter 	bool set_fup_cfe_ip;
2203733a98bSAdrian Hunter 	bool set_fup_cfe;
221cf0c98e2SAdrian Hunter 	bool set_fup_mode_exec;
2227b4b4f83SAdrian Hunter 	bool sample_cyc;
223f4aa0819SAdrian Hunter 	unsigned int fup_tx_flags;
224f4aa0819SAdrian Hunter 	unsigned int tx_flags;
225a472e65fSAdrian Hunter 	uint64_t fup_ptw_payload;
226a472e65fSAdrian Hunter 	uint64_t fup_mwait_payload;
227a472e65fSAdrian Hunter 	uint64_t fup_pwre_payload;
2280a7c700dSAdrian Hunter 	uint64_t cbr_payload;
229f4aa0819SAdrian Hunter 	uint64_t timestamp_insn_cnt;
2303f04d98eSAdrian Hunter 	uint64_t sample_insn_cnt;
231f4aa0819SAdrian Hunter 	uint64_t stuck_ip;
2323733a98bSAdrian Hunter 	struct intel_pt_pkt fup_cfe_pkt;
233b4b046ffSAdrian Hunter 	int max_loops;
234f4aa0819SAdrian Hunter 	int no_progress;
235f4aa0819SAdrian Hunter 	int stuck_ip_prd;
236f4aa0819SAdrian Hunter 	int stuck_ip_cnt;
237c840cbfeSAdrian Hunter 	uint64_t psb_ip;
238f4aa0819SAdrian Hunter 	const unsigned char *next_buf;
239f4aa0819SAdrian Hunter 	size_t next_len;
240f4aa0819SAdrian Hunter 	unsigned char temp_buf[INTEL_PT_PKT_MAX_SZ];
2413733a98bSAdrian Hunter 	int evd_cnt;
2423733a98bSAdrian Hunter 	struct intel_pt_evd evd[INTEL_PT_MAX_EVDS];
243f4aa0819SAdrian Hunter };
244f4aa0819SAdrian Hunter 
intel_pt_lower_power_of_2(uint64_t x)245f4aa0819SAdrian Hunter static uint64_t intel_pt_lower_power_of_2(uint64_t x)
246f4aa0819SAdrian Hunter {
247f4aa0819SAdrian Hunter 	int i;
248f4aa0819SAdrian Hunter 
249f4aa0819SAdrian Hunter 	for (i = 0; x != 1; i++)
250f4aa0819SAdrian Hunter 		x >>= 1;
251f4aa0819SAdrian Hunter 
252f4aa0819SAdrian Hunter 	return x << i;
253f4aa0819SAdrian Hunter }
254f4aa0819SAdrian Hunter 
255fa8f949dSAdrian Hunter __printf(1, 2)
p_log(const char * fmt,...)256fa8f949dSAdrian Hunter static void p_log(const char *fmt, ...)
257fa8f949dSAdrian Hunter {
258fa8f949dSAdrian Hunter 	char buf[512];
259fa8f949dSAdrian Hunter 	va_list args;
260fa8f949dSAdrian Hunter 
261fa8f949dSAdrian Hunter 	va_start(args, fmt);
262fa8f949dSAdrian Hunter 	vsnprintf(buf, sizeof(buf), fmt, args);
263fa8f949dSAdrian Hunter 	va_end(args);
264fa8f949dSAdrian Hunter 
265fa8f949dSAdrian Hunter 	fprintf(stderr, "%s\n", buf);
266fa8f949dSAdrian Hunter 	intel_pt_log("%s\n", buf);
267fa8f949dSAdrian Hunter }
268fa8f949dSAdrian Hunter 
intel_pt_print_once(struct intel_pt_decoder * decoder,enum intel_pt_p_once id)269fa8f949dSAdrian Hunter static bool intel_pt_print_once(struct intel_pt_decoder *decoder,
270fa8f949dSAdrian Hunter 				enum intel_pt_p_once id)
271fa8f949dSAdrian Hunter {
272fa8f949dSAdrian Hunter 	uint64_t bit = 1ULL << id;
273fa8f949dSAdrian Hunter 
274fa8f949dSAdrian Hunter 	if (decoder->print_once & bit)
275fa8f949dSAdrian Hunter 		return false;
276fa8f949dSAdrian Hunter 	decoder->print_once |= bit;
277fa8f949dSAdrian Hunter 	return true;
278fa8f949dSAdrian Hunter }
279fa8f949dSAdrian Hunter 
intel_pt_cyc_threshold(uint64_t ctl)2806af4b600SAdrian Hunter static uint64_t intel_pt_cyc_threshold(uint64_t ctl)
2816af4b600SAdrian Hunter {
2826af4b600SAdrian Hunter 	if (!(ctl & INTEL_PT_CYC_ENABLE))
2836af4b600SAdrian Hunter 		return 0;
2846af4b600SAdrian Hunter 
2856af4b600SAdrian Hunter 	return (ctl & INTEL_PT_CYC_THRESHOLD) >> INTEL_PT_CYC_THRESHOLD_SHIFT;
2866af4b600SAdrian Hunter }
2876af4b600SAdrian Hunter 
intel_pt_setup_period(struct intel_pt_decoder * decoder)288f4aa0819SAdrian Hunter static void intel_pt_setup_period(struct intel_pt_decoder *decoder)
289f4aa0819SAdrian Hunter {
290f4aa0819SAdrian Hunter 	if (decoder->period_type == INTEL_PT_PERIOD_TICKS) {
291f4aa0819SAdrian Hunter 		uint64_t period;
292f4aa0819SAdrian Hunter 
293f4aa0819SAdrian Hunter 		period = intel_pt_lower_power_of_2(decoder->period);
294f4aa0819SAdrian Hunter 		decoder->period_mask  = ~(period - 1);
295f4aa0819SAdrian Hunter 		decoder->period_ticks = period;
296f4aa0819SAdrian Hunter 	}
297f4aa0819SAdrian Hunter }
298f4aa0819SAdrian Hunter 
multdiv(uint64_t t,uint32_t n,uint32_t d)29979b58424SAdrian Hunter static uint64_t multdiv(uint64_t t, uint32_t n, uint32_t d)
30079b58424SAdrian Hunter {
30179b58424SAdrian Hunter 	if (!d)
30279b58424SAdrian Hunter 		return 0;
30379b58424SAdrian Hunter 	return (t / d) * n + ((t % d) * n) / d;
30479b58424SAdrian Hunter }
30579b58424SAdrian Hunter 
intel_pt_decoder_new(struct intel_pt_params * params)306f4aa0819SAdrian Hunter struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
307f4aa0819SAdrian Hunter {
308f4aa0819SAdrian Hunter 	struct intel_pt_decoder *decoder;
309f4aa0819SAdrian Hunter 
310f4aa0819SAdrian Hunter 	if (!params->get_trace || !params->walk_insn)
311f4aa0819SAdrian Hunter 		return NULL;
312f4aa0819SAdrian Hunter 
313f4aa0819SAdrian Hunter 	decoder = zalloc(sizeof(struct intel_pt_decoder));
314f4aa0819SAdrian Hunter 	if (!decoder)
315f4aa0819SAdrian Hunter 		return NULL;
316f4aa0819SAdrian Hunter 
317f4aa0819SAdrian Hunter 	decoder->get_trace          = params->get_trace;
318f4aa0819SAdrian Hunter 	decoder->walk_insn          = params->walk_insn;
3199f1d122bSAdrian Hunter 	decoder->pgd_ip             = params->pgd_ip;
3204d678e90SAdrian Hunter 	decoder->lookahead          = params->lookahead;
3210fc9d338SAdrian Hunter 	decoder->findnew_vmcs_info  = params->findnew_vmcs_info;
322f4aa0819SAdrian Hunter 	decoder->data               = params->data;
323f4aa0819SAdrian Hunter 	decoder->return_compression = params->return_compression;
32483959817SAdrian Hunter 	decoder->branch_enable      = params->branch_enable;
3257c1b16baSAdrian Hunter 	decoder->hop                = params->quick >= 1;
326347a7389SAdrian Hunter 	decoder->leap               = params->quick >= 2;
327fa8f949dSAdrian Hunter 	decoder->vm_time_correlation = params->vm_time_correlation;
328fa8f949dSAdrian Hunter 	decoder->vm_tm_corr_dry_run = params->vm_tm_corr_dry_run;
3295ac35d77SAdrian Hunter 	decoder->first_timestamp    = params->first_timestamp;
330fa8f949dSAdrian Hunter 	decoder->last_reliable_timestamp = params->first_timestamp;
331b4b046ffSAdrian Hunter 	decoder->max_loops          = params->max_loops ? params->max_loops : INTEL_PT_MAX_LOOPS;
332f4aa0819SAdrian Hunter 
3339fb52336SAdrian Hunter 	decoder->flags              = params->flags;
3349fb52336SAdrian Hunter 
3356af4b600SAdrian Hunter 	decoder->ctl                = params->ctl;
336f4aa0819SAdrian Hunter 	decoder->period             = params->period;
337f4aa0819SAdrian Hunter 	decoder->period_type        = params->period_type;
338f4aa0819SAdrian Hunter 
339f4aa0819SAdrian Hunter 	decoder->max_non_turbo_ratio    = params->max_non_turbo_ratio;
340cc336186SAdrian Hunter 	decoder->max_non_turbo_ratio_fp = params->max_non_turbo_ratio;
341f4aa0819SAdrian Hunter 
3426af4b600SAdrian Hunter 	decoder->cyc_threshold = intel_pt_cyc_threshold(decoder->ctl);
3436af4b600SAdrian Hunter 
344f4aa0819SAdrian Hunter 	intel_pt_setup_period(decoder);
345f4aa0819SAdrian Hunter 
34679b58424SAdrian Hunter 	decoder->mtc_shift = params->mtc_period;
34779b58424SAdrian Hunter 	decoder->ctc_rem_mask = (1 << decoder->mtc_shift) - 1;
34879b58424SAdrian Hunter 
34979b58424SAdrian Hunter 	decoder->tsc_ctc_ratio_n = params->tsc_ctc_ratio_n;
35079b58424SAdrian Hunter 	decoder->tsc_ctc_ratio_d = params->tsc_ctc_ratio_d;
35179b58424SAdrian Hunter 
35279b58424SAdrian Hunter 	if (!decoder->tsc_ctc_ratio_n)
35379b58424SAdrian Hunter 		decoder->tsc_ctc_ratio_d = 0;
35479b58424SAdrian Hunter 
35579b58424SAdrian Hunter 	if (decoder->tsc_ctc_ratio_d) {
35679b58424SAdrian Hunter 		if (!(decoder->tsc_ctc_ratio_n % decoder->tsc_ctc_ratio_d))
35779b58424SAdrian Hunter 			decoder->tsc_ctc_mult = decoder->tsc_ctc_ratio_n /
35879b58424SAdrian Hunter 						decoder->tsc_ctc_ratio_d;
359f3b4e06bSAdrian Hunter 	}
36079b58424SAdrian Hunter 
36179b58424SAdrian Hunter 	/*
362f3b4e06bSAdrian Hunter 	 * A TSC packet can slip past MTC packets so that the timestamp appears
363f3b4e06bSAdrian Hunter 	 * to go backwards. One estimate is that can be up to about 40 CPU
364f3b4e06bSAdrian Hunter 	 * cycles, which is certainly less than 0x1000 TSC ticks, but accept
365f3b4e06bSAdrian Hunter 	 * slippage an order of magnitude more to be on the safe side.
36679b58424SAdrian Hunter 	 */
367f3b4e06bSAdrian Hunter 	decoder->tsc_slip = 0x10000;
36879b58424SAdrian Hunter 
36979b58424SAdrian Hunter 	intel_pt_log("timestamp: mtc_shift %u\n", decoder->mtc_shift);
37079b58424SAdrian Hunter 	intel_pt_log("timestamp: tsc_ctc_ratio_n %u\n", decoder->tsc_ctc_ratio_n);
37179b58424SAdrian Hunter 	intel_pt_log("timestamp: tsc_ctc_ratio_d %u\n", decoder->tsc_ctc_ratio_d);
37279b58424SAdrian Hunter 	intel_pt_log("timestamp: tsc_ctc_mult %u\n", decoder->tsc_ctc_mult);
37379b58424SAdrian Hunter 	intel_pt_log("timestamp: tsc_slip %#x\n", decoder->tsc_slip);
37479b58424SAdrian Hunter 
3757c1b16baSAdrian Hunter 	if (decoder->hop)
3767c1b16baSAdrian Hunter 		intel_pt_log("Hop mode: decoding FUP and TIPs, but not TNT\n");
3777c1b16baSAdrian Hunter 
378f4aa0819SAdrian Hunter 	return decoder;
379f4aa0819SAdrian Hunter }
380f4aa0819SAdrian Hunter 
intel_pt_set_first_timestamp(struct intel_pt_decoder * decoder,uint64_t first_timestamp)3815ac35d77SAdrian Hunter void intel_pt_set_first_timestamp(struct intel_pt_decoder *decoder,
3825ac35d77SAdrian Hunter 				  uint64_t first_timestamp)
3835ac35d77SAdrian Hunter {
3845ac35d77SAdrian Hunter 	decoder->first_timestamp = first_timestamp;
3855ac35d77SAdrian Hunter }
3865ac35d77SAdrian Hunter 
intel_pt_pop_blk(struct intel_pt_stack * stack)387f4aa0819SAdrian Hunter static void intel_pt_pop_blk(struct intel_pt_stack *stack)
388f4aa0819SAdrian Hunter {
389f4aa0819SAdrian Hunter 	struct intel_pt_blk *blk = stack->blk;
390f4aa0819SAdrian Hunter 
391f4aa0819SAdrian Hunter 	stack->blk = blk->prev;
392f4aa0819SAdrian Hunter 	if (!stack->spare)
393f4aa0819SAdrian Hunter 		stack->spare = blk;
394f4aa0819SAdrian Hunter 	else
395f4aa0819SAdrian Hunter 		free(blk);
396f4aa0819SAdrian Hunter }
397f4aa0819SAdrian Hunter 
intel_pt_pop(struct intel_pt_stack * stack)398f4aa0819SAdrian Hunter static uint64_t intel_pt_pop(struct intel_pt_stack *stack)
399f4aa0819SAdrian Hunter {
400f4aa0819SAdrian Hunter 	if (!stack->pos) {
401f4aa0819SAdrian Hunter 		if (!stack->blk)
402f4aa0819SAdrian Hunter 			return 0;
403f4aa0819SAdrian Hunter 		intel_pt_pop_blk(stack);
404f4aa0819SAdrian Hunter 		if (!stack->blk)
405f4aa0819SAdrian Hunter 			return 0;
406f4aa0819SAdrian Hunter 		stack->pos = INTEL_PT_BLK_SIZE;
407f4aa0819SAdrian Hunter 	}
408f4aa0819SAdrian Hunter 	return stack->blk->ip[--stack->pos];
409f4aa0819SAdrian Hunter }
410f4aa0819SAdrian Hunter 
intel_pt_alloc_blk(struct intel_pt_stack * stack)411f4aa0819SAdrian Hunter static int intel_pt_alloc_blk(struct intel_pt_stack *stack)
412f4aa0819SAdrian Hunter {
413f4aa0819SAdrian Hunter 	struct intel_pt_blk *blk;
414f4aa0819SAdrian Hunter 
415f4aa0819SAdrian Hunter 	if (stack->spare) {
416f4aa0819SAdrian Hunter 		blk = stack->spare;
417f4aa0819SAdrian Hunter 		stack->spare = NULL;
418f4aa0819SAdrian Hunter 	} else {
419f4aa0819SAdrian Hunter 		blk = malloc(sizeof(struct intel_pt_blk));
420f4aa0819SAdrian Hunter 		if (!blk)
421f4aa0819SAdrian Hunter 			return -ENOMEM;
422f4aa0819SAdrian Hunter 	}
423f4aa0819SAdrian Hunter 
424f4aa0819SAdrian Hunter 	blk->prev = stack->blk;
425f4aa0819SAdrian Hunter 	stack->blk = blk;
426f4aa0819SAdrian Hunter 	stack->pos = 0;
427f4aa0819SAdrian Hunter 	return 0;
428f4aa0819SAdrian Hunter }
429f4aa0819SAdrian Hunter 
intel_pt_push(struct intel_pt_stack * stack,uint64_t ip)430f4aa0819SAdrian Hunter static int intel_pt_push(struct intel_pt_stack *stack, uint64_t ip)
431f4aa0819SAdrian Hunter {
432f4aa0819SAdrian Hunter 	int err;
433f4aa0819SAdrian Hunter 
434f4aa0819SAdrian Hunter 	if (!stack->blk || stack->pos == INTEL_PT_BLK_SIZE) {
435f4aa0819SAdrian Hunter 		err = intel_pt_alloc_blk(stack);
436f4aa0819SAdrian Hunter 		if (err)
437f4aa0819SAdrian Hunter 			return err;
438f4aa0819SAdrian Hunter 	}
439f4aa0819SAdrian Hunter 
440f4aa0819SAdrian Hunter 	stack->blk->ip[stack->pos++] = ip;
441f4aa0819SAdrian Hunter 	return 0;
442f4aa0819SAdrian Hunter }
443f4aa0819SAdrian Hunter 
intel_pt_clear_stack(struct intel_pt_stack * stack)444f4aa0819SAdrian Hunter static void intel_pt_clear_stack(struct intel_pt_stack *stack)
445f4aa0819SAdrian Hunter {
446f4aa0819SAdrian Hunter 	while (stack->blk)
447f4aa0819SAdrian Hunter 		intel_pt_pop_blk(stack);
448f4aa0819SAdrian Hunter 	stack->pos = 0;
449f4aa0819SAdrian Hunter }
450f4aa0819SAdrian Hunter 
intel_pt_free_stack(struct intel_pt_stack * stack)451f4aa0819SAdrian Hunter static void intel_pt_free_stack(struct intel_pt_stack *stack)
452f4aa0819SAdrian Hunter {
453f4aa0819SAdrian Hunter 	intel_pt_clear_stack(stack);
454f4aa0819SAdrian Hunter 	zfree(&stack->blk);
455f4aa0819SAdrian Hunter 	zfree(&stack->spare);
456f4aa0819SAdrian Hunter }
457f4aa0819SAdrian Hunter 
intel_pt_decoder_free(struct intel_pt_decoder * decoder)458f4aa0819SAdrian Hunter void intel_pt_decoder_free(struct intel_pt_decoder *decoder)
459f4aa0819SAdrian Hunter {
460f4aa0819SAdrian Hunter 	intel_pt_free_stack(&decoder->stack);
461f4aa0819SAdrian Hunter 	free(decoder);
462f4aa0819SAdrian Hunter }
463f4aa0819SAdrian Hunter 
intel_pt_ext_err(int code)464f4aa0819SAdrian Hunter static int intel_pt_ext_err(int code)
465f4aa0819SAdrian Hunter {
466f4aa0819SAdrian Hunter 	switch (code) {
467f4aa0819SAdrian Hunter 	case -ENOMEM:
468f4aa0819SAdrian Hunter 		return INTEL_PT_ERR_NOMEM;
469f4aa0819SAdrian Hunter 	case -ENOSYS:
470f4aa0819SAdrian Hunter 		return INTEL_PT_ERR_INTERN;
471f4aa0819SAdrian Hunter 	case -EBADMSG:
472f4aa0819SAdrian Hunter 		return INTEL_PT_ERR_BADPKT;
473f4aa0819SAdrian Hunter 	case -ENODATA:
474f4aa0819SAdrian Hunter 		return INTEL_PT_ERR_NODATA;
475f4aa0819SAdrian Hunter 	case -EILSEQ:
476f4aa0819SAdrian Hunter 		return INTEL_PT_ERR_NOINSN;
477f4aa0819SAdrian Hunter 	case -ENOENT:
478f4aa0819SAdrian Hunter 		return INTEL_PT_ERR_MISMAT;
479f4aa0819SAdrian Hunter 	case -EOVERFLOW:
480f4aa0819SAdrian Hunter 		return INTEL_PT_ERR_OVR;
481f4aa0819SAdrian Hunter 	case -ENOSPC:
482f4aa0819SAdrian Hunter 		return INTEL_PT_ERR_LOST;
483f4aa0819SAdrian Hunter 	case -ELOOP:
484f4aa0819SAdrian Hunter 		return INTEL_PT_ERR_NELOOP;
485d7015e50SAdrian Hunter 	case -ECONNRESET:
486d7015e50SAdrian Hunter 		return INTEL_PT_ERR_EPTW;
487f4aa0819SAdrian Hunter 	default:
488f4aa0819SAdrian Hunter 		return INTEL_PT_ERR_UNK;
489f4aa0819SAdrian Hunter 	}
490f4aa0819SAdrian Hunter }
491f4aa0819SAdrian Hunter 
492f4aa0819SAdrian Hunter static const char *intel_pt_err_msgs[] = {
493f4aa0819SAdrian Hunter 	[INTEL_PT_ERR_NOMEM]  = "Memory allocation failed",
494f4aa0819SAdrian Hunter 	[INTEL_PT_ERR_INTERN] = "Internal error",
495f4aa0819SAdrian Hunter 	[INTEL_PT_ERR_BADPKT] = "Bad packet",
496f4aa0819SAdrian Hunter 	[INTEL_PT_ERR_NODATA] = "No more data",
497f4aa0819SAdrian Hunter 	[INTEL_PT_ERR_NOINSN] = "Failed to get instruction",
498f4aa0819SAdrian Hunter 	[INTEL_PT_ERR_MISMAT] = "Trace doesn't match instruction",
499f4aa0819SAdrian Hunter 	[INTEL_PT_ERR_OVR]    = "Overflow packet",
500f4aa0819SAdrian Hunter 	[INTEL_PT_ERR_LOST]   = "Lost trace data",
501f4aa0819SAdrian Hunter 	[INTEL_PT_ERR_UNK]    = "Unknown error!",
502b4b046ffSAdrian Hunter 	[INTEL_PT_ERR_NELOOP] = "Never-ending loop (refer perf config intel-pt.max-loops)",
503d7015e50SAdrian Hunter 	[INTEL_PT_ERR_EPTW]   = "Broken emulated ptwrite",
504f4aa0819SAdrian Hunter };
505f4aa0819SAdrian Hunter 
intel_pt__strerror(int code,char * buf,size_t buflen)506f4aa0819SAdrian Hunter int intel_pt__strerror(int code, char *buf, size_t buflen)
507f4aa0819SAdrian Hunter {
508c0664893SColin Ian King 	if (code < 1 || code >= INTEL_PT_ERR_MAX)
509f4aa0819SAdrian Hunter 		code = INTEL_PT_ERR_UNK;
510f4aa0819SAdrian Hunter 	strlcpy(buf, intel_pt_err_msgs[code], buflen);
511f4aa0819SAdrian Hunter 	return 0;
512f4aa0819SAdrian Hunter }
513f4aa0819SAdrian Hunter 
intel_pt_calc_ip(const struct intel_pt_pkt * packet,uint64_t last_ip)514e1717e04SAdrian Hunter static uint64_t intel_pt_calc_ip(const struct intel_pt_pkt *packet,
515f4aa0819SAdrian Hunter 				 uint64_t last_ip)
516f4aa0819SAdrian Hunter {
517f4aa0819SAdrian Hunter 	uint64_t ip;
518f4aa0819SAdrian Hunter 
519f4aa0819SAdrian Hunter 	switch (packet->count) {
520e1717e04SAdrian Hunter 	case 1:
521f4aa0819SAdrian Hunter 		ip = (last_ip & (uint64_t)0xffffffffffff0000ULL) |
522f4aa0819SAdrian Hunter 		     packet->payload;
523f4aa0819SAdrian Hunter 		break;
524e1717e04SAdrian Hunter 	case 2:
525f4aa0819SAdrian Hunter 		ip = (last_ip & (uint64_t)0xffffffff00000000ULL) |
526f4aa0819SAdrian Hunter 		     packet->payload;
527f4aa0819SAdrian Hunter 		break;
528e1717e04SAdrian Hunter 	case 3:
529e1717e04SAdrian Hunter 		ip = packet->payload;
530e1717e04SAdrian Hunter 		/* Sign-extend 6-byte ip */
531e1717e04SAdrian Hunter 		if (ip & (uint64_t)0x800000000000ULL)
532e1717e04SAdrian Hunter 			ip |= (uint64_t)0xffff000000000000ULL;
533e1717e04SAdrian Hunter 		break;
534e1717e04SAdrian Hunter 	case 4:
535e1717e04SAdrian Hunter 		ip = (last_ip & (uint64_t)0xffff000000000000ULL) |
536e1717e04SAdrian Hunter 		     packet->payload;
537e1717e04SAdrian Hunter 		break;
538f4aa0819SAdrian Hunter 	case 6:
539f4aa0819SAdrian Hunter 		ip = packet->payload;
540f4aa0819SAdrian Hunter 		break;
541f4aa0819SAdrian Hunter 	default:
542f4aa0819SAdrian Hunter 		return 0;
543f4aa0819SAdrian Hunter 	}
544f4aa0819SAdrian Hunter 
545f4aa0819SAdrian Hunter 	return ip;
546f4aa0819SAdrian Hunter }
547f4aa0819SAdrian Hunter 
intel_pt_set_last_ip(struct intel_pt_decoder * decoder)548f4aa0819SAdrian Hunter static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder)
549f4aa0819SAdrian Hunter {
550e1717e04SAdrian Hunter 	decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip);
551ee14ac0eSAdrian Hunter 	decoder->have_last_ip = true;
552f4aa0819SAdrian Hunter }
553f4aa0819SAdrian Hunter 
intel_pt_set_ip(struct intel_pt_decoder * decoder)554f4aa0819SAdrian Hunter static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder)
555f4aa0819SAdrian Hunter {
556f4aa0819SAdrian Hunter 	intel_pt_set_last_ip(decoder);
557f4aa0819SAdrian Hunter 	decoder->ip = decoder->last_ip;
558f4aa0819SAdrian Hunter }
559f4aa0819SAdrian Hunter 
intel_pt_decoder_log_packet(struct intel_pt_decoder * decoder)560f4aa0819SAdrian Hunter static void intel_pt_decoder_log_packet(struct intel_pt_decoder *decoder)
561f4aa0819SAdrian Hunter {
562f4aa0819SAdrian Hunter 	intel_pt_log_packet(&decoder->packet, decoder->pkt_len, decoder->pos,
563f4aa0819SAdrian Hunter 			    decoder->buf);
564f4aa0819SAdrian Hunter }
565f4aa0819SAdrian Hunter 
intel_pt_bug(struct intel_pt_decoder * decoder)566f4aa0819SAdrian Hunter static int intel_pt_bug(struct intel_pt_decoder *decoder)
567f4aa0819SAdrian Hunter {
568f4aa0819SAdrian Hunter 	intel_pt_log("ERROR: Internal error\n");
569f4aa0819SAdrian Hunter 	decoder->pkt_state = INTEL_PT_STATE_NO_PSB;
570f4aa0819SAdrian Hunter 	return -ENOSYS;
571f4aa0819SAdrian Hunter }
572f4aa0819SAdrian Hunter 
intel_pt_clear_tx_flags(struct intel_pt_decoder * decoder)573f4aa0819SAdrian Hunter static inline void intel_pt_clear_tx_flags(struct intel_pt_decoder *decoder)
574f4aa0819SAdrian Hunter {
575f4aa0819SAdrian Hunter 	decoder->tx_flags = 0;
576f4aa0819SAdrian Hunter }
577f4aa0819SAdrian Hunter 
intel_pt_update_in_tx(struct intel_pt_decoder * decoder)578f4aa0819SAdrian Hunter static inline void intel_pt_update_in_tx(struct intel_pt_decoder *decoder)
579f4aa0819SAdrian Hunter {
580f4aa0819SAdrian Hunter 	decoder->tx_flags = decoder->packet.payload & INTEL_PT_IN_TX;
581f4aa0819SAdrian Hunter }
582f4aa0819SAdrian Hunter 
intel_pt_update_pip(struct intel_pt_decoder * decoder)58380a03886SAdrian Hunter static inline void intel_pt_update_pip(struct intel_pt_decoder *decoder)
58480a03886SAdrian Hunter {
58580a03886SAdrian Hunter 	decoder->pip_payload = decoder->packet.payload;
58680a03886SAdrian Hunter }
58780a03886SAdrian Hunter 
intel_pt_update_nr(struct intel_pt_decoder * decoder)58880a03886SAdrian Hunter static inline void intel_pt_update_nr(struct intel_pt_decoder *decoder)
58980a03886SAdrian Hunter {
59080a03886SAdrian Hunter 	decoder->next_nr = decoder->pip_payload & 1;
59180a03886SAdrian Hunter }
59280a03886SAdrian Hunter 
intel_pt_set_nr(struct intel_pt_decoder * decoder)59380a03886SAdrian Hunter static inline void intel_pt_set_nr(struct intel_pt_decoder *decoder)
59480a03886SAdrian Hunter {
59580a03886SAdrian Hunter 	decoder->nr = decoder->pip_payload & 1;
59680a03886SAdrian Hunter 	decoder->next_nr = decoder->nr;
59780a03886SAdrian Hunter }
59880a03886SAdrian Hunter 
intel_pt_set_pip(struct intel_pt_decoder * decoder)59980a03886SAdrian Hunter static inline void intel_pt_set_pip(struct intel_pt_decoder *decoder)
60080a03886SAdrian Hunter {
60180a03886SAdrian Hunter 	intel_pt_update_pip(decoder);
60280a03886SAdrian Hunter 	intel_pt_set_nr(decoder);
60380a03886SAdrian Hunter }
60480a03886SAdrian Hunter 
intel_pt_bad_packet(struct intel_pt_decoder * decoder)605f4aa0819SAdrian Hunter static int intel_pt_bad_packet(struct intel_pt_decoder *decoder)
606f4aa0819SAdrian Hunter {
607f4aa0819SAdrian Hunter 	intel_pt_clear_tx_flags(decoder);
60879b58424SAdrian Hunter 	decoder->have_tma = false;
609f4aa0819SAdrian Hunter 	decoder->pkt_len = 1;
610f4aa0819SAdrian Hunter 	decoder->pkt_step = 1;
611f4aa0819SAdrian Hunter 	intel_pt_decoder_log_packet(decoder);
612f4aa0819SAdrian Hunter 	if (decoder->pkt_state != INTEL_PT_STATE_NO_PSB) {
613f4aa0819SAdrian Hunter 		intel_pt_log("ERROR: Bad packet\n");
614f4aa0819SAdrian Hunter 		decoder->pkt_state = INTEL_PT_STATE_ERR1;
615f4aa0819SAdrian Hunter 	}
616f4aa0819SAdrian Hunter 	return -EBADMSG;
617f4aa0819SAdrian Hunter }
618f4aa0819SAdrian Hunter 
intel_pt_update_sample_time(struct intel_pt_decoder * decoder)619948e9dc8SAdrian Hunter static inline void intel_pt_update_sample_time(struct intel_pt_decoder *decoder)
620948e9dc8SAdrian Hunter {
621948e9dc8SAdrian Hunter 	decoder->sample_timestamp = decoder->timestamp;
622948e9dc8SAdrian Hunter 	decoder->sample_insn_cnt = decoder->timestamp_insn_cnt;
623f2b91386SAdrian Hunter 	decoder->state.cycles = decoder->tot_cyc_cnt;
624948e9dc8SAdrian Hunter }
625948e9dc8SAdrian Hunter 
intel_pt_reposition(struct intel_pt_decoder * decoder)6266492e5f0SAdrian Hunter static void intel_pt_reposition(struct intel_pt_decoder *decoder)
6276492e5f0SAdrian Hunter {
6286492e5f0SAdrian Hunter 	decoder->ip = 0;
6296492e5f0SAdrian Hunter 	decoder->pkt_state = INTEL_PT_STATE_NO_PSB;
6306492e5f0SAdrian Hunter 	decoder->timestamp = 0;
6316492e5f0SAdrian Hunter 	decoder->have_tma = false;
6326492e5f0SAdrian Hunter }
6336492e5f0SAdrian Hunter 
intel_pt_get_data(struct intel_pt_decoder * decoder,bool reposition)6346c1f0b18SAdrian Hunter static int intel_pt_get_data(struct intel_pt_decoder *decoder, bool reposition)
635f4aa0819SAdrian Hunter {
636f4aa0819SAdrian Hunter 	struct intel_pt_buffer buffer = { .buf = 0, };
637f4aa0819SAdrian Hunter 	int ret;
638f4aa0819SAdrian Hunter 
639f4aa0819SAdrian Hunter 	decoder->pkt_step = 0;
640f4aa0819SAdrian Hunter 
641f4aa0819SAdrian Hunter 	intel_pt_log("Getting more data\n");
642f4aa0819SAdrian Hunter 	ret = decoder->get_trace(&buffer, decoder->data);
643f4aa0819SAdrian Hunter 	if (ret)
644f4aa0819SAdrian Hunter 		return ret;
645f4aa0819SAdrian Hunter 	decoder->buf = buffer.buf;
646f4aa0819SAdrian Hunter 	decoder->len = buffer.len;
647f4aa0819SAdrian Hunter 	if (!decoder->len) {
648f4aa0819SAdrian Hunter 		intel_pt_log("No more data\n");
649f4aa0819SAdrian Hunter 		return -ENODATA;
650f4aa0819SAdrian Hunter 	}
651a7fa19f5SAdrian Hunter 	decoder->buf_timestamp = buffer.ref_timestamp;
6526c1f0b18SAdrian Hunter 	if (!buffer.consecutive || reposition) {
6536492e5f0SAdrian Hunter 		intel_pt_reposition(decoder);
654f4aa0819SAdrian Hunter 		decoder->ref_timestamp = buffer.ref_timestamp;
655f4aa0819SAdrian Hunter 		decoder->state.trace_nr = buffer.trace_nr;
656fa8f949dSAdrian Hunter 		decoder->vm_tm_corr_same_buf = false;
657f4aa0819SAdrian Hunter 		intel_pt_log("Reference timestamp 0x%" PRIx64 "\n",
658f4aa0819SAdrian Hunter 			     decoder->ref_timestamp);
659f4aa0819SAdrian Hunter 		return -ENOLINK;
660f4aa0819SAdrian Hunter 	}
661f4aa0819SAdrian Hunter 
662f4aa0819SAdrian Hunter 	return 0;
663f4aa0819SAdrian Hunter }
664f4aa0819SAdrian Hunter 
intel_pt_get_next_data(struct intel_pt_decoder * decoder,bool reposition)6656c1f0b18SAdrian Hunter static int intel_pt_get_next_data(struct intel_pt_decoder *decoder,
6666c1f0b18SAdrian Hunter 				  bool reposition)
667f4aa0819SAdrian Hunter {
668f4aa0819SAdrian Hunter 	if (!decoder->next_buf)
6696c1f0b18SAdrian Hunter 		return intel_pt_get_data(decoder, reposition);
670f4aa0819SAdrian Hunter 
671f4aa0819SAdrian Hunter 	decoder->buf = decoder->next_buf;
672f4aa0819SAdrian Hunter 	decoder->len = decoder->next_len;
673f4aa0819SAdrian Hunter 	decoder->next_buf = 0;
674f4aa0819SAdrian Hunter 	decoder->next_len = 0;
675f4aa0819SAdrian Hunter 	return 0;
676f4aa0819SAdrian Hunter }
677f4aa0819SAdrian Hunter 
intel_pt_get_split_packet(struct intel_pt_decoder * decoder)678f4aa0819SAdrian Hunter static int intel_pt_get_split_packet(struct intel_pt_decoder *decoder)
679f4aa0819SAdrian Hunter {
680f4aa0819SAdrian Hunter 	unsigned char *buf = decoder->temp_buf;
681f4aa0819SAdrian Hunter 	size_t old_len, len, n;
682f4aa0819SAdrian Hunter 	int ret;
683f4aa0819SAdrian Hunter 
684f4aa0819SAdrian Hunter 	old_len = decoder->len;
685f4aa0819SAdrian Hunter 	len = decoder->len;
686f4aa0819SAdrian Hunter 	memcpy(buf, decoder->buf, len);
687f4aa0819SAdrian Hunter 
6886c1f0b18SAdrian Hunter 	ret = intel_pt_get_data(decoder, false);
689f4aa0819SAdrian Hunter 	if (ret) {
690f4aa0819SAdrian Hunter 		decoder->pos += old_len;
691f4aa0819SAdrian Hunter 		return ret < 0 ? ret : -EINVAL;
692f4aa0819SAdrian Hunter 	}
693f4aa0819SAdrian Hunter 
694f4aa0819SAdrian Hunter 	n = INTEL_PT_PKT_MAX_SZ - len;
695f4aa0819SAdrian Hunter 	if (n > decoder->len)
696f4aa0819SAdrian Hunter 		n = decoder->len;
697f4aa0819SAdrian Hunter 	memcpy(buf + len, decoder->buf, n);
698f4aa0819SAdrian Hunter 	len += n;
699f4aa0819SAdrian Hunter 
7004c35595eSAdrian Hunter 	decoder->prev_pkt_ctx = decoder->pkt_ctx;
701edff7809SAdrian Hunter 	ret = intel_pt_get_packet(buf, len, &decoder->packet, &decoder->pkt_ctx);
702f4aa0819SAdrian Hunter 	if (ret < (int)old_len) {
703f4aa0819SAdrian Hunter 		decoder->next_buf = decoder->buf;
704f4aa0819SAdrian Hunter 		decoder->next_len = decoder->len;
705f4aa0819SAdrian Hunter 		decoder->buf = buf;
706f4aa0819SAdrian Hunter 		decoder->len = old_len;
707f4aa0819SAdrian Hunter 		return intel_pt_bad_packet(decoder);
708f4aa0819SAdrian Hunter 	}
709f4aa0819SAdrian Hunter 
710f4aa0819SAdrian Hunter 	decoder->next_buf = decoder->buf + (ret - old_len);
711f4aa0819SAdrian Hunter 	decoder->next_len = decoder->len - (ret - old_len);
712f4aa0819SAdrian Hunter 
713f4aa0819SAdrian Hunter 	decoder->buf = buf;
714f4aa0819SAdrian Hunter 	decoder->len = ret;
715f4aa0819SAdrian Hunter 
716f4aa0819SAdrian Hunter 	return ret;
717f4aa0819SAdrian Hunter }
718f4aa0819SAdrian Hunter 
719cc336186SAdrian Hunter struct intel_pt_pkt_info {
720cc336186SAdrian Hunter 	struct intel_pt_decoder	  *decoder;
721cc336186SAdrian Hunter 	struct intel_pt_pkt       packet;
722cc336186SAdrian Hunter 	uint64_t                  pos;
723cc336186SAdrian Hunter 	int                       pkt_len;
724cc336186SAdrian Hunter 	int                       last_packet_type;
725cc336186SAdrian Hunter 	void                      *data;
726cc336186SAdrian Hunter };
727cc336186SAdrian Hunter 
728cc336186SAdrian Hunter typedef int (*intel_pt_pkt_cb_t)(struct intel_pt_pkt_info *pkt_info);
729cc336186SAdrian Hunter 
730cc336186SAdrian Hunter /* Lookahead packets in current buffer */
intel_pt_pkt_lookahead(struct intel_pt_decoder * decoder,intel_pt_pkt_cb_t cb,void * data)731cc336186SAdrian Hunter static int intel_pt_pkt_lookahead(struct intel_pt_decoder *decoder,
732cc336186SAdrian Hunter 				  intel_pt_pkt_cb_t cb, void *data)
733cc336186SAdrian Hunter {
734cc336186SAdrian Hunter 	struct intel_pt_pkt_info pkt_info;
735cc336186SAdrian Hunter 	const unsigned char *buf = decoder->buf;
736edff7809SAdrian Hunter 	enum intel_pt_pkt_ctx pkt_ctx = decoder->pkt_ctx;
737cc336186SAdrian Hunter 	size_t len = decoder->len;
738cc336186SAdrian Hunter 	int ret;
739cc336186SAdrian Hunter 
740cc336186SAdrian Hunter 	pkt_info.decoder          = decoder;
741cc336186SAdrian Hunter 	pkt_info.pos              = decoder->pos;
742cc336186SAdrian Hunter 	pkt_info.pkt_len          = decoder->pkt_step;
743cc336186SAdrian Hunter 	pkt_info.last_packet_type = decoder->last_packet_type;
744cc336186SAdrian Hunter 	pkt_info.data             = data;
745cc336186SAdrian Hunter 
746cc336186SAdrian Hunter 	while (1) {
747cc336186SAdrian Hunter 		do {
748cc336186SAdrian Hunter 			pkt_info.pos += pkt_info.pkt_len;
749cc336186SAdrian Hunter 			buf          += pkt_info.pkt_len;
750cc336186SAdrian Hunter 			len          -= pkt_info.pkt_len;
751cc336186SAdrian Hunter 
752cc336186SAdrian Hunter 			if (!len)
753cc336186SAdrian Hunter 				return INTEL_PT_NEED_MORE_BYTES;
754cc336186SAdrian Hunter 
755edff7809SAdrian Hunter 			ret = intel_pt_get_packet(buf, len, &pkt_info.packet,
756edff7809SAdrian Hunter 						  &pkt_ctx);
757cc336186SAdrian Hunter 			if (!ret)
758cc336186SAdrian Hunter 				return INTEL_PT_NEED_MORE_BYTES;
759cc336186SAdrian Hunter 			if (ret < 0)
760cc336186SAdrian Hunter 				return ret;
761cc336186SAdrian Hunter 
762cc336186SAdrian Hunter 			pkt_info.pkt_len = ret;
763cc336186SAdrian Hunter 		} while (pkt_info.packet.type == INTEL_PT_PAD);
764cc336186SAdrian Hunter 
765cc336186SAdrian Hunter 		ret = cb(&pkt_info);
766cc336186SAdrian Hunter 		if (ret)
767cc336186SAdrian Hunter 			return 0;
768cc336186SAdrian Hunter 
769cc336186SAdrian Hunter 		pkt_info.last_packet_type = pkt_info.packet.type;
770cc336186SAdrian Hunter 	}
771cc336186SAdrian Hunter }
772cc336186SAdrian Hunter 
773cc336186SAdrian Hunter struct intel_pt_calc_cyc_to_tsc_info {
774cc336186SAdrian Hunter 	uint64_t        cycle_cnt;
775cc336186SAdrian Hunter 	unsigned int    cbr;
776cc336186SAdrian Hunter 	uint32_t        last_mtc;
777cc336186SAdrian Hunter 	uint64_t        ctc_timestamp;
778cc336186SAdrian Hunter 	uint64_t        ctc_delta;
779cc336186SAdrian Hunter 	uint64_t        tsc_timestamp;
780cc336186SAdrian Hunter 	uint64_t        timestamp;
781cc336186SAdrian Hunter 	bool            have_tma;
7823bccbe20SAdrian Hunter 	bool            fixup_last_mtc;
783cc336186SAdrian Hunter 	bool            from_mtc;
784cc336186SAdrian Hunter 	double          cbr_cyc_to_tsc;
785cc336186SAdrian Hunter };
786cc336186SAdrian Hunter 
7873bccbe20SAdrian Hunter /*
7883bccbe20SAdrian Hunter  * MTC provides a 8-bit slice of CTC but the TMA packet only provides the lower
7893bccbe20SAdrian Hunter  * 16 bits of CTC. If mtc_shift > 8 then some of the MTC bits are not in the CTC
7903bccbe20SAdrian Hunter  * provided by the TMA packet. Fix-up the last_mtc calculated from the TMA
7913bccbe20SAdrian Hunter  * packet by copying the missing bits from the current MTC assuming the least
7923bccbe20SAdrian Hunter  * difference between the two, and that the current MTC comes after last_mtc.
7933bccbe20SAdrian Hunter  */
intel_pt_fixup_last_mtc(uint32_t mtc,int mtc_shift,uint32_t * last_mtc)7943bccbe20SAdrian Hunter static void intel_pt_fixup_last_mtc(uint32_t mtc, int mtc_shift,
7953bccbe20SAdrian Hunter 				    uint32_t *last_mtc)
7963bccbe20SAdrian Hunter {
7973bccbe20SAdrian Hunter 	uint32_t first_missing_bit = 1U << (16 - mtc_shift);
7983bccbe20SAdrian Hunter 	uint32_t mask = ~(first_missing_bit - 1);
7993bccbe20SAdrian Hunter 
8003bccbe20SAdrian Hunter 	*last_mtc |= mtc & mask;
8013bccbe20SAdrian Hunter 	if (*last_mtc >= mtc) {
8023bccbe20SAdrian Hunter 		*last_mtc -= first_missing_bit;
8033bccbe20SAdrian Hunter 		*last_mtc &= 0xff;
8043bccbe20SAdrian Hunter 	}
8053bccbe20SAdrian Hunter }
8063bccbe20SAdrian Hunter 
intel_pt_calc_cyc_cb(struct intel_pt_pkt_info * pkt_info)807cc336186SAdrian Hunter static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
808cc336186SAdrian Hunter {
809cc336186SAdrian Hunter 	struct intel_pt_decoder *decoder = pkt_info->decoder;
810cc336186SAdrian Hunter 	struct intel_pt_calc_cyc_to_tsc_info *data = pkt_info->data;
811cc336186SAdrian Hunter 	uint64_t timestamp;
812cc336186SAdrian Hunter 	double cyc_to_tsc;
813cc336186SAdrian Hunter 	unsigned int cbr;
814cc336186SAdrian Hunter 	uint32_t mtc, mtc_delta, ctc, fc, ctc_rem;
815cc336186SAdrian Hunter 
816cc336186SAdrian Hunter 	switch (pkt_info->packet.type) {
817cc336186SAdrian Hunter 	case INTEL_PT_TNT:
818cc336186SAdrian Hunter 	case INTEL_PT_TIP_PGE:
819cc336186SAdrian Hunter 	case INTEL_PT_TIP:
820cc336186SAdrian Hunter 	case INTEL_PT_FUP:
821cc336186SAdrian Hunter 	case INTEL_PT_PSB:
822cc336186SAdrian Hunter 	case INTEL_PT_PIP:
823cc336186SAdrian Hunter 	case INTEL_PT_MODE_EXEC:
824cc336186SAdrian Hunter 	case INTEL_PT_MODE_TSX:
825cc336186SAdrian Hunter 	case INTEL_PT_PSBEND:
826cc336186SAdrian Hunter 	case INTEL_PT_PAD:
827cc336186SAdrian Hunter 	case INTEL_PT_VMCS:
828cc336186SAdrian Hunter 	case INTEL_PT_MNT:
829a472e65fSAdrian Hunter 	case INTEL_PT_PTWRITE:
830a472e65fSAdrian Hunter 	case INTEL_PT_PTWRITE_IP:
831edff7809SAdrian Hunter 	case INTEL_PT_BBP:
832edff7809SAdrian Hunter 	case INTEL_PT_BIP:
833edff7809SAdrian Hunter 	case INTEL_PT_BEP:
834edff7809SAdrian Hunter 	case INTEL_PT_BEP_IP:
8352750af50SAdrian Hunter 	case INTEL_PT_CFE:
8362750af50SAdrian Hunter 	case INTEL_PT_CFE_IP:
8372750af50SAdrian Hunter 	case INTEL_PT_EVD:
838cc336186SAdrian Hunter 		return 0;
839cc336186SAdrian Hunter 
840cc336186SAdrian Hunter 	case INTEL_PT_MTC:
841cc336186SAdrian Hunter 		if (!data->have_tma)
842cc336186SAdrian Hunter 			return 0;
843cc336186SAdrian Hunter 
844cc336186SAdrian Hunter 		mtc = pkt_info->packet.payload;
8453bccbe20SAdrian Hunter 		if (decoder->mtc_shift > 8 && data->fixup_last_mtc) {
8463bccbe20SAdrian Hunter 			data->fixup_last_mtc = false;
8473bccbe20SAdrian Hunter 			intel_pt_fixup_last_mtc(mtc, decoder->mtc_shift,
8483bccbe20SAdrian Hunter 						&data->last_mtc);
8493bccbe20SAdrian Hunter 		}
850cc336186SAdrian Hunter 		if (mtc > data->last_mtc)
851cc336186SAdrian Hunter 			mtc_delta = mtc - data->last_mtc;
852cc336186SAdrian Hunter 		else
853cc336186SAdrian Hunter 			mtc_delta = mtc + 256 - data->last_mtc;
854cc336186SAdrian Hunter 		data->ctc_delta += mtc_delta << decoder->mtc_shift;
855cc336186SAdrian Hunter 		data->last_mtc = mtc;
856cc336186SAdrian Hunter 
857cc336186SAdrian Hunter 		if (decoder->tsc_ctc_mult) {
858cc336186SAdrian Hunter 			timestamp = data->ctc_timestamp +
859cc336186SAdrian Hunter 				data->ctc_delta * decoder->tsc_ctc_mult;
860cc336186SAdrian Hunter 		} else {
861cc336186SAdrian Hunter 			timestamp = data->ctc_timestamp +
862cc336186SAdrian Hunter 				multdiv(data->ctc_delta,
863cc336186SAdrian Hunter 					decoder->tsc_ctc_ratio_n,
864cc336186SAdrian Hunter 					decoder->tsc_ctc_ratio_d);
865cc336186SAdrian Hunter 		}
866cc336186SAdrian Hunter 
867cc336186SAdrian Hunter 		if (timestamp < data->timestamp)
868cc336186SAdrian Hunter 			return 1;
869cc336186SAdrian Hunter 
870cc336186SAdrian Hunter 		if (pkt_info->last_packet_type != INTEL_PT_CYC) {
871cc336186SAdrian Hunter 			data->timestamp = timestamp;
872cc336186SAdrian Hunter 			return 0;
873cc336186SAdrian Hunter 		}
874cc336186SAdrian Hunter 
875cc336186SAdrian Hunter 		break;
876cc336186SAdrian Hunter 
877cc336186SAdrian Hunter 	case INTEL_PT_TSC:
87838b65b08SAdrian Hunter 		/*
87938b65b08SAdrian Hunter 		 * For now, do not support using TSC packets - refer
88038b65b08SAdrian Hunter 		 * intel_pt_calc_cyc_to_tsc().
88138b65b08SAdrian Hunter 		 */
88238b65b08SAdrian Hunter 		if (data->from_mtc)
88338b65b08SAdrian Hunter 			return 1;
884cc336186SAdrian Hunter 		timestamp = pkt_info->packet.payload |
885cc336186SAdrian Hunter 			    (data->timestamp & (0xffULL << 56));
886cc336186SAdrian Hunter 		if (data->from_mtc && timestamp < data->timestamp &&
887cc336186SAdrian Hunter 		    data->timestamp - timestamp < decoder->tsc_slip)
888cc336186SAdrian Hunter 			return 1;
8899992c2d5SAdrian Hunter 		if (timestamp < data->timestamp)
890cc336186SAdrian Hunter 			timestamp += (1ULL << 56);
891cc336186SAdrian Hunter 		if (pkt_info->last_packet_type != INTEL_PT_CYC) {
892cc336186SAdrian Hunter 			if (data->from_mtc)
893cc336186SAdrian Hunter 				return 1;
894cc336186SAdrian Hunter 			data->tsc_timestamp = timestamp;
895cc336186SAdrian Hunter 			data->timestamp = timestamp;
896cc336186SAdrian Hunter 			return 0;
897cc336186SAdrian Hunter 		}
898cc336186SAdrian Hunter 		break;
899cc336186SAdrian Hunter 
900cc336186SAdrian Hunter 	case INTEL_PT_TMA:
901cc336186SAdrian Hunter 		if (data->from_mtc)
902cc336186SAdrian Hunter 			return 1;
903cc336186SAdrian Hunter 
904cc336186SAdrian Hunter 		if (!decoder->tsc_ctc_ratio_d)
905cc336186SAdrian Hunter 			return 0;
906cc336186SAdrian Hunter 
907cc336186SAdrian Hunter 		ctc = pkt_info->packet.payload;
908cc336186SAdrian Hunter 		fc = pkt_info->packet.count;
909cc336186SAdrian Hunter 		ctc_rem = ctc & decoder->ctc_rem_mask;
910cc336186SAdrian Hunter 
911cc336186SAdrian Hunter 		data->last_mtc = (ctc >> decoder->mtc_shift) & 0xff;
912cc336186SAdrian Hunter 
913cc336186SAdrian Hunter 		data->ctc_timestamp = data->tsc_timestamp - fc;
914cc336186SAdrian Hunter 		if (decoder->tsc_ctc_mult) {
915cc336186SAdrian Hunter 			data->ctc_timestamp -= ctc_rem * decoder->tsc_ctc_mult;
916cc336186SAdrian Hunter 		} else {
917cc336186SAdrian Hunter 			data->ctc_timestamp -=
918cc336186SAdrian Hunter 				multdiv(ctc_rem, decoder->tsc_ctc_ratio_n,
919cc336186SAdrian Hunter 					decoder->tsc_ctc_ratio_d);
920cc336186SAdrian Hunter 		}
921cc336186SAdrian Hunter 
922cc336186SAdrian Hunter 		data->ctc_delta = 0;
923cc336186SAdrian Hunter 		data->have_tma = true;
9243bccbe20SAdrian Hunter 		data->fixup_last_mtc = true;
925cc336186SAdrian Hunter 
926cc336186SAdrian Hunter 		return 0;
927cc336186SAdrian Hunter 
928cc336186SAdrian Hunter 	case INTEL_PT_CYC:
929cc336186SAdrian Hunter 		data->cycle_cnt += pkt_info->packet.payload;
930cc336186SAdrian Hunter 		return 0;
931cc336186SAdrian Hunter 
932cc336186SAdrian Hunter 	case INTEL_PT_CBR:
933cc336186SAdrian Hunter 		cbr = pkt_info->packet.payload;
934cc336186SAdrian Hunter 		if (data->cbr && data->cbr != cbr)
935cc336186SAdrian Hunter 			return 1;
936cc336186SAdrian Hunter 		data->cbr = cbr;
937cc336186SAdrian Hunter 		data->cbr_cyc_to_tsc = decoder->max_non_turbo_ratio_fp / cbr;
938cc336186SAdrian Hunter 		return 0;
939cc336186SAdrian Hunter 
940cc336186SAdrian Hunter 	case INTEL_PT_TIP_PGD:
941cc336186SAdrian Hunter 	case INTEL_PT_TRACESTOP:
942a472e65fSAdrian Hunter 	case INTEL_PT_EXSTOP:
943a472e65fSAdrian Hunter 	case INTEL_PT_EXSTOP_IP:
944a472e65fSAdrian Hunter 	case INTEL_PT_MWAIT:
945a472e65fSAdrian Hunter 	case INTEL_PT_PWRE:
946a472e65fSAdrian Hunter 	case INTEL_PT_PWRX:
947cc336186SAdrian Hunter 	case INTEL_PT_OVF:
948cc336186SAdrian Hunter 	case INTEL_PT_BAD: /* Does not happen */
949cc336186SAdrian Hunter 	default:
950cc336186SAdrian Hunter 		return 1;
951cc336186SAdrian Hunter 	}
952cc336186SAdrian Hunter 
953cc336186SAdrian Hunter 	if (!data->cbr && decoder->cbr) {
954cc336186SAdrian Hunter 		data->cbr = decoder->cbr;
955cc336186SAdrian Hunter 		data->cbr_cyc_to_tsc = decoder->cbr_cyc_to_tsc;
956cc336186SAdrian Hunter 	}
957cc336186SAdrian Hunter 
958cc336186SAdrian Hunter 	if (!data->cycle_cnt)
959cc336186SAdrian Hunter 		return 1;
960cc336186SAdrian Hunter 
961cc336186SAdrian Hunter 	cyc_to_tsc = (double)(timestamp - decoder->timestamp) / data->cycle_cnt;
962cc336186SAdrian Hunter 
963cc336186SAdrian Hunter 	if (data->cbr && cyc_to_tsc > data->cbr_cyc_to_tsc &&
964cc336186SAdrian Hunter 	    cyc_to_tsc / data->cbr_cyc_to_tsc > 1.25) {
965cc336186SAdrian Hunter 		intel_pt_log("Timestamp: calculated %g TSC ticks per cycle too big (c.f. CBR-based value %g), pos " x64_fmt "\n",
966cc336186SAdrian Hunter 			     cyc_to_tsc, data->cbr_cyc_to_tsc, pkt_info->pos);
967cc336186SAdrian Hunter 		return 1;
968cc336186SAdrian Hunter 	}
969cc336186SAdrian Hunter 
970cc336186SAdrian Hunter 	decoder->calc_cyc_to_tsc = cyc_to_tsc;
971cc336186SAdrian Hunter 	decoder->have_calc_cyc_to_tsc = true;
972cc336186SAdrian Hunter 
973cc336186SAdrian Hunter 	if (data->cbr) {
974cc336186SAdrian Hunter 		intel_pt_log("Timestamp: calculated %g TSC ticks per cycle c.f. CBR-based value %g, pos " x64_fmt "\n",
975cc336186SAdrian Hunter 			     cyc_to_tsc, data->cbr_cyc_to_tsc, pkt_info->pos);
976cc336186SAdrian Hunter 	} else {
977cc336186SAdrian Hunter 		intel_pt_log("Timestamp: calculated %g TSC ticks per cycle c.f. unknown CBR-based value, pos " x64_fmt "\n",
978cc336186SAdrian Hunter 			     cyc_to_tsc, pkt_info->pos);
979cc336186SAdrian Hunter 	}
980cc336186SAdrian Hunter 
981cc336186SAdrian Hunter 	return 1;
982cc336186SAdrian Hunter }
983cc336186SAdrian Hunter 
intel_pt_calc_cyc_to_tsc(struct intel_pt_decoder * decoder,bool from_mtc)984cc336186SAdrian Hunter static void intel_pt_calc_cyc_to_tsc(struct intel_pt_decoder *decoder,
985cc336186SAdrian Hunter 				     bool from_mtc)
986cc336186SAdrian Hunter {
987cc336186SAdrian Hunter 	struct intel_pt_calc_cyc_to_tsc_info data = {
988cc336186SAdrian Hunter 		.cycle_cnt      = 0,
989cc336186SAdrian Hunter 		.cbr            = 0,
990cc336186SAdrian Hunter 		.last_mtc       = decoder->last_mtc,
991cc336186SAdrian Hunter 		.ctc_timestamp  = decoder->ctc_timestamp,
992cc336186SAdrian Hunter 		.ctc_delta      = decoder->ctc_delta,
993cc336186SAdrian Hunter 		.tsc_timestamp  = decoder->tsc_timestamp,
994cc336186SAdrian Hunter 		.timestamp      = decoder->timestamp,
995cc336186SAdrian Hunter 		.have_tma       = decoder->have_tma,
9963bccbe20SAdrian Hunter 		.fixup_last_mtc = decoder->fixup_last_mtc,
997cc336186SAdrian Hunter 		.from_mtc       = from_mtc,
998cc336186SAdrian Hunter 		.cbr_cyc_to_tsc = 0,
999cc336186SAdrian Hunter 	};
1000cc336186SAdrian Hunter 
100138b65b08SAdrian Hunter 	/*
100238b65b08SAdrian Hunter 	 * For now, do not support using TSC packets for at least the reasons:
100338b65b08SAdrian Hunter 	 * 1) timing might have stopped
100438b65b08SAdrian Hunter 	 * 2) TSC packets within PSB+ can slip against CYC packets
100538b65b08SAdrian Hunter 	 */
100638b65b08SAdrian Hunter 	if (!from_mtc)
100738b65b08SAdrian Hunter 		return;
100838b65b08SAdrian Hunter 
1009cc336186SAdrian Hunter 	intel_pt_pkt_lookahead(decoder, intel_pt_calc_cyc_cb, &data);
1010cc336186SAdrian Hunter }
1011cc336186SAdrian Hunter 
intel_pt_get_next_packet(struct intel_pt_decoder * decoder)1012f4aa0819SAdrian Hunter static int intel_pt_get_next_packet(struct intel_pt_decoder *decoder)
1013f4aa0819SAdrian Hunter {
1014f4aa0819SAdrian Hunter 	int ret;
1015f4aa0819SAdrian Hunter 
1016cc336186SAdrian Hunter 	decoder->last_packet_type = decoder->packet.type;
1017cc336186SAdrian Hunter 
1018f4aa0819SAdrian Hunter 	do {
1019f4aa0819SAdrian Hunter 		decoder->pos += decoder->pkt_step;
1020f4aa0819SAdrian Hunter 		decoder->buf += decoder->pkt_step;
1021f4aa0819SAdrian Hunter 		decoder->len -= decoder->pkt_step;
1022f4aa0819SAdrian Hunter 
1023f4aa0819SAdrian Hunter 		if (!decoder->len) {
10246c1f0b18SAdrian Hunter 			ret = intel_pt_get_next_data(decoder, false);
1025f4aa0819SAdrian Hunter 			if (ret)
1026f4aa0819SAdrian Hunter 				return ret;
1027f4aa0819SAdrian Hunter 		}
1028f4aa0819SAdrian Hunter 
10294c35595eSAdrian Hunter 		decoder->prev_pkt_ctx = decoder->pkt_ctx;
1030f4aa0819SAdrian Hunter 		ret = intel_pt_get_packet(decoder->buf, decoder->len,
1031edff7809SAdrian Hunter 					  &decoder->packet, &decoder->pkt_ctx);
103226ee2bcdSAdrian Hunter 		if (ret == INTEL_PT_NEED_MORE_BYTES && BITS_PER_LONG == 32 &&
1033f4aa0819SAdrian Hunter 		    decoder->len < INTEL_PT_PKT_MAX_SZ && !decoder->next_buf) {
1034f4aa0819SAdrian Hunter 			ret = intel_pt_get_split_packet(decoder);
1035f4aa0819SAdrian Hunter 			if (ret < 0)
1036f4aa0819SAdrian Hunter 				return ret;
1037f4aa0819SAdrian Hunter 		}
1038f4aa0819SAdrian Hunter 		if (ret <= 0)
1039f4aa0819SAdrian Hunter 			return intel_pt_bad_packet(decoder);
1040f4aa0819SAdrian Hunter 
1041f4aa0819SAdrian Hunter 		decoder->pkt_len = ret;
1042f4aa0819SAdrian Hunter 		decoder->pkt_step = ret;
1043f4aa0819SAdrian Hunter 		intel_pt_decoder_log_packet(decoder);
1044f4aa0819SAdrian Hunter 	} while (decoder->packet.type == INTEL_PT_PAD);
1045f4aa0819SAdrian Hunter 
1046f4aa0819SAdrian Hunter 	return 0;
1047f4aa0819SAdrian Hunter }
1048f4aa0819SAdrian Hunter 
intel_pt_next_period(struct intel_pt_decoder * decoder)1049f4aa0819SAdrian Hunter static uint64_t intel_pt_next_period(struct intel_pt_decoder *decoder)
1050f4aa0819SAdrian Hunter {
1051f4aa0819SAdrian Hunter 	uint64_t timestamp, masked_timestamp;
1052f4aa0819SAdrian Hunter 
1053f4aa0819SAdrian Hunter 	timestamp = decoder->timestamp + decoder->timestamp_insn_cnt;
1054f4aa0819SAdrian Hunter 	masked_timestamp = timestamp & decoder->period_mask;
1055f4aa0819SAdrian Hunter 	if (decoder->continuous_period) {
10567ba8fa20SAdrian Hunter 		if (masked_timestamp > decoder->last_masked_timestamp)
1057f4aa0819SAdrian Hunter 			return 1;
1058f4aa0819SAdrian Hunter 	} else {
1059f4aa0819SAdrian Hunter 		timestamp += 1;
1060f4aa0819SAdrian Hunter 		masked_timestamp = timestamp & decoder->period_mask;
10617ba8fa20SAdrian Hunter 		if (masked_timestamp > decoder->last_masked_timestamp) {
1062f4aa0819SAdrian Hunter 			decoder->last_masked_timestamp = masked_timestamp;
1063f4aa0819SAdrian Hunter 			decoder->continuous_period = true;
1064f4aa0819SAdrian Hunter 		}
1065f4aa0819SAdrian Hunter 	}
10667ba8fa20SAdrian Hunter 
10677ba8fa20SAdrian Hunter 	if (masked_timestamp < decoder->last_masked_timestamp)
10687ba8fa20SAdrian Hunter 		return decoder->period_ticks;
10697ba8fa20SAdrian Hunter 
1070f4aa0819SAdrian Hunter 	return decoder->period_ticks - (timestamp - masked_timestamp);
1071f4aa0819SAdrian Hunter }
1072f4aa0819SAdrian Hunter 
intel_pt_next_sample(struct intel_pt_decoder * decoder)1073f4aa0819SAdrian Hunter static uint64_t intel_pt_next_sample(struct intel_pt_decoder *decoder)
1074f4aa0819SAdrian Hunter {
1075f4aa0819SAdrian Hunter 	switch (decoder->period_type) {
1076f4aa0819SAdrian Hunter 	case INTEL_PT_PERIOD_INSTRUCTIONS:
1077f4aa0819SAdrian Hunter 		return decoder->period - decoder->period_insn_cnt;
1078f4aa0819SAdrian Hunter 	case INTEL_PT_PERIOD_TICKS:
1079f4aa0819SAdrian Hunter 		return intel_pt_next_period(decoder);
1080f4aa0819SAdrian Hunter 	case INTEL_PT_PERIOD_NONE:
108179b58424SAdrian Hunter 	case INTEL_PT_PERIOD_MTC:
1082f4aa0819SAdrian Hunter 	default:
1083f4aa0819SAdrian Hunter 		return 0;
1084f4aa0819SAdrian Hunter 	}
1085f4aa0819SAdrian Hunter }
1086f4aa0819SAdrian Hunter 
intel_pt_sample_insn(struct intel_pt_decoder * decoder)1087f4aa0819SAdrian Hunter static void intel_pt_sample_insn(struct intel_pt_decoder *decoder)
1088f4aa0819SAdrian Hunter {
1089f4aa0819SAdrian Hunter 	uint64_t timestamp, masked_timestamp;
1090f4aa0819SAdrian Hunter 
1091f4aa0819SAdrian Hunter 	switch (decoder->period_type) {
1092f4aa0819SAdrian Hunter 	case INTEL_PT_PERIOD_INSTRUCTIONS:
1093f4aa0819SAdrian Hunter 		decoder->period_insn_cnt = 0;
1094f4aa0819SAdrian Hunter 		break;
1095f4aa0819SAdrian Hunter 	case INTEL_PT_PERIOD_TICKS:
1096f4aa0819SAdrian Hunter 		timestamp = decoder->timestamp + decoder->timestamp_insn_cnt;
1097f4aa0819SAdrian Hunter 		masked_timestamp = timestamp & decoder->period_mask;
10987ba8fa20SAdrian Hunter 		if (masked_timestamp > decoder->last_masked_timestamp)
1099f4aa0819SAdrian Hunter 			decoder->last_masked_timestamp = masked_timestamp;
11007ba8fa20SAdrian Hunter 		else
11017ba8fa20SAdrian Hunter 			decoder->last_masked_timestamp += decoder->period_ticks;
1102f4aa0819SAdrian Hunter 		break;
1103f4aa0819SAdrian Hunter 	case INTEL_PT_PERIOD_NONE:
110479b58424SAdrian Hunter 	case INTEL_PT_PERIOD_MTC:
1105f4aa0819SAdrian Hunter 	default:
1106f4aa0819SAdrian Hunter 		break;
1107f4aa0819SAdrian Hunter 	}
1108f4aa0819SAdrian Hunter 
1109f4aa0819SAdrian Hunter 	decoder->state.type |= INTEL_PT_INSTRUCTION;
1110f4aa0819SAdrian Hunter }
1111f4aa0819SAdrian Hunter 
1112cf0c98e2SAdrian Hunter /*
1113cf0c98e2SAdrian Hunter  * Sample FUP instruction at the same time as reporting the FUP event, so the
1114cf0c98e2SAdrian Hunter  * instruction sample gets the same flags as the FUP event.
1115cf0c98e2SAdrian Hunter  */
intel_pt_sample_fup_insn(struct intel_pt_decoder * decoder)1116cf0c98e2SAdrian Hunter static void intel_pt_sample_fup_insn(struct intel_pt_decoder *decoder)
1117cf0c98e2SAdrian Hunter {
1118cf0c98e2SAdrian Hunter 	struct intel_pt_insn intel_pt_insn;
1119cf0c98e2SAdrian Hunter 	uint64_t max_insn_cnt, insn_cnt = 0;
1120cf0c98e2SAdrian Hunter 	int err;
1121cf0c98e2SAdrian Hunter 
1122cf0c98e2SAdrian Hunter 	decoder->state.insn_op = INTEL_PT_OP_OTHER;
1123cf0c98e2SAdrian Hunter 	decoder->state.insn_len = 0;
1124cf0c98e2SAdrian Hunter 
1125cf0c98e2SAdrian Hunter 	if (!decoder->branch_enable || !decoder->pge || decoder->hop ||
1126cf0c98e2SAdrian Hunter 	    decoder->ip != decoder->last_ip)
1127cf0c98e2SAdrian Hunter 		return;
1128cf0c98e2SAdrian Hunter 
1129cf0c98e2SAdrian Hunter 	if (!decoder->mtc_insn)
1130cf0c98e2SAdrian Hunter 		decoder->mtc_insn = true;
1131cf0c98e2SAdrian Hunter 
1132cf0c98e2SAdrian Hunter 	max_insn_cnt = intel_pt_next_sample(decoder);
1133cf0c98e2SAdrian Hunter 	if (max_insn_cnt != 1)
1134cf0c98e2SAdrian Hunter 		return;
1135cf0c98e2SAdrian Hunter 
1136cf0c98e2SAdrian Hunter 	err = decoder->walk_insn(&intel_pt_insn, &insn_cnt, &decoder->ip,
1137cf0c98e2SAdrian Hunter 				 0, max_insn_cnt, decoder->data);
1138cf0c98e2SAdrian Hunter 	/* Ignore error, it will be reported next walk anyway */
1139cf0c98e2SAdrian Hunter 	if (err)
1140cf0c98e2SAdrian Hunter 		return;
1141cf0c98e2SAdrian Hunter 
1142cf0c98e2SAdrian Hunter 	if (intel_pt_insn.branch != INTEL_PT_BR_NO_BRANCH) {
1143cf0c98e2SAdrian Hunter 		intel_pt_log_at("ERROR: Unexpected branch at FUP instruction", decoder->ip);
1144cf0c98e2SAdrian Hunter 		return;
1145cf0c98e2SAdrian Hunter 	}
1146cf0c98e2SAdrian Hunter 
1147cf0c98e2SAdrian Hunter 	decoder->tot_insn_cnt += insn_cnt;
1148cf0c98e2SAdrian Hunter 	decoder->timestamp_insn_cnt += insn_cnt;
1149cf0c98e2SAdrian Hunter 	decoder->sample_insn_cnt += insn_cnt;
1150cf0c98e2SAdrian Hunter 	decoder->period_insn_cnt += insn_cnt;
1151cf0c98e2SAdrian Hunter 
1152cf0c98e2SAdrian Hunter 	intel_pt_sample_insn(decoder);
1153cf0c98e2SAdrian Hunter 
1154cf0c98e2SAdrian Hunter 	decoder->state.type |= INTEL_PT_INSTRUCTION;
1155cf0c98e2SAdrian Hunter 	decoder->ip += intel_pt_insn.length;
1156cf0c98e2SAdrian Hunter }
1157cf0c98e2SAdrian Hunter 
intel_pt_walk_insn(struct intel_pt_decoder * decoder,struct intel_pt_insn * intel_pt_insn,uint64_t ip)1158f4aa0819SAdrian Hunter static int intel_pt_walk_insn(struct intel_pt_decoder *decoder,
1159f4aa0819SAdrian Hunter 			      struct intel_pt_insn *intel_pt_insn, uint64_t ip)
1160f4aa0819SAdrian Hunter {
1161f4aa0819SAdrian Hunter 	uint64_t max_insn_cnt, insn_cnt = 0;
1162f4aa0819SAdrian Hunter 	int err;
1163f4aa0819SAdrian Hunter 
116479b58424SAdrian Hunter 	if (!decoder->mtc_insn)
116579b58424SAdrian Hunter 		decoder->mtc_insn = true;
116679b58424SAdrian Hunter 
1167f4aa0819SAdrian Hunter 	max_insn_cnt = intel_pt_next_sample(decoder);
1168f4aa0819SAdrian Hunter 
1169f4aa0819SAdrian Hunter 	err = decoder->walk_insn(intel_pt_insn, &insn_cnt, &decoder->ip, ip,
1170f4aa0819SAdrian Hunter 				 max_insn_cnt, decoder->data);
1171f4aa0819SAdrian Hunter 
11722a21d036SAdrian Hunter 	decoder->tot_insn_cnt += insn_cnt;
1173f4aa0819SAdrian Hunter 	decoder->timestamp_insn_cnt += insn_cnt;
11743f04d98eSAdrian Hunter 	decoder->sample_insn_cnt += insn_cnt;
1175f4aa0819SAdrian Hunter 	decoder->period_insn_cnt += insn_cnt;
1176f4aa0819SAdrian Hunter 
1177f4aa0819SAdrian Hunter 	if (err) {
1178f4aa0819SAdrian Hunter 		decoder->no_progress = 0;
1179f4aa0819SAdrian Hunter 		decoder->pkt_state = INTEL_PT_STATE_ERR2;
1180f4aa0819SAdrian Hunter 		intel_pt_log_at("ERROR: Failed to get instruction",
1181f4aa0819SAdrian Hunter 				decoder->ip);
1182f4aa0819SAdrian Hunter 		if (err == -ENOENT)
1183f4aa0819SAdrian Hunter 			return -ENOLINK;
1184f4aa0819SAdrian Hunter 		return -EILSEQ;
1185f4aa0819SAdrian Hunter 	}
1186f4aa0819SAdrian Hunter 
1187f4aa0819SAdrian Hunter 	if (ip && decoder->ip == ip) {
1188f4aa0819SAdrian Hunter 		err = -EAGAIN;
1189f4aa0819SAdrian Hunter 		goto out;
1190f4aa0819SAdrian Hunter 	}
1191f4aa0819SAdrian Hunter 
1192f4aa0819SAdrian Hunter 	if (max_insn_cnt && insn_cnt >= max_insn_cnt)
1193f4aa0819SAdrian Hunter 		intel_pt_sample_insn(decoder);
1194f4aa0819SAdrian Hunter 
1195f4aa0819SAdrian Hunter 	if (intel_pt_insn->branch == INTEL_PT_BR_NO_BRANCH) {
1196f4aa0819SAdrian Hunter 		decoder->state.type = INTEL_PT_INSTRUCTION;
1197f4aa0819SAdrian Hunter 		decoder->state.from_ip = decoder->ip;
1198f4aa0819SAdrian Hunter 		decoder->state.to_ip = 0;
1199f4aa0819SAdrian Hunter 		decoder->ip += intel_pt_insn->length;
1200f4aa0819SAdrian Hunter 		err = INTEL_PT_RETURN;
1201f4aa0819SAdrian Hunter 		goto out;
1202f4aa0819SAdrian Hunter 	}
1203f4aa0819SAdrian Hunter 
1204f4aa0819SAdrian Hunter 	if (intel_pt_insn->op == INTEL_PT_OP_CALL) {
1205f4aa0819SAdrian Hunter 		/* Zero-length calls are excluded */
1206f4aa0819SAdrian Hunter 		if (intel_pt_insn->branch != INTEL_PT_BR_UNCONDITIONAL ||
1207f4aa0819SAdrian Hunter 		    intel_pt_insn->rel) {
1208f4aa0819SAdrian Hunter 			err = intel_pt_push(&decoder->stack, decoder->ip +
1209f4aa0819SAdrian Hunter 					    intel_pt_insn->length);
1210f4aa0819SAdrian Hunter 			if (err)
1211f4aa0819SAdrian Hunter 				goto out;
1212f4aa0819SAdrian Hunter 		}
1213f4aa0819SAdrian Hunter 	} else if (intel_pt_insn->op == INTEL_PT_OP_RET) {
1214f4aa0819SAdrian Hunter 		decoder->ret_addr = intel_pt_pop(&decoder->stack);
1215f4aa0819SAdrian Hunter 	}
1216f4aa0819SAdrian Hunter 
1217f4aa0819SAdrian Hunter 	if (intel_pt_insn->branch == INTEL_PT_BR_UNCONDITIONAL) {
1218f4aa0819SAdrian Hunter 		int cnt = decoder->no_progress++;
1219f4aa0819SAdrian Hunter 
1220f4aa0819SAdrian Hunter 		decoder->state.from_ip = decoder->ip;
1221f4aa0819SAdrian Hunter 		decoder->ip += intel_pt_insn->length +
1222f4aa0819SAdrian Hunter 				intel_pt_insn->rel;
1223f4aa0819SAdrian Hunter 		decoder->state.to_ip = decoder->ip;
1224f4aa0819SAdrian Hunter 		err = INTEL_PT_RETURN;
1225f4aa0819SAdrian Hunter 
1226f4aa0819SAdrian Hunter 		/*
1227f4aa0819SAdrian Hunter 		 * Check for being stuck in a loop.  This can happen if a
1228f4aa0819SAdrian Hunter 		 * decoder error results in the decoder erroneously setting the
1229f4aa0819SAdrian Hunter 		 * ip to an address that is itself in an infinite loop that
1230f4aa0819SAdrian Hunter 		 * consumes no packets.  When that happens, there must be an
1231f4aa0819SAdrian Hunter 		 * unconditional branch.
1232f4aa0819SAdrian Hunter 		 */
1233f4aa0819SAdrian Hunter 		if (cnt) {
1234f4aa0819SAdrian Hunter 			if (cnt == 1) {
1235f4aa0819SAdrian Hunter 				decoder->stuck_ip = decoder->state.to_ip;
1236f4aa0819SAdrian Hunter 				decoder->stuck_ip_prd = 1;
1237f4aa0819SAdrian Hunter 				decoder->stuck_ip_cnt = 1;
1238b4b046ffSAdrian Hunter 			} else if (cnt > decoder->max_loops ||
1239f4aa0819SAdrian Hunter 				   decoder->state.to_ip == decoder->stuck_ip) {
1240f4aa0819SAdrian Hunter 				intel_pt_log_at("ERROR: Never-ending loop",
1241f4aa0819SAdrian Hunter 						decoder->state.to_ip);
1242f4aa0819SAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
1243f4aa0819SAdrian Hunter 				err = -ELOOP;
1244f4aa0819SAdrian Hunter 				goto out;
1245f4aa0819SAdrian Hunter 			} else if (!--decoder->stuck_ip_cnt) {
1246f4aa0819SAdrian Hunter 				decoder->stuck_ip_prd += 1;
1247f4aa0819SAdrian Hunter 				decoder->stuck_ip_cnt = decoder->stuck_ip_prd;
1248f4aa0819SAdrian Hunter 				decoder->stuck_ip = decoder->state.to_ip;
1249f4aa0819SAdrian Hunter 			}
1250f4aa0819SAdrian Hunter 		}
1251f4aa0819SAdrian Hunter 		goto out_no_progress;
1252f4aa0819SAdrian Hunter 	}
1253f4aa0819SAdrian Hunter out:
1254f4aa0819SAdrian Hunter 	decoder->no_progress = 0;
1255f4aa0819SAdrian Hunter out_no_progress:
1256f4aa0819SAdrian Hunter 	decoder->state.insn_op = intel_pt_insn->op;
1257f4aa0819SAdrian Hunter 	decoder->state.insn_len = intel_pt_insn->length;
1258faaa8768SAndi Kleen 	memcpy(decoder->state.insn, intel_pt_insn->buf,
1259faaa8768SAndi Kleen 	       INTEL_PT_INSN_BUF_SZ);
1260f4aa0819SAdrian Hunter 
1261f4aa0819SAdrian Hunter 	if (decoder->tx_flags & INTEL_PT_IN_TX)
1262f4aa0819SAdrian Hunter 		decoder->state.flags |= INTEL_PT_IN_TX;
1263f4aa0819SAdrian Hunter 
1264f4aa0819SAdrian Hunter 	return err;
1265f4aa0819SAdrian Hunter }
1266f4aa0819SAdrian Hunter 
intel_pt_mode_exec_status(struct intel_pt_decoder * decoder)1267cf0c98e2SAdrian Hunter static void intel_pt_mode_exec_status(struct intel_pt_decoder *decoder)
1268cf0c98e2SAdrian Hunter {
1269cf0c98e2SAdrian Hunter 	bool iflag = decoder->packet.count & INTEL_PT_IFLAG;
1270cf0c98e2SAdrian Hunter 
1271cf0c98e2SAdrian Hunter 	decoder->exec_mode = decoder->packet.payload;
1272cf0c98e2SAdrian Hunter 	decoder->iflag = iflag;
1273cf0c98e2SAdrian Hunter 	decoder->next_iflag = iflag;
1274cf0c98e2SAdrian Hunter 	decoder->state.from_iflag = iflag;
1275cf0c98e2SAdrian Hunter 	decoder->state.to_iflag = iflag;
1276cf0c98e2SAdrian Hunter }
1277cf0c98e2SAdrian Hunter 
intel_pt_mode_exec(struct intel_pt_decoder * decoder)1278cf0c98e2SAdrian Hunter static void intel_pt_mode_exec(struct intel_pt_decoder *decoder)
1279cf0c98e2SAdrian Hunter {
1280cf0c98e2SAdrian Hunter 	bool iflag = decoder->packet.count & INTEL_PT_IFLAG;
1281cf0c98e2SAdrian Hunter 
1282cf0c98e2SAdrian Hunter 	decoder->exec_mode = decoder->packet.payload;
1283cf0c98e2SAdrian Hunter 	decoder->next_iflag = iflag;
1284cf0c98e2SAdrian Hunter }
1285cf0c98e2SAdrian Hunter 
intel_pt_sample_iflag(struct intel_pt_decoder * decoder)1286cf0c98e2SAdrian Hunter static void intel_pt_sample_iflag(struct intel_pt_decoder *decoder)
1287cf0c98e2SAdrian Hunter {
1288cf0c98e2SAdrian Hunter 	decoder->state.type |= INTEL_PT_IFLAG_CHG;
1289cf0c98e2SAdrian Hunter 	decoder->state.from_iflag = decoder->iflag;
1290cf0c98e2SAdrian Hunter 	decoder->state.to_iflag = decoder->next_iflag;
1291cf0c98e2SAdrian Hunter 	decoder->iflag = decoder->next_iflag;
1292cf0c98e2SAdrian Hunter }
1293cf0c98e2SAdrian Hunter 
intel_pt_sample_iflag_chg(struct intel_pt_decoder * decoder)1294cf0c98e2SAdrian Hunter static void intel_pt_sample_iflag_chg(struct intel_pt_decoder *decoder)
1295cf0c98e2SAdrian Hunter {
1296cf0c98e2SAdrian Hunter 	if (decoder->iflag != decoder->next_iflag)
1297cf0c98e2SAdrian Hunter 		intel_pt_sample_iflag(decoder);
1298cf0c98e2SAdrian Hunter }
1299cf0c98e2SAdrian Hunter 
intel_pt_clear_fup_event(struct intel_pt_decoder * decoder)130068ff3cbaSAdrian Hunter static void intel_pt_clear_fup_event(struct intel_pt_decoder *decoder)
130168ff3cbaSAdrian Hunter {
130268ff3cbaSAdrian Hunter 	decoder->set_fup_tx_flags = false;
130368ff3cbaSAdrian Hunter 	decoder->set_fup_ptw = false;
130468ff3cbaSAdrian Hunter 	decoder->set_fup_mwait = false;
130568ff3cbaSAdrian Hunter 	decoder->set_fup_pwre = false;
130668ff3cbaSAdrian Hunter 	decoder->set_fup_exstop = false;
130768ff3cbaSAdrian Hunter 	decoder->set_fup_bep = false;
13083733a98bSAdrian Hunter 	decoder->set_fup_cfe_ip = false;
13093733a98bSAdrian Hunter 	decoder->set_fup_cfe = false;
13103733a98bSAdrian Hunter 	decoder->evd_cnt = 0;
1311cf0c98e2SAdrian Hunter 	decoder->set_fup_mode_exec = false;
1312cf0c98e2SAdrian Hunter 	decoder->iflag = decoder->next_iflag;
131368ff3cbaSAdrian Hunter }
131468ff3cbaSAdrian Hunter 
intel_pt_fup_event(struct intel_pt_decoder * decoder,bool no_tip)1315cf0c98e2SAdrian Hunter static bool intel_pt_fup_event(struct intel_pt_decoder *decoder, bool no_tip)
1316a472e65fSAdrian Hunter {
13174c761d80SAdrian Hunter 	enum intel_pt_sample_type type = decoder->state.type;
1318cf0c98e2SAdrian Hunter 	bool sample_fup_insn = false;
1319a472e65fSAdrian Hunter 	bool ret = false;
1320a472e65fSAdrian Hunter 
13214c761d80SAdrian Hunter 	decoder->state.type &= ~INTEL_PT_BRANCH;
1322*e101a05fSAdrian Hunter 	decoder->state.insn_op = INTEL_PT_OP_OTHER;
1323*e101a05fSAdrian Hunter 	decoder->state.insn_len = 0;
13244c761d80SAdrian Hunter 
13253733a98bSAdrian Hunter 	if (decoder->set_fup_cfe_ip || decoder->set_fup_cfe) {
13263733a98bSAdrian Hunter 		bool ip = decoder->set_fup_cfe_ip;
13273733a98bSAdrian Hunter 
13283733a98bSAdrian Hunter 		decoder->set_fup_cfe_ip = false;
13293733a98bSAdrian Hunter 		decoder->set_fup_cfe = false;
13303733a98bSAdrian Hunter 		decoder->state.type |= INTEL_PT_EVT;
13313733a98bSAdrian Hunter 		if (!ip && decoder->pge)
13323733a98bSAdrian Hunter 			decoder->state.type |= INTEL_PT_BRANCH;
13333733a98bSAdrian Hunter 		decoder->state.cfe_type = decoder->fup_cfe_pkt.count;
13343733a98bSAdrian Hunter 		decoder->state.cfe_vector = decoder->fup_cfe_pkt.payload;
13353733a98bSAdrian Hunter 		decoder->state.evd_cnt = decoder->evd_cnt;
13363733a98bSAdrian Hunter 		decoder->state.evd = decoder->evd;
13373733a98bSAdrian Hunter 		decoder->evd_cnt = 0;
13383733a98bSAdrian Hunter 		if (ip || decoder->pge)
13393733a98bSAdrian Hunter 			decoder->state.flags |= INTEL_PT_FUP_IP;
13403733a98bSAdrian Hunter 		ret = true;
13413733a98bSAdrian Hunter 	}
1342cf0c98e2SAdrian Hunter 	if (decoder->set_fup_mode_exec) {
1343cf0c98e2SAdrian Hunter 		decoder->set_fup_mode_exec = false;
1344cf0c98e2SAdrian Hunter 		intel_pt_sample_iflag(decoder);
1345cf0c98e2SAdrian Hunter 		sample_fup_insn = no_tip;
1346cf0c98e2SAdrian Hunter 		ret = true;
1347cf0c98e2SAdrian Hunter 	}
1348a472e65fSAdrian Hunter 	if (decoder->set_fup_tx_flags) {
1349a472e65fSAdrian Hunter 		decoder->set_fup_tx_flags = false;
1350a472e65fSAdrian Hunter 		decoder->tx_flags = decoder->fup_tx_flags;
13514c761d80SAdrian Hunter 		decoder->state.type |= INTEL_PT_TRANSACTION;
1352cb798783SAdrian Hunter 		if (decoder->fup_tx_flags & INTEL_PT_ABORT_TX)
1353cb798783SAdrian Hunter 			decoder->state.type |= INTEL_PT_BRANCH;
1354a472e65fSAdrian Hunter 		decoder->state.flags = decoder->fup_tx_flags;
13554c761d80SAdrian Hunter 		ret = true;
1356a472e65fSAdrian Hunter 	}
1357a472e65fSAdrian Hunter 	if (decoder->set_fup_ptw) {
1358a472e65fSAdrian Hunter 		decoder->set_fup_ptw = false;
13594c761d80SAdrian Hunter 		decoder->state.type |= INTEL_PT_PTW;
1360a472e65fSAdrian Hunter 		decoder->state.flags |= INTEL_PT_FUP_IP;
1361a472e65fSAdrian Hunter 		decoder->state.ptw_payload = decoder->fup_ptw_payload;
13624c761d80SAdrian Hunter 		ret = true;
1363a472e65fSAdrian Hunter 	}
1364a472e65fSAdrian Hunter 	if (decoder->set_fup_mwait) {
1365a472e65fSAdrian Hunter 		decoder->set_fup_mwait = false;
13664c761d80SAdrian Hunter 		decoder->state.type |= INTEL_PT_MWAIT_OP;
1367a472e65fSAdrian Hunter 		decoder->state.mwait_payload = decoder->fup_mwait_payload;
1368a472e65fSAdrian Hunter 		ret = true;
1369a472e65fSAdrian Hunter 	}
1370a472e65fSAdrian Hunter 	if (decoder->set_fup_pwre) {
1371a472e65fSAdrian Hunter 		decoder->set_fup_pwre = false;
1372a472e65fSAdrian Hunter 		decoder->state.type |= INTEL_PT_PWR_ENTRY;
1373a472e65fSAdrian Hunter 		decoder->state.pwre_payload = decoder->fup_pwre_payload;
1374a472e65fSAdrian Hunter 		ret = true;
1375a472e65fSAdrian Hunter 	}
1376a472e65fSAdrian Hunter 	if (decoder->set_fup_exstop) {
1377a472e65fSAdrian Hunter 		decoder->set_fup_exstop = false;
1378a472e65fSAdrian Hunter 		decoder->state.type |= INTEL_PT_EX_STOP;
1379a472e65fSAdrian Hunter 		decoder->state.flags |= INTEL_PT_FUP_IP;
1380a472e65fSAdrian Hunter 		ret = true;
1381a472e65fSAdrian Hunter 	}
13824c35595eSAdrian Hunter 	if (decoder->set_fup_bep) {
13834c35595eSAdrian Hunter 		decoder->set_fup_bep = false;
13844c35595eSAdrian Hunter 		decoder->state.type |= INTEL_PT_BLK_ITEMS;
13854c761d80SAdrian Hunter 		ret = true;
13864c761d80SAdrian Hunter 	}
1387c79ee2b2SAdrian Hunter 	if (decoder->overflow) {
1388c79ee2b2SAdrian Hunter 		decoder->overflow = false;
1389c79ee2b2SAdrian Hunter 		if (!ret && !decoder->pge) {
1390c79ee2b2SAdrian Hunter 			if (decoder->hop) {
1391c79ee2b2SAdrian Hunter 				decoder->state.type = 0;
1392c79ee2b2SAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
1393c79ee2b2SAdrian Hunter 			}
1394c79ee2b2SAdrian Hunter 			decoder->pge = true;
1395c79ee2b2SAdrian Hunter 			decoder->state.type |= INTEL_PT_BRANCH | INTEL_PT_TRACE_BEGIN;
1396c79ee2b2SAdrian Hunter 			decoder->state.from_ip = 0;
1397c79ee2b2SAdrian Hunter 			decoder->state.to_ip = decoder->ip;
1398c79ee2b2SAdrian Hunter 			return true;
1399c79ee2b2SAdrian Hunter 		}
1400c79ee2b2SAdrian Hunter 	}
14014c761d80SAdrian Hunter 	if (ret) {
14024c35595eSAdrian Hunter 		decoder->state.from_ip = decoder->ip;
14034c35595eSAdrian Hunter 		decoder->state.to_ip = 0;
1404cf0c98e2SAdrian Hunter 		if (sample_fup_insn)
1405cf0c98e2SAdrian Hunter 			intel_pt_sample_fup_insn(decoder);
14064c761d80SAdrian Hunter 	} else {
14074c761d80SAdrian Hunter 		decoder->state.type = type;
14084c35595eSAdrian Hunter 	}
1409a472e65fSAdrian Hunter 	return ret;
1410a472e65fSAdrian Hunter }
1411a472e65fSAdrian Hunter 
intel_pt_fup_with_nlip(struct intel_pt_decoder * decoder,struct intel_pt_insn * intel_pt_insn,uint64_t ip,int err)14129fb52336SAdrian Hunter static inline bool intel_pt_fup_with_nlip(struct intel_pt_decoder *decoder,
14139fb52336SAdrian Hunter 					  struct intel_pt_insn *intel_pt_insn,
14149fb52336SAdrian Hunter 					  uint64_t ip, int err)
14159fb52336SAdrian Hunter {
14169fb52336SAdrian Hunter 	return decoder->flags & INTEL_PT_FUP_WITH_NLIP && !err &&
14179fb52336SAdrian Hunter 	       intel_pt_insn->branch == INTEL_PT_BR_INDIRECT &&
14189fb52336SAdrian Hunter 	       ip == decoder->ip + intel_pt_insn->length;
14199fb52336SAdrian Hunter }
14209fb52336SAdrian Hunter 
intel_pt_walk_fup(struct intel_pt_decoder * decoder)1421f4aa0819SAdrian Hunter static int intel_pt_walk_fup(struct intel_pt_decoder *decoder)
1422f4aa0819SAdrian Hunter {
1423f4aa0819SAdrian Hunter 	struct intel_pt_insn intel_pt_insn;
1424f4aa0819SAdrian Hunter 	uint64_t ip;
1425f4aa0819SAdrian Hunter 	int err;
1426f4aa0819SAdrian Hunter 
1427f4aa0819SAdrian Hunter 	ip = decoder->last_ip;
1428f4aa0819SAdrian Hunter 
1429f4aa0819SAdrian Hunter 	while (1) {
1430f4aa0819SAdrian Hunter 		err = intel_pt_walk_insn(decoder, &intel_pt_insn, ip);
1431f4aa0819SAdrian Hunter 		if (err == INTEL_PT_RETURN)
1432f4aa0819SAdrian Hunter 			return 0;
14339fb52336SAdrian Hunter 		if (err == -EAGAIN ||
14349fb52336SAdrian Hunter 		    intel_pt_fup_with_nlip(decoder, &intel_pt_insn, ip, err)) {
1435cb798783SAdrian Hunter 			bool no_tip = decoder->pkt_state != INTEL_PT_STATE_FUP;
1436cb798783SAdrian Hunter 
1437401136bbSAdrian Hunter 			decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1438cf0c98e2SAdrian Hunter 			if (intel_pt_fup_event(decoder, no_tip) && no_tip)
1439f4aa0819SAdrian Hunter 				return 0;
14409fb52336SAdrian Hunter 			return -EAGAIN;
1441f4aa0819SAdrian Hunter 		}
1442f4aa0819SAdrian Hunter 		decoder->set_fup_tx_flags = false;
1443f4aa0819SAdrian Hunter 		if (err)
1444f4aa0819SAdrian Hunter 			return err;
1445f4aa0819SAdrian Hunter 
1446f4aa0819SAdrian Hunter 		if (intel_pt_insn.branch == INTEL_PT_BR_INDIRECT) {
1447f4aa0819SAdrian Hunter 			intel_pt_log_at("ERROR: Unexpected indirect branch",
1448f4aa0819SAdrian Hunter 					decoder->ip);
1449f4aa0819SAdrian Hunter 			decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
1450f4aa0819SAdrian Hunter 			return -ENOENT;
1451f4aa0819SAdrian Hunter 		}
1452f4aa0819SAdrian Hunter 
1453f4aa0819SAdrian Hunter 		if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) {
1454f4aa0819SAdrian Hunter 			intel_pt_log_at("ERROR: Unexpected conditional branch",
1455f4aa0819SAdrian Hunter 					decoder->ip);
1456f4aa0819SAdrian Hunter 			decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
1457f4aa0819SAdrian Hunter 			return -ENOENT;
1458f4aa0819SAdrian Hunter 		}
1459f4aa0819SAdrian Hunter 
1460f4aa0819SAdrian Hunter 		intel_pt_bug(decoder);
1461f4aa0819SAdrian Hunter 	}
1462f4aa0819SAdrian Hunter }
1463f4aa0819SAdrian Hunter 
intel_pt_walk_tip(struct intel_pt_decoder * decoder)1464f4aa0819SAdrian Hunter static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
1465f4aa0819SAdrian Hunter {
1466f4aa0819SAdrian Hunter 	struct intel_pt_insn intel_pt_insn;
1467f4aa0819SAdrian Hunter 	int err;
1468f4aa0819SAdrian Hunter 
1469f4aa0819SAdrian Hunter 	err = intel_pt_walk_insn(decoder, &intel_pt_insn, 0);
14709f1d122bSAdrian Hunter 	if (err == INTEL_PT_RETURN &&
14719f1d122bSAdrian Hunter 	    decoder->pgd_ip &&
14729f1d122bSAdrian Hunter 	    decoder->pkt_state == INTEL_PT_STATE_TIP_PGD &&
14739f1d122bSAdrian Hunter 	    (decoder->state.type & INTEL_PT_BRANCH) &&
14749f1d122bSAdrian Hunter 	    decoder->pgd_ip(decoder->state.to_ip, decoder->data)) {
14759f1d122bSAdrian Hunter 		/* Unconditional branch leaving filter region */
14769f1d122bSAdrian Hunter 		decoder->no_progress = 0;
14779f1d122bSAdrian Hunter 		decoder->pge = false;
14789f1d122bSAdrian Hunter 		decoder->continuous_period = false;
14799f1d122bSAdrian Hunter 		decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1480bea63857SAdrian Hunter 		decoder->state.type |= INTEL_PT_TRACE_END;
148180a03886SAdrian Hunter 		intel_pt_update_nr(decoder);
14829f1d122bSAdrian Hunter 		return 0;
14839f1d122bSAdrian Hunter 	}
1484f4aa0819SAdrian Hunter 	if (err == INTEL_PT_RETURN)
1485f4aa0819SAdrian Hunter 		return 0;
1486f4aa0819SAdrian Hunter 	if (err)
1487f4aa0819SAdrian Hunter 		return err;
1488f4aa0819SAdrian Hunter 
148980a03886SAdrian Hunter 	intel_pt_update_nr(decoder);
1490cf0c98e2SAdrian Hunter 	intel_pt_sample_iflag_chg(decoder);
149180a03886SAdrian Hunter 
1492f4aa0819SAdrian Hunter 	if (intel_pt_insn.branch == INTEL_PT_BR_INDIRECT) {
1493f4aa0819SAdrian Hunter 		if (decoder->pkt_state == INTEL_PT_STATE_TIP_PGD) {
1494f4aa0819SAdrian Hunter 			decoder->pge = false;
1495f4aa0819SAdrian Hunter 			decoder->continuous_period = false;
1496f4aa0819SAdrian Hunter 			decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1497f4aa0819SAdrian Hunter 			decoder->state.from_ip = decoder->ip;
1498bea63857SAdrian Hunter 			if (decoder->packet.count == 0) {
1499f4aa0819SAdrian Hunter 				decoder->state.to_ip = 0;
1500bea63857SAdrian Hunter 			} else {
1501bea63857SAdrian Hunter 				decoder->state.to_ip = decoder->last_ip;
1502f4aa0819SAdrian Hunter 				decoder->ip = decoder->last_ip;
1503bea63857SAdrian Hunter 			}
1504bea63857SAdrian Hunter 			decoder->state.type |= INTEL_PT_TRACE_END;
1505f4aa0819SAdrian Hunter 		} else {
1506f4aa0819SAdrian Hunter 			decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1507f4aa0819SAdrian Hunter 			decoder->state.from_ip = decoder->ip;
1508f4aa0819SAdrian Hunter 			if (decoder->packet.count == 0) {
1509f4aa0819SAdrian Hunter 				decoder->state.to_ip = 0;
1510f4aa0819SAdrian Hunter 			} else {
1511f4aa0819SAdrian Hunter 				decoder->state.to_ip = decoder->last_ip;
1512f4aa0819SAdrian Hunter 				decoder->ip = decoder->last_ip;
1513f4aa0819SAdrian Hunter 			}
1514f4aa0819SAdrian Hunter 		}
1515f4aa0819SAdrian Hunter 		return 0;
1516f4aa0819SAdrian Hunter 	}
1517f4aa0819SAdrian Hunter 
1518f4aa0819SAdrian Hunter 	if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) {
15199f1d122bSAdrian Hunter 		uint64_t to_ip = decoder->ip + intel_pt_insn.length +
15209f1d122bSAdrian Hunter 				 intel_pt_insn.rel;
15219f1d122bSAdrian Hunter 
15229f1d122bSAdrian Hunter 		if (decoder->pgd_ip &&
15239f1d122bSAdrian Hunter 		    decoder->pkt_state == INTEL_PT_STATE_TIP_PGD &&
15249f1d122bSAdrian Hunter 		    decoder->pgd_ip(to_ip, decoder->data)) {
15259f1d122bSAdrian Hunter 			/* Conditional branch leaving filter region */
15269f1d122bSAdrian Hunter 			decoder->pge = false;
15279f1d122bSAdrian Hunter 			decoder->continuous_period = false;
15289f1d122bSAdrian Hunter 			decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
15299f1d122bSAdrian Hunter 			decoder->ip = to_ip;
15309f1d122bSAdrian Hunter 			decoder->state.from_ip = decoder->ip;
1531bea63857SAdrian Hunter 			decoder->state.to_ip = to_ip;
1532bea63857SAdrian Hunter 			decoder->state.type |= INTEL_PT_TRACE_END;
15339f1d122bSAdrian Hunter 			return 0;
15349f1d122bSAdrian Hunter 		}
1535f4aa0819SAdrian Hunter 		intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch",
1536f4aa0819SAdrian Hunter 				decoder->ip);
1537f4aa0819SAdrian Hunter 		decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
1538f4aa0819SAdrian Hunter 		return -ENOENT;
1539f4aa0819SAdrian Hunter 	}
1540f4aa0819SAdrian Hunter 
1541f4aa0819SAdrian Hunter 	return intel_pt_bug(decoder);
1542f4aa0819SAdrian Hunter }
1543f4aa0819SAdrian Hunter 
1544d7015e50SAdrian Hunter struct eptw_data {
1545d7015e50SAdrian Hunter 	int bit_countdown;
1546d7015e50SAdrian Hunter 	uint64_t payload;
1547d7015e50SAdrian Hunter };
1548d7015e50SAdrian Hunter 
intel_pt_eptw_lookahead_cb(struct intel_pt_pkt_info * pkt_info)1549d7015e50SAdrian Hunter static int intel_pt_eptw_lookahead_cb(struct intel_pt_pkt_info *pkt_info)
1550d7015e50SAdrian Hunter {
1551d7015e50SAdrian Hunter 	struct eptw_data *data = pkt_info->data;
1552d7015e50SAdrian Hunter 	int nr_bits;
1553d7015e50SAdrian Hunter 
1554d7015e50SAdrian Hunter 	switch (pkt_info->packet.type) {
1555d7015e50SAdrian Hunter 	case INTEL_PT_PAD:
1556d7015e50SAdrian Hunter 	case INTEL_PT_MNT:
1557d7015e50SAdrian Hunter 	case INTEL_PT_MODE_EXEC:
1558d7015e50SAdrian Hunter 	case INTEL_PT_MODE_TSX:
1559d7015e50SAdrian Hunter 	case INTEL_PT_MTC:
1560d7015e50SAdrian Hunter 	case INTEL_PT_FUP:
1561d7015e50SAdrian Hunter 	case INTEL_PT_CYC:
1562d7015e50SAdrian Hunter 	case INTEL_PT_CBR:
1563d7015e50SAdrian Hunter 	case INTEL_PT_TSC:
1564d7015e50SAdrian Hunter 	case INTEL_PT_TMA:
1565d7015e50SAdrian Hunter 	case INTEL_PT_PIP:
1566d7015e50SAdrian Hunter 	case INTEL_PT_VMCS:
1567d7015e50SAdrian Hunter 	case INTEL_PT_PSB:
1568d7015e50SAdrian Hunter 	case INTEL_PT_PSBEND:
1569d7015e50SAdrian Hunter 	case INTEL_PT_PTWRITE:
1570d7015e50SAdrian Hunter 	case INTEL_PT_PTWRITE_IP:
1571d7015e50SAdrian Hunter 	case INTEL_PT_EXSTOP:
1572d7015e50SAdrian Hunter 	case INTEL_PT_EXSTOP_IP:
1573d7015e50SAdrian Hunter 	case INTEL_PT_MWAIT:
1574d7015e50SAdrian Hunter 	case INTEL_PT_PWRE:
1575d7015e50SAdrian Hunter 	case INTEL_PT_PWRX:
1576d7015e50SAdrian Hunter 	case INTEL_PT_BBP:
1577d7015e50SAdrian Hunter 	case INTEL_PT_BIP:
1578d7015e50SAdrian Hunter 	case INTEL_PT_BEP:
1579d7015e50SAdrian Hunter 	case INTEL_PT_BEP_IP:
1580d7015e50SAdrian Hunter 	case INTEL_PT_CFE:
1581d7015e50SAdrian Hunter 	case INTEL_PT_CFE_IP:
1582d7015e50SAdrian Hunter 	case INTEL_PT_EVD:
1583d7015e50SAdrian Hunter 		break;
1584d7015e50SAdrian Hunter 
1585d7015e50SAdrian Hunter 	case INTEL_PT_TNT:
1586d7015e50SAdrian Hunter 		nr_bits = data->bit_countdown;
1587d7015e50SAdrian Hunter 		if (nr_bits > pkt_info->packet.count)
1588d7015e50SAdrian Hunter 			nr_bits = pkt_info->packet.count;
1589d7015e50SAdrian Hunter 		data->payload <<= nr_bits;
1590d7015e50SAdrian Hunter 		data->payload |= pkt_info->packet.payload >> (64 - nr_bits);
1591d7015e50SAdrian Hunter 		data->bit_countdown -= nr_bits;
1592d7015e50SAdrian Hunter 		return !data->bit_countdown;
1593d7015e50SAdrian Hunter 
1594d7015e50SAdrian Hunter 	case INTEL_PT_TIP_PGE:
1595d7015e50SAdrian Hunter 	case INTEL_PT_TIP_PGD:
1596d7015e50SAdrian Hunter 	case INTEL_PT_TIP:
1597d7015e50SAdrian Hunter 	case INTEL_PT_BAD:
1598d7015e50SAdrian Hunter 	case INTEL_PT_OVF:
1599d7015e50SAdrian Hunter 	case INTEL_PT_TRACESTOP:
1600d7015e50SAdrian Hunter 	default:
1601d7015e50SAdrian Hunter 		return 1;
1602d7015e50SAdrian Hunter 	}
1603d7015e50SAdrian Hunter 
1604d7015e50SAdrian Hunter 	return 0;
1605d7015e50SAdrian Hunter }
1606d7015e50SAdrian Hunter 
intel_pt_emulated_ptwrite(struct intel_pt_decoder * decoder)1607d7015e50SAdrian Hunter static int intel_pt_emulated_ptwrite(struct intel_pt_decoder *decoder)
1608d7015e50SAdrian Hunter {
1609d7015e50SAdrian Hunter 	int n = 64 - decoder->tnt.count;
1610d7015e50SAdrian Hunter 	struct eptw_data data = {
1611d7015e50SAdrian Hunter 		.bit_countdown = n,
1612d7015e50SAdrian Hunter 		.payload = decoder->tnt.payload >> n,
1613d7015e50SAdrian Hunter 	};
1614d7015e50SAdrian Hunter 
1615d7015e50SAdrian Hunter 	decoder->emulated_ptwrite = false;
1616d7015e50SAdrian Hunter 	intel_pt_log("Emulated ptwrite detected\n");
1617d7015e50SAdrian Hunter 
1618d7015e50SAdrian Hunter 	intel_pt_pkt_lookahead(decoder, intel_pt_eptw_lookahead_cb, &data);
1619d7015e50SAdrian Hunter 	if (data.bit_countdown)
1620d7015e50SAdrian Hunter 		return -ECONNRESET;
1621d7015e50SAdrian Hunter 
1622d7015e50SAdrian Hunter 	decoder->state.type = INTEL_PT_PTW;
1623d7015e50SAdrian Hunter 	decoder->state.from_ip = decoder->ip;
1624d7015e50SAdrian Hunter 	decoder->state.to_ip = 0;
1625d7015e50SAdrian Hunter 	decoder->state.ptw_payload = data.payload;
1626d7015e50SAdrian Hunter 	return 0;
1627d7015e50SAdrian Hunter }
1628d7015e50SAdrian Hunter 
intel_pt_walk_tnt(struct intel_pt_decoder * decoder)1629f4aa0819SAdrian Hunter static int intel_pt_walk_tnt(struct intel_pt_decoder *decoder)
1630f4aa0819SAdrian Hunter {
1631f4aa0819SAdrian Hunter 	struct intel_pt_insn intel_pt_insn;
1632f4aa0819SAdrian Hunter 	int err;
1633f4aa0819SAdrian Hunter 
1634f4aa0819SAdrian Hunter 	while (1) {
1635d7015e50SAdrian Hunter 		if (decoder->emulated_ptwrite)
1636d7015e50SAdrian Hunter 			return intel_pt_emulated_ptwrite(decoder);
1637f4aa0819SAdrian Hunter 		err = intel_pt_walk_insn(decoder, &intel_pt_insn, 0);
1638d7015e50SAdrian Hunter 		if (err == INTEL_PT_RETURN) {
1639d7015e50SAdrian Hunter 			decoder->emulated_ptwrite = intel_pt_insn.emulated_ptwrite;
1640f4aa0819SAdrian Hunter 			return 0;
1641d7015e50SAdrian Hunter 		}
1642d7015e50SAdrian Hunter 		if (err) {
1643d7015e50SAdrian Hunter 			decoder->emulated_ptwrite = false;
1644f4aa0819SAdrian Hunter 			return err;
1645d7015e50SAdrian Hunter 		}
1646f4aa0819SAdrian Hunter 
1647f4aa0819SAdrian Hunter 		if (intel_pt_insn.op == INTEL_PT_OP_RET) {
1648f4aa0819SAdrian Hunter 			if (!decoder->return_compression) {
1649f4aa0819SAdrian Hunter 				intel_pt_log_at("ERROR: RET when expecting conditional branch",
1650f4aa0819SAdrian Hunter 						decoder->ip);
1651f4aa0819SAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_ERR3;
1652f4aa0819SAdrian Hunter 				return -ENOENT;
1653f4aa0819SAdrian Hunter 			}
1654f4aa0819SAdrian Hunter 			if (!decoder->ret_addr) {
1655f4aa0819SAdrian Hunter 				intel_pt_log_at("ERROR: Bad RET compression (stack empty)",
1656f4aa0819SAdrian Hunter 						decoder->ip);
1657f4aa0819SAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_ERR3;
1658f4aa0819SAdrian Hunter 				return -ENOENT;
1659f4aa0819SAdrian Hunter 			}
1660f4aa0819SAdrian Hunter 			if (!(decoder->tnt.payload & BIT63)) {
1661f4aa0819SAdrian Hunter 				intel_pt_log_at("ERROR: Bad RET compression (TNT=N)",
1662f4aa0819SAdrian Hunter 						decoder->ip);
1663f4aa0819SAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_ERR3;
1664f4aa0819SAdrian Hunter 				return -ENOENT;
1665f4aa0819SAdrian Hunter 			}
1666f4aa0819SAdrian Hunter 			decoder->tnt.count -= 1;
166761b6e08dSAdrian Hunter 			if (decoder->tnt.count)
166861b6e08dSAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_TNT_CONT;
166961b6e08dSAdrian Hunter 			else
1670f4aa0819SAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1671f4aa0819SAdrian Hunter 			decoder->tnt.payload <<= 1;
1672f4aa0819SAdrian Hunter 			decoder->state.from_ip = decoder->ip;
1673f4aa0819SAdrian Hunter 			decoder->ip = decoder->ret_addr;
1674f4aa0819SAdrian Hunter 			decoder->state.to_ip = decoder->ip;
1675f4aa0819SAdrian Hunter 			return 0;
1676f4aa0819SAdrian Hunter 		}
1677f4aa0819SAdrian Hunter 
1678f4aa0819SAdrian Hunter 		if (intel_pt_insn.branch == INTEL_PT_BR_INDIRECT) {
1679f4aa0819SAdrian Hunter 			/* Handle deferred TIPs */
1680f4aa0819SAdrian Hunter 			err = intel_pt_get_next_packet(decoder);
1681f4aa0819SAdrian Hunter 			if (err)
1682f4aa0819SAdrian Hunter 				return err;
1683f4aa0819SAdrian Hunter 			if (decoder->packet.type != INTEL_PT_TIP ||
1684f4aa0819SAdrian Hunter 			    decoder->packet.count == 0) {
1685f4aa0819SAdrian Hunter 				intel_pt_log_at("ERROR: Missing deferred TIP for indirect branch",
1686f4aa0819SAdrian Hunter 						decoder->ip);
1687f4aa0819SAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_ERR3;
1688f4aa0819SAdrian Hunter 				decoder->pkt_step = 0;
1689f4aa0819SAdrian Hunter 				return -ENOENT;
1690f4aa0819SAdrian Hunter 			}
1691f4aa0819SAdrian Hunter 			intel_pt_set_last_ip(decoder);
1692f4aa0819SAdrian Hunter 			decoder->state.from_ip = decoder->ip;
1693f4aa0819SAdrian Hunter 			decoder->state.to_ip = decoder->last_ip;
1694f4aa0819SAdrian Hunter 			decoder->ip = decoder->last_ip;
169580a03886SAdrian Hunter 			intel_pt_update_nr(decoder);
1696cf0c98e2SAdrian Hunter 			intel_pt_sample_iflag_chg(decoder);
1697f4aa0819SAdrian Hunter 			return 0;
1698f4aa0819SAdrian Hunter 		}
1699f4aa0819SAdrian Hunter 
1700f4aa0819SAdrian Hunter 		if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) {
1701f4aa0819SAdrian Hunter 			decoder->tnt.count -= 1;
170261b6e08dSAdrian Hunter 			if (decoder->tnt.count)
170361b6e08dSAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_TNT_CONT;
170461b6e08dSAdrian Hunter 			else
1705f4aa0819SAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1706f4aa0819SAdrian Hunter 			if (decoder->tnt.payload & BIT63) {
1707f4aa0819SAdrian Hunter 				decoder->tnt.payload <<= 1;
1708f4aa0819SAdrian Hunter 				decoder->state.from_ip = decoder->ip;
1709f4aa0819SAdrian Hunter 				decoder->ip += intel_pt_insn.length +
1710f4aa0819SAdrian Hunter 					       intel_pt_insn.rel;
1711f4aa0819SAdrian Hunter 				decoder->state.to_ip = decoder->ip;
1712f4aa0819SAdrian Hunter 				return 0;
1713f4aa0819SAdrian Hunter 			}
1714f4aa0819SAdrian Hunter 			/* Instruction sample for a non-taken branch */
1715f4aa0819SAdrian Hunter 			if (decoder->state.type & INTEL_PT_INSTRUCTION) {
1716f4aa0819SAdrian Hunter 				decoder->tnt.payload <<= 1;
1717f4aa0819SAdrian Hunter 				decoder->state.type = INTEL_PT_INSTRUCTION;
1718f4aa0819SAdrian Hunter 				decoder->state.from_ip = decoder->ip;
1719f4aa0819SAdrian Hunter 				decoder->state.to_ip = 0;
1720f4aa0819SAdrian Hunter 				decoder->ip += intel_pt_insn.length;
1721f4aa0819SAdrian Hunter 				return 0;
1722f4aa0819SAdrian Hunter 			}
17237b4b4f83SAdrian Hunter 			decoder->sample_cyc = false;
1724f4aa0819SAdrian Hunter 			decoder->ip += intel_pt_insn.length;
17251b6599a9SAdrian Hunter 			if (!decoder->tnt.count) {
1726948e9dc8SAdrian Hunter 				intel_pt_update_sample_time(decoder);
1727f4aa0819SAdrian Hunter 				return -EAGAIN;
17281b6599a9SAdrian Hunter 			}
1729f4aa0819SAdrian Hunter 			decoder->tnt.payload <<= 1;
1730f4aa0819SAdrian Hunter 			continue;
1731f4aa0819SAdrian Hunter 		}
1732f4aa0819SAdrian Hunter 
1733f4aa0819SAdrian Hunter 		return intel_pt_bug(decoder);
1734f4aa0819SAdrian Hunter 	}
1735f4aa0819SAdrian Hunter }
1736f4aa0819SAdrian Hunter 
intel_pt_mode_tsx(struct intel_pt_decoder * decoder,bool * no_tip)1737f4aa0819SAdrian Hunter static int intel_pt_mode_tsx(struct intel_pt_decoder *decoder, bool *no_tip)
1738f4aa0819SAdrian Hunter {
1739f4aa0819SAdrian Hunter 	unsigned int fup_tx_flags;
1740f4aa0819SAdrian Hunter 	int err;
1741f4aa0819SAdrian Hunter 
1742f4aa0819SAdrian Hunter 	fup_tx_flags = decoder->packet.payload &
1743f4aa0819SAdrian Hunter 		       (INTEL_PT_IN_TX | INTEL_PT_ABORT_TX);
1744f4aa0819SAdrian Hunter 	err = intel_pt_get_next_packet(decoder);
1745f4aa0819SAdrian Hunter 	if (err)
1746f4aa0819SAdrian Hunter 		return err;
1747f4aa0819SAdrian Hunter 	if (decoder->packet.type == INTEL_PT_FUP) {
1748f4aa0819SAdrian Hunter 		decoder->fup_tx_flags = fup_tx_flags;
1749f4aa0819SAdrian Hunter 		decoder->set_fup_tx_flags = true;
1750f4aa0819SAdrian Hunter 		if (!(decoder->fup_tx_flags & INTEL_PT_ABORT_TX))
1751f4aa0819SAdrian Hunter 			*no_tip = true;
1752f4aa0819SAdrian Hunter 	} else {
1753f4aa0819SAdrian Hunter 		intel_pt_log_at("ERROR: Missing FUP after MODE.TSX",
1754f4aa0819SAdrian Hunter 				decoder->pos);
1755f4aa0819SAdrian Hunter 		intel_pt_update_in_tx(decoder);
1756f4aa0819SAdrian Hunter 	}
1757f4aa0819SAdrian Hunter 	return 0;
1758f4aa0819SAdrian Hunter }
1759f4aa0819SAdrian Hunter 
intel_pt_evd(struct intel_pt_decoder * decoder)17603733a98bSAdrian Hunter static int intel_pt_evd(struct intel_pt_decoder *decoder)
17613733a98bSAdrian Hunter {
17623733a98bSAdrian Hunter 	if (decoder->evd_cnt >= INTEL_PT_MAX_EVDS) {
17633733a98bSAdrian Hunter 		intel_pt_log_at("ERROR: Too many EVD packets", decoder->pos);
17643733a98bSAdrian Hunter 		return -ENOSYS;
17653733a98bSAdrian Hunter 	}
17663733a98bSAdrian Hunter 	decoder->evd[decoder->evd_cnt++] = (struct intel_pt_evd){
17673733a98bSAdrian Hunter 		.type = decoder->packet.count,
17683733a98bSAdrian Hunter 		.payload = decoder->packet.payload,
17693733a98bSAdrian Hunter 	};
17703733a98bSAdrian Hunter 	return 0;
17713733a98bSAdrian Hunter }
17723733a98bSAdrian Hunter 
intel_pt_8b_tsc(uint64_t timestamp,uint64_t ref_timestamp)1773e72b52a2SAdrian Hunter static uint64_t intel_pt_8b_tsc(uint64_t timestamp, uint64_t ref_timestamp)
1774e72b52a2SAdrian Hunter {
1775e72b52a2SAdrian Hunter 	timestamp |= (ref_timestamp & (0xffULL << 56));
1776e72b52a2SAdrian Hunter 
1777e72b52a2SAdrian Hunter 	if (timestamp < ref_timestamp) {
1778e72b52a2SAdrian Hunter 		if (ref_timestamp - timestamp > (1ULL << 55))
1779e72b52a2SAdrian Hunter 			timestamp += (1ULL << 56);
1780e72b52a2SAdrian Hunter 	} else {
1781e72b52a2SAdrian Hunter 		if (timestamp - ref_timestamp > (1ULL << 55))
1782e72b52a2SAdrian Hunter 			timestamp -= (1ULL << 56);
1783e72b52a2SAdrian Hunter 	}
1784e72b52a2SAdrian Hunter 
1785e72b52a2SAdrian Hunter 	return timestamp;
1786e72b52a2SAdrian Hunter }
1787e72b52a2SAdrian Hunter 
1788fa8f949dSAdrian Hunter /* For use only when decoder->vm_time_correlation is true */
intel_pt_time_in_range(struct intel_pt_decoder * decoder,uint64_t timestamp)1789fa8f949dSAdrian Hunter static bool intel_pt_time_in_range(struct intel_pt_decoder *decoder,
1790fa8f949dSAdrian Hunter 				   uint64_t timestamp)
1791fa8f949dSAdrian Hunter {
1792fa8f949dSAdrian Hunter 	uint64_t max_timestamp = decoder->buf_timestamp;
1793fa8f949dSAdrian Hunter 
1794fa8f949dSAdrian Hunter 	if (!max_timestamp) {
1795fa8f949dSAdrian Hunter 		max_timestamp = decoder->last_reliable_timestamp +
1796fa8f949dSAdrian Hunter 				0x400000000ULL;
1797fa8f949dSAdrian Hunter 	}
1798fa8f949dSAdrian Hunter 	return timestamp >= decoder->last_reliable_timestamp &&
1799fa8f949dSAdrian Hunter 	       timestamp < decoder->buf_timestamp;
1800fa8f949dSAdrian Hunter }
1801fa8f949dSAdrian Hunter 
intel_pt_calc_tsc_timestamp(struct intel_pt_decoder * decoder)1802f4aa0819SAdrian Hunter static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder)
1803f4aa0819SAdrian Hunter {
1804f4aa0819SAdrian Hunter 	uint64_t timestamp;
1805fa8f949dSAdrian Hunter 	bool bad = false;
1806f4aa0819SAdrian Hunter 
180779b58424SAdrian Hunter 	decoder->have_tma = false;
180879b58424SAdrian Hunter 
1809f4aa0819SAdrian Hunter 	if (decoder->ref_timestamp) {
1810e72b52a2SAdrian Hunter 		timestamp = intel_pt_8b_tsc(decoder->packet.payload,
1811e72b52a2SAdrian Hunter 					    decoder->ref_timestamp);
1812f4aa0819SAdrian Hunter 		decoder->tsc_timestamp = timestamp;
1813f4aa0819SAdrian Hunter 		decoder->timestamp = timestamp;
1814f4aa0819SAdrian Hunter 		decoder->ref_timestamp = 0;
1815f4aa0819SAdrian Hunter 		decoder->timestamp_insn_cnt = 0;
1816f4aa0819SAdrian Hunter 	} else if (decoder->timestamp) {
1817f4aa0819SAdrian Hunter 		timestamp = decoder->packet.payload |
1818f4aa0819SAdrian Hunter 			    (decoder->timestamp & (0xffULL << 56));
181979b58424SAdrian Hunter 		decoder->tsc_timestamp = timestamp;
1820f4aa0819SAdrian Hunter 		if (timestamp < decoder->timestamp &&
182179b58424SAdrian Hunter 		    decoder->timestamp - timestamp < decoder->tsc_slip) {
182279b58424SAdrian Hunter 			intel_pt_log_to("Suppressing backwards timestamp",
1823f4aa0819SAdrian Hunter 					timestamp);
1824f4aa0819SAdrian Hunter 			timestamp = decoder->timestamp;
1825f4aa0819SAdrian Hunter 		}
18269992c2d5SAdrian Hunter 		if (timestamp < decoder->timestamp) {
182731c7e27dSAdrian Hunter 			if (!decoder->buf_timestamp ||
182831c7e27dSAdrian Hunter 			    (timestamp + (1ULL << 56) < decoder->buf_timestamp)) {
1829f4aa0819SAdrian Hunter 				intel_pt_log_to("Wraparound timestamp", timestamp);
1830f4aa0819SAdrian Hunter 				timestamp += (1ULL << 56);
1831f4aa0819SAdrian Hunter 				decoder->tsc_timestamp = timestamp;
183231c7e27dSAdrian Hunter 			} else {
183331c7e27dSAdrian Hunter 				intel_pt_log_to("Suppressing bad timestamp", timestamp);
183431c7e27dSAdrian Hunter 				timestamp = decoder->timestamp;
1835fa8f949dSAdrian Hunter 				bad = true;
183631c7e27dSAdrian Hunter 			}
183779b58424SAdrian Hunter 		}
1838fa8f949dSAdrian Hunter 		if (decoder->vm_time_correlation &&
1839fa8f949dSAdrian Hunter 		    (bad || !intel_pt_time_in_range(decoder, timestamp)) &&
1840fa8f949dSAdrian Hunter 		    intel_pt_print_once(decoder, INTEL_PT_PRT_ONCE_ERANGE))
1841fa8f949dSAdrian Hunter 			p_log("Timestamp out of range");
1842f4aa0819SAdrian Hunter 		decoder->timestamp = timestamp;
1843f4aa0819SAdrian Hunter 		decoder->timestamp_insn_cnt = 0;
1844f4aa0819SAdrian Hunter 	}
1845f4aa0819SAdrian Hunter 
1846cc336186SAdrian Hunter 	if (decoder->last_packet_type == INTEL_PT_CYC) {
1847cc336186SAdrian Hunter 		decoder->cyc_ref_timestamp = decoder->timestamp;
1848cc336186SAdrian Hunter 		decoder->cycle_cnt = 0;
1849cc336186SAdrian Hunter 		decoder->have_calc_cyc_to_tsc = false;
1850cc336186SAdrian Hunter 		intel_pt_calc_cyc_to_tsc(decoder, false);
1851cc336186SAdrian Hunter 	}
1852cc336186SAdrian Hunter 
1853f4aa0819SAdrian Hunter 	intel_pt_log_to("Setting timestamp", decoder->timestamp);
1854f4aa0819SAdrian Hunter }
1855f4aa0819SAdrian Hunter 
intel_pt_overflow(struct intel_pt_decoder * decoder)1856f4aa0819SAdrian Hunter static int intel_pt_overflow(struct intel_pt_decoder *decoder)
1857f4aa0819SAdrian Hunter {
1858f4aa0819SAdrian Hunter 	intel_pt_log("ERROR: Buffer overflow\n");
1859f4aa0819SAdrian Hunter 	intel_pt_clear_tx_flags(decoder);
186080a03886SAdrian Hunter 	intel_pt_set_nr(decoder);
186191d29b28SAdrian Hunter 	decoder->timestamp_insn_cnt = 0;
1862c79ee2b2SAdrian Hunter 	decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1863c79ee2b2SAdrian Hunter 	decoder->state.from_ip = decoder->ip;
1864c79ee2b2SAdrian Hunter 	decoder->ip = 0;
1865c79ee2b2SAdrian Hunter 	decoder->pge = false;
186668ff3cbaSAdrian Hunter 	intel_pt_clear_fup_event(decoder);
1867f4aa0819SAdrian Hunter 	decoder->overflow = true;
1868f4aa0819SAdrian Hunter 	return -EOVERFLOW;
1869f4aa0819SAdrian Hunter }
1870f4aa0819SAdrian Hunter 
intel_pt_mtc_cyc_cnt_pge(struct intel_pt_decoder * decoder)18713f055167SAdrian Hunter static inline void intel_pt_mtc_cyc_cnt_pge(struct intel_pt_decoder *decoder)
18723f055167SAdrian Hunter {
18733f055167SAdrian Hunter 	if (decoder->have_cyc)
18743f055167SAdrian Hunter 		return;
18753f055167SAdrian Hunter 
18763f055167SAdrian Hunter 	decoder->cyc_cnt_timestamp = decoder->timestamp;
18773f055167SAdrian Hunter 	decoder->base_cyc_cnt = decoder->tot_cyc_cnt;
18783f055167SAdrian Hunter }
18793f055167SAdrian Hunter 
intel_pt_mtc_cyc_cnt_cbr(struct intel_pt_decoder * decoder)18803f055167SAdrian Hunter static inline void intel_pt_mtc_cyc_cnt_cbr(struct intel_pt_decoder *decoder)
18813f055167SAdrian Hunter {
18823f055167SAdrian Hunter 	decoder->tsc_to_cyc = decoder->cbr / decoder->max_non_turbo_ratio_fp;
18833f055167SAdrian Hunter 
18843f055167SAdrian Hunter 	if (decoder->pge)
18853f055167SAdrian Hunter 		intel_pt_mtc_cyc_cnt_pge(decoder);
18863f055167SAdrian Hunter }
18873f055167SAdrian Hunter 
intel_pt_mtc_cyc_cnt_upd(struct intel_pt_decoder * decoder)18883f055167SAdrian Hunter static inline void intel_pt_mtc_cyc_cnt_upd(struct intel_pt_decoder *decoder)
18893f055167SAdrian Hunter {
18903f055167SAdrian Hunter 	uint64_t tot_cyc_cnt, tsc_delta;
18913f055167SAdrian Hunter 
18923f055167SAdrian Hunter 	if (decoder->have_cyc)
18933f055167SAdrian Hunter 		return;
18943f055167SAdrian Hunter 
18953f055167SAdrian Hunter 	decoder->sample_cyc = true;
18963f055167SAdrian Hunter 
18973f055167SAdrian Hunter 	if (!decoder->pge || decoder->timestamp <= decoder->cyc_cnt_timestamp)
18983f055167SAdrian Hunter 		return;
18993f055167SAdrian Hunter 
19003f055167SAdrian Hunter 	tsc_delta = decoder->timestamp - decoder->cyc_cnt_timestamp;
19013f055167SAdrian Hunter 	tot_cyc_cnt = tsc_delta * decoder->tsc_to_cyc + decoder->base_cyc_cnt;
19023f055167SAdrian Hunter 
19033f055167SAdrian Hunter 	if (tot_cyc_cnt > decoder->tot_cyc_cnt)
19043f055167SAdrian Hunter 		decoder->tot_cyc_cnt = tot_cyc_cnt;
19053f055167SAdrian Hunter }
19063f055167SAdrian Hunter 
intel_pt_calc_tma(struct intel_pt_decoder * decoder)190779b58424SAdrian Hunter static void intel_pt_calc_tma(struct intel_pt_decoder *decoder)
190879b58424SAdrian Hunter {
190979b58424SAdrian Hunter 	uint32_t ctc = decoder->packet.payload;
191079b58424SAdrian Hunter 	uint32_t fc = decoder->packet.count;
191179b58424SAdrian Hunter 	uint32_t ctc_rem = ctc & decoder->ctc_rem_mask;
191279b58424SAdrian Hunter 
191379b58424SAdrian Hunter 	if (!decoder->tsc_ctc_ratio_d)
191479b58424SAdrian Hunter 		return;
191579b58424SAdrian Hunter 
19163f055167SAdrian Hunter 	if (decoder->pge && !decoder->in_psb)
19173f055167SAdrian Hunter 		intel_pt_mtc_cyc_cnt_pge(decoder);
19183f055167SAdrian Hunter 	else
19193f055167SAdrian Hunter 		intel_pt_mtc_cyc_cnt_upd(decoder);
19203f055167SAdrian Hunter 
192179b58424SAdrian Hunter 	decoder->last_mtc = (ctc >> decoder->mtc_shift) & 0xff;
1922fa8f949dSAdrian Hunter 	decoder->last_ctc = ctc - ctc_rem;
192379b58424SAdrian Hunter 	decoder->ctc_timestamp = decoder->tsc_timestamp - fc;
192479b58424SAdrian Hunter 	if (decoder->tsc_ctc_mult) {
192579b58424SAdrian Hunter 		decoder->ctc_timestamp -= ctc_rem * decoder->tsc_ctc_mult;
192679b58424SAdrian Hunter 	} else {
192779b58424SAdrian Hunter 		decoder->ctc_timestamp -= multdiv(ctc_rem,
192879b58424SAdrian Hunter 						  decoder->tsc_ctc_ratio_n,
192979b58424SAdrian Hunter 						  decoder->tsc_ctc_ratio_d);
193079b58424SAdrian Hunter 	}
193179b58424SAdrian Hunter 	decoder->ctc_delta = 0;
193279b58424SAdrian Hunter 	decoder->have_tma = true;
19333bccbe20SAdrian Hunter 	decoder->fixup_last_mtc = true;
193479b58424SAdrian Hunter 	intel_pt_log("CTC timestamp " x64_fmt " last MTC %#x  CTC rem %#x\n",
193579b58424SAdrian Hunter 		     decoder->ctc_timestamp, decoder->last_mtc, ctc_rem);
193679b58424SAdrian Hunter }
193779b58424SAdrian Hunter 
intel_pt_calc_mtc_timestamp(struct intel_pt_decoder * decoder)193879b58424SAdrian Hunter static void intel_pt_calc_mtc_timestamp(struct intel_pt_decoder *decoder)
193979b58424SAdrian Hunter {
194079b58424SAdrian Hunter 	uint64_t timestamp;
194179b58424SAdrian Hunter 	uint32_t mtc, mtc_delta;
194279b58424SAdrian Hunter 
194379b58424SAdrian Hunter 	if (!decoder->have_tma)
194479b58424SAdrian Hunter 		return;
194579b58424SAdrian Hunter 
194679b58424SAdrian Hunter 	mtc = decoder->packet.payload;
194779b58424SAdrian Hunter 
19483bccbe20SAdrian Hunter 	if (decoder->mtc_shift > 8 && decoder->fixup_last_mtc) {
19493bccbe20SAdrian Hunter 		decoder->fixup_last_mtc = false;
19503bccbe20SAdrian Hunter 		intel_pt_fixup_last_mtc(mtc, decoder->mtc_shift,
19513bccbe20SAdrian Hunter 					&decoder->last_mtc);
19523bccbe20SAdrian Hunter 	}
19533bccbe20SAdrian Hunter 
195479b58424SAdrian Hunter 	if (mtc > decoder->last_mtc)
195579b58424SAdrian Hunter 		mtc_delta = mtc - decoder->last_mtc;
195679b58424SAdrian Hunter 	else
195779b58424SAdrian Hunter 		mtc_delta = mtc + 256 - decoder->last_mtc;
195879b58424SAdrian Hunter 
195979b58424SAdrian Hunter 	decoder->ctc_delta += mtc_delta << decoder->mtc_shift;
196079b58424SAdrian Hunter 
196179b58424SAdrian Hunter 	if (decoder->tsc_ctc_mult) {
196279b58424SAdrian Hunter 		timestamp = decoder->ctc_timestamp +
196379b58424SAdrian Hunter 			    decoder->ctc_delta * decoder->tsc_ctc_mult;
196479b58424SAdrian Hunter 	} else {
196579b58424SAdrian Hunter 		timestamp = decoder->ctc_timestamp +
196679b58424SAdrian Hunter 			    multdiv(decoder->ctc_delta,
196779b58424SAdrian Hunter 				    decoder->tsc_ctc_ratio_n,
196879b58424SAdrian Hunter 				    decoder->tsc_ctc_ratio_d);
196979b58424SAdrian Hunter 	}
197079b58424SAdrian Hunter 
197179b58424SAdrian Hunter 	if (timestamp < decoder->timestamp)
197279b58424SAdrian Hunter 		intel_pt_log("Suppressing MTC timestamp " x64_fmt " less than current timestamp " x64_fmt "\n",
197379b58424SAdrian Hunter 			     timestamp, decoder->timestamp);
197479b58424SAdrian Hunter 	else
197579b58424SAdrian Hunter 		decoder->timestamp = timestamp;
197679b58424SAdrian Hunter 
19773f055167SAdrian Hunter 	intel_pt_mtc_cyc_cnt_upd(decoder);
19783f055167SAdrian Hunter 
197979b58424SAdrian Hunter 	decoder->timestamp_insn_cnt = 0;
198079b58424SAdrian Hunter 	decoder->last_mtc = mtc;
1981cc336186SAdrian Hunter 
1982cc336186SAdrian Hunter 	if (decoder->last_packet_type == INTEL_PT_CYC) {
1983cc336186SAdrian Hunter 		decoder->cyc_ref_timestamp = decoder->timestamp;
1984cc336186SAdrian Hunter 		decoder->cycle_cnt = 0;
1985cc336186SAdrian Hunter 		decoder->have_calc_cyc_to_tsc = false;
1986cc336186SAdrian Hunter 		intel_pt_calc_cyc_to_tsc(decoder, true);
1987cc336186SAdrian Hunter 	}
1988f6c23e3bSAdrian Hunter 
1989f6c23e3bSAdrian Hunter 	intel_pt_log_to("Setting timestamp", decoder->timestamp);
1990cc336186SAdrian Hunter }
1991cc336186SAdrian Hunter 
intel_pt_calc_cbr(struct intel_pt_decoder * decoder)1992cc336186SAdrian Hunter static void intel_pt_calc_cbr(struct intel_pt_decoder *decoder)
1993cc336186SAdrian Hunter {
199426fb2fb1SAdrian Hunter 	unsigned int cbr = decoder->packet.payload & 0xff;
1995cc336186SAdrian Hunter 
19960a7c700dSAdrian Hunter 	decoder->cbr_payload = decoder->packet.payload;
19970a7c700dSAdrian Hunter 
1998cc336186SAdrian Hunter 	if (decoder->cbr == cbr)
1999cc336186SAdrian Hunter 		return;
2000cc336186SAdrian Hunter 
2001cc336186SAdrian Hunter 	decoder->cbr = cbr;
2002cc336186SAdrian Hunter 	decoder->cbr_cyc_to_tsc = decoder->max_non_turbo_ratio_fp / cbr;
2003430635a0SAdrian Hunter 	decoder->cyc_ref_timestamp = decoder->timestamp;
2004430635a0SAdrian Hunter 	decoder->cycle_cnt = 0;
20053f055167SAdrian Hunter 
20063f055167SAdrian Hunter 	intel_pt_mtc_cyc_cnt_cbr(decoder);
2007cc336186SAdrian Hunter }
2008cc336186SAdrian Hunter 
intel_pt_calc_cyc_timestamp(struct intel_pt_decoder * decoder)2009cc336186SAdrian Hunter static void intel_pt_calc_cyc_timestamp(struct intel_pt_decoder *decoder)
2010cc336186SAdrian Hunter {
2011cc336186SAdrian Hunter 	uint64_t timestamp = decoder->cyc_ref_timestamp;
2012cc336186SAdrian Hunter 
2013cc336186SAdrian Hunter 	decoder->have_cyc = true;
2014cc336186SAdrian Hunter 
2015cc336186SAdrian Hunter 	decoder->cycle_cnt += decoder->packet.payload;
20167b4b4f83SAdrian Hunter 	if (decoder->pge)
20177b4b4f83SAdrian Hunter 		decoder->tot_cyc_cnt += decoder->packet.payload;
20187b4b4f83SAdrian Hunter 	decoder->sample_cyc = true;
2019cc336186SAdrian Hunter 
2020cc336186SAdrian Hunter 	if (!decoder->cyc_ref_timestamp)
2021cc336186SAdrian Hunter 		return;
2022cc336186SAdrian Hunter 
2023cc336186SAdrian Hunter 	if (decoder->have_calc_cyc_to_tsc)
2024cc336186SAdrian Hunter 		timestamp += decoder->cycle_cnt * decoder->calc_cyc_to_tsc;
2025cc336186SAdrian Hunter 	else if (decoder->cbr)
2026cc336186SAdrian Hunter 		timestamp += decoder->cycle_cnt * decoder->cbr_cyc_to_tsc;
2027cc336186SAdrian Hunter 	else
2028cc336186SAdrian Hunter 		return;
2029cc336186SAdrian Hunter 
2030cc336186SAdrian Hunter 	if (timestamp < decoder->timestamp)
2031cc336186SAdrian Hunter 		intel_pt_log("Suppressing CYC timestamp " x64_fmt " less than current timestamp " x64_fmt "\n",
2032cc336186SAdrian Hunter 			     timestamp, decoder->timestamp);
2033cc336186SAdrian Hunter 	else
2034cc336186SAdrian Hunter 		decoder->timestamp = timestamp;
203551ee6481SAdrian Hunter 
203651ee6481SAdrian Hunter 	decoder->timestamp_insn_cnt = 0;
2037f6c23e3bSAdrian Hunter 
2038f6c23e3bSAdrian Hunter 	intel_pt_log_to("Setting timestamp", decoder->timestamp);
203979b58424SAdrian Hunter }
204079b58424SAdrian Hunter 
intel_pt_bbp(struct intel_pt_decoder * decoder)20414c35595eSAdrian Hunter static void intel_pt_bbp(struct intel_pt_decoder *decoder)
20424c35595eSAdrian Hunter {
20434c35595eSAdrian Hunter 	if (decoder->prev_pkt_ctx == INTEL_PT_NO_CTX) {
20444c35595eSAdrian Hunter 		memset(decoder->state.items.mask, 0, sizeof(decoder->state.items.mask));
20454c35595eSAdrian Hunter 		decoder->state.items.is_32_bit = false;
20464c35595eSAdrian Hunter 	}
20474c35595eSAdrian Hunter 	decoder->blk_type = decoder->packet.payload;
20484c35595eSAdrian Hunter 	decoder->blk_type_pos = intel_pt_blk_type_pos(decoder->blk_type);
20494c35595eSAdrian Hunter 	if (decoder->blk_type == INTEL_PT_GP_REGS)
20504c35595eSAdrian Hunter 		decoder->state.items.is_32_bit = decoder->packet.count;
20514c35595eSAdrian Hunter 	if (decoder->blk_type_pos < 0) {
20524c35595eSAdrian Hunter 		intel_pt_log("WARNING: Unknown block type %u\n",
20534c35595eSAdrian Hunter 			     decoder->blk_type);
20544c35595eSAdrian Hunter 	} else if (decoder->state.items.mask[decoder->blk_type_pos]) {
20554c35595eSAdrian Hunter 		intel_pt_log("WARNING: Duplicate block type %u\n",
20564c35595eSAdrian Hunter 			     decoder->blk_type);
20574c35595eSAdrian Hunter 	}
20584c35595eSAdrian Hunter }
20594c35595eSAdrian Hunter 
intel_pt_bip(struct intel_pt_decoder * decoder)20604c35595eSAdrian Hunter static void intel_pt_bip(struct intel_pt_decoder *decoder)
20614c35595eSAdrian Hunter {
20624c35595eSAdrian Hunter 	uint32_t id = decoder->packet.count;
20634c35595eSAdrian Hunter 	uint32_t bit = 1 << id;
20644c35595eSAdrian Hunter 	int pos = decoder->blk_type_pos;
20654c35595eSAdrian Hunter 
20664c35595eSAdrian Hunter 	if (pos < 0 || id >= INTEL_PT_BLK_ITEM_ID_CNT) {
20674c35595eSAdrian Hunter 		intel_pt_log("WARNING: Unknown block item %u type %d\n",
20684c35595eSAdrian Hunter 			     id, decoder->blk_type);
20694c35595eSAdrian Hunter 		return;
20704c35595eSAdrian Hunter 	}
20714c35595eSAdrian Hunter 
20724c35595eSAdrian Hunter 	if (decoder->state.items.mask[pos] & bit) {
20734c35595eSAdrian Hunter 		intel_pt_log("WARNING: Duplicate block item %u type %d\n",
20744c35595eSAdrian Hunter 			     id, decoder->blk_type);
20754c35595eSAdrian Hunter 	}
20764c35595eSAdrian Hunter 
20774c35595eSAdrian Hunter 	decoder->state.items.mask[pos] |= bit;
20784c35595eSAdrian Hunter 	decoder->state.items.val[pos][id] = decoder->packet.payload;
20794c35595eSAdrian Hunter }
20804c35595eSAdrian Hunter 
2081f4aa0819SAdrian Hunter /* Walk PSB+ packets when already in sync. */
intel_pt_walk_psbend(struct intel_pt_decoder * decoder)2082f4aa0819SAdrian Hunter static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
2083f4aa0819SAdrian Hunter {
2084f4aa0819SAdrian Hunter 	int err;
2085f4aa0819SAdrian Hunter 
20869bc668e3SAdrian Hunter 	decoder->in_psb = true;
20879bc668e3SAdrian Hunter 
2088f4aa0819SAdrian Hunter 	while (1) {
2089f4aa0819SAdrian Hunter 		err = intel_pt_get_next_packet(decoder);
2090f4aa0819SAdrian Hunter 		if (err)
20919bc668e3SAdrian Hunter 			goto out;
2092f4aa0819SAdrian Hunter 
2093f4aa0819SAdrian Hunter 		switch (decoder->packet.type) {
2094f4aa0819SAdrian Hunter 		case INTEL_PT_PSBEND:
20959bc668e3SAdrian Hunter 			err = 0;
20969bc668e3SAdrian Hunter 			goto out;
2097f4aa0819SAdrian Hunter 
2098f4aa0819SAdrian Hunter 		case INTEL_PT_TIP_PGD:
2099f4aa0819SAdrian Hunter 		case INTEL_PT_TIP_PGE:
2100f4aa0819SAdrian Hunter 		case INTEL_PT_TIP:
2101f4aa0819SAdrian Hunter 		case INTEL_PT_TNT:
21023d498078SAdrian Hunter 		case INTEL_PT_TRACESTOP:
2103f4aa0819SAdrian Hunter 		case INTEL_PT_BAD:
2104f4aa0819SAdrian Hunter 		case INTEL_PT_PSB:
2105a472e65fSAdrian Hunter 		case INTEL_PT_PTWRITE:
2106a472e65fSAdrian Hunter 		case INTEL_PT_PTWRITE_IP:
2107a472e65fSAdrian Hunter 		case INTEL_PT_EXSTOP:
2108a472e65fSAdrian Hunter 		case INTEL_PT_EXSTOP_IP:
2109a472e65fSAdrian Hunter 		case INTEL_PT_MWAIT:
2110a472e65fSAdrian Hunter 		case INTEL_PT_PWRE:
2111a472e65fSAdrian Hunter 		case INTEL_PT_PWRX:
2112edff7809SAdrian Hunter 		case INTEL_PT_BBP:
2113edff7809SAdrian Hunter 		case INTEL_PT_BIP:
2114edff7809SAdrian Hunter 		case INTEL_PT_BEP:
2115edff7809SAdrian Hunter 		case INTEL_PT_BEP_IP:
21162750af50SAdrian Hunter 		case INTEL_PT_CFE:
21172750af50SAdrian Hunter 		case INTEL_PT_CFE_IP:
21182750af50SAdrian Hunter 		case INTEL_PT_EVD:
211979b58424SAdrian Hunter 			decoder->have_tma = false;
2120f4aa0819SAdrian Hunter 			intel_pt_log("ERROR: Unexpected packet\n");
21219bc668e3SAdrian Hunter 			err = -EAGAIN;
21229bc668e3SAdrian Hunter 			goto out;
2123f4aa0819SAdrian Hunter 
2124f4aa0819SAdrian Hunter 		case INTEL_PT_OVF:
21259bc668e3SAdrian Hunter 			err = intel_pt_overflow(decoder);
21269bc668e3SAdrian Hunter 			goto out;
2127f4aa0819SAdrian Hunter 
2128f4aa0819SAdrian Hunter 		case INTEL_PT_TSC:
2129f4aa0819SAdrian Hunter 			intel_pt_calc_tsc_timestamp(decoder);
2130f4aa0819SAdrian Hunter 			break;
2131f4aa0819SAdrian Hunter 
21323d498078SAdrian Hunter 		case INTEL_PT_TMA:
213379b58424SAdrian Hunter 			intel_pt_calc_tma(decoder);
21343d498078SAdrian Hunter 			break;
21353d498078SAdrian Hunter 
2136f4aa0819SAdrian Hunter 		case INTEL_PT_CBR:
2137cc336186SAdrian Hunter 			intel_pt_calc_cbr(decoder);
2138f4aa0819SAdrian Hunter 			break;
2139f4aa0819SAdrian Hunter 
2140f4aa0819SAdrian Hunter 		case INTEL_PT_MODE_EXEC:
2141cf0c98e2SAdrian Hunter 			intel_pt_mode_exec_status(decoder);
2142f4aa0819SAdrian Hunter 			break;
2143f4aa0819SAdrian Hunter 
2144f4aa0819SAdrian Hunter 		case INTEL_PT_PIP:
214580a03886SAdrian Hunter 			intel_pt_set_pip(decoder);
2146f4aa0819SAdrian Hunter 			break;
2147f4aa0819SAdrian Hunter 
2148f4aa0819SAdrian Hunter 		case INTEL_PT_FUP:
2149f4aa0819SAdrian Hunter 			decoder->pge = true;
21507c1b16baSAdrian Hunter 			if (decoder->packet.count) {
2151f4aa0819SAdrian Hunter 				intel_pt_set_last_ip(decoder);
2152c840cbfeSAdrian Hunter 				decoder->psb_ip = decoder->last_ip;
21537c1b16baSAdrian Hunter 			}
2154f4aa0819SAdrian Hunter 			break;
2155f4aa0819SAdrian Hunter 
2156f4aa0819SAdrian Hunter 		case INTEL_PT_MODE_TSX:
2157f4aa0819SAdrian Hunter 			intel_pt_update_in_tx(decoder);
2158f4aa0819SAdrian Hunter 			break;
2159f4aa0819SAdrian Hunter 
21603d498078SAdrian Hunter 		case INTEL_PT_MTC:
216179b58424SAdrian Hunter 			intel_pt_calc_mtc_timestamp(decoder);
216279b58424SAdrian Hunter 			if (decoder->period_type == INTEL_PT_PERIOD_MTC)
216379b58424SAdrian Hunter 				decoder->state.type |= INTEL_PT_INSTRUCTION;
21643d498078SAdrian Hunter 			break;
21653d498078SAdrian Hunter 
21663d498078SAdrian Hunter 		case INTEL_PT_CYC:
216703fb0f85SAdrian Hunter 			intel_pt_calc_cyc_timestamp(decoder);
216803fb0f85SAdrian Hunter 			break;
216903fb0f85SAdrian Hunter 
21703d498078SAdrian Hunter 		case INTEL_PT_VMCS:
21713d498078SAdrian Hunter 		case INTEL_PT_MNT:
2172f4aa0819SAdrian Hunter 		case INTEL_PT_PAD:
2173f4aa0819SAdrian Hunter 		default:
2174f4aa0819SAdrian Hunter 			break;
2175f4aa0819SAdrian Hunter 		}
2176f4aa0819SAdrian Hunter 	}
21779bc668e3SAdrian Hunter out:
21789bc668e3SAdrian Hunter 	decoder->in_psb = false;
21799bc668e3SAdrian Hunter 
21809bc668e3SAdrian Hunter 	return err;
2181f4aa0819SAdrian Hunter }
2182f4aa0819SAdrian Hunter 
intel_pt_walk_fup_tip(struct intel_pt_decoder * decoder)2183f4aa0819SAdrian Hunter static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
2184f4aa0819SAdrian Hunter {
2185f4aa0819SAdrian Hunter 	int err;
2186f4aa0819SAdrian Hunter 
2187f4aa0819SAdrian Hunter 	if (decoder->tx_flags & INTEL_PT_ABORT_TX) {
2188f4aa0819SAdrian Hunter 		decoder->tx_flags = 0;
2189f4aa0819SAdrian Hunter 		decoder->state.flags &= ~INTEL_PT_IN_TX;
2190f4aa0819SAdrian Hunter 		decoder->state.flags |= INTEL_PT_ABORT_TX;
2191f4aa0819SAdrian Hunter 	} else {
2192f4aa0819SAdrian Hunter 		decoder->state.flags |= INTEL_PT_ASYNC;
2193f4aa0819SAdrian Hunter 	}
2194f4aa0819SAdrian Hunter 
2195f4aa0819SAdrian Hunter 	while (1) {
2196f4aa0819SAdrian Hunter 		err = intel_pt_get_next_packet(decoder);
2197f4aa0819SAdrian Hunter 		if (err)
2198f4aa0819SAdrian Hunter 			return err;
2199f4aa0819SAdrian Hunter 
2200f4aa0819SAdrian Hunter 		switch (decoder->packet.type) {
2201f4aa0819SAdrian Hunter 		case INTEL_PT_TNT:
2202f4aa0819SAdrian Hunter 		case INTEL_PT_FUP:
22033d498078SAdrian Hunter 		case INTEL_PT_TRACESTOP:
2204f4aa0819SAdrian Hunter 		case INTEL_PT_PSB:
2205f4aa0819SAdrian Hunter 		case INTEL_PT_TSC:
22063d498078SAdrian Hunter 		case INTEL_PT_TMA:
2207f4aa0819SAdrian Hunter 		case INTEL_PT_MODE_TSX:
2208f4aa0819SAdrian Hunter 		case INTEL_PT_BAD:
2209f4aa0819SAdrian Hunter 		case INTEL_PT_PSBEND:
2210a472e65fSAdrian Hunter 		case INTEL_PT_PTWRITE:
2211a472e65fSAdrian Hunter 		case INTEL_PT_PTWRITE_IP:
2212a472e65fSAdrian Hunter 		case INTEL_PT_EXSTOP:
2213a472e65fSAdrian Hunter 		case INTEL_PT_EXSTOP_IP:
2214a472e65fSAdrian Hunter 		case INTEL_PT_MWAIT:
2215a472e65fSAdrian Hunter 		case INTEL_PT_PWRE:
2216a472e65fSAdrian Hunter 		case INTEL_PT_PWRX:
2217edff7809SAdrian Hunter 		case INTEL_PT_BBP:
2218edff7809SAdrian Hunter 		case INTEL_PT_BIP:
2219edff7809SAdrian Hunter 		case INTEL_PT_BEP:
2220edff7809SAdrian Hunter 		case INTEL_PT_BEP_IP:
22212750af50SAdrian Hunter 		case INTEL_PT_CFE:
22222750af50SAdrian Hunter 		case INTEL_PT_CFE_IP:
22232750af50SAdrian Hunter 		case INTEL_PT_EVD:
2224f4aa0819SAdrian Hunter 			intel_pt_log("ERROR: Missing TIP after FUP\n");
2225f4aa0819SAdrian Hunter 			decoder->pkt_state = INTEL_PT_STATE_ERR3;
22261c196a6cSAdrian Hunter 			decoder->pkt_step = 0;
2227f4aa0819SAdrian Hunter 			return -ENOENT;
2228f4aa0819SAdrian Hunter 
2229bd2e49ecSAdrian Hunter 		case INTEL_PT_CBR:
2230bd2e49ecSAdrian Hunter 			intel_pt_calc_cbr(decoder);
2231bd2e49ecSAdrian Hunter 			break;
2232bd2e49ecSAdrian Hunter 
2233f4aa0819SAdrian Hunter 		case INTEL_PT_OVF:
2234f4aa0819SAdrian Hunter 			return intel_pt_overflow(decoder);
2235f4aa0819SAdrian Hunter 
2236f4aa0819SAdrian Hunter 		case INTEL_PT_TIP_PGD:
2237f4aa0819SAdrian Hunter 			decoder->state.from_ip = decoder->ip;
2238bea63857SAdrian Hunter 			if (decoder->packet.count == 0) {
2239f4aa0819SAdrian Hunter 				decoder->state.to_ip = 0;
2240bea63857SAdrian Hunter 			} else {
2241f4aa0819SAdrian Hunter 				intel_pt_set_ip(decoder);
2242bea63857SAdrian Hunter 				decoder->state.to_ip = decoder->ip;
2243f4aa0819SAdrian Hunter 			}
2244f4aa0819SAdrian Hunter 			decoder->pge = false;
2245f4aa0819SAdrian Hunter 			decoder->continuous_period = false;
2246bea63857SAdrian Hunter 			decoder->state.type |= INTEL_PT_TRACE_END;
224780a03886SAdrian Hunter 			intel_pt_update_nr(decoder);
2248f4aa0819SAdrian Hunter 			return 0;
2249f4aa0819SAdrian Hunter 
2250f4aa0819SAdrian Hunter 		case INTEL_PT_TIP_PGE:
2251f4aa0819SAdrian Hunter 			decoder->pge = true;
2252f4aa0819SAdrian Hunter 			intel_pt_log("Omitting PGE ip " x64_fmt "\n",
2253f4aa0819SAdrian Hunter 				     decoder->ip);
2254f4aa0819SAdrian Hunter 			decoder->state.from_ip = 0;
2255f4aa0819SAdrian Hunter 			if (decoder->packet.count == 0) {
2256f4aa0819SAdrian Hunter 				decoder->state.to_ip = 0;
2257f4aa0819SAdrian Hunter 			} else {
2258f4aa0819SAdrian Hunter 				intel_pt_set_ip(decoder);
2259f4aa0819SAdrian Hunter 				decoder->state.to_ip = decoder->ip;
2260f4aa0819SAdrian Hunter 			}
2261bea63857SAdrian Hunter 			decoder->state.type |= INTEL_PT_TRACE_BEGIN;
22623f055167SAdrian Hunter 			intel_pt_mtc_cyc_cnt_pge(decoder);
226380a03886SAdrian Hunter 			intel_pt_set_nr(decoder);
2264f4aa0819SAdrian Hunter 			return 0;
2265f4aa0819SAdrian Hunter 
2266f4aa0819SAdrian Hunter 		case INTEL_PT_TIP:
2267f4aa0819SAdrian Hunter 			decoder->state.from_ip = decoder->ip;
2268f4aa0819SAdrian Hunter 			if (decoder->packet.count == 0) {
2269f4aa0819SAdrian Hunter 				decoder->state.to_ip = 0;
2270f4aa0819SAdrian Hunter 			} else {
2271f4aa0819SAdrian Hunter 				intel_pt_set_ip(decoder);
2272f4aa0819SAdrian Hunter 				decoder->state.to_ip = decoder->ip;
2273f4aa0819SAdrian Hunter 			}
227480a03886SAdrian Hunter 			intel_pt_update_nr(decoder);
2275cf0c98e2SAdrian Hunter 			intel_pt_sample_iflag_chg(decoder);
2276f4aa0819SAdrian Hunter 			return 0;
2277f4aa0819SAdrian Hunter 
2278f4aa0819SAdrian Hunter 		case INTEL_PT_PIP:
227980a03886SAdrian Hunter 			intel_pt_update_pip(decoder);
22803d498078SAdrian Hunter 			break;
22813d498078SAdrian Hunter 
22823d498078SAdrian Hunter 		case INTEL_PT_MTC:
228379b58424SAdrian Hunter 			intel_pt_calc_mtc_timestamp(decoder);
228479b58424SAdrian Hunter 			if (decoder->period_type == INTEL_PT_PERIOD_MTC)
228579b58424SAdrian Hunter 				decoder->state.type |= INTEL_PT_INSTRUCTION;
22863d498078SAdrian Hunter 			break;
22873d498078SAdrian Hunter 
22883d498078SAdrian Hunter 		case INTEL_PT_CYC:
2289cc336186SAdrian Hunter 			intel_pt_calc_cyc_timestamp(decoder);
2290f4aa0819SAdrian Hunter 			break;
2291f4aa0819SAdrian Hunter 
2292f4aa0819SAdrian Hunter 		case INTEL_PT_MODE_EXEC:
2293cf0c98e2SAdrian Hunter 			intel_pt_mode_exec(decoder);
2294f4aa0819SAdrian Hunter 			break;
2295f4aa0819SAdrian Hunter 
22963d498078SAdrian Hunter 		case INTEL_PT_VMCS:
22973d498078SAdrian Hunter 		case INTEL_PT_MNT:
2298f4aa0819SAdrian Hunter 		case INTEL_PT_PAD:
2299f4aa0819SAdrian Hunter 			break;
2300f4aa0819SAdrian Hunter 
2301f4aa0819SAdrian Hunter 		default:
2302f4aa0819SAdrian Hunter 			return intel_pt_bug(decoder);
2303f4aa0819SAdrian Hunter 		}
2304f4aa0819SAdrian Hunter 	}
2305f4aa0819SAdrian Hunter }
2306f4aa0819SAdrian Hunter 
intel_pt_resample(struct intel_pt_decoder * decoder)23077c1b16baSAdrian Hunter static int intel_pt_resample(struct intel_pt_decoder *decoder)
23087c1b16baSAdrian Hunter {
23097c1b16baSAdrian Hunter 	decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
23107c1b16baSAdrian Hunter 	decoder->state.type = INTEL_PT_INSTRUCTION;
23117c1b16baSAdrian Hunter 	decoder->state.from_ip = decoder->ip;
23127c1b16baSAdrian Hunter 	decoder->state.to_ip = 0;
23137c1b16baSAdrian Hunter 	return 0;
23147c1b16baSAdrian Hunter }
23157c1b16baSAdrian Hunter 
2316fa8f949dSAdrian Hunter struct intel_pt_vm_tsc_info {
2317fa8f949dSAdrian Hunter 	struct intel_pt_pkt pip_packet;
2318fa8f949dSAdrian Hunter 	struct intel_pt_pkt vmcs_packet;
2319fa8f949dSAdrian Hunter 	struct intel_pt_pkt tma_packet;
2320fa8f949dSAdrian Hunter 	bool tsc, pip, vmcs, tma, psbend;
2321fa8f949dSAdrian Hunter 	uint64_t ctc_delta;
2322fa8f949dSAdrian Hunter 	uint64_t last_ctc;
2323fa8f949dSAdrian Hunter 	int max_lookahead;
2324fa8f949dSAdrian Hunter };
2325fa8f949dSAdrian Hunter 
2326fa8f949dSAdrian Hunter /* Lookahead and get the PIP, VMCS and TMA packets from PSB+ */
intel_pt_vm_psb_lookahead_cb(struct intel_pt_pkt_info * pkt_info)2327fa8f949dSAdrian Hunter static int intel_pt_vm_psb_lookahead_cb(struct intel_pt_pkt_info *pkt_info)
2328fa8f949dSAdrian Hunter {
2329fa8f949dSAdrian Hunter 	struct intel_pt_vm_tsc_info *data = pkt_info->data;
2330fa8f949dSAdrian Hunter 
2331fa8f949dSAdrian Hunter 	switch (pkt_info->packet.type) {
2332fa8f949dSAdrian Hunter 	case INTEL_PT_PAD:
2333fa8f949dSAdrian Hunter 	case INTEL_PT_MNT:
2334fa8f949dSAdrian Hunter 	case INTEL_PT_MODE_EXEC:
2335fa8f949dSAdrian Hunter 	case INTEL_PT_MODE_TSX:
2336fa8f949dSAdrian Hunter 	case INTEL_PT_MTC:
2337fa8f949dSAdrian Hunter 	case INTEL_PT_FUP:
2338fa8f949dSAdrian Hunter 	case INTEL_PT_CYC:
2339fa8f949dSAdrian Hunter 	case INTEL_PT_CBR:
2340fa8f949dSAdrian Hunter 		break;
2341fa8f949dSAdrian Hunter 
2342fa8f949dSAdrian Hunter 	case INTEL_PT_TSC:
2343fa8f949dSAdrian Hunter 		data->tsc = true;
2344fa8f949dSAdrian Hunter 		break;
2345fa8f949dSAdrian Hunter 
2346fa8f949dSAdrian Hunter 	case INTEL_PT_TMA:
2347fa8f949dSAdrian Hunter 		data->tma_packet = pkt_info->packet;
2348fa8f949dSAdrian Hunter 		data->tma = true;
2349fa8f949dSAdrian Hunter 		break;
2350fa8f949dSAdrian Hunter 
2351fa8f949dSAdrian Hunter 	case INTEL_PT_PIP:
2352fa8f949dSAdrian Hunter 		data->pip_packet = pkt_info->packet;
2353fa8f949dSAdrian Hunter 		data->pip = true;
2354fa8f949dSAdrian Hunter 		break;
2355fa8f949dSAdrian Hunter 
2356fa8f949dSAdrian Hunter 	case INTEL_PT_VMCS:
2357fa8f949dSAdrian Hunter 		data->vmcs_packet = pkt_info->packet;
2358fa8f949dSAdrian Hunter 		data->vmcs = true;
2359fa8f949dSAdrian Hunter 		break;
2360fa8f949dSAdrian Hunter 
2361fa8f949dSAdrian Hunter 	case INTEL_PT_PSBEND:
2362fa8f949dSAdrian Hunter 		data->psbend = true;
2363fa8f949dSAdrian Hunter 		return 1;
2364fa8f949dSAdrian Hunter 
2365fa8f949dSAdrian Hunter 	case INTEL_PT_TIP_PGE:
2366fa8f949dSAdrian Hunter 	case INTEL_PT_PTWRITE:
2367fa8f949dSAdrian Hunter 	case INTEL_PT_PTWRITE_IP:
2368fa8f949dSAdrian Hunter 	case INTEL_PT_EXSTOP:
2369fa8f949dSAdrian Hunter 	case INTEL_PT_EXSTOP_IP:
2370fa8f949dSAdrian Hunter 	case INTEL_PT_MWAIT:
2371fa8f949dSAdrian Hunter 	case INTEL_PT_PWRE:
2372fa8f949dSAdrian Hunter 	case INTEL_PT_PWRX:
2373fa8f949dSAdrian Hunter 	case INTEL_PT_BBP:
2374fa8f949dSAdrian Hunter 	case INTEL_PT_BIP:
2375fa8f949dSAdrian Hunter 	case INTEL_PT_BEP:
2376fa8f949dSAdrian Hunter 	case INTEL_PT_BEP_IP:
2377fa8f949dSAdrian Hunter 	case INTEL_PT_OVF:
2378fa8f949dSAdrian Hunter 	case INTEL_PT_BAD:
2379fa8f949dSAdrian Hunter 	case INTEL_PT_TNT:
2380fa8f949dSAdrian Hunter 	case INTEL_PT_TIP_PGD:
2381fa8f949dSAdrian Hunter 	case INTEL_PT_TIP:
2382fa8f949dSAdrian Hunter 	case INTEL_PT_PSB:
2383fa8f949dSAdrian Hunter 	case INTEL_PT_TRACESTOP:
23842750af50SAdrian Hunter 	case INTEL_PT_CFE:
23852750af50SAdrian Hunter 	case INTEL_PT_CFE_IP:
23862750af50SAdrian Hunter 	case INTEL_PT_EVD:
2387fa8f949dSAdrian Hunter 	default:
2388fa8f949dSAdrian Hunter 		return 1;
2389fa8f949dSAdrian Hunter 	}
2390fa8f949dSAdrian Hunter 
2391fa8f949dSAdrian Hunter 	return 0;
2392fa8f949dSAdrian Hunter }
2393fa8f949dSAdrian Hunter 
2394fa8f949dSAdrian Hunter struct intel_pt_ovf_fup_info {
2395fa8f949dSAdrian Hunter 	int max_lookahead;
2396fa8f949dSAdrian Hunter 	bool found;
2397fa8f949dSAdrian Hunter };
2398fa8f949dSAdrian Hunter 
2399fa8f949dSAdrian Hunter /* Lookahead to detect a FUP packet after OVF */
intel_pt_ovf_fup_lookahead_cb(struct intel_pt_pkt_info * pkt_info)2400fa8f949dSAdrian Hunter static int intel_pt_ovf_fup_lookahead_cb(struct intel_pt_pkt_info *pkt_info)
2401fa8f949dSAdrian Hunter {
2402fa8f949dSAdrian Hunter 	struct intel_pt_ovf_fup_info *data = pkt_info->data;
2403fa8f949dSAdrian Hunter 
2404fa8f949dSAdrian Hunter 	if (pkt_info->packet.type == INTEL_PT_CYC ||
2405fa8f949dSAdrian Hunter 	    pkt_info->packet.type == INTEL_PT_MTC ||
2406fa8f949dSAdrian Hunter 	    pkt_info->packet.type == INTEL_PT_TSC)
2407fa8f949dSAdrian Hunter 		return !--(data->max_lookahead);
2408fa8f949dSAdrian Hunter 	data->found = pkt_info->packet.type == INTEL_PT_FUP;
2409fa8f949dSAdrian Hunter 	return 1;
2410fa8f949dSAdrian Hunter }
2411fa8f949dSAdrian Hunter 
intel_pt_ovf_fup_lookahead(struct intel_pt_decoder * decoder)2412fa8f949dSAdrian Hunter static bool intel_pt_ovf_fup_lookahead(struct intel_pt_decoder *decoder)
2413fa8f949dSAdrian Hunter {
2414fa8f949dSAdrian Hunter 	struct intel_pt_ovf_fup_info data = {
2415fa8f949dSAdrian Hunter 		.max_lookahead = 16,
2416fa8f949dSAdrian Hunter 		.found = false,
2417fa8f949dSAdrian Hunter 	};
2418fa8f949dSAdrian Hunter 
2419fa8f949dSAdrian Hunter 	intel_pt_pkt_lookahead(decoder, intel_pt_ovf_fup_lookahead_cb, &data);
2420fa8f949dSAdrian Hunter 	return data.found;
2421fa8f949dSAdrian Hunter }
2422fa8f949dSAdrian Hunter 
2423fa8f949dSAdrian Hunter /* Lookahead and get the TMA packet after TSC */
intel_pt_tma_lookahead_cb(struct intel_pt_pkt_info * pkt_info)2424fa8f949dSAdrian Hunter static int intel_pt_tma_lookahead_cb(struct intel_pt_pkt_info *pkt_info)
2425fa8f949dSAdrian Hunter {
2426fa8f949dSAdrian Hunter 	struct intel_pt_vm_tsc_info *data = pkt_info->data;
2427fa8f949dSAdrian Hunter 
2428fa8f949dSAdrian Hunter 	if (pkt_info->packet.type == INTEL_PT_CYC ||
2429fa8f949dSAdrian Hunter 	    pkt_info->packet.type == INTEL_PT_MTC)
2430fa8f949dSAdrian Hunter 		return !--(data->max_lookahead);
2431fa8f949dSAdrian Hunter 
2432fa8f949dSAdrian Hunter 	if (pkt_info->packet.type == INTEL_PT_TMA) {
2433fa8f949dSAdrian Hunter 		data->tma_packet = pkt_info->packet;
2434fa8f949dSAdrian Hunter 		data->tma = true;
2435fa8f949dSAdrian Hunter 	}
2436fa8f949dSAdrian Hunter 	return 1;
2437fa8f949dSAdrian Hunter }
2438fa8f949dSAdrian Hunter 
intel_pt_ctc_to_tsc(struct intel_pt_decoder * decoder,uint64_t ctc)2439fa8f949dSAdrian Hunter static uint64_t intel_pt_ctc_to_tsc(struct intel_pt_decoder *decoder, uint64_t ctc)
2440fa8f949dSAdrian Hunter {
2441fa8f949dSAdrian Hunter 	if (decoder->tsc_ctc_mult)
2442fa8f949dSAdrian Hunter 		return ctc * decoder->tsc_ctc_mult;
2443fa8f949dSAdrian Hunter 	else
2444fa8f949dSAdrian Hunter 		return multdiv(ctc, decoder->tsc_ctc_ratio_n, decoder->tsc_ctc_ratio_d);
2445fa8f949dSAdrian Hunter }
2446fa8f949dSAdrian Hunter 
intel_pt_calc_expected_tsc(struct intel_pt_decoder * decoder,uint32_t ctc,uint32_t fc,uint64_t last_ctc_timestamp,uint64_t ctc_delta,uint32_t last_ctc)2447fa8f949dSAdrian Hunter static uint64_t intel_pt_calc_expected_tsc(struct intel_pt_decoder *decoder,
2448fa8f949dSAdrian Hunter 					   uint32_t ctc,
2449fa8f949dSAdrian Hunter 					   uint32_t fc,
2450fa8f949dSAdrian Hunter 					   uint64_t last_ctc_timestamp,
2451fa8f949dSAdrian Hunter 					   uint64_t ctc_delta,
2452fa8f949dSAdrian Hunter 					   uint32_t last_ctc)
2453fa8f949dSAdrian Hunter {
2454fa8f949dSAdrian Hunter 	/* Number of CTC ticks from last_ctc_timestamp to last_mtc */
2455fa8f949dSAdrian Hunter 	uint64_t last_mtc_ctc = last_ctc + ctc_delta;
2456fa8f949dSAdrian Hunter 	/*
2457fa8f949dSAdrian Hunter 	 * Number of CTC ticks from there until current TMA packet. We would
2458fa8f949dSAdrian Hunter 	 * expect last_mtc_ctc to be before ctc, but the TSC packet can slip
2459fa8f949dSAdrian Hunter 	 * past an MTC, so a sign-extended value is used.
2460fa8f949dSAdrian Hunter 	 */
2461fa8f949dSAdrian Hunter 	uint64_t delta = (int16_t)((uint16_t)ctc - (uint16_t)last_mtc_ctc);
2462fa8f949dSAdrian Hunter 	/* Total CTC ticks from last_ctc_timestamp to current TMA packet */
2463fa8f949dSAdrian Hunter 	uint64_t new_ctc_delta = ctc_delta + delta;
2464fa8f949dSAdrian Hunter 	uint64_t expected_tsc;
2465fa8f949dSAdrian Hunter 
2466fa8f949dSAdrian Hunter 	/*
2467fa8f949dSAdrian Hunter 	 * Convert CTC ticks to TSC ticks, add the starting point
2468fa8f949dSAdrian Hunter 	 * (last_ctc_timestamp) and the fast counter from the TMA packet.
2469fa8f949dSAdrian Hunter 	 */
2470fa8f949dSAdrian Hunter 	expected_tsc = last_ctc_timestamp + intel_pt_ctc_to_tsc(decoder, new_ctc_delta) + fc;
2471fa8f949dSAdrian Hunter 
2472fa8f949dSAdrian Hunter 	if (intel_pt_enable_logging) {
2473fa8f949dSAdrian Hunter 		intel_pt_log_x64(last_mtc_ctc);
2474fa8f949dSAdrian Hunter 		intel_pt_log_x32(last_ctc);
2475fa8f949dSAdrian Hunter 		intel_pt_log_x64(ctc_delta);
2476fa8f949dSAdrian Hunter 		intel_pt_log_x64(delta);
2477fa8f949dSAdrian Hunter 		intel_pt_log_x32(ctc);
2478fa8f949dSAdrian Hunter 		intel_pt_log_x64(new_ctc_delta);
2479fa8f949dSAdrian Hunter 		intel_pt_log_x64(last_ctc_timestamp);
2480fa8f949dSAdrian Hunter 		intel_pt_log_x32(fc);
2481fa8f949dSAdrian Hunter 		intel_pt_log_x64(intel_pt_ctc_to_tsc(decoder, new_ctc_delta));
2482fa8f949dSAdrian Hunter 		intel_pt_log_x64(expected_tsc);
2483fa8f949dSAdrian Hunter 	}
2484fa8f949dSAdrian Hunter 
2485fa8f949dSAdrian Hunter 	return expected_tsc;
2486fa8f949dSAdrian Hunter }
2487fa8f949dSAdrian Hunter 
intel_pt_expected_tsc(struct intel_pt_decoder * decoder,struct intel_pt_vm_tsc_info * data)2488fa8f949dSAdrian Hunter static uint64_t intel_pt_expected_tsc(struct intel_pt_decoder *decoder,
2489fa8f949dSAdrian Hunter 				      struct intel_pt_vm_tsc_info *data)
2490fa8f949dSAdrian Hunter {
2491fa8f949dSAdrian Hunter 	uint32_t ctc = data->tma_packet.payload;
2492fa8f949dSAdrian Hunter 	uint32_t fc = data->tma_packet.count;
2493fa8f949dSAdrian Hunter 
2494fa8f949dSAdrian Hunter 	return intel_pt_calc_expected_tsc(decoder, ctc, fc,
2495fa8f949dSAdrian Hunter 					  decoder->ctc_timestamp,
2496fa8f949dSAdrian Hunter 					  data->ctc_delta, data->last_ctc);
2497fa8f949dSAdrian Hunter }
2498fa8f949dSAdrian Hunter 
intel_pt_translate_vm_tsc(struct intel_pt_decoder * decoder,struct intel_pt_vmcs_info * vmcs_info)2499fa8f949dSAdrian Hunter static void intel_pt_translate_vm_tsc(struct intel_pt_decoder *decoder,
2500fa8f949dSAdrian Hunter 				      struct intel_pt_vmcs_info *vmcs_info)
2501fa8f949dSAdrian Hunter {
2502fa8f949dSAdrian Hunter 	uint64_t payload = decoder->packet.payload;
2503fa8f949dSAdrian Hunter 
2504fa8f949dSAdrian Hunter 	/* VMX adds the TSC Offset, so subtract to get host TSC */
2505fa8f949dSAdrian Hunter 	decoder->packet.payload -= vmcs_info->tsc_offset;
2506fa8f949dSAdrian Hunter 	/* TSC packet has only 7 bytes */
2507fa8f949dSAdrian Hunter 	decoder->packet.payload &= SEVEN_BYTES;
2508fa8f949dSAdrian Hunter 
2509fa8f949dSAdrian Hunter 	/*
2510fa8f949dSAdrian Hunter 	 * The buffer is mmapped from the data file, so this also updates the
2511fa8f949dSAdrian Hunter 	 * data file.
2512fa8f949dSAdrian Hunter 	 */
2513fa8f949dSAdrian Hunter 	if (!decoder->vm_tm_corr_dry_run)
2514fa8f949dSAdrian Hunter 		memcpy((void *)decoder->buf + 1, &decoder->packet.payload, 7);
2515fa8f949dSAdrian Hunter 
2516fa8f949dSAdrian Hunter 	intel_pt_log("Translated VM TSC %#" PRIx64 " -> %#" PRIx64
2517fa8f949dSAdrian Hunter 		     "    VMCS %#" PRIx64 "    TSC Offset %#" PRIx64 "\n",
2518fa8f949dSAdrian Hunter 		     payload, decoder->packet.payload, vmcs_info->vmcs,
2519fa8f949dSAdrian Hunter 		     vmcs_info->tsc_offset);
2520fa8f949dSAdrian Hunter }
2521fa8f949dSAdrian Hunter 
intel_pt_translate_vm_tsc_offset(struct intel_pt_decoder * decoder,uint64_t tsc_offset)2522fa8f949dSAdrian Hunter static void intel_pt_translate_vm_tsc_offset(struct intel_pt_decoder *decoder,
2523fa8f949dSAdrian Hunter 					     uint64_t tsc_offset)
2524fa8f949dSAdrian Hunter {
2525fa8f949dSAdrian Hunter 	struct intel_pt_vmcs_info vmcs_info = {
2526fa8f949dSAdrian Hunter 		.vmcs = NO_VMCS,
2527fa8f949dSAdrian Hunter 		.tsc_offset = tsc_offset
2528fa8f949dSAdrian Hunter 	};
2529fa8f949dSAdrian Hunter 
2530fa8f949dSAdrian Hunter 	intel_pt_translate_vm_tsc(decoder, &vmcs_info);
2531fa8f949dSAdrian Hunter }
2532fa8f949dSAdrian Hunter 
in_vm(uint64_t pip_payload)2533fa8f949dSAdrian Hunter static inline bool in_vm(uint64_t pip_payload)
2534fa8f949dSAdrian Hunter {
2535fa8f949dSAdrian Hunter 	return pip_payload & 1;
2536fa8f949dSAdrian Hunter }
2537fa8f949dSAdrian Hunter 
pip_in_vm(struct intel_pt_pkt * pip_packet)2538fa8f949dSAdrian Hunter static inline bool pip_in_vm(struct intel_pt_pkt *pip_packet)
2539fa8f949dSAdrian Hunter {
2540fa8f949dSAdrian Hunter 	return pip_packet->payload & 1;
2541fa8f949dSAdrian Hunter }
2542fa8f949dSAdrian Hunter 
intel_pt_print_vmcs_info(struct intel_pt_vmcs_info * vmcs_info)2543fa8f949dSAdrian Hunter static void intel_pt_print_vmcs_info(struct intel_pt_vmcs_info *vmcs_info)
2544fa8f949dSAdrian Hunter {
2545fa8f949dSAdrian Hunter 	p_log("VMCS: %#" PRIx64 "  TSC Offset %#" PRIx64,
2546fa8f949dSAdrian Hunter 	      vmcs_info->vmcs, vmcs_info->tsc_offset);
2547fa8f949dSAdrian Hunter }
2548fa8f949dSAdrian Hunter 
intel_pt_vm_tm_corr_psb(struct intel_pt_decoder * decoder,struct intel_pt_vm_tsc_info * data)2549fa8f949dSAdrian Hunter static void intel_pt_vm_tm_corr_psb(struct intel_pt_decoder *decoder,
2550fa8f949dSAdrian Hunter 				    struct intel_pt_vm_tsc_info *data)
2551fa8f949dSAdrian Hunter {
2552fa8f949dSAdrian Hunter 	memset(data, 0, sizeof(*data));
2553fa8f949dSAdrian Hunter 	data->ctc_delta = decoder->ctc_delta;
2554fa8f949dSAdrian Hunter 	data->last_ctc = decoder->last_ctc;
2555fa8f949dSAdrian Hunter 	intel_pt_pkt_lookahead(decoder, intel_pt_vm_psb_lookahead_cb, data);
2556fa8f949dSAdrian Hunter 	if (data->tsc && !data->psbend)
2557fa8f949dSAdrian Hunter 		p_log("ERROR: PSB without PSBEND");
2558fa8f949dSAdrian Hunter 	decoder->in_psb = data->psbend;
2559fa8f949dSAdrian Hunter }
2560fa8f949dSAdrian Hunter 
intel_pt_vm_tm_corr_first_tsc(struct intel_pt_decoder * decoder,struct intel_pt_vm_tsc_info * data,struct intel_pt_vmcs_info * vmcs_info,uint64_t host_tsc)2561fa8f949dSAdrian Hunter static void intel_pt_vm_tm_corr_first_tsc(struct intel_pt_decoder *decoder,
2562fa8f949dSAdrian Hunter 					  struct intel_pt_vm_tsc_info *data,
2563fa8f949dSAdrian Hunter 					  struct intel_pt_vmcs_info *vmcs_info,
2564fa8f949dSAdrian Hunter 					  uint64_t host_tsc)
2565fa8f949dSAdrian Hunter {
2566fa8f949dSAdrian Hunter 	if (!decoder->in_psb) {
2567fa8f949dSAdrian Hunter 		/* Can't happen */
2568fa8f949dSAdrian Hunter 		p_log("ERROR: First TSC is not in PSB+");
2569fa8f949dSAdrian Hunter 	}
2570fa8f949dSAdrian Hunter 
2571fa8f949dSAdrian Hunter 	if (data->pip) {
2572fa8f949dSAdrian Hunter 		if (pip_in_vm(&data->pip_packet)) { /* Guest */
2573fa8f949dSAdrian Hunter 			if (vmcs_info && vmcs_info->tsc_offset) {
2574fa8f949dSAdrian Hunter 				intel_pt_translate_vm_tsc(decoder, vmcs_info);
2575fa8f949dSAdrian Hunter 				decoder->vm_tm_corr_reliable = true;
2576fa8f949dSAdrian Hunter 			} else {
2577fa8f949dSAdrian Hunter 				p_log("ERROR: First TSC, unknown TSC Offset");
2578fa8f949dSAdrian Hunter 			}
2579fa8f949dSAdrian Hunter 		} else { /* Host */
2580fa8f949dSAdrian Hunter 			decoder->vm_tm_corr_reliable = true;
2581fa8f949dSAdrian Hunter 		}
2582fa8f949dSAdrian Hunter 	} else { /* Host or Guest */
2583fa8f949dSAdrian Hunter 		decoder->vm_tm_corr_reliable = false;
2584fa8f949dSAdrian Hunter 		if (intel_pt_time_in_range(decoder, host_tsc)) {
2585fa8f949dSAdrian Hunter 			/* Assume Host */
2586fa8f949dSAdrian Hunter 		} else {
2587fa8f949dSAdrian Hunter 			/* Assume Guest */
2588fa8f949dSAdrian Hunter 			if (vmcs_info && vmcs_info->tsc_offset)
2589fa8f949dSAdrian Hunter 				intel_pt_translate_vm_tsc(decoder, vmcs_info);
2590fa8f949dSAdrian Hunter 			else
2591fa8f949dSAdrian Hunter 				p_log("ERROR: First TSC, no PIP, unknown TSC Offset");
2592fa8f949dSAdrian Hunter 		}
2593fa8f949dSAdrian Hunter 	}
2594fa8f949dSAdrian Hunter }
2595fa8f949dSAdrian Hunter 
intel_pt_vm_tm_corr_tsc(struct intel_pt_decoder * decoder,struct intel_pt_vm_tsc_info * data)2596fa8f949dSAdrian Hunter static void intel_pt_vm_tm_corr_tsc(struct intel_pt_decoder *decoder,
2597fa8f949dSAdrian Hunter 				    struct intel_pt_vm_tsc_info *data)
2598fa8f949dSAdrian Hunter {
2599fa8f949dSAdrian Hunter 	struct intel_pt_vmcs_info *vmcs_info;
2600fa8f949dSAdrian Hunter 	uint64_t tsc_offset = 0;
2601fa8f949dSAdrian Hunter 	uint64_t vmcs;
2602fa8f949dSAdrian Hunter 	bool reliable = true;
2603fa8f949dSAdrian Hunter 	uint64_t expected_tsc;
2604fa8f949dSAdrian Hunter 	uint64_t host_tsc;
2605fa8f949dSAdrian Hunter 	uint64_t ref_timestamp;
2606fa8f949dSAdrian Hunter 
2607fa8f949dSAdrian Hunter 	bool assign = false;
2608fa8f949dSAdrian Hunter 	bool assign_reliable = false;
2609fa8f949dSAdrian Hunter 
2610fa8f949dSAdrian Hunter 	/* Already have 'data' for the in_psb case */
2611fa8f949dSAdrian Hunter 	if (!decoder->in_psb) {
2612fa8f949dSAdrian Hunter 		memset(data, 0, sizeof(*data));
2613fa8f949dSAdrian Hunter 		data->ctc_delta = decoder->ctc_delta;
2614fa8f949dSAdrian Hunter 		data->last_ctc = decoder->last_ctc;
2615fa8f949dSAdrian Hunter 		data->max_lookahead = 16;
2616fa8f949dSAdrian Hunter 		intel_pt_pkt_lookahead(decoder, intel_pt_tma_lookahead_cb, data);
2617fa8f949dSAdrian Hunter 		if (decoder->pge) {
2618fa8f949dSAdrian Hunter 			data->pip = true;
2619fa8f949dSAdrian Hunter 			data->pip_packet.payload = decoder->pip_payload;
2620fa8f949dSAdrian Hunter 		}
2621fa8f949dSAdrian Hunter 	}
2622fa8f949dSAdrian Hunter 
2623fa8f949dSAdrian Hunter 	/* Calculations depend on having TMA packets */
2624fa8f949dSAdrian Hunter 	if (!data->tma) {
2625fa8f949dSAdrian Hunter 		p_log("ERROR: TSC without TMA");
2626fa8f949dSAdrian Hunter 		return;
2627fa8f949dSAdrian Hunter 	}
2628fa8f949dSAdrian Hunter 
2629fa8f949dSAdrian Hunter 	vmcs = data->vmcs ? data->vmcs_packet.payload : decoder->vmcs;
2630fa8f949dSAdrian Hunter 	if (vmcs == NO_VMCS)
2631fa8f949dSAdrian Hunter 		vmcs = 0;
2632fa8f949dSAdrian Hunter 
2633fa8f949dSAdrian Hunter 	vmcs_info = decoder->findnew_vmcs_info(decoder->data, vmcs);
2634fa8f949dSAdrian Hunter 
2635fa8f949dSAdrian Hunter 	ref_timestamp = decoder->timestamp ? decoder->timestamp : decoder->buf_timestamp;
2636fa8f949dSAdrian Hunter 	host_tsc = intel_pt_8b_tsc(decoder->packet.payload, ref_timestamp);
2637fa8f949dSAdrian Hunter 
2638fa8f949dSAdrian Hunter 	if (!decoder->ctc_timestamp) {
2639fa8f949dSAdrian Hunter 		intel_pt_vm_tm_corr_first_tsc(decoder, data, vmcs_info, host_tsc);
2640fa8f949dSAdrian Hunter 		return;
2641fa8f949dSAdrian Hunter 	}
2642fa8f949dSAdrian Hunter 
2643fa8f949dSAdrian Hunter 	expected_tsc = intel_pt_expected_tsc(decoder, data);
2644fa8f949dSAdrian Hunter 
2645fa8f949dSAdrian Hunter 	tsc_offset = host_tsc - expected_tsc;
2646fa8f949dSAdrian Hunter 
2647fa8f949dSAdrian Hunter 	/* Determine if TSC is from Host or Guest */
2648fa8f949dSAdrian Hunter 	if (data->pip) {
2649fa8f949dSAdrian Hunter 		if (pip_in_vm(&data->pip_packet)) { /* Guest */
2650fa8f949dSAdrian Hunter 			if (!vmcs_info) {
2651fa8f949dSAdrian Hunter 				/* PIP NR=1 without VMCS cannot happen */
2652fa8f949dSAdrian Hunter 				p_log("ERROR: Missing VMCS");
2653fa8f949dSAdrian Hunter 				intel_pt_translate_vm_tsc_offset(decoder, tsc_offset);
2654fa8f949dSAdrian Hunter 				decoder->vm_tm_corr_reliable = false;
2655fa8f949dSAdrian Hunter 				return;
2656fa8f949dSAdrian Hunter 			}
2657fa8f949dSAdrian Hunter 		} else { /* Host */
2658fa8f949dSAdrian Hunter 			decoder->last_reliable_timestamp = host_tsc;
2659fa8f949dSAdrian Hunter 			decoder->vm_tm_corr_reliable = true;
2660fa8f949dSAdrian Hunter 			return;
2661fa8f949dSAdrian Hunter 		}
2662fa8f949dSAdrian Hunter 	} else { /* Host or Guest */
2663fa8f949dSAdrian Hunter 		reliable = false; /* Host/Guest is a guess, so not reliable */
2664fa8f949dSAdrian Hunter 		if (decoder->in_psb) {
2665fa8f949dSAdrian Hunter 			if (!tsc_offset)
2666fa8f949dSAdrian Hunter 				return; /* Zero TSC Offset, assume Host */
2667fa8f949dSAdrian Hunter 			/*
2668fa8f949dSAdrian Hunter 			 * TSC packet has only 7 bytes of TSC. We have no
2669fa8f949dSAdrian Hunter 			 * information about the Guest's 8th byte, but it
2670fa8f949dSAdrian Hunter 			 * doesn't matter because we only need 7 bytes.
2671fa8f949dSAdrian Hunter 			 * Here, since the 8th byte is unreliable and
2672fa8f949dSAdrian Hunter 			 * irrelevant, compare only 7 byes.
2673fa8f949dSAdrian Hunter 			 */
2674fa8f949dSAdrian Hunter 			if (vmcs_info &&
2675fa8f949dSAdrian Hunter 			    (tsc_offset & SEVEN_BYTES) ==
2676fa8f949dSAdrian Hunter 			    (vmcs_info->tsc_offset & SEVEN_BYTES)) {
2677fa8f949dSAdrian Hunter 				/* Same TSC Offset as last VMCS, assume Guest */
2678fa8f949dSAdrian Hunter 				goto guest;
2679fa8f949dSAdrian Hunter 			}
2680fa8f949dSAdrian Hunter 		}
2681fa8f949dSAdrian Hunter 		/*
2682fa8f949dSAdrian Hunter 		 * Check if the host_tsc is within the expected range.
2683fa8f949dSAdrian Hunter 		 * Note, we could narrow the range more by looking ahead for
2684fa8f949dSAdrian Hunter 		 * the next host TSC in the same buffer, but we don't bother to
2685fa8f949dSAdrian Hunter 		 * do that because this is probably good enough.
2686fa8f949dSAdrian Hunter 		 */
2687fa8f949dSAdrian Hunter 		if (host_tsc >= expected_tsc && intel_pt_time_in_range(decoder, host_tsc)) {
2688fa8f949dSAdrian Hunter 			/* Within expected range for Host TSC, assume Host */
2689fa8f949dSAdrian Hunter 			decoder->vm_tm_corr_reliable = false;
2690fa8f949dSAdrian Hunter 			return;
2691fa8f949dSAdrian Hunter 		}
2692fa8f949dSAdrian Hunter 	}
2693fa8f949dSAdrian Hunter 
2694fa8f949dSAdrian Hunter guest: /* Assuming Guest */
2695fa8f949dSAdrian Hunter 
2696fa8f949dSAdrian Hunter 	/* Determine whether to assign TSC Offset */
2697fa8f949dSAdrian Hunter 	if (vmcs_info && vmcs_info->vmcs) {
2698fa8f949dSAdrian Hunter 		if (vmcs_info->tsc_offset && vmcs_info->reliable) {
2699fa8f949dSAdrian Hunter 			assign = false;
2700fa8f949dSAdrian Hunter 		} else if (decoder->in_psb && data->pip && decoder->vm_tm_corr_reliable &&
2701fa8f949dSAdrian Hunter 			   decoder->vm_tm_corr_continuous && decoder->vm_tm_corr_same_buf) {
2702fa8f949dSAdrian Hunter 			/* Continuous tracing, TSC in a PSB is not a time loss */
2703fa8f949dSAdrian Hunter 			assign = true;
2704fa8f949dSAdrian Hunter 			assign_reliable = true;
2705fa8f949dSAdrian Hunter 		} else if (decoder->in_psb && data->pip && decoder->vm_tm_corr_same_buf) {
2706fa8f949dSAdrian Hunter 			/*
2707fa8f949dSAdrian Hunter 			 * Unlikely to be a time loss TSC in a PSB which is not
2708fa8f949dSAdrian Hunter 			 * at the start of a buffer.
2709fa8f949dSAdrian Hunter 			 */
2710fa8f949dSAdrian Hunter 			assign = true;
2711fa8f949dSAdrian Hunter 			assign_reliable = false;
2712fa8f949dSAdrian Hunter 		}
2713fa8f949dSAdrian Hunter 	}
2714fa8f949dSAdrian Hunter 
2715fa8f949dSAdrian Hunter 	/* Record VMCS TSC Offset */
2716fa8f949dSAdrian Hunter 	if (assign && (vmcs_info->tsc_offset != tsc_offset ||
2717fa8f949dSAdrian Hunter 		       vmcs_info->reliable != assign_reliable)) {
2718fa8f949dSAdrian Hunter 		bool print = vmcs_info->tsc_offset != tsc_offset;
2719fa8f949dSAdrian Hunter 
2720fa8f949dSAdrian Hunter 		vmcs_info->tsc_offset = tsc_offset;
2721fa8f949dSAdrian Hunter 		vmcs_info->reliable = assign_reliable;
2722fa8f949dSAdrian Hunter 		if (print)
2723fa8f949dSAdrian Hunter 			intel_pt_print_vmcs_info(vmcs_info);
2724fa8f949dSAdrian Hunter 	}
2725fa8f949dSAdrian Hunter 
2726fa8f949dSAdrian Hunter 	/* Determine what TSC Offset to use */
2727fa8f949dSAdrian Hunter 	if (vmcs_info && vmcs_info->tsc_offset) {
2728fa8f949dSAdrian Hunter 		if (!vmcs_info->reliable)
2729fa8f949dSAdrian Hunter 			reliable = false;
2730fa8f949dSAdrian Hunter 		intel_pt_translate_vm_tsc(decoder, vmcs_info);
2731fa8f949dSAdrian Hunter 	} else {
2732fa8f949dSAdrian Hunter 		reliable = false;
2733fa8f949dSAdrian Hunter 		if (vmcs_info) {
2734fa8f949dSAdrian Hunter 			if (!vmcs_info->error_printed) {
2735fa8f949dSAdrian Hunter 				p_log("ERROR: Unknown TSC Offset for VMCS %#" PRIx64,
2736fa8f949dSAdrian Hunter 				      vmcs_info->vmcs);
2737fa8f949dSAdrian Hunter 				vmcs_info->error_printed = true;
2738fa8f949dSAdrian Hunter 			}
2739fa8f949dSAdrian Hunter 		} else {
2740fa8f949dSAdrian Hunter 			if (intel_pt_print_once(decoder, INTEL_PT_PRT_ONCE_UNK_VMCS))
2741fa8f949dSAdrian Hunter 				p_log("ERROR: Unknown VMCS");
2742fa8f949dSAdrian Hunter 		}
2743fa8f949dSAdrian Hunter 		intel_pt_translate_vm_tsc_offset(decoder, tsc_offset);
2744fa8f949dSAdrian Hunter 	}
2745fa8f949dSAdrian Hunter 
2746fa8f949dSAdrian Hunter 	decoder->vm_tm_corr_reliable = reliable;
2747fa8f949dSAdrian Hunter }
2748fa8f949dSAdrian Hunter 
intel_pt_vm_tm_corr_pebs_tsc(struct intel_pt_decoder * decoder)2749fa8f949dSAdrian Hunter static void intel_pt_vm_tm_corr_pebs_tsc(struct intel_pt_decoder *decoder)
2750fa8f949dSAdrian Hunter {
2751fa8f949dSAdrian Hunter 	uint64_t host_tsc = decoder->packet.payload;
2752fa8f949dSAdrian Hunter 	uint64_t guest_tsc = decoder->packet.payload;
2753fa8f949dSAdrian Hunter 	struct intel_pt_vmcs_info *vmcs_info;
2754fa8f949dSAdrian Hunter 	uint64_t vmcs;
2755fa8f949dSAdrian Hunter 
2756fa8f949dSAdrian Hunter 	vmcs = decoder->vmcs;
2757fa8f949dSAdrian Hunter 	if (vmcs == NO_VMCS)
2758fa8f949dSAdrian Hunter 		vmcs = 0;
2759fa8f949dSAdrian Hunter 
2760fa8f949dSAdrian Hunter 	vmcs_info = decoder->findnew_vmcs_info(decoder->data, vmcs);
2761fa8f949dSAdrian Hunter 
2762fa8f949dSAdrian Hunter 	if (decoder->pge) {
2763fa8f949dSAdrian Hunter 		if (in_vm(decoder->pip_payload)) { /* Guest */
2764fa8f949dSAdrian Hunter 			if (!vmcs_info) {
2765fa8f949dSAdrian Hunter 				/* PIP NR=1 without VMCS cannot happen */
2766fa8f949dSAdrian Hunter 				p_log("ERROR: Missing VMCS");
2767fa8f949dSAdrian Hunter 			}
2768fa8f949dSAdrian Hunter 		} else { /* Host */
2769fa8f949dSAdrian Hunter 			return;
2770fa8f949dSAdrian Hunter 		}
2771fa8f949dSAdrian Hunter 	} else { /* Host or Guest */
2772fa8f949dSAdrian Hunter 		if (intel_pt_time_in_range(decoder, host_tsc)) {
2773fa8f949dSAdrian Hunter 			/* Within expected range for Host TSC, assume Host */
2774fa8f949dSAdrian Hunter 			return;
2775fa8f949dSAdrian Hunter 		}
2776fa8f949dSAdrian Hunter 	}
2777fa8f949dSAdrian Hunter 
2778fa8f949dSAdrian Hunter 	if (vmcs_info) {
2779fa8f949dSAdrian Hunter 		/* Translate Guest TSC to Host TSC */
2780fa8f949dSAdrian Hunter 		host_tsc = ((guest_tsc & SEVEN_BYTES) - vmcs_info->tsc_offset) & SEVEN_BYTES;
2781fa8f949dSAdrian Hunter 		host_tsc = intel_pt_8b_tsc(host_tsc, decoder->timestamp);
2782fa8f949dSAdrian Hunter 		intel_pt_log("Translated VM TSC %#" PRIx64 " -> %#" PRIx64
2783fa8f949dSAdrian Hunter 			     "    VMCS %#" PRIx64 "    TSC Offset %#" PRIx64 "\n",
2784fa8f949dSAdrian Hunter 			     guest_tsc, host_tsc, vmcs_info->vmcs,
2785fa8f949dSAdrian Hunter 			     vmcs_info->tsc_offset);
2786fa8f949dSAdrian Hunter 		if (!intel_pt_time_in_range(decoder, host_tsc) &&
2787fa8f949dSAdrian Hunter 		    intel_pt_print_once(decoder, INTEL_PT_PRT_ONCE_ERANGE))
2788fa8f949dSAdrian Hunter 			p_log("Timestamp out of range");
2789fa8f949dSAdrian Hunter 	} else {
2790fa8f949dSAdrian Hunter 		if (intel_pt_print_once(decoder, INTEL_PT_PRT_ONCE_UNK_VMCS))
2791fa8f949dSAdrian Hunter 			p_log("ERROR: Unknown VMCS");
2792fa8f949dSAdrian Hunter 		host_tsc = decoder->timestamp;
2793fa8f949dSAdrian Hunter 	}
2794fa8f949dSAdrian Hunter 
2795fa8f949dSAdrian Hunter 	decoder->packet.payload = host_tsc;
2796fa8f949dSAdrian Hunter 
2797fa8f949dSAdrian Hunter 	if (!decoder->vm_tm_corr_dry_run)
2798fa8f949dSAdrian Hunter 		memcpy((void *)decoder->buf + 1, &host_tsc, 8);
2799fa8f949dSAdrian Hunter }
2800fa8f949dSAdrian Hunter 
intel_pt_vm_time_correlation(struct intel_pt_decoder * decoder)2801fa8f949dSAdrian Hunter static int intel_pt_vm_time_correlation(struct intel_pt_decoder *decoder)
2802fa8f949dSAdrian Hunter {
2803fa8f949dSAdrian Hunter 	struct intel_pt_vm_tsc_info data = { .psbend = false };
2804fa8f949dSAdrian Hunter 	bool pge;
2805fa8f949dSAdrian Hunter 	int err;
2806fa8f949dSAdrian Hunter 
2807fa8f949dSAdrian Hunter 	if (decoder->in_psb)
2808fa8f949dSAdrian Hunter 		intel_pt_vm_tm_corr_psb(decoder, &data);
2809fa8f949dSAdrian Hunter 
2810fa8f949dSAdrian Hunter 	while (1) {
2811fa8f949dSAdrian Hunter 		err = intel_pt_get_next_packet(decoder);
2812fa8f949dSAdrian Hunter 		if (err == -ENOLINK)
2813fa8f949dSAdrian Hunter 			continue;
2814fa8f949dSAdrian Hunter 		if (err)
2815fa8f949dSAdrian Hunter 			break;
2816fa8f949dSAdrian Hunter 
2817fa8f949dSAdrian Hunter 		switch (decoder->packet.type) {
2818fa8f949dSAdrian Hunter 		case INTEL_PT_TIP_PGD:
2819fa8f949dSAdrian Hunter 			decoder->pge = false;
2820fa8f949dSAdrian Hunter 			decoder->vm_tm_corr_continuous = false;
2821fa8f949dSAdrian Hunter 			break;
2822fa8f949dSAdrian Hunter 
2823fa8f949dSAdrian Hunter 		case INTEL_PT_TNT:
2824fa8f949dSAdrian Hunter 		case INTEL_PT_TIP:
2825fa8f949dSAdrian Hunter 		case INTEL_PT_TIP_PGE:
2826fa8f949dSAdrian Hunter 			decoder->pge = true;
2827fa8f949dSAdrian Hunter 			break;
2828fa8f949dSAdrian Hunter 
2829fa8f949dSAdrian Hunter 		case INTEL_PT_OVF:
2830fa8f949dSAdrian Hunter 			decoder->in_psb = false;
2831fa8f949dSAdrian Hunter 			pge = decoder->pge;
2832fa8f949dSAdrian Hunter 			decoder->pge = intel_pt_ovf_fup_lookahead(decoder);
2833fa8f949dSAdrian Hunter 			if (pge != decoder->pge)
2834fa8f949dSAdrian Hunter 				intel_pt_log("Surprising PGE change in OVF!");
2835fa8f949dSAdrian Hunter 			if (!decoder->pge)
2836fa8f949dSAdrian Hunter 				decoder->vm_tm_corr_continuous = false;
2837fa8f949dSAdrian Hunter 			break;
2838fa8f949dSAdrian Hunter 
2839fa8f949dSAdrian Hunter 		case INTEL_PT_FUP:
2840fa8f949dSAdrian Hunter 			if (decoder->in_psb)
2841fa8f949dSAdrian Hunter 				decoder->pge = true;
2842fa8f949dSAdrian Hunter 			break;
2843fa8f949dSAdrian Hunter 
2844fa8f949dSAdrian Hunter 		case INTEL_PT_TRACESTOP:
2845fa8f949dSAdrian Hunter 			decoder->pge = false;
2846fa8f949dSAdrian Hunter 			decoder->vm_tm_corr_continuous = false;
2847fa8f949dSAdrian Hunter 			decoder->have_tma = false;
2848fa8f949dSAdrian Hunter 			break;
2849fa8f949dSAdrian Hunter 
2850fa8f949dSAdrian Hunter 		case INTEL_PT_PSB:
2851fa8f949dSAdrian Hunter 			intel_pt_vm_tm_corr_psb(decoder, &data);
2852fa8f949dSAdrian Hunter 			break;
2853fa8f949dSAdrian Hunter 
2854fa8f949dSAdrian Hunter 		case INTEL_PT_PIP:
2855fa8f949dSAdrian Hunter 			decoder->pip_payload = decoder->packet.payload;
2856fa8f949dSAdrian Hunter 			break;
2857fa8f949dSAdrian Hunter 
2858fa8f949dSAdrian Hunter 		case INTEL_PT_MTC:
2859fa8f949dSAdrian Hunter 			intel_pt_calc_mtc_timestamp(decoder);
2860fa8f949dSAdrian Hunter 			break;
2861fa8f949dSAdrian Hunter 
2862fa8f949dSAdrian Hunter 		case INTEL_PT_TSC:
2863fa8f949dSAdrian Hunter 			intel_pt_vm_tm_corr_tsc(decoder, &data);
2864fa8f949dSAdrian Hunter 			intel_pt_calc_tsc_timestamp(decoder);
2865fa8f949dSAdrian Hunter 			decoder->vm_tm_corr_same_buf = true;
2866fa8f949dSAdrian Hunter 			decoder->vm_tm_corr_continuous = decoder->pge;
2867fa8f949dSAdrian Hunter 			break;
2868fa8f949dSAdrian Hunter 
2869fa8f949dSAdrian Hunter 		case INTEL_PT_TMA:
2870fa8f949dSAdrian Hunter 			intel_pt_calc_tma(decoder);
2871fa8f949dSAdrian Hunter 			break;
2872fa8f949dSAdrian Hunter 
2873fa8f949dSAdrian Hunter 		case INTEL_PT_CYC:
2874fa8f949dSAdrian Hunter 			intel_pt_calc_cyc_timestamp(decoder);
2875fa8f949dSAdrian Hunter 			break;
2876fa8f949dSAdrian Hunter 
2877fa8f949dSAdrian Hunter 		case INTEL_PT_CBR:
2878fa8f949dSAdrian Hunter 			intel_pt_calc_cbr(decoder);
2879fa8f949dSAdrian Hunter 			break;
2880fa8f949dSAdrian Hunter 
2881fa8f949dSAdrian Hunter 		case INTEL_PT_PSBEND:
2882fa8f949dSAdrian Hunter 			decoder->in_psb = false;
2883fa8f949dSAdrian Hunter 			data.psbend = false;
2884fa8f949dSAdrian Hunter 			break;
2885fa8f949dSAdrian Hunter 
2886fa8f949dSAdrian Hunter 		case INTEL_PT_VMCS:
2887fa8f949dSAdrian Hunter 			if (decoder->packet.payload != NO_VMCS)
2888fa8f949dSAdrian Hunter 				decoder->vmcs = decoder->packet.payload;
2889fa8f949dSAdrian Hunter 			break;
2890fa8f949dSAdrian Hunter 
2891fa8f949dSAdrian Hunter 		case INTEL_PT_BBP:
2892fa8f949dSAdrian Hunter 			decoder->blk_type = decoder->packet.payload;
2893fa8f949dSAdrian Hunter 			break;
2894fa8f949dSAdrian Hunter 
2895fa8f949dSAdrian Hunter 		case INTEL_PT_BIP:
2896fa8f949dSAdrian Hunter 			if (decoder->blk_type == INTEL_PT_PEBS_BASIC &&
2897fa8f949dSAdrian Hunter 			    decoder->packet.count == 2)
2898fa8f949dSAdrian Hunter 				intel_pt_vm_tm_corr_pebs_tsc(decoder);
2899fa8f949dSAdrian Hunter 			break;
2900fa8f949dSAdrian Hunter 
2901fa8f949dSAdrian Hunter 		case INTEL_PT_BEP:
2902fa8f949dSAdrian Hunter 		case INTEL_PT_BEP_IP:
2903fa8f949dSAdrian Hunter 			decoder->blk_type = 0;
2904fa8f949dSAdrian Hunter 			break;
2905fa8f949dSAdrian Hunter 
29062750af50SAdrian Hunter 		case INTEL_PT_CFE:
29072750af50SAdrian Hunter 		case INTEL_PT_CFE_IP:
29082750af50SAdrian Hunter 		case INTEL_PT_EVD:
2909fa8f949dSAdrian Hunter 		case INTEL_PT_MODE_EXEC:
2910fa8f949dSAdrian Hunter 		case INTEL_PT_MODE_TSX:
2911fa8f949dSAdrian Hunter 		case INTEL_PT_MNT:
2912fa8f949dSAdrian Hunter 		case INTEL_PT_PAD:
2913fa8f949dSAdrian Hunter 		case INTEL_PT_PTWRITE_IP:
2914fa8f949dSAdrian Hunter 		case INTEL_PT_PTWRITE:
2915fa8f949dSAdrian Hunter 		case INTEL_PT_MWAIT:
2916fa8f949dSAdrian Hunter 		case INTEL_PT_PWRE:
2917fa8f949dSAdrian Hunter 		case INTEL_PT_EXSTOP_IP:
2918fa8f949dSAdrian Hunter 		case INTEL_PT_EXSTOP:
2919fa8f949dSAdrian Hunter 		case INTEL_PT_PWRX:
2920fa8f949dSAdrian Hunter 		case INTEL_PT_BAD: /* Does not happen */
2921fa8f949dSAdrian Hunter 		default:
2922fa8f949dSAdrian Hunter 			break;
2923fa8f949dSAdrian Hunter 		}
2924fa8f949dSAdrian Hunter 	}
2925fa8f949dSAdrian Hunter 
2926fa8f949dSAdrian Hunter 	return err;
2927fa8f949dSAdrian Hunter }
2928fa8f949dSAdrian Hunter 
29297c1b16baSAdrian Hunter #define HOP_PROCESS	0
29307c1b16baSAdrian Hunter #define HOP_IGNORE	1
29317c1b16baSAdrian Hunter #define HOP_RETURN	2
29327c1b16baSAdrian Hunter #define HOP_AGAIN	3
29337c1b16baSAdrian Hunter 
2934347a7389SAdrian Hunter static int intel_pt_scan_for_psb(struct intel_pt_decoder *decoder);
2935347a7389SAdrian Hunter 
29367c1b16baSAdrian Hunter /* Hop mode: Ignore TNT, do not walk code, but get ip from FUPs and TIPs */
intel_pt_hop_trace(struct intel_pt_decoder * decoder,bool * no_tip,int * err)29377c1b16baSAdrian Hunter static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, int *err)
29387c1b16baSAdrian Hunter {
2939a882cc94SAdrian Hunter 	*err = 0;
2940a882cc94SAdrian Hunter 
2941347a7389SAdrian Hunter 	/* Leap from PSB to PSB, getting ip from FUP within PSB+ */
2942347a7389SAdrian Hunter 	if (decoder->leap && !decoder->in_psb && decoder->packet.type != INTEL_PT_PSB) {
2943347a7389SAdrian Hunter 		*err = intel_pt_scan_for_psb(decoder);
2944347a7389SAdrian Hunter 		if (*err)
2945347a7389SAdrian Hunter 			return HOP_RETURN;
2946347a7389SAdrian Hunter 	}
2947347a7389SAdrian Hunter 
29487c1b16baSAdrian Hunter 	switch (decoder->packet.type) {
29497c1b16baSAdrian Hunter 	case INTEL_PT_TNT:
29507c1b16baSAdrian Hunter 		return HOP_IGNORE;
29517c1b16baSAdrian Hunter 
29527c1b16baSAdrian Hunter 	case INTEL_PT_TIP_PGD:
2953057ae59fSAdrian Hunter 		decoder->pge = false;
295480a03886SAdrian Hunter 		if (!decoder->packet.count) {
295580a03886SAdrian Hunter 			intel_pt_set_nr(decoder);
29567c1b16baSAdrian Hunter 			return HOP_IGNORE;
295780a03886SAdrian Hunter 		}
29587c1b16baSAdrian Hunter 		intel_pt_set_ip(decoder);
29597c1b16baSAdrian Hunter 		decoder->state.type |= INTEL_PT_TRACE_END;
29607c1b16baSAdrian Hunter 		decoder->state.from_ip = 0;
29617c1b16baSAdrian Hunter 		decoder->state.to_ip = decoder->ip;
296280a03886SAdrian Hunter 		intel_pt_update_nr(decoder);
29637c1b16baSAdrian Hunter 		return HOP_RETURN;
29647c1b16baSAdrian Hunter 
29657c1b16baSAdrian Hunter 	case INTEL_PT_TIP:
296680a03886SAdrian Hunter 		if (!decoder->packet.count) {
296780a03886SAdrian Hunter 			intel_pt_set_nr(decoder);
29687c1b16baSAdrian Hunter 			return HOP_IGNORE;
296980a03886SAdrian Hunter 		}
29707c1b16baSAdrian Hunter 		intel_pt_set_ip(decoder);
29717c1b16baSAdrian Hunter 		decoder->state.type = INTEL_PT_INSTRUCTION;
29727c1b16baSAdrian Hunter 		decoder->state.from_ip = decoder->ip;
29737c1b16baSAdrian Hunter 		decoder->state.to_ip = 0;
297480a03886SAdrian Hunter 		intel_pt_update_nr(decoder);
2975cf0c98e2SAdrian Hunter 		intel_pt_sample_iflag_chg(decoder);
29767c1b16baSAdrian Hunter 		return HOP_RETURN;
29777c1b16baSAdrian Hunter 
29787c1b16baSAdrian Hunter 	case INTEL_PT_FUP:
29797c1b16baSAdrian Hunter 		if (!decoder->packet.count)
29807c1b16baSAdrian Hunter 			return HOP_IGNORE;
29817c1b16baSAdrian Hunter 		intel_pt_set_ip(decoder);
2982a882cc94SAdrian Hunter 		if (decoder->set_fup_mwait || decoder->set_fup_pwre)
2983a882cc94SAdrian Hunter 			*no_tip = true;
2984057ae59fSAdrian Hunter 		if (!decoder->branch_enable || !decoder->pge)
29857c1b16baSAdrian Hunter 			*no_tip = true;
29867c1b16baSAdrian Hunter 		if (*no_tip) {
29877c1b16baSAdrian Hunter 			decoder->state.type = INTEL_PT_INSTRUCTION;
29887c1b16baSAdrian Hunter 			decoder->state.from_ip = decoder->ip;
29897c1b16baSAdrian Hunter 			decoder->state.to_ip = 0;
2990cf0c98e2SAdrian Hunter 			intel_pt_fup_event(decoder, *no_tip);
29917c1b16baSAdrian Hunter 			return HOP_RETURN;
29927c1b16baSAdrian Hunter 		}
2993cf0c98e2SAdrian Hunter 		intel_pt_fup_event(decoder, *no_tip);
2994a882cc94SAdrian Hunter 		decoder->state.type |= INTEL_PT_INSTRUCTION | INTEL_PT_BRANCH;
29957c1b16baSAdrian Hunter 		*err = intel_pt_walk_fup_tip(decoder);
2996a882cc94SAdrian Hunter 		if (!*err && decoder->state.to_ip)
29977c1b16baSAdrian Hunter 			decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
29987c1b16baSAdrian Hunter 		return HOP_RETURN;
29997c1b16baSAdrian Hunter 
30007c1b16baSAdrian Hunter 	case INTEL_PT_PSB:
3001c840cbfeSAdrian Hunter 		decoder->state.psb_offset = decoder->pos;
3002c840cbfeSAdrian Hunter 		decoder->psb_ip = 0;
30037c1b16baSAdrian Hunter 		decoder->last_ip = 0;
30047c1b16baSAdrian Hunter 		decoder->have_last_ip = true;
30057c1b16baSAdrian Hunter 		*err = intel_pt_walk_psbend(decoder);
30067c1b16baSAdrian Hunter 		if (*err == -EAGAIN)
30077c1b16baSAdrian Hunter 			return HOP_AGAIN;
30087c1b16baSAdrian Hunter 		if (*err)
30097c1b16baSAdrian Hunter 			return HOP_RETURN;
3010c840cbfeSAdrian Hunter 		decoder->state.type = INTEL_PT_PSB_EVT;
3011c840cbfeSAdrian Hunter 		if (decoder->psb_ip) {
3012c840cbfeSAdrian Hunter 			decoder->state.type |= INTEL_PT_INSTRUCTION;
3013c840cbfeSAdrian Hunter 			decoder->ip = decoder->psb_ip;
3014c840cbfeSAdrian Hunter 		}
3015c840cbfeSAdrian Hunter 		decoder->state.from_ip = decoder->psb_ip;
30167c1b16baSAdrian Hunter 		decoder->state.to_ip = 0;
30177c1b16baSAdrian Hunter 		return HOP_RETURN;
30187c1b16baSAdrian Hunter 
30197c1b16baSAdrian Hunter 	case INTEL_PT_BAD:
30207c1b16baSAdrian Hunter 	case INTEL_PT_PAD:
30217c1b16baSAdrian Hunter 	case INTEL_PT_TIP_PGE:
30227c1b16baSAdrian Hunter 	case INTEL_PT_TSC:
30237c1b16baSAdrian Hunter 	case INTEL_PT_TMA:
30247c1b16baSAdrian Hunter 	case INTEL_PT_MODE_EXEC:
30257c1b16baSAdrian Hunter 	case INTEL_PT_MODE_TSX:
30267c1b16baSAdrian Hunter 	case INTEL_PT_MTC:
30277c1b16baSAdrian Hunter 	case INTEL_PT_CYC:
30287c1b16baSAdrian Hunter 	case INTEL_PT_VMCS:
30297c1b16baSAdrian Hunter 	case INTEL_PT_PSBEND:
30307c1b16baSAdrian Hunter 	case INTEL_PT_CBR:
30317c1b16baSAdrian Hunter 	case INTEL_PT_TRACESTOP:
30327c1b16baSAdrian Hunter 	case INTEL_PT_PIP:
30337c1b16baSAdrian Hunter 	case INTEL_PT_OVF:
30347c1b16baSAdrian Hunter 	case INTEL_PT_MNT:
30357c1b16baSAdrian Hunter 	case INTEL_PT_PTWRITE:
30367c1b16baSAdrian Hunter 	case INTEL_PT_PTWRITE_IP:
30377c1b16baSAdrian Hunter 	case INTEL_PT_EXSTOP:
30387c1b16baSAdrian Hunter 	case INTEL_PT_EXSTOP_IP:
30397c1b16baSAdrian Hunter 	case INTEL_PT_MWAIT:
30407c1b16baSAdrian Hunter 	case INTEL_PT_PWRE:
30417c1b16baSAdrian Hunter 	case INTEL_PT_PWRX:
30427c1b16baSAdrian Hunter 	case INTEL_PT_BBP:
30437c1b16baSAdrian Hunter 	case INTEL_PT_BIP:
30447c1b16baSAdrian Hunter 	case INTEL_PT_BEP:
30457c1b16baSAdrian Hunter 	case INTEL_PT_BEP_IP:
30462750af50SAdrian Hunter 	case INTEL_PT_CFE:
30472750af50SAdrian Hunter 	case INTEL_PT_CFE_IP:
30482750af50SAdrian Hunter 	case INTEL_PT_EVD:
30497c1b16baSAdrian Hunter 	default:
30507c1b16baSAdrian Hunter 		return HOP_PROCESS;
30517c1b16baSAdrian Hunter 	}
30527c1b16baSAdrian Hunter }
30537c1b16baSAdrian Hunter 
3054c840cbfeSAdrian Hunter struct intel_pt_psb_info {
3055c840cbfeSAdrian Hunter 	struct intel_pt_pkt fup_packet;
3056c840cbfeSAdrian Hunter 	bool fup;
3057c840cbfeSAdrian Hunter 	int after_psbend;
3058c840cbfeSAdrian Hunter };
3059c840cbfeSAdrian Hunter 
3060c840cbfeSAdrian Hunter /* Lookahead and get the FUP packet from PSB+ */
intel_pt_psb_lookahead_cb(struct intel_pt_pkt_info * pkt_info)3061c840cbfeSAdrian Hunter static int intel_pt_psb_lookahead_cb(struct intel_pt_pkt_info *pkt_info)
3062c840cbfeSAdrian Hunter {
3063c840cbfeSAdrian Hunter 	struct intel_pt_psb_info *data = pkt_info->data;
3064c840cbfeSAdrian Hunter 
3065c840cbfeSAdrian Hunter 	switch (pkt_info->packet.type) {
3066c840cbfeSAdrian Hunter 	case INTEL_PT_PAD:
3067c840cbfeSAdrian Hunter 	case INTEL_PT_MNT:
3068c840cbfeSAdrian Hunter 	case INTEL_PT_TSC:
3069c840cbfeSAdrian Hunter 	case INTEL_PT_TMA:
3070c840cbfeSAdrian Hunter 	case INTEL_PT_MODE_EXEC:
3071c840cbfeSAdrian Hunter 	case INTEL_PT_MODE_TSX:
3072c840cbfeSAdrian Hunter 	case INTEL_PT_MTC:
3073c840cbfeSAdrian Hunter 	case INTEL_PT_CYC:
3074c840cbfeSAdrian Hunter 	case INTEL_PT_VMCS:
3075c840cbfeSAdrian Hunter 	case INTEL_PT_CBR:
3076c840cbfeSAdrian Hunter 	case INTEL_PT_PIP:
3077c840cbfeSAdrian Hunter 		if (data->after_psbend) {
3078c840cbfeSAdrian Hunter 			data->after_psbend -= 1;
3079c840cbfeSAdrian Hunter 			if (!data->after_psbend)
3080c840cbfeSAdrian Hunter 				return 1;
3081c840cbfeSAdrian Hunter 		}
3082c840cbfeSAdrian Hunter 		break;
3083c840cbfeSAdrian Hunter 
3084c840cbfeSAdrian Hunter 	case INTEL_PT_FUP:
3085c840cbfeSAdrian Hunter 		if (data->after_psbend)
3086c840cbfeSAdrian Hunter 			return 1;
3087c840cbfeSAdrian Hunter 		if (data->fup || pkt_info->packet.count == 0)
3088c840cbfeSAdrian Hunter 			return 1;
3089c840cbfeSAdrian Hunter 		data->fup_packet = pkt_info->packet;
3090c840cbfeSAdrian Hunter 		data->fup = true;
3091c840cbfeSAdrian Hunter 		break;
3092c840cbfeSAdrian Hunter 
3093c840cbfeSAdrian Hunter 	case INTEL_PT_PSBEND:
3094c840cbfeSAdrian Hunter 		if (!data->fup)
3095c840cbfeSAdrian Hunter 			return 1;
3096c840cbfeSAdrian Hunter 		/* Keep going to check for a TIP.PGE */
3097c840cbfeSAdrian Hunter 		data->after_psbend = 6;
3098c840cbfeSAdrian Hunter 		break;
3099c840cbfeSAdrian Hunter 
3100c840cbfeSAdrian Hunter 	case INTEL_PT_TIP_PGE:
3101c840cbfeSAdrian Hunter 		/* Ignore FUP in PSB+ if followed by TIP.PGE */
3102c840cbfeSAdrian Hunter 		if (data->after_psbend)
3103c840cbfeSAdrian Hunter 			data->fup = false;
3104c840cbfeSAdrian Hunter 		return 1;
3105c840cbfeSAdrian Hunter 
3106c840cbfeSAdrian Hunter 	case INTEL_PT_PTWRITE:
3107c840cbfeSAdrian Hunter 	case INTEL_PT_PTWRITE_IP:
3108c840cbfeSAdrian Hunter 	case INTEL_PT_EXSTOP:
3109c840cbfeSAdrian Hunter 	case INTEL_PT_EXSTOP_IP:
3110c840cbfeSAdrian Hunter 	case INTEL_PT_MWAIT:
3111c840cbfeSAdrian Hunter 	case INTEL_PT_PWRE:
3112c840cbfeSAdrian Hunter 	case INTEL_PT_PWRX:
3113c840cbfeSAdrian Hunter 	case INTEL_PT_BBP:
3114c840cbfeSAdrian Hunter 	case INTEL_PT_BIP:
3115c840cbfeSAdrian Hunter 	case INTEL_PT_BEP:
3116c840cbfeSAdrian Hunter 	case INTEL_PT_BEP_IP:
31172750af50SAdrian Hunter 	case INTEL_PT_CFE:
31182750af50SAdrian Hunter 	case INTEL_PT_CFE_IP:
31192750af50SAdrian Hunter 	case INTEL_PT_EVD:
3120c840cbfeSAdrian Hunter 		if (data->after_psbend) {
3121c840cbfeSAdrian Hunter 			data->after_psbend -= 1;
3122c840cbfeSAdrian Hunter 			if (!data->after_psbend)
3123c840cbfeSAdrian Hunter 				return 1;
3124c840cbfeSAdrian Hunter 			break;
3125c840cbfeSAdrian Hunter 		}
3126c840cbfeSAdrian Hunter 		return 1;
3127c840cbfeSAdrian Hunter 
3128c840cbfeSAdrian Hunter 	case INTEL_PT_OVF:
3129c840cbfeSAdrian Hunter 	case INTEL_PT_BAD:
3130c840cbfeSAdrian Hunter 	case INTEL_PT_TNT:
3131c840cbfeSAdrian Hunter 	case INTEL_PT_TIP_PGD:
3132c840cbfeSAdrian Hunter 	case INTEL_PT_TIP:
3133c840cbfeSAdrian Hunter 	case INTEL_PT_PSB:
3134c840cbfeSAdrian Hunter 	case INTEL_PT_TRACESTOP:
3135c840cbfeSAdrian Hunter 	default:
3136c840cbfeSAdrian Hunter 		return 1;
3137c840cbfeSAdrian Hunter 	}
3138c840cbfeSAdrian Hunter 
3139c840cbfeSAdrian Hunter 	return 0;
3140c840cbfeSAdrian Hunter }
3141c840cbfeSAdrian Hunter 
intel_pt_psb(struct intel_pt_decoder * decoder)3142c840cbfeSAdrian Hunter static int intel_pt_psb(struct intel_pt_decoder *decoder)
3143c840cbfeSAdrian Hunter {
3144c840cbfeSAdrian Hunter 	int err;
3145c840cbfeSAdrian Hunter 
3146c840cbfeSAdrian Hunter 	decoder->last_ip = 0;
3147c840cbfeSAdrian Hunter 	decoder->psb_ip = 0;
3148c840cbfeSAdrian Hunter 	decoder->have_last_ip = true;
3149c840cbfeSAdrian Hunter 	intel_pt_clear_stack(&decoder->stack);
3150c840cbfeSAdrian Hunter 	err = intel_pt_walk_psbend(decoder);
3151c840cbfeSAdrian Hunter 	if (err)
3152c840cbfeSAdrian Hunter 		return err;
3153c840cbfeSAdrian Hunter 	decoder->state.type = INTEL_PT_PSB_EVT;
3154c840cbfeSAdrian Hunter 	decoder->state.from_ip = decoder->psb_ip;
3155c840cbfeSAdrian Hunter 	decoder->state.to_ip = 0;
3156c840cbfeSAdrian Hunter 	return 0;
3157c840cbfeSAdrian Hunter }
3158c840cbfeSAdrian Hunter 
intel_pt_fup_in_psb(struct intel_pt_decoder * decoder)3159c840cbfeSAdrian Hunter static int intel_pt_fup_in_psb(struct intel_pt_decoder *decoder)
3160c840cbfeSAdrian Hunter {
3161c840cbfeSAdrian Hunter 	int err;
3162c840cbfeSAdrian Hunter 
3163c840cbfeSAdrian Hunter 	if (decoder->ip != decoder->last_ip) {
3164c840cbfeSAdrian Hunter 		err = intel_pt_walk_fup(decoder);
3165c840cbfeSAdrian Hunter 		if (!err || err != -EAGAIN)
3166c840cbfeSAdrian Hunter 			return err;
3167c840cbfeSAdrian Hunter 	}
3168c840cbfeSAdrian Hunter 
3169c840cbfeSAdrian Hunter 	decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
3170c840cbfeSAdrian Hunter 	err = intel_pt_psb(decoder);
3171c840cbfeSAdrian Hunter 	if (err) {
3172c840cbfeSAdrian Hunter 		decoder->pkt_state = INTEL_PT_STATE_ERR3;
3173c840cbfeSAdrian Hunter 		return -ENOENT;
3174c840cbfeSAdrian Hunter 	}
3175c840cbfeSAdrian Hunter 
3176c840cbfeSAdrian Hunter 	return 0;
3177c840cbfeSAdrian Hunter }
3178c840cbfeSAdrian Hunter 
intel_pt_psb_with_fup(struct intel_pt_decoder * decoder,int * err)3179c840cbfeSAdrian Hunter static bool intel_pt_psb_with_fup(struct intel_pt_decoder *decoder, int *err)
3180c840cbfeSAdrian Hunter {
3181c840cbfeSAdrian Hunter 	struct intel_pt_psb_info data = { .fup = false };
3182c840cbfeSAdrian Hunter 
3183057ae59fSAdrian Hunter 	if (!decoder->branch_enable)
3184c840cbfeSAdrian Hunter 		return false;
3185c840cbfeSAdrian Hunter 
3186c840cbfeSAdrian Hunter 	intel_pt_pkt_lookahead(decoder, intel_pt_psb_lookahead_cb, &data);
3187c840cbfeSAdrian Hunter 	if (!data.fup)
3188c840cbfeSAdrian Hunter 		return false;
3189c840cbfeSAdrian Hunter 
3190c840cbfeSAdrian Hunter 	decoder->packet = data.fup_packet;
3191c840cbfeSAdrian Hunter 	intel_pt_set_last_ip(decoder);
3192c840cbfeSAdrian Hunter 	decoder->pkt_state = INTEL_PT_STATE_FUP_IN_PSB;
3193c840cbfeSAdrian Hunter 
3194c840cbfeSAdrian Hunter 	*err = intel_pt_fup_in_psb(decoder);
3195c840cbfeSAdrian Hunter 
3196c840cbfeSAdrian Hunter 	return true;
3197c840cbfeSAdrian Hunter }
3198c840cbfeSAdrian Hunter 
intel_pt_walk_trace(struct intel_pt_decoder * decoder)3199f4aa0819SAdrian Hunter static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
3200f4aa0819SAdrian Hunter {
32016af4b600SAdrian Hunter 	int last_packet_type = INTEL_PT_PAD;
3202f4aa0819SAdrian Hunter 	bool no_tip = false;
3203f4aa0819SAdrian Hunter 	int err;
3204f4aa0819SAdrian Hunter 
3205f4aa0819SAdrian Hunter 	while (1) {
3206f4aa0819SAdrian Hunter 		err = intel_pt_get_next_packet(decoder);
3207f4aa0819SAdrian Hunter 		if (err)
3208f4aa0819SAdrian Hunter 			return err;
3209f4aa0819SAdrian Hunter next:
3210a32e6c5dSAdrian Hunter 		err = 0;
32116af4b600SAdrian Hunter 		if (decoder->cyc_threshold) {
32126af4b600SAdrian Hunter 			if (decoder->sample_cyc && last_packet_type != INTEL_PT_CYC)
32136af4b600SAdrian Hunter 				decoder->sample_cyc = false;
32146af4b600SAdrian Hunter 			last_packet_type = decoder->packet.type;
32156af4b600SAdrian Hunter 		}
32166af4b600SAdrian Hunter 
32177c1b16baSAdrian Hunter 		if (decoder->hop) {
32187c1b16baSAdrian Hunter 			switch (intel_pt_hop_trace(decoder, &no_tip, &err)) {
32197c1b16baSAdrian Hunter 			case HOP_IGNORE:
32207c1b16baSAdrian Hunter 				continue;
32217c1b16baSAdrian Hunter 			case HOP_RETURN:
32227c1b16baSAdrian Hunter 				return err;
32237c1b16baSAdrian Hunter 			case HOP_AGAIN:
32247c1b16baSAdrian Hunter 				goto next;
32257c1b16baSAdrian Hunter 			default:
32267c1b16baSAdrian Hunter 				break;
32277c1b16baSAdrian Hunter 			}
32287c1b16baSAdrian Hunter 		}
32297c1b16baSAdrian Hunter 
3230f4aa0819SAdrian Hunter 		switch (decoder->packet.type) {
3231f4aa0819SAdrian Hunter 		case INTEL_PT_TNT:
3232f4aa0819SAdrian Hunter 			if (!decoder->packet.count)
3233f4aa0819SAdrian Hunter 				break;
3234f4aa0819SAdrian Hunter 			decoder->tnt = decoder->packet;
3235f4aa0819SAdrian Hunter 			decoder->pkt_state = INTEL_PT_STATE_TNT;
3236f4aa0819SAdrian Hunter 			err = intel_pt_walk_tnt(decoder);
3237f4aa0819SAdrian Hunter 			if (err == -EAGAIN)
3238f4aa0819SAdrian Hunter 				break;
3239f4aa0819SAdrian Hunter 			return err;
3240f4aa0819SAdrian Hunter 
3241f4aa0819SAdrian Hunter 		case INTEL_PT_TIP_PGD:
3242f4aa0819SAdrian Hunter 			if (decoder->packet.count != 0)
3243f4aa0819SAdrian Hunter 				intel_pt_set_last_ip(decoder);
3244f4aa0819SAdrian Hunter 			decoder->pkt_state = INTEL_PT_STATE_TIP_PGD;
3245f4aa0819SAdrian Hunter 			return intel_pt_walk_tip(decoder);
3246f4aa0819SAdrian Hunter 
3247f4aa0819SAdrian Hunter 		case INTEL_PT_TIP_PGE: {
3248f4aa0819SAdrian Hunter 			decoder->pge = true;
3249c79ee2b2SAdrian Hunter 			decoder->overflow = false;
32503f055167SAdrian Hunter 			intel_pt_mtc_cyc_cnt_pge(decoder);
325180a03886SAdrian Hunter 			intel_pt_set_nr(decoder);
3252f4aa0819SAdrian Hunter 			if (decoder->packet.count == 0) {
3253f4aa0819SAdrian Hunter 				intel_pt_log_at("Skipping zero TIP.PGE",
3254f4aa0819SAdrian Hunter 						decoder->pos);
3255f4aa0819SAdrian Hunter 				break;
3256f4aa0819SAdrian Hunter 			}
3257cf0c98e2SAdrian Hunter 			intel_pt_sample_iflag_chg(decoder);
3258f4aa0819SAdrian Hunter 			intel_pt_set_ip(decoder);
3259f4aa0819SAdrian Hunter 			decoder->state.from_ip = 0;
3260f4aa0819SAdrian Hunter 			decoder->state.to_ip = decoder->ip;
3261bea63857SAdrian Hunter 			decoder->state.type |= INTEL_PT_TRACE_BEGIN;
32627c1b16baSAdrian Hunter 			/*
32637c1b16baSAdrian Hunter 			 * In hop mode, resample to get the to_ip as an
32647c1b16baSAdrian Hunter 			 * "instruction" sample.
32657c1b16baSAdrian Hunter 			 */
32667c1b16baSAdrian Hunter 			if (decoder->hop)
32677c1b16baSAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
3268f4aa0819SAdrian Hunter 			return 0;
3269f4aa0819SAdrian Hunter 		}
3270f4aa0819SAdrian Hunter 
3271f4aa0819SAdrian Hunter 		case INTEL_PT_OVF:
3272f4aa0819SAdrian Hunter 			return intel_pt_overflow(decoder);
3273f4aa0819SAdrian Hunter 
3274f4aa0819SAdrian Hunter 		case INTEL_PT_TIP:
3275f4aa0819SAdrian Hunter 			if (decoder->packet.count != 0)
3276f4aa0819SAdrian Hunter 				intel_pt_set_last_ip(decoder);
3277f4aa0819SAdrian Hunter 			decoder->pkt_state = INTEL_PT_STATE_TIP;
3278f4aa0819SAdrian Hunter 			return intel_pt_walk_tip(decoder);
3279f4aa0819SAdrian Hunter 
3280f4aa0819SAdrian Hunter 		case INTEL_PT_FUP:
3281f4aa0819SAdrian Hunter 			if (decoder->packet.count == 0) {
3282f4aa0819SAdrian Hunter 				intel_pt_log_at("Skipping zero FUP",
3283f4aa0819SAdrian Hunter 						decoder->pos);
3284f4aa0819SAdrian Hunter 				no_tip = false;
3285f4aa0819SAdrian Hunter 				break;
3286f4aa0819SAdrian Hunter 			}
3287f4aa0819SAdrian Hunter 			intel_pt_set_last_ip(decoder);
3288057ae59fSAdrian Hunter 			if (!decoder->branch_enable || !decoder->pge) {
328983959817SAdrian Hunter 				decoder->ip = decoder->last_ip;
3290cf0c98e2SAdrian Hunter 				if (intel_pt_fup_event(decoder, no_tip))
3291a472e65fSAdrian Hunter 					return 0;
3292a472e65fSAdrian Hunter 				no_tip = false;
329383959817SAdrian Hunter 				break;
329483959817SAdrian Hunter 			}
3295a472e65fSAdrian Hunter 			if (decoder->set_fup_mwait)
3296a472e65fSAdrian Hunter 				no_tip = true;
3297f4aa0819SAdrian Hunter 			if (no_tip)
3298401136bbSAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_FUP_NO_TIP;
3299f4aa0819SAdrian Hunter 			else
3300f4aa0819SAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_FUP;
3301401136bbSAdrian Hunter 			err = intel_pt_walk_fup(decoder);
3302401136bbSAdrian Hunter 			if (err != -EAGAIN)
3303401136bbSAdrian Hunter 				return err;
3304f4aa0819SAdrian Hunter 			if (no_tip) {
3305f4aa0819SAdrian Hunter 				no_tip = false;
3306f4aa0819SAdrian Hunter 				break;
3307f4aa0819SAdrian Hunter 			}
3308f4aa0819SAdrian Hunter 			return intel_pt_walk_fup_tip(decoder);
3309f4aa0819SAdrian Hunter 
33103d498078SAdrian Hunter 		case INTEL_PT_TRACESTOP:
33117eacca3eSAdrian Hunter 			decoder->pge = false;
33127eacca3eSAdrian Hunter 			decoder->continuous_period = false;
33137eacca3eSAdrian Hunter 			intel_pt_clear_tx_flags(decoder);
33147eacca3eSAdrian Hunter 			decoder->have_tma = false;
33153d498078SAdrian Hunter 			break;
33163d498078SAdrian Hunter 
3317f4aa0819SAdrian Hunter 		case INTEL_PT_PSB:
3318c840cbfeSAdrian Hunter 			decoder->state.psb_offset = decoder->pos;
3319c840cbfeSAdrian Hunter 			decoder->psb_ip = 0;
3320c840cbfeSAdrian Hunter 			if (intel_pt_psb_with_fup(decoder, &err))
3321c840cbfeSAdrian Hunter 				return err;
3322c840cbfeSAdrian Hunter 			err = intel_pt_psb(decoder);
3323f4aa0819SAdrian Hunter 			if (err == -EAGAIN)
3324f4aa0819SAdrian Hunter 				goto next;
3325f4aa0819SAdrian Hunter 			return err;
3326f4aa0819SAdrian Hunter 
3327f4aa0819SAdrian Hunter 		case INTEL_PT_PIP:
332880a03886SAdrian Hunter 			intel_pt_update_pip(decoder);
33293d498078SAdrian Hunter 			break;
33303d498078SAdrian Hunter 
33313d498078SAdrian Hunter 		case INTEL_PT_MTC:
333279b58424SAdrian Hunter 			intel_pt_calc_mtc_timestamp(decoder);
333379b58424SAdrian Hunter 			if (decoder->period_type != INTEL_PT_PERIOD_MTC)
3334f4aa0819SAdrian Hunter 				break;
333579b58424SAdrian Hunter 			/*
333679b58424SAdrian Hunter 			 * Ensure that there has been an instruction since the
333779b58424SAdrian Hunter 			 * last MTC.
333879b58424SAdrian Hunter 			 */
333979b58424SAdrian Hunter 			if (!decoder->mtc_insn)
334079b58424SAdrian Hunter 				break;
334179b58424SAdrian Hunter 			decoder->mtc_insn = false;
334279b58424SAdrian Hunter 			/* Ensure that there is a timestamp */
334379b58424SAdrian Hunter 			if (!decoder->timestamp)
334479b58424SAdrian Hunter 				break;
334579b58424SAdrian Hunter 			decoder->state.type = INTEL_PT_INSTRUCTION;
334679b58424SAdrian Hunter 			decoder->state.from_ip = decoder->ip;
334779b58424SAdrian Hunter 			decoder->state.to_ip = 0;
334879b58424SAdrian Hunter 			decoder->mtc_insn = false;
334979b58424SAdrian Hunter 			return 0;
3350f4aa0819SAdrian Hunter 
3351f4aa0819SAdrian Hunter 		case INTEL_PT_TSC:
3352f4aa0819SAdrian Hunter 			intel_pt_calc_tsc_timestamp(decoder);
3353f4aa0819SAdrian Hunter 			break;
3354f4aa0819SAdrian Hunter 
33553d498078SAdrian Hunter 		case INTEL_PT_TMA:
335679b58424SAdrian Hunter 			intel_pt_calc_tma(decoder);
33573d498078SAdrian Hunter 			break;
33583d498078SAdrian Hunter 
33593d498078SAdrian Hunter 		case INTEL_PT_CYC:
3360cc336186SAdrian Hunter 			intel_pt_calc_cyc_timestamp(decoder);
33613d498078SAdrian Hunter 			break;
33623d498078SAdrian Hunter 
3363f4aa0819SAdrian Hunter 		case INTEL_PT_CBR:
3364cc336186SAdrian Hunter 			intel_pt_calc_cbr(decoder);
3365a58a057cSAdrian Hunter 			if (decoder->cbr != decoder->cbr_seen) {
3366a58a057cSAdrian Hunter 				decoder->state.type = 0;
33670a7c700dSAdrian Hunter 				return 0;
3368a58a057cSAdrian Hunter 			}
3369f4aa0819SAdrian Hunter 			break;
3370f4aa0819SAdrian Hunter 
3371f4aa0819SAdrian Hunter 		case INTEL_PT_MODE_EXEC:
3372cf0c98e2SAdrian Hunter 			intel_pt_mode_exec(decoder);
3373cf0c98e2SAdrian Hunter 			err = intel_pt_get_next_packet(decoder);
3374cf0c98e2SAdrian Hunter 			if (err)
3375cf0c98e2SAdrian Hunter 				return err;
3376cf0c98e2SAdrian Hunter 			if (decoder->packet.type == INTEL_PT_FUP) {
3377cf0c98e2SAdrian Hunter 				decoder->set_fup_mode_exec = true;
3378cf0c98e2SAdrian Hunter 				no_tip = true;
3379cf0c98e2SAdrian Hunter 			}
3380cf0c98e2SAdrian Hunter 			goto next;
3381f4aa0819SAdrian Hunter 
3382f4aa0819SAdrian Hunter 		case INTEL_PT_MODE_TSX:
3383f4aa0819SAdrian Hunter 			/* MODE_TSX need not be followed by FUP */
33847c1b16baSAdrian Hunter 			if (!decoder->pge || decoder->in_psb) {
3385f4aa0819SAdrian Hunter 				intel_pt_update_in_tx(decoder);
3386f4aa0819SAdrian Hunter 				break;
3387f4aa0819SAdrian Hunter 			}
3388f4aa0819SAdrian Hunter 			err = intel_pt_mode_tsx(decoder, &no_tip);
3389f4aa0819SAdrian Hunter 			if (err)
3390f4aa0819SAdrian Hunter 				return err;
3391f4aa0819SAdrian Hunter 			goto next;
3392f4aa0819SAdrian Hunter 
3393f4aa0819SAdrian Hunter 		case INTEL_PT_BAD: /* Does not happen */
3394f4aa0819SAdrian Hunter 			return intel_pt_bug(decoder);
3395f4aa0819SAdrian Hunter 
3396f4aa0819SAdrian Hunter 		case INTEL_PT_PSBEND:
33973d498078SAdrian Hunter 		case INTEL_PT_VMCS:
33983d498078SAdrian Hunter 		case INTEL_PT_MNT:
3399f4aa0819SAdrian Hunter 		case INTEL_PT_PAD:
3400f4aa0819SAdrian Hunter 			break;
3401f4aa0819SAdrian Hunter 
3402a472e65fSAdrian Hunter 		case INTEL_PT_PTWRITE_IP:
3403a472e65fSAdrian Hunter 			decoder->fup_ptw_payload = decoder->packet.payload;
3404a472e65fSAdrian Hunter 			err = intel_pt_get_next_packet(decoder);
3405a472e65fSAdrian Hunter 			if (err)
3406a472e65fSAdrian Hunter 				return err;
3407a472e65fSAdrian Hunter 			if (decoder->packet.type == INTEL_PT_FUP) {
3408a472e65fSAdrian Hunter 				decoder->set_fup_ptw = true;
3409a472e65fSAdrian Hunter 				no_tip = true;
3410a472e65fSAdrian Hunter 			} else {
3411a472e65fSAdrian Hunter 				intel_pt_log_at("ERROR: Missing FUP after PTWRITE",
3412a472e65fSAdrian Hunter 						decoder->pos);
3413a472e65fSAdrian Hunter 			}
3414a472e65fSAdrian Hunter 			goto next;
3415a472e65fSAdrian Hunter 
3416a472e65fSAdrian Hunter 		case INTEL_PT_PTWRITE:
3417a472e65fSAdrian Hunter 			decoder->state.type = INTEL_PT_PTW;
3418a472e65fSAdrian Hunter 			decoder->state.from_ip = decoder->ip;
3419a472e65fSAdrian Hunter 			decoder->state.to_ip = 0;
3420a472e65fSAdrian Hunter 			decoder->state.ptw_payload = decoder->packet.payload;
3421a472e65fSAdrian Hunter 			return 0;
3422a472e65fSAdrian Hunter 
3423a472e65fSAdrian Hunter 		case INTEL_PT_MWAIT:
3424a472e65fSAdrian Hunter 			decoder->fup_mwait_payload = decoder->packet.payload;
3425a472e65fSAdrian Hunter 			decoder->set_fup_mwait = true;
3426a472e65fSAdrian Hunter 			break;
3427a472e65fSAdrian Hunter 
3428a472e65fSAdrian Hunter 		case INTEL_PT_PWRE:
3429a472e65fSAdrian Hunter 			if (decoder->set_fup_mwait) {
3430a472e65fSAdrian Hunter 				decoder->fup_pwre_payload =
3431a472e65fSAdrian Hunter 							decoder->packet.payload;
3432a472e65fSAdrian Hunter 				decoder->set_fup_pwre = true;
3433a472e65fSAdrian Hunter 				break;
3434a472e65fSAdrian Hunter 			}
3435a472e65fSAdrian Hunter 			decoder->state.type = INTEL_PT_PWR_ENTRY;
3436a472e65fSAdrian Hunter 			decoder->state.from_ip = decoder->ip;
3437a472e65fSAdrian Hunter 			decoder->state.to_ip = 0;
3438a472e65fSAdrian Hunter 			decoder->state.pwrx_payload = decoder->packet.payload;
3439a472e65fSAdrian Hunter 			return 0;
3440a472e65fSAdrian Hunter 
3441a472e65fSAdrian Hunter 		case INTEL_PT_EXSTOP_IP:
3442a472e65fSAdrian Hunter 			err = intel_pt_get_next_packet(decoder);
3443a472e65fSAdrian Hunter 			if (err)
3444a472e65fSAdrian Hunter 				return err;
3445a472e65fSAdrian Hunter 			if (decoder->packet.type == INTEL_PT_FUP) {
3446a472e65fSAdrian Hunter 				decoder->set_fup_exstop = true;
3447a472e65fSAdrian Hunter 				no_tip = true;
3448a472e65fSAdrian Hunter 			} else {
3449a472e65fSAdrian Hunter 				intel_pt_log_at("ERROR: Missing FUP after EXSTOP",
3450a472e65fSAdrian Hunter 						decoder->pos);
3451a472e65fSAdrian Hunter 			}
3452a472e65fSAdrian Hunter 			goto next;
3453a472e65fSAdrian Hunter 
3454a472e65fSAdrian Hunter 		case INTEL_PT_EXSTOP:
3455a472e65fSAdrian Hunter 			decoder->state.type = INTEL_PT_EX_STOP;
3456a472e65fSAdrian Hunter 			decoder->state.from_ip = decoder->ip;
3457a472e65fSAdrian Hunter 			decoder->state.to_ip = 0;
3458a472e65fSAdrian Hunter 			return 0;
3459a472e65fSAdrian Hunter 
3460a472e65fSAdrian Hunter 		case INTEL_PT_PWRX:
3461a472e65fSAdrian Hunter 			decoder->state.type = INTEL_PT_PWR_EXIT;
3462a472e65fSAdrian Hunter 			decoder->state.from_ip = decoder->ip;
3463a472e65fSAdrian Hunter 			decoder->state.to_ip = 0;
3464a472e65fSAdrian Hunter 			decoder->state.pwrx_payload = decoder->packet.payload;
3465a472e65fSAdrian Hunter 			return 0;
3466a472e65fSAdrian Hunter 
3467edff7809SAdrian Hunter 		case INTEL_PT_BBP:
34684c35595eSAdrian Hunter 			intel_pt_bbp(decoder);
3469edff7809SAdrian Hunter 			break;
3470edff7809SAdrian Hunter 
34714c35595eSAdrian Hunter 		case INTEL_PT_BIP:
34724c35595eSAdrian Hunter 			intel_pt_bip(decoder);
34734c35595eSAdrian Hunter 			break;
34744c35595eSAdrian Hunter 
34754c35595eSAdrian Hunter 		case INTEL_PT_BEP:
34764c35595eSAdrian Hunter 			decoder->state.type = INTEL_PT_BLK_ITEMS;
34774c35595eSAdrian Hunter 			decoder->state.from_ip = decoder->ip;
34784c35595eSAdrian Hunter 			decoder->state.to_ip = 0;
34794c35595eSAdrian Hunter 			return 0;
34804c35595eSAdrian Hunter 
34814c35595eSAdrian Hunter 		case INTEL_PT_BEP_IP:
34824c35595eSAdrian Hunter 			err = intel_pt_get_next_packet(decoder);
34834c35595eSAdrian Hunter 			if (err)
34844c35595eSAdrian Hunter 				return err;
34854c35595eSAdrian Hunter 			if (decoder->packet.type == INTEL_PT_FUP) {
34864c35595eSAdrian Hunter 				decoder->set_fup_bep = true;
34874c35595eSAdrian Hunter 				no_tip = true;
34884c35595eSAdrian Hunter 			} else {
34894c35595eSAdrian Hunter 				intel_pt_log_at("ERROR: Missing FUP after BEP",
34904c35595eSAdrian Hunter 						decoder->pos);
34914c35595eSAdrian Hunter 			}
34924c35595eSAdrian Hunter 			goto next;
34934c35595eSAdrian Hunter 
34942750af50SAdrian Hunter 		case INTEL_PT_CFE:
34953733a98bSAdrian Hunter 			decoder->fup_cfe_pkt = decoder->packet;
34963733a98bSAdrian Hunter 			decoder->set_fup_cfe = true;
34973733a98bSAdrian Hunter 			if (!decoder->pge) {
3498cf0c98e2SAdrian Hunter 				intel_pt_fup_event(decoder, true);
34993733a98bSAdrian Hunter 				return 0;
35003733a98bSAdrian Hunter 			}
35013733a98bSAdrian Hunter 			break;
35023733a98bSAdrian Hunter 
35032750af50SAdrian Hunter 		case INTEL_PT_CFE_IP:
35043733a98bSAdrian Hunter 			decoder->fup_cfe_pkt = decoder->packet;
35053733a98bSAdrian Hunter 			err = intel_pt_get_next_packet(decoder);
35063733a98bSAdrian Hunter 			if (err)
35073733a98bSAdrian Hunter 				return err;
35083733a98bSAdrian Hunter 			if (decoder->packet.type == INTEL_PT_FUP) {
35093733a98bSAdrian Hunter 				decoder->set_fup_cfe_ip = true;
35103733a98bSAdrian Hunter 				no_tip = true;
35113733a98bSAdrian Hunter 			} else {
35123733a98bSAdrian Hunter 				intel_pt_log_at("ERROR: Missing FUP after CFE",
35133733a98bSAdrian Hunter 						decoder->pos);
35143733a98bSAdrian Hunter 			}
35153733a98bSAdrian Hunter 			goto next;
35163733a98bSAdrian Hunter 
35172750af50SAdrian Hunter 		case INTEL_PT_EVD:
35183733a98bSAdrian Hunter 			err = intel_pt_evd(decoder);
35193733a98bSAdrian Hunter 			if (err)
35203733a98bSAdrian Hunter 				return err;
35212750af50SAdrian Hunter 			break;
35222750af50SAdrian Hunter 
3523f4aa0819SAdrian Hunter 		default:
3524f4aa0819SAdrian Hunter 			return intel_pt_bug(decoder);
3525f4aa0819SAdrian Hunter 		}
3526f4aa0819SAdrian Hunter 	}
3527f4aa0819SAdrian Hunter }
3528f4aa0819SAdrian Hunter 
intel_pt_have_ip(struct intel_pt_decoder * decoder)3529e1717e04SAdrian Hunter static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder)
3530e1717e04SAdrian Hunter {
3531f952eaceSAdrian Hunter 	return decoder->packet.count &&
3532f952eaceSAdrian Hunter 	       (decoder->have_last_ip || decoder->packet.count == 3 ||
3533f952eaceSAdrian Hunter 		decoder->packet.count == 6);
3534e1717e04SAdrian Hunter }
3535e1717e04SAdrian Hunter 
3536f4aa0819SAdrian Hunter /* Walk PSB+ packets to get in sync. */
intel_pt_walk_psb(struct intel_pt_decoder * decoder)3537f4aa0819SAdrian Hunter static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
3538f4aa0819SAdrian Hunter {
3539f4aa0819SAdrian Hunter 	int err;
3540f4aa0819SAdrian Hunter 
35419bc668e3SAdrian Hunter 	decoder->in_psb = true;
35429bc668e3SAdrian Hunter 
3543f4aa0819SAdrian Hunter 	while (1) {
3544f4aa0819SAdrian Hunter 		err = intel_pt_get_next_packet(decoder);
3545f4aa0819SAdrian Hunter 		if (err)
35469bc668e3SAdrian Hunter 			goto out;
3547f4aa0819SAdrian Hunter 
3548f4aa0819SAdrian Hunter 		switch (decoder->packet.type) {
3549f4aa0819SAdrian Hunter 		case INTEL_PT_TIP_PGD:
3550f4aa0819SAdrian Hunter 			decoder->continuous_period = false;
3551f7a858bfSLiam Howlett 			fallthrough;
3552f4aa0819SAdrian Hunter 		case INTEL_PT_TIP_PGE:
3553f4aa0819SAdrian Hunter 		case INTEL_PT_TIP:
3554a472e65fSAdrian Hunter 		case INTEL_PT_PTWRITE:
3555a472e65fSAdrian Hunter 		case INTEL_PT_PTWRITE_IP:
3556a472e65fSAdrian Hunter 		case INTEL_PT_EXSTOP:
3557a472e65fSAdrian Hunter 		case INTEL_PT_EXSTOP_IP:
3558a472e65fSAdrian Hunter 		case INTEL_PT_MWAIT:
3559a472e65fSAdrian Hunter 		case INTEL_PT_PWRE:
3560a472e65fSAdrian Hunter 		case INTEL_PT_PWRX:
3561edff7809SAdrian Hunter 		case INTEL_PT_BBP:
3562edff7809SAdrian Hunter 		case INTEL_PT_BIP:
3563edff7809SAdrian Hunter 		case INTEL_PT_BEP:
3564edff7809SAdrian Hunter 		case INTEL_PT_BEP_IP:
35652750af50SAdrian Hunter 		case INTEL_PT_CFE:
35662750af50SAdrian Hunter 		case INTEL_PT_CFE_IP:
35672750af50SAdrian Hunter 		case INTEL_PT_EVD:
3568f4aa0819SAdrian Hunter 			intel_pt_log("ERROR: Unexpected packet\n");
35699bc668e3SAdrian Hunter 			err = -ENOENT;
35709bc668e3SAdrian Hunter 			goto out;
3571f4aa0819SAdrian Hunter 
3572f4aa0819SAdrian Hunter 		case INTEL_PT_FUP:
3573f4aa0819SAdrian Hunter 			decoder->pge = true;
3574e1717e04SAdrian Hunter 			if (intel_pt_have_ip(decoder)) {
3575f4aa0819SAdrian Hunter 				uint64_t current_ip = decoder->ip;
3576f4aa0819SAdrian Hunter 
3577f4aa0819SAdrian Hunter 				intel_pt_set_ip(decoder);
3578c840cbfeSAdrian Hunter 				decoder->psb_ip = decoder->ip;
3579f4aa0819SAdrian Hunter 				if (current_ip)
3580f4aa0819SAdrian Hunter 					intel_pt_log_to("Setting IP",
3581f4aa0819SAdrian Hunter 							decoder->ip);
3582f4aa0819SAdrian Hunter 			}
3583f4aa0819SAdrian Hunter 			break;
3584f4aa0819SAdrian Hunter 
35853d498078SAdrian Hunter 		case INTEL_PT_MTC:
358679b58424SAdrian Hunter 			intel_pt_calc_mtc_timestamp(decoder);
35873d498078SAdrian Hunter 			break;
35883d498078SAdrian Hunter 
3589f4aa0819SAdrian Hunter 		case INTEL_PT_TSC:
3590f4aa0819SAdrian Hunter 			intel_pt_calc_tsc_timestamp(decoder);
3591f4aa0819SAdrian Hunter 			break;
3592f4aa0819SAdrian Hunter 
35933d498078SAdrian Hunter 		case INTEL_PT_TMA:
359479b58424SAdrian Hunter 			intel_pt_calc_tma(decoder);
35953d498078SAdrian Hunter 			break;
35963d498078SAdrian Hunter 
35973d498078SAdrian Hunter 		case INTEL_PT_CYC:
3598cc336186SAdrian Hunter 			intel_pt_calc_cyc_timestamp(decoder);
35993d498078SAdrian Hunter 			break;
36003d498078SAdrian Hunter 
3601f4aa0819SAdrian Hunter 		case INTEL_PT_CBR:
3602cc336186SAdrian Hunter 			intel_pt_calc_cbr(decoder);
3603f4aa0819SAdrian Hunter 			break;
3604f4aa0819SAdrian Hunter 
3605f4aa0819SAdrian Hunter 		case INTEL_PT_PIP:
360680a03886SAdrian Hunter 			intel_pt_set_pip(decoder);
3607f4aa0819SAdrian Hunter 			break;
3608f4aa0819SAdrian Hunter 
3609f4aa0819SAdrian Hunter 		case INTEL_PT_MODE_EXEC:
3610cf0c98e2SAdrian Hunter 			intel_pt_mode_exec_status(decoder);
3611f4aa0819SAdrian Hunter 			break;
3612f4aa0819SAdrian Hunter 
3613f4aa0819SAdrian Hunter 		case INTEL_PT_MODE_TSX:
3614f4aa0819SAdrian Hunter 			intel_pt_update_in_tx(decoder);
3615f4aa0819SAdrian Hunter 			break;
3616f4aa0819SAdrian Hunter 
36173d498078SAdrian Hunter 		case INTEL_PT_TRACESTOP:
36187eacca3eSAdrian Hunter 			decoder->pge = false;
36197eacca3eSAdrian Hunter 			decoder->continuous_period = false;
36207eacca3eSAdrian Hunter 			intel_pt_clear_tx_flags(decoder);
3621f7a858bfSLiam Howlett 			fallthrough;
36227ea6856dSArnaldo Carvalho de Melo 
3623f4aa0819SAdrian Hunter 		case INTEL_PT_TNT:
362479b58424SAdrian Hunter 			decoder->have_tma = false;
3625f4aa0819SAdrian Hunter 			intel_pt_log("ERROR: Unexpected packet\n");
3626f4aa0819SAdrian Hunter 			if (decoder->ip)
3627f4aa0819SAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_ERR4;
3628f4aa0819SAdrian Hunter 			else
3629f4aa0819SAdrian Hunter 				decoder->pkt_state = INTEL_PT_STATE_ERR3;
36309bc668e3SAdrian Hunter 			err = -ENOENT;
36319bc668e3SAdrian Hunter 			goto out;
3632f4aa0819SAdrian Hunter 
3633f4aa0819SAdrian Hunter 		case INTEL_PT_BAD: /* Does not happen */
36349bc668e3SAdrian Hunter 			err = intel_pt_bug(decoder);
36359bc668e3SAdrian Hunter 			goto out;
3636f4aa0819SAdrian Hunter 
3637f4aa0819SAdrian Hunter 		case INTEL_PT_OVF:
36389bc668e3SAdrian Hunter 			err = intel_pt_overflow(decoder);
36399bc668e3SAdrian Hunter 			goto out;
3640f4aa0819SAdrian Hunter 
3641f4aa0819SAdrian Hunter 		case INTEL_PT_PSBEND:
36429bc668e3SAdrian Hunter 			err = 0;
36439bc668e3SAdrian Hunter 			goto out;
3644f4aa0819SAdrian Hunter 
3645f4aa0819SAdrian Hunter 		case INTEL_PT_PSB:
36463d498078SAdrian Hunter 		case INTEL_PT_VMCS:
36473d498078SAdrian Hunter 		case INTEL_PT_MNT:
3648f4aa0819SAdrian Hunter 		case INTEL_PT_PAD:
3649f4aa0819SAdrian Hunter 		default:
3650f4aa0819SAdrian Hunter 			break;
3651f4aa0819SAdrian Hunter 		}
3652f4aa0819SAdrian Hunter 	}
36539bc668e3SAdrian Hunter out:
36549bc668e3SAdrian Hunter 	decoder->in_psb = false;
36559bc668e3SAdrian Hunter 
36569bc668e3SAdrian Hunter 	return err;
3657f4aa0819SAdrian Hunter }
3658f4aa0819SAdrian Hunter 
intel_pt_walk_to_ip(struct intel_pt_decoder * decoder)3659f4aa0819SAdrian Hunter static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
3660f4aa0819SAdrian Hunter {
3661f4aa0819SAdrian Hunter 	int err;
3662f4aa0819SAdrian Hunter 
3663f4aa0819SAdrian Hunter 	while (1) {
3664f4aa0819SAdrian Hunter 		err = intel_pt_get_next_packet(decoder);
3665f4aa0819SAdrian Hunter 		if (err)
3666f4aa0819SAdrian Hunter 			return err;
3667f4aa0819SAdrian Hunter 
3668f4aa0819SAdrian Hunter 		switch (decoder->packet.type) {
3669f4aa0819SAdrian Hunter 		case INTEL_PT_TIP_PGD:
3670f4aa0819SAdrian Hunter 			decoder->continuous_period = false;
3671f3c98c4bSAdrian Hunter 			decoder->pge = false;
3672e1717e04SAdrian Hunter 			if (intel_pt_have_ip(decoder))
3673f4aa0819SAdrian Hunter 				intel_pt_set_ip(decoder);
3674bea63857SAdrian Hunter 			if (!decoder->ip)
3675f4aa0819SAdrian Hunter 				break;
3676bea63857SAdrian Hunter 			decoder->state.type |= INTEL_PT_TRACE_END;
3677bea63857SAdrian Hunter 			return 0;
3678f4aa0819SAdrian Hunter 
3679f3c98c4bSAdrian Hunter 		case INTEL_PT_TIP_PGE:
3680f3c98c4bSAdrian Hunter 			decoder->pge = true;
36813f055167SAdrian Hunter 			intel_pt_mtc_cyc_cnt_pge(decoder);
3682f3c98c4bSAdrian Hunter 			if (intel_pt_have_ip(decoder))
3683f3c98c4bSAdrian Hunter 				intel_pt_set_ip(decoder);
3684f3c98c4bSAdrian Hunter 			if (!decoder->ip)
3685f3c98c4bSAdrian Hunter 				break;
3686f3c98c4bSAdrian Hunter 			decoder->state.type |= INTEL_PT_TRACE_BEGIN;
3687f3c98c4bSAdrian Hunter 			return 0;
3688f3c98c4bSAdrian Hunter 
3689f3c98c4bSAdrian Hunter 		case INTEL_PT_TIP:
3690f3c98c4bSAdrian Hunter 			decoder->pge = true;
3691f3c98c4bSAdrian Hunter 			if (intel_pt_have_ip(decoder))
3692f3c98c4bSAdrian Hunter 				intel_pt_set_ip(decoder);
3693f3c98c4bSAdrian Hunter 			if (!decoder->ip)
3694f3c98c4bSAdrian Hunter 				break;
3695f3c98c4bSAdrian Hunter 			return 0;
3696f3c98c4bSAdrian Hunter 
3697f4aa0819SAdrian Hunter 		case INTEL_PT_FUP:
3698e1717e04SAdrian Hunter 			if (intel_pt_have_ip(decoder))
3699f4aa0819SAdrian Hunter 				intel_pt_set_ip(decoder);
3700f4aa0819SAdrian Hunter 			if (decoder->ip)
3701f4aa0819SAdrian Hunter 				return 0;
3702f4aa0819SAdrian Hunter 			break;
3703f4aa0819SAdrian Hunter 
37043d498078SAdrian Hunter 		case INTEL_PT_MTC:
370579b58424SAdrian Hunter 			intel_pt_calc_mtc_timestamp(decoder);
37063d498078SAdrian Hunter 			break;
37073d498078SAdrian Hunter 
3708f4aa0819SAdrian Hunter 		case INTEL_PT_TSC:
3709f4aa0819SAdrian Hunter 			intel_pt_calc_tsc_timestamp(decoder);
3710f4aa0819SAdrian Hunter 			break;
3711f4aa0819SAdrian Hunter 
37123d498078SAdrian Hunter 		case INTEL_PT_TMA:
371379b58424SAdrian Hunter 			intel_pt_calc_tma(decoder);
37143d498078SAdrian Hunter 			break;
37153d498078SAdrian Hunter 
37163d498078SAdrian Hunter 		case INTEL_PT_CYC:
3717cc336186SAdrian Hunter 			intel_pt_calc_cyc_timestamp(decoder);
37183d498078SAdrian Hunter 			break;
37193d498078SAdrian Hunter 
3720f4aa0819SAdrian Hunter 		case INTEL_PT_CBR:
3721cc336186SAdrian Hunter 			intel_pt_calc_cbr(decoder);
3722f4aa0819SAdrian Hunter 			break;
3723f4aa0819SAdrian Hunter 
3724f4aa0819SAdrian Hunter 		case INTEL_PT_PIP:
372580a03886SAdrian Hunter 			intel_pt_set_pip(decoder);
3726f4aa0819SAdrian Hunter 			break;
3727f4aa0819SAdrian Hunter 
3728f4aa0819SAdrian Hunter 		case INTEL_PT_MODE_EXEC:
3729cf0c98e2SAdrian Hunter 			intel_pt_mode_exec_status(decoder);
3730f4aa0819SAdrian Hunter 			break;
3731f4aa0819SAdrian Hunter 
3732f4aa0819SAdrian Hunter 		case INTEL_PT_MODE_TSX:
3733f4aa0819SAdrian Hunter 			intel_pt_update_in_tx(decoder);
3734f4aa0819SAdrian Hunter 			break;
3735f4aa0819SAdrian Hunter 
3736f4aa0819SAdrian Hunter 		case INTEL_PT_OVF:
3737f4aa0819SAdrian Hunter 			return intel_pt_overflow(decoder);
3738f4aa0819SAdrian Hunter 
3739f4aa0819SAdrian Hunter 		case INTEL_PT_BAD: /* Does not happen */
3740f4aa0819SAdrian Hunter 			return intel_pt_bug(decoder);
3741f4aa0819SAdrian Hunter 
37423d498078SAdrian Hunter 		case INTEL_PT_TRACESTOP:
37437eacca3eSAdrian Hunter 			decoder->pge = false;
37447eacca3eSAdrian Hunter 			decoder->continuous_period = false;
37457eacca3eSAdrian Hunter 			intel_pt_clear_tx_flags(decoder);
37467eacca3eSAdrian Hunter 			decoder->have_tma = false;
37473d498078SAdrian Hunter 			break;
37483d498078SAdrian Hunter 
3749f4aa0819SAdrian Hunter 		case INTEL_PT_PSB:
3750c840cbfeSAdrian Hunter 			decoder->state.psb_offset = decoder->pos;
3751c840cbfeSAdrian Hunter 			decoder->psb_ip = 0;
3752ee14ac0eSAdrian Hunter 			decoder->last_ip = 0;
3753ee14ac0eSAdrian Hunter 			decoder->have_last_ip = true;
375412b70806SAdrian Hunter 			intel_pt_clear_stack(&decoder->stack);
3755f4aa0819SAdrian Hunter 			err = intel_pt_walk_psb(decoder);
3756f4aa0819SAdrian Hunter 			if (err)
3757f4aa0819SAdrian Hunter 				return err;
3758c840cbfeSAdrian Hunter 			decoder->state.type = INTEL_PT_PSB_EVT;
3759c840cbfeSAdrian Hunter 			decoder->state.from_ip = decoder->psb_ip;
3760c840cbfeSAdrian Hunter 			decoder->state.to_ip = 0;
3761f4aa0819SAdrian Hunter 			return 0;
3762f4aa0819SAdrian Hunter 
3763f4aa0819SAdrian Hunter 		case INTEL_PT_TNT:
3764f4aa0819SAdrian Hunter 		case INTEL_PT_PSBEND:
37653d498078SAdrian Hunter 		case INTEL_PT_VMCS:
37663d498078SAdrian Hunter 		case INTEL_PT_MNT:
3767f4aa0819SAdrian Hunter 		case INTEL_PT_PAD:
3768a472e65fSAdrian Hunter 		case INTEL_PT_PTWRITE:
3769a472e65fSAdrian Hunter 		case INTEL_PT_PTWRITE_IP:
3770a472e65fSAdrian Hunter 		case INTEL_PT_EXSTOP:
3771a472e65fSAdrian Hunter 		case INTEL_PT_EXSTOP_IP:
3772a472e65fSAdrian Hunter 		case INTEL_PT_MWAIT:
3773a472e65fSAdrian Hunter 		case INTEL_PT_PWRE:
3774a472e65fSAdrian Hunter 		case INTEL_PT_PWRX:
3775edff7809SAdrian Hunter 		case INTEL_PT_BBP:
3776edff7809SAdrian Hunter 		case INTEL_PT_BIP:
3777edff7809SAdrian Hunter 		case INTEL_PT_BEP:
3778edff7809SAdrian Hunter 		case INTEL_PT_BEP_IP:
37792750af50SAdrian Hunter 		case INTEL_PT_CFE:
37802750af50SAdrian Hunter 		case INTEL_PT_CFE_IP:
37812750af50SAdrian Hunter 		case INTEL_PT_EVD:
3782f4aa0819SAdrian Hunter 		default:
3783f4aa0819SAdrian Hunter 			break;
3784f4aa0819SAdrian Hunter 		}
3785f4aa0819SAdrian Hunter 	}
3786f4aa0819SAdrian Hunter }
3787f4aa0819SAdrian Hunter 
intel_pt_sync_ip(struct intel_pt_decoder * decoder)3788f4aa0819SAdrian Hunter static int intel_pt_sync_ip(struct intel_pt_decoder *decoder)
3789f4aa0819SAdrian Hunter {
3790f4aa0819SAdrian Hunter 	int err;
3791f4aa0819SAdrian Hunter 
379268ff3cbaSAdrian Hunter 	intel_pt_clear_fup_event(decoder);
3793c79ee2b2SAdrian Hunter 	decoder->overflow = false;
37946a558f12SAdrian Hunter 
379583959817SAdrian Hunter 	if (!decoder->branch_enable) {
379683959817SAdrian Hunter 		decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
379783959817SAdrian Hunter 		decoder->state.type = 0; /* Do not have a sample */
379883959817SAdrian Hunter 		return 0;
379983959817SAdrian Hunter 	}
380083959817SAdrian Hunter 
3801f4aa0819SAdrian Hunter 	intel_pt_log("Scanning for full IP\n");
3802f4aa0819SAdrian Hunter 	err = intel_pt_walk_to_ip(decoder);
3803c840cbfeSAdrian Hunter 	if (err || ((decoder->state.type & INTEL_PT_PSB_EVT) && !decoder->ip))
3804f4aa0819SAdrian Hunter 		return err;
3805f4aa0819SAdrian Hunter 
38067c1b16baSAdrian Hunter 	/* In hop mode, resample to get the to_ip as an "instruction" sample */
38077c1b16baSAdrian Hunter 	if (decoder->hop)
38087c1b16baSAdrian Hunter 		decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
38097c1b16baSAdrian Hunter 	else
3810f4aa0819SAdrian Hunter 		decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
3811f4aa0819SAdrian Hunter 
3812f4aa0819SAdrian Hunter 	decoder->state.from_ip = 0;
3813f4aa0819SAdrian Hunter 	decoder->state.to_ip = decoder->ip;
3814f4aa0819SAdrian Hunter 	intel_pt_log_to("Setting IP", decoder->ip);
3815f4aa0819SAdrian Hunter 
3816f4aa0819SAdrian Hunter 	return 0;
3817f4aa0819SAdrian Hunter }
3818f4aa0819SAdrian Hunter 
intel_pt_part_psb(struct intel_pt_decoder * decoder)3819f4aa0819SAdrian Hunter static int intel_pt_part_psb(struct intel_pt_decoder *decoder)
3820f4aa0819SAdrian Hunter {
3821f4aa0819SAdrian Hunter 	const unsigned char *end = decoder->buf + decoder->len;
3822f4aa0819SAdrian Hunter 	size_t i;
3823f4aa0819SAdrian Hunter 
3824f4aa0819SAdrian Hunter 	for (i = INTEL_PT_PSB_LEN - 1; i; i--) {
3825f4aa0819SAdrian Hunter 		if (i > decoder->len)
3826f4aa0819SAdrian Hunter 			continue;
3827f4aa0819SAdrian Hunter 		if (!memcmp(end - i, INTEL_PT_PSB_STR, i))
3828f4aa0819SAdrian Hunter 			return i;
3829f4aa0819SAdrian Hunter 	}
3830f4aa0819SAdrian Hunter 	return 0;
3831f4aa0819SAdrian Hunter }
3832f4aa0819SAdrian Hunter 
intel_pt_rest_psb(struct intel_pt_decoder * decoder,int part_psb)3833f4aa0819SAdrian Hunter static int intel_pt_rest_psb(struct intel_pt_decoder *decoder, int part_psb)
3834f4aa0819SAdrian Hunter {
3835f4aa0819SAdrian Hunter 	size_t rest_psb = INTEL_PT_PSB_LEN - part_psb;
3836f4aa0819SAdrian Hunter 	const char *psb = INTEL_PT_PSB_STR;
3837f4aa0819SAdrian Hunter 
3838f4aa0819SAdrian Hunter 	if (rest_psb > decoder->len ||
3839f4aa0819SAdrian Hunter 	    memcmp(decoder->buf, psb + part_psb, rest_psb))
3840f4aa0819SAdrian Hunter 		return 0;
3841f4aa0819SAdrian Hunter 
3842f4aa0819SAdrian Hunter 	return rest_psb;
3843f4aa0819SAdrian Hunter }
3844f4aa0819SAdrian Hunter 
intel_pt_get_split_psb(struct intel_pt_decoder * decoder,int part_psb)3845f4aa0819SAdrian Hunter static int intel_pt_get_split_psb(struct intel_pt_decoder *decoder,
3846f4aa0819SAdrian Hunter 				  int part_psb)
3847f4aa0819SAdrian Hunter {
3848f4aa0819SAdrian Hunter 	int rest_psb, ret;
3849f4aa0819SAdrian Hunter 
3850f4aa0819SAdrian Hunter 	decoder->pos += decoder->len;
3851f4aa0819SAdrian Hunter 	decoder->len = 0;
3852f4aa0819SAdrian Hunter 
38536c1f0b18SAdrian Hunter 	ret = intel_pt_get_next_data(decoder, false);
3854f4aa0819SAdrian Hunter 	if (ret)
3855f4aa0819SAdrian Hunter 		return ret;
3856f4aa0819SAdrian Hunter 
3857f4aa0819SAdrian Hunter 	rest_psb = intel_pt_rest_psb(decoder, part_psb);
3858f4aa0819SAdrian Hunter 	if (!rest_psb)
3859f4aa0819SAdrian Hunter 		return 0;
3860f4aa0819SAdrian Hunter 
3861f4aa0819SAdrian Hunter 	decoder->pos -= part_psb;
3862f4aa0819SAdrian Hunter 	decoder->next_buf = decoder->buf + rest_psb;
3863f4aa0819SAdrian Hunter 	decoder->next_len = decoder->len - rest_psb;
3864f4aa0819SAdrian Hunter 	memcpy(decoder->temp_buf, INTEL_PT_PSB_STR, INTEL_PT_PSB_LEN);
3865f4aa0819SAdrian Hunter 	decoder->buf = decoder->temp_buf;
3866f4aa0819SAdrian Hunter 	decoder->len = INTEL_PT_PSB_LEN;
3867f4aa0819SAdrian Hunter 
3868f4aa0819SAdrian Hunter 	return 0;
3869f4aa0819SAdrian Hunter }
3870f4aa0819SAdrian Hunter 
intel_pt_scan_for_psb(struct intel_pt_decoder * decoder)3871f4aa0819SAdrian Hunter static int intel_pt_scan_for_psb(struct intel_pt_decoder *decoder)
3872f4aa0819SAdrian Hunter {
3873f4aa0819SAdrian Hunter 	unsigned char *next;
3874f4aa0819SAdrian Hunter 	int ret;
3875f4aa0819SAdrian Hunter 
3876f4aa0819SAdrian Hunter 	intel_pt_log("Scanning for PSB\n");
3877f4aa0819SAdrian Hunter 	while (1) {
3878f4aa0819SAdrian Hunter 		if (!decoder->len) {
38796c1f0b18SAdrian Hunter 			ret = intel_pt_get_next_data(decoder, false);
3880f4aa0819SAdrian Hunter 			if (ret)
3881f4aa0819SAdrian Hunter 				return ret;
3882f4aa0819SAdrian Hunter 		}
3883f4aa0819SAdrian Hunter 
3884f4aa0819SAdrian Hunter 		next = memmem(decoder->buf, decoder->len, INTEL_PT_PSB_STR,
3885f4aa0819SAdrian Hunter 			      INTEL_PT_PSB_LEN);
3886f4aa0819SAdrian Hunter 		if (!next) {
3887f4aa0819SAdrian Hunter 			int part_psb;
3888f4aa0819SAdrian Hunter 
3889f4aa0819SAdrian Hunter 			part_psb = intel_pt_part_psb(decoder);
3890f4aa0819SAdrian Hunter 			if (part_psb) {
3891f4aa0819SAdrian Hunter 				ret = intel_pt_get_split_psb(decoder, part_psb);
3892f4aa0819SAdrian Hunter 				if (ret)
3893f4aa0819SAdrian Hunter 					return ret;
3894f4aa0819SAdrian Hunter 			} else {
3895f4aa0819SAdrian Hunter 				decoder->pos += decoder->len;
3896f4aa0819SAdrian Hunter 				decoder->len = 0;
3897f4aa0819SAdrian Hunter 			}
3898f4aa0819SAdrian Hunter 			continue;
3899f4aa0819SAdrian Hunter 		}
3900f4aa0819SAdrian Hunter 
3901f4aa0819SAdrian Hunter 		decoder->pkt_step = next - decoder->buf;
3902f4aa0819SAdrian Hunter 		return intel_pt_get_next_packet(decoder);
3903f4aa0819SAdrian Hunter 	}
3904f4aa0819SAdrian Hunter }
3905f4aa0819SAdrian Hunter 
intel_pt_sync(struct intel_pt_decoder * decoder)3906f4aa0819SAdrian Hunter static int intel_pt_sync(struct intel_pt_decoder *decoder)
3907f4aa0819SAdrian Hunter {
3908f4aa0819SAdrian Hunter 	int err;
3909f4aa0819SAdrian Hunter 
3910f4aa0819SAdrian Hunter 	decoder->pge = false;
3911f4aa0819SAdrian Hunter 	decoder->continuous_period = false;
3912ee14ac0eSAdrian Hunter 	decoder->have_last_ip = false;
3913f4aa0819SAdrian Hunter 	decoder->last_ip = 0;
3914c840cbfeSAdrian Hunter 	decoder->psb_ip = 0;
3915f4aa0819SAdrian Hunter 	decoder->ip = 0;
3916f4aa0819SAdrian Hunter 	intel_pt_clear_stack(&decoder->stack);
3917f4aa0819SAdrian Hunter 
3918f4aa0819SAdrian Hunter 	err = intel_pt_scan_for_psb(decoder);
3919f4aa0819SAdrian Hunter 	if (err)
3920f4aa0819SAdrian Hunter 		return err;
3921f4aa0819SAdrian Hunter 
3922fa8f949dSAdrian Hunter 	if (decoder->vm_time_correlation) {
3923fa8f949dSAdrian Hunter 		decoder->in_psb = true;
3924fa8f949dSAdrian Hunter 		if (!decoder->timestamp)
3925fa8f949dSAdrian Hunter 			decoder->timestamp = 1;
3926fa8f949dSAdrian Hunter 		decoder->state.type = 0;
3927fa8f949dSAdrian Hunter 		decoder->pkt_state = INTEL_PT_STATE_VM_TIME_CORRELATION;
3928fa8f949dSAdrian Hunter 		return 0;
3929fa8f949dSAdrian Hunter 	}
3930fa8f949dSAdrian Hunter 
3931ee14ac0eSAdrian Hunter 	decoder->have_last_ip = true;
3932ad106a26SAdrian Hunter 	decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
3933f4aa0819SAdrian Hunter 
3934f4aa0819SAdrian Hunter 	err = intel_pt_walk_psb(decoder);
3935f4aa0819SAdrian Hunter 	if (err)
3936f4aa0819SAdrian Hunter 		return err;
3937f4aa0819SAdrian Hunter 
3938c840cbfeSAdrian Hunter 	decoder->state.type = INTEL_PT_PSB_EVT; /* Only PSB sample */
3939c840cbfeSAdrian Hunter 	decoder->state.from_ip = decoder->psb_ip;
3940c840cbfeSAdrian Hunter 	decoder->state.to_ip = 0;
3941c840cbfeSAdrian Hunter 
3942f4aa0819SAdrian Hunter 	if (decoder->ip) {
39437c1b16baSAdrian Hunter 		/*
39447c1b16baSAdrian Hunter 		 * In hop mode, resample to get the PSB FUP ip as an
39457c1b16baSAdrian Hunter 		 * "instruction" sample.
39467c1b16baSAdrian Hunter 		 */
39477c1b16baSAdrian Hunter 		if (decoder->hop)
39487c1b16baSAdrian Hunter 			decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
39497c1b16baSAdrian Hunter 		else
3950f4aa0819SAdrian Hunter 			decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
3951f4aa0819SAdrian Hunter 	}
3952f4aa0819SAdrian Hunter 
3953f4aa0819SAdrian Hunter 	return 0;
3954f4aa0819SAdrian Hunter }
3955f4aa0819SAdrian Hunter 
intel_pt_est_timestamp(struct intel_pt_decoder * decoder)3956f4aa0819SAdrian Hunter static uint64_t intel_pt_est_timestamp(struct intel_pt_decoder *decoder)
3957f4aa0819SAdrian Hunter {
39583f04d98eSAdrian Hunter 	uint64_t est = decoder->sample_insn_cnt << 1;
3959f4aa0819SAdrian Hunter 
3960f4aa0819SAdrian Hunter 	if (!decoder->cbr || !decoder->max_non_turbo_ratio)
3961f4aa0819SAdrian Hunter 		goto out;
3962f4aa0819SAdrian Hunter 
3963f4aa0819SAdrian Hunter 	est *= decoder->max_non_turbo_ratio;
3964f4aa0819SAdrian Hunter 	est /= decoder->cbr;
3965f4aa0819SAdrian Hunter out:
39663f04d98eSAdrian Hunter 	return decoder->sample_timestamp + est;
3967f4aa0819SAdrian Hunter }
3968f4aa0819SAdrian Hunter 
intel_pt_decode(struct intel_pt_decoder * decoder)3969f4aa0819SAdrian Hunter const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
3970f4aa0819SAdrian Hunter {
3971f4aa0819SAdrian Hunter 	int err;
3972f4aa0819SAdrian Hunter 
3973f4aa0819SAdrian Hunter 	do {
3974f4aa0819SAdrian Hunter 		decoder->state.type = INTEL_PT_BRANCH;
3975f4aa0819SAdrian Hunter 		decoder->state.flags = 0;
3976f4aa0819SAdrian Hunter 
3977f4aa0819SAdrian Hunter 		switch (decoder->pkt_state) {
3978f4aa0819SAdrian Hunter 		case INTEL_PT_STATE_NO_PSB:
3979f4aa0819SAdrian Hunter 			err = intel_pt_sync(decoder);
3980f4aa0819SAdrian Hunter 			break;
3981f4aa0819SAdrian Hunter 		case INTEL_PT_STATE_NO_IP:
3982ee14ac0eSAdrian Hunter 			decoder->have_last_ip = false;
3983f4aa0819SAdrian Hunter 			decoder->last_ip = 0;
3984ad7167a8SAdrian Hunter 			decoder->ip = 0;
3985f7a858bfSLiam Howlett 			fallthrough;
3986f4aa0819SAdrian Hunter 		case INTEL_PT_STATE_ERR_RESYNC:
3987f4aa0819SAdrian Hunter 			err = intel_pt_sync_ip(decoder);
3988f4aa0819SAdrian Hunter 			break;
3989f4aa0819SAdrian Hunter 		case INTEL_PT_STATE_IN_SYNC:
3990f4aa0819SAdrian Hunter 			err = intel_pt_walk_trace(decoder);
3991f4aa0819SAdrian Hunter 			break;
3992f4aa0819SAdrian Hunter 		case INTEL_PT_STATE_TNT:
399361b6e08dSAdrian Hunter 		case INTEL_PT_STATE_TNT_CONT:
3994f4aa0819SAdrian Hunter 			err = intel_pt_walk_tnt(decoder);
3995f4aa0819SAdrian Hunter 			if (err == -EAGAIN)
3996f4aa0819SAdrian Hunter 				err = intel_pt_walk_trace(decoder);
3997f4aa0819SAdrian Hunter 			break;
3998f4aa0819SAdrian Hunter 		case INTEL_PT_STATE_TIP:
3999f4aa0819SAdrian Hunter 		case INTEL_PT_STATE_TIP_PGD:
4000f4aa0819SAdrian Hunter 			err = intel_pt_walk_tip(decoder);
4001f4aa0819SAdrian Hunter 			break;
4002f4aa0819SAdrian Hunter 		case INTEL_PT_STATE_FUP:
4003f4aa0819SAdrian Hunter 			err = intel_pt_walk_fup(decoder);
4004f4aa0819SAdrian Hunter 			if (err == -EAGAIN)
4005f4aa0819SAdrian Hunter 				err = intel_pt_walk_fup_tip(decoder);
4006f4aa0819SAdrian Hunter 			break;
4007f4aa0819SAdrian Hunter 		case INTEL_PT_STATE_FUP_NO_TIP:
4008f4aa0819SAdrian Hunter 			err = intel_pt_walk_fup(decoder);
4009f4aa0819SAdrian Hunter 			if (err == -EAGAIN)
4010f4aa0819SAdrian Hunter 				err = intel_pt_walk_trace(decoder);
4011f4aa0819SAdrian Hunter 			break;
4012c840cbfeSAdrian Hunter 		case INTEL_PT_STATE_FUP_IN_PSB:
4013c840cbfeSAdrian Hunter 			err = intel_pt_fup_in_psb(decoder);
4014c840cbfeSAdrian Hunter 			break;
40157c1b16baSAdrian Hunter 		case INTEL_PT_STATE_RESAMPLE:
40167c1b16baSAdrian Hunter 			err = intel_pt_resample(decoder);
40177c1b16baSAdrian Hunter 			break;
4018fa8f949dSAdrian Hunter 		case INTEL_PT_STATE_VM_TIME_CORRELATION:
4019fa8f949dSAdrian Hunter 			err = intel_pt_vm_time_correlation(decoder);
4020fa8f949dSAdrian Hunter 			break;
4021f4aa0819SAdrian Hunter 		default:
4022f4aa0819SAdrian Hunter 			err = intel_pt_bug(decoder);
4023f4aa0819SAdrian Hunter 			break;
4024f4aa0819SAdrian Hunter 		}
4025f4aa0819SAdrian Hunter 	} while (err == -ENOLINK);
4026f4aa0819SAdrian Hunter 
402722c06892SAdrian Hunter 	if (err) {
402822c06892SAdrian Hunter 		decoder->state.err = intel_pt_ext_err(err);
4029c79ee2b2SAdrian Hunter 		if (err != -EOVERFLOW)
403022c06892SAdrian Hunter 			decoder->state.from_ip = decoder->ip;
4031948e9dc8SAdrian Hunter 		intel_pt_update_sample_time(decoder);
40327b4b4f83SAdrian Hunter 		decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt;
403380a03886SAdrian Hunter 		intel_pt_set_nr(decoder);
403422c06892SAdrian Hunter 	} else {
403522c06892SAdrian Hunter 		decoder->state.err = 0;
4036abe5a1d3SAdrian Hunter 		if (decoder->cbr != decoder->cbr_seen) {
40370a7c700dSAdrian Hunter 			decoder->cbr_seen = decoder->cbr;
4038abe5a1d3SAdrian Hunter 			if (!decoder->state.type) {
4039abe5a1d3SAdrian Hunter 				decoder->state.from_ip = decoder->ip;
4040abe5a1d3SAdrian Hunter 				decoder->state.to_ip = 0;
4041abe5a1d3SAdrian Hunter 			}
40420a7c700dSAdrian Hunter 			decoder->state.type |= INTEL_PT_CBR_CHG;
40430a7c700dSAdrian Hunter 			decoder->state.cbr_payload = decoder->cbr_payload;
404451b09186SAdrian Hunter 			decoder->state.cbr = decoder->cbr;
40450a7c700dSAdrian Hunter 		}
40463f04d98eSAdrian Hunter 		if (intel_pt_sample_time(decoder->pkt_state)) {
4047948e9dc8SAdrian Hunter 			intel_pt_update_sample_time(decoder);
404820aa3970SAdrian Hunter 			if (decoder->sample_cyc) {
40497b4b4f83SAdrian Hunter 				decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt;
405020aa3970SAdrian Hunter 				decoder->state.flags |= INTEL_PT_SAMPLE_IPC;
405120aa3970SAdrian Hunter 				decoder->sample_cyc = false;
40523f04d98eSAdrian Hunter 			}
405322c06892SAdrian Hunter 		}
405420aa3970SAdrian Hunter 		/*
405520aa3970SAdrian Hunter 		 * When using only TSC/MTC to compute cycles, IPC can be
405620aa3970SAdrian Hunter 		 * sampled as soon as the cycle count changes.
405720aa3970SAdrian Hunter 		 */
405820aa3970SAdrian Hunter 		if (!decoder->have_cyc)
405920aa3970SAdrian Hunter 			decoder->state.flags |= INTEL_PT_SAMPLE_IPC;
406020aa3970SAdrian Hunter 	}
406122c06892SAdrian Hunter 
4062c840cbfeSAdrian Hunter 	 /* Let PSB event always have TSC timestamp */
4063c840cbfeSAdrian Hunter 	if ((decoder->state.type & INTEL_PT_PSB_EVT) && decoder->tsc_timestamp)
4064c840cbfeSAdrian Hunter 		decoder->sample_timestamp = decoder->tsc_timestamp;
4065c840cbfeSAdrian Hunter 
406680a03886SAdrian Hunter 	decoder->state.from_nr = decoder->nr;
406780a03886SAdrian Hunter 	decoder->state.to_nr = decoder->next_nr;
406880a03886SAdrian Hunter 	decoder->nr = decoder->next_nr;
406980a03886SAdrian Hunter 
40703f04d98eSAdrian Hunter 	decoder->state.timestamp = decoder->sample_timestamp;
4071f4aa0819SAdrian Hunter 	decoder->state.est_timestamp = intel_pt_est_timestamp(decoder);
40722a21d036SAdrian Hunter 	decoder->state.tot_insn_cnt = decoder->tot_insn_cnt;
40737b4b4f83SAdrian Hunter 	decoder->state.tot_cyc_cnt = decoder->sample_tot_cyc_cnt;
4074f4aa0819SAdrian Hunter 
4075f4aa0819SAdrian Hunter 	return &decoder->state;
4076f4aa0819SAdrian Hunter }
4077f4aa0819SAdrian Hunter 
4078f4aa0819SAdrian Hunter /**
4079f4aa0819SAdrian Hunter  * intel_pt_next_psb - move buffer pointer to the start of the next PSB packet.
4080f4aa0819SAdrian Hunter  * @buf: pointer to buffer pointer
4081f4aa0819SAdrian Hunter  * @len: size of buffer
4082f4aa0819SAdrian Hunter  *
4083f4aa0819SAdrian Hunter  * Updates the buffer pointer to point to the start of the next PSB packet if
4084f4aa0819SAdrian Hunter  * there is one, otherwise the buffer pointer is unchanged.  If @buf is updated,
4085f4aa0819SAdrian Hunter  * @len is adjusted accordingly.
4086f4aa0819SAdrian Hunter  *
4087f4aa0819SAdrian Hunter  * Return: %true if a PSB packet is found, %false otherwise.
4088f4aa0819SAdrian Hunter  */
intel_pt_next_psb(unsigned char ** buf,size_t * len)4089f4aa0819SAdrian Hunter static bool intel_pt_next_psb(unsigned char **buf, size_t *len)
4090f4aa0819SAdrian Hunter {
4091f4aa0819SAdrian Hunter 	unsigned char *next;
4092f4aa0819SAdrian Hunter 
4093f4aa0819SAdrian Hunter 	next = memmem(*buf, *len, INTEL_PT_PSB_STR, INTEL_PT_PSB_LEN);
4094f4aa0819SAdrian Hunter 	if (next) {
4095f4aa0819SAdrian Hunter 		*len -= next - *buf;
4096f4aa0819SAdrian Hunter 		*buf = next;
4097f4aa0819SAdrian Hunter 		return true;
4098f4aa0819SAdrian Hunter 	}
4099f4aa0819SAdrian Hunter 	return false;
4100f4aa0819SAdrian Hunter }
4101f4aa0819SAdrian Hunter 
4102f4aa0819SAdrian Hunter /**
4103f4aa0819SAdrian Hunter  * intel_pt_step_psb - move buffer pointer to the start of the following PSB
4104f4aa0819SAdrian Hunter  *                     packet.
4105f4aa0819SAdrian Hunter  * @buf: pointer to buffer pointer
4106f4aa0819SAdrian Hunter  * @len: size of buffer
4107f4aa0819SAdrian Hunter  *
4108f4aa0819SAdrian Hunter  * Updates the buffer pointer to point to the start of the following PSB packet
4109f4aa0819SAdrian Hunter  * (skipping the PSB at @buf itself) if there is one, otherwise the buffer
4110f4aa0819SAdrian Hunter  * pointer is unchanged.  If @buf is updated, @len is adjusted accordingly.
4111f4aa0819SAdrian Hunter  *
4112f4aa0819SAdrian Hunter  * Return: %true if a PSB packet is found, %false otherwise.
4113f4aa0819SAdrian Hunter  */
intel_pt_step_psb(unsigned char ** buf,size_t * len)4114f4aa0819SAdrian Hunter static bool intel_pt_step_psb(unsigned char **buf, size_t *len)
4115f4aa0819SAdrian Hunter {
4116f4aa0819SAdrian Hunter 	unsigned char *next;
4117f4aa0819SAdrian Hunter 
4118f4aa0819SAdrian Hunter 	if (!*len)
4119f4aa0819SAdrian Hunter 		return false;
4120f4aa0819SAdrian Hunter 
4121f4aa0819SAdrian Hunter 	next = memmem(*buf + 1, *len - 1, INTEL_PT_PSB_STR, INTEL_PT_PSB_LEN);
4122f4aa0819SAdrian Hunter 	if (next) {
4123f4aa0819SAdrian Hunter 		*len -= next - *buf;
4124f4aa0819SAdrian Hunter 		*buf = next;
4125f4aa0819SAdrian Hunter 		return true;
4126f4aa0819SAdrian Hunter 	}
4127f4aa0819SAdrian Hunter 	return false;
4128f4aa0819SAdrian Hunter }
4129f4aa0819SAdrian Hunter 
4130f4aa0819SAdrian Hunter /**
4131f4aa0819SAdrian Hunter  * intel_pt_last_psb - find the last PSB packet in a buffer.
4132f4aa0819SAdrian Hunter  * @buf: buffer
4133f4aa0819SAdrian Hunter  * @len: size of buffer
4134f4aa0819SAdrian Hunter  *
4135f4aa0819SAdrian Hunter  * This function finds the last PSB in a buffer.
4136f4aa0819SAdrian Hunter  *
4137f4aa0819SAdrian Hunter  * Return: A pointer to the last PSB in @buf if found, %NULL otherwise.
4138f4aa0819SAdrian Hunter  */
intel_pt_last_psb(unsigned char * buf,size_t len)4139f4aa0819SAdrian Hunter static unsigned char *intel_pt_last_psb(unsigned char *buf, size_t len)
4140f4aa0819SAdrian Hunter {
4141f4aa0819SAdrian Hunter 	const char *n = INTEL_PT_PSB_STR;
4142f4aa0819SAdrian Hunter 	unsigned char *p;
4143f4aa0819SAdrian Hunter 	size_t k;
4144f4aa0819SAdrian Hunter 
4145f4aa0819SAdrian Hunter 	if (len < INTEL_PT_PSB_LEN)
4146f4aa0819SAdrian Hunter 		return NULL;
4147f4aa0819SAdrian Hunter 
4148f4aa0819SAdrian Hunter 	k = len - INTEL_PT_PSB_LEN + 1;
4149f4aa0819SAdrian Hunter 	while (1) {
4150f4aa0819SAdrian Hunter 		p = memrchr(buf, n[0], k);
4151f4aa0819SAdrian Hunter 		if (!p)
4152f4aa0819SAdrian Hunter 			return NULL;
4153f4aa0819SAdrian Hunter 		if (!memcmp(p + 1, n + 1, INTEL_PT_PSB_LEN - 1))
4154f4aa0819SAdrian Hunter 			return p;
4155f4aa0819SAdrian Hunter 		k = p - buf;
4156f4aa0819SAdrian Hunter 		if (!k)
4157f4aa0819SAdrian Hunter 			return NULL;
4158f4aa0819SAdrian Hunter 	}
4159f4aa0819SAdrian Hunter }
4160f4aa0819SAdrian Hunter 
4161f4aa0819SAdrian Hunter /**
4162f4aa0819SAdrian Hunter  * intel_pt_next_tsc - find and return next TSC.
4163f4aa0819SAdrian Hunter  * @buf: buffer
4164f4aa0819SAdrian Hunter  * @len: size of buffer
4165f4aa0819SAdrian Hunter  * @tsc: TSC value returned
4166117db4b2SAdrian Hunter  * @rem: returns remaining size when TSC is found
4167f4aa0819SAdrian Hunter  *
4168f4aa0819SAdrian Hunter  * Find a TSC packet in @buf and return the TSC value.  This function assumes
4169f4aa0819SAdrian Hunter  * that @buf starts at a PSB and that PSB+ will contain TSC and so stops if a
4170f4aa0819SAdrian Hunter  * PSBEND packet is found.
4171f4aa0819SAdrian Hunter  *
4172f4aa0819SAdrian Hunter  * Return: %true if TSC is found, false otherwise.
4173f4aa0819SAdrian Hunter  */
intel_pt_next_tsc(unsigned char * buf,size_t len,uint64_t * tsc,size_t * rem)4174117db4b2SAdrian Hunter static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc,
4175117db4b2SAdrian Hunter 			      size_t *rem)
4176f4aa0819SAdrian Hunter {
4177edff7809SAdrian Hunter 	enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX;
4178f4aa0819SAdrian Hunter 	struct intel_pt_pkt packet;
4179f4aa0819SAdrian Hunter 	int ret;
4180f4aa0819SAdrian Hunter 
4181f4aa0819SAdrian Hunter 	while (len) {
4182edff7809SAdrian Hunter 		ret = intel_pt_get_packet(buf, len, &packet, &ctx);
4183f4aa0819SAdrian Hunter 		if (ret <= 0)
4184f4aa0819SAdrian Hunter 			return false;
4185f4aa0819SAdrian Hunter 		if (packet.type == INTEL_PT_TSC) {
4186f4aa0819SAdrian Hunter 			*tsc = packet.payload;
4187117db4b2SAdrian Hunter 			*rem = len;
4188f4aa0819SAdrian Hunter 			return true;
4189f4aa0819SAdrian Hunter 		}
4190f4aa0819SAdrian Hunter 		if (packet.type == INTEL_PT_PSBEND)
4191f4aa0819SAdrian Hunter 			return false;
4192f4aa0819SAdrian Hunter 		buf += ret;
4193f4aa0819SAdrian Hunter 		len -= ret;
4194f4aa0819SAdrian Hunter 	}
4195f4aa0819SAdrian Hunter 	return false;
4196f4aa0819SAdrian Hunter }
4197f4aa0819SAdrian Hunter 
4198f4aa0819SAdrian Hunter /**
4199f4aa0819SAdrian Hunter  * intel_pt_tsc_cmp - compare 7-byte TSCs.
4200f4aa0819SAdrian Hunter  * @tsc1: first TSC to compare
4201f4aa0819SAdrian Hunter  * @tsc2: second TSC to compare
4202f4aa0819SAdrian Hunter  *
4203f4aa0819SAdrian Hunter  * This function compares 7-byte TSC values allowing for the possibility that
4204f4aa0819SAdrian Hunter  * TSC wrapped around.  Generally it is not possible to know if TSC has wrapped
4205f4aa0819SAdrian Hunter  * around so for that purpose this function assumes the absolute difference is
4206f4aa0819SAdrian Hunter  * less than half the maximum difference.
4207f4aa0819SAdrian Hunter  *
4208f4aa0819SAdrian Hunter  * Return: %-1 if @tsc1 is before @tsc2, %0 if @tsc1 == @tsc2, %1 if @tsc1 is
4209f4aa0819SAdrian Hunter  * after @tsc2.
4210f4aa0819SAdrian Hunter  */
intel_pt_tsc_cmp(uint64_t tsc1,uint64_t tsc2)4211f4aa0819SAdrian Hunter static int intel_pt_tsc_cmp(uint64_t tsc1, uint64_t tsc2)
4212f4aa0819SAdrian Hunter {
4213f4aa0819SAdrian Hunter 	const uint64_t halfway = (1ULL << 55);
4214f4aa0819SAdrian Hunter 
4215f4aa0819SAdrian Hunter 	if (tsc1 == tsc2)
4216f4aa0819SAdrian Hunter 		return 0;
4217f4aa0819SAdrian Hunter 
4218f4aa0819SAdrian Hunter 	if (tsc1 < tsc2) {
4219f4aa0819SAdrian Hunter 		if (tsc2 - tsc1 < halfway)
4220f4aa0819SAdrian Hunter 			return -1;
4221f4aa0819SAdrian Hunter 		else
4222f4aa0819SAdrian Hunter 			return 1;
4223f4aa0819SAdrian Hunter 	} else {
4224f4aa0819SAdrian Hunter 		if (tsc1 - tsc2 < halfway)
4225f4aa0819SAdrian Hunter 			return 1;
4226f4aa0819SAdrian Hunter 		else
4227f4aa0819SAdrian Hunter 			return -1;
4228f4aa0819SAdrian Hunter 	}
4229f4aa0819SAdrian Hunter }
4230f4aa0819SAdrian Hunter 
42315a99d99eSAdrian Hunter #define MAX_PADDING (PERF_AUXTRACE_RECORD_ALIGNMENT - 1)
42325a99d99eSAdrian Hunter 
42335a99d99eSAdrian Hunter /**
42345a99d99eSAdrian Hunter  * adj_for_padding - adjust overlap to account for padding.
42355a99d99eSAdrian Hunter  * @buf_b: second buffer
42365a99d99eSAdrian Hunter  * @buf_a: first buffer
42375a99d99eSAdrian Hunter  * @len_a: size of first buffer
42385a99d99eSAdrian Hunter  *
42395a99d99eSAdrian Hunter  * @buf_a might have up to 7 bytes of padding appended. Adjust the overlap
42405a99d99eSAdrian Hunter  * accordingly.
42415a99d99eSAdrian Hunter  *
42425a99d99eSAdrian Hunter  * Return: A pointer into @buf_b from where non-overlapped data starts
42435a99d99eSAdrian Hunter  */
adj_for_padding(unsigned char * buf_b,unsigned char * buf_a,size_t len_a)42445a99d99eSAdrian Hunter static unsigned char *adj_for_padding(unsigned char *buf_b,
42455a99d99eSAdrian Hunter 				      unsigned char *buf_a, size_t len_a)
42465a99d99eSAdrian Hunter {
42475a99d99eSAdrian Hunter 	unsigned char *p = buf_b - MAX_PADDING;
42485a99d99eSAdrian Hunter 	unsigned char *q = buf_a + len_a - MAX_PADDING;
42495a99d99eSAdrian Hunter 	int i;
42505a99d99eSAdrian Hunter 
42515a99d99eSAdrian Hunter 	for (i = MAX_PADDING; i; i--, p++, q++) {
42525a99d99eSAdrian Hunter 		if (*p != *q)
42535a99d99eSAdrian Hunter 			break;
42545a99d99eSAdrian Hunter 	}
42555a99d99eSAdrian Hunter 
42565a99d99eSAdrian Hunter 	return p;
42575a99d99eSAdrian Hunter }
42585a99d99eSAdrian Hunter 
4259f4aa0819SAdrian Hunter /**
4260f4aa0819SAdrian Hunter  * intel_pt_find_overlap_tsc - determine start of non-overlapped trace data
4261f4aa0819SAdrian Hunter  *                             using TSC.
4262f4aa0819SAdrian Hunter  * @buf_a: first buffer
4263f4aa0819SAdrian Hunter  * @len_a: size of first buffer
4264f4aa0819SAdrian Hunter  * @buf_b: second buffer
4265f4aa0819SAdrian Hunter  * @len_b: size of second buffer
4266117db4b2SAdrian Hunter  * @consecutive: returns true if there is data in buf_b that is consecutive
4267117db4b2SAdrian Hunter  *               to buf_a
4268335358ccSAdrian Hunter  * @ooo_tsc: out-of-order TSC due to VM TSC offset / scaling
4269f4aa0819SAdrian Hunter  *
4270f4aa0819SAdrian Hunter  * If the trace contains TSC we can look at the last TSC of @buf_a and the
4271f4aa0819SAdrian Hunter  * first TSC of @buf_b in order to determine if the buffers overlap, and then
4272f4aa0819SAdrian Hunter  * walk forward in @buf_b until a later TSC is found.  A precondition is that
4273f4aa0819SAdrian Hunter  * @buf_a and @buf_b are positioned at a PSB.
4274f4aa0819SAdrian Hunter  *
4275f4aa0819SAdrian Hunter  * Return: A pointer into @buf_b from where non-overlapped data starts, or
4276f4aa0819SAdrian Hunter  * @buf_b + @len_b if there is no non-overlapped data.
4277f4aa0819SAdrian Hunter  */
intel_pt_find_overlap_tsc(unsigned char * buf_a,size_t len_a,unsigned char * buf_b,size_t len_b,bool * consecutive,bool ooo_tsc)4278f4aa0819SAdrian Hunter static unsigned char *intel_pt_find_overlap_tsc(unsigned char *buf_a,
4279f4aa0819SAdrian Hunter 						size_t len_a,
4280f4aa0819SAdrian Hunter 						unsigned char *buf_b,
4281335358ccSAdrian Hunter 						size_t len_b, bool *consecutive,
4282335358ccSAdrian Hunter 						bool ooo_tsc)
4283f4aa0819SAdrian Hunter {
4284f4aa0819SAdrian Hunter 	uint64_t tsc_a, tsc_b;
4285f4aa0819SAdrian Hunter 	unsigned char *p;
4286117db4b2SAdrian Hunter 	size_t len, rem_a, rem_b;
4287f4aa0819SAdrian Hunter 
4288f4aa0819SAdrian Hunter 	p = intel_pt_last_psb(buf_a, len_a);
4289f4aa0819SAdrian Hunter 	if (!p)
4290f4aa0819SAdrian Hunter 		return buf_b; /* No PSB in buf_a => no overlap */
4291f4aa0819SAdrian Hunter 
4292f4aa0819SAdrian Hunter 	len = len_a - (p - buf_a);
4293117db4b2SAdrian Hunter 	if (!intel_pt_next_tsc(p, len, &tsc_a, &rem_a)) {
4294f4aa0819SAdrian Hunter 		/* The last PSB+ in buf_a is incomplete, so go back one more */
4295f4aa0819SAdrian Hunter 		len_a -= len;
4296f4aa0819SAdrian Hunter 		p = intel_pt_last_psb(buf_a, len_a);
4297f4aa0819SAdrian Hunter 		if (!p)
4298f4aa0819SAdrian Hunter 			return buf_b; /* No full PSB+ => assume no overlap */
4299f4aa0819SAdrian Hunter 		len = len_a - (p - buf_a);
4300117db4b2SAdrian Hunter 		if (!intel_pt_next_tsc(p, len, &tsc_a, &rem_a))
4301f4aa0819SAdrian Hunter 			return buf_b; /* No TSC in buf_a => assume no overlap */
4302f4aa0819SAdrian Hunter 	}
4303f4aa0819SAdrian Hunter 
4304f4aa0819SAdrian Hunter 	while (1) {
4305f4aa0819SAdrian Hunter 		/* Ignore PSB+ with no TSC */
4306117db4b2SAdrian Hunter 		if (intel_pt_next_tsc(buf_b, len_b, &tsc_b, &rem_b)) {
4307117db4b2SAdrian Hunter 			int cmp = intel_pt_tsc_cmp(tsc_a, tsc_b);
4308117db4b2SAdrian Hunter 
4309117db4b2SAdrian Hunter 			/* Same TSC, so buffers are consecutive */
4310117db4b2SAdrian Hunter 			if (!cmp && rem_b >= rem_a) {
43115a99d99eSAdrian Hunter 				unsigned char *start;
43125a99d99eSAdrian Hunter 
4313117db4b2SAdrian Hunter 				*consecutive = true;
43145a99d99eSAdrian Hunter 				start = buf_b + len_b - (rem_b - rem_a);
43155a99d99eSAdrian Hunter 				return adj_for_padding(start, buf_a, len_a);
4316117db4b2SAdrian Hunter 			}
4317335358ccSAdrian Hunter 			if (cmp < 0 && !ooo_tsc)
4318f4aa0819SAdrian Hunter 				return buf_b; /* tsc_a < tsc_b => no overlap */
4319117db4b2SAdrian Hunter 		}
4320f4aa0819SAdrian Hunter 
4321f4aa0819SAdrian Hunter 		if (!intel_pt_step_psb(&buf_b, &len_b))
4322f4aa0819SAdrian Hunter 			return buf_b + len_b; /* No PSB in buf_b => no data */
4323f4aa0819SAdrian Hunter 	}
4324f4aa0819SAdrian Hunter }
4325f4aa0819SAdrian Hunter 
4326f4aa0819SAdrian Hunter /**
4327f4aa0819SAdrian Hunter  * intel_pt_find_overlap - determine start of non-overlapped trace data.
4328f4aa0819SAdrian Hunter  * @buf_a: first buffer
4329f4aa0819SAdrian Hunter  * @len_a: size of first buffer
4330f4aa0819SAdrian Hunter  * @buf_b: second buffer
4331f4aa0819SAdrian Hunter  * @len_b: size of second buffer
4332f4aa0819SAdrian Hunter  * @have_tsc: can use TSC packets to detect overlap
4333117db4b2SAdrian Hunter  * @consecutive: returns true if there is data in buf_b that is consecutive
4334117db4b2SAdrian Hunter  *               to buf_a
4335335358ccSAdrian Hunter  * @ooo_tsc: out-of-order TSC due to VM TSC offset / scaling
4336f4aa0819SAdrian Hunter  *
4337f4aa0819SAdrian Hunter  * When trace samples or snapshots are recorded there is the possibility that
4338f4aa0819SAdrian Hunter  * the data overlaps.  Note that, for the purposes of decoding, data is only
4339f4aa0819SAdrian Hunter  * useful if it begins with a PSB packet.
4340f4aa0819SAdrian Hunter  *
4341f4aa0819SAdrian Hunter  * Return: A pointer into @buf_b from where non-overlapped data starts, or
4342f4aa0819SAdrian Hunter  * @buf_b + @len_b if there is no non-overlapped data.
4343f4aa0819SAdrian Hunter  */
intel_pt_find_overlap(unsigned char * buf_a,size_t len_a,unsigned char * buf_b,size_t len_b,bool have_tsc,bool * consecutive,bool ooo_tsc)4344f4aa0819SAdrian Hunter unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a,
4345f4aa0819SAdrian Hunter 				     unsigned char *buf_b, size_t len_b,
4346335358ccSAdrian Hunter 				     bool have_tsc, bool *consecutive,
4347335358ccSAdrian Hunter 				     bool ooo_tsc)
4348f4aa0819SAdrian Hunter {
4349f4aa0819SAdrian Hunter 	unsigned char *found;
4350f4aa0819SAdrian Hunter 
4351f4aa0819SAdrian Hunter 	/* Buffer 'b' must start at PSB so throw away everything before that */
4352f4aa0819SAdrian Hunter 	if (!intel_pt_next_psb(&buf_b, &len_b))
4353f4aa0819SAdrian Hunter 		return buf_b + len_b; /* No PSB */
4354f4aa0819SAdrian Hunter 
4355f4aa0819SAdrian Hunter 	if (!intel_pt_next_psb(&buf_a, &len_a))
4356f4aa0819SAdrian Hunter 		return buf_b; /* No overlap */
4357f4aa0819SAdrian Hunter 
4358f4aa0819SAdrian Hunter 	if (have_tsc) {
4359117db4b2SAdrian Hunter 		found = intel_pt_find_overlap_tsc(buf_a, len_a, buf_b, len_b,
4360335358ccSAdrian Hunter 						  consecutive, ooo_tsc);
4361f4aa0819SAdrian Hunter 		if (found)
4362f4aa0819SAdrian Hunter 			return found;
4363f4aa0819SAdrian Hunter 	}
4364f4aa0819SAdrian Hunter 
4365f4aa0819SAdrian Hunter 	/*
4366f4aa0819SAdrian Hunter 	 * Buffer 'b' cannot end within buffer 'a' so, for comparison purposes,
4367f4aa0819SAdrian Hunter 	 * we can ignore the first part of buffer 'a'.
4368f4aa0819SAdrian Hunter 	 */
4369f4aa0819SAdrian Hunter 	while (len_b < len_a) {
4370f4aa0819SAdrian Hunter 		if (!intel_pt_step_psb(&buf_a, &len_a))
4371f4aa0819SAdrian Hunter 			return buf_b; /* No overlap */
4372f4aa0819SAdrian Hunter 	}
4373f4aa0819SAdrian Hunter 
4374f4aa0819SAdrian Hunter 	/* Now len_b >= len_a */
4375f4aa0819SAdrian Hunter 	while (1) {
4376f4aa0819SAdrian Hunter 		/* Potential overlap so check the bytes */
4377f4aa0819SAdrian Hunter 		found = memmem(buf_a, len_a, buf_b, len_a);
4378117db4b2SAdrian Hunter 		if (found) {
4379117db4b2SAdrian Hunter 			*consecutive = true;
43805a99d99eSAdrian Hunter 			return adj_for_padding(buf_b + len_a, buf_a, len_a);
4381117db4b2SAdrian Hunter 		}
4382f4aa0819SAdrian Hunter 
4383f4aa0819SAdrian Hunter 		/* Try again at next PSB in buffer 'a' */
4384f4aa0819SAdrian Hunter 		if (!intel_pt_step_psb(&buf_a, &len_a))
4385f4aa0819SAdrian Hunter 			return buf_b; /* No overlap */
4386f4aa0819SAdrian Hunter 	}
4387f4aa0819SAdrian Hunter }
4388a7fa19f5SAdrian Hunter 
4389a7fa19f5SAdrian Hunter /**
4390a7fa19f5SAdrian Hunter  * struct fast_forward_data - data used by intel_pt_ff_cb().
4391a7fa19f5SAdrian Hunter  * @timestamp: timestamp to fast forward towards
4392a7fa19f5SAdrian Hunter  * @buf_timestamp: buffer timestamp of last buffer with trace data earlier than
4393a7fa19f5SAdrian Hunter  *                 the fast forward timestamp.
4394a7fa19f5SAdrian Hunter  */
4395a7fa19f5SAdrian Hunter struct fast_forward_data {
4396a7fa19f5SAdrian Hunter 	uint64_t timestamp;
4397a7fa19f5SAdrian Hunter 	uint64_t buf_timestamp;
4398a7fa19f5SAdrian Hunter };
4399a7fa19f5SAdrian Hunter 
4400a7fa19f5SAdrian Hunter /**
4401a7fa19f5SAdrian Hunter  * intel_pt_ff_cb - fast forward lookahead callback.
4402a7fa19f5SAdrian Hunter  * @buffer: Intel PT trace buffer
4403a7fa19f5SAdrian Hunter  * @data: opaque pointer to fast forward data (struct fast_forward_data)
4404a7fa19f5SAdrian Hunter  *
4405a7fa19f5SAdrian Hunter  * Determine if @buffer trace is past the fast forward timestamp.
4406a7fa19f5SAdrian Hunter  *
4407a7fa19f5SAdrian Hunter  * Return: 1 (stop lookahead) if @buffer trace is past the fast forward
4408a7fa19f5SAdrian Hunter  *         timestamp, and 0 otherwise.
4409a7fa19f5SAdrian Hunter  */
intel_pt_ff_cb(struct intel_pt_buffer * buffer,void * data)4410a7fa19f5SAdrian Hunter static int intel_pt_ff_cb(struct intel_pt_buffer *buffer, void *data)
4411a7fa19f5SAdrian Hunter {
4412a7fa19f5SAdrian Hunter 	struct fast_forward_data *d = data;
4413a7fa19f5SAdrian Hunter 	unsigned char *buf;
4414a7fa19f5SAdrian Hunter 	uint64_t tsc;
4415a7fa19f5SAdrian Hunter 	size_t rem;
4416a7fa19f5SAdrian Hunter 	size_t len;
4417a7fa19f5SAdrian Hunter 
4418a7fa19f5SAdrian Hunter 	buf = (unsigned char *)buffer->buf;
4419a7fa19f5SAdrian Hunter 	len = buffer->len;
4420a7fa19f5SAdrian Hunter 
4421a7fa19f5SAdrian Hunter 	if (!intel_pt_next_psb(&buf, &len) ||
4422a7fa19f5SAdrian Hunter 	    !intel_pt_next_tsc(buf, len, &tsc, &rem))
4423a7fa19f5SAdrian Hunter 		return 0;
4424a7fa19f5SAdrian Hunter 
4425a7fa19f5SAdrian Hunter 	tsc = intel_pt_8b_tsc(tsc, buffer->ref_timestamp);
4426a7fa19f5SAdrian Hunter 
4427a7fa19f5SAdrian Hunter 	intel_pt_log("Buffer 1st timestamp " x64_fmt " ref timestamp " x64_fmt "\n",
4428a7fa19f5SAdrian Hunter 		     tsc, buffer->ref_timestamp);
4429a7fa19f5SAdrian Hunter 
4430a7fa19f5SAdrian Hunter 	/*
4431a7fa19f5SAdrian Hunter 	 * If the buffer contains a timestamp earlier that the fast forward
4432a7fa19f5SAdrian Hunter 	 * timestamp, then record it, else stop.
4433a7fa19f5SAdrian Hunter 	 */
4434a7fa19f5SAdrian Hunter 	if (tsc < d->timestamp)
4435a7fa19f5SAdrian Hunter 		d->buf_timestamp = buffer->ref_timestamp;
4436a7fa19f5SAdrian Hunter 	else
4437a7fa19f5SAdrian Hunter 		return 1;
4438a7fa19f5SAdrian Hunter 
4439a7fa19f5SAdrian Hunter 	return 0;
4440a7fa19f5SAdrian Hunter }
4441a7fa19f5SAdrian Hunter 
4442a7fa19f5SAdrian Hunter /**
4443a7fa19f5SAdrian Hunter  * intel_pt_fast_forward - reposition decoder forwards.
4444a7fa19f5SAdrian Hunter  * @decoder: Intel PT decoder
4445a7fa19f5SAdrian Hunter  * @timestamp: timestamp to fast forward towards
4446a7fa19f5SAdrian Hunter  *
4447a7fa19f5SAdrian Hunter  * Reposition decoder at the last PSB with a timestamp earlier than @timestamp.
4448a7fa19f5SAdrian Hunter  *
4449a7fa19f5SAdrian Hunter  * Return: 0 on success or negative error code on failure.
4450a7fa19f5SAdrian Hunter  */
intel_pt_fast_forward(struct intel_pt_decoder * decoder,uint64_t timestamp)4451a7fa19f5SAdrian Hunter int intel_pt_fast_forward(struct intel_pt_decoder *decoder, uint64_t timestamp)
4452a7fa19f5SAdrian Hunter {
4453a7fa19f5SAdrian Hunter 	struct fast_forward_data d = { .timestamp = timestamp };
4454a7fa19f5SAdrian Hunter 	unsigned char *buf;
4455a7fa19f5SAdrian Hunter 	size_t len;
4456a7fa19f5SAdrian Hunter 	int err;
4457a7fa19f5SAdrian Hunter 
4458a7fa19f5SAdrian Hunter 	intel_pt_log("Fast forward towards timestamp " x64_fmt "\n", timestamp);
4459a7fa19f5SAdrian Hunter 
4460a7fa19f5SAdrian Hunter 	/* Find buffer timestamp of buffer to fast forward to */
4461a7fa19f5SAdrian Hunter 	err = decoder->lookahead(decoder->data, intel_pt_ff_cb, &d);
4462a7fa19f5SAdrian Hunter 	if (err < 0)
4463a7fa19f5SAdrian Hunter 		return err;
4464a7fa19f5SAdrian Hunter 
4465a7fa19f5SAdrian Hunter 	/* Walk to buffer with same buffer timestamp */
4466a7fa19f5SAdrian Hunter 	if (d.buf_timestamp) {
4467a7fa19f5SAdrian Hunter 		do {
4468a7fa19f5SAdrian Hunter 			decoder->pos += decoder->len;
4469a7fa19f5SAdrian Hunter 			decoder->len = 0;
4470a7fa19f5SAdrian Hunter 			err = intel_pt_get_next_data(decoder, true);
4471a7fa19f5SAdrian Hunter 			/* -ENOLINK means non-consecutive trace */
4472a7fa19f5SAdrian Hunter 			if (err && err != -ENOLINK)
4473a7fa19f5SAdrian Hunter 				return err;
4474a7fa19f5SAdrian Hunter 		} while (decoder->buf_timestamp != d.buf_timestamp);
4475a7fa19f5SAdrian Hunter 	}
4476a7fa19f5SAdrian Hunter 
4477a7fa19f5SAdrian Hunter 	if (!decoder->buf)
4478a7fa19f5SAdrian Hunter 		return 0;
4479a7fa19f5SAdrian Hunter 
4480a7fa19f5SAdrian Hunter 	buf = (unsigned char *)decoder->buf;
4481a7fa19f5SAdrian Hunter 	len = decoder->len;
4482a7fa19f5SAdrian Hunter 
4483a7fa19f5SAdrian Hunter 	if (!intel_pt_next_psb(&buf, &len))
4484a7fa19f5SAdrian Hunter 		return 0;
4485a7fa19f5SAdrian Hunter 
4486a7fa19f5SAdrian Hunter 	/*
4487a7fa19f5SAdrian Hunter 	 * Walk PSBs while the PSB timestamp is less than the fast forward
4488a7fa19f5SAdrian Hunter 	 * timestamp.
4489a7fa19f5SAdrian Hunter 	 */
4490a7fa19f5SAdrian Hunter 	do {
4491a7fa19f5SAdrian Hunter 		uint64_t tsc;
4492a7fa19f5SAdrian Hunter 		size_t rem;
4493a7fa19f5SAdrian Hunter 
4494a7fa19f5SAdrian Hunter 		if (!intel_pt_next_tsc(buf, len, &tsc, &rem))
4495a7fa19f5SAdrian Hunter 			break;
4496a7fa19f5SAdrian Hunter 		tsc = intel_pt_8b_tsc(tsc, decoder->buf_timestamp);
4497a7fa19f5SAdrian Hunter 		/*
4498a7fa19f5SAdrian Hunter 		 * A TSC packet can slip past MTC packets but, after fast
4499a7fa19f5SAdrian Hunter 		 * forward, decoding starts at the TSC timestamp. That means
4500a7fa19f5SAdrian Hunter 		 * the timestamps may not be exactly the same as the timestamps
4501a7fa19f5SAdrian Hunter 		 * that would have been decoded without fast forward.
4502a7fa19f5SAdrian Hunter 		 */
4503a7fa19f5SAdrian Hunter 		if (tsc < timestamp) {
4504a7fa19f5SAdrian Hunter 			intel_pt_log("Fast forward to next PSB timestamp " x64_fmt "\n", tsc);
4505a7fa19f5SAdrian Hunter 			decoder->pos += decoder->len - len;
4506a7fa19f5SAdrian Hunter 			decoder->buf = buf;
4507a7fa19f5SAdrian Hunter 			decoder->len = len;
4508a7fa19f5SAdrian Hunter 			intel_pt_reposition(decoder);
4509a7fa19f5SAdrian Hunter 		} else {
4510a7fa19f5SAdrian Hunter 			break;
4511a7fa19f5SAdrian Hunter 		}
4512a7fa19f5SAdrian Hunter 	} while (intel_pt_step_psb(&buf, &len));
4513a7fa19f5SAdrian Hunter 
4514a7fa19f5SAdrian Hunter 	return 0;
4515a7fa19f5SAdrian Hunter }
4516