1*74fe6c29SRuslan Bukin /*
2*74fe6c29SRuslan Bukin  * Copyright (c) 2014-2018, Intel Corporation
3*74fe6c29SRuslan Bukin  *
4*74fe6c29SRuslan Bukin  * Redistribution and use in source and binary forms, with or without
5*74fe6c29SRuslan Bukin  * modification, are permitted provided that the following conditions are met:
6*74fe6c29SRuslan Bukin  *
7*74fe6c29SRuslan Bukin  *  * Redistributions of source code must retain the above copyright notice,
8*74fe6c29SRuslan Bukin  *    this list of conditions and the following disclaimer.
9*74fe6c29SRuslan Bukin  *  * Redistributions in binary form must reproduce the above copyright notice,
10*74fe6c29SRuslan Bukin  *    this list of conditions and the following disclaimer in the documentation
11*74fe6c29SRuslan Bukin  *    and/or other materials provided with the distribution.
12*74fe6c29SRuslan Bukin  *  * Neither the name of Intel Corporation nor the names of its contributors
13*74fe6c29SRuslan Bukin  *    may be used to endorse or promote products derived from this software
14*74fe6c29SRuslan Bukin  *    without specific prior written permission.
15*74fe6c29SRuslan Bukin  *
16*74fe6c29SRuslan Bukin  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*74fe6c29SRuslan Bukin  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*74fe6c29SRuslan Bukin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*74fe6c29SRuslan Bukin  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20*74fe6c29SRuslan Bukin  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*74fe6c29SRuslan Bukin  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*74fe6c29SRuslan Bukin  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*74fe6c29SRuslan Bukin  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*74fe6c29SRuslan Bukin  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*74fe6c29SRuslan Bukin  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*74fe6c29SRuslan Bukin  * POSSIBILITY OF SUCH DAMAGE.
27*74fe6c29SRuslan Bukin  */
28*74fe6c29SRuslan Bukin 
29*74fe6c29SRuslan Bukin #include "pt_query_decoder.h"
30*74fe6c29SRuslan Bukin #include "pt_sync.h"
31*74fe6c29SRuslan Bukin #include "pt_decoder_function.h"
32*74fe6c29SRuslan Bukin #include "pt_packet.h"
33*74fe6c29SRuslan Bukin #include "pt_packet_decoder.h"
34*74fe6c29SRuslan Bukin #include "pt_config.h"
35*74fe6c29SRuslan Bukin #include "pt_opcodes.h"
36*74fe6c29SRuslan Bukin #include "pt_compiler.h"
37*74fe6c29SRuslan Bukin 
38*74fe6c29SRuslan Bukin #include "intel-pt.h"
39*74fe6c29SRuslan Bukin 
40*74fe6c29SRuslan Bukin #include <string.h>
41*74fe6c29SRuslan Bukin #include <stddef.h>
42*74fe6c29SRuslan Bukin #include <stdlib.h>
43*74fe6c29SRuslan Bukin #include <limits.h>
44*74fe6c29SRuslan Bukin 
45*74fe6c29SRuslan Bukin 
46*74fe6c29SRuslan Bukin /* Find a FUP in a PSB+ header.
47*74fe6c29SRuslan Bukin  *
48*74fe6c29SRuslan Bukin  * The packet @decoder must be synchronized onto the trace stream at the
49*74fe6c29SRuslan Bukin  * beginning or somewhere inside a PSB+ header.
50*74fe6c29SRuslan Bukin  *
51*74fe6c29SRuslan Bukin  * It uses @packet to hold trace packets during its search.  If the search is
52*74fe6c29SRuslan Bukin  * successful, @packet will contain the first (and hopefully only) FUP packet in
53*74fe6c29SRuslan Bukin  * this PSB+.  Otherwise, @packet may contain anything.
54*74fe6c29SRuslan Bukin  *
55*74fe6c29SRuslan Bukin  * Returns one if a FUP packet is found (@packet will contain it).
56*74fe6c29SRuslan Bukin  * Returns zero if no FUP packet is found (@packet is undefined).
57*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
58*74fe6c29SRuslan Bukin  */
pt_qry_find_header_fup(struct pt_packet * packet,struct pt_packet_decoder * decoder)59*74fe6c29SRuslan Bukin static int pt_qry_find_header_fup(struct pt_packet *packet,
60*74fe6c29SRuslan Bukin 				  struct pt_packet_decoder *decoder)
61*74fe6c29SRuslan Bukin {
62*74fe6c29SRuslan Bukin 	if (!packet || !decoder)
63*74fe6c29SRuslan Bukin 		return -pte_internal;
64*74fe6c29SRuslan Bukin 
65*74fe6c29SRuslan Bukin 	for (;;) {
66*74fe6c29SRuslan Bukin 		int errcode;
67*74fe6c29SRuslan Bukin 
68*74fe6c29SRuslan Bukin 		errcode = pt_pkt_next(decoder, packet, sizeof(*packet));
69*74fe6c29SRuslan Bukin 		if (errcode < 0)
70*74fe6c29SRuslan Bukin 			return errcode;
71*74fe6c29SRuslan Bukin 
72*74fe6c29SRuslan Bukin 		switch (packet->type) {
73*74fe6c29SRuslan Bukin 		default:
74*74fe6c29SRuslan Bukin 			/* Ignore the packet. */
75*74fe6c29SRuslan Bukin 			break;
76*74fe6c29SRuslan Bukin 
77*74fe6c29SRuslan Bukin 		case ppt_psbend:
78*74fe6c29SRuslan Bukin 			/* There's no FUP in here. */
79*74fe6c29SRuslan Bukin 			return 0;
80*74fe6c29SRuslan Bukin 
81*74fe6c29SRuslan Bukin 		case ppt_fup:
82*74fe6c29SRuslan Bukin 			/* Found it. */
83*74fe6c29SRuslan Bukin 			return 1;
84*74fe6c29SRuslan Bukin 		}
85*74fe6c29SRuslan Bukin 	}
86*74fe6c29SRuslan Bukin }
87*74fe6c29SRuslan Bukin 
pt_qry_decoder_init(struct pt_query_decoder * decoder,const struct pt_config * config)88*74fe6c29SRuslan Bukin int pt_qry_decoder_init(struct pt_query_decoder *decoder,
89*74fe6c29SRuslan Bukin 			const struct pt_config *config)
90*74fe6c29SRuslan Bukin {
91*74fe6c29SRuslan Bukin 	int errcode;
92*74fe6c29SRuslan Bukin 
93*74fe6c29SRuslan Bukin 	if (!decoder)
94*74fe6c29SRuslan Bukin 		return -pte_invalid;
95*74fe6c29SRuslan Bukin 
96*74fe6c29SRuslan Bukin 	memset(decoder, 0, sizeof(*decoder));
97*74fe6c29SRuslan Bukin 
98*74fe6c29SRuslan Bukin 	errcode = pt_config_from_user(&decoder->config, config);
99*74fe6c29SRuslan Bukin 	if (errcode < 0)
100*74fe6c29SRuslan Bukin 		return errcode;
101*74fe6c29SRuslan Bukin 
102*74fe6c29SRuslan Bukin 	pt_last_ip_init(&decoder->ip);
103*74fe6c29SRuslan Bukin 	pt_tnt_cache_init(&decoder->tnt);
104*74fe6c29SRuslan Bukin 	pt_time_init(&decoder->time);
105*74fe6c29SRuslan Bukin 	pt_time_init(&decoder->last_time);
106*74fe6c29SRuslan Bukin 	pt_tcal_init(&decoder->tcal);
107*74fe6c29SRuslan Bukin 	pt_evq_init(&decoder->evq);
108*74fe6c29SRuslan Bukin 
109*74fe6c29SRuslan Bukin 	return 0;
110*74fe6c29SRuslan Bukin }
111*74fe6c29SRuslan Bukin 
pt_qry_alloc_decoder(const struct pt_config * config)112*74fe6c29SRuslan Bukin struct pt_query_decoder *pt_qry_alloc_decoder(const struct pt_config *config)
113*74fe6c29SRuslan Bukin {
114*74fe6c29SRuslan Bukin 	struct pt_query_decoder *decoder;
115*74fe6c29SRuslan Bukin 	int errcode;
116*74fe6c29SRuslan Bukin 
117*74fe6c29SRuslan Bukin 	decoder = malloc(sizeof(*decoder));
118*74fe6c29SRuslan Bukin 	if (!decoder)
119*74fe6c29SRuslan Bukin 		return NULL;
120*74fe6c29SRuslan Bukin 
121*74fe6c29SRuslan Bukin 	errcode = pt_qry_decoder_init(decoder, config);
122*74fe6c29SRuslan Bukin 	if (errcode < 0) {
123*74fe6c29SRuslan Bukin 		free(decoder);
124*74fe6c29SRuslan Bukin 		return NULL;
125*74fe6c29SRuslan Bukin 	}
126*74fe6c29SRuslan Bukin 
127*74fe6c29SRuslan Bukin 	return decoder;
128*74fe6c29SRuslan Bukin }
129*74fe6c29SRuslan Bukin 
pt_qry_decoder_fini(struct pt_query_decoder * decoder)130*74fe6c29SRuslan Bukin void pt_qry_decoder_fini(struct pt_query_decoder *decoder)
131*74fe6c29SRuslan Bukin {
132*74fe6c29SRuslan Bukin 	(void) decoder;
133*74fe6c29SRuslan Bukin 
134*74fe6c29SRuslan Bukin 	/* Nothing to do. */
135*74fe6c29SRuslan Bukin }
136*74fe6c29SRuslan Bukin 
pt_qry_free_decoder(struct pt_query_decoder * decoder)137*74fe6c29SRuslan Bukin void pt_qry_free_decoder(struct pt_query_decoder *decoder)
138*74fe6c29SRuslan Bukin {
139*74fe6c29SRuslan Bukin 	pt_qry_decoder_fini(decoder);
140*74fe6c29SRuslan Bukin 	free(decoder);
141*74fe6c29SRuslan Bukin }
142*74fe6c29SRuslan Bukin 
pt_qry_reset(struct pt_query_decoder * decoder)143*74fe6c29SRuslan Bukin static void pt_qry_reset(struct pt_query_decoder *decoder)
144*74fe6c29SRuslan Bukin {
145*74fe6c29SRuslan Bukin 	if (!decoder)
146*74fe6c29SRuslan Bukin 		return;
147*74fe6c29SRuslan Bukin 
148*74fe6c29SRuslan Bukin 	decoder->enabled = 0;
149*74fe6c29SRuslan Bukin 	decoder->consume_packet = 0;
150*74fe6c29SRuslan Bukin 	decoder->event = NULL;
151*74fe6c29SRuslan Bukin 
152*74fe6c29SRuslan Bukin 	pt_last_ip_init(&decoder->ip);
153*74fe6c29SRuslan Bukin 	pt_tnt_cache_init(&decoder->tnt);
154*74fe6c29SRuslan Bukin 	pt_time_init(&decoder->time);
155*74fe6c29SRuslan Bukin 	pt_time_init(&decoder->last_time);
156*74fe6c29SRuslan Bukin 	pt_tcal_init(&decoder->tcal);
157*74fe6c29SRuslan Bukin 	pt_evq_init(&decoder->evq);
158*74fe6c29SRuslan Bukin }
159*74fe6c29SRuslan Bukin 
pt_qry_will_event(const struct pt_query_decoder * decoder)160*74fe6c29SRuslan Bukin static int pt_qry_will_event(const struct pt_query_decoder *decoder)
161*74fe6c29SRuslan Bukin {
162*74fe6c29SRuslan Bukin 	const struct pt_decoder_function *dfun;
163*74fe6c29SRuslan Bukin 
164*74fe6c29SRuslan Bukin 	if (!decoder)
165*74fe6c29SRuslan Bukin 		return -pte_internal;
166*74fe6c29SRuslan Bukin 
167*74fe6c29SRuslan Bukin 	dfun = decoder->next;
168*74fe6c29SRuslan Bukin 	if (!dfun)
169*74fe6c29SRuslan Bukin 		return 0;
170*74fe6c29SRuslan Bukin 
171*74fe6c29SRuslan Bukin 	if (dfun->flags & pdff_event)
172*74fe6c29SRuslan Bukin 		return 1;
173*74fe6c29SRuslan Bukin 
174*74fe6c29SRuslan Bukin 	if (dfun->flags & pdff_psbend)
175*74fe6c29SRuslan Bukin 		return pt_evq_pending(&decoder->evq, evb_psbend);
176*74fe6c29SRuslan Bukin 
177*74fe6c29SRuslan Bukin 	if (dfun->flags & pdff_tip)
178*74fe6c29SRuslan Bukin 		return pt_evq_pending(&decoder->evq, evb_tip);
179*74fe6c29SRuslan Bukin 
180*74fe6c29SRuslan Bukin 	if (dfun->flags & pdff_fup)
181*74fe6c29SRuslan Bukin 		return pt_evq_pending(&decoder->evq, evb_fup);
182*74fe6c29SRuslan Bukin 
183*74fe6c29SRuslan Bukin 	return 0;
184*74fe6c29SRuslan Bukin }
185*74fe6c29SRuslan Bukin 
pt_qry_will_eos(const struct pt_query_decoder * decoder)186*74fe6c29SRuslan Bukin static int pt_qry_will_eos(const struct pt_query_decoder *decoder)
187*74fe6c29SRuslan Bukin {
188*74fe6c29SRuslan Bukin 	const struct pt_decoder_function *dfun;
189*74fe6c29SRuslan Bukin 	int errcode;
190*74fe6c29SRuslan Bukin 
191*74fe6c29SRuslan Bukin 	if (!decoder)
192*74fe6c29SRuslan Bukin 		return -pte_internal;
193*74fe6c29SRuslan Bukin 
194*74fe6c29SRuslan Bukin 	dfun = decoder->next;
195*74fe6c29SRuslan Bukin 	if (dfun)
196*74fe6c29SRuslan Bukin 		return 0;
197*74fe6c29SRuslan Bukin 
198*74fe6c29SRuslan Bukin 	/* The decoding function may be NULL for two reasons:
199*74fe6c29SRuslan Bukin 	 *
200*74fe6c29SRuslan Bukin 	 *   - we ran out of trace
201*74fe6c29SRuslan Bukin 	 *   - we ran into a fetch error such as -pte_bad_opc
202*74fe6c29SRuslan Bukin 	 *
203*74fe6c29SRuslan Bukin 	 * Let's fetch again.
204*74fe6c29SRuslan Bukin 	 */
205*74fe6c29SRuslan Bukin 	errcode = pt_df_fetch(&dfun, decoder->pos, &decoder->config);
206*74fe6c29SRuslan Bukin 	return errcode == -pte_eos;
207*74fe6c29SRuslan Bukin }
208*74fe6c29SRuslan Bukin 
pt_qry_status_flags(const struct pt_query_decoder * decoder)209*74fe6c29SRuslan Bukin static int pt_qry_status_flags(const struct pt_query_decoder *decoder)
210*74fe6c29SRuslan Bukin {
211*74fe6c29SRuslan Bukin 	int flags = 0;
212*74fe6c29SRuslan Bukin 
213*74fe6c29SRuslan Bukin 	if (!decoder)
214*74fe6c29SRuslan Bukin 		return -pte_internal;
215*74fe6c29SRuslan Bukin 
216*74fe6c29SRuslan Bukin 	/* Some packets force out TNT and any deferred TIPs in order to
217*74fe6c29SRuslan Bukin 	 * establish the correct context for the subsequent packet.
218*74fe6c29SRuslan Bukin 	 *
219*74fe6c29SRuslan Bukin 	 * Users are expected to first navigate to the correct code region
220*74fe6c29SRuslan Bukin 	 * by using up the cached TNT bits before interpreting any subsequent
221*74fe6c29SRuslan Bukin 	 * packets.
222*74fe6c29SRuslan Bukin 	 *
223*74fe6c29SRuslan Bukin 	 * We do need to read ahead in order to signal upcoming events.  We may
224*74fe6c29SRuslan Bukin 	 * have already decoded those packets while our user has not navigated
225*74fe6c29SRuslan Bukin 	 * to the correct code region, yet.
226*74fe6c29SRuslan Bukin 	 *
227*74fe6c29SRuslan Bukin 	 * In order to have our user use up the cached TNT bits first, we do
228*74fe6c29SRuslan Bukin 	 * not indicate the next event until the TNT cache is empty.
229*74fe6c29SRuslan Bukin 	 */
230*74fe6c29SRuslan Bukin 	if (pt_tnt_cache_is_empty(&decoder->tnt)) {
231*74fe6c29SRuslan Bukin 		if (pt_qry_will_event(decoder))
232*74fe6c29SRuslan Bukin 			flags |= pts_event_pending;
233*74fe6c29SRuslan Bukin 
234*74fe6c29SRuslan Bukin 		if (pt_qry_will_eos(decoder))
235*74fe6c29SRuslan Bukin 			flags |= pts_eos;
236*74fe6c29SRuslan Bukin 	}
237*74fe6c29SRuslan Bukin 
238*74fe6c29SRuslan Bukin 	return flags;
239*74fe6c29SRuslan Bukin }
240*74fe6c29SRuslan Bukin 
pt_qry_provoke_fetch_error(const struct pt_query_decoder * decoder)241*74fe6c29SRuslan Bukin static int pt_qry_provoke_fetch_error(const struct pt_query_decoder *decoder)
242*74fe6c29SRuslan Bukin {
243*74fe6c29SRuslan Bukin 	const struct pt_decoder_function *dfun;
244*74fe6c29SRuslan Bukin 	int errcode;
245*74fe6c29SRuslan Bukin 
246*74fe6c29SRuslan Bukin 	if (!decoder)
247*74fe6c29SRuslan Bukin 		return -pte_internal;
248*74fe6c29SRuslan Bukin 
249*74fe6c29SRuslan Bukin 	/* Repeat the decoder fetch to reproduce the error. */
250*74fe6c29SRuslan Bukin 	errcode = pt_df_fetch(&dfun, decoder->pos, &decoder->config);
251*74fe6c29SRuslan Bukin 	if (errcode < 0)
252*74fe6c29SRuslan Bukin 		return errcode;
253*74fe6c29SRuslan Bukin 
254*74fe6c29SRuslan Bukin 	/* We must get some error or something's wrong. */
255*74fe6c29SRuslan Bukin 	return -pte_internal;
256*74fe6c29SRuslan Bukin }
257*74fe6c29SRuslan Bukin 
pt_qry_read_ahead(struct pt_query_decoder * decoder)258*74fe6c29SRuslan Bukin static int pt_qry_read_ahead(struct pt_query_decoder *decoder)
259*74fe6c29SRuslan Bukin {
260*74fe6c29SRuslan Bukin 	if (!decoder)
261*74fe6c29SRuslan Bukin 		return -pte_internal;
262*74fe6c29SRuslan Bukin 
263*74fe6c29SRuslan Bukin 	for (;;) {
264*74fe6c29SRuslan Bukin 		const struct pt_decoder_function *dfun;
265*74fe6c29SRuslan Bukin 		int errcode;
266*74fe6c29SRuslan Bukin 
267*74fe6c29SRuslan Bukin 		errcode = pt_df_fetch(&decoder->next, decoder->pos,
268*74fe6c29SRuslan Bukin 				      &decoder->config);
269*74fe6c29SRuslan Bukin 		if (errcode)
270*74fe6c29SRuslan Bukin 			return errcode;
271*74fe6c29SRuslan Bukin 
272*74fe6c29SRuslan Bukin 		dfun = decoder->next;
273*74fe6c29SRuslan Bukin 		if (!dfun)
274*74fe6c29SRuslan Bukin 			return -pte_internal;
275*74fe6c29SRuslan Bukin 
276*74fe6c29SRuslan Bukin 		if (!dfun->decode)
277*74fe6c29SRuslan Bukin 			return -pte_internal;
278*74fe6c29SRuslan Bukin 
279*74fe6c29SRuslan Bukin 		/* We're done once we reach
280*74fe6c29SRuslan Bukin 		 *
281*74fe6c29SRuslan Bukin 		 * - a branching related packet. */
282*74fe6c29SRuslan Bukin 		if (dfun->flags & (pdff_tip | pdff_tnt))
283*74fe6c29SRuslan Bukin 			return 0;
284*74fe6c29SRuslan Bukin 
285*74fe6c29SRuslan Bukin 		/* - an event related packet. */
286*74fe6c29SRuslan Bukin 		if (pt_qry_will_event(decoder))
287*74fe6c29SRuslan Bukin 			return 0;
288*74fe6c29SRuslan Bukin 
289*74fe6c29SRuslan Bukin 		/* Decode status update packets. */
290*74fe6c29SRuslan Bukin 		errcode = dfun->decode(decoder);
291*74fe6c29SRuslan Bukin 		if (errcode) {
292*74fe6c29SRuslan Bukin 			/* Ignore truncated status packets at the end.
293*74fe6c29SRuslan Bukin 			 *
294*74fe6c29SRuslan Bukin 			 * Move beyond the packet and clear @decoder->next to
295*74fe6c29SRuslan Bukin 			 * indicate that we were not able to fetch the next
296*74fe6c29SRuslan Bukin 			 * packet.
297*74fe6c29SRuslan Bukin 			 */
298*74fe6c29SRuslan Bukin 			if (errcode == -pte_eos) {
299*74fe6c29SRuslan Bukin 				decoder->pos = decoder->config.end;
300*74fe6c29SRuslan Bukin 				decoder->next = NULL;
301*74fe6c29SRuslan Bukin 			}
302*74fe6c29SRuslan Bukin 
303*74fe6c29SRuslan Bukin 			return errcode;
304*74fe6c29SRuslan Bukin 		}
305*74fe6c29SRuslan Bukin 	}
306*74fe6c29SRuslan Bukin }
307*74fe6c29SRuslan Bukin 
pt_qry_start(struct pt_query_decoder * decoder,const uint8_t * pos,uint64_t * addr)308*74fe6c29SRuslan Bukin static int pt_qry_start(struct pt_query_decoder *decoder, const uint8_t *pos,
309*74fe6c29SRuslan Bukin 			uint64_t *addr)
310*74fe6c29SRuslan Bukin {
311*74fe6c29SRuslan Bukin 	const struct pt_decoder_function *dfun;
312*74fe6c29SRuslan Bukin 	int status, errcode;
313*74fe6c29SRuslan Bukin 
314*74fe6c29SRuslan Bukin 	if (!decoder || !pos)
315*74fe6c29SRuslan Bukin 		return -pte_invalid;
316*74fe6c29SRuslan Bukin 
317*74fe6c29SRuslan Bukin 	pt_qry_reset(decoder);
318*74fe6c29SRuslan Bukin 
319*74fe6c29SRuslan Bukin 	decoder->sync = pos;
320*74fe6c29SRuslan Bukin 	decoder->pos = pos;
321*74fe6c29SRuslan Bukin 
322*74fe6c29SRuslan Bukin 	errcode = pt_df_fetch(&decoder->next, pos, &decoder->config);
323*74fe6c29SRuslan Bukin 	if (errcode)
324*74fe6c29SRuslan Bukin 		return errcode;
325*74fe6c29SRuslan Bukin 
326*74fe6c29SRuslan Bukin 	dfun = decoder->next;
327*74fe6c29SRuslan Bukin 
328*74fe6c29SRuslan Bukin 	/* We do need to start at a PSB in order to initialize the state. */
329*74fe6c29SRuslan Bukin 	if (dfun != &pt_decode_psb)
330*74fe6c29SRuslan Bukin 		return -pte_nosync;
331*74fe6c29SRuslan Bukin 
332*74fe6c29SRuslan Bukin 	/* Decode the PSB+ header to initialize the state. */
333*74fe6c29SRuslan Bukin 	errcode = dfun->decode(decoder);
334*74fe6c29SRuslan Bukin 	if (errcode < 0)
335*74fe6c29SRuslan Bukin 		return errcode;
336*74fe6c29SRuslan Bukin 
337*74fe6c29SRuslan Bukin 	/* Fill in the start address.
338*74fe6c29SRuslan Bukin 	 * We do this before reading ahead since the latter may read an
339*74fe6c29SRuslan Bukin 	 * adjacent PSB+ that might change the decoder's IP, causing us
340*74fe6c29SRuslan Bukin 	 * to skip code.
341*74fe6c29SRuslan Bukin 	 */
342*74fe6c29SRuslan Bukin 	if (addr) {
343*74fe6c29SRuslan Bukin 		status = pt_last_ip_query(addr, &decoder->ip);
344*74fe6c29SRuslan Bukin 
345*74fe6c29SRuslan Bukin 		/* Make sure we don't clobber it later on. */
346*74fe6c29SRuslan Bukin 		if (!status)
347*74fe6c29SRuslan Bukin 			addr = NULL;
348*74fe6c29SRuslan Bukin 	}
349*74fe6c29SRuslan Bukin 
350*74fe6c29SRuslan Bukin 	/* Read ahead until the first query-relevant packet. */
351*74fe6c29SRuslan Bukin 	errcode = pt_qry_read_ahead(decoder);
352*74fe6c29SRuslan Bukin 	if (errcode < 0)
353*74fe6c29SRuslan Bukin 		return errcode;
354*74fe6c29SRuslan Bukin 
355*74fe6c29SRuslan Bukin 	/* We return the current decoder status. */
356*74fe6c29SRuslan Bukin 	status = pt_qry_status_flags(decoder);
357*74fe6c29SRuslan Bukin 	if (status < 0)
358*74fe6c29SRuslan Bukin 		return status;
359*74fe6c29SRuslan Bukin 
360*74fe6c29SRuslan Bukin 	errcode = pt_last_ip_query(addr, &decoder->ip);
361*74fe6c29SRuslan Bukin 	if (errcode < 0) {
362*74fe6c29SRuslan Bukin 		/* Indicate the missing IP in the status. */
363*74fe6c29SRuslan Bukin 		if (addr)
364*74fe6c29SRuslan Bukin 			status |= pts_ip_suppressed;
365*74fe6c29SRuslan Bukin 	}
366*74fe6c29SRuslan Bukin 
367*74fe6c29SRuslan Bukin 	return status;
368*74fe6c29SRuslan Bukin }
369*74fe6c29SRuslan Bukin 
pt_qry_apply_tsc(struct pt_time * time,struct pt_time_cal * tcal,const struct pt_packet_tsc * packet,const struct pt_config * config)370*74fe6c29SRuslan Bukin static int pt_qry_apply_tsc(struct pt_time *time, struct pt_time_cal *tcal,
371*74fe6c29SRuslan Bukin 			    const struct pt_packet_tsc *packet,
372*74fe6c29SRuslan Bukin 			    const struct pt_config *config)
373*74fe6c29SRuslan Bukin {
374*74fe6c29SRuslan Bukin 	int errcode;
375*74fe6c29SRuslan Bukin 
376*74fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
377*74fe6c29SRuslan Bukin 	 * calibration which will result in imprecise cycle-accurate timing.
378*74fe6c29SRuslan Bukin 	 *
379*74fe6c29SRuslan Bukin 	 * We currently do not track them.
380*74fe6c29SRuslan Bukin 	 */
381*74fe6c29SRuslan Bukin 	errcode = pt_tcal_update_tsc(tcal, packet, config);
382*74fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
383*74fe6c29SRuslan Bukin 		return errcode;
384*74fe6c29SRuslan Bukin 
385*74fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
386*74fe6c29SRuslan Bukin 	 * timing and are tracked as packet losses in struct pt_time.
387*74fe6c29SRuslan Bukin 	 */
388*74fe6c29SRuslan Bukin 	errcode = pt_time_update_tsc(time, packet, config);
389*74fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
390*74fe6c29SRuslan Bukin 		return errcode;
391*74fe6c29SRuslan Bukin 
392*74fe6c29SRuslan Bukin 	return 0;
393*74fe6c29SRuslan Bukin }
394*74fe6c29SRuslan Bukin 
pt_qry_apply_header_tsc(struct pt_time * time,struct pt_time_cal * tcal,const struct pt_packet_tsc * packet,const struct pt_config * config)395*74fe6c29SRuslan Bukin static int pt_qry_apply_header_tsc(struct pt_time *time,
396*74fe6c29SRuslan Bukin 				   struct pt_time_cal *tcal,
397*74fe6c29SRuslan Bukin 				   const struct pt_packet_tsc *packet,
398*74fe6c29SRuslan Bukin 				   const struct pt_config *config)
399*74fe6c29SRuslan Bukin {
400*74fe6c29SRuslan Bukin 	int errcode;
401*74fe6c29SRuslan Bukin 
402*74fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
403*74fe6c29SRuslan Bukin 	 * calibration which will result in imprecise cycle-accurate timing.
404*74fe6c29SRuslan Bukin 	 *
405*74fe6c29SRuslan Bukin 	 * We currently do not track them.
406*74fe6c29SRuslan Bukin 	 */
407*74fe6c29SRuslan Bukin 	errcode = pt_tcal_header_tsc(tcal, packet, config);
408*74fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
409*74fe6c29SRuslan Bukin 		return errcode;
410*74fe6c29SRuslan Bukin 
411*74fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
412*74fe6c29SRuslan Bukin 	 * timing and are tracked as packet losses in struct pt_time.
413*74fe6c29SRuslan Bukin 	 */
414*74fe6c29SRuslan Bukin 	errcode = pt_time_update_tsc(time, packet, config);
415*74fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
416*74fe6c29SRuslan Bukin 		return errcode;
417*74fe6c29SRuslan Bukin 
418*74fe6c29SRuslan Bukin 	return 0;
419*74fe6c29SRuslan Bukin }
420*74fe6c29SRuslan Bukin 
pt_qry_apply_cbr(struct pt_time * time,struct pt_time_cal * tcal,const struct pt_packet_cbr * packet,const struct pt_config * config)421*74fe6c29SRuslan Bukin static int pt_qry_apply_cbr(struct pt_time *time, struct pt_time_cal *tcal,
422*74fe6c29SRuslan Bukin 			    const struct pt_packet_cbr *packet,
423*74fe6c29SRuslan Bukin 			    const struct pt_config *config)
424*74fe6c29SRuslan Bukin {
425*74fe6c29SRuslan Bukin 	int errcode;
426*74fe6c29SRuslan Bukin 
427*74fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
428*74fe6c29SRuslan Bukin 	 * calibration which will result in imprecise cycle-accurate timing.
429*74fe6c29SRuslan Bukin 	 *
430*74fe6c29SRuslan Bukin 	 * We currently do not track them.
431*74fe6c29SRuslan Bukin 	 */
432*74fe6c29SRuslan Bukin 	errcode = pt_tcal_update_cbr(tcal, packet, config);
433*74fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
434*74fe6c29SRuslan Bukin 		return errcode;
435*74fe6c29SRuslan Bukin 
436*74fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
437*74fe6c29SRuslan Bukin 	 * timing and are tracked as packet losses in struct pt_time.
438*74fe6c29SRuslan Bukin 	 */
439*74fe6c29SRuslan Bukin 	errcode = pt_time_update_cbr(time, packet, config);
440*74fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
441*74fe6c29SRuslan Bukin 		return errcode;
442*74fe6c29SRuslan Bukin 
443*74fe6c29SRuslan Bukin 	return 0;
444*74fe6c29SRuslan Bukin }
445*74fe6c29SRuslan Bukin 
pt_qry_apply_header_cbr(struct pt_time * time,struct pt_time_cal * tcal,const struct pt_packet_cbr * packet,const struct pt_config * config)446*74fe6c29SRuslan Bukin static int pt_qry_apply_header_cbr(struct pt_time *time,
447*74fe6c29SRuslan Bukin 				   struct pt_time_cal *tcal,
448*74fe6c29SRuslan Bukin 				   const struct pt_packet_cbr *packet,
449*74fe6c29SRuslan Bukin 				   const struct pt_config *config)
450*74fe6c29SRuslan Bukin {
451*74fe6c29SRuslan Bukin 	int errcode;
452*74fe6c29SRuslan Bukin 
453*74fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
454*74fe6c29SRuslan Bukin 	 * calibration which will result in imprecise cycle-accurate timing.
455*74fe6c29SRuslan Bukin 	 *
456*74fe6c29SRuslan Bukin 	 * We currently do not track them.
457*74fe6c29SRuslan Bukin 	 */
458*74fe6c29SRuslan Bukin 	errcode = pt_tcal_header_cbr(tcal, packet, config);
459*74fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
460*74fe6c29SRuslan Bukin 		return errcode;
461*74fe6c29SRuslan Bukin 
462*74fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
463*74fe6c29SRuslan Bukin 	 * timing and are tracked as packet losses in struct pt_time.
464*74fe6c29SRuslan Bukin 	 */
465*74fe6c29SRuslan Bukin 	errcode = pt_time_update_cbr(time, packet, config);
466*74fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
467*74fe6c29SRuslan Bukin 		return errcode;
468*74fe6c29SRuslan Bukin 
469*74fe6c29SRuslan Bukin 	return 0;
470*74fe6c29SRuslan Bukin }
471*74fe6c29SRuslan Bukin 
pt_qry_apply_tma(struct pt_time * time,struct pt_time_cal * tcal,const struct pt_packet_tma * packet,const struct pt_config * config)472*74fe6c29SRuslan Bukin static int pt_qry_apply_tma(struct pt_time *time, struct pt_time_cal *tcal,
473*74fe6c29SRuslan Bukin 			    const struct pt_packet_tma *packet,
474*74fe6c29SRuslan Bukin 			    const struct pt_config *config)
475*74fe6c29SRuslan Bukin {
476*74fe6c29SRuslan Bukin 	int errcode;
477*74fe6c29SRuslan Bukin 
478*74fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
479*74fe6c29SRuslan Bukin 	 * calibration which will result in imprecise cycle-accurate timing.
480*74fe6c29SRuslan Bukin 	 *
481*74fe6c29SRuslan Bukin 	 * We currently do not track them.
482*74fe6c29SRuslan Bukin 	 */
483*74fe6c29SRuslan Bukin 	errcode = pt_tcal_update_tma(tcal, packet, config);
484*74fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
485*74fe6c29SRuslan Bukin 		return errcode;
486*74fe6c29SRuslan Bukin 
487*74fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
488*74fe6c29SRuslan Bukin 	 * timing and are tracked as packet losses in struct pt_time.
489*74fe6c29SRuslan Bukin 	 */
490*74fe6c29SRuslan Bukin 	errcode = pt_time_update_tma(time, packet, config);
491*74fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
492*74fe6c29SRuslan Bukin 		return errcode;
493*74fe6c29SRuslan Bukin 
494*74fe6c29SRuslan Bukin 	return 0;
495*74fe6c29SRuslan Bukin }
496*74fe6c29SRuslan Bukin 
pt_qry_apply_mtc(struct pt_time * time,struct pt_time_cal * tcal,const struct pt_packet_mtc * packet,const struct pt_config * config)497*74fe6c29SRuslan Bukin static int pt_qry_apply_mtc(struct pt_time *time, struct pt_time_cal *tcal,
498*74fe6c29SRuslan Bukin 			    const struct pt_packet_mtc *packet,
499*74fe6c29SRuslan Bukin 			    const struct pt_config *config)
500*74fe6c29SRuslan Bukin {
501*74fe6c29SRuslan Bukin 	int errcode;
502*74fe6c29SRuslan Bukin 
503*74fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
504*74fe6c29SRuslan Bukin 	 * calibration which will result in imprecise cycle-accurate timing.
505*74fe6c29SRuslan Bukin 	 *
506*74fe6c29SRuslan Bukin 	 * We currently do not track them.
507*74fe6c29SRuslan Bukin 	 */
508*74fe6c29SRuslan Bukin 	errcode = pt_tcal_update_mtc(tcal, packet, config);
509*74fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
510*74fe6c29SRuslan Bukin 		return errcode;
511*74fe6c29SRuslan Bukin 
512*74fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
513*74fe6c29SRuslan Bukin 	 * timing and are tracked as packet losses in struct pt_time.
514*74fe6c29SRuslan Bukin 	 */
515*74fe6c29SRuslan Bukin 	errcode = pt_time_update_mtc(time, packet, config);
516*74fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
517*74fe6c29SRuslan Bukin 		return errcode;
518*74fe6c29SRuslan Bukin 
519*74fe6c29SRuslan Bukin 	return 0;
520*74fe6c29SRuslan Bukin }
521*74fe6c29SRuslan Bukin 
pt_qry_apply_cyc(struct pt_time * time,struct pt_time_cal * tcal,const struct pt_packet_cyc * packet,const struct pt_config * config)522*74fe6c29SRuslan Bukin static int pt_qry_apply_cyc(struct pt_time *time, struct pt_time_cal *tcal,
523*74fe6c29SRuslan Bukin 			    const struct pt_packet_cyc *packet,
524*74fe6c29SRuslan Bukin 			    const struct pt_config *config)
525*74fe6c29SRuslan Bukin {
526*74fe6c29SRuslan Bukin 	uint64_t fcr;
527*74fe6c29SRuslan Bukin 	int errcode;
528*74fe6c29SRuslan Bukin 
529*74fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
530*74fe6c29SRuslan Bukin 	 * calibration which will result in imprecise cycle-accurate timing.
531*74fe6c29SRuslan Bukin 	 *
532*74fe6c29SRuslan Bukin 	 * We currently do not track them.
533*74fe6c29SRuslan Bukin 	 */
534*74fe6c29SRuslan Bukin 	errcode = pt_tcal_update_cyc(tcal, packet, config);
535*74fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
536*74fe6c29SRuslan Bukin 		return errcode;
537*74fe6c29SRuslan Bukin 
538*74fe6c29SRuslan Bukin 	/* We need the FastCounter to Cycles ratio below.  Fall back to
539*74fe6c29SRuslan Bukin 	 * an invalid ratio of 0 if calibration has not kicked in, yet.
540*74fe6c29SRuslan Bukin 	 *
541*74fe6c29SRuslan Bukin 	 * This will be tracked as packet loss in struct pt_time.
542*74fe6c29SRuslan Bukin 	 */
543*74fe6c29SRuslan Bukin 	errcode = pt_tcal_fcr(&fcr, tcal);
544*74fe6c29SRuslan Bukin 	if (errcode < 0) {
545*74fe6c29SRuslan Bukin 		if (errcode == -pte_no_time)
546*74fe6c29SRuslan Bukin 			fcr = 0ull;
547*74fe6c29SRuslan Bukin 		else
548*74fe6c29SRuslan Bukin 			return errcode;
549*74fe6c29SRuslan Bukin 	}
550*74fe6c29SRuslan Bukin 
551*74fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
552*74fe6c29SRuslan Bukin 	 * timing and are tracked as packet losses in struct pt_time.
553*74fe6c29SRuslan Bukin 	 */
554*74fe6c29SRuslan Bukin 	errcode = pt_time_update_cyc(time, packet, config, fcr);
555*74fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
556*74fe6c29SRuslan Bukin 		return errcode;
557*74fe6c29SRuslan Bukin 
558*74fe6c29SRuslan Bukin 	return 0;
559*74fe6c29SRuslan Bukin }
560*74fe6c29SRuslan Bukin 
pt_qry_sync_forward(struct pt_query_decoder * decoder,uint64_t * ip)561*74fe6c29SRuslan Bukin int pt_qry_sync_forward(struct pt_query_decoder *decoder, uint64_t *ip)
562*74fe6c29SRuslan Bukin {
563*74fe6c29SRuslan Bukin 	const uint8_t *pos, *sync;
564*74fe6c29SRuslan Bukin 	int errcode;
565*74fe6c29SRuslan Bukin 
566*74fe6c29SRuslan Bukin 	if (!decoder)
567*74fe6c29SRuslan Bukin 		return -pte_invalid;
568*74fe6c29SRuslan Bukin 
569*74fe6c29SRuslan Bukin 	sync = decoder->sync;
570*74fe6c29SRuslan Bukin 	pos = decoder->pos;
571*74fe6c29SRuslan Bukin 	if (!pos)
572*74fe6c29SRuslan Bukin 		pos = decoder->config.begin;
573*74fe6c29SRuslan Bukin 
574*74fe6c29SRuslan Bukin 	if (pos == sync)
575*74fe6c29SRuslan Bukin 		pos += ptps_psb;
576*74fe6c29SRuslan Bukin 
577*74fe6c29SRuslan Bukin 	errcode = pt_sync_forward(&sync, pos, &decoder->config);
578*74fe6c29SRuslan Bukin 	if (errcode < 0)
579*74fe6c29SRuslan Bukin 		return errcode;
580*74fe6c29SRuslan Bukin 
581*74fe6c29SRuslan Bukin 	return pt_qry_start(decoder, sync, ip);
582*74fe6c29SRuslan Bukin }
583*74fe6c29SRuslan Bukin 
pt_qry_sync_backward(struct pt_query_decoder * decoder,uint64_t * ip)584*74fe6c29SRuslan Bukin int pt_qry_sync_backward(struct pt_query_decoder *decoder, uint64_t *ip)
585*74fe6c29SRuslan Bukin {
586*74fe6c29SRuslan Bukin 	const uint8_t *start, *sync;
587*74fe6c29SRuslan Bukin 	int errcode;
588*74fe6c29SRuslan Bukin 
589*74fe6c29SRuslan Bukin 	if (!decoder)
590*74fe6c29SRuslan Bukin 		return -pte_invalid;
591*74fe6c29SRuslan Bukin 
592*74fe6c29SRuslan Bukin 	start = decoder->pos;
593*74fe6c29SRuslan Bukin 	if (!start)
594*74fe6c29SRuslan Bukin 		start = decoder->config.end;
595*74fe6c29SRuslan Bukin 
596*74fe6c29SRuslan Bukin 	sync = start;
597*74fe6c29SRuslan Bukin 	for (;;) {
598*74fe6c29SRuslan Bukin 		errcode = pt_sync_backward(&sync, sync, &decoder->config);
599*74fe6c29SRuslan Bukin 		if (errcode < 0)
600*74fe6c29SRuslan Bukin 			return errcode;
601*74fe6c29SRuslan Bukin 
602*74fe6c29SRuslan Bukin 		errcode = pt_qry_start(decoder, sync, ip);
603*74fe6c29SRuslan Bukin 		if (errcode < 0) {
604*74fe6c29SRuslan Bukin 			/* Ignore incomplete trace segments at the end.  We need
605*74fe6c29SRuslan Bukin 			 * a full PSB+ to start decoding.
606*74fe6c29SRuslan Bukin 			 */
607*74fe6c29SRuslan Bukin 			if (errcode == -pte_eos)
608*74fe6c29SRuslan Bukin 				continue;
609*74fe6c29SRuslan Bukin 
610*74fe6c29SRuslan Bukin 			return errcode;
611*74fe6c29SRuslan Bukin 		}
612*74fe6c29SRuslan Bukin 
613*74fe6c29SRuslan Bukin 		/* An empty trace segment in the middle of the trace might bring
614*74fe6c29SRuslan Bukin 		 * us back to where we started.
615*74fe6c29SRuslan Bukin 		 *
616*74fe6c29SRuslan Bukin 		 * We're done when we reached a new position.
617*74fe6c29SRuslan Bukin 		 */
618*74fe6c29SRuslan Bukin 		if (decoder->pos != start)
619*74fe6c29SRuslan Bukin 			break;
620*74fe6c29SRuslan Bukin 	}
621*74fe6c29SRuslan Bukin 
622*74fe6c29SRuslan Bukin 	return 0;
623*74fe6c29SRuslan Bukin }
624*74fe6c29SRuslan Bukin 
pt_qry_sync_set(struct pt_query_decoder * decoder,uint64_t * ip,uint64_t offset)625*74fe6c29SRuslan Bukin int pt_qry_sync_set(struct pt_query_decoder *decoder, uint64_t *ip,
626*74fe6c29SRuslan Bukin 		    uint64_t offset)
627*74fe6c29SRuslan Bukin {
628*74fe6c29SRuslan Bukin 	const uint8_t *sync, *pos;
629*74fe6c29SRuslan Bukin 	int errcode;
630*74fe6c29SRuslan Bukin 
631*74fe6c29SRuslan Bukin 	if (!decoder)
632*74fe6c29SRuslan Bukin 		return -pte_invalid;
633*74fe6c29SRuslan Bukin 
634*74fe6c29SRuslan Bukin 	pos = decoder->config.begin + offset;
635*74fe6c29SRuslan Bukin 
636*74fe6c29SRuslan Bukin 	errcode = pt_sync_set(&sync, pos, &decoder->config);
637*74fe6c29SRuslan Bukin 	if (errcode < 0)
638*74fe6c29SRuslan Bukin 		return errcode;
639*74fe6c29SRuslan Bukin 
640*74fe6c29SRuslan Bukin 	return pt_qry_start(decoder, sync, ip);
641*74fe6c29SRuslan Bukin }
642*74fe6c29SRuslan Bukin 
pt_qry_get_offset(const struct pt_query_decoder * decoder,uint64_t * offset)643*74fe6c29SRuslan Bukin int pt_qry_get_offset(const struct pt_query_decoder *decoder, uint64_t *offset)
644*74fe6c29SRuslan Bukin {
645*74fe6c29SRuslan Bukin 	const uint8_t *begin, *pos;
646*74fe6c29SRuslan Bukin 
647*74fe6c29SRuslan Bukin 	if (!decoder || !offset)
648*74fe6c29SRuslan Bukin 		return -pte_invalid;
649*74fe6c29SRuslan Bukin 
650*74fe6c29SRuslan Bukin 	begin = decoder->config.begin;
651*74fe6c29SRuslan Bukin 	pos = decoder->pos;
652*74fe6c29SRuslan Bukin 
653*74fe6c29SRuslan Bukin 	if (!pos)
654*74fe6c29SRuslan Bukin 		return -pte_nosync;
655*74fe6c29SRuslan Bukin 
656*74fe6c29SRuslan Bukin 	*offset = pos - begin;
657*74fe6c29SRuslan Bukin 	return 0;
658*74fe6c29SRuslan Bukin }
659*74fe6c29SRuslan Bukin 
pt_qry_get_sync_offset(const struct pt_query_decoder * decoder,uint64_t * offset)660*74fe6c29SRuslan Bukin int pt_qry_get_sync_offset(const struct pt_query_decoder *decoder,
661*74fe6c29SRuslan Bukin 			   uint64_t *offset)
662*74fe6c29SRuslan Bukin {
663*74fe6c29SRuslan Bukin 	const uint8_t *begin, *sync;
664*74fe6c29SRuslan Bukin 
665*74fe6c29SRuslan Bukin 	if (!decoder || !offset)
666*74fe6c29SRuslan Bukin 		return -pte_invalid;
667*74fe6c29SRuslan Bukin 
668*74fe6c29SRuslan Bukin 	begin = decoder->config.begin;
669*74fe6c29SRuslan Bukin 	sync = decoder->sync;
670*74fe6c29SRuslan Bukin 
671*74fe6c29SRuslan Bukin 	if (!sync)
672*74fe6c29SRuslan Bukin 		return -pte_nosync;
673*74fe6c29SRuslan Bukin 
674*74fe6c29SRuslan Bukin 	*offset = sync - begin;
675*74fe6c29SRuslan Bukin 	return 0;
676*74fe6c29SRuslan Bukin }
677*74fe6c29SRuslan Bukin 
678*74fe6c29SRuslan Bukin const struct pt_config *
pt_qry_get_config(const struct pt_query_decoder * decoder)679*74fe6c29SRuslan Bukin pt_qry_get_config(const struct pt_query_decoder *decoder)
680*74fe6c29SRuslan Bukin {
681*74fe6c29SRuslan Bukin 	if (!decoder)
682*74fe6c29SRuslan Bukin 		return NULL;
683*74fe6c29SRuslan Bukin 
684*74fe6c29SRuslan Bukin 	return &decoder->config;
685*74fe6c29SRuslan Bukin }
686*74fe6c29SRuslan Bukin 
pt_qry_cache_tnt(struct pt_query_decoder * decoder)687*74fe6c29SRuslan Bukin static int pt_qry_cache_tnt(struct pt_query_decoder *decoder)
688*74fe6c29SRuslan Bukin {
689*74fe6c29SRuslan Bukin 	int errcode;
690*74fe6c29SRuslan Bukin 
691*74fe6c29SRuslan Bukin 	if (!decoder)
692*74fe6c29SRuslan Bukin 		return -pte_internal;
693*74fe6c29SRuslan Bukin 
694*74fe6c29SRuslan Bukin 	for (;;) {
695*74fe6c29SRuslan Bukin 		const struct pt_decoder_function *dfun;
696*74fe6c29SRuslan Bukin 
697*74fe6c29SRuslan Bukin 		dfun = decoder->next;
698*74fe6c29SRuslan Bukin 		if (!dfun)
699*74fe6c29SRuslan Bukin 			return pt_qry_provoke_fetch_error(decoder);
700*74fe6c29SRuslan Bukin 
701*74fe6c29SRuslan Bukin 		if (!dfun->decode)
702*74fe6c29SRuslan Bukin 			return -pte_internal;
703*74fe6c29SRuslan Bukin 
704*74fe6c29SRuslan Bukin 		/* There's an event ahead of us. */
705*74fe6c29SRuslan Bukin 		if (pt_qry_will_event(decoder))
706*74fe6c29SRuslan Bukin 			return -pte_bad_query;
707*74fe6c29SRuslan Bukin 
708*74fe6c29SRuslan Bukin 		/* Diagnose a TIP that has not been part of an event. */
709*74fe6c29SRuslan Bukin 		if (dfun->flags & pdff_tip)
710*74fe6c29SRuslan Bukin 			return -pte_bad_query;
711*74fe6c29SRuslan Bukin 
712*74fe6c29SRuslan Bukin 		/* Clear the decoder's current event so we know when we
713*74fe6c29SRuslan Bukin 		 * accidentally skipped an event.
714*74fe6c29SRuslan Bukin 		 */
715*74fe6c29SRuslan Bukin 		decoder->event = NULL;
716*74fe6c29SRuslan Bukin 
717*74fe6c29SRuslan Bukin 		/* Apply the decoder function. */
718*74fe6c29SRuslan Bukin 		errcode = dfun->decode(decoder);
719*74fe6c29SRuslan Bukin 		if (errcode)
720*74fe6c29SRuslan Bukin 			return errcode;
721*74fe6c29SRuslan Bukin 
722*74fe6c29SRuslan Bukin 		/* If we skipped an event, we're in trouble. */
723*74fe6c29SRuslan Bukin 		if (decoder->event)
724*74fe6c29SRuslan Bukin 			return -pte_event_ignored;
725*74fe6c29SRuslan Bukin 
726*74fe6c29SRuslan Bukin 		/* We're done when we decoded a TNT packet. */
727*74fe6c29SRuslan Bukin 		if (dfun->flags & pdff_tnt)
728*74fe6c29SRuslan Bukin 			break;
729*74fe6c29SRuslan Bukin 
730*74fe6c29SRuslan Bukin 		/* Read ahead until the next query-relevant packet. */
731*74fe6c29SRuslan Bukin 		errcode = pt_qry_read_ahead(decoder);
732*74fe6c29SRuslan Bukin 		if (errcode)
733*74fe6c29SRuslan Bukin 			return errcode;
734*74fe6c29SRuslan Bukin 	}
735*74fe6c29SRuslan Bukin 
736*74fe6c29SRuslan Bukin 	/* Preserve the time at the TNT packet. */
737*74fe6c29SRuslan Bukin 	decoder->last_time = decoder->time;
738*74fe6c29SRuslan Bukin 
739*74fe6c29SRuslan Bukin 	/* Read ahead until the next query-relevant packet. */
740*74fe6c29SRuslan Bukin 	errcode = pt_qry_read_ahead(decoder);
741*74fe6c29SRuslan Bukin 	if ((errcode < 0) && (errcode != -pte_eos))
742*74fe6c29SRuslan Bukin 		return errcode;
743*74fe6c29SRuslan Bukin 
744*74fe6c29SRuslan Bukin 	return 0;
745*74fe6c29SRuslan Bukin }
746*74fe6c29SRuslan Bukin 
pt_qry_cond_branch(struct pt_query_decoder * decoder,int * taken)747*74fe6c29SRuslan Bukin int pt_qry_cond_branch(struct pt_query_decoder *decoder, int *taken)
748*74fe6c29SRuslan Bukin {
749*74fe6c29SRuslan Bukin 	int errcode, query;
750*74fe6c29SRuslan Bukin 
751*74fe6c29SRuslan Bukin 	if (!decoder || !taken)
752*74fe6c29SRuslan Bukin 		return -pte_invalid;
753*74fe6c29SRuslan Bukin 
754*74fe6c29SRuslan Bukin 	/* We cache the latest tnt packet in the decoder. Let's re-fill the
755*74fe6c29SRuslan Bukin 	 * cache in case it is empty.
756*74fe6c29SRuslan Bukin 	 */
757*74fe6c29SRuslan Bukin 	if (pt_tnt_cache_is_empty(&decoder->tnt)) {
758*74fe6c29SRuslan Bukin 		errcode = pt_qry_cache_tnt(decoder);
759*74fe6c29SRuslan Bukin 		if (errcode < 0)
760*74fe6c29SRuslan Bukin 			return errcode;
761*74fe6c29SRuslan Bukin 	}
762*74fe6c29SRuslan Bukin 
763*74fe6c29SRuslan Bukin 	query = pt_tnt_cache_query(&decoder->tnt);
764*74fe6c29SRuslan Bukin 	if (query < 0)
765*74fe6c29SRuslan Bukin 		return query;
766*74fe6c29SRuslan Bukin 
767*74fe6c29SRuslan Bukin 	*taken = query;
768*74fe6c29SRuslan Bukin 
769*74fe6c29SRuslan Bukin 	return pt_qry_status_flags(decoder);
770*74fe6c29SRuslan Bukin }
771*74fe6c29SRuslan Bukin 
pt_qry_indirect_branch(struct pt_query_decoder * decoder,uint64_t * addr)772*74fe6c29SRuslan Bukin int pt_qry_indirect_branch(struct pt_query_decoder *decoder, uint64_t *addr)
773*74fe6c29SRuslan Bukin {
774*74fe6c29SRuslan Bukin 	int errcode, flags;
775*74fe6c29SRuslan Bukin 
776*74fe6c29SRuslan Bukin 	if (!decoder || !addr)
777*74fe6c29SRuslan Bukin 		return -pte_invalid;
778*74fe6c29SRuslan Bukin 
779*74fe6c29SRuslan Bukin 	flags = 0;
780*74fe6c29SRuslan Bukin 	for (;;) {
781*74fe6c29SRuslan Bukin 		const struct pt_decoder_function *dfun;
782*74fe6c29SRuslan Bukin 
783*74fe6c29SRuslan Bukin 		dfun = decoder->next;
784*74fe6c29SRuslan Bukin 		if (!dfun)
785*74fe6c29SRuslan Bukin 			return pt_qry_provoke_fetch_error(decoder);
786*74fe6c29SRuslan Bukin 
787*74fe6c29SRuslan Bukin 		if (!dfun->decode)
788*74fe6c29SRuslan Bukin 			return -pte_internal;
789*74fe6c29SRuslan Bukin 
790*74fe6c29SRuslan Bukin 		/* There's an event ahead of us. */
791*74fe6c29SRuslan Bukin 		if (pt_qry_will_event(decoder))
792*74fe6c29SRuslan Bukin 			return -pte_bad_query;
793*74fe6c29SRuslan Bukin 
794*74fe6c29SRuslan Bukin 		/* Clear the decoder's current event so we know when we
795*74fe6c29SRuslan Bukin 		 * accidentally skipped an event.
796*74fe6c29SRuslan Bukin 		 */
797*74fe6c29SRuslan Bukin 		decoder->event = NULL;
798*74fe6c29SRuslan Bukin 
799*74fe6c29SRuslan Bukin 		/* We may see a single TNT packet if the current tnt is empty.
800*74fe6c29SRuslan Bukin 		 *
801*74fe6c29SRuslan Bukin 		 * If we see a TNT while the current tnt is not empty, it means
802*74fe6c29SRuslan Bukin 		 * that our user got out of sync. Let's report no data and hope
803*74fe6c29SRuslan Bukin 		 * that our user is able to re-sync.
804*74fe6c29SRuslan Bukin 		 */
805*74fe6c29SRuslan Bukin 		if ((dfun->flags & pdff_tnt) &&
806*74fe6c29SRuslan Bukin 		    !pt_tnt_cache_is_empty(&decoder->tnt))
807*74fe6c29SRuslan Bukin 			return -pte_bad_query;
808*74fe6c29SRuslan Bukin 
809*74fe6c29SRuslan Bukin 		/* Apply the decoder function. */
810*74fe6c29SRuslan Bukin 		errcode = dfun->decode(decoder);
811*74fe6c29SRuslan Bukin 		if (errcode)
812*74fe6c29SRuslan Bukin 			return errcode;
813*74fe6c29SRuslan Bukin 
814*74fe6c29SRuslan Bukin 		/* If we skipped an event, we're in trouble. */
815*74fe6c29SRuslan Bukin 		if (decoder->event)
816*74fe6c29SRuslan Bukin 			return -pte_event_ignored;
817*74fe6c29SRuslan Bukin 
818*74fe6c29SRuslan Bukin 		/* We're done when we found a TIP packet that isn't part of an
819*74fe6c29SRuslan Bukin 		 * event.
820*74fe6c29SRuslan Bukin 		 */
821*74fe6c29SRuslan Bukin 		if (dfun->flags & pdff_tip) {
822*74fe6c29SRuslan Bukin 			uint64_t ip;
823*74fe6c29SRuslan Bukin 
824*74fe6c29SRuslan Bukin 			/* We already decoded it, so the branch destination
825*74fe6c29SRuslan Bukin 			 * is stored in the decoder's last ip.
826*74fe6c29SRuslan Bukin 			 */
827*74fe6c29SRuslan Bukin 			errcode = pt_last_ip_query(&ip, &decoder->ip);
828*74fe6c29SRuslan Bukin 			if (errcode < 0)
829*74fe6c29SRuslan Bukin 				flags |= pts_ip_suppressed;
830*74fe6c29SRuslan Bukin 			else
831*74fe6c29SRuslan Bukin 				*addr = ip;
832*74fe6c29SRuslan Bukin 
833*74fe6c29SRuslan Bukin 			break;
834*74fe6c29SRuslan Bukin 		}
835*74fe6c29SRuslan Bukin 
836*74fe6c29SRuslan Bukin 		/* Read ahead until the next query-relevant packet. */
837*74fe6c29SRuslan Bukin 		errcode = pt_qry_read_ahead(decoder);
838*74fe6c29SRuslan Bukin 		if (errcode)
839*74fe6c29SRuslan Bukin 			return errcode;
840*74fe6c29SRuslan Bukin 	}
841*74fe6c29SRuslan Bukin 
842*74fe6c29SRuslan Bukin 	/* Preserve the time at the TIP packet. */
843*74fe6c29SRuslan Bukin 	decoder->last_time = decoder->time;
844*74fe6c29SRuslan Bukin 
845*74fe6c29SRuslan Bukin 	/* Read ahead until the next query-relevant packet. */
846*74fe6c29SRuslan Bukin 	errcode = pt_qry_read_ahead(decoder);
847*74fe6c29SRuslan Bukin 	if ((errcode < 0) && (errcode != -pte_eos))
848*74fe6c29SRuslan Bukin 		return errcode;
849*74fe6c29SRuslan Bukin 
850*74fe6c29SRuslan Bukin 	flags |= pt_qry_status_flags(decoder);
851*74fe6c29SRuslan Bukin 
852*74fe6c29SRuslan Bukin 	return flags;
853*74fe6c29SRuslan Bukin }
854*74fe6c29SRuslan Bukin 
pt_qry_event(struct pt_query_decoder * decoder,struct pt_event * event,size_t size)855*74fe6c29SRuslan Bukin int pt_qry_event(struct pt_query_decoder *decoder, struct pt_event *event,
856*74fe6c29SRuslan Bukin 		 size_t size)
857*74fe6c29SRuslan Bukin {
858*74fe6c29SRuslan Bukin 	int errcode, flags;
859*74fe6c29SRuslan Bukin 
860*74fe6c29SRuslan Bukin 	if (!decoder || !event)
861*74fe6c29SRuslan Bukin 		return -pte_invalid;
862*74fe6c29SRuslan Bukin 
863*74fe6c29SRuslan Bukin 	if (size < offsetof(struct pt_event, variant))
864*74fe6c29SRuslan Bukin 		return -pte_invalid;
865*74fe6c29SRuslan Bukin 
866*74fe6c29SRuslan Bukin 	/* We do not allow querying for events while there are still TNT
867*74fe6c29SRuslan Bukin 	 * bits to consume.
868*74fe6c29SRuslan Bukin 	 */
869*74fe6c29SRuslan Bukin 	if (!pt_tnt_cache_is_empty(&decoder->tnt))
870*74fe6c29SRuslan Bukin 		return -pte_bad_query;
871*74fe6c29SRuslan Bukin 
872*74fe6c29SRuslan Bukin 	/* Do not provide more than we actually have. */
873*74fe6c29SRuslan Bukin 	if (sizeof(*event) < size)
874*74fe6c29SRuslan Bukin 		size = sizeof(*event);
875*74fe6c29SRuslan Bukin 
876*74fe6c29SRuslan Bukin 	flags = 0;
877*74fe6c29SRuslan Bukin 	for (;;) {
878*74fe6c29SRuslan Bukin 		const struct pt_decoder_function *dfun;
879*74fe6c29SRuslan Bukin 
880*74fe6c29SRuslan Bukin 		dfun = decoder->next;
881*74fe6c29SRuslan Bukin 		if (!dfun)
882*74fe6c29SRuslan Bukin 			return pt_qry_provoke_fetch_error(decoder);
883*74fe6c29SRuslan Bukin 
884*74fe6c29SRuslan Bukin 		if (!dfun->decode)
885*74fe6c29SRuslan Bukin 			return -pte_internal;
886*74fe6c29SRuslan Bukin 
887*74fe6c29SRuslan Bukin 		/* We must not see a TIP or TNT packet unless it belongs
888*74fe6c29SRuslan Bukin 		 * to an event.
889*74fe6c29SRuslan Bukin 		 *
890*74fe6c29SRuslan Bukin 		 * If we see one, it means that our user got out of sync.
891*74fe6c29SRuslan Bukin 		 * Let's report no data and hope that our user is able
892*74fe6c29SRuslan Bukin 		 * to re-sync.
893*74fe6c29SRuslan Bukin 		 */
894*74fe6c29SRuslan Bukin 		if ((dfun->flags & (pdff_tip | pdff_tnt)) &&
895*74fe6c29SRuslan Bukin 		    !pt_qry_will_event(decoder))
896*74fe6c29SRuslan Bukin 			return -pte_bad_query;
897*74fe6c29SRuslan Bukin 
898*74fe6c29SRuslan Bukin 		/* Clear the decoder's current event so we know when decoding
899*74fe6c29SRuslan Bukin 		 * produces a new event.
900*74fe6c29SRuslan Bukin 		 */
901*74fe6c29SRuslan Bukin 		decoder->event = NULL;
902*74fe6c29SRuslan Bukin 
903*74fe6c29SRuslan Bukin 		/* Apply any other decoder function. */
904*74fe6c29SRuslan Bukin 		errcode = dfun->decode(decoder);
905*74fe6c29SRuslan Bukin 		if (errcode)
906*74fe6c29SRuslan Bukin 			return errcode;
907*74fe6c29SRuslan Bukin 
908*74fe6c29SRuslan Bukin 		/* Check if there has been an event.
909*74fe6c29SRuslan Bukin 		 *
910*74fe6c29SRuslan Bukin 		 * Some packets may result in events in some but not in all
911*74fe6c29SRuslan Bukin 		 * configurations.
912*74fe6c29SRuslan Bukin 		 */
913*74fe6c29SRuslan Bukin 		if (decoder->event) {
914*74fe6c29SRuslan Bukin 			(void) memcpy(event, decoder->event, size);
915*74fe6c29SRuslan Bukin 			break;
916*74fe6c29SRuslan Bukin 		}
917*74fe6c29SRuslan Bukin 
918*74fe6c29SRuslan Bukin 		/* Read ahead until the next query-relevant packet. */
919*74fe6c29SRuslan Bukin 		errcode = pt_qry_read_ahead(decoder);
920*74fe6c29SRuslan Bukin 		if (errcode)
921*74fe6c29SRuslan Bukin 			return errcode;
922*74fe6c29SRuslan Bukin 	}
923*74fe6c29SRuslan Bukin 
924*74fe6c29SRuslan Bukin 	/* Preserve the time at the event. */
925*74fe6c29SRuslan Bukin 	decoder->last_time = decoder->time;
926*74fe6c29SRuslan Bukin 
927*74fe6c29SRuslan Bukin 	/* Read ahead until the next query-relevant packet. */
928*74fe6c29SRuslan Bukin 	errcode = pt_qry_read_ahead(decoder);
929*74fe6c29SRuslan Bukin 	if ((errcode < 0) && (errcode != -pte_eos))
930*74fe6c29SRuslan Bukin 		return errcode;
931*74fe6c29SRuslan Bukin 
932*74fe6c29SRuslan Bukin 	flags |= pt_qry_status_flags(decoder);
933*74fe6c29SRuslan Bukin 
934*74fe6c29SRuslan Bukin 	return flags;
935*74fe6c29SRuslan Bukin }
936*74fe6c29SRuslan Bukin 
pt_qry_time(struct pt_query_decoder * decoder,uint64_t * time,uint32_t * lost_mtc,uint32_t * lost_cyc)937*74fe6c29SRuslan Bukin int pt_qry_time(struct pt_query_decoder *decoder, uint64_t *time,
938*74fe6c29SRuslan Bukin 		uint32_t *lost_mtc, uint32_t *lost_cyc)
939*74fe6c29SRuslan Bukin {
940*74fe6c29SRuslan Bukin 	if (!decoder || !time)
941*74fe6c29SRuslan Bukin 		return -pte_invalid;
942*74fe6c29SRuslan Bukin 
943*74fe6c29SRuslan Bukin 	return pt_time_query_tsc(time, lost_mtc, lost_cyc, &decoder->last_time);
944*74fe6c29SRuslan Bukin }
945*74fe6c29SRuslan Bukin 
pt_qry_core_bus_ratio(struct pt_query_decoder * decoder,uint32_t * cbr)946*74fe6c29SRuslan Bukin int pt_qry_core_bus_ratio(struct pt_query_decoder *decoder, uint32_t *cbr)
947*74fe6c29SRuslan Bukin {
948*74fe6c29SRuslan Bukin 	if (!decoder || !cbr)
949*74fe6c29SRuslan Bukin 		return -pte_invalid;
950*74fe6c29SRuslan Bukin 
951*74fe6c29SRuslan Bukin 	return pt_time_query_cbr(cbr, &decoder->last_time);
952*74fe6c29SRuslan Bukin }
953*74fe6c29SRuslan Bukin 
pt_qry_event_time(struct pt_event * event,const struct pt_query_decoder * decoder)954*74fe6c29SRuslan Bukin static int pt_qry_event_time(struct pt_event *event,
955*74fe6c29SRuslan Bukin 			     const struct pt_query_decoder *decoder)
956*74fe6c29SRuslan Bukin {
957*74fe6c29SRuslan Bukin 	int errcode;
958*74fe6c29SRuslan Bukin 
959*74fe6c29SRuslan Bukin 	if (!event || !decoder)
960*74fe6c29SRuslan Bukin 		return -pte_internal;
961*74fe6c29SRuslan Bukin 
962*74fe6c29SRuslan Bukin 	errcode = pt_time_query_tsc(&event->tsc, &event->lost_mtc,
963*74fe6c29SRuslan Bukin 				    &event->lost_cyc, &decoder->time);
964*74fe6c29SRuslan Bukin 	if (errcode < 0) {
965*74fe6c29SRuslan Bukin 		if (errcode != -pte_no_time)
966*74fe6c29SRuslan Bukin 			return errcode;
967*74fe6c29SRuslan Bukin 	} else
968*74fe6c29SRuslan Bukin 		event->has_tsc = 1;
969*74fe6c29SRuslan Bukin 
970*74fe6c29SRuslan Bukin 	return 0;
971*74fe6c29SRuslan Bukin }
972*74fe6c29SRuslan Bukin 
pt_qry_decode_unknown(struct pt_query_decoder * decoder)973*74fe6c29SRuslan Bukin int pt_qry_decode_unknown(struct pt_query_decoder *decoder)
974*74fe6c29SRuslan Bukin {
975*74fe6c29SRuslan Bukin 	struct pt_packet packet;
976*74fe6c29SRuslan Bukin 	int size;
977*74fe6c29SRuslan Bukin 
978*74fe6c29SRuslan Bukin 	if (!decoder)
979*74fe6c29SRuslan Bukin 		return -pte_internal;
980*74fe6c29SRuslan Bukin 
981*74fe6c29SRuslan Bukin 	size = pt_pkt_read_unknown(&packet, decoder->pos, &decoder->config);
982*74fe6c29SRuslan Bukin 	if (size < 0)
983*74fe6c29SRuslan Bukin 		return size;
984*74fe6c29SRuslan Bukin 
985*74fe6c29SRuslan Bukin 	decoder->pos += size;
986*74fe6c29SRuslan Bukin 	return 0;
987*74fe6c29SRuslan Bukin }
988*74fe6c29SRuslan Bukin 
pt_qry_decode_pad(struct pt_query_decoder * decoder)989*74fe6c29SRuslan Bukin int pt_qry_decode_pad(struct pt_query_decoder *decoder)
990*74fe6c29SRuslan Bukin {
991*74fe6c29SRuslan Bukin 	if (!decoder)
992*74fe6c29SRuslan Bukin 		return -pte_internal;
993*74fe6c29SRuslan Bukin 
994*74fe6c29SRuslan Bukin 	decoder->pos += ptps_pad;
995*74fe6c29SRuslan Bukin 
996*74fe6c29SRuslan Bukin 	return 0;
997*74fe6c29SRuslan Bukin }
998*74fe6c29SRuslan Bukin 
pt_qry_read_psb_header(struct pt_query_decoder * decoder)999*74fe6c29SRuslan Bukin static int pt_qry_read_psb_header(struct pt_query_decoder *decoder)
1000*74fe6c29SRuslan Bukin {
1001*74fe6c29SRuslan Bukin 	if (!decoder)
1002*74fe6c29SRuslan Bukin 		return -pte_internal;
1003*74fe6c29SRuslan Bukin 
1004*74fe6c29SRuslan Bukin 	pt_last_ip_init(&decoder->ip);
1005*74fe6c29SRuslan Bukin 
1006*74fe6c29SRuslan Bukin 	for (;;) {
1007*74fe6c29SRuslan Bukin 		const struct pt_decoder_function *dfun;
1008*74fe6c29SRuslan Bukin 		int errcode;
1009*74fe6c29SRuslan Bukin 
1010*74fe6c29SRuslan Bukin 		errcode = pt_df_fetch(&decoder->next, decoder->pos,
1011*74fe6c29SRuslan Bukin 				      &decoder->config);
1012*74fe6c29SRuslan Bukin 		if (errcode)
1013*74fe6c29SRuslan Bukin 			return errcode;
1014*74fe6c29SRuslan Bukin 
1015*74fe6c29SRuslan Bukin 		dfun = decoder->next;
1016*74fe6c29SRuslan Bukin 		if (!dfun)
1017*74fe6c29SRuslan Bukin 			return -pte_internal;
1018*74fe6c29SRuslan Bukin 
1019*74fe6c29SRuslan Bukin 		/* We're done once we reach an psbend packet. */
1020*74fe6c29SRuslan Bukin 		if (dfun->flags & pdff_psbend)
1021*74fe6c29SRuslan Bukin 			return 0;
1022*74fe6c29SRuslan Bukin 
1023*74fe6c29SRuslan Bukin 		if (!dfun->header)
1024*74fe6c29SRuslan Bukin 			return -pte_bad_context;
1025*74fe6c29SRuslan Bukin 
1026*74fe6c29SRuslan Bukin 		errcode = dfun->header(decoder);
1027*74fe6c29SRuslan Bukin 		if (errcode)
1028*74fe6c29SRuslan Bukin 			return errcode;
1029*74fe6c29SRuslan Bukin 	}
1030*74fe6c29SRuslan Bukin }
1031*74fe6c29SRuslan Bukin 
pt_qry_decode_psb(struct pt_query_decoder * decoder)1032*74fe6c29SRuslan Bukin int pt_qry_decode_psb(struct pt_query_decoder *decoder)
1033*74fe6c29SRuslan Bukin {
1034*74fe6c29SRuslan Bukin 	const uint8_t *pos;
1035*74fe6c29SRuslan Bukin 	int size, errcode;
1036*74fe6c29SRuslan Bukin 
1037*74fe6c29SRuslan Bukin 	if (!decoder)
1038*74fe6c29SRuslan Bukin 		return -pte_internal;
1039*74fe6c29SRuslan Bukin 
1040*74fe6c29SRuslan Bukin 	pos = decoder->pos;
1041*74fe6c29SRuslan Bukin 
1042*74fe6c29SRuslan Bukin 	size = pt_pkt_read_psb(pos, &decoder->config);
1043*74fe6c29SRuslan Bukin 	if (size < 0)
1044*74fe6c29SRuslan Bukin 		return size;
1045*74fe6c29SRuslan Bukin 
1046*74fe6c29SRuslan Bukin 	decoder->pos += size;
1047*74fe6c29SRuslan Bukin 
1048*74fe6c29SRuslan Bukin 	errcode = pt_qry_read_psb_header(decoder);
1049*74fe6c29SRuslan Bukin 	if (errcode < 0) {
1050*74fe6c29SRuslan Bukin 		/* Move back to the PSB so we have a chance to recover and
1051*74fe6c29SRuslan Bukin 		 * continue decoding.
1052*74fe6c29SRuslan Bukin 		 */
1053*74fe6c29SRuslan Bukin 		decoder->pos = pos;
1054*74fe6c29SRuslan Bukin 
1055*74fe6c29SRuslan Bukin 		/* Clear any PSB+ events that have already been queued. */
1056*74fe6c29SRuslan Bukin 		(void) pt_evq_clear(&decoder->evq, evb_psbend);
1057*74fe6c29SRuslan Bukin 
1058*74fe6c29SRuslan Bukin 		/* Reset the decoder's decode function. */
1059*74fe6c29SRuslan Bukin 		decoder->next = &pt_decode_psb;
1060*74fe6c29SRuslan Bukin 
1061*74fe6c29SRuslan Bukin 		return errcode;
1062*74fe6c29SRuslan Bukin 	}
1063*74fe6c29SRuslan Bukin 
1064*74fe6c29SRuslan Bukin 	/* The next packet following the PSB header will be of type PSBEND.
1065*74fe6c29SRuslan Bukin 	 *
1066*74fe6c29SRuslan Bukin 	 * Decoding this packet will publish the PSB events what have been
1067*74fe6c29SRuslan Bukin 	 * accumulated while reading the PSB header.
1068*74fe6c29SRuslan Bukin 	 */
1069*74fe6c29SRuslan Bukin 	return 0;
1070*74fe6c29SRuslan Bukin }
1071*74fe6c29SRuslan Bukin 
pt_qry_event_ip(uint64_t * ip,struct pt_event * event,const struct pt_query_decoder * decoder)1072*74fe6c29SRuslan Bukin static int pt_qry_event_ip(uint64_t *ip, struct pt_event *event,
1073*74fe6c29SRuslan Bukin 			   const struct pt_query_decoder *decoder)
1074*74fe6c29SRuslan Bukin {
1075*74fe6c29SRuslan Bukin 	int errcode;
1076*74fe6c29SRuslan Bukin 
1077*74fe6c29SRuslan Bukin 	if (!decoder)
1078*74fe6c29SRuslan Bukin 		return -pte_internal;
1079*74fe6c29SRuslan Bukin 
1080*74fe6c29SRuslan Bukin 	errcode = pt_last_ip_query(ip, &decoder->ip);
1081*74fe6c29SRuslan Bukin 	if (errcode < 0) {
1082*74fe6c29SRuslan Bukin 		switch (pt_errcode(errcode)) {
1083*74fe6c29SRuslan Bukin 		case pte_noip:
1084*74fe6c29SRuslan Bukin 		case pte_ip_suppressed:
1085*74fe6c29SRuslan Bukin 			event->ip_suppressed = 1;
1086*74fe6c29SRuslan Bukin 			break;
1087*74fe6c29SRuslan Bukin 
1088*74fe6c29SRuslan Bukin 		default:
1089*74fe6c29SRuslan Bukin 			return errcode;
1090*74fe6c29SRuslan Bukin 		}
1091*74fe6c29SRuslan Bukin 	}
1092*74fe6c29SRuslan Bukin 
1093*74fe6c29SRuslan Bukin 	return 0;
1094*74fe6c29SRuslan Bukin }
1095*74fe6c29SRuslan Bukin 
1096*74fe6c29SRuslan Bukin /* Decode a generic IP packet.
1097*74fe6c29SRuslan Bukin  *
1098*74fe6c29SRuslan Bukin  * Returns the number of bytes read, on success.
1099*74fe6c29SRuslan Bukin  * Returns -pte_eos if the ip does not fit into the buffer.
1100*74fe6c29SRuslan Bukin  * Returns -pte_bad_packet if the ip compression is not known.
1101*74fe6c29SRuslan Bukin  */
pt_qry_decode_ip(struct pt_query_decoder * decoder)1102*74fe6c29SRuslan Bukin static int pt_qry_decode_ip(struct pt_query_decoder *decoder)
1103*74fe6c29SRuslan Bukin {
1104*74fe6c29SRuslan Bukin 	struct pt_packet_ip packet;
1105*74fe6c29SRuslan Bukin 	int errcode, size;
1106*74fe6c29SRuslan Bukin 
1107*74fe6c29SRuslan Bukin 	if (!decoder)
1108*74fe6c29SRuslan Bukin 		return -pte_internal;
1109*74fe6c29SRuslan Bukin 
1110*74fe6c29SRuslan Bukin 	size = pt_pkt_read_ip(&packet, decoder->pos, &decoder->config);
1111*74fe6c29SRuslan Bukin 	if (size < 0)
1112*74fe6c29SRuslan Bukin 		return size;
1113*74fe6c29SRuslan Bukin 
1114*74fe6c29SRuslan Bukin 	errcode = pt_last_ip_update_ip(&decoder->ip, &packet, &decoder->config);
1115*74fe6c29SRuslan Bukin 	if (errcode < 0)
1116*74fe6c29SRuslan Bukin 		return errcode;
1117*74fe6c29SRuslan Bukin 
1118*74fe6c29SRuslan Bukin 	/* We do not update the decoder's position, yet. */
1119*74fe6c29SRuslan Bukin 
1120*74fe6c29SRuslan Bukin 	return size;
1121*74fe6c29SRuslan Bukin }
1122*74fe6c29SRuslan Bukin 
pt_qry_consume_tip(struct pt_query_decoder * decoder,int size)1123*74fe6c29SRuslan Bukin static int pt_qry_consume_tip(struct pt_query_decoder *decoder, int size)
1124*74fe6c29SRuslan Bukin {
1125*74fe6c29SRuslan Bukin 	if (!decoder)
1126*74fe6c29SRuslan Bukin 		return -pte_internal;
1127*74fe6c29SRuslan Bukin 
1128*74fe6c29SRuslan Bukin 	decoder->pos += size;
1129*74fe6c29SRuslan Bukin 	return 0;
1130*74fe6c29SRuslan Bukin }
1131*74fe6c29SRuslan Bukin 
pt_qry_event_tip(struct pt_event * ev,struct pt_query_decoder * decoder)1132*74fe6c29SRuslan Bukin static int pt_qry_event_tip(struct pt_event *ev,
1133*74fe6c29SRuslan Bukin 			    struct pt_query_decoder *decoder)
1134*74fe6c29SRuslan Bukin {
1135*74fe6c29SRuslan Bukin 	if (!ev || !decoder)
1136*74fe6c29SRuslan Bukin 		return -pte_internal;
1137*74fe6c29SRuslan Bukin 
1138*74fe6c29SRuslan Bukin 	switch (ev->type) {
1139*74fe6c29SRuslan Bukin 	case ptev_async_branch:
1140*74fe6c29SRuslan Bukin 		decoder->consume_packet = 1;
1141*74fe6c29SRuslan Bukin 
1142*74fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.async_branch.to, ev,
1143*74fe6c29SRuslan Bukin 				       decoder);
1144*74fe6c29SRuslan Bukin 
1145*74fe6c29SRuslan Bukin 	case ptev_async_paging:
1146*74fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.async_paging.ip, ev,
1147*74fe6c29SRuslan Bukin 				       decoder);
1148*74fe6c29SRuslan Bukin 
1149*74fe6c29SRuslan Bukin 	case ptev_async_vmcs:
1150*74fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.async_vmcs.ip, ev,
1151*74fe6c29SRuslan Bukin 				       decoder);
1152*74fe6c29SRuslan Bukin 
1153*74fe6c29SRuslan Bukin 	case ptev_exec_mode:
1154*74fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.exec_mode.ip, ev,
1155*74fe6c29SRuslan Bukin 				       decoder);
1156*74fe6c29SRuslan Bukin 
1157*74fe6c29SRuslan Bukin 	default:
1158*74fe6c29SRuslan Bukin 		break;
1159*74fe6c29SRuslan Bukin 	}
1160*74fe6c29SRuslan Bukin 
1161*74fe6c29SRuslan Bukin 	return -pte_bad_context;
1162*74fe6c29SRuslan Bukin }
1163*74fe6c29SRuslan Bukin 
pt_qry_decode_tip(struct pt_query_decoder * decoder)1164*74fe6c29SRuslan Bukin int pt_qry_decode_tip(struct pt_query_decoder *decoder)
1165*74fe6c29SRuslan Bukin {
1166*74fe6c29SRuslan Bukin 	struct pt_event *ev;
1167*74fe6c29SRuslan Bukin 	int size, errcode;
1168*74fe6c29SRuslan Bukin 
1169*74fe6c29SRuslan Bukin 	if (!decoder)
1170*74fe6c29SRuslan Bukin 		return -pte_internal;
1171*74fe6c29SRuslan Bukin 
1172*74fe6c29SRuslan Bukin 	size = pt_qry_decode_ip(decoder);
1173*74fe6c29SRuslan Bukin 	if (size < 0)
1174*74fe6c29SRuslan Bukin 		return size;
1175*74fe6c29SRuslan Bukin 
1176*74fe6c29SRuslan Bukin 	/* Process any pending events binding to TIP. */
1177*74fe6c29SRuslan Bukin 	ev = pt_evq_dequeue(&decoder->evq, evb_tip);
1178*74fe6c29SRuslan Bukin 	if (ev) {
1179*74fe6c29SRuslan Bukin 		errcode = pt_qry_event_tip(ev, decoder);
1180*74fe6c29SRuslan Bukin 		if (errcode < 0)
1181*74fe6c29SRuslan Bukin 			return errcode;
1182*74fe6c29SRuslan Bukin 
1183*74fe6c29SRuslan Bukin 		/* Publish the event. */
1184*74fe6c29SRuslan Bukin 		decoder->event = ev;
1185*74fe6c29SRuslan Bukin 
1186*74fe6c29SRuslan Bukin 		/* Process further pending events. */
1187*74fe6c29SRuslan Bukin 		if (pt_evq_pending(&decoder->evq, evb_tip))
1188*74fe6c29SRuslan Bukin 			return 0;
1189*74fe6c29SRuslan Bukin 
1190*74fe6c29SRuslan Bukin 		/* No further events.
1191*74fe6c29SRuslan Bukin 		 *
1192*74fe6c29SRuslan Bukin 		 * If none of the events consumed the packet, we're done.
1193*74fe6c29SRuslan Bukin 		 */
1194*74fe6c29SRuslan Bukin 		if (!decoder->consume_packet)
1195*74fe6c29SRuslan Bukin 			return 0;
1196*74fe6c29SRuslan Bukin 
1197*74fe6c29SRuslan Bukin 		/* We're done with this packet. Clear the flag we set previously
1198*74fe6c29SRuslan Bukin 		 * and consume it.
1199*74fe6c29SRuslan Bukin 		 */
1200*74fe6c29SRuslan Bukin 		decoder->consume_packet = 0;
1201*74fe6c29SRuslan Bukin 	}
1202*74fe6c29SRuslan Bukin 
1203*74fe6c29SRuslan Bukin 	return pt_qry_consume_tip(decoder, size);
1204*74fe6c29SRuslan Bukin }
1205*74fe6c29SRuslan Bukin 
pt_qry_decode_tnt_8(struct pt_query_decoder * decoder)1206*74fe6c29SRuslan Bukin int pt_qry_decode_tnt_8(struct pt_query_decoder *decoder)
1207*74fe6c29SRuslan Bukin {
1208*74fe6c29SRuslan Bukin 	struct pt_packet_tnt packet;
1209*74fe6c29SRuslan Bukin 	int size, errcode;
1210*74fe6c29SRuslan Bukin 
1211*74fe6c29SRuslan Bukin 	if (!decoder)
1212*74fe6c29SRuslan Bukin 		return -pte_internal;
1213*74fe6c29SRuslan Bukin 
1214*74fe6c29SRuslan Bukin 	size = pt_pkt_read_tnt_8(&packet, decoder->pos, &decoder->config);
1215*74fe6c29SRuslan Bukin 	if (size < 0)
1216*74fe6c29SRuslan Bukin 		return size;
1217*74fe6c29SRuslan Bukin 
1218*74fe6c29SRuslan Bukin 	errcode = pt_tnt_cache_update_tnt(&decoder->tnt, &packet,
1219*74fe6c29SRuslan Bukin 					  &decoder->config);
1220*74fe6c29SRuslan Bukin 	if (errcode < 0)
1221*74fe6c29SRuslan Bukin 		return errcode;
1222*74fe6c29SRuslan Bukin 
1223*74fe6c29SRuslan Bukin 	decoder->pos += size;
1224*74fe6c29SRuslan Bukin 	return 0;
1225*74fe6c29SRuslan Bukin }
1226*74fe6c29SRuslan Bukin 
pt_qry_decode_tnt_64(struct pt_query_decoder * decoder)1227*74fe6c29SRuslan Bukin int pt_qry_decode_tnt_64(struct pt_query_decoder *decoder)
1228*74fe6c29SRuslan Bukin {
1229*74fe6c29SRuslan Bukin 	struct pt_packet_tnt packet;
1230*74fe6c29SRuslan Bukin 	int size, errcode;
1231*74fe6c29SRuslan Bukin 
1232*74fe6c29SRuslan Bukin 	if (!decoder)
1233*74fe6c29SRuslan Bukin 		return -pte_internal;
1234*74fe6c29SRuslan Bukin 
1235*74fe6c29SRuslan Bukin 	size = pt_pkt_read_tnt_64(&packet, decoder->pos, &decoder->config);
1236*74fe6c29SRuslan Bukin 	if (size < 0)
1237*74fe6c29SRuslan Bukin 		return size;
1238*74fe6c29SRuslan Bukin 
1239*74fe6c29SRuslan Bukin 	errcode = pt_tnt_cache_update_tnt(&decoder->tnt, &packet,
1240*74fe6c29SRuslan Bukin 					  &decoder->config);
1241*74fe6c29SRuslan Bukin 	if (errcode < 0)
1242*74fe6c29SRuslan Bukin 		return errcode;
1243*74fe6c29SRuslan Bukin 
1244*74fe6c29SRuslan Bukin 	decoder->pos += size;
1245*74fe6c29SRuslan Bukin 	return 0;
1246*74fe6c29SRuslan Bukin }
1247*74fe6c29SRuslan Bukin 
pt_qry_consume_tip_pge(struct pt_query_decoder * decoder,int size)1248*74fe6c29SRuslan Bukin static int pt_qry_consume_tip_pge(struct pt_query_decoder *decoder, int size)
1249*74fe6c29SRuslan Bukin {
1250*74fe6c29SRuslan Bukin 	if (!decoder)
1251*74fe6c29SRuslan Bukin 		return -pte_internal;
1252*74fe6c29SRuslan Bukin 
1253*74fe6c29SRuslan Bukin 	decoder->pos += size;
1254*74fe6c29SRuslan Bukin 	return 0;
1255*74fe6c29SRuslan Bukin }
1256*74fe6c29SRuslan Bukin 
pt_qry_event_tip_pge(struct pt_event * ev,const struct pt_query_decoder * decoder)1257*74fe6c29SRuslan Bukin static int pt_qry_event_tip_pge(struct pt_event *ev,
1258*74fe6c29SRuslan Bukin 				const struct pt_query_decoder *decoder)
1259*74fe6c29SRuslan Bukin {
1260*74fe6c29SRuslan Bukin 	if (!ev)
1261*74fe6c29SRuslan Bukin 		return -pte_internal;
1262*74fe6c29SRuslan Bukin 
1263*74fe6c29SRuslan Bukin 	switch (ev->type) {
1264*74fe6c29SRuslan Bukin 	case ptev_exec_mode:
1265*74fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.exec_mode.ip, ev, decoder);
1266*74fe6c29SRuslan Bukin 
1267*74fe6c29SRuslan Bukin 	default:
1268*74fe6c29SRuslan Bukin 		break;
1269*74fe6c29SRuslan Bukin 	}
1270*74fe6c29SRuslan Bukin 
1271*74fe6c29SRuslan Bukin 	return -pte_bad_context;
1272*74fe6c29SRuslan Bukin }
1273*74fe6c29SRuslan Bukin 
pt_qry_decode_tip_pge(struct pt_query_decoder * decoder)1274*74fe6c29SRuslan Bukin int pt_qry_decode_tip_pge(struct pt_query_decoder *decoder)
1275*74fe6c29SRuslan Bukin {
1276*74fe6c29SRuslan Bukin 	struct pt_event *ev;
1277*74fe6c29SRuslan Bukin 	int size, errcode;
1278*74fe6c29SRuslan Bukin 
1279*74fe6c29SRuslan Bukin 	if (!decoder)
1280*74fe6c29SRuslan Bukin 		return -pte_internal;
1281*74fe6c29SRuslan Bukin 
1282*74fe6c29SRuslan Bukin 	size = pt_qry_decode_ip(decoder);
1283*74fe6c29SRuslan Bukin 	if (size < 0)
1284*74fe6c29SRuslan Bukin 		return size;
1285*74fe6c29SRuslan Bukin 
1286*74fe6c29SRuslan Bukin 	/* We send the enable event first. This is more convenient for our users
1287*74fe6c29SRuslan Bukin 	 * and does not require them to either store or blindly apply other
1288*74fe6c29SRuslan Bukin 	 * events that might be pending.
1289*74fe6c29SRuslan Bukin 	 *
1290*74fe6c29SRuslan Bukin 	 * We use the consume packet decoder flag to indicate this.
1291*74fe6c29SRuslan Bukin 	 */
1292*74fe6c29SRuslan Bukin 	if (!decoder->consume_packet) {
1293*74fe6c29SRuslan Bukin 		/* This packet signals a standalone enabled event. */
1294*74fe6c29SRuslan Bukin 		ev = pt_evq_standalone(&decoder->evq);
1295*74fe6c29SRuslan Bukin 		if (!ev)
1296*74fe6c29SRuslan Bukin 			return -pte_internal;
1297*74fe6c29SRuslan Bukin 
1298*74fe6c29SRuslan Bukin 		ev->type = ptev_enabled;
1299*74fe6c29SRuslan Bukin 
1300*74fe6c29SRuslan Bukin 		/* We can't afford having a suppressed IP here. */
1301*74fe6c29SRuslan Bukin 		errcode = pt_last_ip_query(&ev->variant.enabled.ip,
1302*74fe6c29SRuslan Bukin 					   &decoder->ip);
1303*74fe6c29SRuslan Bukin 		if (errcode < 0)
1304*74fe6c29SRuslan Bukin 			return -pte_bad_packet;
1305*74fe6c29SRuslan Bukin 
1306*74fe6c29SRuslan Bukin 		errcode = pt_qry_event_time(ev, decoder);
1307*74fe6c29SRuslan Bukin 		if (errcode < 0)
1308*74fe6c29SRuslan Bukin 			return errcode;
1309*74fe6c29SRuslan Bukin 
1310*74fe6c29SRuslan Bukin 		/* Discard any cached TNT bits.
1311*74fe6c29SRuslan Bukin 		 *
1312*74fe6c29SRuslan Bukin 		 * They should have been consumed at the corresponding disable
1313*74fe6c29SRuslan Bukin 		 * event. If they have not, for whatever reason, discard them
1314*74fe6c29SRuslan Bukin 		 * now so our user does not get out of sync.
1315*74fe6c29SRuslan Bukin 		 */
1316*74fe6c29SRuslan Bukin 		pt_tnt_cache_init(&decoder->tnt);
1317*74fe6c29SRuslan Bukin 
1318*74fe6c29SRuslan Bukin 		/* Process pending events next. */
1319*74fe6c29SRuslan Bukin 		decoder->consume_packet = 1;
1320*74fe6c29SRuslan Bukin 		decoder->enabled = 1;
1321*74fe6c29SRuslan Bukin 	} else {
1322*74fe6c29SRuslan Bukin 		/* Process any pending events binding to TIP. */
1323*74fe6c29SRuslan Bukin 		ev = pt_evq_dequeue(&decoder->evq, evb_tip);
1324*74fe6c29SRuslan Bukin 		if (ev) {
1325*74fe6c29SRuslan Bukin 			errcode = pt_qry_event_tip_pge(ev, decoder);
1326*74fe6c29SRuslan Bukin 			if (errcode < 0)
1327*74fe6c29SRuslan Bukin 				return errcode;
1328*74fe6c29SRuslan Bukin 		}
1329*74fe6c29SRuslan Bukin 	}
1330*74fe6c29SRuslan Bukin 
1331*74fe6c29SRuslan Bukin 	/* We must have an event. Either the initial enable event or one of the
1332*74fe6c29SRuslan Bukin 	 * queued events.
1333*74fe6c29SRuslan Bukin 	 */
1334*74fe6c29SRuslan Bukin 	if (!ev)
1335*74fe6c29SRuslan Bukin 		return -pte_internal;
1336*74fe6c29SRuslan Bukin 
1337*74fe6c29SRuslan Bukin 	/* Publish the event. */
1338*74fe6c29SRuslan Bukin 	decoder->event = ev;
1339*74fe6c29SRuslan Bukin 
1340*74fe6c29SRuslan Bukin 	/* Process further pending events. */
1341*74fe6c29SRuslan Bukin 	if (pt_evq_pending(&decoder->evq, evb_tip))
1342*74fe6c29SRuslan Bukin 		return 0;
1343*74fe6c29SRuslan Bukin 
1344*74fe6c29SRuslan Bukin 	/* We must consume the packet. */
1345*74fe6c29SRuslan Bukin 	if (!decoder->consume_packet)
1346*74fe6c29SRuslan Bukin 		return -pte_internal;
1347*74fe6c29SRuslan Bukin 
1348*74fe6c29SRuslan Bukin 	decoder->consume_packet = 0;
1349*74fe6c29SRuslan Bukin 
1350*74fe6c29SRuslan Bukin 	return pt_qry_consume_tip_pge(decoder, size);
1351*74fe6c29SRuslan Bukin }
1352*74fe6c29SRuslan Bukin 
pt_qry_consume_tip_pgd(struct pt_query_decoder * decoder,int size)1353*74fe6c29SRuslan Bukin static int pt_qry_consume_tip_pgd(struct pt_query_decoder *decoder, int size)
1354*74fe6c29SRuslan Bukin {
1355*74fe6c29SRuslan Bukin 	if (!decoder)
1356*74fe6c29SRuslan Bukin 		return -pte_internal;
1357*74fe6c29SRuslan Bukin 
1358*74fe6c29SRuslan Bukin 	decoder->enabled = 0;
1359*74fe6c29SRuslan Bukin 	decoder->pos += size;
1360*74fe6c29SRuslan Bukin 	return 0;
1361*74fe6c29SRuslan Bukin }
1362*74fe6c29SRuslan Bukin 
pt_qry_event_tip_pgd(struct pt_event * ev,const struct pt_query_decoder * decoder)1363*74fe6c29SRuslan Bukin static int pt_qry_event_tip_pgd(struct pt_event *ev,
1364*74fe6c29SRuslan Bukin 				const struct pt_query_decoder *decoder)
1365*74fe6c29SRuslan Bukin {
1366*74fe6c29SRuslan Bukin 	if (!ev)
1367*74fe6c29SRuslan Bukin 		return -pte_internal;
1368*74fe6c29SRuslan Bukin 
1369*74fe6c29SRuslan Bukin 	switch (ev->type) {
1370*74fe6c29SRuslan Bukin 	case ptev_async_branch: {
1371*74fe6c29SRuslan Bukin 		uint64_t at;
1372*74fe6c29SRuslan Bukin 
1373*74fe6c29SRuslan Bukin 		/* Turn the async branch into an async disable. */
1374*74fe6c29SRuslan Bukin 		at = ev->variant.async_branch.from;
1375*74fe6c29SRuslan Bukin 
1376*74fe6c29SRuslan Bukin 		ev->type = ptev_async_disabled;
1377*74fe6c29SRuslan Bukin 		ev->variant.async_disabled.at = at;
1378*74fe6c29SRuslan Bukin 
1379*74fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.async_disabled.ip, ev,
1380*74fe6c29SRuslan Bukin 				       decoder);
1381*74fe6c29SRuslan Bukin 	}
1382*74fe6c29SRuslan Bukin 
1383*74fe6c29SRuslan Bukin 	case ptev_async_paging:
1384*74fe6c29SRuslan Bukin 	case ptev_async_vmcs:
1385*74fe6c29SRuslan Bukin 	case ptev_exec_mode:
1386*74fe6c29SRuslan Bukin 		/* These events are ordered after the async disable event.  It
1387*74fe6c29SRuslan Bukin 		 * is not quite clear what IP to give them.
1388*74fe6c29SRuslan Bukin 		 *
1389*74fe6c29SRuslan Bukin 		 * If we give them the async disable's source IP, we'd make an
1390*74fe6c29SRuslan Bukin 		 * error if the IP is updated when applying the async disable
1391*74fe6c29SRuslan Bukin 		 * event.
1392*74fe6c29SRuslan Bukin 		 *
1393*74fe6c29SRuslan Bukin 		 * If we give them the async disable's destination IP, we'd make
1394*74fe6c29SRuslan Bukin 		 * an error if the IP is not updated when applying the async
1395*74fe6c29SRuslan Bukin 		 * disable event.  That's what our decoders do since tracing is
1396*74fe6c29SRuslan Bukin 		 * likely to resume from there.
1397*74fe6c29SRuslan Bukin 		 *
1398*74fe6c29SRuslan Bukin 		 * In all cases, tracing will be disabled when those events are
1399*74fe6c29SRuslan Bukin 		 * applied, so we may as well suppress the IP.
1400*74fe6c29SRuslan Bukin 		 */
1401*74fe6c29SRuslan Bukin 		ev->ip_suppressed = 1;
1402*74fe6c29SRuslan Bukin 
1403*74fe6c29SRuslan Bukin 		return 0;
1404*74fe6c29SRuslan Bukin 
1405*74fe6c29SRuslan Bukin 	default:
1406*74fe6c29SRuslan Bukin 		break;
1407*74fe6c29SRuslan Bukin 	}
1408*74fe6c29SRuslan Bukin 
1409*74fe6c29SRuslan Bukin 	return -pte_bad_context;
1410*74fe6c29SRuslan Bukin }
1411*74fe6c29SRuslan Bukin 
pt_qry_decode_tip_pgd(struct pt_query_decoder * decoder)1412*74fe6c29SRuslan Bukin int pt_qry_decode_tip_pgd(struct pt_query_decoder *decoder)
1413*74fe6c29SRuslan Bukin {
1414*74fe6c29SRuslan Bukin 	struct pt_event *ev;
1415*74fe6c29SRuslan Bukin 	int size, errcode;
1416*74fe6c29SRuslan Bukin 
1417*74fe6c29SRuslan Bukin 	if (!decoder)
1418*74fe6c29SRuslan Bukin 		return -pte_internal;
1419*74fe6c29SRuslan Bukin 
1420*74fe6c29SRuslan Bukin 	size = pt_qry_decode_ip(decoder);
1421*74fe6c29SRuslan Bukin 	if (size < 0)
1422*74fe6c29SRuslan Bukin 		return size;
1423*74fe6c29SRuslan Bukin 
1424*74fe6c29SRuslan Bukin 	/* Process any pending events binding to TIP. */
1425*74fe6c29SRuslan Bukin 	ev = pt_evq_dequeue(&decoder->evq, evb_tip);
1426*74fe6c29SRuslan Bukin 	if (ev) {
1427*74fe6c29SRuslan Bukin 		errcode = pt_qry_event_tip_pgd(ev, decoder);
1428*74fe6c29SRuslan Bukin 		if (errcode < 0)
1429*74fe6c29SRuslan Bukin 			return errcode;
1430*74fe6c29SRuslan Bukin 	} else {
1431*74fe6c29SRuslan Bukin 		/* This packet signals a standalone disabled event. */
1432*74fe6c29SRuslan Bukin 		ev = pt_evq_standalone(&decoder->evq);
1433*74fe6c29SRuslan Bukin 		if (!ev)
1434*74fe6c29SRuslan Bukin 			return -pte_internal;
1435*74fe6c29SRuslan Bukin 		ev->type = ptev_disabled;
1436*74fe6c29SRuslan Bukin 
1437*74fe6c29SRuslan Bukin 		errcode = pt_qry_event_ip(&ev->variant.disabled.ip, ev,
1438*74fe6c29SRuslan Bukin 					  decoder);
1439*74fe6c29SRuslan Bukin 		if (errcode < 0)
1440*74fe6c29SRuslan Bukin 			return errcode;
1441*74fe6c29SRuslan Bukin 
1442*74fe6c29SRuslan Bukin 		errcode = pt_qry_event_time(ev, decoder);
1443*74fe6c29SRuslan Bukin 		if (errcode < 0)
1444*74fe6c29SRuslan Bukin 			return errcode;
1445*74fe6c29SRuslan Bukin 	}
1446*74fe6c29SRuslan Bukin 
1447*74fe6c29SRuslan Bukin 	/* We must have an event. Either the initial enable event or one of the
1448*74fe6c29SRuslan Bukin 	 * queued events.
1449*74fe6c29SRuslan Bukin 	 */
1450*74fe6c29SRuslan Bukin 	if (!ev)
1451*74fe6c29SRuslan Bukin 		return -pte_internal;
1452*74fe6c29SRuslan Bukin 
1453*74fe6c29SRuslan Bukin 	/* Publish the event. */
1454*74fe6c29SRuslan Bukin 	decoder->event = ev;
1455*74fe6c29SRuslan Bukin 
1456*74fe6c29SRuslan Bukin 	/* Process further pending events. */
1457*74fe6c29SRuslan Bukin 	if (pt_evq_pending(&decoder->evq, evb_tip))
1458*74fe6c29SRuslan Bukin 		return 0;
1459*74fe6c29SRuslan Bukin 
1460*74fe6c29SRuslan Bukin 	return pt_qry_consume_tip_pgd(decoder, size);
1461*74fe6c29SRuslan Bukin }
1462*74fe6c29SRuslan Bukin 
pt_qry_consume_fup(struct pt_query_decoder * decoder,int size)1463*74fe6c29SRuslan Bukin static int pt_qry_consume_fup(struct pt_query_decoder *decoder, int size)
1464*74fe6c29SRuslan Bukin {
1465*74fe6c29SRuslan Bukin 	if (!decoder)
1466*74fe6c29SRuslan Bukin 		return -pte_internal;
1467*74fe6c29SRuslan Bukin 
1468*74fe6c29SRuslan Bukin 	decoder->pos += size;
1469*74fe6c29SRuslan Bukin 	return 0;
1470*74fe6c29SRuslan Bukin }
1471*74fe6c29SRuslan Bukin 
scan_for_erratum_bdm70(struct pt_packet_decoder * decoder)1472*74fe6c29SRuslan Bukin static int scan_for_erratum_bdm70(struct pt_packet_decoder *decoder)
1473*74fe6c29SRuslan Bukin {
1474*74fe6c29SRuslan Bukin 	for (;;) {
1475*74fe6c29SRuslan Bukin 		struct pt_packet packet;
1476*74fe6c29SRuslan Bukin 		int errcode;
1477*74fe6c29SRuslan Bukin 
1478*74fe6c29SRuslan Bukin 		errcode = pt_pkt_next(decoder, &packet, sizeof(packet));
1479*74fe6c29SRuslan Bukin 		if (errcode < 0) {
1480*74fe6c29SRuslan Bukin 			/* Running out of packets is not an error. */
1481*74fe6c29SRuslan Bukin 			if (errcode == -pte_eos)
1482*74fe6c29SRuslan Bukin 				errcode = 0;
1483*74fe6c29SRuslan Bukin 
1484*74fe6c29SRuslan Bukin 			return errcode;
1485*74fe6c29SRuslan Bukin 		}
1486*74fe6c29SRuslan Bukin 
1487*74fe6c29SRuslan Bukin 		switch (packet.type) {
1488*74fe6c29SRuslan Bukin 		default:
1489*74fe6c29SRuslan Bukin 			/* All other packets cancel our search.
1490*74fe6c29SRuslan Bukin 			 *
1491*74fe6c29SRuslan Bukin 			 * We do not enumerate those packets since we also
1492*74fe6c29SRuslan Bukin 			 * want to include new packets.
1493*74fe6c29SRuslan Bukin 			 */
1494*74fe6c29SRuslan Bukin 			return 0;
1495*74fe6c29SRuslan Bukin 
1496*74fe6c29SRuslan Bukin 		case ppt_tip_pge:
1497*74fe6c29SRuslan Bukin 			/* We found it - the erratum applies. */
1498*74fe6c29SRuslan Bukin 			return 1;
1499*74fe6c29SRuslan Bukin 
1500*74fe6c29SRuslan Bukin 		case ppt_pad:
1501*74fe6c29SRuslan Bukin 		case ppt_tsc:
1502*74fe6c29SRuslan Bukin 		case ppt_cbr:
1503*74fe6c29SRuslan Bukin 		case ppt_psbend:
1504*74fe6c29SRuslan Bukin 		case ppt_pip:
1505*74fe6c29SRuslan Bukin 		case ppt_mode:
1506*74fe6c29SRuslan Bukin 		case ppt_vmcs:
1507*74fe6c29SRuslan Bukin 		case ppt_tma:
1508*74fe6c29SRuslan Bukin 		case ppt_mtc:
1509*74fe6c29SRuslan Bukin 		case ppt_cyc:
1510*74fe6c29SRuslan Bukin 		case ppt_mnt:
1511*74fe6c29SRuslan Bukin 			/* Intentionally skip a few packets. */
1512*74fe6c29SRuslan Bukin 			continue;
1513*74fe6c29SRuslan Bukin 		}
1514*74fe6c29SRuslan Bukin 	}
1515*74fe6c29SRuslan Bukin }
1516*74fe6c29SRuslan Bukin 
check_erratum_bdm70(const uint8_t * pos,const struct pt_config * config)1517*74fe6c29SRuslan Bukin static int check_erratum_bdm70(const uint8_t *pos,
1518*74fe6c29SRuslan Bukin 			       const struct pt_config *config)
1519*74fe6c29SRuslan Bukin {
1520*74fe6c29SRuslan Bukin 	struct pt_packet_decoder decoder;
1521*74fe6c29SRuslan Bukin 	int errcode;
1522*74fe6c29SRuslan Bukin 
1523*74fe6c29SRuslan Bukin 	if (!pos || !config)
1524*74fe6c29SRuslan Bukin 		return -pte_internal;
1525*74fe6c29SRuslan Bukin 
1526*74fe6c29SRuslan Bukin 	errcode = pt_pkt_decoder_init(&decoder, config);
1527*74fe6c29SRuslan Bukin 	if (errcode < 0)
1528*74fe6c29SRuslan Bukin 		return errcode;
1529*74fe6c29SRuslan Bukin 
1530*74fe6c29SRuslan Bukin 	errcode = pt_pkt_sync_set(&decoder, (uint64_t) (pos - config->begin));
1531*74fe6c29SRuslan Bukin 	if (errcode >= 0)
1532*74fe6c29SRuslan Bukin 		errcode = scan_for_erratum_bdm70(&decoder);
1533*74fe6c29SRuslan Bukin 
1534*74fe6c29SRuslan Bukin 	pt_pkt_decoder_fini(&decoder);
1535*74fe6c29SRuslan Bukin 	return errcode;
1536*74fe6c29SRuslan Bukin }
1537*74fe6c29SRuslan Bukin 
pt_qry_header_fup(struct pt_query_decoder * decoder)1538*74fe6c29SRuslan Bukin int pt_qry_header_fup(struct pt_query_decoder *decoder)
1539*74fe6c29SRuslan Bukin {
1540*74fe6c29SRuslan Bukin 	struct pt_packet_ip packet;
1541*74fe6c29SRuslan Bukin 	int errcode, size;
1542*74fe6c29SRuslan Bukin 
1543*74fe6c29SRuslan Bukin 	if (!decoder)
1544*74fe6c29SRuslan Bukin 		return -pte_internal;
1545*74fe6c29SRuslan Bukin 
1546*74fe6c29SRuslan Bukin 	size = pt_pkt_read_ip(&packet, decoder->pos, &decoder->config);
1547*74fe6c29SRuslan Bukin 	if (size < 0)
1548*74fe6c29SRuslan Bukin 		return size;
1549*74fe6c29SRuslan Bukin 
1550*74fe6c29SRuslan Bukin 	if (decoder->config.errata.bdm70 && !decoder->enabled) {
1551*74fe6c29SRuslan Bukin 		errcode = check_erratum_bdm70(decoder->pos + size,
1552*74fe6c29SRuslan Bukin 					      &decoder->config);
1553*74fe6c29SRuslan Bukin 		if (errcode < 0)
1554*74fe6c29SRuslan Bukin 			return errcode;
1555*74fe6c29SRuslan Bukin 
1556*74fe6c29SRuslan Bukin 		if (errcode)
1557*74fe6c29SRuslan Bukin 			return pt_qry_consume_fup(decoder, size);
1558*74fe6c29SRuslan Bukin 	}
1559*74fe6c29SRuslan Bukin 
1560*74fe6c29SRuslan Bukin 	errcode = pt_last_ip_update_ip(&decoder->ip, &packet, &decoder->config);
1561*74fe6c29SRuslan Bukin 	if (errcode < 0)
1562*74fe6c29SRuslan Bukin 		return errcode;
1563*74fe6c29SRuslan Bukin 
1564*74fe6c29SRuslan Bukin 	/* Tracing is enabled if we have an IP in the header. */
1565*74fe6c29SRuslan Bukin 	if (packet.ipc != pt_ipc_suppressed)
1566*74fe6c29SRuslan Bukin 		decoder->enabled = 1;
1567*74fe6c29SRuslan Bukin 
1568*74fe6c29SRuslan Bukin 	return pt_qry_consume_fup(decoder, size);
1569*74fe6c29SRuslan Bukin }
1570*74fe6c29SRuslan Bukin 
pt_qry_event_fup(struct pt_event * ev,struct pt_query_decoder * decoder)1571*74fe6c29SRuslan Bukin static int pt_qry_event_fup(struct pt_event *ev,
1572*74fe6c29SRuslan Bukin 			    struct pt_query_decoder *decoder)
1573*74fe6c29SRuslan Bukin {
1574*74fe6c29SRuslan Bukin 	if (!ev || !decoder)
1575*74fe6c29SRuslan Bukin 		return -pte_internal;
1576*74fe6c29SRuslan Bukin 
1577*74fe6c29SRuslan Bukin 	switch (ev->type) {
1578*74fe6c29SRuslan Bukin 	case ptev_overflow:
1579*74fe6c29SRuslan Bukin 		decoder->consume_packet = 1;
1580*74fe6c29SRuslan Bukin 
1581*74fe6c29SRuslan Bukin 		/* We can't afford having a suppressed IP here. */
1582*74fe6c29SRuslan Bukin 		return pt_last_ip_query(&ev->variant.overflow.ip,
1583*74fe6c29SRuslan Bukin 					&decoder->ip);
1584*74fe6c29SRuslan Bukin 
1585*74fe6c29SRuslan Bukin 	case ptev_tsx:
1586*74fe6c29SRuslan Bukin 		if (!(ev->variant.tsx.aborted))
1587*74fe6c29SRuslan Bukin 			decoder->consume_packet = 1;
1588*74fe6c29SRuslan Bukin 
1589*74fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.tsx.ip, ev, decoder);
1590*74fe6c29SRuslan Bukin 
1591*74fe6c29SRuslan Bukin 	case ptev_exstop:
1592*74fe6c29SRuslan Bukin 		decoder->consume_packet = 1;
1593*74fe6c29SRuslan Bukin 
1594*74fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.exstop.ip, ev, decoder);
1595*74fe6c29SRuslan Bukin 
1596*74fe6c29SRuslan Bukin 	case ptev_mwait:
1597*74fe6c29SRuslan Bukin 		decoder->consume_packet = 1;
1598*74fe6c29SRuslan Bukin 
1599*74fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.mwait.ip, ev, decoder);
1600*74fe6c29SRuslan Bukin 
1601*74fe6c29SRuslan Bukin 	case ptev_ptwrite:
1602*74fe6c29SRuslan Bukin 		decoder->consume_packet = 1;
1603*74fe6c29SRuslan Bukin 
1604*74fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.ptwrite.ip, ev, decoder);
1605*74fe6c29SRuslan Bukin 
1606*74fe6c29SRuslan Bukin 	default:
1607*74fe6c29SRuslan Bukin 		break;
1608*74fe6c29SRuslan Bukin 	}
1609*74fe6c29SRuslan Bukin 
1610*74fe6c29SRuslan Bukin 	return -pte_internal;
1611*74fe6c29SRuslan Bukin }
1612*74fe6c29SRuslan Bukin 
pt_qry_decode_fup(struct pt_query_decoder * decoder)1613*74fe6c29SRuslan Bukin int pt_qry_decode_fup(struct pt_query_decoder *decoder)
1614*74fe6c29SRuslan Bukin {
1615*74fe6c29SRuslan Bukin 	struct pt_event *ev;
1616*74fe6c29SRuslan Bukin 	int size, errcode;
1617*74fe6c29SRuslan Bukin 
1618*74fe6c29SRuslan Bukin 	if (!decoder)
1619*74fe6c29SRuslan Bukin 		return -pte_internal;
1620*74fe6c29SRuslan Bukin 
1621*74fe6c29SRuslan Bukin 	size = pt_qry_decode_ip(decoder);
1622*74fe6c29SRuslan Bukin 	if (size < 0)
1623*74fe6c29SRuslan Bukin 		return size;
1624*74fe6c29SRuslan Bukin 
1625*74fe6c29SRuslan Bukin 	/* Process any pending events binding to FUP. */
1626*74fe6c29SRuslan Bukin 	ev = pt_evq_dequeue(&decoder->evq, evb_fup);
1627*74fe6c29SRuslan Bukin 	if (ev) {
1628*74fe6c29SRuslan Bukin 		errcode = pt_qry_event_fup(ev, decoder);
1629*74fe6c29SRuslan Bukin 		if (errcode < 0)
1630*74fe6c29SRuslan Bukin 			return errcode;
1631*74fe6c29SRuslan Bukin 
1632*74fe6c29SRuslan Bukin 		/* Publish the event. */
1633*74fe6c29SRuslan Bukin 		decoder->event = ev;
1634*74fe6c29SRuslan Bukin 
1635*74fe6c29SRuslan Bukin 		/* Process further pending events. */
1636*74fe6c29SRuslan Bukin 		if (pt_evq_pending(&decoder->evq, evb_fup))
1637*74fe6c29SRuslan Bukin 			return 0;
1638*74fe6c29SRuslan Bukin 
1639*74fe6c29SRuslan Bukin 		/* No further events.
1640*74fe6c29SRuslan Bukin 		 *
1641*74fe6c29SRuslan Bukin 		 * If none of the events consumed the packet, we're done.
1642*74fe6c29SRuslan Bukin 		 */
1643*74fe6c29SRuslan Bukin 		if (!decoder->consume_packet)
1644*74fe6c29SRuslan Bukin 			return 0;
1645*74fe6c29SRuslan Bukin 
1646*74fe6c29SRuslan Bukin 		/* We're done with this packet. Clear the flag we set previously
1647*74fe6c29SRuslan Bukin 		 * and consume it.
1648*74fe6c29SRuslan Bukin 		 */
1649*74fe6c29SRuslan Bukin 		decoder->consume_packet = 0;
1650*74fe6c29SRuslan Bukin 	} else {
1651*74fe6c29SRuslan Bukin 		/* FUP indicates an async branch event; it binds to TIP.
1652*74fe6c29SRuslan Bukin 		 *
1653*74fe6c29SRuslan Bukin 		 * We do need an IP in this case.
1654*74fe6c29SRuslan Bukin 		 */
1655*74fe6c29SRuslan Bukin 		uint64_t ip;
1656*74fe6c29SRuslan Bukin 
1657*74fe6c29SRuslan Bukin 		errcode = pt_last_ip_query(&ip, &decoder->ip);
1658*74fe6c29SRuslan Bukin 		if (errcode < 0)
1659*74fe6c29SRuslan Bukin 			return errcode;
1660*74fe6c29SRuslan Bukin 
1661*74fe6c29SRuslan Bukin 		ev = pt_evq_enqueue(&decoder->evq, evb_tip);
1662*74fe6c29SRuslan Bukin 		if (!ev)
1663*74fe6c29SRuslan Bukin 			return -pte_nomem;
1664*74fe6c29SRuslan Bukin 
1665*74fe6c29SRuslan Bukin 		ev->type = ptev_async_branch;
1666*74fe6c29SRuslan Bukin 		ev->variant.async_branch.from = ip;
1667*74fe6c29SRuslan Bukin 
1668*74fe6c29SRuslan Bukin 		errcode = pt_qry_event_time(ev, decoder);
1669*74fe6c29SRuslan Bukin 		if (errcode < 0)
1670*74fe6c29SRuslan Bukin 			return errcode;
1671*74fe6c29SRuslan Bukin 	}
1672*74fe6c29SRuslan Bukin 
1673*74fe6c29SRuslan Bukin 	return pt_qry_consume_fup(decoder, size);
1674*74fe6c29SRuslan Bukin }
1675*74fe6c29SRuslan Bukin 
pt_qry_decode_pip(struct pt_query_decoder * decoder)1676*74fe6c29SRuslan Bukin int pt_qry_decode_pip(struct pt_query_decoder *decoder)
1677*74fe6c29SRuslan Bukin {
1678*74fe6c29SRuslan Bukin 	struct pt_packet_pip packet;
1679*74fe6c29SRuslan Bukin 	struct pt_event *event;
1680*74fe6c29SRuslan Bukin 	int size, errcode;
1681*74fe6c29SRuslan Bukin 
1682*74fe6c29SRuslan Bukin 	if (!decoder)
1683*74fe6c29SRuslan Bukin 		return -pte_internal;
1684*74fe6c29SRuslan Bukin 
1685*74fe6c29SRuslan Bukin 	size = pt_pkt_read_pip(&packet, decoder->pos, &decoder->config);
1686*74fe6c29SRuslan Bukin 	if (size < 0)
1687*74fe6c29SRuslan Bukin 		return size;
1688*74fe6c29SRuslan Bukin 
1689*74fe6c29SRuslan Bukin 	/* Paging events are either standalone or bind to the same TIP packet
1690*74fe6c29SRuslan Bukin 	 * as an in-flight async branch event.
1691*74fe6c29SRuslan Bukin 	 */
1692*74fe6c29SRuslan Bukin 	event = pt_evq_find(&decoder->evq, evb_tip, ptev_async_branch);
1693*74fe6c29SRuslan Bukin 	if (!event) {
1694*74fe6c29SRuslan Bukin 		event = pt_evq_standalone(&decoder->evq);
1695*74fe6c29SRuslan Bukin 		if (!event)
1696*74fe6c29SRuslan Bukin 			return -pte_internal;
1697*74fe6c29SRuslan Bukin 		event->type = ptev_paging;
1698*74fe6c29SRuslan Bukin 		event->variant.paging.cr3 = packet.cr3;
1699*74fe6c29SRuslan Bukin 		event->variant.paging.non_root = packet.nr;
1700*74fe6c29SRuslan Bukin 
1701*74fe6c29SRuslan Bukin 		decoder->event = event;
1702*74fe6c29SRuslan Bukin 	} else {
1703*74fe6c29SRuslan Bukin 		event = pt_evq_enqueue(&decoder->evq, evb_tip);
1704*74fe6c29SRuslan Bukin 		if (!event)
1705*74fe6c29SRuslan Bukin 			return -pte_nomem;
1706*74fe6c29SRuslan Bukin 
1707*74fe6c29SRuslan Bukin 		event->type = ptev_async_paging;
1708*74fe6c29SRuslan Bukin 		event->variant.async_paging.cr3 = packet.cr3;
1709*74fe6c29SRuslan Bukin 		event->variant.async_paging.non_root = packet.nr;
1710*74fe6c29SRuslan Bukin 	}
1711*74fe6c29SRuslan Bukin 
1712*74fe6c29SRuslan Bukin 	errcode = pt_qry_event_time(event, decoder);
1713*74fe6c29SRuslan Bukin 	if (errcode < 0)
1714*74fe6c29SRuslan Bukin 		return errcode;
1715*74fe6c29SRuslan Bukin 
1716*74fe6c29SRuslan Bukin 	decoder->pos += size;
1717*74fe6c29SRuslan Bukin 	return 0;
1718*74fe6c29SRuslan Bukin }
1719*74fe6c29SRuslan Bukin 
pt_qry_header_pip(struct pt_query_decoder * decoder)1720*74fe6c29SRuslan Bukin int pt_qry_header_pip(struct pt_query_decoder *decoder)
1721*74fe6c29SRuslan Bukin {
1722*74fe6c29SRuslan Bukin 	struct pt_packet_pip packet;
1723*74fe6c29SRuslan Bukin 	struct pt_event *event;
1724*74fe6c29SRuslan Bukin 	int size;
1725*74fe6c29SRuslan Bukin 
1726*74fe6c29SRuslan Bukin 	if (!decoder)
1727*74fe6c29SRuslan Bukin 		return -pte_internal;
1728*74fe6c29SRuslan Bukin 
1729*74fe6c29SRuslan Bukin 	size = pt_pkt_read_pip(&packet, decoder->pos, &decoder->config);
1730*74fe6c29SRuslan Bukin 	if (size < 0)
1731*74fe6c29SRuslan Bukin 		return size;
1732*74fe6c29SRuslan Bukin 
1733*74fe6c29SRuslan Bukin 	/* Paging events are reported at the end of the PSB. */
1734*74fe6c29SRuslan Bukin 	event = pt_evq_enqueue(&decoder->evq, evb_psbend);
1735*74fe6c29SRuslan Bukin 	if (!event)
1736*74fe6c29SRuslan Bukin 		return -pte_nomem;
1737*74fe6c29SRuslan Bukin 
1738*74fe6c29SRuslan Bukin 	event->type = ptev_async_paging;
1739*74fe6c29SRuslan Bukin 	event->variant.async_paging.cr3 = packet.cr3;
1740*74fe6c29SRuslan Bukin 	event->variant.async_paging.non_root = packet.nr;
1741*74fe6c29SRuslan Bukin 
1742*74fe6c29SRuslan Bukin 	decoder->pos += size;
1743*74fe6c29SRuslan Bukin 	return 0;
1744*74fe6c29SRuslan Bukin }
1745*74fe6c29SRuslan Bukin 
pt_qry_event_psbend(struct pt_event * ev,struct pt_query_decoder * decoder)1746*74fe6c29SRuslan Bukin static int pt_qry_event_psbend(struct pt_event *ev,
1747*74fe6c29SRuslan Bukin 			       struct pt_query_decoder *decoder)
1748*74fe6c29SRuslan Bukin {
1749*74fe6c29SRuslan Bukin 	int errcode;
1750*74fe6c29SRuslan Bukin 
1751*74fe6c29SRuslan Bukin 	if (!ev || !decoder)
1752*74fe6c29SRuslan Bukin 		return -pte_internal;
1753*74fe6c29SRuslan Bukin 
1754*74fe6c29SRuslan Bukin 	/* PSB+ events are status updates. */
1755*74fe6c29SRuslan Bukin 	ev->status_update = 1;
1756*74fe6c29SRuslan Bukin 
1757*74fe6c29SRuslan Bukin 	errcode = pt_qry_event_time(ev, decoder);
1758*74fe6c29SRuslan Bukin 	if (errcode < 0)
1759*74fe6c29SRuslan Bukin 		return errcode;
1760*74fe6c29SRuslan Bukin 
1761*74fe6c29SRuslan Bukin 	switch (ev->type) {
1762*74fe6c29SRuslan Bukin 	case ptev_async_paging:
1763*74fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.async_paging.ip, ev,
1764*74fe6c29SRuslan Bukin 				       decoder);
1765*74fe6c29SRuslan Bukin 
1766*74fe6c29SRuslan Bukin 	case ptev_exec_mode:
1767*74fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.exec_mode.ip, ev, decoder);
1768*74fe6c29SRuslan Bukin 
1769*74fe6c29SRuslan Bukin 	case ptev_tsx:
1770*74fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.tsx.ip, ev, decoder);
1771*74fe6c29SRuslan Bukin 
1772*74fe6c29SRuslan Bukin 	case ptev_async_vmcs:
1773*74fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.async_vmcs.ip, ev,
1774*74fe6c29SRuslan Bukin 				       decoder);
1775*74fe6c29SRuslan Bukin 
1776*74fe6c29SRuslan Bukin 	case ptev_cbr:
1777*74fe6c29SRuslan Bukin 		return 0;
1778*74fe6c29SRuslan Bukin 
1779*74fe6c29SRuslan Bukin 	case ptev_mnt:
1780*74fe6c29SRuslan Bukin 		/* Maintenance packets may appear anywhere.  Do not mark them as
1781*74fe6c29SRuslan Bukin 		 * status updates even if they appear in PSB+.
1782*74fe6c29SRuslan Bukin 		 */
1783*74fe6c29SRuslan Bukin 		ev->status_update = 0;
1784*74fe6c29SRuslan Bukin 		return 0;
1785*74fe6c29SRuslan Bukin 
1786*74fe6c29SRuslan Bukin 	default:
1787*74fe6c29SRuslan Bukin 		break;
1788*74fe6c29SRuslan Bukin 	}
1789*74fe6c29SRuslan Bukin 
1790*74fe6c29SRuslan Bukin 	return -pte_internal;
1791*74fe6c29SRuslan Bukin }
1792*74fe6c29SRuslan Bukin 
pt_qry_process_pending_psb_events(struct pt_query_decoder * decoder)1793*74fe6c29SRuslan Bukin static int pt_qry_process_pending_psb_events(struct pt_query_decoder *decoder)
1794*74fe6c29SRuslan Bukin {
1795*74fe6c29SRuslan Bukin 	struct pt_event *ev;
1796*74fe6c29SRuslan Bukin 	int errcode;
1797*74fe6c29SRuslan Bukin 
1798*74fe6c29SRuslan Bukin 	if (!decoder)
1799*74fe6c29SRuslan Bukin 		return -pte_internal;
1800*74fe6c29SRuslan Bukin 
1801*74fe6c29SRuslan Bukin 	ev = pt_evq_dequeue(&decoder->evq, evb_psbend);
1802*74fe6c29SRuslan Bukin 	if (!ev)
1803*74fe6c29SRuslan Bukin 		return 0;
1804*74fe6c29SRuslan Bukin 
1805*74fe6c29SRuslan Bukin 	errcode = pt_qry_event_psbend(ev, decoder);
1806*74fe6c29SRuslan Bukin 	if (errcode < 0)
1807*74fe6c29SRuslan Bukin 		return errcode;
1808*74fe6c29SRuslan Bukin 
1809*74fe6c29SRuslan Bukin 	/* Publish the event. */
1810*74fe6c29SRuslan Bukin 	decoder->event = ev;
1811*74fe6c29SRuslan Bukin 
1812*74fe6c29SRuslan Bukin 	/* Signal a pending event. */
1813*74fe6c29SRuslan Bukin 	return 1;
1814*74fe6c29SRuslan Bukin }
1815*74fe6c29SRuslan Bukin 
1816*74fe6c29SRuslan Bukin /* Create a standalone overflow event with tracing disabled.
1817*74fe6c29SRuslan Bukin  *
1818*74fe6c29SRuslan Bukin  * Creates and published the event and disables tracing in @decoder.
1819*74fe6c29SRuslan Bukin  *
1820*74fe6c29SRuslan Bukin  * Returns zero on success, a negative pt_error_code otherwise.
1821*74fe6c29SRuslan Bukin  */
pt_qry_event_ovf_disabled(struct pt_query_decoder * decoder)1822*74fe6c29SRuslan Bukin static int pt_qry_event_ovf_disabled(struct pt_query_decoder *decoder)
1823*74fe6c29SRuslan Bukin {
1824*74fe6c29SRuslan Bukin 	struct pt_event *ev;
1825*74fe6c29SRuslan Bukin 
1826*74fe6c29SRuslan Bukin 	if (!decoder)
1827*74fe6c29SRuslan Bukin 		return -pte_internal;
1828*74fe6c29SRuslan Bukin 
1829*74fe6c29SRuslan Bukin 	ev = pt_evq_standalone(&decoder->evq);
1830*74fe6c29SRuslan Bukin 	if (!ev)
1831*74fe6c29SRuslan Bukin 		return -pte_internal;
1832*74fe6c29SRuslan Bukin 
1833*74fe6c29SRuslan Bukin 	ev->type = ptev_overflow;
1834*74fe6c29SRuslan Bukin 
1835*74fe6c29SRuslan Bukin 	/* We suppress the IP to indicate that tracing has been disabled before
1836*74fe6c29SRuslan Bukin 	 * the overflow resolved.  There can be several events before tracing is
1837*74fe6c29SRuslan Bukin 	 * enabled again.
1838*74fe6c29SRuslan Bukin 	 */
1839*74fe6c29SRuslan Bukin 	ev->ip_suppressed = 1;
1840*74fe6c29SRuslan Bukin 
1841*74fe6c29SRuslan Bukin 	decoder->enabled = 0;
1842*74fe6c29SRuslan Bukin 	decoder->event = ev;
1843*74fe6c29SRuslan Bukin 
1844*74fe6c29SRuslan Bukin 	return pt_qry_event_time(ev, decoder);
1845*74fe6c29SRuslan Bukin }
1846*74fe6c29SRuslan Bukin 
1847*74fe6c29SRuslan Bukin /* Queues an overflow event with tracing enabled.
1848*74fe6c29SRuslan Bukin  *
1849*74fe6c29SRuslan Bukin  * Creates and enqueues the event and enables tracing in @decoder.
1850*74fe6c29SRuslan Bukin  *
1851*74fe6c29SRuslan Bukin  * Returns zero on success, a negative pt_error_code otherwise.
1852*74fe6c29SRuslan Bukin  */
pt_qry_event_ovf_enabled(struct pt_query_decoder * decoder)1853*74fe6c29SRuslan Bukin static int pt_qry_event_ovf_enabled(struct pt_query_decoder *decoder)
1854*74fe6c29SRuslan Bukin {
1855*74fe6c29SRuslan Bukin 	struct pt_event *ev;
1856*74fe6c29SRuslan Bukin 
1857*74fe6c29SRuslan Bukin 	if (!decoder)
1858*74fe6c29SRuslan Bukin 		return -pte_internal;
1859*74fe6c29SRuslan Bukin 
1860*74fe6c29SRuslan Bukin 	ev = pt_evq_enqueue(&decoder->evq, evb_fup);
1861*74fe6c29SRuslan Bukin 	if (!ev)
1862*74fe6c29SRuslan Bukin 		return -pte_internal;
1863*74fe6c29SRuslan Bukin 
1864*74fe6c29SRuslan Bukin 	ev->type = ptev_overflow;
1865*74fe6c29SRuslan Bukin 
1866*74fe6c29SRuslan Bukin 	decoder->enabled = 1;
1867*74fe6c29SRuslan Bukin 
1868*74fe6c29SRuslan Bukin 	return pt_qry_event_time(ev, decoder);
1869*74fe6c29SRuslan Bukin }
1870*74fe6c29SRuslan Bukin 
1871*74fe6c29SRuslan Bukin /* Recover from SKD010.
1872*74fe6c29SRuslan Bukin  *
1873*74fe6c29SRuslan Bukin  * Creates and publishes an overflow event at @packet's IP payload.
1874*74fe6c29SRuslan Bukin  *
1875*74fe6c29SRuslan Bukin  * Further updates @decoder as follows:
1876*74fe6c29SRuslan Bukin  *
1877*74fe6c29SRuslan Bukin  *   - set time tracking to @time and @tcal
1878*74fe6c29SRuslan Bukin  *   - set the position to @offset
1879*74fe6c29SRuslan Bukin  *   - set ip to @packet's IP payload
1880*74fe6c29SRuslan Bukin  *   - set tracing to be enabled
1881*74fe6c29SRuslan Bukin  *
1882*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
1883*74fe6c29SRuslan Bukin  */
skd010_recover(struct pt_query_decoder * decoder,const struct pt_packet_ip * packet,const struct pt_time_cal * tcal,const struct pt_time * time,uint64_t offset)1884*74fe6c29SRuslan Bukin static int skd010_recover(struct pt_query_decoder *decoder,
1885*74fe6c29SRuslan Bukin 			  const struct pt_packet_ip *packet,
1886*74fe6c29SRuslan Bukin 			  const struct pt_time_cal *tcal,
1887*74fe6c29SRuslan Bukin 			  const struct pt_time *time, uint64_t offset)
1888*74fe6c29SRuslan Bukin {
1889*74fe6c29SRuslan Bukin 	struct pt_last_ip ip;
1890*74fe6c29SRuslan Bukin 	struct pt_event *ev;
1891*74fe6c29SRuslan Bukin 	int errcode;
1892*74fe6c29SRuslan Bukin 
1893*74fe6c29SRuslan Bukin 	if (!decoder || !packet || !tcal || !time)
1894*74fe6c29SRuslan Bukin 		return -pte_internal;
1895*74fe6c29SRuslan Bukin 
1896*74fe6c29SRuslan Bukin 	/* We use the decoder's IP.  It should be newly initialized. */
1897*74fe6c29SRuslan Bukin 	ip = decoder->ip;
1898*74fe6c29SRuslan Bukin 
1899*74fe6c29SRuslan Bukin 	/* Extract the IP payload from the packet. */
1900*74fe6c29SRuslan Bukin 	errcode = pt_last_ip_update_ip(&ip, packet, &decoder->config);
1901*74fe6c29SRuslan Bukin 	if (errcode < 0)
1902*74fe6c29SRuslan Bukin 		return errcode;
1903*74fe6c29SRuslan Bukin 
1904*74fe6c29SRuslan Bukin 	/* Synthesize the overflow event. */
1905*74fe6c29SRuslan Bukin 	ev = pt_evq_standalone(&decoder->evq);
1906*74fe6c29SRuslan Bukin 	if (!ev)
1907*74fe6c29SRuslan Bukin 		return -pte_internal;
1908*74fe6c29SRuslan Bukin 
1909*74fe6c29SRuslan Bukin 	ev->type = ptev_overflow;
1910*74fe6c29SRuslan Bukin 
1911*74fe6c29SRuslan Bukin 	/* We do need a full IP. */
1912*74fe6c29SRuslan Bukin 	errcode = pt_last_ip_query(&ev->variant.overflow.ip, &ip);
1913*74fe6c29SRuslan Bukin 	if (errcode < 0)
1914*74fe6c29SRuslan Bukin 		return -pte_bad_context;
1915*74fe6c29SRuslan Bukin 
1916*74fe6c29SRuslan Bukin 	/* We continue decoding at the given offset. */
1917*74fe6c29SRuslan Bukin 	decoder->pos = decoder->config.begin + offset;
1918*74fe6c29SRuslan Bukin 
1919*74fe6c29SRuslan Bukin 	/* Tracing is enabled. */
1920*74fe6c29SRuslan Bukin 	decoder->enabled = 1;
1921*74fe6c29SRuslan Bukin 	decoder->ip = ip;
1922*74fe6c29SRuslan Bukin 
1923*74fe6c29SRuslan Bukin 	decoder->time = *time;
1924*74fe6c29SRuslan Bukin 	decoder->tcal = *tcal;
1925*74fe6c29SRuslan Bukin 
1926*74fe6c29SRuslan Bukin 	/* Publish the event. */
1927*74fe6c29SRuslan Bukin 	decoder->event = ev;
1928*74fe6c29SRuslan Bukin 
1929*74fe6c29SRuslan Bukin 	return pt_qry_event_time(ev, decoder);
1930*74fe6c29SRuslan Bukin }
1931*74fe6c29SRuslan Bukin 
1932*74fe6c29SRuslan Bukin /* Recover from SKD010 with tracing disabled.
1933*74fe6c29SRuslan Bukin  *
1934*74fe6c29SRuslan Bukin  * Creates and publishes a standalone overflow event.
1935*74fe6c29SRuslan Bukin  *
1936*74fe6c29SRuslan Bukin  * Further updates @decoder as follows:
1937*74fe6c29SRuslan Bukin  *
1938*74fe6c29SRuslan Bukin  *   - set time tracking to @time and @tcal
1939*74fe6c29SRuslan Bukin  *   - set the position to @offset
1940*74fe6c29SRuslan Bukin  *   - set tracing to be disabled
1941*74fe6c29SRuslan Bukin  *
1942*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
1943*74fe6c29SRuslan Bukin  */
skd010_recover_disabled(struct pt_query_decoder * decoder,const struct pt_time_cal * tcal,const struct pt_time * time,uint64_t offset)1944*74fe6c29SRuslan Bukin static int skd010_recover_disabled(struct pt_query_decoder *decoder,
1945*74fe6c29SRuslan Bukin 				   const struct pt_time_cal *tcal,
1946*74fe6c29SRuslan Bukin 				   const struct pt_time *time, uint64_t offset)
1947*74fe6c29SRuslan Bukin {
1948*74fe6c29SRuslan Bukin 	if (!decoder || !tcal || !time)
1949*74fe6c29SRuslan Bukin 		return -pte_internal;
1950*74fe6c29SRuslan Bukin 
1951*74fe6c29SRuslan Bukin 	decoder->time = *time;
1952*74fe6c29SRuslan Bukin 	decoder->tcal = *tcal;
1953*74fe6c29SRuslan Bukin 
1954*74fe6c29SRuslan Bukin 	/* We continue decoding at the given offset. */
1955*74fe6c29SRuslan Bukin 	decoder->pos = decoder->config.begin + offset;
1956*74fe6c29SRuslan Bukin 
1957*74fe6c29SRuslan Bukin 	return pt_qry_event_ovf_disabled(decoder);
1958*74fe6c29SRuslan Bukin }
1959*74fe6c29SRuslan Bukin 
1960*74fe6c29SRuslan Bukin /* Scan ahead for a packet at which to resume after an overflow.
1961*74fe6c29SRuslan Bukin  *
1962*74fe6c29SRuslan Bukin  * This function is called after an OVF without a corresponding FUP.  This
1963*74fe6c29SRuslan Bukin  * normally means that the overflow resolved while tracing was disabled.
1964*74fe6c29SRuslan Bukin  *
1965*74fe6c29SRuslan Bukin  * With erratum SKD010 it might also mean that the FUP (or TIP.PGE) was dropped.
1966*74fe6c29SRuslan Bukin  * The overflow thus resolved while tracing was enabled (or tracing was enabled
1967*74fe6c29SRuslan Bukin  * after the overflow resolved).  Search for an indication whether tracing is
1968*74fe6c29SRuslan Bukin  * enabled or disabled by scanning upcoming packets.
1969*74fe6c29SRuslan Bukin  *
1970*74fe6c29SRuslan Bukin  * If we can confirm that tracing is disabled, the erratum does not apply and we
1971*74fe6c29SRuslan Bukin  * can continue normally.
1972*74fe6c29SRuslan Bukin  *
1973*74fe6c29SRuslan Bukin  * If we can confirm that tracing is enabled, the erratum applies and we try to
1974*74fe6c29SRuslan Bukin  * recover by synchronizing at a later packet and a different IP.  If we can't
1975*74fe6c29SRuslan Bukin  * recover, pretend the erratum didn't apply so we run into the error later.
1976*74fe6c29SRuslan Bukin  * Since this assumes that tracing is disabled, no harm should be done, i.e. no
1977*74fe6c29SRuslan Bukin  * bad trace should be generated.
1978*74fe6c29SRuslan Bukin  *
1979*74fe6c29SRuslan Bukin  * Returns zero if the overflow is handled.
1980*74fe6c29SRuslan Bukin  * Returns a positive value if the overflow is not yet handled.
1981*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
1982*74fe6c29SRuslan Bukin  */
skd010_scan_for_ovf_resume(struct pt_packet_decoder * pkt,struct pt_query_decoder * decoder)1983*74fe6c29SRuslan Bukin static int skd010_scan_for_ovf_resume(struct pt_packet_decoder *pkt,
1984*74fe6c29SRuslan Bukin 				      struct pt_query_decoder *decoder)
1985*74fe6c29SRuslan Bukin {
1986*74fe6c29SRuslan Bukin 	struct pt_time_cal tcal;
1987*74fe6c29SRuslan Bukin 	struct pt_time time;
1988*74fe6c29SRuslan Bukin 	struct {
1989*74fe6c29SRuslan Bukin 		struct pt_time_cal tcal;
1990*74fe6c29SRuslan Bukin 		struct pt_time time;
1991*74fe6c29SRuslan Bukin 		uint64_t offset;
1992*74fe6c29SRuslan Bukin 	} mode_tsx;
1993*74fe6c29SRuslan Bukin 	int errcode;
1994*74fe6c29SRuslan Bukin 
1995*74fe6c29SRuslan Bukin 	if (!decoder)
1996*74fe6c29SRuslan Bukin 		return -pte_internal;
1997*74fe6c29SRuslan Bukin 
1998*74fe6c29SRuslan Bukin 	/* Keep track of time as we skip packets. */
1999*74fe6c29SRuslan Bukin 	time = decoder->time;
2000*74fe6c29SRuslan Bukin 	tcal = decoder->tcal;
2001*74fe6c29SRuslan Bukin 
2002*74fe6c29SRuslan Bukin 	/* Keep track of a potential recovery point at MODE.TSX. */
2003*74fe6c29SRuslan Bukin 	memset(&mode_tsx, 0, sizeof(mode_tsx));
2004*74fe6c29SRuslan Bukin 
2005*74fe6c29SRuslan Bukin 	for (;;) {
2006*74fe6c29SRuslan Bukin 		struct pt_packet packet;
2007*74fe6c29SRuslan Bukin 		uint64_t offset;
2008*74fe6c29SRuslan Bukin 
2009*74fe6c29SRuslan Bukin 		errcode = pt_pkt_get_offset(pkt, &offset);
2010*74fe6c29SRuslan Bukin 		if (errcode < 0)
2011*74fe6c29SRuslan Bukin 			return errcode;
2012*74fe6c29SRuslan Bukin 
2013*74fe6c29SRuslan Bukin 		errcode = pt_pkt_next(pkt, &packet, sizeof(packet));
2014*74fe6c29SRuslan Bukin 		if (errcode < 0) {
2015*74fe6c29SRuslan Bukin 			/* Let's assume the trace is correct if we run out
2016*74fe6c29SRuslan Bukin 			 * of packets.
2017*74fe6c29SRuslan Bukin 			 */
2018*74fe6c29SRuslan Bukin 			if (errcode == -pte_eos)
2019*74fe6c29SRuslan Bukin 				errcode = 1;
2020*74fe6c29SRuslan Bukin 
2021*74fe6c29SRuslan Bukin 			return errcode;
2022*74fe6c29SRuslan Bukin 		}
2023*74fe6c29SRuslan Bukin 
2024*74fe6c29SRuslan Bukin 		switch (packet.type) {
2025*74fe6c29SRuslan Bukin 		case ppt_tip_pge:
2026*74fe6c29SRuslan Bukin 			/* Everything is fine.  There is nothing to do. */
2027*74fe6c29SRuslan Bukin 			return 1;
2028*74fe6c29SRuslan Bukin 
2029*74fe6c29SRuslan Bukin 		case ppt_tip_pgd:
2030*74fe6c29SRuslan Bukin 			/* This is a clear indication that the erratum
2031*74fe6c29SRuslan Bukin 			 * applies.
2032*74fe6c29SRuslan Bukin 			 *
2033*74fe6c29SRuslan Bukin 			 * We synchronize after the disable.
2034*74fe6c29SRuslan Bukin 			 */
2035*74fe6c29SRuslan Bukin 			return skd010_recover_disabled(decoder, &tcal, &time,
2036*74fe6c29SRuslan Bukin 						       offset + packet.size);
2037*74fe6c29SRuslan Bukin 
2038*74fe6c29SRuslan Bukin 		case ppt_tnt_8:
2039*74fe6c29SRuslan Bukin 		case ppt_tnt_64:
2040*74fe6c29SRuslan Bukin 			/* This is a clear indication that the erratum
2041*74fe6c29SRuslan Bukin 			 * apllies.
2042*74fe6c29SRuslan Bukin 			 *
2043*74fe6c29SRuslan Bukin 			 * Yet, we can't recover from it as we wouldn't know how
2044*74fe6c29SRuslan Bukin 			 * many TNT bits will have been used when we eventually
2045*74fe6c29SRuslan Bukin 			 * find an IP packet at which to resume tracing.
2046*74fe6c29SRuslan Bukin 			 */
2047*74fe6c29SRuslan Bukin 			return 1;
2048*74fe6c29SRuslan Bukin 
2049*74fe6c29SRuslan Bukin 		case ppt_pip:
2050*74fe6c29SRuslan Bukin 		case ppt_vmcs:
2051*74fe6c29SRuslan Bukin 			/* We could track those changes and synthesize extra
2052*74fe6c29SRuslan Bukin 			 * events after the overflow event when recovering from
2053*74fe6c29SRuslan Bukin 			 * the erratum.  This requires infrastructure that we
2054*74fe6c29SRuslan Bukin 			 * don't currently have, though, so we're not going to
2055*74fe6c29SRuslan Bukin 			 * do it.
2056*74fe6c29SRuslan Bukin 			 *
2057*74fe6c29SRuslan Bukin 			 * Instead, we ignore those changes.  We already don't
2058*74fe6c29SRuslan Bukin 			 * know how many other changes were lost in the
2059*74fe6c29SRuslan Bukin 			 * overflow.
2060*74fe6c29SRuslan Bukin 			 */
2061*74fe6c29SRuslan Bukin 			break;
2062*74fe6c29SRuslan Bukin 
2063*74fe6c29SRuslan Bukin 		case ppt_mode:
2064*74fe6c29SRuslan Bukin 			switch (packet.payload.mode.leaf) {
2065*74fe6c29SRuslan Bukin 			case pt_mol_exec:
2066*74fe6c29SRuslan Bukin 				/* A MODE.EXEC packet binds to TIP, i.e.
2067*74fe6c29SRuslan Bukin 				 *
2068*74fe6c29SRuslan Bukin 				 *   TIP.PGE:  everything is fine
2069*74fe6c29SRuslan Bukin 				 *   TIP:      the erratum applies
2070*74fe6c29SRuslan Bukin 				 *
2071*74fe6c29SRuslan Bukin 				 * In the TIP.PGE case, we may just follow the
2072*74fe6c29SRuslan Bukin 				 * normal code flow.
2073*74fe6c29SRuslan Bukin 				 *
2074*74fe6c29SRuslan Bukin 				 * In the TIP case, we'd be able to re-sync at
2075*74fe6c29SRuslan Bukin 				 * the TIP IP but have to skip packets up to and
2076*74fe6c29SRuslan Bukin 				 * including the TIP.
2077*74fe6c29SRuslan Bukin 				 *
2078*74fe6c29SRuslan Bukin 				 * We'd need to synthesize the MODE.EXEC event
2079*74fe6c29SRuslan Bukin 				 * after the overflow event when recovering at
2080*74fe6c29SRuslan Bukin 				 * the TIP.  We lack the infrastructure for this
2081*74fe6c29SRuslan Bukin 				 * - it's getting too complicated.
2082*74fe6c29SRuslan Bukin 				 *
2083*74fe6c29SRuslan Bukin 				 * Instead, we ignore the execution mode change;
2084*74fe6c29SRuslan Bukin 				 * we already don't know how many more such
2085*74fe6c29SRuslan Bukin 				 * changes were lost in the overflow.
2086*74fe6c29SRuslan Bukin 				 */
2087*74fe6c29SRuslan Bukin 				break;
2088*74fe6c29SRuslan Bukin 
2089*74fe6c29SRuslan Bukin 			case pt_mol_tsx:
2090*74fe6c29SRuslan Bukin 				/* A MODE.TSX packet may be standalone or bind
2091*74fe6c29SRuslan Bukin 				 * to FUP.
2092*74fe6c29SRuslan Bukin 				 *
2093*74fe6c29SRuslan Bukin 				 * If this is the second MODE.TSX, we're sure
2094*74fe6c29SRuslan Bukin 				 * that tracing is disabled and everything is
2095*74fe6c29SRuslan Bukin 				 * fine.
2096*74fe6c29SRuslan Bukin 				 */
2097*74fe6c29SRuslan Bukin 				if (mode_tsx.offset)
2098*74fe6c29SRuslan Bukin 					return 1;
2099*74fe6c29SRuslan Bukin 
2100*74fe6c29SRuslan Bukin 				/* If we find the FUP this packet binds to, we
2101*74fe6c29SRuslan Bukin 				 * may recover at the FUP IP and restart
2102*74fe6c29SRuslan Bukin 				 * processing packets from here.  Remember the
2103*74fe6c29SRuslan Bukin 				 * current state.
2104*74fe6c29SRuslan Bukin 				 */
2105*74fe6c29SRuslan Bukin 				mode_tsx.offset = offset;
2106*74fe6c29SRuslan Bukin 				mode_tsx.time = time;
2107*74fe6c29SRuslan Bukin 				mode_tsx.tcal = tcal;
2108*74fe6c29SRuslan Bukin 
2109*74fe6c29SRuslan Bukin 				break;
2110*74fe6c29SRuslan Bukin 			}
2111*74fe6c29SRuslan Bukin 
2112*74fe6c29SRuslan Bukin 			break;
2113*74fe6c29SRuslan Bukin 
2114*74fe6c29SRuslan Bukin 		case ppt_fup:
2115*74fe6c29SRuslan Bukin 			/* This is a pretty good indication that tracing
2116*74fe6c29SRuslan Bukin 			 * is indeed enabled and the erratum applies.
2117*74fe6c29SRuslan Bukin 			 */
2118*74fe6c29SRuslan Bukin 
2119*74fe6c29SRuslan Bukin 			/* If we got a MODE.TSX packet before, we synchronize at
2120*74fe6c29SRuslan Bukin 			 * the FUP IP but continue decoding packets starting
2121*74fe6c29SRuslan Bukin 			 * from the MODE.TSX.
2122*74fe6c29SRuslan Bukin 			 */
2123*74fe6c29SRuslan Bukin 			if (mode_tsx.offset)
2124*74fe6c29SRuslan Bukin 				return skd010_recover(decoder,
2125*74fe6c29SRuslan Bukin 						      &packet.payload.ip,
2126*74fe6c29SRuslan Bukin 						      &mode_tsx.tcal,
2127*74fe6c29SRuslan Bukin 						      &mode_tsx.time,
2128*74fe6c29SRuslan Bukin 						      mode_tsx.offset);
2129*74fe6c29SRuslan Bukin 
2130*74fe6c29SRuslan Bukin 			/* Without a preceding MODE.TSX, this FUP is the start
2131*74fe6c29SRuslan Bukin 			 * of an async branch or disable.  We synchronize at the
2132*74fe6c29SRuslan Bukin 			 * FUP IP and continue decoding packets from here.
2133*74fe6c29SRuslan Bukin 			 */
2134*74fe6c29SRuslan Bukin 			return skd010_recover(decoder, &packet.payload.ip,
2135*74fe6c29SRuslan Bukin 					      &tcal, &time, offset);
2136*74fe6c29SRuslan Bukin 
2137*74fe6c29SRuslan Bukin 		case ppt_tip:
2138*74fe6c29SRuslan Bukin 			/* We syhchronize at the TIP IP and continue decoding
2139*74fe6c29SRuslan Bukin 			 * packets after the TIP packet.
2140*74fe6c29SRuslan Bukin 			 */
2141*74fe6c29SRuslan Bukin 			return skd010_recover(decoder, &packet.payload.ip,
2142*74fe6c29SRuslan Bukin 					      &tcal, &time,
2143*74fe6c29SRuslan Bukin 					      offset + packet.size);
2144*74fe6c29SRuslan Bukin 
2145*74fe6c29SRuslan Bukin 		case ppt_psb:
2146*74fe6c29SRuslan Bukin 			/* We reached a synchronization point.  Tracing is
2147*74fe6c29SRuslan Bukin 			 * enabled if and only if the PSB+ contains a FUP.
2148*74fe6c29SRuslan Bukin 			 */
2149*74fe6c29SRuslan Bukin 			errcode = pt_qry_find_header_fup(&packet, pkt);
2150*74fe6c29SRuslan Bukin 			if (errcode < 0) {
2151*74fe6c29SRuslan Bukin 				/* If we ran out of packets, we can't tell.
2152*74fe6c29SRuslan Bukin 				 * Let's assume the trace is correct.
2153*74fe6c29SRuslan Bukin 				 */
2154*74fe6c29SRuslan Bukin 				if (errcode == -pte_eos)
2155*74fe6c29SRuslan Bukin 					errcode = 1;
2156*74fe6c29SRuslan Bukin 
2157*74fe6c29SRuslan Bukin 				return errcode;
2158*74fe6c29SRuslan Bukin 			}
2159*74fe6c29SRuslan Bukin 
2160*74fe6c29SRuslan Bukin 			/* If there is no FUP, tracing is disabled and
2161*74fe6c29SRuslan Bukin 			 * everything is fine.
2162*74fe6c29SRuslan Bukin 			 */
2163*74fe6c29SRuslan Bukin 			if (!errcode)
2164*74fe6c29SRuslan Bukin 				return 1;
2165*74fe6c29SRuslan Bukin 
2166*74fe6c29SRuslan Bukin 			/* We should have a FUP. */
2167*74fe6c29SRuslan Bukin 			if (packet.type != ppt_fup)
2168*74fe6c29SRuslan Bukin 				return -pte_internal;
2169*74fe6c29SRuslan Bukin 
2170*74fe6c29SRuslan Bukin 			/* Otherwise, we may synchronize at the FUP IP and
2171*74fe6c29SRuslan Bukin 			 * continue decoding packets at the PSB.
2172*74fe6c29SRuslan Bukin 			 */
2173*74fe6c29SRuslan Bukin 			return skd010_recover(decoder, &packet.payload.ip,
2174*74fe6c29SRuslan Bukin 					      &tcal, &time, offset);
2175*74fe6c29SRuslan Bukin 
2176*74fe6c29SRuslan Bukin 		case ppt_psbend:
2177*74fe6c29SRuslan Bukin 			/* We shouldn't see this. */
2178*74fe6c29SRuslan Bukin 			return -pte_bad_context;
2179*74fe6c29SRuslan Bukin 
2180*74fe6c29SRuslan Bukin 		case ppt_ovf:
2181*74fe6c29SRuslan Bukin 		case ppt_stop:
2182*74fe6c29SRuslan Bukin 			/* It doesn't matter if it had been enabled or disabled
2183*74fe6c29SRuslan Bukin 			 * before.  We may resume normally.
2184*74fe6c29SRuslan Bukin 			 */
2185*74fe6c29SRuslan Bukin 			return 1;
2186*74fe6c29SRuslan Bukin 
2187*74fe6c29SRuslan Bukin 		case ppt_unknown:
2188*74fe6c29SRuslan Bukin 		case ppt_invalid:
2189*74fe6c29SRuslan Bukin 			/* We can't skip this packet. */
2190*74fe6c29SRuslan Bukin 			return 1;
2191*74fe6c29SRuslan Bukin 
2192*74fe6c29SRuslan Bukin 		case ppt_pad:
2193*74fe6c29SRuslan Bukin 		case ppt_mnt:
2194*74fe6c29SRuslan Bukin 		case ppt_pwre:
2195*74fe6c29SRuslan Bukin 		case ppt_pwrx:
2196*74fe6c29SRuslan Bukin 			/* Ignore this packet. */
2197*74fe6c29SRuslan Bukin 			break;
2198*74fe6c29SRuslan Bukin 
2199*74fe6c29SRuslan Bukin 		case ppt_exstop:
2200*74fe6c29SRuslan Bukin 			/* We may skip a stand-alone EXSTOP. */
2201*74fe6c29SRuslan Bukin 			if (!packet.payload.exstop.ip)
2202*74fe6c29SRuslan Bukin 				break;
2203*74fe6c29SRuslan Bukin 
2204*74fe6c29SRuslan Bukin 			fallthrough;
2205*74fe6c29SRuslan Bukin 		case ppt_mwait:
2206*74fe6c29SRuslan Bukin 			/* To skip this packet, we'd need to take care of the
2207*74fe6c29SRuslan Bukin 			 * FUP it binds to.  This is getting complicated.
2208*74fe6c29SRuslan Bukin 			 */
2209*74fe6c29SRuslan Bukin 			return 1;
2210*74fe6c29SRuslan Bukin 
2211*74fe6c29SRuslan Bukin 		case ppt_ptw:
2212*74fe6c29SRuslan Bukin 			/* We may skip a stand-alone PTW. */
2213*74fe6c29SRuslan Bukin 			if (!packet.payload.ptw.ip)
2214*74fe6c29SRuslan Bukin 				break;
2215*74fe6c29SRuslan Bukin 
2216*74fe6c29SRuslan Bukin 			/* To skip this packet, we'd need to take care of the
2217*74fe6c29SRuslan Bukin 			 * FUP it binds to.  This is getting complicated.
2218*74fe6c29SRuslan Bukin 			 */
2219*74fe6c29SRuslan Bukin 			return 1;
2220*74fe6c29SRuslan Bukin 
2221*74fe6c29SRuslan Bukin 		case ppt_tsc:
2222*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2223*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_tsc(&time, &tcal,
2224*74fe6c29SRuslan Bukin 						   &packet.payload.tsc,
2225*74fe6c29SRuslan Bukin 						   &decoder->config);
2226*74fe6c29SRuslan Bukin 			if (errcode < 0)
2227*74fe6c29SRuslan Bukin 				return errcode;
2228*74fe6c29SRuslan Bukin 
2229*74fe6c29SRuslan Bukin 			break;
2230*74fe6c29SRuslan Bukin 
2231*74fe6c29SRuslan Bukin 		case ppt_cbr:
2232*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2233*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_cbr(&time, &tcal,
2234*74fe6c29SRuslan Bukin 						   &packet.payload.cbr,
2235*74fe6c29SRuslan Bukin 						   &decoder->config);
2236*74fe6c29SRuslan Bukin 			if (errcode < 0)
2237*74fe6c29SRuslan Bukin 				return errcode;
2238*74fe6c29SRuslan Bukin 
2239*74fe6c29SRuslan Bukin 			break;
2240*74fe6c29SRuslan Bukin 
2241*74fe6c29SRuslan Bukin 		case ppt_tma:
2242*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2243*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_tma(&time, &tcal,
2244*74fe6c29SRuslan Bukin 						   &packet.payload.tma,
2245*74fe6c29SRuslan Bukin 						   &decoder->config);
2246*74fe6c29SRuslan Bukin 			if (errcode < 0)
2247*74fe6c29SRuslan Bukin 				return errcode;
2248*74fe6c29SRuslan Bukin 
2249*74fe6c29SRuslan Bukin 			break;
2250*74fe6c29SRuslan Bukin 
2251*74fe6c29SRuslan Bukin 		case ppt_mtc:
2252*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2253*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_mtc(&time, &tcal,
2254*74fe6c29SRuslan Bukin 						   &packet.payload.mtc,
2255*74fe6c29SRuslan Bukin 						   &decoder->config);
2256*74fe6c29SRuslan Bukin 			if (errcode < 0)
2257*74fe6c29SRuslan Bukin 				return errcode;
2258*74fe6c29SRuslan Bukin 
2259*74fe6c29SRuslan Bukin 			break;
2260*74fe6c29SRuslan Bukin 
2261*74fe6c29SRuslan Bukin 		case ppt_cyc:
2262*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2263*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_cyc(&time, &tcal,
2264*74fe6c29SRuslan Bukin 						   &packet.payload.cyc,
2265*74fe6c29SRuslan Bukin 						   &decoder->config);
2266*74fe6c29SRuslan Bukin 			if (errcode < 0)
2267*74fe6c29SRuslan Bukin 				return errcode;
2268*74fe6c29SRuslan Bukin 
2269*74fe6c29SRuslan Bukin 			break;
2270*74fe6c29SRuslan Bukin 		}
2271*74fe6c29SRuslan Bukin 	}
2272*74fe6c29SRuslan Bukin }
2273*74fe6c29SRuslan Bukin 
pt_qry_handle_skd010(struct pt_query_decoder * decoder)2274*74fe6c29SRuslan Bukin static int pt_qry_handle_skd010(struct pt_query_decoder *decoder)
2275*74fe6c29SRuslan Bukin {
2276*74fe6c29SRuslan Bukin 	struct pt_packet_decoder pkt;
2277*74fe6c29SRuslan Bukin 	uint64_t offset;
2278*74fe6c29SRuslan Bukin 	int errcode;
2279*74fe6c29SRuslan Bukin 
2280*74fe6c29SRuslan Bukin 	if (!decoder)
2281*74fe6c29SRuslan Bukin 		return -pte_internal;
2282*74fe6c29SRuslan Bukin 
2283*74fe6c29SRuslan Bukin 	errcode = pt_qry_get_offset(decoder, &offset);
2284*74fe6c29SRuslan Bukin 	if (errcode < 0)
2285*74fe6c29SRuslan Bukin 		return errcode;
2286*74fe6c29SRuslan Bukin 
2287*74fe6c29SRuslan Bukin 	errcode = pt_pkt_decoder_init(&pkt, &decoder->config);
2288*74fe6c29SRuslan Bukin 	if (errcode < 0)
2289*74fe6c29SRuslan Bukin 		return errcode;
2290*74fe6c29SRuslan Bukin 
2291*74fe6c29SRuslan Bukin 	errcode = pt_pkt_sync_set(&pkt, offset);
2292*74fe6c29SRuslan Bukin 	if (errcode >= 0)
2293*74fe6c29SRuslan Bukin 		errcode = skd010_scan_for_ovf_resume(&pkt, decoder);
2294*74fe6c29SRuslan Bukin 
2295*74fe6c29SRuslan Bukin 	pt_pkt_decoder_fini(&pkt);
2296*74fe6c29SRuslan Bukin 	return errcode;
2297*74fe6c29SRuslan Bukin }
2298*74fe6c29SRuslan Bukin 
2299*74fe6c29SRuslan Bukin /* Scan ahead for an indication whether tracing is enabled or disabled.
2300*74fe6c29SRuslan Bukin  *
2301*74fe6c29SRuslan Bukin  * Returns zero if tracing is clearly disabled.
2302*74fe6c29SRuslan Bukin  * Returns a positive integer if tracing is enabled or if we can't tell.
2303*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
2304*74fe6c29SRuslan Bukin  */
apl12_tracing_is_disabled(struct pt_packet_decoder * decoder)2305*74fe6c29SRuslan Bukin static int apl12_tracing_is_disabled(struct pt_packet_decoder *decoder)
2306*74fe6c29SRuslan Bukin {
2307*74fe6c29SRuslan Bukin 	if (!decoder)
2308*74fe6c29SRuslan Bukin 		return -pte_internal;
2309*74fe6c29SRuslan Bukin 
2310*74fe6c29SRuslan Bukin 	for (;;) {
2311*74fe6c29SRuslan Bukin 		struct pt_packet packet;
2312*74fe6c29SRuslan Bukin 		int status;
2313*74fe6c29SRuslan Bukin 
2314*74fe6c29SRuslan Bukin 		status = pt_pkt_next(decoder, &packet, sizeof(packet));
2315*74fe6c29SRuslan Bukin 		if (status < 0) {
2316*74fe6c29SRuslan Bukin 			/* Running out of packets is not an error. */
2317*74fe6c29SRuslan Bukin 			if (status == -pte_eos)
2318*74fe6c29SRuslan Bukin 				status = 1;
2319*74fe6c29SRuslan Bukin 
2320*74fe6c29SRuslan Bukin 			return status;
2321*74fe6c29SRuslan Bukin 		}
2322*74fe6c29SRuslan Bukin 
2323*74fe6c29SRuslan Bukin 		switch (packet.type) {
2324*74fe6c29SRuslan Bukin 		default:
2325*74fe6c29SRuslan Bukin 			/* Skip other packets. */
2326*74fe6c29SRuslan Bukin 			break;
2327*74fe6c29SRuslan Bukin 
2328*74fe6c29SRuslan Bukin 		case ppt_stop:
2329*74fe6c29SRuslan Bukin 			/* Tracing is disabled before a stop. */
2330*74fe6c29SRuslan Bukin 			return 0;
2331*74fe6c29SRuslan Bukin 
2332*74fe6c29SRuslan Bukin 		case ppt_tip_pge:
2333*74fe6c29SRuslan Bukin 			/* Tracing gets enabled - it must have been disabled. */
2334*74fe6c29SRuslan Bukin 			return 0;
2335*74fe6c29SRuslan Bukin 
2336*74fe6c29SRuslan Bukin 		case ppt_tnt_8:
2337*74fe6c29SRuslan Bukin 		case ppt_tnt_64:
2338*74fe6c29SRuslan Bukin 		case ppt_tip:
2339*74fe6c29SRuslan Bukin 		case ppt_tip_pgd:
2340*74fe6c29SRuslan Bukin 			/* Those packets are only generated when tracing is
2341*74fe6c29SRuslan Bukin 			 * enabled.  We're done.
2342*74fe6c29SRuslan Bukin 			 */
2343*74fe6c29SRuslan Bukin 			return 1;
2344*74fe6c29SRuslan Bukin 
2345*74fe6c29SRuslan Bukin 		case ppt_psb:
2346*74fe6c29SRuslan Bukin 			/* We reached a synchronization point.  Tracing is
2347*74fe6c29SRuslan Bukin 			 * enabled if and only if the PSB+ contains a FUP.
2348*74fe6c29SRuslan Bukin 			 */
2349*74fe6c29SRuslan Bukin 			status = pt_qry_find_header_fup(&packet, decoder);
2350*74fe6c29SRuslan Bukin 
2351*74fe6c29SRuslan Bukin 			/* If we ran out of packets, we can't tell. */
2352*74fe6c29SRuslan Bukin 			if (status == -pte_eos)
2353*74fe6c29SRuslan Bukin 				status = 1;
2354*74fe6c29SRuslan Bukin 
2355*74fe6c29SRuslan Bukin 			return status;
2356*74fe6c29SRuslan Bukin 
2357*74fe6c29SRuslan Bukin 		case ppt_psbend:
2358*74fe6c29SRuslan Bukin 			/* We shouldn't see this. */
2359*74fe6c29SRuslan Bukin 			return -pte_bad_context;
2360*74fe6c29SRuslan Bukin 
2361*74fe6c29SRuslan Bukin 		case ppt_ovf:
2362*74fe6c29SRuslan Bukin 			/* It doesn't matter - we run into the next overflow. */
2363*74fe6c29SRuslan Bukin 			return 1;
2364*74fe6c29SRuslan Bukin 
2365*74fe6c29SRuslan Bukin 		case ppt_unknown:
2366*74fe6c29SRuslan Bukin 		case ppt_invalid:
2367*74fe6c29SRuslan Bukin 			/* We can't skip this packet. */
2368*74fe6c29SRuslan Bukin 			return 1;
2369*74fe6c29SRuslan Bukin 		}
2370*74fe6c29SRuslan Bukin 	}
2371*74fe6c29SRuslan Bukin }
2372*74fe6c29SRuslan Bukin 
2373*74fe6c29SRuslan Bukin /* Apply workaround for erratum APL12.
2374*74fe6c29SRuslan Bukin  *
2375*74fe6c29SRuslan Bukin  * We resume from @offset (relative to @decoder->pos) with tracing disabled.  On
2376*74fe6c29SRuslan Bukin  * our way to the resume location we process packets to update our state.
2377*74fe6c29SRuslan Bukin  *
2378*74fe6c29SRuslan Bukin  * Any event will be dropped.
2379*74fe6c29SRuslan Bukin  *
2380*74fe6c29SRuslan Bukin  * Returns zero on success, a negative pt_error_code otherwise.
2381*74fe6c29SRuslan Bukin  */
apl12_resume_disabled(struct pt_query_decoder * decoder,struct pt_packet_decoder * pkt,unsigned int offset)2382*74fe6c29SRuslan Bukin static int apl12_resume_disabled(struct pt_query_decoder *decoder,
2383*74fe6c29SRuslan Bukin 				 struct pt_packet_decoder *pkt,
2384*74fe6c29SRuslan Bukin 				 unsigned int offset)
2385*74fe6c29SRuslan Bukin {
2386*74fe6c29SRuslan Bukin 	uint64_t begin, end;
2387*74fe6c29SRuslan Bukin 	int errcode;
2388*74fe6c29SRuslan Bukin 
2389*74fe6c29SRuslan Bukin 	if (!decoder)
2390*74fe6c29SRuslan Bukin 		return -pte_internal;
2391*74fe6c29SRuslan Bukin 
2392*74fe6c29SRuslan Bukin 	errcode = pt_qry_get_offset(decoder, &begin);
2393*74fe6c29SRuslan Bukin 	if (errcode < 0)
2394*74fe6c29SRuslan Bukin 		return errcode;
2395*74fe6c29SRuslan Bukin 
2396*74fe6c29SRuslan Bukin 	errcode = pt_pkt_sync_set(pkt, begin);
2397*74fe6c29SRuslan Bukin 	if (errcode < 0)
2398*74fe6c29SRuslan Bukin 		return errcode;
2399*74fe6c29SRuslan Bukin 
2400*74fe6c29SRuslan Bukin 	end = begin + offset;
2401*74fe6c29SRuslan Bukin 	for (;;) {
2402*74fe6c29SRuslan Bukin 		struct pt_packet packet;
2403*74fe6c29SRuslan Bukin 		uint64_t next;
2404*74fe6c29SRuslan Bukin 
2405*74fe6c29SRuslan Bukin 		errcode = pt_pkt_next(pkt, &packet, sizeof(packet));
2406*74fe6c29SRuslan Bukin 		if (errcode < 0) {
2407*74fe6c29SRuslan Bukin 			/* Running out of packets is not an error. */
2408*74fe6c29SRuslan Bukin 			if (errcode == -pte_eos)
2409*74fe6c29SRuslan Bukin 				errcode = 0;
2410*74fe6c29SRuslan Bukin 
2411*74fe6c29SRuslan Bukin 			return errcode;
2412*74fe6c29SRuslan Bukin 		}
2413*74fe6c29SRuslan Bukin 
2414*74fe6c29SRuslan Bukin 		/* The offset is the start of the next packet. */
2415*74fe6c29SRuslan Bukin 		errcode = pt_pkt_get_offset(pkt, &next);
2416*74fe6c29SRuslan Bukin 		if (errcode < 0)
2417*74fe6c29SRuslan Bukin 			return errcode;
2418*74fe6c29SRuslan Bukin 
2419*74fe6c29SRuslan Bukin 		/* We're done when we reach @offset.
2420*74fe6c29SRuslan Bukin 		 *
2421*74fe6c29SRuslan Bukin 		 * The current @packet will be the FUP after which we started
2422*74fe6c29SRuslan Bukin 		 * our search.  We skip it.
2423*74fe6c29SRuslan Bukin 		 *
2424*74fe6c29SRuslan Bukin 		 * Check that we're not accidentally proceeding past @offset.
2425*74fe6c29SRuslan Bukin 		 */
2426*74fe6c29SRuslan Bukin 		if (end <= next) {
2427*74fe6c29SRuslan Bukin 			if (end < next)
2428*74fe6c29SRuslan Bukin 				return -pte_internal;
2429*74fe6c29SRuslan Bukin 
2430*74fe6c29SRuslan Bukin 			break;
2431*74fe6c29SRuslan Bukin 		}
2432*74fe6c29SRuslan Bukin 
2433*74fe6c29SRuslan Bukin 		switch (packet.type) {
2434*74fe6c29SRuslan Bukin 		default:
2435*74fe6c29SRuslan Bukin 			/* Skip other packets. */
2436*74fe6c29SRuslan Bukin 			break;
2437*74fe6c29SRuslan Bukin 
2438*74fe6c29SRuslan Bukin 		case ppt_mode:
2439*74fe6c29SRuslan Bukin 		case ppt_pip:
2440*74fe6c29SRuslan Bukin 		case ppt_vmcs:
2441*74fe6c29SRuslan Bukin 			/* We should not encounter those.
2442*74fe6c29SRuslan Bukin 			 *
2443*74fe6c29SRuslan Bukin 			 * We should not encounter a lot of packets but those
2444*74fe6c29SRuslan Bukin 			 * are state-relevant; let's check them explicitly.
2445*74fe6c29SRuslan Bukin 			 */
2446*74fe6c29SRuslan Bukin 			return -pte_internal;
2447*74fe6c29SRuslan Bukin 
2448*74fe6c29SRuslan Bukin 		case ppt_tsc:
2449*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2450*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_tsc(&decoder->time,
2451*74fe6c29SRuslan Bukin 						   &decoder->tcal,
2452*74fe6c29SRuslan Bukin 						   &packet.payload.tsc,
2453*74fe6c29SRuslan Bukin 						   &decoder->config);
2454*74fe6c29SRuslan Bukin 			if (errcode < 0)
2455*74fe6c29SRuslan Bukin 				return errcode;
2456*74fe6c29SRuslan Bukin 
2457*74fe6c29SRuslan Bukin 			break;
2458*74fe6c29SRuslan Bukin 
2459*74fe6c29SRuslan Bukin 		case ppt_cbr:
2460*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2461*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_cbr(&decoder->time,
2462*74fe6c29SRuslan Bukin 						   &decoder->tcal,
2463*74fe6c29SRuslan Bukin 						   &packet.payload.cbr,
2464*74fe6c29SRuslan Bukin 						   &decoder->config);
2465*74fe6c29SRuslan Bukin 			if (errcode < 0)
2466*74fe6c29SRuslan Bukin 				return errcode;
2467*74fe6c29SRuslan Bukin 
2468*74fe6c29SRuslan Bukin 			break;
2469*74fe6c29SRuslan Bukin 
2470*74fe6c29SRuslan Bukin 		case ppt_tma:
2471*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2472*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_tma(&decoder->time,
2473*74fe6c29SRuslan Bukin 						   &decoder->tcal,
2474*74fe6c29SRuslan Bukin 						   &packet.payload.tma,
2475*74fe6c29SRuslan Bukin 						   &decoder->config);
2476*74fe6c29SRuslan Bukin 			if (errcode < 0)
2477*74fe6c29SRuslan Bukin 				return errcode;
2478*74fe6c29SRuslan Bukin 
2479*74fe6c29SRuslan Bukin 			break;
2480*74fe6c29SRuslan Bukin 
2481*74fe6c29SRuslan Bukin 		case ppt_mtc:
2482*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2483*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_mtc(&decoder->time,
2484*74fe6c29SRuslan Bukin 						   &decoder->tcal,
2485*74fe6c29SRuslan Bukin 						   &packet.payload.mtc,
2486*74fe6c29SRuslan Bukin 						   &decoder->config);
2487*74fe6c29SRuslan Bukin 			if (errcode < 0)
2488*74fe6c29SRuslan Bukin 				return errcode;
2489*74fe6c29SRuslan Bukin 
2490*74fe6c29SRuslan Bukin 			break;
2491*74fe6c29SRuslan Bukin 
2492*74fe6c29SRuslan Bukin 		case ppt_cyc:
2493*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2494*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_cyc(&decoder->time,
2495*74fe6c29SRuslan Bukin 						   &decoder->tcal,
2496*74fe6c29SRuslan Bukin 						   &packet.payload.cyc,
2497*74fe6c29SRuslan Bukin 						   &decoder->config);
2498*74fe6c29SRuslan Bukin 			if (errcode < 0)
2499*74fe6c29SRuslan Bukin 				return errcode;
2500*74fe6c29SRuslan Bukin 
2501*74fe6c29SRuslan Bukin 			break;
2502*74fe6c29SRuslan Bukin 		}
2503*74fe6c29SRuslan Bukin 	}
2504*74fe6c29SRuslan Bukin 
2505*74fe6c29SRuslan Bukin 	decoder->pos += offset;
2506*74fe6c29SRuslan Bukin 
2507*74fe6c29SRuslan Bukin 	return pt_qry_event_ovf_disabled(decoder);
2508*74fe6c29SRuslan Bukin }
2509*74fe6c29SRuslan Bukin 
2510*74fe6c29SRuslan Bukin /* Handle erratum APL12.
2511*74fe6c29SRuslan Bukin  *
2512*74fe6c29SRuslan Bukin  * This function is called when a FUP is found after an OVF.  The @offset
2513*74fe6c29SRuslan Bukin  * argument gives the relative offset from @decoder->pos to after the FUP.
2514*74fe6c29SRuslan Bukin  *
2515*74fe6c29SRuslan Bukin  * A FUP after OVF normally indicates that the overflow resolved while tracing
2516*74fe6c29SRuslan Bukin  * is enabled.  Due to erratum APL12, however, the overflow may have resolved
2517*74fe6c29SRuslan Bukin  * while tracing is disabled and still generate a FUP.
2518*74fe6c29SRuslan Bukin  *
2519*74fe6c29SRuslan Bukin  * We scan ahead for an indication whether tracing is actually disabled.  If we
2520*74fe6c29SRuslan Bukin  * find one, the erratum applies and we proceed from after the FUP packet.
2521*74fe6c29SRuslan Bukin  *
2522*74fe6c29SRuslan Bukin  * This will drop any CBR or MTC events.  We will update @decoder's timing state
2523*74fe6c29SRuslan Bukin  * on CBR but drop the event.
2524*74fe6c29SRuslan Bukin  *
2525*74fe6c29SRuslan Bukin  * Returns zero if the erratum was handled.
2526*74fe6c29SRuslan Bukin  * Returns a positive integer if the erratum was not handled.
2527*74fe6c29SRuslan Bukin  * Returns a negative pt_error_code otherwise.
2528*74fe6c29SRuslan Bukin  */
pt_qry_handle_apl12(struct pt_query_decoder * decoder,unsigned int offset)2529*74fe6c29SRuslan Bukin static int pt_qry_handle_apl12(struct pt_query_decoder *decoder,
2530*74fe6c29SRuslan Bukin 			       unsigned int offset)
2531*74fe6c29SRuslan Bukin {
2532*74fe6c29SRuslan Bukin 	struct pt_packet_decoder pkt;
2533*74fe6c29SRuslan Bukin 	uint64_t here;
2534*74fe6c29SRuslan Bukin 	int status;
2535*74fe6c29SRuslan Bukin 
2536*74fe6c29SRuslan Bukin 	if (!decoder)
2537*74fe6c29SRuslan Bukin 		return -pte_internal;
2538*74fe6c29SRuslan Bukin 
2539*74fe6c29SRuslan Bukin 	status = pt_qry_get_offset(decoder, &here);
2540*74fe6c29SRuslan Bukin 	if (status < 0)
2541*74fe6c29SRuslan Bukin 		return status;
2542*74fe6c29SRuslan Bukin 
2543*74fe6c29SRuslan Bukin 	status = pt_pkt_decoder_init(&pkt, &decoder->config);
2544*74fe6c29SRuslan Bukin 	if (status < 0)
2545*74fe6c29SRuslan Bukin 		return status;
2546*74fe6c29SRuslan Bukin 
2547*74fe6c29SRuslan Bukin 	status = pt_pkt_sync_set(&pkt, here + offset);
2548*74fe6c29SRuslan Bukin 	if (status >= 0) {
2549*74fe6c29SRuslan Bukin 		status = apl12_tracing_is_disabled(&pkt);
2550*74fe6c29SRuslan Bukin 		if (!status)
2551*74fe6c29SRuslan Bukin 			status = apl12_resume_disabled(decoder, &pkt, offset);
2552*74fe6c29SRuslan Bukin 	}
2553*74fe6c29SRuslan Bukin 
2554*74fe6c29SRuslan Bukin 	pt_pkt_decoder_fini(&pkt);
2555*74fe6c29SRuslan Bukin 	return status;
2556*74fe6c29SRuslan Bukin }
2557*74fe6c29SRuslan Bukin 
2558*74fe6c29SRuslan Bukin /* Apply workaround for erratum APL11.
2559*74fe6c29SRuslan Bukin  *
2560*74fe6c29SRuslan Bukin  * We search for a TIP.PGD and, if we found one, resume from after that packet
2561*74fe6c29SRuslan Bukin  * with tracing disabled.  On our way to the resume location we process packets
2562*74fe6c29SRuslan Bukin  * to update our state.
2563*74fe6c29SRuslan Bukin  *
2564*74fe6c29SRuslan Bukin  * If we don't find a TIP.PGD but instead some other packet that indicates that
2565*74fe6c29SRuslan Bukin  * tracing is disabled, indicate that the erratum does not apply.
2566*74fe6c29SRuslan Bukin  *
2567*74fe6c29SRuslan Bukin  * Any event will be dropped.
2568*74fe6c29SRuslan Bukin  *
2569*74fe6c29SRuslan Bukin  * Returns zero if the erratum was handled.
2570*74fe6c29SRuslan Bukin  * Returns a positive integer if the erratum was not handled.
2571*74fe6c29SRuslan Bukin  * Returns a negative pt_error_code otherwise.
2572*74fe6c29SRuslan Bukin  */
apl11_apply(struct pt_query_decoder * decoder,struct pt_packet_decoder * pkt)2573*74fe6c29SRuslan Bukin static int apl11_apply(struct pt_query_decoder *decoder,
2574*74fe6c29SRuslan Bukin 		       struct pt_packet_decoder *pkt)
2575*74fe6c29SRuslan Bukin {
2576*74fe6c29SRuslan Bukin 	struct pt_time_cal tcal;
2577*74fe6c29SRuslan Bukin 	struct pt_time time;
2578*74fe6c29SRuslan Bukin 
2579*74fe6c29SRuslan Bukin 	if (!decoder)
2580*74fe6c29SRuslan Bukin 		return -pte_internal;
2581*74fe6c29SRuslan Bukin 
2582*74fe6c29SRuslan Bukin 	time = decoder->time;
2583*74fe6c29SRuslan Bukin 	tcal = decoder->tcal;
2584*74fe6c29SRuslan Bukin 	for (;;) {
2585*74fe6c29SRuslan Bukin 		struct pt_packet packet;
2586*74fe6c29SRuslan Bukin 		int errcode;
2587*74fe6c29SRuslan Bukin 
2588*74fe6c29SRuslan Bukin 		errcode = pt_pkt_next(pkt, &packet, sizeof(packet));
2589*74fe6c29SRuslan Bukin 		if (errcode < 0)
2590*74fe6c29SRuslan Bukin 			return errcode;
2591*74fe6c29SRuslan Bukin 
2592*74fe6c29SRuslan Bukin 		switch (packet.type) {
2593*74fe6c29SRuslan Bukin 		case ppt_tip_pgd: {
2594*74fe6c29SRuslan Bukin 			uint64_t offset;
2595*74fe6c29SRuslan Bukin 
2596*74fe6c29SRuslan Bukin 			/* We found a TIP.PGD.  The erratum applies.
2597*74fe6c29SRuslan Bukin 			 *
2598*74fe6c29SRuslan Bukin 			 * Resume from here with tracing disabled.
2599*74fe6c29SRuslan Bukin 			 */
2600*74fe6c29SRuslan Bukin 			errcode = pt_pkt_get_offset(pkt, &offset);
2601*74fe6c29SRuslan Bukin 			if (errcode < 0)
2602*74fe6c29SRuslan Bukin 				return errcode;
2603*74fe6c29SRuslan Bukin 
2604*74fe6c29SRuslan Bukin 			decoder->time = time;
2605*74fe6c29SRuslan Bukin 			decoder->tcal = tcal;
2606*74fe6c29SRuslan Bukin 			decoder->pos = decoder->config.begin + offset;
2607*74fe6c29SRuslan Bukin 
2608*74fe6c29SRuslan Bukin 			return pt_qry_event_ovf_disabled(decoder);
2609*74fe6c29SRuslan Bukin 		}
2610*74fe6c29SRuslan Bukin 
2611*74fe6c29SRuslan Bukin 		case ppt_invalid:
2612*74fe6c29SRuslan Bukin 			return -pte_bad_opc;
2613*74fe6c29SRuslan Bukin 
2614*74fe6c29SRuslan Bukin 		case ppt_fup:
2615*74fe6c29SRuslan Bukin 		case ppt_psb:
2616*74fe6c29SRuslan Bukin 		case ppt_tip_pge:
2617*74fe6c29SRuslan Bukin 		case ppt_stop:
2618*74fe6c29SRuslan Bukin 		case ppt_ovf:
2619*74fe6c29SRuslan Bukin 		case ppt_mode:
2620*74fe6c29SRuslan Bukin 		case ppt_pip:
2621*74fe6c29SRuslan Bukin 		case ppt_vmcs:
2622*74fe6c29SRuslan Bukin 		case ppt_exstop:
2623*74fe6c29SRuslan Bukin 		case ppt_mwait:
2624*74fe6c29SRuslan Bukin 		case ppt_pwre:
2625*74fe6c29SRuslan Bukin 		case ppt_pwrx:
2626*74fe6c29SRuslan Bukin 		case ppt_ptw:
2627*74fe6c29SRuslan Bukin 			/* The erratum does not apply. */
2628*74fe6c29SRuslan Bukin 			return 1;
2629*74fe6c29SRuslan Bukin 
2630*74fe6c29SRuslan Bukin 		case ppt_unknown:
2631*74fe6c29SRuslan Bukin 		case ppt_pad:
2632*74fe6c29SRuslan Bukin 		case ppt_mnt:
2633*74fe6c29SRuslan Bukin 			/* Skip those packets. */
2634*74fe6c29SRuslan Bukin 			break;
2635*74fe6c29SRuslan Bukin 
2636*74fe6c29SRuslan Bukin 		case ppt_psbend:
2637*74fe6c29SRuslan Bukin 		case ppt_tip:
2638*74fe6c29SRuslan Bukin 		case ppt_tnt_8:
2639*74fe6c29SRuslan Bukin 		case ppt_tnt_64:
2640*74fe6c29SRuslan Bukin 			return -pte_bad_context;
2641*74fe6c29SRuslan Bukin 
2642*74fe6c29SRuslan Bukin 
2643*74fe6c29SRuslan Bukin 		case ppt_tsc:
2644*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2645*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_tsc(&time, &tcal,
2646*74fe6c29SRuslan Bukin 						   &packet.payload.tsc,
2647*74fe6c29SRuslan Bukin 						   &decoder->config);
2648*74fe6c29SRuslan Bukin 			if (errcode < 0)
2649*74fe6c29SRuslan Bukin 				return errcode;
2650*74fe6c29SRuslan Bukin 
2651*74fe6c29SRuslan Bukin 			break;
2652*74fe6c29SRuslan Bukin 
2653*74fe6c29SRuslan Bukin 		case ppt_cbr:
2654*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2655*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_cbr(&time, &tcal,
2656*74fe6c29SRuslan Bukin 						   &packet.payload.cbr,
2657*74fe6c29SRuslan Bukin 						   &decoder->config);
2658*74fe6c29SRuslan Bukin 			if (errcode < 0)
2659*74fe6c29SRuslan Bukin 				return errcode;
2660*74fe6c29SRuslan Bukin 
2661*74fe6c29SRuslan Bukin 			break;
2662*74fe6c29SRuslan Bukin 
2663*74fe6c29SRuslan Bukin 		case ppt_tma:
2664*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2665*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_tma(&time, &tcal,
2666*74fe6c29SRuslan Bukin 						   &packet.payload.tma,
2667*74fe6c29SRuslan Bukin 						   &decoder->config);
2668*74fe6c29SRuslan Bukin 			if (errcode < 0)
2669*74fe6c29SRuslan Bukin 				return errcode;
2670*74fe6c29SRuslan Bukin 
2671*74fe6c29SRuslan Bukin 			break;
2672*74fe6c29SRuslan Bukin 
2673*74fe6c29SRuslan Bukin 		case ppt_mtc:
2674*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2675*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_mtc(&time, &tcal,
2676*74fe6c29SRuslan Bukin 						   &packet.payload.mtc,
2677*74fe6c29SRuslan Bukin 						   &decoder->config);
2678*74fe6c29SRuslan Bukin 			if (errcode < 0)
2679*74fe6c29SRuslan Bukin 				return errcode;
2680*74fe6c29SRuslan Bukin 
2681*74fe6c29SRuslan Bukin 			break;
2682*74fe6c29SRuslan Bukin 
2683*74fe6c29SRuslan Bukin 		case ppt_cyc:
2684*74fe6c29SRuslan Bukin 			/* Keep track of time. */
2685*74fe6c29SRuslan Bukin 			errcode = pt_qry_apply_cyc(&time, &tcal,
2686*74fe6c29SRuslan Bukin 						   &packet.payload.cyc,
2687*74fe6c29SRuslan Bukin 						   &decoder->config);
2688*74fe6c29SRuslan Bukin 			if (errcode < 0)
2689*74fe6c29SRuslan Bukin 				return errcode;
2690*74fe6c29SRuslan Bukin 
2691*74fe6c29SRuslan Bukin 			break;
2692*74fe6c29SRuslan Bukin 		}
2693*74fe6c29SRuslan Bukin 	}
2694*74fe6c29SRuslan Bukin }
2695*74fe6c29SRuslan Bukin 
2696*74fe6c29SRuslan Bukin /* Handle erratum APL11.
2697*74fe6c29SRuslan Bukin  *
2698*74fe6c29SRuslan Bukin  * This function is called when we diagnose a bad packet while searching for a
2699*74fe6c29SRuslan Bukin  * FUP after an OVF.
2700*74fe6c29SRuslan Bukin  *
2701*74fe6c29SRuslan Bukin  * Due to erratum APL11 we may get an extra TIP.PGD after the OVF.  Find that
2702*74fe6c29SRuslan Bukin  * TIP.PGD and resume from there with tracing disabled.
2703*74fe6c29SRuslan Bukin  *
2704*74fe6c29SRuslan Bukin  * This will drop any CBR or MTC events.  We will update @decoder's timing state
2705*74fe6c29SRuslan Bukin  * on CBR but drop the event.
2706*74fe6c29SRuslan Bukin  *
2707*74fe6c29SRuslan Bukin  * Returns zero if the erratum was handled.
2708*74fe6c29SRuslan Bukin  * Returns a positive integer if the erratum was not handled.
2709*74fe6c29SRuslan Bukin  * Returns a negative pt_error_code otherwise.
2710*74fe6c29SRuslan Bukin  */
pt_qry_handle_apl11(struct pt_query_decoder * decoder)2711*74fe6c29SRuslan Bukin static int pt_qry_handle_apl11(struct pt_query_decoder *decoder)
2712*74fe6c29SRuslan Bukin {
2713*74fe6c29SRuslan Bukin 	struct pt_packet_decoder pkt;
2714*74fe6c29SRuslan Bukin 	uint64_t offset;
2715*74fe6c29SRuslan Bukin 	int status;
2716*74fe6c29SRuslan Bukin 
2717*74fe6c29SRuslan Bukin 	if (!decoder)
2718*74fe6c29SRuslan Bukin 		return -pte_internal;
2719*74fe6c29SRuslan Bukin 
2720*74fe6c29SRuslan Bukin 	status = pt_qry_get_offset(decoder, &offset);
2721*74fe6c29SRuslan Bukin 	if (status < 0)
2722*74fe6c29SRuslan Bukin 		return status;
2723*74fe6c29SRuslan Bukin 
2724*74fe6c29SRuslan Bukin 	status = pt_pkt_decoder_init(&pkt, &decoder->config);
2725*74fe6c29SRuslan Bukin 	if (status < 0)
2726*74fe6c29SRuslan Bukin 		return status;
2727*74fe6c29SRuslan Bukin 
2728*74fe6c29SRuslan Bukin 	status = pt_pkt_sync_set(&pkt, offset);
2729*74fe6c29SRuslan Bukin 	if (status >= 0)
2730*74fe6c29SRuslan Bukin 		status = apl11_apply(decoder, &pkt);
2731*74fe6c29SRuslan Bukin 
2732*74fe6c29SRuslan Bukin 	pt_pkt_decoder_fini(&pkt);
2733*74fe6c29SRuslan Bukin 	return status;
2734*74fe6c29SRuslan Bukin }
2735*74fe6c29SRuslan Bukin 
pt_pkt_find_ovf_fup(struct pt_packet_decoder * decoder)2736*74fe6c29SRuslan Bukin static int pt_pkt_find_ovf_fup(struct pt_packet_decoder *decoder)
2737*74fe6c29SRuslan Bukin {
2738*74fe6c29SRuslan Bukin 	for (;;) {
2739*74fe6c29SRuslan Bukin 		struct pt_packet packet;
2740*74fe6c29SRuslan Bukin 		int errcode;
2741*74fe6c29SRuslan Bukin 
2742*74fe6c29SRuslan Bukin 		errcode = pt_pkt_next(decoder, &packet, sizeof(packet));
2743*74fe6c29SRuslan Bukin 		if (errcode < 0)
2744*74fe6c29SRuslan Bukin 			return errcode;
2745*74fe6c29SRuslan Bukin 
2746*74fe6c29SRuslan Bukin 		switch (packet.type) {
2747*74fe6c29SRuslan Bukin 		case ppt_fup:
2748*74fe6c29SRuslan Bukin 			return 1;
2749*74fe6c29SRuslan Bukin 
2750*74fe6c29SRuslan Bukin 		case ppt_invalid:
2751*74fe6c29SRuslan Bukin 			return -pte_bad_opc;
2752*74fe6c29SRuslan Bukin 
2753*74fe6c29SRuslan Bukin 		case ppt_unknown:
2754*74fe6c29SRuslan Bukin 		case ppt_pad:
2755*74fe6c29SRuslan Bukin 		case ppt_mnt:
2756*74fe6c29SRuslan Bukin 		case ppt_cbr:
2757*74fe6c29SRuslan Bukin 		case ppt_tsc:
2758*74fe6c29SRuslan Bukin 		case ppt_tma:
2759*74fe6c29SRuslan Bukin 		case ppt_mtc:
2760*74fe6c29SRuslan Bukin 		case ppt_cyc:
2761*74fe6c29SRuslan Bukin 			continue;
2762*74fe6c29SRuslan Bukin 
2763*74fe6c29SRuslan Bukin 		case ppt_psb:
2764*74fe6c29SRuslan Bukin 		case ppt_tip_pge:
2765*74fe6c29SRuslan Bukin 		case ppt_mode:
2766*74fe6c29SRuslan Bukin 		case ppt_pip:
2767*74fe6c29SRuslan Bukin 		case ppt_vmcs:
2768*74fe6c29SRuslan Bukin 		case ppt_stop:
2769*74fe6c29SRuslan Bukin 		case ppt_ovf:
2770*74fe6c29SRuslan Bukin 		case ppt_exstop:
2771*74fe6c29SRuslan Bukin 		case ppt_mwait:
2772*74fe6c29SRuslan Bukin 		case ppt_pwre:
2773*74fe6c29SRuslan Bukin 		case ppt_pwrx:
2774*74fe6c29SRuslan Bukin 		case ppt_ptw:
2775*74fe6c29SRuslan Bukin 			return 0;
2776*74fe6c29SRuslan Bukin 
2777*74fe6c29SRuslan Bukin 		case ppt_psbend:
2778*74fe6c29SRuslan Bukin 		case ppt_tip:
2779*74fe6c29SRuslan Bukin 		case ppt_tip_pgd:
2780*74fe6c29SRuslan Bukin 		case ppt_tnt_8:
2781*74fe6c29SRuslan Bukin 		case ppt_tnt_64:
2782*74fe6c29SRuslan Bukin 			return -pte_bad_context;
2783*74fe6c29SRuslan Bukin 		}
2784*74fe6c29SRuslan Bukin 	}
2785*74fe6c29SRuslan Bukin }
2786*74fe6c29SRuslan Bukin 
2787*74fe6c29SRuslan Bukin /* Find a FUP to which the current OVF may bind.
2788*74fe6c29SRuslan Bukin  *
2789*74fe6c29SRuslan Bukin  * Scans the trace for a FUP or for a packet that indicates that tracing is
2790*74fe6c29SRuslan Bukin  * disabled.
2791*74fe6c29SRuslan Bukin  *
2792*74fe6c29SRuslan Bukin  * Return the relative offset of the packet following the found FUP on success.
2793*74fe6c29SRuslan Bukin  * Returns zero if no FUP is found and tracing is assumed to be disabled.
2794*74fe6c29SRuslan Bukin  * Returns a negative pt_error_code otherwise.
2795*74fe6c29SRuslan Bukin  */
pt_qry_find_ovf_fup(const struct pt_query_decoder * decoder)2796*74fe6c29SRuslan Bukin static int pt_qry_find_ovf_fup(const struct pt_query_decoder *decoder)
2797*74fe6c29SRuslan Bukin {
2798*74fe6c29SRuslan Bukin 	struct pt_packet_decoder pkt;
2799*74fe6c29SRuslan Bukin 	uint64_t begin, end, offset;
2800*74fe6c29SRuslan Bukin 	int status;
2801*74fe6c29SRuslan Bukin 
2802*74fe6c29SRuslan Bukin 	if (!decoder)
2803*74fe6c29SRuslan Bukin 		return -pte_internal;
2804*74fe6c29SRuslan Bukin 
2805*74fe6c29SRuslan Bukin 	status = pt_qry_get_offset(decoder, &begin);
2806*74fe6c29SRuslan Bukin 	if (status < 0)
2807*74fe6c29SRuslan Bukin 		return status;
2808*74fe6c29SRuslan Bukin 
2809*74fe6c29SRuslan Bukin 	status = pt_pkt_decoder_init(&pkt, &decoder->config);
2810*74fe6c29SRuslan Bukin 	if (status < 0)
2811*74fe6c29SRuslan Bukin 		return status;
2812*74fe6c29SRuslan Bukin 
2813*74fe6c29SRuslan Bukin 	status = pt_pkt_sync_set(&pkt, begin);
2814*74fe6c29SRuslan Bukin 	if (status >= 0) {
2815*74fe6c29SRuslan Bukin 		status = pt_pkt_find_ovf_fup(&pkt);
2816*74fe6c29SRuslan Bukin 		if (status > 0) {
2817*74fe6c29SRuslan Bukin 			status = pt_pkt_get_offset(&pkt, &end);
2818*74fe6c29SRuslan Bukin 			if (status < 0)
2819*74fe6c29SRuslan Bukin 				return status;
2820*74fe6c29SRuslan Bukin 
2821*74fe6c29SRuslan Bukin 			if (end <= begin)
2822*74fe6c29SRuslan Bukin 				return -pte_overflow;
2823*74fe6c29SRuslan Bukin 
2824*74fe6c29SRuslan Bukin 			offset = end - begin;
2825*74fe6c29SRuslan Bukin 			if (INT_MAX < offset)
2826*74fe6c29SRuslan Bukin 				return -pte_overflow;
2827*74fe6c29SRuslan Bukin 
2828*74fe6c29SRuslan Bukin 			status = (int) offset;
2829*74fe6c29SRuslan Bukin 		}
2830*74fe6c29SRuslan Bukin 	}
2831*74fe6c29SRuslan Bukin 
2832*74fe6c29SRuslan Bukin 	pt_pkt_decoder_fini(&pkt);
2833*74fe6c29SRuslan Bukin 	return status;
2834*74fe6c29SRuslan Bukin }
2835*74fe6c29SRuslan Bukin 
pt_qry_decode_ovf(struct pt_query_decoder * decoder)2836*74fe6c29SRuslan Bukin int pt_qry_decode_ovf(struct pt_query_decoder *decoder)
2837*74fe6c29SRuslan Bukin {
2838*74fe6c29SRuslan Bukin 	struct pt_time time;
2839*74fe6c29SRuslan Bukin 	int status, offset;
2840*74fe6c29SRuslan Bukin 
2841*74fe6c29SRuslan Bukin 	if (!decoder)
2842*74fe6c29SRuslan Bukin 		return -pte_internal;
2843*74fe6c29SRuslan Bukin 
2844*74fe6c29SRuslan Bukin 	status = pt_qry_process_pending_psb_events(decoder);
2845*74fe6c29SRuslan Bukin 	if (status < 0)
2846*74fe6c29SRuslan Bukin 		return status;
2847*74fe6c29SRuslan Bukin 
2848*74fe6c29SRuslan Bukin 	/* If we have any pending psbend events, we're done for now. */
2849*74fe6c29SRuslan Bukin 	if (status)
2850*74fe6c29SRuslan Bukin 		return 0;
2851*74fe6c29SRuslan Bukin 
2852*74fe6c29SRuslan Bukin 	/* Reset the decoder state but preserve timing. */
2853*74fe6c29SRuslan Bukin 	time = decoder->time;
2854*74fe6c29SRuslan Bukin 	pt_qry_reset(decoder);
2855*74fe6c29SRuslan Bukin 	decoder->time = time;
2856*74fe6c29SRuslan Bukin 
2857*74fe6c29SRuslan Bukin 	/* We must consume the OVF before we search for the binding packet. */
2858*74fe6c29SRuslan Bukin 	decoder->pos += ptps_ovf;
2859*74fe6c29SRuslan Bukin 
2860*74fe6c29SRuslan Bukin 	/* Overflow binds to either FUP or TIP.PGE.
2861*74fe6c29SRuslan Bukin 	 *
2862*74fe6c29SRuslan Bukin 	 * If the overflow can be resolved while PacketEn=1 it binds to FUP.  We
2863*74fe6c29SRuslan Bukin 	 * can see timing packets between OVF anf FUP but that's it.
2864*74fe6c29SRuslan Bukin 	 *
2865*74fe6c29SRuslan Bukin 	 * Otherwise, PacketEn will be zero when the overflow resolves and OVF
2866*74fe6c29SRuslan Bukin 	 * binds to TIP.PGE.  There can be packets between OVF and TIP.PGE that
2867*74fe6c29SRuslan Bukin 	 * do not depend on PacketEn.
2868*74fe6c29SRuslan Bukin 	 *
2869*74fe6c29SRuslan Bukin 	 * We don't need to decode everything until TIP.PGE, however.  As soon
2870*74fe6c29SRuslan Bukin 	 * as we see a non-timing non-FUP packet, we know that tracing has been
2871*74fe6c29SRuslan Bukin 	 * disabled before the overflow resolves.
2872*74fe6c29SRuslan Bukin 	 */
2873*74fe6c29SRuslan Bukin 	offset = pt_qry_find_ovf_fup(decoder);
2874*74fe6c29SRuslan Bukin 	if (offset <= 0) {
2875*74fe6c29SRuslan Bukin 		/* Check for erratum SKD010.
2876*74fe6c29SRuslan Bukin 		 *
2877*74fe6c29SRuslan Bukin 		 * The FUP may have been dropped.  If we can figure out that
2878*74fe6c29SRuslan Bukin 		 * tracing is enabled and hence the FUP is missing, we resume
2879*74fe6c29SRuslan Bukin 		 * at a later packet and a different IP.
2880*74fe6c29SRuslan Bukin 		 */
2881*74fe6c29SRuslan Bukin 		if (decoder->config.errata.skd010) {
2882*74fe6c29SRuslan Bukin 			status = pt_qry_handle_skd010(decoder);
2883*74fe6c29SRuslan Bukin 			if (status <= 0)
2884*74fe6c29SRuslan Bukin 				return status;
2885*74fe6c29SRuslan Bukin 		}
2886*74fe6c29SRuslan Bukin 
2887*74fe6c29SRuslan Bukin 		/* Check for erratum APL11.
2888*74fe6c29SRuslan Bukin 		 *
2889*74fe6c29SRuslan Bukin 		 * We may have gotten an extra TIP.PGD, which should be
2890*74fe6c29SRuslan Bukin 		 * diagnosed by our search for a subsequent FUP.
2891*74fe6c29SRuslan Bukin 		 */
2892*74fe6c29SRuslan Bukin 		if (decoder->config.errata.apl11 &&
2893*74fe6c29SRuslan Bukin 		    (offset == -pte_bad_context)) {
2894*74fe6c29SRuslan Bukin 			status = pt_qry_handle_apl11(decoder);
2895*74fe6c29SRuslan Bukin 			if (status <= 0)
2896*74fe6c29SRuslan Bukin 				return status;
2897*74fe6c29SRuslan Bukin 		}
2898*74fe6c29SRuslan Bukin 
2899*74fe6c29SRuslan Bukin 		/* Report the original error from searching for the FUP packet
2900*74fe6c29SRuslan Bukin 		 * if we were not able to fix the trace.
2901*74fe6c29SRuslan Bukin 		 *
2902*74fe6c29SRuslan Bukin 		 * We treat an overflow at the end of the trace as standalone.
2903*74fe6c29SRuslan Bukin 		 */
2904*74fe6c29SRuslan Bukin 		if (offset < 0 && offset != -pte_eos)
2905*74fe6c29SRuslan Bukin 			return offset;
2906*74fe6c29SRuslan Bukin 
2907*74fe6c29SRuslan Bukin 		return pt_qry_event_ovf_disabled(decoder);
2908*74fe6c29SRuslan Bukin 	} else {
2909*74fe6c29SRuslan Bukin 		/* Check for erratum APL12.
2910*74fe6c29SRuslan Bukin 		 *
2911*74fe6c29SRuslan Bukin 		 * We may get an extra FUP even though the overflow resolved
2912*74fe6c29SRuslan Bukin 		 * with tracing disabled.
2913*74fe6c29SRuslan Bukin 		 */
2914*74fe6c29SRuslan Bukin 		if (decoder->config.errata.apl12) {
2915*74fe6c29SRuslan Bukin 			status = pt_qry_handle_apl12(decoder,
2916*74fe6c29SRuslan Bukin 						     (unsigned int) offset);
2917*74fe6c29SRuslan Bukin 			if (status <= 0)
2918*74fe6c29SRuslan Bukin 				return status;
2919*74fe6c29SRuslan Bukin 		}
2920*74fe6c29SRuslan Bukin 
2921*74fe6c29SRuslan Bukin 		return pt_qry_event_ovf_enabled(decoder);
2922*74fe6c29SRuslan Bukin 	}
2923*74fe6c29SRuslan Bukin }
2924*74fe6c29SRuslan Bukin 
pt_qry_decode_mode_exec(struct pt_query_decoder * decoder,const struct pt_packet_mode_exec * packet)2925*74fe6c29SRuslan Bukin static int pt_qry_decode_mode_exec(struct pt_query_decoder *decoder,
2926*74fe6c29SRuslan Bukin 				   const struct pt_packet_mode_exec *packet)
2927*74fe6c29SRuslan Bukin {
2928*74fe6c29SRuslan Bukin 	struct pt_event *event;
2929*74fe6c29SRuslan Bukin 
2930*74fe6c29SRuslan Bukin 	if (!decoder || !packet)
2931*74fe6c29SRuslan Bukin 		return -pte_internal;
2932*74fe6c29SRuslan Bukin 
2933*74fe6c29SRuslan Bukin 	/* MODE.EXEC binds to TIP. */
2934*74fe6c29SRuslan Bukin 	event = pt_evq_enqueue(&decoder->evq, evb_tip);
2935*74fe6c29SRuslan Bukin 	if (!event)
2936*74fe6c29SRuslan Bukin 		return -pte_nomem;
2937*74fe6c29SRuslan Bukin 
2938*74fe6c29SRuslan Bukin 	event->type = ptev_exec_mode;
2939*74fe6c29SRuslan Bukin 	event->variant.exec_mode.mode = pt_get_exec_mode(packet);
2940*74fe6c29SRuslan Bukin 
2941*74fe6c29SRuslan Bukin 	return pt_qry_event_time(event, decoder);
2942*74fe6c29SRuslan Bukin }
2943*74fe6c29SRuslan Bukin 
pt_qry_decode_mode_tsx(struct pt_query_decoder * decoder,const struct pt_packet_mode_tsx * packet)2944*74fe6c29SRuslan Bukin static int pt_qry_decode_mode_tsx(struct pt_query_decoder *decoder,
2945*74fe6c29SRuslan Bukin 				  const struct pt_packet_mode_tsx *packet)
2946*74fe6c29SRuslan Bukin {
2947*74fe6c29SRuslan Bukin 	struct pt_event *event;
2948*74fe6c29SRuslan Bukin 
2949*74fe6c29SRuslan Bukin 	if (!decoder || !packet)
2950*74fe6c29SRuslan Bukin 		return -pte_internal;
2951*74fe6c29SRuslan Bukin 
2952*74fe6c29SRuslan Bukin 	/* MODE.TSX is standalone if tracing is disabled. */
2953*74fe6c29SRuslan Bukin 	if (!decoder->enabled) {
2954*74fe6c29SRuslan Bukin 		event = pt_evq_standalone(&decoder->evq);
2955*74fe6c29SRuslan Bukin 		if (!event)
2956*74fe6c29SRuslan Bukin 			return -pte_internal;
2957*74fe6c29SRuslan Bukin 
2958*74fe6c29SRuslan Bukin 		/* We don't have an IP in this case. */
2959*74fe6c29SRuslan Bukin 		event->variant.tsx.ip = 0;
2960*74fe6c29SRuslan Bukin 		event->ip_suppressed = 1;
2961*74fe6c29SRuslan Bukin 
2962*74fe6c29SRuslan Bukin 		/* Publish the event. */
2963*74fe6c29SRuslan Bukin 		decoder->event = event;
2964*74fe6c29SRuslan Bukin 	} else {
2965*74fe6c29SRuslan Bukin 		/* MODE.TSX binds to FUP. */
2966*74fe6c29SRuslan Bukin 		event = pt_evq_enqueue(&decoder->evq, evb_fup);
2967*74fe6c29SRuslan Bukin 		if (!event)
2968*74fe6c29SRuslan Bukin 			return -pte_nomem;
2969*74fe6c29SRuslan Bukin 	}
2970*74fe6c29SRuslan Bukin 
2971*74fe6c29SRuslan Bukin 	event->type = ptev_tsx;
2972*74fe6c29SRuslan Bukin 	event->variant.tsx.speculative = packet->intx;
2973*74fe6c29SRuslan Bukin 	event->variant.tsx.aborted = packet->abrt;
2974*74fe6c29SRuslan Bukin 
2975*74fe6c29SRuslan Bukin 	return pt_qry_event_time(event, decoder);
2976*74fe6c29SRuslan Bukin }
2977*74fe6c29SRuslan Bukin 
pt_qry_decode_mode(struct pt_query_decoder * decoder)2978*74fe6c29SRuslan Bukin int pt_qry_decode_mode(struct pt_query_decoder *decoder)
2979*74fe6c29SRuslan Bukin {
2980*74fe6c29SRuslan Bukin 	struct pt_packet_mode packet;
2981*74fe6c29SRuslan Bukin 	int size, errcode;
2982*74fe6c29SRuslan Bukin 
2983*74fe6c29SRuslan Bukin 	if (!decoder)
2984*74fe6c29SRuslan Bukin 		return -pte_internal;
2985*74fe6c29SRuslan Bukin 
2986*74fe6c29SRuslan Bukin 	size = pt_pkt_read_mode(&packet, decoder->pos, &decoder->config);
2987*74fe6c29SRuslan Bukin 	if (size < 0)
2988*74fe6c29SRuslan Bukin 		return size;
2989*74fe6c29SRuslan Bukin 
2990*74fe6c29SRuslan Bukin 	errcode = 0;
2991*74fe6c29SRuslan Bukin 	switch (packet.leaf) {
2992*74fe6c29SRuslan Bukin 	case pt_mol_exec:
2993*74fe6c29SRuslan Bukin 		errcode = pt_qry_decode_mode_exec(decoder, &packet.bits.exec);
2994*74fe6c29SRuslan Bukin 		break;
2995*74fe6c29SRuslan Bukin 
2996*74fe6c29SRuslan Bukin 	case pt_mol_tsx:
2997*74fe6c29SRuslan Bukin 		errcode = pt_qry_decode_mode_tsx(decoder, &packet.bits.tsx);
2998*74fe6c29SRuslan Bukin 		break;
2999*74fe6c29SRuslan Bukin 	}
3000*74fe6c29SRuslan Bukin 
3001*74fe6c29SRuslan Bukin 	if (errcode < 0)
3002*74fe6c29SRuslan Bukin 		return errcode;
3003*74fe6c29SRuslan Bukin 
3004*74fe6c29SRuslan Bukin 	decoder->pos += size;
3005*74fe6c29SRuslan Bukin 	return 0;
3006*74fe6c29SRuslan Bukin }
3007*74fe6c29SRuslan Bukin 
pt_qry_header_mode(struct pt_query_decoder * decoder)3008*74fe6c29SRuslan Bukin int pt_qry_header_mode(struct pt_query_decoder *decoder)
3009*74fe6c29SRuslan Bukin {
3010*74fe6c29SRuslan Bukin 	struct pt_packet_mode packet;
3011*74fe6c29SRuslan Bukin 	struct pt_event *event;
3012*74fe6c29SRuslan Bukin 	int size;
3013*74fe6c29SRuslan Bukin 
3014*74fe6c29SRuslan Bukin 	if (!decoder)
3015*74fe6c29SRuslan Bukin 		return -pte_internal;
3016*74fe6c29SRuslan Bukin 
3017*74fe6c29SRuslan Bukin 	size = pt_pkt_read_mode(&packet, decoder->pos, &decoder->config);
3018*74fe6c29SRuslan Bukin 	if (size < 0)
3019*74fe6c29SRuslan Bukin 		return size;
3020*74fe6c29SRuslan Bukin 
3021*74fe6c29SRuslan Bukin 	/* Inside the header, events are reported at the end. */
3022*74fe6c29SRuslan Bukin 	event = pt_evq_enqueue(&decoder->evq, evb_psbend);
3023*74fe6c29SRuslan Bukin 	if (!event)
3024*74fe6c29SRuslan Bukin 		return -pte_nomem;
3025*74fe6c29SRuslan Bukin 
3026*74fe6c29SRuslan Bukin 	switch (packet.leaf) {
3027*74fe6c29SRuslan Bukin 	case pt_mol_exec:
3028*74fe6c29SRuslan Bukin 		event->type = ptev_exec_mode;
3029*74fe6c29SRuslan Bukin 		event->variant.exec_mode.mode =
3030*74fe6c29SRuslan Bukin 			pt_get_exec_mode(&packet.bits.exec);
3031*74fe6c29SRuslan Bukin 		break;
3032*74fe6c29SRuslan Bukin 
3033*74fe6c29SRuslan Bukin 	case pt_mol_tsx:
3034*74fe6c29SRuslan Bukin 		event->type = ptev_tsx;
3035*74fe6c29SRuslan Bukin 		event->variant.tsx.speculative = packet.bits.tsx.intx;
3036*74fe6c29SRuslan Bukin 		event->variant.tsx.aborted = packet.bits.tsx.abrt;
3037*74fe6c29SRuslan Bukin 		break;
3038*74fe6c29SRuslan Bukin 	}
3039*74fe6c29SRuslan Bukin 
3040*74fe6c29SRuslan Bukin 	decoder->pos += size;
3041*74fe6c29SRuslan Bukin 	return 0;
3042*74fe6c29SRuslan Bukin }
3043*74fe6c29SRuslan Bukin 
pt_qry_decode_psbend(struct pt_query_decoder * decoder)3044*74fe6c29SRuslan Bukin int pt_qry_decode_psbend(struct pt_query_decoder *decoder)
3045*74fe6c29SRuslan Bukin {
3046*74fe6c29SRuslan Bukin 	int status;
3047*74fe6c29SRuslan Bukin 
3048*74fe6c29SRuslan Bukin 	if (!decoder)
3049*74fe6c29SRuslan Bukin 		return -pte_internal;
3050*74fe6c29SRuslan Bukin 
3051*74fe6c29SRuslan Bukin 	status = pt_qry_process_pending_psb_events(decoder);
3052*74fe6c29SRuslan Bukin 	if (status < 0)
3053*74fe6c29SRuslan Bukin 		return status;
3054*74fe6c29SRuslan Bukin 
3055*74fe6c29SRuslan Bukin 	/* If we had any psb events, we're done for now. */
3056*74fe6c29SRuslan Bukin 	if (status)
3057*74fe6c29SRuslan Bukin 		return 0;
3058*74fe6c29SRuslan Bukin 
3059*74fe6c29SRuslan Bukin 	/* Skip the psbend extended opcode that we fetched before if no more
3060*74fe6c29SRuslan Bukin 	 * psbend events are pending.
3061*74fe6c29SRuslan Bukin 	 */
3062*74fe6c29SRuslan Bukin 	decoder->pos += ptps_psbend;
3063*74fe6c29SRuslan Bukin 	return 0;
3064*74fe6c29SRuslan Bukin }
3065*74fe6c29SRuslan Bukin 
pt_qry_decode_tsc(struct pt_query_decoder * decoder)3066*74fe6c29SRuslan Bukin int pt_qry_decode_tsc(struct pt_query_decoder *decoder)
3067*74fe6c29SRuslan Bukin {
3068*74fe6c29SRuslan Bukin 	struct pt_packet_tsc packet;
3069*74fe6c29SRuslan Bukin 	int size, errcode;
3070*74fe6c29SRuslan Bukin 
3071*74fe6c29SRuslan Bukin 	if (!decoder)
3072*74fe6c29SRuslan Bukin 		return -pte_internal;
3073*74fe6c29SRuslan Bukin 
3074*74fe6c29SRuslan Bukin 	size = pt_pkt_read_tsc(&packet, decoder->pos, &decoder->config);
3075*74fe6c29SRuslan Bukin 	if (size < 0)
3076*74fe6c29SRuslan Bukin 		return size;
3077*74fe6c29SRuslan Bukin 
3078*74fe6c29SRuslan Bukin 	errcode = pt_qry_apply_tsc(&decoder->time, &decoder->tcal,
3079*74fe6c29SRuslan Bukin 				   &packet, &decoder->config);
3080*74fe6c29SRuslan Bukin 	if (errcode < 0)
3081*74fe6c29SRuslan Bukin 		return errcode;
3082*74fe6c29SRuslan Bukin 
3083*74fe6c29SRuslan Bukin 	decoder->pos += size;
3084*74fe6c29SRuslan Bukin 	return 0;
3085*74fe6c29SRuslan Bukin }
3086*74fe6c29SRuslan Bukin 
pt_qry_header_tsc(struct pt_query_decoder * decoder)3087*74fe6c29SRuslan Bukin int pt_qry_header_tsc(struct pt_query_decoder *decoder)
3088*74fe6c29SRuslan Bukin {
3089*74fe6c29SRuslan Bukin 	struct pt_packet_tsc packet;
3090*74fe6c29SRuslan Bukin 	int size, errcode;
3091*74fe6c29SRuslan Bukin 
3092*74fe6c29SRuslan Bukin 	if (!decoder)
3093*74fe6c29SRuslan Bukin 		return -pte_internal;
3094*74fe6c29SRuslan Bukin 
3095*74fe6c29SRuslan Bukin 	size = pt_pkt_read_tsc(&packet, decoder->pos, &decoder->config);
3096*74fe6c29SRuslan Bukin 	if (size < 0)
3097*74fe6c29SRuslan Bukin 		return size;
3098*74fe6c29SRuslan Bukin 
3099*74fe6c29SRuslan Bukin 	errcode = pt_qry_apply_header_tsc(&decoder->time, &decoder->tcal,
3100*74fe6c29SRuslan Bukin 					  &packet, &decoder->config);
3101*74fe6c29SRuslan Bukin 	if (errcode < 0)
3102*74fe6c29SRuslan Bukin 		return errcode;
3103*74fe6c29SRuslan Bukin 
3104*74fe6c29SRuslan Bukin 	decoder->pos += size;
3105*74fe6c29SRuslan Bukin 	return 0;
3106*74fe6c29SRuslan Bukin }
3107*74fe6c29SRuslan Bukin 
pt_qry_decode_cbr(struct pt_query_decoder * decoder)3108*74fe6c29SRuslan Bukin int pt_qry_decode_cbr(struct pt_query_decoder *decoder)
3109*74fe6c29SRuslan Bukin {
3110*74fe6c29SRuslan Bukin 	struct pt_packet_cbr packet;
3111*74fe6c29SRuslan Bukin 	struct pt_event *event;
3112*74fe6c29SRuslan Bukin 	int size, errcode;
3113*74fe6c29SRuslan Bukin 
3114*74fe6c29SRuslan Bukin 	if (!decoder)
3115*74fe6c29SRuslan Bukin 		return -pte_internal;
3116*74fe6c29SRuslan Bukin 
3117*74fe6c29SRuslan Bukin 	size = pt_pkt_read_cbr(&packet, decoder->pos, &decoder->config);
3118*74fe6c29SRuslan Bukin 	if (size < 0)
3119*74fe6c29SRuslan Bukin 		return size;
3120*74fe6c29SRuslan Bukin 
3121*74fe6c29SRuslan Bukin 	errcode = pt_qry_apply_cbr(&decoder->time, &decoder->tcal,
3122*74fe6c29SRuslan Bukin 				   &packet, &decoder->config);
3123*74fe6c29SRuslan Bukin 	if (errcode < 0)
3124*74fe6c29SRuslan Bukin 		return errcode;
3125*74fe6c29SRuslan Bukin 
3126*74fe6c29SRuslan Bukin 	event = pt_evq_standalone(&decoder->evq);
3127*74fe6c29SRuslan Bukin 	if (!event)
3128*74fe6c29SRuslan Bukin 		return -pte_internal;
3129*74fe6c29SRuslan Bukin 
3130*74fe6c29SRuslan Bukin 	event->type = ptev_cbr;
3131*74fe6c29SRuslan Bukin 	event->variant.cbr.ratio = packet.ratio;
3132*74fe6c29SRuslan Bukin 
3133*74fe6c29SRuslan Bukin 	decoder->event = event;
3134*74fe6c29SRuslan Bukin 
3135*74fe6c29SRuslan Bukin 	errcode = pt_qry_event_time(event, decoder);
3136*74fe6c29SRuslan Bukin 	if (errcode < 0)
3137*74fe6c29SRuslan Bukin 		return errcode;
3138*74fe6c29SRuslan Bukin 
3139*74fe6c29SRuslan Bukin 	decoder->pos += size;
3140*74fe6c29SRuslan Bukin 	return 0;
3141*74fe6c29SRuslan Bukin }
3142*74fe6c29SRuslan Bukin 
pt_qry_header_cbr(struct pt_query_decoder * decoder)3143*74fe6c29SRuslan Bukin int pt_qry_header_cbr(struct pt_query_decoder *decoder)
3144*74fe6c29SRuslan Bukin {
3145*74fe6c29SRuslan Bukin 	struct pt_packet_cbr packet;
3146*74fe6c29SRuslan Bukin 	struct pt_event *event;
3147*74fe6c29SRuslan Bukin 	int size, errcode;
3148*74fe6c29SRuslan Bukin 
3149*74fe6c29SRuslan Bukin 	if (!decoder)
3150*74fe6c29SRuslan Bukin 		return -pte_internal;
3151*74fe6c29SRuslan Bukin 
3152*74fe6c29SRuslan Bukin 	size = pt_pkt_read_cbr(&packet, decoder->pos, &decoder->config);
3153*74fe6c29SRuslan Bukin 	if (size < 0)
3154*74fe6c29SRuslan Bukin 		return size;
3155*74fe6c29SRuslan Bukin 
3156*74fe6c29SRuslan Bukin 	errcode = pt_qry_apply_header_cbr(&decoder->time, &decoder->tcal,
3157*74fe6c29SRuslan Bukin 					  &packet, &decoder->config);
3158*74fe6c29SRuslan Bukin 	if (errcode < 0)
3159*74fe6c29SRuslan Bukin 		return errcode;
3160*74fe6c29SRuslan Bukin 
3161*74fe6c29SRuslan Bukin 	event = pt_evq_enqueue(&decoder->evq, evb_psbend);
3162*74fe6c29SRuslan Bukin 	if (!event)
3163*74fe6c29SRuslan Bukin 		return -pte_nomem;
3164*74fe6c29SRuslan Bukin 
3165*74fe6c29SRuslan Bukin 	event->type = ptev_cbr;
3166*74fe6c29SRuslan Bukin 	event->variant.cbr.ratio = packet.ratio;
3167*74fe6c29SRuslan Bukin 
3168*74fe6c29SRuslan Bukin 	decoder->pos += size;
3169*74fe6c29SRuslan Bukin 	return 0;
3170*74fe6c29SRuslan Bukin }
3171*74fe6c29SRuslan Bukin 
pt_qry_decode_tma(struct pt_query_decoder * decoder)3172*74fe6c29SRuslan Bukin int pt_qry_decode_tma(struct pt_query_decoder *decoder)
3173*74fe6c29SRuslan Bukin {
3174*74fe6c29SRuslan Bukin 	struct pt_packet_tma packet;
3175*74fe6c29SRuslan Bukin 	int size, errcode;
3176*74fe6c29SRuslan Bukin 
3177*74fe6c29SRuslan Bukin 	if (!decoder)
3178*74fe6c29SRuslan Bukin 		return -pte_internal;
3179*74fe6c29SRuslan Bukin 
3180*74fe6c29SRuslan Bukin 	size = pt_pkt_read_tma(&packet, decoder->pos, &decoder->config);
3181*74fe6c29SRuslan Bukin 	if (size < 0)
3182*74fe6c29SRuslan Bukin 		return size;
3183*74fe6c29SRuslan Bukin 
3184*74fe6c29SRuslan Bukin 	errcode = pt_qry_apply_tma(&decoder->time, &decoder->tcal,
3185*74fe6c29SRuslan Bukin 				   &packet, &decoder->config);
3186*74fe6c29SRuslan Bukin 	if (errcode < 0)
3187*74fe6c29SRuslan Bukin 		return errcode;
3188*74fe6c29SRuslan Bukin 
3189*74fe6c29SRuslan Bukin 	decoder->pos += size;
3190*74fe6c29SRuslan Bukin 	return 0;
3191*74fe6c29SRuslan Bukin }
3192*74fe6c29SRuslan Bukin 
pt_qry_decode_mtc(struct pt_query_decoder * decoder)3193*74fe6c29SRuslan Bukin int pt_qry_decode_mtc(struct pt_query_decoder *decoder)
3194*74fe6c29SRuslan Bukin {
3195*74fe6c29SRuslan Bukin 	struct pt_packet_mtc packet;
3196*74fe6c29SRuslan Bukin 	int size, errcode;
3197*74fe6c29SRuslan Bukin 
3198*74fe6c29SRuslan Bukin 	if (!decoder)
3199*74fe6c29SRuslan Bukin 		return -pte_internal;
3200*74fe6c29SRuslan Bukin 
3201*74fe6c29SRuslan Bukin 	size = pt_pkt_read_mtc(&packet, decoder->pos, &decoder->config);
3202*74fe6c29SRuslan Bukin 	if (size < 0)
3203*74fe6c29SRuslan Bukin 		return size;
3204*74fe6c29SRuslan Bukin 
3205*74fe6c29SRuslan Bukin 	errcode = pt_qry_apply_mtc(&decoder->time, &decoder->tcal,
3206*74fe6c29SRuslan Bukin 				   &packet, &decoder->config);
3207*74fe6c29SRuslan Bukin 	if (errcode < 0)
3208*74fe6c29SRuslan Bukin 		return errcode;
3209*74fe6c29SRuslan Bukin 
3210*74fe6c29SRuslan Bukin 	decoder->pos += size;
3211*74fe6c29SRuslan Bukin 	return 0;
3212*74fe6c29SRuslan Bukin }
3213*74fe6c29SRuslan Bukin 
check_erratum_skd007(struct pt_query_decoder * decoder,const struct pt_packet_cyc * packet,int size)3214*74fe6c29SRuslan Bukin static int check_erratum_skd007(struct pt_query_decoder *decoder,
3215*74fe6c29SRuslan Bukin 				const struct pt_packet_cyc *packet, int size)
3216*74fe6c29SRuslan Bukin {
3217*74fe6c29SRuslan Bukin 	const uint8_t *pos;
3218*74fe6c29SRuslan Bukin 	uint16_t payload;
3219*74fe6c29SRuslan Bukin 
3220*74fe6c29SRuslan Bukin 	if (!decoder || !packet || size < 0)
3221*74fe6c29SRuslan Bukin 		return -pte_internal;
3222*74fe6c29SRuslan Bukin 
3223*74fe6c29SRuslan Bukin 	/* It must be a 2-byte CYC. */
3224*74fe6c29SRuslan Bukin 	if (size != 2)
3225*74fe6c29SRuslan Bukin 		return 0;
3226*74fe6c29SRuslan Bukin 
3227*74fe6c29SRuslan Bukin 	payload = (uint16_t) packet->value;
3228*74fe6c29SRuslan Bukin 
3229*74fe6c29SRuslan Bukin 	/* The 2nd byte of the CYC payload must look like an ext opcode. */
3230*74fe6c29SRuslan Bukin 	if ((payload & ~0x1f) != 0x20)
3231*74fe6c29SRuslan Bukin 		return 0;
3232*74fe6c29SRuslan Bukin 
3233*74fe6c29SRuslan Bukin 	/* Skip this CYC packet. */
3234*74fe6c29SRuslan Bukin 	pos = decoder->pos + size;
3235*74fe6c29SRuslan Bukin 	if (decoder->config.end <= pos)
3236*74fe6c29SRuslan Bukin 		return 0;
3237*74fe6c29SRuslan Bukin 
3238*74fe6c29SRuslan Bukin 	/* See if we got a second CYC that looks like an OVF ext opcode. */
3239*74fe6c29SRuslan Bukin 	if (*pos != pt_ext_ovf)
3240*74fe6c29SRuslan Bukin 		return 0;
3241*74fe6c29SRuslan Bukin 
3242*74fe6c29SRuslan Bukin 	/* We shouldn't get back-to-back CYCs unless they are sent when the
3243*74fe6c29SRuslan Bukin 	 * counter wraps around.  In this case, we'd expect a full payload.
3244*74fe6c29SRuslan Bukin 	 *
3245*74fe6c29SRuslan Bukin 	 * Since we got two non-full CYC packets, we assume the erratum hit.
3246*74fe6c29SRuslan Bukin 	 */
3247*74fe6c29SRuslan Bukin 
3248*74fe6c29SRuslan Bukin 	return 1;
3249*74fe6c29SRuslan Bukin }
3250*74fe6c29SRuslan Bukin 
pt_qry_decode_cyc(struct pt_query_decoder * decoder)3251*74fe6c29SRuslan Bukin int pt_qry_decode_cyc(struct pt_query_decoder *decoder)
3252*74fe6c29SRuslan Bukin {
3253*74fe6c29SRuslan Bukin 	struct pt_packet_cyc packet;
3254*74fe6c29SRuslan Bukin 	struct pt_config *config;
3255*74fe6c29SRuslan Bukin 	int size, errcode;
3256*74fe6c29SRuslan Bukin 
3257*74fe6c29SRuslan Bukin 	if (!decoder)
3258*74fe6c29SRuslan Bukin 		return -pte_internal;
3259*74fe6c29SRuslan Bukin 
3260*74fe6c29SRuslan Bukin 	config = &decoder->config;
3261*74fe6c29SRuslan Bukin 
3262*74fe6c29SRuslan Bukin 	size = pt_pkt_read_cyc(&packet, decoder->pos, config);
3263*74fe6c29SRuslan Bukin 	if (size < 0)
3264*74fe6c29SRuslan Bukin 		return size;
3265*74fe6c29SRuslan Bukin 
3266*74fe6c29SRuslan Bukin 	if (config->errata.skd007) {
3267*74fe6c29SRuslan Bukin 		errcode = check_erratum_skd007(decoder, &packet, size);
3268*74fe6c29SRuslan Bukin 		if (errcode < 0)
3269*74fe6c29SRuslan Bukin 			return errcode;
3270*74fe6c29SRuslan Bukin 
3271*74fe6c29SRuslan Bukin 		/* If the erratum hits, we ignore the partial CYC and instead
3272*74fe6c29SRuslan Bukin 		 * process the OVF following/overlapping it.
3273*74fe6c29SRuslan Bukin 		 */
3274*74fe6c29SRuslan Bukin 		if (errcode) {
3275*74fe6c29SRuslan Bukin 			/* We skip the first byte of the CYC, which brings us
3276*74fe6c29SRuslan Bukin 			 * to the beginning of the OVF packet.
3277*74fe6c29SRuslan Bukin 			 */
3278*74fe6c29SRuslan Bukin 			decoder->pos += 1;
3279*74fe6c29SRuslan Bukin 			return 0;
3280*74fe6c29SRuslan Bukin 		}
3281*74fe6c29SRuslan Bukin 	}
3282*74fe6c29SRuslan Bukin 
3283*74fe6c29SRuslan Bukin 	errcode = pt_qry_apply_cyc(&decoder->time, &decoder->tcal,
3284*74fe6c29SRuslan Bukin 				   &packet, config);
3285*74fe6c29SRuslan Bukin 	if (errcode < 0)
3286*74fe6c29SRuslan Bukin 		return errcode;
3287*74fe6c29SRuslan Bukin 
3288*74fe6c29SRuslan Bukin 	decoder->pos += size;
3289*74fe6c29SRuslan Bukin 	return 0;
3290*74fe6c29SRuslan Bukin }
3291*74fe6c29SRuslan Bukin 
pt_qry_decode_stop(struct pt_query_decoder * decoder)3292*74fe6c29SRuslan Bukin int pt_qry_decode_stop(struct pt_query_decoder *decoder)
3293*74fe6c29SRuslan Bukin {
3294*74fe6c29SRuslan Bukin 	struct pt_event *event;
3295*74fe6c29SRuslan Bukin 	int errcode;
3296*74fe6c29SRuslan Bukin 
3297*74fe6c29SRuslan Bukin 	if (!decoder)
3298*74fe6c29SRuslan Bukin 		return -pte_internal;
3299*74fe6c29SRuslan Bukin 
3300*74fe6c29SRuslan Bukin 	/* Stop events are reported immediately. */
3301*74fe6c29SRuslan Bukin 	event = pt_evq_standalone(&decoder->evq);
3302*74fe6c29SRuslan Bukin 	if (!event)
3303*74fe6c29SRuslan Bukin 		return -pte_internal;
3304*74fe6c29SRuslan Bukin 
3305*74fe6c29SRuslan Bukin 	event->type = ptev_stop;
3306*74fe6c29SRuslan Bukin 
3307*74fe6c29SRuslan Bukin 	decoder->event = event;
3308*74fe6c29SRuslan Bukin 
3309*74fe6c29SRuslan Bukin 	errcode = pt_qry_event_time(event, decoder);
3310*74fe6c29SRuslan Bukin 	if (errcode < 0)
3311*74fe6c29SRuslan Bukin 		return errcode;
3312*74fe6c29SRuslan Bukin 
3313*74fe6c29SRuslan Bukin 	decoder->pos += ptps_stop;
3314*74fe6c29SRuslan Bukin 	return 0;
3315*74fe6c29SRuslan Bukin }
3316*74fe6c29SRuslan Bukin 
pt_qry_header_vmcs(struct pt_query_decoder * decoder)3317*74fe6c29SRuslan Bukin int pt_qry_header_vmcs(struct pt_query_decoder *decoder)
3318*74fe6c29SRuslan Bukin {
3319*74fe6c29SRuslan Bukin 	struct pt_packet_vmcs packet;
3320*74fe6c29SRuslan Bukin 	struct pt_event *event;
3321*74fe6c29SRuslan Bukin 	int size;
3322*74fe6c29SRuslan Bukin 
3323*74fe6c29SRuslan Bukin 	if (!decoder)
3324*74fe6c29SRuslan Bukin 		return -pte_internal;
3325*74fe6c29SRuslan Bukin 
3326*74fe6c29SRuslan Bukin 	size = pt_pkt_read_vmcs(&packet, decoder->pos, &decoder->config);
3327*74fe6c29SRuslan Bukin 	if (size < 0)
3328*74fe6c29SRuslan Bukin 		return size;
3329*74fe6c29SRuslan Bukin 
3330*74fe6c29SRuslan Bukin 	event = pt_evq_enqueue(&decoder->evq, evb_psbend);
3331*74fe6c29SRuslan Bukin 	if (!event)
3332*74fe6c29SRuslan Bukin 		return -pte_nomem;
3333*74fe6c29SRuslan Bukin 
3334*74fe6c29SRuslan Bukin 	event->type = ptev_async_vmcs;
3335*74fe6c29SRuslan Bukin 	event->variant.async_vmcs.base = packet.base;
3336*74fe6c29SRuslan Bukin 
3337*74fe6c29SRuslan Bukin 	decoder->pos += size;
3338*74fe6c29SRuslan Bukin 	return 0;
3339*74fe6c29SRuslan Bukin }
3340*74fe6c29SRuslan Bukin 
pt_qry_decode_vmcs(struct pt_query_decoder * decoder)3341*74fe6c29SRuslan Bukin int pt_qry_decode_vmcs(struct pt_query_decoder *decoder)
3342*74fe6c29SRuslan Bukin {
3343*74fe6c29SRuslan Bukin 	struct pt_packet_vmcs packet;
3344*74fe6c29SRuslan Bukin 	struct pt_event *event;
3345*74fe6c29SRuslan Bukin 	int size, errcode;
3346*74fe6c29SRuslan Bukin 
3347*74fe6c29SRuslan Bukin 	if (!decoder)
3348*74fe6c29SRuslan Bukin 		return -pte_internal;
3349*74fe6c29SRuslan Bukin 
3350*74fe6c29SRuslan Bukin 	size = pt_pkt_read_vmcs(&packet, decoder->pos, &decoder->config);
3351*74fe6c29SRuslan Bukin 	if (size < 0)
3352*74fe6c29SRuslan Bukin 		return size;
3353*74fe6c29SRuslan Bukin 
3354*74fe6c29SRuslan Bukin 	/* VMCS events bind to the same IP as an in-flight async paging event.
3355*74fe6c29SRuslan Bukin 	 *
3356*74fe6c29SRuslan Bukin 	 * In that case, the VMCS event should be applied first.  We reorder
3357*74fe6c29SRuslan Bukin 	 * events here to simplify the life of higher layers.
3358*74fe6c29SRuslan Bukin 	 */
3359*74fe6c29SRuslan Bukin 	event = pt_evq_find(&decoder->evq, evb_tip, ptev_async_paging);
3360*74fe6c29SRuslan Bukin 	if (event) {
3361*74fe6c29SRuslan Bukin 		struct pt_event *paging;
3362*74fe6c29SRuslan Bukin 
3363*74fe6c29SRuslan Bukin 		paging = pt_evq_enqueue(&decoder->evq, evb_tip);
3364*74fe6c29SRuslan Bukin 		if (!paging)
3365*74fe6c29SRuslan Bukin 			return -pte_nomem;
3366*74fe6c29SRuslan Bukin 
3367*74fe6c29SRuslan Bukin 		*paging = *event;
3368*74fe6c29SRuslan Bukin 
3369*74fe6c29SRuslan Bukin 		event->type = ptev_async_vmcs;
3370*74fe6c29SRuslan Bukin 		event->variant.async_vmcs.base = packet.base;
3371*74fe6c29SRuslan Bukin 
3372*74fe6c29SRuslan Bukin 		decoder->pos += size;
3373*74fe6c29SRuslan Bukin 		return 0;
3374*74fe6c29SRuslan Bukin 	}
3375*74fe6c29SRuslan Bukin 
3376*74fe6c29SRuslan Bukin 	/* VMCS events bind to the same TIP packet as an in-flight async
3377*74fe6c29SRuslan Bukin 	 * branch event.
3378*74fe6c29SRuslan Bukin 	 */
3379*74fe6c29SRuslan Bukin 	event = pt_evq_find(&decoder->evq, evb_tip, ptev_async_branch);
3380*74fe6c29SRuslan Bukin 	if (event) {
3381*74fe6c29SRuslan Bukin 		event = pt_evq_enqueue(&decoder->evq, evb_tip);
3382*74fe6c29SRuslan Bukin 		if (!event)
3383*74fe6c29SRuslan Bukin 			return -pte_nomem;
3384*74fe6c29SRuslan Bukin 
3385*74fe6c29SRuslan Bukin 		event->type = ptev_async_vmcs;
3386*74fe6c29SRuslan Bukin 		event->variant.async_vmcs.base = packet.base;
3387*74fe6c29SRuslan Bukin 
3388*74fe6c29SRuslan Bukin 		decoder->pos += size;
3389*74fe6c29SRuslan Bukin 		return 0;
3390*74fe6c29SRuslan Bukin 	}
3391*74fe6c29SRuslan Bukin 
3392*74fe6c29SRuslan Bukin 	/* VMCS events that do not bind to an in-flight async event are
3393*74fe6c29SRuslan Bukin 	 * stand-alone.
3394*74fe6c29SRuslan Bukin 	 */
3395*74fe6c29SRuslan Bukin 	event = pt_evq_standalone(&decoder->evq);
3396*74fe6c29SRuslan Bukin 	if (!event)
3397*74fe6c29SRuslan Bukin 		return -pte_internal;
3398*74fe6c29SRuslan Bukin 
3399*74fe6c29SRuslan Bukin 	event->type = ptev_vmcs;
3400*74fe6c29SRuslan Bukin 	event->variant.vmcs.base = packet.base;
3401*74fe6c29SRuslan Bukin 
3402*74fe6c29SRuslan Bukin 	decoder->event = event;
3403*74fe6c29SRuslan Bukin 
3404*74fe6c29SRuslan Bukin 	errcode = pt_qry_event_time(event, decoder);
3405*74fe6c29SRuslan Bukin 	if (errcode < 0)
3406*74fe6c29SRuslan Bukin 		return errcode;
3407*74fe6c29SRuslan Bukin 
3408*74fe6c29SRuslan Bukin 	decoder->pos += size;
3409*74fe6c29SRuslan Bukin 	return 0;
3410*74fe6c29SRuslan Bukin }
3411*74fe6c29SRuslan Bukin 
pt_qry_decode_mnt(struct pt_query_decoder * decoder)3412*74fe6c29SRuslan Bukin int pt_qry_decode_mnt(struct pt_query_decoder *decoder)
3413*74fe6c29SRuslan Bukin {
3414*74fe6c29SRuslan Bukin 	struct pt_packet_mnt packet;
3415*74fe6c29SRuslan Bukin 	struct pt_event *event;
3416*74fe6c29SRuslan Bukin 	int size, errcode;
3417*74fe6c29SRuslan Bukin 
3418*74fe6c29SRuslan Bukin 	if (!decoder)
3419*74fe6c29SRuslan Bukin 		return -pte_internal;
3420*74fe6c29SRuslan Bukin 
3421*74fe6c29SRuslan Bukin 	size = pt_pkt_read_mnt(&packet, decoder->pos, &decoder->config);
3422*74fe6c29SRuslan Bukin 	if (size < 0)
3423*74fe6c29SRuslan Bukin 		return size;
3424*74fe6c29SRuslan Bukin 
3425*74fe6c29SRuslan Bukin 	event = pt_evq_standalone(&decoder->evq);
3426*74fe6c29SRuslan Bukin 	if (!event)
3427*74fe6c29SRuslan Bukin 		return -pte_internal;
3428*74fe6c29SRuslan Bukin 
3429*74fe6c29SRuslan Bukin 	event->type = ptev_mnt;
3430*74fe6c29SRuslan Bukin 	event->variant.mnt.payload = packet.payload;
3431*74fe6c29SRuslan Bukin 
3432*74fe6c29SRuslan Bukin 	decoder->event = event;
3433*74fe6c29SRuslan Bukin 
3434*74fe6c29SRuslan Bukin 	errcode = pt_qry_event_time(event, decoder);
3435*74fe6c29SRuslan Bukin 	if (errcode < 0)
3436*74fe6c29SRuslan Bukin 		return errcode;
3437*74fe6c29SRuslan Bukin 
3438*74fe6c29SRuslan Bukin 	decoder->pos += size;
3439*74fe6c29SRuslan Bukin 
3440*74fe6c29SRuslan Bukin 	return 0;
3441*74fe6c29SRuslan Bukin }
3442*74fe6c29SRuslan Bukin 
pt_qry_header_mnt(struct pt_query_decoder * decoder)3443*74fe6c29SRuslan Bukin int pt_qry_header_mnt(struct pt_query_decoder *decoder)
3444*74fe6c29SRuslan Bukin {
3445*74fe6c29SRuslan Bukin 	struct pt_packet_mnt packet;
3446*74fe6c29SRuslan Bukin 	struct pt_event *event;
3447*74fe6c29SRuslan Bukin 	int size;
3448*74fe6c29SRuslan Bukin 
3449*74fe6c29SRuslan Bukin 	if (!decoder)
3450*74fe6c29SRuslan Bukin 		return -pte_internal;
3451*74fe6c29SRuslan Bukin 
3452*74fe6c29SRuslan Bukin 	size = pt_pkt_read_mnt(&packet, decoder->pos, &decoder->config);
3453*74fe6c29SRuslan Bukin 	if (size < 0)
3454*74fe6c29SRuslan Bukin 		return size;
3455*74fe6c29SRuslan Bukin 
3456*74fe6c29SRuslan Bukin 	event = pt_evq_enqueue(&decoder->evq, evb_psbend);
3457*74fe6c29SRuslan Bukin 	if (!event)
3458*74fe6c29SRuslan Bukin 		return -pte_nomem;
3459*74fe6c29SRuslan Bukin 
3460*74fe6c29SRuslan Bukin 	event->type = ptev_mnt;
3461*74fe6c29SRuslan Bukin 	event->variant.mnt.payload = packet.payload;
3462*74fe6c29SRuslan Bukin 
3463*74fe6c29SRuslan Bukin 	decoder->pos += size;
3464*74fe6c29SRuslan Bukin 
3465*74fe6c29SRuslan Bukin 	return 0;
3466*74fe6c29SRuslan Bukin }
3467*74fe6c29SRuslan Bukin 
pt_qry_decode_exstop(struct pt_query_decoder * decoder)3468*74fe6c29SRuslan Bukin int pt_qry_decode_exstop(struct pt_query_decoder *decoder)
3469*74fe6c29SRuslan Bukin {
3470*74fe6c29SRuslan Bukin 	struct pt_packet_exstop packet;
3471*74fe6c29SRuslan Bukin 	struct pt_event *event;
3472*74fe6c29SRuslan Bukin 	int size;
3473*74fe6c29SRuslan Bukin 
3474*74fe6c29SRuslan Bukin 	if (!decoder)
3475*74fe6c29SRuslan Bukin 		return -pte_internal;
3476*74fe6c29SRuslan Bukin 
3477*74fe6c29SRuslan Bukin 	size = pt_pkt_read_exstop(&packet, decoder->pos, &decoder->config);
3478*74fe6c29SRuslan Bukin 	if (size < 0)
3479*74fe6c29SRuslan Bukin 		return size;
3480*74fe6c29SRuslan Bukin 
3481*74fe6c29SRuslan Bukin 	if (packet.ip) {
3482*74fe6c29SRuslan Bukin 		event = pt_evq_enqueue(&decoder->evq, evb_fup);
3483*74fe6c29SRuslan Bukin 		if (!event)
3484*74fe6c29SRuslan Bukin 			return -pte_internal;
3485*74fe6c29SRuslan Bukin 
3486*74fe6c29SRuslan Bukin 		event->type = ptev_exstop;
3487*74fe6c29SRuslan Bukin 	} else {
3488*74fe6c29SRuslan Bukin 		event = pt_evq_standalone(&decoder->evq);
3489*74fe6c29SRuslan Bukin 		if (!event)
3490*74fe6c29SRuslan Bukin 			return -pte_internal;
3491*74fe6c29SRuslan Bukin 
3492*74fe6c29SRuslan Bukin 		event->type = ptev_exstop;
3493*74fe6c29SRuslan Bukin 
3494*74fe6c29SRuslan Bukin 		event->ip_suppressed = 1;
3495*74fe6c29SRuslan Bukin 		event->variant.exstop.ip = 0ull;
3496*74fe6c29SRuslan Bukin 
3497*74fe6c29SRuslan Bukin 		decoder->event = event;
3498*74fe6c29SRuslan Bukin 	}
3499*74fe6c29SRuslan Bukin 
3500*74fe6c29SRuslan Bukin 	decoder->pos += size;
3501*74fe6c29SRuslan Bukin 	return 0;
3502*74fe6c29SRuslan Bukin }
3503*74fe6c29SRuslan Bukin 
pt_qry_decode_mwait(struct pt_query_decoder * decoder)3504*74fe6c29SRuslan Bukin int pt_qry_decode_mwait(struct pt_query_decoder *decoder)
3505*74fe6c29SRuslan Bukin {
3506*74fe6c29SRuslan Bukin 	struct pt_packet_mwait packet;
3507*74fe6c29SRuslan Bukin 	struct pt_event *event;
3508*74fe6c29SRuslan Bukin 	int size;
3509*74fe6c29SRuslan Bukin 
3510*74fe6c29SRuslan Bukin 	if (!decoder)
3511*74fe6c29SRuslan Bukin 		return -pte_internal;
3512*74fe6c29SRuslan Bukin 
3513*74fe6c29SRuslan Bukin 	size = pt_pkt_read_mwait(&packet, decoder->pos, &decoder->config);
3514*74fe6c29SRuslan Bukin 	if (size < 0)
3515*74fe6c29SRuslan Bukin 		return size;
3516*74fe6c29SRuslan Bukin 
3517*74fe6c29SRuslan Bukin 	event = pt_evq_enqueue(&decoder->evq, evb_fup);
3518*74fe6c29SRuslan Bukin 	if (!event)
3519*74fe6c29SRuslan Bukin 		return -pte_internal;
3520*74fe6c29SRuslan Bukin 
3521*74fe6c29SRuslan Bukin 	event->type = ptev_mwait;
3522*74fe6c29SRuslan Bukin 	event->variant.mwait.hints = packet.hints;
3523*74fe6c29SRuslan Bukin 	event->variant.mwait.ext = packet.ext;
3524*74fe6c29SRuslan Bukin 
3525*74fe6c29SRuslan Bukin 	decoder->pos += size;
3526*74fe6c29SRuslan Bukin 	return 0;
3527*74fe6c29SRuslan Bukin }
3528*74fe6c29SRuslan Bukin 
pt_qry_decode_pwre(struct pt_query_decoder * decoder)3529*74fe6c29SRuslan Bukin int pt_qry_decode_pwre(struct pt_query_decoder *decoder)
3530*74fe6c29SRuslan Bukin {
3531*74fe6c29SRuslan Bukin 	struct pt_packet_pwre packet;
3532*74fe6c29SRuslan Bukin 	struct pt_event *event;
3533*74fe6c29SRuslan Bukin 	int size;
3534*74fe6c29SRuslan Bukin 
3535*74fe6c29SRuslan Bukin 	if (!decoder)
3536*74fe6c29SRuslan Bukin 		return -pte_internal;
3537*74fe6c29SRuslan Bukin 
3538*74fe6c29SRuslan Bukin 	size = pt_pkt_read_pwre(&packet, decoder->pos, &decoder->config);
3539*74fe6c29SRuslan Bukin 	if (size < 0)
3540*74fe6c29SRuslan Bukin 		return size;
3541*74fe6c29SRuslan Bukin 
3542*74fe6c29SRuslan Bukin 	event = pt_evq_standalone(&decoder->evq);
3543*74fe6c29SRuslan Bukin 	if (!event)
3544*74fe6c29SRuslan Bukin 		return -pte_internal;
3545*74fe6c29SRuslan Bukin 
3546*74fe6c29SRuslan Bukin 	event->type = ptev_pwre;
3547*74fe6c29SRuslan Bukin 	event->variant.pwre.state = packet.state;
3548*74fe6c29SRuslan Bukin 	event->variant.pwre.sub_state = packet.sub_state;
3549*74fe6c29SRuslan Bukin 
3550*74fe6c29SRuslan Bukin 	if (packet.hw)
3551*74fe6c29SRuslan Bukin 		event->variant.pwre.hw = 1;
3552*74fe6c29SRuslan Bukin 
3553*74fe6c29SRuslan Bukin 	decoder->event = event;
3554*74fe6c29SRuslan Bukin 
3555*74fe6c29SRuslan Bukin 	decoder->pos += size;
3556*74fe6c29SRuslan Bukin 	return 0;
3557*74fe6c29SRuslan Bukin }
3558*74fe6c29SRuslan Bukin 
pt_qry_decode_pwrx(struct pt_query_decoder * decoder)3559*74fe6c29SRuslan Bukin int pt_qry_decode_pwrx(struct pt_query_decoder *decoder)
3560*74fe6c29SRuslan Bukin {
3561*74fe6c29SRuslan Bukin 	struct pt_packet_pwrx packet;
3562*74fe6c29SRuslan Bukin 	struct pt_event *event;
3563*74fe6c29SRuslan Bukin 	int size;
3564*74fe6c29SRuslan Bukin 
3565*74fe6c29SRuslan Bukin 	if (!decoder)
3566*74fe6c29SRuslan Bukin 		return -pte_internal;
3567*74fe6c29SRuslan Bukin 
3568*74fe6c29SRuslan Bukin 	size = pt_pkt_read_pwrx(&packet, decoder->pos, &decoder->config);
3569*74fe6c29SRuslan Bukin 	if (size < 0)
3570*74fe6c29SRuslan Bukin 		return size;
3571*74fe6c29SRuslan Bukin 
3572*74fe6c29SRuslan Bukin 	event = pt_evq_standalone(&decoder->evq);
3573*74fe6c29SRuslan Bukin 	if (!event)
3574*74fe6c29SRuslan Bukin 		return -pte_internal;
3575*74fe6c29SRuslan Bukin 
3576*74fe6c29SRuslan Bukin 	event->type = ptev_pwrx;
3577*74fe6c29SRuslan Bukin 	event->variant.pwrx.last = packet.last;
3578*74fe6c29SRuslan Bukin 	event->variant.pwrx.deepest = packet.deepest;
3579*74fe6c29SRuslan Bukin 
3580*74fe6c29SRuslan Bukin 	if (packet.interrupt)
3581*74fe6c29SRuslan Bukin 		event->variant.pwrx.interrupt = 1;
3582*74fe6c29SRuslan Bukin 	if (packet.store)
3583*74fe6c29SRuslan Bukin 		event->variant.pwrx.store = 1;
3584*74fe6c29SRuslan Bukin 	if (packet.autonomous)
3585*74fe6c29SRuslan Bukin 		event->variant.pwrx.autonomous = 1;
3586*74fe6c29SRuslan Bukin 
3587*74fe6c29SRuslan Bukin 	decoder->event = event;
3588*74fe6c29SRuslan Bukin 
3589*74fe6c29SRuslan Bukin 	decoder->pos += size;
3590*74fe6c29SRuslan Bukin 	return 0;
3591*74fe6c29SRuslan Bukin }
3592*74fe6c29SRuslan Bukin 
pt_qry_decode_ptw(struct pt_query_decoder * decoder)3593*74fe6c29SRuslan Bukin int pt_qry_decode_ptw(struct pt_query_decoder *decoder)
3594*74fe6c29SRuslan Bukin {
3595*74fe6c29SRuslan Bukin 	struct pt_packet_ptw packet;
3596*74fe6c29SRuslan Bukin 	struct pt_event *event;
3597*74fe6c29SRuslan Bukin 	int size, pls;
3598*74fe6c29SRuslan Bukin 
3599*74fe6c29SRuslan Bukin 	if (!decoder)
3600*74fe6c29SRuslan Bukin 		return -pte_internal;
3601*74fe6c29SRuslan Bukin 
3602*74fe6c29SRuslan Bukin 	size = pt_pkt_read_ptw(&packet, decoder->pos, &decoder->config);
3603*74fe6c29SRuslan Bukin 	if (size < 0)
3604*74fe6c29SRuslan Bukin 		return size;
3605*74fe6c29SRuslan Bukin 
3606*74fe6c29SRuslan Bukin 	pls = pt_ptw_size(packet.plc);
3607*74fe6c29SRuslan Bukin 	if (pls < 0)
3608*74fe6c29SRuslan Bukin 		return pls;
3609*74fe6c29SRuslan Bukin 
3610*74fe6c29SRuslan Bukin 	if (packet.ip) {
3611*74fe6c29SRuslan Bukin 		event = pt_evq_enqueue(&decoder->evq, evb_fup);
3612*74fe6c29SRuslan Bukin 		if (!event)
3613*74fe6c29SRuslan Bukin 			return -pte_internal;
3614*74fe6c29SRuslan Bukin 	} else {
3615*74fe6c29SRuslan Bukin 		event = pt_evq_standalone(&decoder->evq);
3616*74fe6c29SRuslan Bukin 		if (!event)
3617*74fe6c29SRuslan Bukin 			return -pte_internal;
3618*74fe6c29SRuslan Bukin 
3619*74fe6c29SRuslan Bukin 		event->ip_suppressed = 1;
3620*74fe6c29SRuslan Bukin 
3621*74fe6c29SRuslan Bukin 		decoder->event = event;
3622*74fe6c29SRuslan Bukin 	}
3623*74fe6c29SRuslan Bukin 
3624*74fe6c29SRuslan Bukin 	event->type = ptev_ptwrite;
3625*74fe6c29SRuslan Bukin 	event->variant.ptwrite.size = (uint8_t) pls;
3626*74fe6c29SRuslan Bukin 	event->variant.ptwrite.payload = packet.payload;
3627*74fe6c29SRuslan Bukin 
3628*74fe6c29SRuslan Bukin 	decoder->pos += size;
3629*74fe6c29SRuslan Bukin 	return 0;
3630*74fe6c29SRuslan Bukin }
3631