xref: /freebsd/contrib/processor-trace/libipt/src/pt_query_decoder.c (revision 85f87cf491bec6f90948a85b10f5523ea24db9e3)
174fe6c29SRuslan Bukin /*
2*85f87cf4SRuslan Bukin  * Copyright (c) 2014-2019, Intel Corporation
374fe6c29SRuslan Bukin  *
474fe6c29SRuslan Bukin  * Redistribution and use in source and binary forms, with or without
574fe6c29SRuslan Bukin  * modification, are permitted provided that the following conditions are met:
674fe6c29SRuslan Bukin  *
774fe6c29SRuslan Bukin  *  * Redistributions of source code must retain the above copyright notice,
874fe6c29SRuslan Bukin  *    this list of conditions and the following disclaimer.
974fe6c29SRuslan Bukin  *  * Redistributions in binary form must reproduce the above copyright notice,
1074fe6c29SRuslan Bukin  *    this list of conditions and the following disclaimer in the documentation
1174fe6c29SRuslan Bukin  *    and/or other materials provided with the distribution.
1274fe6c29SRuslan Bukin  *  * Neither the name of Intel Corporation nor the names of its contributors
1374fe6c29SRuslan Bukin  *    may be used to endorse or promote products derived from this software
1474fe6c29SRuslan Bukin  *    without specific prior written permission.
1574fe6c29SRuslan Bukin  *
1674fe6c29SRuslan Bukin  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1774fe6c29SRuslan Bukin  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1874fe6c29SRuslan Bukin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1974fe6c29SRuslan Bukin  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2074fe6c29SRuslan Bukin  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2174fe6c29SRuslan Bukin  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2274fe6c29SRuslan Bukin  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2374fe6c29SRuslan Bukin  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2474fe6c29SRuslan Bukin  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2574fe6c29SRuslan Bukin  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2674fe6c29SRuslan Bukin  * POSSIBILITY OF SUCH DAMAGE.
2774fe6c29SRuslan Bukin  */
2874fe6c29SRuslan Bukin 
2974fe6c29SRuslan Bukin #include "pt_query_decoder.h"
3074fe6c29SRuslan Bukin #include "pt_sync.h"
3174fe6c29SRuslan Bukin #include "pt_decoder_function.h"
3274fe6c29SRuslan Bukin #include "pt_packet.h"
3374fe6c29SRuslan Bukin #include "pt_packet_decoder.h"
3474fe6c29SRuslan Bukin #include "pt_config.h"
3574fe6c29SRuslan Bukin #include "pt_opcodes.h"
3674fe6c29SRuslan Bukin #include "pt_compiler.h"
3774fe6c29SRuslan Bukin 
3874fe6c29SRuslan Bukin #include "intel-pt.h"
3974fe6c29SRuslan Bukin 
4074fe6c29SRuslan Bukin #include <string.h>
4174fe6c29SRuslan Bukin #include <stddef.h>
4274fe6c29SRuslan Bukin #include <stdlib.h>
4374fe6c29SRuslan Bukin #include <limits.h>
4474fe6c29SRuslan Bukin 
4574fe6c29SRuslan Bukin 
4674fe6c29SRuslan Bukin /* Find a FUP in a PSB+ header.
4774fe6c29SRuslan Bukin  *
4874fe6c29SRuslan Bukin  * The packet @decoder must be synchronized onto the trace stream at the
4974fe6c29SRuslan Bukin  * beginning or somewhere inside a PSB+ header.
5074fe6c29SRuslan Bukin  *
5174fe6c29SRuslan Bukin  * It uses @packet to hold trace packets during its search.  If the search is
5274fe6c29SRuslan Bukin  * successful, @packet will contain the first (and hopefully only) FUP packet in
5374fe6c29SRuslan Bukin  * this PSB+.  Otherwise, @packet may contain anything.
5474fe6c29SRuslan Bukin  *
5574fe6c29SRuslan Bukin  * Returns one if a FUP packet is found (@packet will contain it).
5674fe6c29SRuslan Bukin  * Returns zero if no FUP packet is found (@packet is undefined).
5774fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
5874fe6c29SRuslan Bukin  */
pt_qry_find_header_fup(struct pt_packet * packet,struct pt_packet_decoder * decoder)5974fe6c29SRuslan Bukin static int pt_qry_find_header_fup(struct pt_packet *packet,
6074fe6c29SRuslan Bukin 				  struct pt_packet_decoder *decoder)
6174fe6c29SRuslan Bukin {
6274fe6c29SRuslan Bukin 	if (!packet || !decoder)
6374fe6c29SRuslan Bukin 		return -pte_internal;
6474fe6c29SRuslan Bukin 
6574fe6c29SRuslan Bukin 	for (;;) {
6674fe6c29SRuslan Bukin 		int errcode;
6774fe6c29SRuslan Bukin 
6874fe6c29SRuslan Bukin 		errcode = pt_pkt_next(decoder, packet, sizeof(*packet));
6974fe6c29SRuslan Bukin 		if (errcode < 0)
7074fe6c29SRuslan Bukin 			return errcode;
7174fe6c29SRuslan Bukin 
7274fe6c29SRuslan Bukin 		switch (packet->type) {
7374fe6c29SRuslan Bukin 		default:
7474fe6c29SRuslan Bukin 			/* Ignore the packet. */
7574fe6c29SRuslan Bukin 			break;
7674fe6c29SRuslan Bukin 
7774fe6c29SRuslan Bukin 		case ppt_psbend:
7874fe6c29SRuslan Bukin 			/* There's no FUP in here. */
7974fe6c29SRuslan Bukin 			return 0;
8074fe6c29SRuslan Bukin 
8174fe6c29SRuslan Bukin 		case ppt_fup:
8274fe6c29SRuslan Bukin 			/* Found it. */
8374fe6c29SRuslan Bukin 			return 1;
8474fe6c29SRuslan Bukin 		}
8574fe6c29SRuslan Bukin 	}
8674fe6c29SRuslan Bukin }
8774fe6c29SRuslan Bukin 
pt_qry_decoder_init(struct pt_query_decoder * decoder,const struct pt_config * config)8874fe6c29SRuslan Bukin int pt_qry_decoder_init(struct pt_query_decoder *decoder,
8974fe6c29SRuslan Bukin 			const struct pt_config *config)
9074fe6c29SRuslan Bukin {
9174fe6c29SRuslan Bukin 	int errcode;
9274fe6c29SRuslan Bukin 
9374fe6c29SRuslan Bukin 	if (!decoder)
9474fe6c29SRuslan Bukin 		return -pte_invalid;
9574fe6c29SRuslan Bukin 
9674fe6c29SRuslan Bukin 	memset(decoder, 0, sizeof(*decoder));
9774fe6c29SRuslan Bukin 
9874fe6c29SRuslan Bukin 	errcode = pt_config_from_user(&decoder->config, config);
9974fe6c29SRuslan Bukin 	if (errcode < 0)
10074fe6c29SRuslan Bukin 		return errcode;
10174fe6c29SRuslan Bukin 
10274fe6c29SRuslan Bukin 	pt_last_ip_init(&decoder->ip);
10374fe6c29SRuslan Bukin 	pt_tnt_cache_init(&decoder->tnt);
10474fe6c29SRuslan Bukin 	pt_time_init(&decoder->time);
10574fe6c29SRuslan Bukin 	pt_time_init(&decoder->last_time);
10674fe6c29SRuslan Bukin 	pt_tcal_init(&decoder->tcal);
10774fe6c29SRuslan Bukin 	pt_evq_init(&decoder->evq);
10874fe6c29SRuslan Bukin 
10974fe6c29SRuslan Bukin 	return 0;
11074fe6c29SRuslan Bukin }
11174fe6c29SRuslan Bukin 
pt_qry_alloc_decoder(const struct pt_config * config)11274fe6c29SRuslan Bukin struct pt_query_decoder *pt_qry_alloc_decoder(const struct pt_config *config)
11374fe6c29SRuslan Bukin {
11474fe6c29SRuslan Bukin 	struct pt_query_decoder *decoder;
11574fe6c29SRuslan Bukin 	int errcode;
11674fe6c29SRuslan Bukin 
11774fe6c29SRuslan Bukin 	decoder = malloc(sizeof(*decoder));
11874fe6c29SRuslan Bukin 	if (!decoder)
11974fe6c29SRuslan Bukin 		return NULL;
12074fe6c29SRuslan Bukin 
12174fe6c29SRuslan Bukin 	errcode = pt_qry_decoder_init(decoder, config);
12274fe6c29SRuslan Bukin 	if (errcode < 0) {
12374fe6c29SRuslan Bukin 		free(decoder);
12474fe6c29SRuslan Bukin 		return NULL;
12574fe6c29SRuslan Bukin 	}
12674fe6c29SRuslan Bukin 
12774fe6c29SRuslan Bukin 	return decoder;
12874fe6c29SRuslan Bukin }
12974fe6c29SRuslan Bukin 
pt_qry_decoder_fini(struct pt_query_decoder * decoder)13074fe6c29SRuslan Bukin void pt_qry_decoder_fini(struct pt_query_decoder *decoder)
13174fe6c29SRuslan Bukin {
13274fe6c29SRuslan Bukin 	(void) decoder;
13374fe6c29SRuslan Bukin 
13474fe6c29SRuslan Bukin 	/* Nothing to do. */
13574fe6c29SRuslan Bukin }
13674fe6c29SRuslan Bukin 
pt_qry_free_decoder(struct pt_query_decoder * decoder)13774fe6c29SRuslan Bukin void pt_qry_free_decoder(struct pt_query_decoder *decoder)
13874fe6c29SRuslan Bukin {
13974fe6c29SRuslan Bukin 	pt_qry_decoder_fini(decoder);
14074fe6c29SRuslan Bukin 	free(decoder);
14174fe6c29SRuslan Bukin }
14274fe6c29SRuslan Bukin 
pt_qry_reset(struct pt_query_decoder * decoder)14374fe6c29SRuslan Bukin static void pt_qry_reset(struct pt_query_decoder *decoder)
14474fe6c29SRuslan Bukin {
14574fe6c29SRuslan Bukin 	if (!decoder)
14674fe6c29SRuslan Bukin 		return;
14774fe6c29SRuslan Bukin 
14874fe6c29SRuslan Bukin 	decoder->enabled = 0;
14974fe6c29SRuslan Bukin 	decoder->consume_packet = 0;
15074fe6c29SRuslan Bukin 	decoder->event = NULL;
15174fe6c29SRuslan Bukin 
15274fe6c29SRuslan Bukin 	pt_last_ip_init(&decoder->ip);
15374fe6c29SRuslan Bukin 	pt_tnt_cache_init(&decoder->tnt);
15474fe6c29SRuslan Bukin 	pt_time_init(&decoder->time);
15574fe6c29SRuslan Bukin 	pt_time_init(&decoder->last_time);
15674fe6c29SRuslan Bukin 	pt_tcal_init(&decoder->tcal);
15774fe6c29SRuslan Bukin 	pt_evq_init(&decoder->evq);
15874fe6c29SRuslan Bukin }
15974fe6c29SRuslan Bukin 
pt_qry_will_event(const struct pt_query_decoder * decoder)16074fe6c29SRuslan Bukin static int pt_qry_will_event(const struct pt_query_decoder *decoder)
16174fe6c29SRuslan Bukin {
16274fe6c29SRuslan Bukin 	const struct pt_decoder_function *dfun;
16374fe6c29SRuslan Bukin 
16474fe6c29SRuslan Bukin 	if (!decoder)
16574fe6c29SRuslan Bukin 		return -pte_internal;
16674fe6c29SRuslan Bukin 
16774fe6c29SRuslan Bukin 	dfun = decoder->next;
16874fe6c29SRuslan Bukin 	if (!dfun)
16974fe6c29SRuslan Bukin 		return 0;
17074fe6c29SRuslan Bukin 
17174fe6c29SRuslan Bukin 	if (dfun->flags & pdff_event)
17274fe6c29SRuslan Bukin 		return 1;
17374fe6c29SRuslan Bukin 
17474fe6c29SRuslan Bukin 	if (dfun->flags & pdff_psbend)
17574fe6c29SRuslan Bukin 		return pt_evq_pending(&decoder->evq, evb_psbend);
17674fe6c29SRuslan Bukin 
17774fe6c29SRuslan Bukin 	if (dfun->flags & pdff_tip)
17874fe6c29SRuslan Bukin 		return pt_evq_pending(&decoder->evq, evb_tip);
17974fe6c29SRuslan Bukin 
18074fe6c29SRuslan Bukin 	if (dfun->flags & pdff_fup)
18174fe6c29SRuslan Bukin 		return pt_evq_pending(&decoder->evq, evb_fup);
18274fe6c29SRuslan Bukin 
18374fe6c29SRuslan Bukin 	return 0;
18474fe6c29SRuslan Bukin }
18574fe6c29SRuslan Bukin 
pt_qry_will_eos(const struct pt_query_decoder * decoder)18674fe6c29SRuslan Bukin static int pt_qry_will_eos(const struct pt_query_decoder *decoder)
18774fe6c29SRuslan Bukin {
18874fe6c29SRuslan Bukin 	const struct pt_decoder_function *dfun;
18974fe6c29SRuslan Bukin 	int errcode;
19074fe6c29SRuslan Bukin 
19174fe6c29SRuslan Bukin 	if (!decoder)
19274fe6c29SRuslan Bukin 		return -pte_internal;
19374fe6c29SRuslan Bukin 
19474fe6c29SRuslan Bukin 	dfun = decoder->next;
19574fe6c29SRuslan Bukin 	if (dfun)
19674fe6c29SRuslan Bukin 		return 0;
19774fe6c29SRuslan Bukin 
19874fe6c29SRuslan Bukin 	/* The decoding function may be NULL for two reasons:
19974fe6c29SRuslan Bukin 	 *
20074fe6c29SRuslan Bukin 	 *   - we ran out of trace
20174fe6c29SRuslan Bukin 	 *   - we ran into a fetch error such as -pte_bad_opc
20274fe6c29SRuslan Bukin 	 *
20374fe6c29SRuslan Bukin 	 * Let's fetch again.
20474fe6c29SRuslan Bukin 	 */
20574fe6c29SRuslan Bukin 	errcode = pt_df_fetch(&dfun, decoder->pos, &decoder->config);
20674fe6c29SRuslan Bukin 	return errcode == -pte_eos;
20774fe6c29SRuslan Bukin }
20874fe6c29SRuslan Bukin 
pt_qry_status_flags(const struct pt_query_decoder * decoder)20974fe6c29SRuslan Bukin static int pt_qry_status_flags(const struct pt_query_decoder *decoder)
21074fe6c29SRuslan Bukin {
21174fe6c29SRuslan Bukin 	int flags = 0;
21274fe6c29SRuslan Bukin 
21374fe6c29SRuslan Bukin 	if (!decoder)
21474fe6c29SRuslan Bukin 		return -pte_internal;
21574fe6c29SRuslan Bukin 
21674fe6c29SRuslan Bukin 	/* Some packets force out TNT and any deferred TIPs in order to
21774fe6c29SRuslan Bukin 	 * establish the correct context for the subsequent packet.
21874fe6c29SRuslan Bukin 	 *
21974fe6c29SRuslan Bukin 	 * Users are expected to first navigate to the correct code region
22074fe6c29SRuslan Bukin 	 * by using up the cached TNT bits before interpreting any subsequent
22174fe6c29SRuslan Bukin 	 * packets.
22274fe6c29SRuslan Bukin 	 *
22374fe6c29SRuslan Bukin 	 * We do need to read ahead in order to signal upcoming events.  We may
22474fe6c29SRuslan Bukin 	 * have already decoded those packets while our user has not navigated
22574fe6c29SRuslan Bukin 	 * to the correct code region, yet.
22674fe6c29SRuslan Bukin 	 *
22774fe6c29SRuslan Bukin 	 * In order to have our user use up the cached TNT bits first, we do
22874fe6c29SRuslan Bukin 	 * not indicate the next event until the TNT cache is empty.
22974fe6c29SRuslan Bukin 	 */
23074fe6c29SRuslan Bukin 	if (pt_tnt_cache_is_empty(&decoder->tnt)) {
23174fe6c29SRuslan Bukin 		if (pt_qry_will_event(decoder))
23274fe6c29SRuslan Bukin 			flags |= pts_event_pending;
23374fe6c29SRuslan Bukin 
23474fe6c29SRuslan Bukin 		if (pt_qry_will_eos(decoder))
23574fe6c29SRuslan Bukin 			flags |= pts_eos;
23674fe6c29SRuslan Bukin 	}
23774fe6c29SRuslan Bukin 
23874fe6c29SRuslan Bukin 	return flags;
23974fe6c29SRuslan Bukin }
24074fe6c29SRuslan Bukin 
pt_qry_provoke_fetch_error(const struct pt_query_decoder * decoder)24174fe6c29SRuslan Bukin static int pt_qry_provoke_fetch_error(const struct pt_query_decoder *decoder)
24274fe6c29SRuslan Bukin {
24374fe6c29SRuslan Bukin 	const struct pt_decoder_function *dfun;
24474fe6c29SRuslan Bukin 	int errcode;
24574fe6c29SRuslan Bukin 
24674fe6c29SRuslan Bukin 	if (!decoder)
24774fe6c29SRuslan Bukin 		return -pte_internal;
24874fe6c29SRuslan Bukin 
24974fe6c29SRuslan Bukin 	/* Repeat the decoder fetch to reproduce the error. */
25074fe6c29SRuslan Bukin 	errcode = pt_df_fetch(&dfun, decoder->pos, &decoder->config);
25174fe6c29SRuslan Bukin 	if (errcode < 0)
25274fe6c29SRuslan Bukin 		return errcode;
25374fe6c29SRuslan Bukin 
25474fe6c29SRuslan Bukin 	/* We must get some error or something's wrong. */
25574fe6c29SRuslan Bukin 	return -pte_internal;
25674fe6c29SRuslan Bukin }
25774fe6c29SRuslan Bukin 
pt_qry_read_ahead(struct pt_query_decoder * decoder)25874fe6c29SRuslan Bukin static int pt_qry_read_ahead(struct pt_query_decoder *decoder)
25974fe6c29SRuslan Bukin {
26074fe6c29SRuslan Bukin 	if (!decoder)
26174fe6c29SRuslan Bukin 		return -pte_internal;
26274fe6c29SRuslan Bukin 
26374fe6c29SRuslan Bukin 	for (;;) {
26474fe6c29SRuslan Bukin 		const struct pt_decoder_function *dfun;
26574fe6c29SRuslan Bukin 		int errcode;
26674fe6c29SRuslan Bukin 
26774fe6c29SRuslan Bukin 		errcode = pt_df_fetch(&decoder->next, decoder->pos,
26874fe6c29SRuslan Bukin 				      &decoder->config);
26974fe6c29SRuslan Bukin 		if (errcode)
27074fe6c29SRuslan Bukin 			return errcode;
27174fe6c29SRuslan Bukin 
27274fe6c29SRuslan Bukin 		dfun = decoder->next;
27374fe6c29SRuslan Bukin 		if (!dfun)
27474fe6c29SRuslan Bukin 			return -pte_internal;
27574fe6c29SRuslan Bukin 
27674fe6c29SRuslan Bukin 		if (!dfun->decode)
27774fe6c29SRuslan Bukin 			return -pte_internal;
27874fe6c29SRuslan Bukin 
27974fe6c29SRuslan Bukin 		/* We're done once we reach
28074fe6c29SRuslan Bukin 		 *
28174fe6c29SRuslan Bukin 		 * - a branching related packet. */
28274fe6c29SRuslan Bukin 		if (dfun->flags & (pdff_tip | pdff_tnt))
28374fe6c29SRuslan Bukin 			return 0;
28474fe6c29SRuslan Bukin 
28574fe6c29SRuslan Bukin 		/* - an event related packet. */
28674fe6c29SRuslan Bukin 		if (pt_qry_will_event(decoder))
28774fe6c29SRuslan Bukin 			return 0;
28874fe6c29SRuslan Bukin 
28974fe6c29SRuslan Bukin 		/* Decode status update packets. */
29074fe6c29SRuslan Bukin 		errcode = dfun->decode(decoder);
29174fe6c29SRuslan Bukin 		if (errcode) {
29274fe6c29SRuslan Bukin 			/* Ignore truncated status packets at the end.
29374fe6c29SRuslan Bukin 			 *
29474fe6c29SRuslan Bukin 			 * Move beyond the packet and clear @decoder->next to
29574fe6c29SRuslan Bukin 			 * indicate that we were not able to fetch the next
29674fe6c29SRuslan Bukin 			 * packet.
29774fe6c29SRuslan Bukin 			 */
29874fe6c29SRuslan Bukin 			if (errcode == -pte_eos) {
29974fe6c29SRuslan Bukin 				decoder->pos = decoder->config.end;
30074fe6c29SRuslan Bukin 				decoder->next = NULL;
30174fe6c29SRuslan Bukin 			}
30274fe6c29SRuslan Bukin 
30374fe6c29SRuslan Bukin 			return errcode;
30474fe6c29SRuslan Bukin 		}
30574fe6c29SRuslan Bukin 	}
30674fe6c29SRuslan Bukin }
30774fe6c29SRuslan Bukin 
pt_qry_start(struct pt_query_decoder * decoder,const uint8_t * pos,uint64_t * addr)30874fe6c29SRuslan Bukin static int pt_qry_start(struct pt_query_decoder *decoder, const uint8_t *pos,
30974fe6c29SRuslan Bukin 			uint64_t *addr)
31074fe6c29SRuslan Bukin {
31174fe6c29SRuslan Bukin 	const struct pt_decoder_function *dfun;
31274fe6c29SRuslan Bukin 	int status, errcode;
31374fe6c29SRuslan Bukin 
31474fe6c29SRuslan Bukin 	if (!decoder || !pos)
31574fe6c29SRuslan Bukin 		return -pte_invalid;
31674fe6c29SRuslan Bukin 
31774fe6c29SRuslan Bukin 	pt_qry_reset(decoder);
31874fe6c29SRuslan Bukin 
31974fe6c29SRuslan Bukin 	decoder->sync = pos;
32074fe6c29SRuslan Bukin 	decoder->pos = pos;
32174fe6c29SRuslan Bukin 
32274fe6c29SRuslan Bukin 	errcode = pt_df_fetch(&decoder->next, pos, &decoder->config);
32374fe6c29SRuslan Bukin 	if (errcode)
32474fe6c29SRuslan Bukin 		return errcode;
32574fe6c29SRuslan Bukin 
32674fe6c29SRuslan Bukin 	dfun = decoder->next;
32774fe6c29SRuslan Bukin 
32874fe6c29SRuslan Bukin 	/* We do need to start at a PSB in order to initialize the state. */
32974fe6c29SRuslan Bukin 	if (dfun != &pt_decode_psb)
33074fe6c29SRuslan Bukin 		return -pte_nosync;
33174fe6c29SRuslan Bukin 
33274fe6c29SRuslan Bukin 	/* Decode the PSB+ header to initialize the state. */
33374fe6c29SRuslan Bukin 	errcode = dfun->decode(decoder);
33474fe6c29SRuslan Bukin 	if (errcode < 0)
33574fe6c29SRuslan Bukin 		return errcode;
33674fe6c29SRuslan Bukin 
33774fe6c29SRuslan Bukin 	/* Fill in the start address.
33874fe6c29SRuslan Bukin 	 * We do this before reading ahead since the latter may read an
33974fe6c29SRuslan Bukin 	 * adjacent PSB+ that might change the decoder's IP, causing us
34074fe6c29SRuslan Bukin 	 * to skip code.
34174fe6c29SRuslan Bukin 	 */
34274fe6c29SRuslan Bukin 	if (addr) {
34374fe6c29SRuslan Bukin 		status = pt_last_ip_query(addr, &decoder->ip);
34474fe6c29SRuslan Bukin 
34574fe6c29SRuslan Bukin 		/* Make sure we don't clobber it later on. */
34674fe6c29SRuslan Bukin 		if (!status)
34774fe6c29SRuslan Bukin 			addr = NULL;
34874fe6c29SRuslan Bukin 	}
34974fe6c29SRuslan Bukin 
35074fe6c29SRuslan Bukin 	/* Read ahead until the first query-relevant packet. */
35174fe6c29SRuslan Bukin 	errcode = pt_qry_read_ahead(decoder);
35274fe6c29SRuslan Bukin 	if (errcode < 0)
35374fe6c29SRuslan Bukin 		return errcode;
35474fe6c29SRuslan Bukin 
35574fe6c29SRuslan Bukin 	/* We return the current decoder status. */
35674fe6c29SRuslan Bukin 	status = pt_qry_status_flags(decoder);
35774fe6c29SRuslan Bukin 	if (status < 0)
35874fe6c29SRuslan Bukin 		return status;
35974fe6c29SRuslan Bukin 
36074fe6c29SRuslan Bukin 	errcode = pt_last_ip_query(addr, &decoder->ip);
36174fe6c29SRuslan Bukin 	if (errcode < 0) {
36274fe6c29SRuslan Bukin 		/* Indicate the missing IP in the status. */
36374fe6c29SRuslan Bukin 		if (addr)
36474fe6c29SRuslan Bukin 			status |= pts_ip_suppressed;
36574fe6c29SRuslan Bukin 	}
36674fe6c29SRuslan Bukin 
36774fe6c29SRuslan Bukin 	return status;
36874fe6c29SRuslan Bukin }
36974fe6c29SRuslan 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)37074fe6c29SRuslan Bukin static int pt_qry_apply_tsc(struct pt_time *time, struct pt_time_cal *tcal,
37174fe6c29SRuslan Bukin 			    const struct pt_packet_tsc *packet,
37274fe6c29SRuslan Bukin 			    const struct pt_config *config)
37374fe6c29SRuslan Bukin {
37474fe6c29SRuslan Bukin 	int errcode;
37574fe6c29SRuslan Bukin 
37674fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
37774fe6c29SRuslan Bukin 	 * calibration which will result in imprecise cycle-accurate timing.
37874fe6c29SRuslan Bukin 	 *
37974fe6c29SRuslan Bukin 	 * We currently do not track them.
38074fe6c29SRuslan Bukin 	 */
38174fe6c29SRuslan Bukin 	errcode = pt_tcal_update_tsc(tcal, packet, config);
38274fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
38374fe6c29SRuslan Bukin 		return errcode;
38474fe6c29SRuslan Bukin 
38574fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
38674fe6c29SRuslan Bukin 	 * timing and are tracked as packet losses in struct pt_time.
38774fe6c29SRuslan Bukin 	 */
38874fe6c29SRuslan Bukin 	errcode = pt_time_update_tsc(time, packet, config);
38974fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
39074fe6c29SRuslan Bukin 		return errcode;
39174fe6c29SRuslan Bukin 
39274fe6c29SRuslan Bukin 	return 0;
39374fe6c29SRuslan Bukin }
39474fe6c29SRuslan 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)39574fe6c29SRuslan Bukin static int pt_qry_apply_header_tsc(struct pt_time *time,
39674fe6c29SRuslan Bukin 				   struct pt_time_cal *tcal,
39774fe6c29SRuslan Bukin 				   const struct pt_packet_tsc *packet,
39874fe6c29SRuslan Bukin 				   const struct pt_config *config)
39974fe6c29SRuslan Bukin {
40074fe6c29SRuslan Bukin 	int errcode;
40174fe6c29SRuslan Bukin 
40274fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
40374fe6c29SRuslan Bukin 	 * calibration which will result in imprecise cycle-accurate timing.
40474fe6c29SRuslan Bukin 	 *
40574fe6c29SRuslan Bukin 	 * We currently do not track them.
40674fe6c29SRuslan Bukin 	 */
40774fe6c29SRuslan Bukin 	errcode = pt_tcal_header_tsc(tcal, packet, config);
40874fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
40974fe6c29SRuslan Bukin 		return errcode;
41074fe6c29SRuslan Bukin 
41174fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
41274fe6c29SRuslan Bukin 	 * timing and are tracked as packet losses in struct pt_time.
41374fe6c29SRuslan Bukin 	 */
41474fe6c29SRuslan Bukin 	errcode = pt_time_update_tsc(time, packet, config);
41574fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
41674fe6c29SRuslan Bukin 		return errcode;
41774fe6c29SRuslan Bukin 
41874fe6c29SRuslan Bukin 	return 0;
41974fe6c29SRuslan Bukin }
42074fe6c29SRuslan 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)42174fe6c29SRuslan Bukin static int pt_qry_apply_cbr(struct pt_time *time, struct pt_time_cal *tcal,
42274fe6c29SRuslan Bukin 			    const struct pt_packet_cbr *packet,
42374fe6c29SRuslan Bukin 			    const struct pt_config *config)
42474fe6c29SRuslan Bukin {
42574fe6c29SRuslan Bukin 	int errcode;
42674fe6c29SRuslan Bukin 
42774fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
42874fe6c29SRuslan Bukin 	 * calibration which will result in imprecise cycle-accurate timing.
42974fe6c29SRuslan Bukin 	 *
43074fe6c29SRuslan Bukin 	 * We currently do not track them.
43174fe6c29SRuslan Bukin 	 */
43274fe6c29SRuslan Bukin 	errcode = pt_tcal_update_cbr(tcal, packet, config);
43374fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
43474fe6c29SRuslan Bukin 		return errcode;
43574fe6c29SRuslan Bukin 
43674fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
43774fe6c29SRuslan Bukin 	 * timing and are tracked as packet losses in struct pt_time.
43874fe6c29SRuslan Bukin 	 */
43974fe6c29SRuslan Bukin 	errcode = pt_time_update_cbr(time, packet, config);
44074fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
44174fe6c29SRuslan Bukin 		return errcode;
44274fe6c29SRuslan Bukin 
44374fe6c29SRuslan Bukin 	return 0;
44474fe6c29SRuslan Bukin }
44574fe6c29SRuslan 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)44674fe6c29SRuslan Bukin static int pt_qry_apply_header_cbr(struct pt_time *time,
44774fe6c29SRuslan Bukin 				   struct pt_time_cal *tcal,
44874fe6c29SRuslan Bukin 				   const struct pt_packet_cbr *packet,
44974fe6c29SRuslan Bukin 				   const struct pt_config *config)
45074fe6c29SRuslan Bukin {
45174fe6c29SRuslan Bukin 	int errcode;
45274fe6c29SRuslan Bukin 
45374fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
45474fe6c29SRuslan Bukin 	 * calibration which will result in imprecise cycle-accurate timing.
45574fe6c29SRuslan Bukin 	 *
45674fe6c29SRuslan Bukin 	 * We currently do not track them.
45774fe6c29SRuslan Bukin 	 */
45874fe6c29SRuslan Bukin 	errcode = pt_tcal_header_cbr(tcal, packet, config);
45974fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
46074fe6c29SRuslan Bukin 		return errcode;
46174fe6c29SRuslan Bukin 
46274fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
46374fe6c29SRuslan Bukin 	 * timing and are tracked as packet losses in struct pt_time.
46474fe6c29SRuslan Bukin 	 */
46574fe6c29SRuslan Bukin 	errcode = pt_time_update_cbr(time, packet, config);
46674fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
46774fe6c29SRuslan Bukin 		return errcode;
46874fe6c29SRuslan Bukin 
46974fe6c29SRuslan Bukin 	return 0;
47074fe6c29SRuslan Bukin }
47174fe6c29SRuslan 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)47274fe6c29SRuslan Bukin static int pt_qry_apply_tma(struct pt_time *time, struct pt_time_cal *tcal,
47374fe6c29SRuslan Bukin 			    const struct pt_packet_tma *packet,
47474fe6c29SRuslan Bukin 			    const struct pt_config *config)
47574fe6c29SRuslan Bukin {
47674fe6c29SRuslan Bukin 	int errcode;
47774fe6c29SRuslan Bukin 
47874fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
47974fe6c29SRuslan Bukin 	 * calibration which will result in imprecise cycle-accurate timing.
48074fe6c29SRuslan Bukin 	 *
48174fe6c29SRuslan Bukin 	 * We currently do not track them.
48274fe6c29SRuslan Bukin 	 */
48374fe6c29SRuslan Bukin 	errcode = pt_tcal_update_tma(tcal, packet, config);
48474fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
48574fe6c29SRuslan Bukin 		return errcode;
48674fe6c29SRuslan Bukin 
48774fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
48874fe6c29SRuslan Bukin 	 * timing and are tracked as packet losses in struct pt_time.
48974fe6c29SRuslan Bukin 	 */
49074fe6c29SRuslan Bukin 	errcode = pt_time_update_tma(time, packet, config);
49174fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
49274fe6c29SRuslan Bukin 		return errcode;
49374fe6c29SRuslan Bukin 
49474fe6c29SRuslan Bukin 	return 0;
49574fe6c29SRuslan Bukin }
49674fe6c29SRuslan 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)49774fe6c29SRuslan Bukin static int pt_qry_apply_mtc(struct pt_time *time, struct pt_time_cal *tcal,
49874fe6c29SRuslan Bukin 			    const struct pt_packet_mtc *packet,
49974fe6c29SRuslan Bukin 			    const struct pt_config *config)
50074fe6c29SRuslan Bukin {
50174fe6c29SRuslan Bukin 	int errcode;
50274fe6c29SRuslan Bukin 
50374fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
50474fe6c29SRuslan Bukin 	 * calibration which will result in imprecise cycle-accurate timing.
50574fe6c29SRuslan Bukin 	 *
50674fe6c29SRuslan Bukin 	 * We currently do not track them.
50774fe6c29SRuslan Bukin 	 */
50874fe6c29SRuslan Bukin 	errcode = pt_tcal_update_mtc(tcal, packet, config);
50974fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
51074fe6c29SRuslan Bukin 		return errcode;
51174fe6c29SRuslan Bukin 
51274fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
51374fe6c29SRuslan Bukin 	 * timing and are tracked as packet losses in struct pt_time.
51474fe6c29SRuslan Bukin 	 */
51574fe6c29SRuslan Bukin 	errcode = pt_time_update_mtc(time, packet, config);
51674fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
51774fe6c29SRuslan Bukin 		return errcode;
51874fe6c29SRuslan Bukin 
51974fe6c29SRuslan Bukin 	return 0;
52074fe6c29SRuslan Bukin }
52174fe6c29SRuslan 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)52274fe6c29SRuslan Bukin static int pt_qry_apply_cyc(struct pt_time *time, struct pt_time_cal *tcal,
52374fe6c29SRuslan Bukin 			    const struct pt_packet_cyc *packet,
52474fe6c29SRuslan Bukin 			    const struct pt_config *config)
52574fe6c29SRuslan Bukin {
52674fe6c29SRuslan Bukin 	uint64_t fcr;
52774fe6c29SRuslan Bukin 	int errcode;
52874fe6c29SRuslan Bukin 
52974fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
53074fe6c29SRuslan Bukin 	 * calibration which will result in imprecise cycle-accurate timing.
53174fe6c29SRuslan Bukin 	 *
53274fe6c29SRuslan Bukin 	 * We currently do not track them.
53374fe6c29SRuslan Bukin 	 */
53474fe6c29SRuslan Bukin 	errcode = pt_tcal_update_cyc(tcal, packet, config);
53574fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
53674fe6c29SRuslan Bukin 		return errcode;
53774fe6c29SRuslan Bukin 
53874fe6c29SRuslan Bukin 	/* We need the FastCounter to Cycles ratio below.  Fall back to
53974fe6c29SRuslan Bukin 	 * an invalid ratio of 0 if calibration has not kicked in, yet.
54074fe6c29SRuslan Bukin 	 *
54174fe6c29SRuslan Bukin 	 * This will be tracked as packet loss in struct pt_time.
54274fe6c29SRuslan Bukin 	 */
54374fe6c29SRuslan Bukin 	errcode = pt_tcal_fcr(&fcr, tcal);
54474fe6c29SRuslan Bukin 	if (errcode < 0) {
54574fe6c29SRuslan Bukin 		if (errcode == -pte_no_time)
54674fe6c29SRuslan Bukin 			fcr = 0ull;
54774fe6c29SRuslan Bukin 		else
54874fe6c29SRuslan Bukin 			return errcode;
54974fe6c29SRuslan Bukin 	}
55074fe6c29SRuslan Bukin 
55174fe6c29SRuslan Bukin 	/* We ignore configuration errors.  They will result in imprecise
55274fe6c29SRuslan Bukin 	 * timing and are tracked as packet losses in struct pt_time.
55374fe6c29SRuslan Bukin 	 */
55474fe6c29SRuslan Bukin 	errcode = pt_time_update_cyc(time, packet, config, fcr);
55574fe6c29SRuslan Bukin 	if (errcode < 0 && (errcode != -pte_bad_config))
55674fe6c29SRuslan Bukin 		return errcode;
55774fe6c29SRuslan Bukin 
55874fe6c29SRuslan Bukin 	return 0;
55974fe6c29SRuslan Bukin }
56074fe6c29SRuslan Bukin 
pt_qry_sync_forward(struct pt_query_decoder * decoder,uint64_t * ip)56174fe6c29SRuslan Bukin int pt_qry_sync_forward(struct pt_query_decoder *decoder, uint64_t *ip)
56274fe6c29SRuslan Bukin {
563*85f87cf4SRuslan Bukin 	const uint8_t *pos, *sync, *begin;
564*85f87cf4SRuslan Bukin 	ptrdiff_t space;
56574fe6c29SRuslan Bukin 	int errcode;
56674fe6c29SRuslan Bukin 
56774fe6c29SRuslan Bukin 	if (!decoder)
56874fe6c29SRuslan Bukin 		return -pte_invalid;
56974fe6c29SRuslan Bukin 
570*85f87cf4SRuslan Bukin 	begin = decoder->config.begin;
57174fe6c29SRuslan Bukin 	sync = decoder->sync;
57274fe6c29SRuslan Bukin 	pos = decoder->pos;
57374fe6c29SRuslan Bukin 	if (!pos)
574*85f87cf4SRuslan Bukin 		pos = begin;
57574fe6c29SRuslan Bukin 
57674fe6c29SRuslan Bukin 	if (pos == sync)
57774fe6c29SRuslan Bukin 		pos += ptps_psb;
57874fe6c29SRuslan Bukin 
579*85f87cf4SRuslan Bukin 	if (pos < begin)
580*85f87cf4SRuslan Bukin 		return -pte_internal;
581*85f87cf4SRuslan Bukin 
582*85f87cf4SRuslan Bukin 	/* Start a bit earlier so we find PSB that have been partially consumed
583*85f87cf4SRuslan Bukin 	 * by a preceding packet.
584*85f87cf4SRuslan Bukin 	 */
585*85f87cf4SRuslan Bukin 	space = pos - begin;
586*85f87cf4SRuslan Bukin 	if (ptps_psb <= space)
587*85f87cf4SRuslan Bukin 		space = ptps_psb - 1;
588*85f87cf4SRuslan Bukin 
589*85f87cf4SRuslan Bukin 	pos -= space;
590*85f87cf4SRuslan Bukin 
59174fe6c29SRuslan Bukin 	errcode = pt_sync_forward(&sync, pos, &decoder->config);
59274fe6c29SRuslan Bukin 	if (errcode < 0)
59374fe6c29SRuslan Bukin 		return errcode;
59474fe6c29SRuslan Bukin 
59574fe6c29SRuslan Bukin 	return pt_qry_start(decoder, sync, ip);
59674fe6c29SRuslan Bukin }
59774fe6c29SRuslan Bukin 
pt_qry_sync_backward(struct pt_query_decoder * decoder,uint64_t * ip)59874fe6c29SRuslan Bukin int pt_qry_sync_backward(struct pt_query_decoder *decoder, uint64_t *ip)
59974fe6c29SRuslan Bukin {
60074fe6c29SRuslan Bukin 	const uint8_t *start, *sync;
60174fe6c29SRuslan Bukin 	int errcode;
60274fe6c29SRuslan Bukin 
60374fe6c29SRuslan Bukin 	if (!decoder)
60474fe6c29SRuslan Bukin 		return -pte_invalid;
60574fe6c29SRuslan Bukin 
60674fe6c29SRuslan Bukin 	start = decoder->pos;
60774fe6c29SRuslan Bukin 	if (!start)
60874fe6c29SRuslan Bukin 		start = decoder->config.end;
60974fe6c29SRuslan Bukin 
61074fe6c29SRuslan Bukin 	sync = start;
61174fe6c29SRuslan Bukin 	for (;;) {
61274fe6c29SRuslan Bukin 		errcode = pt_sync_backward(&sync, sync, &decoder->config);
61374fe6c29SRuslan Bukin 		if (errcode < 0)
61474fe6c29SRuslan Bukin 			return errcode;
61574fe6c29SRuslan Bukin 
61674fe6c29SRuslan Bukin 		errcode = pt_qry_start(decoder, sync, ip);
61774fe6c29SRuslan Bukin 		if (errcode < 0) {
61874fe6c29SRuslan Bukin 			/* Ignore incomplete trace segments at the end.  We need
61974fe6c29SRuslan Bukin 			 * a full PSB+ to start decoding.
62074fe6c29SRuslan Bukin 			 */
62174fe6c29SRuslan Bukin 			if (errcode == -pte_eos)
62274fe6c29SRuslan Bukin 				continue;
62374fe6c29SRuslan Bukin 
62474fe6c29SRuslan Bukin 			return errcode;
62574fe6c29SRuslan Bukin 		}
62674fe6c29SRuslan Bukin 
62774fe6c29SRuslan Bukin 		/* An empty trace segment in the middle of the trace might bring
62874fe6c29SRuslan Bukin 		 * us back to where we started.
62974fe6c29SRuslan Bukin 		 *
63074fe6c29SRuslan Bukin 		 * We're done when we reached a new position.
63174fe6c29SRuslan Bukin 		 */
63274fe6c29SRuslan Bukin 		if (decoder->pos != start)
63374fe6c29SRuslan Bukin 			break;
63474fe6c29SRuslan Bukin 	}
63574fe6c29SRuslan Bukin 
63674fe6c29SRuslan Bukin 	return 0;
63774fe6c29SRuslan Bukin }
63874fe6c29SRuslan Bukin 
pt_qry_sync_set(struct pt_query_decoder * decoder,uint64_t * ip,uint64_t offset)63974fe6c29SRuslan Bukin int pt_qry_sync_set(struct pt_query_decoder *decoder, uint64_t *ip,
64074fe6c29SRuslan Bukin 		    uint64_t offset)
64174fe6c29SRuslan Bukin {
64274fe6c29SRuslan Bukin 	const uint8_t *sync, *pos;
64374fe6c29SRuslan Bukin 	int errcode;
64474fe6c29SRuslan Bukin 
64574fe6c29SRuslan Bukin 	if (!decoder)
64674fe6c29SRuslan Bukin 		return -pte_invalid;
64774fe6c29SRuslan Bukin 
64874fe6c29SRuslan Bukin 	pos = decoder->config.begin + offset;
64974fe6c29SRuslan Bukin 
65074fe6c29SRuslan Bukin 	errcode = pt_sync_set(&sync, pos, &decoder->config);
65174fe6c29SRuslan Bukin 	if (errcode < 0)
65274fe6c29SRuslan Bukin 		return errcode;
65374fe6c29SRuslan Bukin 
65474fe6c29SRuslan Bukin 	return pt_qry_start(decoder, sync, ip);
65574fe6c29SRuslan Bukin }
65674fe6c29SRuslan Bukin 
pt_qry_get_offset(const struct pt_query_decoder * decoder,uint64_t * offset)65774fe6c29SRuslan Bukin int pt_qry_get_offset(const struct pt_query_decoder *decoder, uint64_t *offset)
65874fe6c29SRuslan Bukin {
65974fe6c29SRuslan Bukin 	const uint8_t *begin, *pos;
66074fe6c29SRuslan Bukin 
66174fe6c29SRuslan Bukin 	if (!decoder || !offset)
66274fe6c29SRuslan Bukin 		return -pte_invalid;
66374fe6c29SRuslan Bukin 
66474fe6c29SRuslan Bukin 	begin = decoder->config.begin;
66574fe6c29SRuslan Bukin 	pos = decoder->pos;
66674fe6c29SRuslan Bukin 
66774fe6c29SRuslan Bukin 	if (!pos)
66874fe6c29SRuslan Bukin 		return -pte_nosync;
66974fe6c29SRuslan Bukin 
670*85f87cf4SRuslan Bukin 	*offset = (uint64_t) (int64_t) (pos - begin);
67174fe6c29SRuslan Bukin 	return 0;
67274fe6c29SRuslan Bukin }
67374fe6c29SRuslan Bukin 
pt_qry_get_sync_offset(const struct pt_query_decoder * decoder,uint64_t * offset)67474fe6c29SRuslan Bukin int pt_qry_get_sync_offset(const struct pt_query_decoder *decoder,
67574fe6c29SRuslan Bukin 			   uint64_t *offset)
67674fe6c29SRuslan Bukin {
67774fe6c29SRuslan Bukin 	const uint8_t *begin, *sync;
67874fe6c29SRuslan Bukin 
67974fe6c29SRuslan Bukin 	if (!decoder || !offset)
68074fe6c29SRuslan Bukin 		return -pte_invalid;
68174fe6c29SRuslan Bukin 
68274fe6c29SRuslan Bukin 	begin = decoder->config.begin;
68374fe6c29SRuslan Bukin 	sync = decoder->sync;
68474fe6c29SRuslan Bukin 
68574fe6c29SRuslan Bukin 	if (!sync)
68674fe6c29SRuslan Bukin 		return -pte_nosync;
68774fe6c29SRuslan Bukin 
688*85f87cf4SRuslan Bukin 	*offset = (uint64_t) (int64_t) (sync - begin);
68974fe6c29SRuslan Bukin 	return 0;
69074fe6c29SRuslan Bukin }
69174fe6c29SRuslan Bukin 
69274fe6c29SRuslan Bukin const struct pt_config *
pt_qry_get_config(const struct pt_query_decoder * decoder)69374fe6c29SRuslan Bukin pt_qry_get_config(const struct pt_query_decoder *decoder)
69474fe6c29SRuslan Bukin {
69574fe6c29SRuslan Bukin 	if (!decoder)
69674fe6c29SRuslan Bukin 		return NULL;
69774fe6c29SRuslan Bukin 
69874fe6c29SRuslan Bukin 	return &decoder->config;
69974fe6c29SRuslan Bukin }
70074fe6c29SRuslan Bukin 
pt_qry_cache_tnt(struct pt_query_decoder * decoder)70174fe6c29SRuslan Bukin static int pt_qry_cache_tnt(struct pt_query_decoder *decoder)
70274fe6c29SRuslan Bukin {
70374fe6c29SRuslan Bukin 	int errcode;
70474fe6c29SRuslan Bukin 
70574fe6c29SRuslan Bukin 	if (!decoder)
70674fe6c29SRuslan Bukin 		return -pte_internal;
70774fe6c29SRuslan Bukin 
70874fe6c29SRuslan Bukin 	for (;;) {
70974fe6c29SRuslan Bukin 		const struct pt_decoder_function *dfun;
71074fe6c29SRuslan Bukin 
71174fe6c29SRuslan Bukin 		dfun = decoder->next;
71274fe6c29SRuslan Bukin 		if (!dfun)
71374fe6c29SRuslan Bukin 			return pt_qry_provoke_fetch_error(decoder);
71474fe6c29SRuslan Bukin 
71574fe6c29SRuslan Bukin 		if (!dfun->decode)
71674fe6c29SRuslan Bukin 			return -pte_internal;
71774fe6c29SRuslan Bukin 
71874fe6c29SRuslan Bukin 		/* There's an event ahead of us. */
71974fe6c29SRuslan Bukin 		if (pt_qry_will_event(decoder))
72074fe6c29SRuslan Bukin 			return -pte_bad_query;
72174fe6c29SRuslan Bukin 
72274fe6c29SRuslan Bukin 		/* Diagnose a TIP that has not been part of an event. */
72374fe6c29SRuslan Bukin 		if (dfun->flags & pdff_tip)
72474fe6c29SRuslan Bukin 			return -pte_bad_query;
72574fe6c29SRuslan Bukin 
72674fe6c29SRuslan Bukin 		/* Clear the decoder's current event so we know when we
72774fe6c29SRuslan Bukin 		 * accidentally skipped an event.
72874fe6c29SRuslan Bukin 		 */
72974fe6c29SRuslan Bukin 		decoder->event = NULL;
73074fe6c29SRuslan Bukin 
73174fe6c29SRuslan Bukin 		/* Apply the decoder function. */
73274fe6c29SRuslan Bukin 		errcode = dfun->decode(decoder);
73374fe6c29SRuslan Bukin 		if (errcode)
73474fe6c29SRuslan Bukin 			return errcode;
73574fe6c29SRuslan Bukin 
73674fe6c29SRuslan Bukin 		/* If we skipped an event, we're in trouble. */
73774fe6c29SRuslan Bukin 		if (decoder->event)
73874fe6c29SRuslan Bukin 			return -pte_event_ignored;
73974fe6c29SRuslan Bukin 
74074fe6c29SRuslan Bukin 		/* We're done when we decoded a TNT packet. */
74174fe6c29SRuslan Bukin 		if (dfun->flags & pdff_tnt)
74274fe6c29SRuslan Bukin 			break;
74374fe6c29SRuslan Bukin 
74474fe6c29SRuslan Bukin 		/* Read ahead until the next query-relevant packet. */
74574fe6c29SRuslan Bukin 		errcode = pt_qry_read_ahead(decoder);
74674fe6c29SRuslan Bukin 		if (errcode)
74774fe6c29SRuslan Bukin 			return errcode;
74874fe6c29SRuslan Bukin 	}
74974fe6c29SRuslan Bukin 
75074fe6c29SRuslan Bukin 	/* Preserve the time at the TNT packet. */
75174fe6c29SRuslan Bukin 	decoder->last_time = decoder->time;
75274fe6c29SRuslan Bukin 
75374fe6c29SRuslan Bukin 	/* Read ahead until the next query-relevant packet. */
75474fe6c29SRuslan Bukin 	errcode = pt_qry_read_ahead(decoder);
75574fe6c29SRuslan Bukin 	if ((errcode < 0) && (errcode != -pte_eos))
75674fe6c29SRuslan Bukin 		return errcode;
75774fe6c29SRuslan Bukin 
75874fe6c29SRuslan Bukin 	return 0;
75974fe6c29SRuslan Bukin }
76074fe6c29SRuslan Bukin 
pt_qry_cond_branch(struct pt_query_decoder * decoder,int * taken)76174fe6c29SRuslan Bukin int pt_qry_cond_branch(struct pt_query_decoder *decoder, int *taken)
76274fe6c29SRuslan Bukin {
76374fe6c29SRuslan Bukin 	int errcode, query;
76474fe6c29SRuslan Bukin 
76574fe6c29SRuslan Bukin 	if (!decoder || !taken)
76674fe6c29SRuslan Bukin 		return -pte_invalid;
76774fe6c29SRuslan Bukin 
76874fe6c29SRuslan Bukin 	/* We cache the latest tnt packet in the decoder. Let's re-fill the
76974fe6c29SRuslan Bukin 	 * cache in case it is empty.
77074fe6c29SRuslan Bukin 	 */
77174fe6c29SRuslan Bukin 	if (pt_tnt_cache_is_empty(&decoder->tnt)) {
77274fe6c29SRuslan Bukin 		errcode = pt_qry_cache_tnt(decoder);
77374fe6c29SRuslan Bukin 		if (errcode < 0)
77474fe6c29SRuslan Bukin 			return errcode;
77574fe6c29SRuslan Bukin 	}
77674fe6c29SRuslan Bukin 
77774fe6c29SRuslan Bukin 	query = pt_tnt_cache_query(&decoder->tnt);
77874fe6c29SRuslan Bukin 	if (query < 0)
77974fe6c29SRuslan Bukin 		return query;
78074fe6c29SRuslan Bukin 
78174fe6c29SRuslan Bukin 	*taken = query;
78274fe6c29SRuslan Bukin 
78374fe6c29SRuslan Bukin 	return pt_qry_status_flags(decoder);
78474fe6c29SRuslan Bukin }
78574fe6c29SRuslan Bukin 
pt_qry_indirect_branch(struct pt_query_decoder * decoder,uint64_t * addr)78674fe6c29SRuslan Bukin int pt_qry_indirect_branch(struct pt_query_decoder *decoder, uint64_t *addr)
78774fe6c29SRuslan Bukin {
78874fe6c29SRuslan Bukin 	int errcode, flags;
78974fe6c29SRuslan Bukin 
79074fe6c29SRuslan Bukin 	if (!decoder || !addr)
79174fe6c29SRuslan Bukin 		return -pte_invalid;
79274fe6c29SRuslan Bukin 
79374fe6c29SRuslan Bukin 	flags = 0;
79474fe6c29SRuslan Bukin 	for (;;) {
79574fe6c29SRuslan Bukin 		const struct pt_decoder_function *dfun;
79674fe6c29SRuslan Bukin 
79774fe6c29SRuslan Bukin 		dfun = decoder->next;
79874fe6c29SRuslan Bukin 		if (!dfun)
79974fe6c29SRuslan Bukin 			return pt_qry_provoke_fetch_error(decoder);
80074fe6c29SRuslan Bukin 
80174fe6c29SRuslan Bukin 		if (!dfun->decode)
80274fe6c29SRuslan Bukin 			return -pte_internal;
80374fe6c29SRuslan Bukin 
80474fe6c29SRuslan Bukin 		/* There's an event ahead of us. */
80574fe6c29SRuslan Bukin 		if (pt_qry_will_event(decoder))
80674fe6c29SRuslan Bukin 			return -pte_bad_query;
80774fe6c29SRuslan Bukin 
80874fe6c29SRuslan Bukin 		/* Clear the decoder's current event so we know when we
80974fe6c29SRuslan Bukin 		 * accidentally skipped an event.
81074fe6c29SRuslan Bukin 		 */
81174fe6c29SRuslan Bukin 		decoder->event = NULL;
81274fe6c29SRuslan Bukin 
81374fe6c29SRuslan Bukin 		/* We may see a single TNT packet if the current tnt is empty.
81474fe6c29SRuslan Bukin 		 *
81574fe6c29SRuslan Bukin 		 * If we see a TNT while the current tnt is not empty, it means
81674fe6c29SRuslan Bukin 		 * that our user got out of sync. Let's report no data and hope
81774fe6c29SRuslan Bukin 		 * that our user is able to re-sync.
81874fe6c29SRuslan Bukin 		 */
81974fe6c29SRuslan Bukin 		if ((dfun->flags & pdff_tnt) &&
82074fe6c29SRuslan Bukin 		    !pt_tnt_cache_is_empty(&decoder->tnt))
82174fe6c29SRuslan Bukin 			return -pte_bad_query;
82274fe6c29SRuslan Bukin 
82374fe6c29SRuslan Bukin 		/* Apply the decoder function. */
82474fe6c29SRuslan Bukin 		errcode = dfun->decode(decoder);
82574fe6c29SRuslan Bukin 		if (errcode)
82674fe6c29SRuslan Bukin 			return errcode;
82774fe6c29SRuslan Bukin 
82874fe6c29SRuslan Bukin 		/* If we skipped an event, we're in trouble. */
82974fe6c29SRuslan Bukin 		if (decoder->event)
83074fe6c29SRuslan Bukin 			return -pte_event_ignored;
83174fe6c29SRuslan Bukin 
83274fe6c29SRuslan Bukin 		/* We're done when we found a TIP packet that isn't part of an
83374fe6c29SRuslan Bukin 		 * event.
83474fe6c29SRuslan Bukin 		 */
83574fe6c29SRuslan Bukin 		if (dfun->flags & pdff_tip) {
83674fe6c29SRuslan Bukin 			uint64_t ip;
83774fe6c29SRuslan Bukin 
83874fe6c29SRuslan Bukin 			/* We already decoded it, so the branch destination
83974fe6c29SRuslan Bukin 			 * is stored in the decoder's last ip.
84074fe6c29SRuslan Bukin 			 */
84174fe6c29SRuslan Bukin 			errcode = pt_last_ip_query(&ip, &decoder->ip);
84274fe6c29SRuslan Bukin 			if (errcode < 0)
84374fe6c29SRuslan Bukin 				flags |= pts_ip_suppressed;
84474fe6c29SRuslan Bukin 			else
84574fe6c29SRuslan Bukin 				*addr = ip;
84674fe6c29SRuslan Bukin 
84774fe6c29SRuslan Bukin 			break;
84874fe6c29SRuslan Bukin 		}
84974fe6c29SRuslan Bukin 
85074fe6c29SRuslan Bukin 		/* Read ahead until the next query-relevant packet. */
85174fe6c29SRuslan Bukin 		errcode = pt_qry_read_ahead(decoder);
85274fe6c29SRuslan Bukin 		if (errcode)
85374fe6c29SRuslan Bukin 			return errcode;
85474fe6c29SRuslan Bukin 	}
85574fe6c29SRuslan Bukin 
85674fe6c29SRuslan Bukin 	/* Preserve the time at the TIP packet. */
85774fe6c29SRuslan Bukin 	decoder->last_time = decoder->time;
85874fe6c29SRuslan Bukin 
85974fe6c29SRuslan Bukin 	/* Read ahead until the next query-relevant packet. */
86074fe6c29SRuslan Bukin 	errcode = pt_qry_read_ahead(decoder);
86174fe6c29SRuslan Bukin 	if ((errcode < 0) && (errcode != -pte_eos))
86274fe6c29SRuslan Bukin 		return errcode;
86374fe6c29SRuslan Bukin 
86474fe6c29SRuslan Bukin 	flags |= pt_qry_status_flags(decoder);
86574fe6c29SRuslan Bukin 
86674fe6c29SRuslan Bukin 	return flags;
86774fe6c29SRuslan Bukin }
86874fe6c29SRuslan Bukin 
pt_qry_event(struct pt_query_decoder * decoder,struct pt_event * event,size_t size)86974fe6c29SRuslan Bukin int pt_qry_event(struct pt_query_decoder *decoder, struct pt_event *event,
87074fe6c29SRuslan Bukin 		 size_t size)
87174fe6c29SRuslan Bukin {
87274fe6c29SRuslan Bukin 	int errcode, flags;
87374fe6c29SRuslan Bukin 
87474fe6c29SRuslan Bukin 	if (!decoder || !event)
87574fe6c29SRuslan Bukin 		return -pte_invalid;
87674fe6c29SRuslan Bukin 
87774fe6c29SRuslan Bukin 	if (size < offsetof(struct pt_event, variant))
87874fe6c29SRuslan Bukin 		return -pte_invalid;
87974fe6c29SRuslan Bukin 
88074fe6c29SRuslan Bukin 	/* We do not allow querying for events while there are still TNT
88174fe6c29SRuslan Bukin 	 * bits to consume.
88274fe6c29SRuslan Bukin 	 */
88374fe6c29SRuslan Bukin 	if (!pt_tnt_cache_is_empty(&decoder->tnt))
88474fe6c29SRuslan Bukin 		return -pte_bad_query;
88574fe6c29SRuslan Bukin 
88674fe6c29SRuslan Bukin 	/* Do not provide more than we actually have. */
88774fe6c29SRuslan Bukin 	if (sizeof(*event) < size)
88874fe6c29SRuslan Bukin 		size = sizeof(*event);
88974fe6c29SRuslan Bukin 
89074fe6c29SRuslan Bukin 	flags = 0;
89174fe6c29SRuslan Bukin 	for (;;) {
89274fe6c29SRuslan Bukin 		const struct pt_decoder_function *dfun;
89374fe6c29SRuslan Bukin 
89474fe6c29SRuslan Bukin 		dfun = decoder->next;
89574fe6c29SRuslan Bukin 		if (!dfun)
89674fe6c29SRuslan Bukin 			return pt_qry_provoke_fetch_error(decoder);
89774fe6c29SRuslan Bukin 
89874fe6c29SRuslan Bukin 		if (!dfun->decode)
89974fe6c29SRuslan Bukin 			return -pte_internal;
90074fe6c29SRuslan Bukin 
90174fe6c29SRuslan Bukin 		/* We must not see a TIP or TNT packet unless it belongs
90274fe6c29SRuslan Bukin 		 * to an event.
90374fe6c29SRuslan Bukin 		 *
90474fe6c29SRuslan Bukin 		 * If we see one, it means that our user got out of sync.
90574fe6c29SRuslan Bukin 		 * Let's report no data and hope that our user is able
90674fe6c29SRuslan Bukin 		 * to re-sync.
90774fe6c29SRuslan Bukin 		 */
90874fe6c29SRuslan Bukin 		if ((dfun->flags & (pdff_tip | pdff_tnt)) &&
90974fe6c29SRuslan Bukin 		    !pt_qry_will_event(decoder))
91074fe6c29SRuslan Bukin 			return -pte_bad_query;
91174fe6c29SRuslan Bukin 
91274fe6c29SRuslan Bukin 		/* Clear the decoder's current event so we know when decoding
91374fe6c29SRuslan Bukin 		 * produces a new event.
91474fe6c29SRuslan Bukin 		 */
91574fe6c29SRuslan Bukin 		decoder->event = NULL;
91674fe6c29SRuslan Bukin 
91774fe6c29SRuslan Bukin 		/* Apply any other decoder function. */
91874fe6c29SRuslan Bukin 		errcode = dfun->decode(decoder);
91974fe6c29SRuslan Bukin 		if (errcode)
92074fe6c29SRuslan Bukin 			return errcode;
92174fe6c29SRuslan Bukin 
92274fe6c29SRuslan Bukin 		/* Check if there has been an event.
92374fe6c29SRuslan Bukin 		 *
92474fe6c29SRuslan Bukin 		 * Some packets may result in events in some but not in all
92574fe6c29SRuslan Bukin 		 * configurations.
92674fe6c29SRuslan Bukin 		 */
92774fe6c29SRuslan Bukin 		if (decoder->event) {
92874fe6c29SRuslan Bukin 			(void) memcpy(event, decoder->event, size);
92974fe6c29SRuslan Bukin 			break;
93074fe6c29SRuslan Bukin 		}
93174fe6c29SRuslan Bukin 
93274fe6c29SRuslan Bukin 		/* Read ahead until the next query-relevant packet. */
93374fe6c29SRuslan Bukin 		errcode = pt_qry_read_ahead(decoder);
93474fe6c29SRuslan Bukin 		if (errcode)
93574fe6c29SRuslan Bukin 			return errcode;
93674fe6c29SRuslan Bukin 	}
93774fe6c29SRuslan Bukin 
93874fe6c29SRuslan Bukin 	/* Preserve the time at the event. */
93974fe6c29SRuslan Bukin 	decoder->last_time = decoder->time;
94074fe6c29SRuslan Bukin 
94174fe6c29SRuslan Bukin 	/* Read ahead until the next query-relevant packet. */
94274fe6c29SRuslan Bukin 	errcode = pt_qry_read_ahead(decoder);
94374fe6c29SRuslan Bukin 	if ((errcode < 0) && (errcode != -pte_eos))
94474fe6c29SRuslan Bukin 		return errcode;
94574fe6c29SRuslan Bukin 
94674fe6c29SRuslan Bukin 	flags |= pt_qry_status_flags(decoder);
94774fe6c29SRuslan Bukin 
94874fe6c29SRuslan Bukin 	return flags;
94974fe6c29SRuslan Bukin }
95074fe6c29SRuslan Bukin 
pt_qry_time(struct pt_query_decoder * decoder,uint64_t * time,uint32_t * lost_mtc,uint32_t * lost_cyc)95174fe6c29SRuslan Bukin int pt_qry_time(struct pt_query_decoder *decoder, uint64_t *time,
95274fe6c29SRuslan Bukin 		uint32_t *lost_mtc, uint32_t *lost_cyc)
95374fe6c29SRuslan Bukin {
95474fe6c29SRuslan Bukin 	if (!decoder || !time)
95574fe6c29SRuslan Bukin 		return -pte_invalid;
95674fe6c29SRuslan Bukin 
95774fe6c29SRuslan Bukin 	return pt_time_query_tsc(time, lost_mtc, lost_cyc, &decoder->last_time);
95874fe6c29SRuslan Bukin }
95974fe6c29SRuslan Bukin 
pt_qry_core_bus_ratio(struct pt_query_decoder * decoder,uint32_t * cbr)96074fe6c29SRuslan Bukin int pt_qry_core_bus_ratio(struct pt_query_decoder *decoder, uint32_t *cbr)
96174fe6c29SRuslan Bukin {
96274fe6c29SRuslan Bukin 	if (!decoder || !cbr)
96374fe6c29SRuslan Bukin 		return -pte_invalid;
96474fe6c29SRuslan Bukin 
96574fe6c29SRuslan Bukin 	return pt_time_query_cbr(cbr, &decoder->last_time);
96674fe6c29SRuslan Bukin }
96774fe6c29SRuslan Bukin 
pt_qry_event_time(struct pt_event * event,const struct pt_query_decoder * decoder)96874fe6c29SRuslan Bukin static int pt_qry_event_time(struct pt_event *event,
96974fe6c29SRuslan Bukin 			     const struct pt_query_decoder *decoder)
97074fe6c29SRuslan Bukin {
97174fe6c29SRuslan Bukin 	int errcode;
97274fe6c29SRuslan Bukin 
97374fe6c29SRuslan Bukin 	if (!event || !decoder)
97474fe6c29SRuslan Bukin 		return -pte_internal;
97574fe6c29SRuslan Bukin 
97674fe6c29SRuslan Bukin 	errcode = pt_time_query_tsc(&event->tsc, &event->lost_mtc,
97774fe6c29SRuslan Bukin 				    &event->lost_cyc, &decoder->time);
97874fe6c29SRuslan Bukin 	if (errcode < 0) {
97974fe6c29SRuslan Bukin 		if (errcode != -pte_no_time)
98074fe6c29SRuslan Bukin 			return errcode;
98174fe6c29SRuslan Bukin 	} else
98274fe6c29SRuslan Bukin 		event->has_tsc = 1;
98374fe6c29SRuslan Bukin 
98474fe6c29SRuslan Bukin 	return 0;
98574fe6c29SRuslan Bukin }
98674fe6c29SRuslan Bukin 
pt_qry_decode_unknown(struct pt_query_decoder * decoder)98774fe6c29SRuslan Bukin int pt_qry_decode_unknown(struct pt_query_decoder *decoder)
98874fe6c29SRuslan Bukin {
98974fe6c29SRuslan Bukin 	struct pt_packet packet;
99074fe6c29SRuslan Bukin 	int size;
99174fe6c29SRuslan Bukin 
99274fe6c29SRuslan Bukin 	if (!decoder)
99374fe6c29SRuslan Bukin 		return -pte_internal;
99474fe6c29SRuslan Bukin 
99574fe6c29SRuslan Bukin 	size = pt_pkt_read_unknown(&packet, decoder->pos, &decoder->config);
99674fe6c29SRuslan Bukin 	if (size < 0)
99774fe6c29SRuslan Bukin 		return size;
99874fe6c29SRuslan Bukin 
99974fe6c29SRuslan Bukin 	decoder->pos += size;
100074fe6c29SRuslan Bukin 	return 0;
100174fe6c29SRuslan Bukin }
100274fe6c29SRuslan Bukin 
pt_qry_decode_pad(struct pt_query_decoder * decoder)100374fe6c29SRuslan Bukin int pt_qry_decode_pad(struct pt_query_decoder *decoder)
100474fe6c29SRuslan Bukin {
100574fe6c29SRuslan Bukin 	if (!decoder)
100674fe6c29SRuslan Bukin 		return -pte_internal;
100774fe6c29SRuslan Bukin 
100874fe6c29SRuslan Bukin 	decoder->pos += ptps_pad;
100974fe6c29SRuslan Bukin 
101074fe6c29SRuslan Bukin 	return 0;
101174fe6c29SRuslan Bukin }
101274fe6c29SRuslan Bukin 
pt_qry_read_psb_header(struct pt_query_decoder * decoder)101374fe6c29SRuslan Bukin static int pt_qry_read_psb_header(struct pt_query_decoder *decoder)
101474fe6c29SRuslan Bukin {
101574fe6c29SRuslan Bukin 	if (!decoder)
101674fe6c29SRuslan Bukin 		return -pte_internal;
101774fe6c29SRuslan Bukin 
101874fe6c29SRuslan Bukin 	pt_last_ip_init(&decoder->ip);
101974fe6c29SRuslan Bukin 
102074fe6c29SRuslan Bukin 	for (;;) {
102174fe6c29SRuslan Bukin 		const struct pt_decoder_function *dfun;
102274fe6c29SRuslan Bukin 		int errcode;
102374fe6c29SRuslan Bukin 
102474fe6c29SRuslan Bukin 		errcode = pt_df_fetch(&decoder->next, decoder->pos,
102574fe6c29SRuslan Bukin 				      &decoder->config);
102674fe6c29SRuslan Bukin 		if (errcode)
102774fe6c29SRuslan Bukin 			return errcode;
102874fe6c29SRuslan Bukin 
102974fe6c29SRuslan Bukin 		dfun = decoder->next;
103074fe6c29SRuslan Bukin 		if (!dfun)
103174fe6c29SRuslan Bukin 			return -pte_internal;
103274fe6c29SRuslan Bukin 
103374fe6c29SRuslan Bukin 		/* We're done once we reach an psbend packet. */
103474fe6c29SRuslan Bukin 		if (dfun->flags & pdff_psbend)
103574fe6c29SRuslan Bukin 			return 0;
103674fe6c29SRuslan Bukin 
103774fe6c29SRuslan Bukin 		if (!dfun->header)
103874fe6c29SRuslan Bukin 			return -pte_bad_context;
103974fe6c29SRuslan Bukin 
104074fe6c29SRuslan Bukin 		errcode = dfun->header(decoder);
104174fe6c29SRuslan Bukin 		if (errcode)
104274fe6c29SRuslan Bukin 			return errcode;
104374fe6c29SRuslan Bukin 	}
104474fe6c29SRuslan Bukin }
104574fe6c29SRuslan Bukin 
pt_qry_decode_psb(struct pt_query_decoder * decoder)104674fe6c29SRuslan Bukin int pt_qry_decode_psb(struct pt_query_decoder *decoder)
104774fe6c29SRuslan Bukin {
104874fe6c29SRuslan Bukin 	const uint8_t *pos;
104974fe6c29SRuslan Bukin 	int size, errcode;
105074fe6c29SRuslan Bukin 
105174fe6c29SRuslan Bukin 	if (!decoder)
105274fe6c29SRuslan Bukin 		return -pte_internal;
105374fe6c29SRuslan Bukin 
105474fe6c29SRuslan Bukin 	pos = decoder->pos;
105574fe6c29SRuslan Bukin 
105674fe6c29SRuslan Bukin 	size = pt_pkt_read_psb(pos, &decoder->config);
105774fe6c29SRuslan Bukin 	if (size < 0)
105874fe6c29SRuslan Bukin 		return size;
105974fe6c29SRuslan Bukin 
1060*85f87cf4SRuslan Bukin 	errcode = pt_tcal_update_psb(&decoder->tcal, &decoder->config);
1061*85f87cf4SRuslan Bukin 	if (errcode < 0)
1062*85f87cf4SRuslan Bukin 		return errcode;
1063*85f87cf4SRuslan Bukin 
106474fe6c29SRuslan Bukin 	decoder->pos += size;
106574fe6c29SRuslan Bukin 
106674fe6c29SRuslan Bukin 	errcode = pt_qry_read_psb_header(decoder);
106774fe6c29SRuslan Bukin 	if (errcode < 0) {
106874fe6c29SRuslan Bukin 		/* Move back to the PSB so we have a chance to recover and
106974fe6c29SRuslan Bukin 		 * continue decoding.
107074fe6c29SRuslan Bukin 		 */
107174fe6c29SRuslan Bukin 		decoder->pos = pos;
107274fe6c29SRuslan Bukin 
107374fe6c29SRuslan Bukin 		/* Clear any PSB+ events that have already been queued. */
107474fe6c29SRuslan Bukin 		(void) pt_evq_clear(&decoder->evq, evb_psbend);
107574fe6c29SRuslan Bukin 
107674fe6c29SRuslan Bukin 		/* Reset the decoder's decode function. */
107774fe6c29SRuslan Bukin 		decoder->next = &pt_decode_psb;
107874fe6c29SRuslan Bukin 
107974fe6c29SRuslan Bukin 		return errcode;
108074fe6c29SRuslan Bukin 	}
108174fe6c29SRuslan Bukin 
108274fe6c29SRuslan Bukin 	/* The next packet following the PSB header will be of type PSBEND.
108374fe6c29SRuslan Bukin 	 *
108474fe6c29SRuslan Bukin 	 * Decoding this packet will publish the PSB events what have been
108574fe6c29SRuslan Bukin 	 * accumulated while reading the PSB header.
108674fe6c29SRuslan Bukin 	 */
108774fe6c29SRuslan Bukin 	return 0;
108874fe6c29SRuslan Bukin }
108974fe6c29SRuslan Bukin 
pt_qry_event_ip(uint64_t * ip,struct pt_event * event,const struct pt_query_decoder * decoder)109074fe6c29SRuslan Bukin static int pt_qry_event_ip(uint64_t *ip, struct pt_event *event,
109174fe6c29SRuslan Bukin 			   const struct pt_query_decoder *decoder)
109274fe6c29SRuslan Bukin {
109374fe6c29SRuslan Bukin 	int errcode;
109474fe6c29SRuslan Bukin 
109574fe6c29SRuslan Bukin 	if (!decoder)
109674fe6c29SRuslan Bukin 		return -pte_internal;
109774fe6c29SRuslan Bukin 
109874fe6c29SRuslan Bukin 	errcode = pt_last_ip_query(ip, &decoder->ip);
109974fe6c29SRuslan Bukin 	if (errcode < 0) {
110074fe6c29SRuslan Bukin 		switch (pt_errcode(errcode)) {
110174fe6c29SRuslan Bukin 		case pte_noip:
110274fe6c29SRuslan Bukin 		case pte_ip_suppressed:
110374fe6c29SRuslan Bukin 			event->ip_suppressed = 1;
110474fe6c29SRuslan Bukin 			break;
110574fe6c29SRuslan Bukin 
110674fe6c29SRuslan Bukin 		default:
110774fe6c29SRuslan Bukin 			return errcode;
110874fe6c29SRuslan Bukin 		}
110974fe6c29SRuslan Bukin 	}
111074fe6c29SRuslan Bukin 
111174fe6c29SRuslan Bukin 	return 0;
111274fe6c29SRuslan Bukin }
111374fe6c29SRuslan Bukin 
111474fe6c29SRuslan Bukin /* Decode a generic IP packet.
111574fe6c29SRuslan Bukin  *
111674fe6c29SRuslan Bukin  * Returns the number of bytes read, on success.
111774fe6c29SRuslan Bukin  * Returns -pte_eos if the ip does not fit into the buffer.
111874fe6c29SRuslan Bukin  * Returns -pte_bad_packet if the ip compression is not known.
111974fe6c29SRuslan Bukin  */
pt_qry_decode_ip(struct pt_query_decoder * decoder)112074fe6c29SRuslan Bukin static int pt_qry_decode_ip(struct pt_query_decoder *decoder)
112174fe6c29SRuslan Bukin {
112274fe6c29SRuslan Bukin 	struct pt_packet_ip packet;
112374fe6c29SRuslan Bukin 	int errcode, size;
112474fe6c29SRuslan Bukin 
112574fe6c29SRuslan Bukin 	if (!decoder)
112674fe6c29SRuslan Bukin 		return -pte_internal;
112774fe6c29SRuslan Bukin 
112874fe6c29SRuslan Bukin 	size = pt_pkt_read_ip(&packet, decoder->pos, &decoder->config);
112974fe6c29SRuslan Bukin 	if (size < 0)
113074fe6c29SRuslan Bukin 		return size;
113174fe6c29SRuslan Bukin 
113274fe6c29SRuslan Bukin 	errcode = pt_last_ip_update_ip(&decoder->ip, &packet, &decoder->config);
113374fe6c29SRuslan Bukin 	if (errcode < 0)
113474fe6c29SRuslan Bukin 		return errcode;
113574fe6c29SRuslan Bukin 
113674fe6c29SRuslan Bukin 	/* We do not update the decoder's position, yet. */
113774fe6c29SRuslan Bukin 
113874fe6c29SRuslan Bukin 	return size;
113974fe6c29SRuslan Bukin }
114074fe6c29SRuslan Bukin 
pt_qry_consume_tip(struct pt_query_decoder * decoder,int size)114174fe6c29SRuslan Bukin static int pt_qry_consume_tip(struct pt_query_decoder *decoder, int size)
114274fe6c29SRuslan Bukin {
114374fe6c29SRuslan Bukin 	if (!decoder)
114474fe6c29SRuslan Bukin 		return -pte_internal;
114574fe6c29SRuslan Bukin 
114674fe6c29SRuslan Bukin 	decoder->pos += size;
114774fe6c29SRuslan Bukin 	return 0;
114874fe6c29SRuslan Bukin }
114974fe6c29SRuslan Bukin 
pt_qry_event_tip(struct pt_event * ev,struct pt_query_decoder * decoder)115074fe6c29SRuslan Bukin static int pt_qry_event_tip(struct pt_event *ev,
115174fe6c29SRuslan Bukin 			    struct pt_query_decoder *decoder)
115274fe6c29SRuslan Bukin {
115374fe6c29SRuslan Bukin 	if (!ev || !decoder)
115474fe6c29SRuslan Bukin 		return -pte_internal;
115574fe6c29SRuslan Bukin 
115674fe6c29SRuslan Bukin 	switch (ev->type) {
115774fe6c29SRuslan Bukin 	case ptev_async_branch:
115874fe6c29SRuslan Bukin 		decoder->consume_packet = 1;
115974fe6c29SRuslan Bukin 
116074fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.async_branch.to, ev,
116174fe6c29SRuslan Bukin 				       decoder);
116274fe6c29SRuslan Bukin 
116374fe6c29SRuslan Bukin 	case ptev_async_paging:
116474fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.async_paging.ip, ev,
116574fe6c29SRuslan Bukin 				       decoder);
116674fe6c29SRuslan Bukin 
116774fe6c29SRuslan Bukin 	case ptev_async_vmcs:
116874fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.async_vmcs.ip, ev,
116974fe6c29SRuslan Bukin 				       decoder);
117074fe6c29SRuslan Bukin 
117174fe6c29SRuslan Bukin 	case ptev_exec_mode:
117274fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.exec_mode.ip, ev,
117374fe6c29SRuslan Bukin 				       decoder);
117474fe6c29SRuslan Bukin 
117574fe6c29SRuslan Bukin 	default:
117674fe6c29SRuslan Bukin 		break;
117774fe6c29SRuslan Bukin 	}
117874fe6c29SRuslan Bukin 
117974fe6c29SRuslan Bukin 	return -pte_bad_context;
118074fe6c29SRuslan Bukin }
118174fe6c29SRuslan Bukin 
pt_qry_decode_tip(struct pt_query_decoder * decoder)118274fe6c29SRuslan Bukin int pt_qry_decode_tip(struct pt_query_decoder *decoder)
118374fe6c29SRuslan Bukin {
118474fe6c29SRuslan Bukin 	struct pt_event *ev;
118574fe6c29SRuslan Bukin 	int size, errcode;
118674fe6c29SRuslan Bukin 
118774fe6c29SRuslan Bukin 	if (!decoder)
118874fe6c29SRuslan Bukin 		return -pte_internal;
118974fe6c29SRuslan Bukin 
119074fe6c29SRuslan Bukin 	size = pt_qry_decode_ip(decoder);
119174fe6c29SRuslan Bukin 	if (size < 0)
119274fe6c29SRuslan Bukin 		return size;
119374fe6c29SRuslan Bukin 
119474fe6c29SRuslan Bukin 	/* Process any pending events binding to TIP. */
119574fe6c29SRuslan Bukin 	ev = pt_evq_dequeue(&decoder->evq, evb_tip);
119674fe6c29SRuslan Bukin 	if (ev) {
119774fe6c29SRuslan Bukin 		errcode = pt_qry_event_tip(ev, decoder);
119874fe6c29SRuslan Bukin 		if (errcode < 0)
119974fe6c29SRuslan Bukin 			return errcode;
120074fe6c29SRuslan Bukin 
120174fe6c29SRuslan Bukin 		/* Publish the event. */
120274fe6c29SRuslan Bukin 		decoder->event = ev;
120374fe6c29SRuslan Bukin 
120474fe6c29SRuslan Bukin 		/* Process further pending events. */
120574fe6c29SRuslan Bukin 		if (pt_evq_pending(&decoder->evq, evb_tip))
120674fe6c29SRuslan Bukin 			return 0;
120774fe6c29SRuslan Bukin 
120874fe6c29SRuslan Bukin 		/* No further events.
120974fe6c29SRuslan Bukin 		 *
121074fe6c29SRuslan Bukin 		 * If none of the events consumed the packet, we're done.
121174fe6c29SRuslan Bukin 		 */
121274fe6c29SRuslan Bukin 		if (!decoder->consume_packet)
121374fe6c29SRuslan Bukin 			return 0;
121474fe6c29SRuslan Bukin 
121574fe6c29SRuslan Bukin 		/* We're done with this packet. Clear the flag we set previously
121674fe6c29SRuslan Bukin 		 * and consume it.
121774fe6c29SRuslan Bukin 		 */
121874fe6c29SRuslan Bukin 		decoder->consume_packet = 0;
121974fe6c29SRuslan Bukin 	}
122074fe6c29SRuslan Bukin 
122174fe6c29SRuslan Bukin 	return pt_qry_consume_tip(decoder, size);
122274fe6c29SRuslan Bukin }
122374fe6c29SRuslan Bukin 
pt_qry_decode_tnt_8(struct pt_query_decoder * decoder)122474fe6c29SRuslan Bukin int pt_qry_decode_tnt_8(struct pt_query_decoder *decoder)
122574fe6c29SRuslan Bukin {
122674fe6c29SRuslan Bukin 	struct pt_packet_tnt packet;
122774fe6c29SRuslan Bukin 	int size, errcode;
122874fe6c29SRuslan Bukin 
122974fe6c29SRuslan Bukin 	if (!decoder)
123074fe6c29SRuslan Bukin 		return -pte_internal;
123174fe6c29SRuslan Bukin 
123274fe6c29SRuslan Bukin 	size = pt_pkt_read_tnt_8(&packet, decoder->pos, &decoder->config);
123374fe6c29SRuslan Bukin 	if (size < 0)
123474fe6c29SRuslan Bukin 		return size;
123574fe6c29SRuslan Bukin 
123674fe6c29SRuslan Bukin 	errcode = pt_tnt_cache_update_tnt(&decoder->tnt, &packet,
123774fe6c29SRuslan Bukin 					  &decoder->config);
123874fe6c29SRuslan Bukin 	if (errcode < 0)
123974fe6c29SRuslan Bukin 		return errcode;
124074fe6c29SRuslan Bukin 
124174fe6c29SRuslan Bukin 	decoder->pos += size;
124274fe6c29SRuslan Bukin 	return 0;
124374fe6c29SRuslan Bukin }
124474fe6c29SRuslan Bukin 
pt_qry_decode_tnt_64(struct pt_query_decoder * decoder)124574fe6c29SRuslan Bukin int pt_qry_decode_tnt_64(struct pt_query_decoder *decoder)
124674fe6c29SRuslan Bukin {
124774fe6c29SRuslan Bukin 	struct pt_packet_tnt packet;
124874fe6c29SRuslan Bukin 	int size, errcode;
124974fe6c29SRuslan Bukin 
125074fe6c29SRuslan Bukin 	if (!decoder)
125174fe6c29SRuslan Bukin 		return -pte_internal;
125274fe6c29SRuslan Bukin 
125374fe6c29SRuslan Bukin 	size = pt_pkt_read_tnt_64(&packet, decoder->pos, &decoder->config);
125474fe6c29SRuslan Bukin 	if (size < 0)
125574fe6c29SRuslan Bukin 		return size;
125674fe6c29SRuslan Bukin 
125774fe6c29SRuslan Bukin 	errcode = pt_tnt_cache_update_tnt(&decoder->tnt, &packet,
125874fe6c29SRuslan Bukin 					  &decoder->config);
125974fe6c29SRuslan Bukin 	if (errcode < 0)
126074fe6c29SRuslan Bukin 		return errcode;
126174fe6c29SRuslan Bukin 
126274fe6c29SRuslan Bukin 	decoder->pos += size;
126374fe6c29SRuslan Bukin 	return 0;
126474fe6c29SRuslan Bukin }
126574fe6c29SRuslan Bukin 
pt_qry_consume_tip_pge(struct pt_query_decoder * decoder,int size)126674fe6c29SRuslan Bukin static int pt_qry_consume_tip_pge(struct pt_query_decoder *decoder, int size)
126774fe6c29SRuslan Bukin {
126874fe6c29SRuslan Bukin 	if (!decoder)
126974fe6c29SRuslan Bukin 		return -pte_internal;
127074fe6c29SRuslan Bukin 
127174fe6c29SRuslan Bukin 	decoder->pos += size;
127274fe6c29SRuslan Bukin 	return 0;
127374fe6c29SRuslan Bukin }
127474fe6c29SRuslan Bukin 
pt_qry_event_tip_pge(struct pt_event * ev,const struct pt_query_decoder * decoder)127574fe6c29SRuslan Bukin static int pt_qry_event_tip_pge(struct pt_event *ev,
127674fe6c29SRuslan Bukin 				const struct pt_query_decoder *decoder)
127774fe6c29SRuslan Bukin {
127874fe6c29SRuslan Bukin 	if (!ev)
127974fe6c29SRuslan Bukin 		return -pte_internal;
128074fe6c29SRuslan Bukin 
128174fe6c29SRuslan Bukin 	switch (ev->type) {
128274fe6c29SRuslan Bukin 	case ptev_exec_mode:
128374fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.exec_mode.ip, ev, decoder);
128474fe6c29SRuslan Bukin 
128574fe6c29SRuslan Bukin 	default:
128674fe6c29SRuslan Bukin 		break;
128774fe6c29SRuslan Bukin 	}
128874fe6c29SRuslan Bukin 
128974fe6c29SRuslan Bukin 	return -pte_bad_context;
129074fe6c29SRuslan Bukin }
129174fe6c29SRuslan Bukin 
pt_qry_decode_tip_pge(struct pt_query_decoder * decoder)129274fe6c29SRuslan Bukin int pt_qry_decode_tip_pge(struct pt_query_decoder *decoder)
129374fe6c29SRuslan Bukin {
129474fe6c29SRuslan Bukin 	struct pt_event *ev;
129574fe6c29SRuslan Bukin 	int size, errcode;
129674fe6c29SRuslan Bukin 
129774fe6c29SRuslan Bukin 	if (!decoder)
129874fe6c29SRuslan Bukin 		return -pte_internal;
129974fe6c29SRuslan Bukin 
130074fe6c29SRuslan Bukin 	size = pt_qry_decode_ip(decoder);
130174fe6c29SRuslan Bukin 	if (size < 0)
130274fe6c29SRuslan Bukin 		return size;
130374fe6c29SRuslan Bukin 
130474fe6c29SRuslan Bukin 	/* We send the enable event first. This is more convenient for our users
130574fe6c29SRuslan Bukin 	 * and does not require them to either store or blindly apply other
130674fe6c29SRuslan Bukin 	 * events that might be pending.
130774fe6c29SRuslan Bukin 	 *
130874fe6c29SRuslan Bukin 	 * We use the consume packet decoder flag to indicate this.
130974fe6c29SRuslan Bukin 	 */
131074fe6c29SRuslan Bukin 	if (!decoder->consume_packet) {
131174fe6c29SRuslan Bukin 		/* This packet signals a standalone enabled event. */
131274fe6c29SRuslan Bukin 		ev = pt_evq_standalone(&decoder->evq);
131374fe6c29SRuslan Bukin 		if (!ev)
131474fe6c29SRuslan Bukin 			return -pte_internal;
131574fe6c29SRuslan Bukin 
131674fe6c29SRuslan Bukin 		ev->type = ptev_enabled;
131774fe6c29SRuslan Bukin 
131874fe6c29SRuslan Bukin 		/* We can't afford having a suppressed IP here. */
131974fe6c29SRuslan Bukin 		errcode = pt_last_ip_query(&ev->variant.enabled.ip,
132074fe6c29SRuslan Bukin 					   &decoder->ip);
132174fe6c29SRuslan Bukin 		if (errcode < 0)
132274fe6c29SRuslan Bukin 			return -pte_bad_packet;
132374fe6c29SRuslan Bukin 
132474fe6c29SRuslan Bukin 		errcode = pt_qry_event_time(ev, decoder);
132574fe6c29SRuslan Bukin 		if (errcode < 0)
132674fe6c29SRuslan Bukin 			return errcode;
132774fe6c29SRuslan Bukin 
132874fe6c29SRuslan Bukin 		/* Discard any cached TNT bits.
132974fe6c29SRuslan Bukin 		 *
133074fe6c29SRuslan Bukin 		 * They should have been consumed at the corresponding disable
133174fe6c29SRuslan Bukin 		 * event. If they have not, for whatever reason, discard them
133274fe6c29SRuslan Bukin 		 * now so our user does not get out of sync.
133374fe6c29SRuslan Bukin 		 */
133474fe6c29SRuslan Bukin 		pt_tnt_cache_init(&decoder->tnt);
133574fe6c29SRuslan Bukin 
133674fe6c29SRuslan Bukin 		/* Process pending events next. */
133774fe6c29SRuslan Bukin 		decoder->consume_packet = 1;
133874fe6c29SRuslan Bukin 		decoder->enabled = 1;
133974fe6c29SRuslan Bukin 	} else {
134074fe6c29SRuslan Bukin 		/* Process any pending events binding to TIP. */
134174fe6c29SRuslan Bukin 		ev = pt_evq_dequeue(&decoder->evq, evb_tip);
134274fe6c29SRuslan Bukin 		if (ev) {
134374fe6c29SRuslan Bukin 			errcode = pt_qry_event_tip_pge(ev, decoder);
134474fe6c29SRuslan Bukin 			if (errcode < 0)
134574fe6c29SRuslan Bukin 				return errcode;
134674fe6c29SRuslan Bukin 		}
134774fe6c29SRuslan Bukin 	}
134874fe6c29SRuslan Bukin 
134974fe6c29SRuslan Bukin 	/* We must have an event. Either the initial enable event or one of the
135074fe6c29SRuslan Bukin 	 * queued events.
135174fe6c29SRuslan Bukin 	 */
135274fe6c29SRuslan Bukin 	if (!ev)
135374fe6c29SRuslan Bukin 		return -pte_internal;
135474fe6c29SRuslan Bukin 
135574fe6c29SRuslan Bukin 	/* Publish the event. */
135674fe6c29SRuslan Bukin 	decoder->event = ev;
135774fe6c29SRuslan Bukin 
135874fe6c29SRuslan Bukin 	/* Process further pending events. */
135974fe6c29SRuslan Bukin 	if (pt_evq_pending(&decoder->evq, evb_tip))
136074fe6c29SRuslan Bukin 		return 0;
136174fe6c29SRuslan Bukin 
136274fe6c29SRuslan Bukin 	/* We must consume the packet. */
136374fe6c29SRuslan Bukin 	if (!decoder->consume_packet)
136474fe6c29SRuslan Bukin 		return -pte_internal;
136574fe6c29SRuslan Bukin 
136674fe6c29SRuslan Bukin 	decoder->consume_packet = 0;
136774fe6c29SRuslan Bukin 
136874fe6c29SRuslan Bukin 	return pt_qry_consume_tip_pge(decoder, size);
136974fe6c29SRuslan Bukin }
137074fe6c29SRuslan Bukin 
pt_qry_consume_tip_pgd(struct pt_query_decoder * decoder,int size)137174fe6c29SRuslan Bukin static int pt_qry_consume_tip_pgd(struct pt_query_decoder *decoder, int size)
137274fe6c29SRuslan Bukin {
137374fe6c29SRuslan Bukin 	if (!decoder)
137474fe6c29SRuslan Bukin 		return -pte_internal;
137574fe6c29SRuslan Bukin 
137674fe6c29SRuslan Bukin 	decoder->enabled = 0;
137774fe6c29SRuslan Bukin 	decoder->pos += size;
137874fe6c29SRuslan Bukin 	return 0;
137974fe6c29SRuslan Bukin }
138074fe6c29SRuslan Bukin 
pt_qry_event_tip_pgd(struct pt_event * ev,const struct pt_query_decoder * decoder)138174fe6c29SRuslan Bukin static int pt_qry_event_tip_pgd(struct pt_event *ev,
138274fe6c29SRuslan Bukin 				const struct pt_query_decoder *decoder)
138374fe6c29SRuslan Bukin {
138474fe6c29SRuslan Bukin 	if (!ev)
138574fe6c29SRuslan Bukin 		return -pte_internal;
138674fe6c29SRuslan Bukin 
138774fe6c29SRuslan Bukin 	switch (ev->type) {
138874fe6c29SRuslan Bukin 	case ptev_async_branch: {
138974fe6c29SRuslan Bukin 		uint64_t at;
139074fe6c29SRuslan Bukin 
139174fe6c29SRuslan Bukin 		/* Turn the async branch into an async disable. */
139274fe6c29SRuslan Bukin 		at = ev->variant.async_branch.from;
139374fe6c29SRuslan Bukin 
139474fe6c29SRuslan Bukin 		ev->type = ptev_async_disabled;
139574fe6c29SRuslan Bukin 		ev->variant.async_disabled.at = at;
139674fe6c29SRuslan Bukin 
139774fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.async_disabled.ip, ev,
139874fe6c29SRuslan Bukin 				       decoder);
139974fe6c29SRuslan Bukin 	}
140074fe6c29SRuslan Bukin 
140174fe6c29SRuslan Bukin 	case ptev_async_paging:
140274fe6c29SRuslan Bukin 	case ptev_async_vmcs:
140374fe6c29SRuslan Bukin 	case ptev_exec_mode:
140474fe6c29SRuslan Bukin 		/* These events are ordered after the async disable event.  It
140574fe6c29SRuslan Bukin 		 * is not quite clear what IP to give them.
140674fe6c29SRuslan Bukin 		 *
140774fe6c29SRuslan Bukin 		 * If we give them the async disable's source IP, we'd make an
140874fe6c29SRuslan Bukin 		 * error if the IP is updated when applying the async disable
140974fe6c29SRuslan Bukin 		 * event.
141074fe6c29SRuslan Bukin 		 *
141174fe6c29SRuslan Bukin 		 * If we give them the async disable's destination IP, we'd make
141274fe6c29SRuslan Bukin 		 * an error if the IP is not updated when applying the async
141374fe6c29SRuslan Bukin 		 * disable event.  That's what our decoders do since tracing is
141474fe6c29SRuslan Bukin 		 * likely to resume from there.
141574fe6c29SRuslan Bukin 		 *
141674fe6c29SRuslan Bukin 		 * In all cases, tracing will be disabled when those events are
141774fe6c29SRuslan Bukin 		 * applied, so we may as well suppress the IP.
141874fe6c29SRuslan Bukin 		 */
141974fe6c29SRuslan Bukin 		ev->ip_suppressed = 1;
142074fe6c29SRuslan Bukin 
142174fe6c29SRuslan Bukin 		return 0;
142274fe6c29SRuslan Bukin 
142374fe6c29SRuslan Bukin 	default:
142474fe6c29SRuslan Bukin 		break;
142574fe6c29SRuslan Bukin 	}
142674fe6c29SRuslan Bukin 
142774fe6c29SRuslan Bukin 	return -pte_bad_context;
142874fe6c29SRuslan Bukin }
142974fe6c29SRuslan Bukin 
pt_qry_decode_tip_pgd(struct pt_query_decoder * decoder)143074fe6c29SRuslan Bukin int pt_qry_decode_tip_pgd(struct pt_query_decoder *decoder)
143174fe6c29SRuslan Bukin {
143274fe6c29SRuslan Bukin 	struct pt_event *ev;
143374fe6c29SRuslan Bukin 	int size, errcode;
143474fe6c29SRuslan Bukin 
143574fe6c29SRuslan Bukin 	if (!decoder)
143674fe6c29SRuslan Bukin 		return -pte_internal;
143774fe6c29SRuslan Bukin 
143874fe6c29SRuslan Bukin 	size = pt_qry_decode_ip(decoder);
143974fe6c29SRuslan Bukin 	if (size < 0)
144074fe6c29SRuslan Bukin 		return size;
144174fe6c29SRuslan Bukin 
144274fe6c29SRuslan Bukin 	/* Process any pending events binding to TIP. */
144374fe6c29SRuslan Bukin 	ev = pt_evq_dequeue(&decoder->evq, evb_tip);
144474fe6c29SRuslan Bukin 	if (ev) {
144574fe6c29SRuslan Bukin 		errcode = pt_qry_event_tip_pgd(ev, decoder);
144674fe6c29SRuslan Bukin 		if (errcode < 0)
144774fe6c29SRuslan Bukin 			return errcode;
144874fe6c29SRuslan Bukin 	} else {
144974fe6c29SRuslan Bukin 		/* This packet signals a standalone disabled event. */
145074fe6c29SRuslan Bukin 		ev = pt_evq_standalone(&decoder->evq);
145174fe6c29SRuslan Bukin 		if (!ev)
145274fe6c29SRuslan Bukin 			return -pte_internal;
145374fe6c29SRuslan Bukin 		ev->type = ptev_disabled;
145474fe6c29SRuslan Bukin 
145574fe6c29SRuslan Bukin 		errcode = pt_qry_event_ip(&ev->variant.disabled.ip, ev,
145674fe6c29SRuslan Bukin 					  decoder);
145774fe6c29SRuslan Bukin 		if (errcode < 0)
145874fe6c29SRuslan Bukin 			return errcode;
145974fe6c29SRuslan Bukin 
146074fe6c29SRuslan Bukin 		errcode = pt_qry_event_time(ev, decoder);
146174fe6c29SRuslan Bukin 		if (errcode < 0)
146274fe6c29SRuslan Bukin 			return errcode;
146374fe6c29SRuslan Bukin 	}
146474fe6c29SRuslan Bukin 
146574fe6c29SRuslan Bukin 	/* We must have an event. Either the initial enable event or one of the
146674fe6c29SRuslan Bukin 	 * queued events.
146774fe6c29SRuslan Bukin 	 */
146874fe6c29SRuslan Bukin 	if (!ev)
146974fe6c29SRuslan Bukin 		return -pte_internal;
147074fe6c29SRuslan Bukin 
147174fe6c29SRuslan Bukin 	/* Publish the event. */
147274fe6c29SRuslan Bukin 	decoder->event = ev;
147374fe6c29SRuslan Bukin 
147474fe6c29SRuslan Bukin 	/* Process further pending events. */
147574fe6c29SRuslan Bukin 	if (pt_evq_pending(&decoder->evq, evb_tip))
147674fe6c29SRuslan Bukin 		return 0;
147774fe6c29SRuslan Bukin 
147874fe6c29SRuslan Bukin 	return pt_qry_consume_tip_pgd(decoder, size);
147974fe6c29SRuslan Bukin }
148074fe6c29SRuslan Bukin 
pt_qry_consume_fup(struct pt_query_decoder * decoder,int size)148174fe6c29SRuslan Bukin static int pt_qry_consume_fup(struct pt_query_decoder *decoder, int size)
148274fe6c29SRuslan Bukin {
148374fe6c29SRuslan Bukin 	if (!decoder)
148474fe6c29SRuslan Bukin 		return -pte_internal;
148574fe6c29SRuslan Bukin 
148674fe6c29SRuslan Bukin 	decoder->pos += size;
148774fe6c29SRuslan Bukin 	return 0;
148874fe6c29SRuslan Bukin }
148974fe6c29SRuslan Bukin 
scan_for_erratum_bdm70(struct pt_packet_decoder * decoder)149074fe6c29SRuslan Bukin static int scan_for_erratum_bdm70(struct pt_packet_decoder *decoder)
149174fe6c29SRuslan Bukin {
149274fe6c29SRuslan Bukin 	for (;;) {
149374fe6c29SRuslan Bukin 		struct pt_packet packet;
149474fe6c29SRuslan Bukin 		int errcode;
149574fe6c29SRuslan Bukin 
149674fe6c29SRuslan Bukin 		errcode = pt_pkt_next(decoder, &packet, sizeof(packet));
149774fe6c29SRuslan Bukin 		if (errcode < 0) {
149874fe6c29SRuslan Bukin 			/* Running out of packets is not an error. */
149974fe6c29SRuslan Bukin 			if (errcode == -pte_eos)
150074fe6c29SRuslan Bukin 				errcode = 0;
150174fe6c29SRuslan Bukin 
150274fe6c29SRuslan Bukin 			return errcode;
150374fe6c29SRuslan Bukin 		}
150474fe6c29SRuslan Bukin 
150574fe6c29SRuslan Bukin 		switch (packet.type) {
150674fe6c29SRuslan Bukin 		default:
150774fe6c29SRuslan Bukin 			/* All other packets cancel our search.
150874fe6c29SRuslan Bukin 			 *
150974fe6c29SRuslan Bukin 			 * We do not enumerate those packets since we also
151074fe6c29SRuslan Bukin 			 * want to include new packets.
151174fe6c29SRuslan Bukin 			 */
151274fe6c29SRuslan Bukin 			return 0;
151374fe6c29SRuslan Bukin 
151474fe6c29SRuslan Bukin 		case ppt_tip_pge:
151574fe6c29SRuslan Bukin 			/* We found it - the erratum applies. */
151674fe6c29SRuslan Bukin 			return 1;
151774fe6c29SRuslan Bukin 
151874fe6c29SRuslan Bukin 		case ppt_pad:
151974fe6c29SRuslan Bukin 		case ppt_tsc:
152074fe6c29SRuslan Bukin 		case ppt_cbr:
152174fe6c29SRuslan Bukin 		case ppt_psbend:
152274fe6c29SRuslan Bukin 		case ppt_pip:
152374fe6c29SRuslan Bukin 		case ppt_mode:
152474fe6c29SRuslan Bukin 		case ppt_vmcs:
152574fe6c29SRuslan Bukin 		case ppt_tma:
152674fe6c29SRuslan Bukin 		case ppt_mtc:
152774fe6c29SRuslan Bukin 		case ppt_cyc:
152874fe6c29SRuslan Bukin 		case ppt_mnt:
152974fe6c29SRuslan Bukin 			/* Intentionally skip a few packets. */
153074fe6c29SRuslan Bukin 			continue;
153174fe6c29SRuslan Bukin 		}
153274fe6c29SRuslan Bukin 	}
153374fe6c29SRuslan Bukin }
153474fe6c29SRuslan Bukin 
check_erratum_bdm70(const uint8_t * pos,const struct pt_config * config)153574fe6c29SRuslan Bukin static int check_erratum_bdm70(const uint8_t *pos,
153674fe6c29SRuslan Bukin 			       const struct pt_config *config)
153774fe6c29SRuslan Bukin {
153874fe6c29SRuslan Bukin 	struct pt_packet_decoder decoder;
153974fe6c29SRuslan Bukin 	int errcode;
154074fe6c29SRuslan Bukin 
154174fe6c29SRuslan Bukin 	if (!pos || !config)
154274fe6c29SRuslan Bukin 		return -pte_internal;
154374fe6c29SRuslan Bukin 
154474fe6c29SRuslan Bukin 	errcode = pt_pkt_decoder_init(&decoder, config);
154574fe6c29SRuslan Bukin 	if (errcode < 0)
154674fe6c29SRuslan Bukin 		return errcode;
154774fe6c29SRuslan Bukin 
154874fe6c29SRuslan Bukin 	errcode = pt_pkt_sync_set(&decoder, (uint64_t) (pos - config->begin));
154974fe6c29SRuslan Bukin 	if (errcode >= 0)
155074fe6c29SRuslan Bukin 		errcode = scan_for_erratum_bdm70(&decoder);
155174fe6c29SRuslan Bukin 
155274fe6c29SRuslan Bukin 	pt_pkt_decoder_fini(&decoder);
155374fe6c29SRuslan Bukin 	return errcode;
155474fe6c29SRuslan Bukin }
155574fe6c29SRuslan Bukin 
pt_qry_header_fup(struct pt_query_decoder * decoder)155674fe6c29SRuslan Bukin int pt_qry_header_fup(struct pt_query_decoder *decoder)
155774fe6c29SRuslan Bukin {
155874fe6c29SRuslan Bukin 	struct pt_packet_ip packet;
155974fe6c29SRuslan Bukin 	int errcode, size;
156074fe6c29SRuslan Bukin 
156174fe6c29SRuslan Bukin 	if (!decoder)
156274fe6c29SRuslan Bukin 		return -pte_internal;
156374fe6c29SRuslan Bukin 
156474fe6c29SRuslan Bukin 	size = pt_pkt_read_ip(&packet, decoder->pos, &decoder->config);
156574fe6c29SRuslan Bukin 	if (size < 0)
156674fe6c29SRuslan Bukin 		return size;
156774fe6c29SRuslan Bukin 
156874fe6c29SRuslan Bukin 	if (decoder->config.errata.bdm70 && !decoder->enabled) {
156974fe6c29SRuslan Bukin 		errcode = check_erratum_bdm70(decoder->pos + size,
157074fe6c29SRuslan Bukin 					      &decoder->config);
157174fe6c29SRuslan Bukin 		if (errcode < 0)
157274fe6c29SRuslan Bukin 			return errcode;
157374fe6c29SRuslan Bukin 
157474fe6c29SRuslan Bukin 		if (errcode)
157574fe6c29SRuslan Bukin 			return pt_qry_consume_fup(decoder, size);
157674fe6c29SRuslan Bukin 	}
157774fe6c29SRuslan Bukin 
157874fe6c29SRuslan Bukin 	errcode = pt_last_ip_update_ip(&decoder->ip, &packet, &decoder->config);
157974fe6c29SRuslan Bukin 	if (errcode < 0)
158074fe6c29SRuslan Bukin 		return errcode;
158174fe6c29SRuslan Bukin 
158274fe6c29SRuslan Bukin 	/* Tracing is enabled if we have an IP in the header. */
158374fe6c29SRuslan Bukin 	if (packet.ipc != pt_ipc_suppressed)
158474fe6c29SRuslan Bukin 		decoder->enabled = 1;
158574fe6c29SRuslan Bukin 
158674fe6c29SRuslan Bukin 	return pt_qry_consume_fup(decoder, size);
158774fe6c29SRuslan Bukin }
158874fe6c29SRuslan Bukin 
pt_qry_event_fup(struct pt_event * ev,struct pt_query_decoder * decoder)158974fe6c29SRuslan Bukin static int pt_qry_event_fup(struct pt_event *ev,
159074fe6c29SRuslan Bukin 			    struct pt_query_decoder *decoder)
159174fe6c29SRuslan Bukin {
159274fe6c29SRuslan Bukin 	if (!ev || !decoder)
159374fe6c29SRuslan Bukin 		return -pte_internal;
159474fe6c29SRuslan Bukin 
159574fe6c29SRuslan Bukin 	switch (ev->type) {
159674fe6c29SRuslan Bukin 	case ptev_overflow:
159774fe6c29SRuslan Bukin 		decoder->consume_packet = 1;
159874fe6c29SRuslan Bukin 
159974fe6c29SRuslan Bukin 		/* We can't afford having a suppressed IP here. */
160074fe6c29SRuslan Bukin 		return pt_last_ip_query(&ev->variant.overflow.ip,
160174fe6c29SRuslan Bukin 					&decoder->ip);
160274fe6c29SRuslan Bukin 
160374fe6c29SRuslan Bukin 	case ptev_tsx:
160474fe6c29SRuslan Bukin 		if (!(ev->variant.tsx.aborted))
160574fe6c29SRuslan Bukin 			decoder->consume_packet = 1;
160674fe6c29SRuslan Bukin 
160774fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.tsx.ip, ev, decoder);
160874fe6c29SRuslan Bukin 
160974fe6c29SRuslan Bukin 	case ptev_exstop:
161074fe6c29SRuslan Bukin 		decoder->consume_packet = 1;
161174fe6c29SRuslan Bukin 
161274fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.exstop.ip, ev, decoder);
161374fe6c29SRuslan Bukin 
161474fe6c29SRuslan Bukin 	case ptev_mwait:
161574fe6c29SRuslan Bukin 		decoder->consume_packet = 1;
161674fe6c29SRuslan Bukin 
161774fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.mwait.ip, ev, decoder);
161874fe6c29SRuslan Bukin 
161974fe6c29SRuslan Bukin 	case ptev_ptwrite:
162074fe6c29SRuslan Bukin 		decoder->consume_packet = 1;
162174fe6c29SRuslan Bukin 
162274fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.ptwrite.ip, ev, decoder);
162374fe6c29SRuslan Bukin 
162474fe6c29SRuslan Bukin 	default:
162574fe6c29SRuslan Bukin 		break;
162674fe6c29SRuslan Bukin 	}
162774fe6c29SRuslan Bukin 
162874fe6c29SRuslan Bukin 	return -pte_internal;
162974fe6c29SRuslan Bukin }
163074fe6c29SRuslan Bukin 
pt_qry_decode_fup(struct pt_query_decoder * decoder)163174fe6c29SRuslan Bukin int pt_qry_decode_fup(struct pt_query_decoder *decoder)
163274fe6c29SRuslan Bukin {
163374fe6c29SRuslan Bukin 	struct pt_event *ev;
163474fe6c29SRuslan Bukin 	int size, errcode;
163574fe6c29SRuslan Bukin 
163674fe6c29SRuslan Bukin 	if (!decoder)
163774fe6c29SRuslan Bukin 		return -pte_internal;
163874fe6c29SRuslan Bukin 
163974fe6c29SRuslan Bukin 	size = pt_qry_decode_ip(decoder);
164074fe6c29SRuslan Bukin 	if (size < 0)
164174fe6c29SRuslan Bukin 		return size;
164274fe6c29SRuslan Bukin 
164374fe6c29SRuslan Bukin 	/* Process any pending events binding to FUP. */
164474fe6c29SRuslan Bukin 	ev = pt_evq_dequeue(&decoder->evq, evb_fup);
164574fe6c29SRuslan Bukin 	if (ev) {
164674fe6c29SRuslan Bukin 		errcode = pt_qry_event_fup(ev, decoder);
164774fe6c29SRuslan Bukin 		if (errcode < 0)
164874fe6c29SRuslan Bukin 			return errcode;
164974fe6c29SRuslan Bukin 
165074fe6c29SRuslan Bukin 		/* Publish the event. */
165174fe6c29SRuslan Bukin 		decoder->event = ev;
165274fe6c29SRuslan Bukin 
165374fe6c29SRuslan Bukin 		/* Process further pending events. */
165474fe6c29SRuslan Bukin 		if (pt_evq_pending(&decoder->evq, evb_fup))
165574fe6c29SRuslan Bukin 			return 0;
165674fe6c29SRuslan Bukin 
165774fe6c29SRuslan Bukin 		/* No further events.
165874fe6c29SRuslan Bukin 		 *
165974fe6c29SRuslan Bukin 		 * If none of the events consumed the packet, we're done.
166074fe6c29SRuslan Bukin 		 */
166174fe6c29SRuslan Bukin 		if (!decoder->consume_packet)
166274fe6c29SRuslan Bukin 			return 0;
166374fe6c29SRuslan Bukin 
166474fe6c29SRuslan Bukin 		/* We're done with this packet. Clear the flag we set previously
166574fe6c29SRuslan Bukin 		 * and consume it.
166674fe6c29SRuslan Bukin 		 */
166774fe6c29SRuslan Bukin 		decoder->consume_packet = 0;
166874fe6c29SRuslan Bukin 	} else {
166974fe6c29SRuslan Bukin 		/* FUP indicates an async branch event; it binds to TIP.
167074fe6c29SRuslan Bukin 		 *
167174fe6c29SRuslan Bukin 		 * We do need an IP in this case.
167274fe6c29SRuslan Bukin 		 */
167374fe6c29SRuslan Bukin 		uint64_t ip;
167474fe6c29SRuslan Bukin 
167574fe6c29SRuslan Bukin 		errcode = pt_last_ip_query(&ip, &decoder->ip);
167674fe6c29SRuslan Bukin 		if (errcode < 0)
167774fe6c29SRuslan Bukin 			return errcode;
167874fe6c29SRuslan Bukin 
167974fe6c29SRuslan Bukin 		ev = pt_evq_enqueue(&decoder->evq, evb_tip);
168074fe6c29SRuslan Bukin 		if (!ev)
168174fe6c29SRuslan Bukin 			return -pte_nomem;
168274fe6c29SRuslan Bukin 
168374fe6c29SRuslan Bukin 		ev->type = ptev_async_branch;
168474fe6c29SRuslan Bukin 		ev->variant.async_branch.from = ip;
168574fe6c29SRuslan Bukin 
168674fe6c29SRuslan Bukin 		errcode = pt_qry_event_time(ev, decoder);
168774fe6c29SRuslan Bukin 		if (errcode < 0)
168874fe6c29SRuslan Bukin 			return errcode;
168974fe6c29SRuslan Bukin 	}
169074fe6c29SRuslan Bukin 
169174fe6c29SRuslan Bukin 	return pt_qry_consume_fup(decoder, size);
169274fe6c29SRuslan Bukin }
169374fe6c29SRuslan Bukin 
pt_qry_decode_pip(struct pt_query_decoder * decoder)169474fe6c29SRuslan Bukin int pt_qry_decode_pip(struct pt_query_decoder *decoder)
169574fe6c29SRuslan Bukin {
169674fe6c29SRuslan Bukin 	struct pt_packet_pip packet;
169774fe6c29SRuslan Bukin 	struct pt_event *event;
169874fe6c29SRuslan Bukin 	int size, errcode;
169974fe6c29SRuslan Bukin 
170074fe6c29SRuslan Bukin 	if (!decoder)
170174fe6c29SRuslan Bukin 		return -pte_internal;
170274fe6c29SRuslan Bukin 
170374fe6c29SRuslan Bukin 	size = pt_pkt_read_pip(&packet, decoder->pos, &decoder->config);
170474fe6c29SRuslan Bukin 	if (size < 0)
170574fe6c29SRuslan Bukin 		return size;
170674fe6c29SRuslan Bukin 
170774fe6c29SRuslan Bukin 	/* Paging events are either standalone or bind to the same TIP packet
170874fe6c29SRuslan Bukin 	 * as an in-flight async branch event.
170974fe6c29SRuslan Bukin 	 */
171074fe6c29SRuslan Bukin 	event = pt_evq_find(&decoder->evq, evb_tip, ptev_async_branch);
171174fe6c29SRuslan Bukin 	if (!event) {
171274fe6c29SRuslan Bukin 		event = pt_evq_standalone(&decoder->evq);
171374fe6c29SRuslan Bukin 		if (!event)
171474fe6c29SRuslan Bukin 			return -pte_internal;
171574fe6c29SRuslan Bukin 		event->type = ptev_paging;
171674fe6c29SRuslan Bukin 		event->variant.paging.cr3 = packet.cr3;
171774fe6c29SRuslan Bukin 		event->variant.paging.non_root = packet.nr;
171874fe6c29SRuslan Bukin 
171974fe6c29SRuslan Bukin 		decoder->event = event;
172074fe6c29SRuslan Bukin 	} else {
172174fe6c29SRuslan Bukin 		event = pt_evq_enqueue(&decoder->evq, evb_tip);
172274fe6c29SRuslan Bukin 		if (!event)
172374fe6c29SRuslan Bukin 			return -pte_nomem;
172474fe6c29SRuslan Bukin 
172574fe6c29SRuslan Bukin 		event->type = ptev_async_paging;
172674fe6c29SRuslan Bukin 		event->variant.async_paging.cr3 = packet.cr3;
172774fe6c29SRuslan Bukin 		event->variant.async_paging.non_root = packet.nr;
172874fe6c29SRuslan Bukin 	}
172974fe6c29SRuslan Bukin 
173074fe6c29SRuslan Bukin 	errcode = pt_qry_event_time(event, decoder);
173174fe6c29SRuslan Bukin 	if (errcode < 0)
173274fe6c29SRuslan Bukin 		return errcode;
173374fe6c29SRuslan Bukin 
173474fe6c29SRuslan Bukin 	decoder->pos += size;
173574fe6c29SRuslan Bukin 	return 0;
173674fe6c29SRuslan Bukin }
173774fe6c29SRuslan Bukin 
pt_qry_header_pip(struct pt_query_decoder * decoder)173874fe6c29SRuslan Bukin int pt_qry_header_pip(struct pt_query_decoder *decoder)
173974fe6c29SRuslan Bukin {
174074fe6c29SRuslan Bukin 	struct pt_packet_pip packet;
174174fe6c29SRuslan Bukin 	struct pt_event *event;
174274fe6c29SRuslan Bukin 	int size;
174374fe6c29SRuslan Bukin 
174474fe6c29SRuslan Bukin 	if (!decoder)
174574fe6c29SRuslan Bukin 		return -pte_internal;
174674fe6c29SRuslan Bukin 
174774fe6c29SRuslan Bukin 	size = pt_pkt_read_pip(&packet, decoder->pos, &decoder->config);
174874fe6c29SRuslan Bukin 	if (size < 0)
174974fe6c29SRuslan Bukin 		return size;
175074fe6c29SRuslan Bukin 
175174fe6c29SRuslan Bukin 	/* Paging events are reported at the end of the PSB. */
175274fe6c29SRuslan Bukin 	event = pt_evq_enqueue(&decoder->evq, evb_psbend);
175374fe6c29SRuslan Bukin 	if (!event)
175474fe6c29SRuslan Bukin 		return -pte_nomem;
175574fe6c29SRuslan Bukin 
175674fe6c29SRuslan Bukin 	event->type = ptev_async_paging;
175774fe6c29SRuslan Bukin 	event->variant.async_paging.cr3 = packet.cr3;
175874fe6c29SRuslan Bukin 	event->variant.async_paging.non_root = packet.nr;
175974fe6c29SRuslan Bukin 
176074fe6c29SRuslan Bukin 	decoder->pos += size;
176174fe6c29SRuslan Bukin 	return 0;
176274fe6c29SRuslan Bukin }
176374fe6c29SRuslan Bukin 
pt_qry_event_psbend(struct pt_event * ev,struct pt_query_decoder * decoder)176474fe6c29SRuslan Bukin static int pt_qry_event_psbend(struct pt_event *ev,
176574fe6c29SRuslan Bukin 			       struct pt_query_decoder *decoder)
176674fe6c29SRuslan Bukin {
176774fe6c29SRuslan Bukin 	int errcode;
176874fe6c29SRuslan Bukin 
176974fe6c29SRuslan Bukin 	if (!ev || !decoder)
177074fe6c29SRuslan Bukin 		return -pte_internal;
177174fe6c29SRuslan Bukin 
177274fe6c29SRuslan Bukin 	/* PSB+ events are status updates. */
177374fe6c29SRuslan Bukin 	ev->status_update = 1;
177474fe6c29SRuslan Bukin 
177574fe6c29SRuslan Bukin 	errcode = pt_qry_event_time(ev, decoder);
177674fe6c29SRuslan Bukin 	if (errcode < 0)
177774fe6c29SRuslan Bukin 		return errcode;
177874fe6c29SRuslan Bukin 
177974fe6c29SRuslan Bukin 	switch (ev->type) {
178074fe6c29SRuslan Bukin 	case ptev_async_paging:
178174fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.async_paging.ip, ev,
178274fe6c29SRuslan Bukin 				       decoder);
178374fe6c29SRuslan Bukin 
178474fe6c29SRuslan Bukin 	case ptev_exec_mode:
178574fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.exec_mode.ip, ev, decoder);
178674fe6c29SRuslan Bukin 
178774fe6c29SRuslan Bukin 	case ptev_tsx:
178874fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.tsx.ip, ev, decoder);
178974fe6c29SRuslan Bukin 
179074fe6c29SRuslan Bukin 	case ptev_async_vmcs:
179174fe6c29SRuslan Bukin 		return pt_qry_event_ip(&ev->variant.async_vmcs.ip, ev,
179274fe6c29SRuslan Bukin 				       decoder);
179374fe6c29SRuslan Bukin 
179474fe6c29SRuslan Bukin 	case ptev_cbr:
179574fe6c29SRuslan Bukin 		return 0;
179674fe6c29SRuslan Bukin 
179774fe6c29SRuslan Bukin 	case ptev_mnt:
179874fe6c29SRuslan Bukin 		/* Maintenance packets may appear anywhere.  Do not mark them as
179974fe6c29SRuslan Bukin 		 * status updates even if they appear in PSB+.
180074fe6c29SRuslan Bukin 		 */
180174fe6c29SRuslan Bukin 		ev->status_update = 0;
180274fe6c29SRuslan Bukin 		return 0;
180374fe6c29SRuslan Bukin 
180474fe6c29SRuslan Bukin 	default:
180574fe6c29SRuslan Bukin 		break;
180674fe6c29SRuslan Bukin 	}
180774fe6c29SRuslan Bukin 
180874fe6c29SRuslan Bukin 	return -pte_internal;
180974fe6c29SRuslan Bukin }
181074fe6c29SRuslan Bukin 
pt_qry_process_pending_psb_events(struct pt_query_decoder * decoder)181174fe6c29SRuslan Bukin static int pt_qry_process_pending_psb_events(struct pt_query_decoder *decoder)
181274fe6c29SRuslan Bukin {
181374fe6c29SRuslan Bukin 	struct pt_event *ev;
181474fe6c29SRuslan Bukin 	int errcode;
181574fe6c29SRuslan Bukin 
181674fe6c29SRuslan Bukin 	if (!decoder)
181774fe6c29SRuslan Bukin 		return -pte_internal;
181874fe6c29SRuslan Bukin 
181974fe6c29SRuslan Bukin 	ev = pt_evq_dequeue(&decoder->evq, evb_psbend);
182074fe6c29SRuslan Bukin 	if (!ev)
182174fe6c29SRuslan Bukin 		return 0;
182274fe6c29SRuslan Bukin 
182374fe6c29SRuslan Bukin 	errcode = pt_qry_event_psbend(ev, decoder);
182474fe6c29SRuslan Bukin 	if (errcode < 0)
182574fe6c29SRuslan Bukin 		return errcode;
182674fe6c29SRuslan Bukin 
182774fe6c29SRuslan Bukin 	/* Publish the event. */
182874fe6c29SRuslan Bukin 	decoder->event = ev;
182974fe6c29SRuslan Bukin 
183074fe6c29SRuslan Bukin 	/* Signal a pending event. */
183174fe6c29SRuslan Bukin 	return 1;
183274fe6c29SRuslan Bukin }
183374fe6c29SRuslan Bukin 
183474fe6c29SRuslan Bukin /* Create a standalone overflow event with tracing disabled.
183574fe6c29SRuslan Bukin  *
183674fe6c29SRuslan Bukin  * Creates and published the event and disables tracing in @decoder.
183774fe6c29SRuslan Bukin  *
183874fe6c29SRuslan Bukin  * Returns zero on success, a negative pt_error_code otherwise.
183974fe6c29SRuslan Bukin  */
pt_qry_event_ovf_disabled(struct pt_query_decoder * decoder)184074fe6c29SRuslan Bukin static int pt_qry_event_ovf_disabled(struct pt_query_decoder *decoder)
184174fe6c29SRuslan Bukin {
184274fe6c29SRuslan Bukin 	struct pt_event *ev;
184374fe6c29SRuslan Bukin 
184474fe6c29SRuslan Bukin 	if (!decoder)
184574fe6c29SRuslan Bukin 		return -pte_internal;
184674fe6c29SRuslan Bukin 
184774fe6c29SRuslan Bukin 	ev = pt_evq_standalone(&decoder->evq);
184874fe6c29SRuslan Bukin 	if (!ev)
184974fe6c29SRuslan Bukin 		return -pte_internal;
185074fe6c29SRuslan Bukin 
185174fe6c29SRuslan Bukin 	ev->type = ptev_overflow;
185274fe6c29SRuslan Bukin 
185374fe6c29SRuslan Bukin 	/* We suppress the IP to indicate that tracing has been disabled before
185474fe6c29SRuslan Bukin 	 * the overflow resolved.  There can be several events before tracing is
185574fe6c29SRuslan Bukin 	 * enabled again.
185674fe6c29SRuslan Bukin 	 */
185774fe6c29SRuslan Bukin 	ev->ip_suppressed = 1;
185874fe6c29SRuslan Bukin 
185974fe6c29SRuslan Bukin 	decoder->enabled = 0;
186074fe6c29SRuslan Bukin 	decoder->event = ev;
186174fe6c29SRuslan Bukin 
186274fe6c29SRuslan Bukin 	return pt_qry_event_time(ev, decoder);
186374fe6c29SRuslan Bukin }
186474fe6c29SRuslan Bukin 
186574fe6c29SRuslan Bukin /* Queues an overflow event with tracing enabled.
186674fe6c29SRuslan Bukin  *
186774fe6c29SRuslan Bukin  * Creates and enqueues the event and enables tracing in @decoder.
186874fe6c29SRuslan Bukin  *
186974fe6c29SRuslan Bukin  * Returns zero on success, a negative pt_error_code otherwise.
187074fe6c29SRuslan Bukin  */
pt_qry_event_ovf_enabled(struct pt_query_decoder * decoder)187174fe6c29SRuslan Bukin static int pt_qry_event_ovf_enabled(struct pt_query_decoder *decoder)
187274fe6c29SRuslan Bukin {
187374fe6c29SRuslan Bukin 	struct pt_event *ev;
187474fe6c29SRuslan Bukin 
187574fe6c29SRuslan Bukin 	if (!decoder)
187674fe6c29SRuslan Bukin 		return -pte_internal;
187774fe6c29SRuslan Bukin 
187874fe6c29SRuslan Bukin 	ev = pt_evq_enqueue(&decoder->evq, evb_fup);
187974fe6c29SRuslan Bukin 	if (!ev)
188074fe6c29SRuslan Bukin 		return -pte_internal;
188174fe6c29SRuslan Bukin 
188274fe6c29SRuslan Bukin 	ev->type = ptev_overflow;
188374fe6c29SRuslan Bukin 
188474fe6c29SRuslan Bukin 	decoder->enabled = 1;
188574fe6c29SRuslan Bukin 
188674fe6c29SRuslan Bukin 	return pt_qry_event_time(ev, decoder);
188774fe6c29SRuslan Bukin }
188874fe6c29SRuslan Bukin 
188974fe6c29SRuslan Bukin /* Recover from SKD010.
189074fe6c29SRuslan Bukin  *
189174fe6c29SRuslan Bukin  * Creates and publishes an overflow event at @packet's IP payload.
189274fe6c29SRuslan Bukin  *
189374fe6c29SRuslan Bukin  * Further updates @decoder as follows:
189474fe6c29SRuslan Bukin  *
189574fe6c29SRuslan Bukin  *   - set time tracking to @time and @tcal
189674fe6c29SRuslan Bukin  *   - set the position to @offset
189774fe6c29SRuslan Bukin  *   - set ip to @packet's IP payload
189874fe6c29SRuslan Bukin  *   - set tracing to be enabled
189974fe6c29SRuslan Bukin  *
190074fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
190174fe6c29SRuslan 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)190274fe6c29SRuslan Bukin static int skd010_recover(struct pt_query_decoder *decoder,
190374fe6c29SRuslan Bukin 			  const struct pt_packet_ip *packet,
190474fe6c29SRuslan Bukin 			  const struct pt_time_cal *tcal,
190574fe6c29SRuslan Bukin 			  const struct pt_time *time, uint64_t offset)
190674fe6c29SRuslan Bukin {
190774fe6c29SRuslan Bukin 	struct pt_last_ip ip;
190874fe6c29SRuslan Bukin 	struct pt_event *ev;
190974fe6c29SRuslan Bukin 	int errcode;
191074fe6c29SRuslan Bukin 
191174fe6c29SRuslan Bukin 	if (!decoder || !packet || !tcal || !time)
191274fe6c29SRuslan Bukin 		return -pte_internal;
191374fe6c29SRuslan Bukin 
191474fe6c29SRuslan Bukin 	/* We use the decoder's IP.  It should be newly initialized. */
191574fe6c29SRuslan Bukin 	ip = decoder->ip;
191674fe6c29SRuslan Bukin 
191774fe6c29SRuslan Bukin 	/* Extract the IP payload from the packet. */
191874fe6c29SRuslan Bukin 	errcode = pt_last_ip_update_ip(&ip, packet, &decoder->config);
191974fe6c29SRuslan Bukin 	if (errcode < 0)
192074fe6c29SRuslan Bukin 		return errcode;
192174fe6c29SRuslan Bukin 
192274fe6c29SRuslan Bukin 	/* Synthesize the overflow event. */
192374fe6c29SRuslan Bukin 	ev = pt_evq_standalone(&decoder->evq);
192474fe6c29SRuslan Bukin 	if (!ev)
192574fe6c29SRuslan Bukin 		return -pte_internal;
192674fe6c29SRuslan Bukin 
192774fe6c29SRuslan Bukin 	ev->type = ptev_overflow;
192874fe6c29SRuslan Bukin 
192974fe6c29SRuslan Bukin 	/* We do need a full IP. */
193074fe6c29SRuslan Bukin 	errcode = pt_last_ip_query(&ev->variant.overflow.ip, &ip);
193174fe6c29SRuslan Bukin 	if (errcode < 0)
193274fe6c29SRuslan Bukin 		return -pte_bad_context;
193374fe6c29SRuslan Bukin 
193474fe6c29SRuslan Bukin 	/* We continue decoding at the given offset. */
193574fe6c29SRuslan Bukin 	decoder->pos = decoder->config.begin + offset;
193674fe6c29SRuslan Bukin 
193774fe6c29SRuslan Bukin 	/* Tracing is enabled. */
193874fe6c29SRuslan Bukin 	decoder->enabled = 1;
193974fe6c29SRuslan Bukin 	decoder->ip = ip;
194074fe6c29SRuslan Bukin 
194174fe6c29SRuslan Bukin 	decoder->time = *time;
194274fe6c29SRuslan Bukin 	decoder->tcal = *tcal;
194374fe6c29SRuslan Bukin 
194474fe6c29SRuslan Bukin 	/* Publish the event. */
194574fe6c29SRuslan Bukin 	decoder->event = ev;
194674fe6c29SRuslan Bukin 
194774fe6c29SRuslan Bukin 	return pt_qry_event_time(ev, decoder);
194874fe6c29SRuslan Bukin }
194974fe6c29SRuslan Bukin 
195074fe6c29SRuslan Bukin /* Recover from SKD010 with tracing disabled.
195174fe6c29SRuslan Bukin  *
195274fe6c29SRuslan Bukin  * Creates and publishes a standalone overflow event.
195374fe6c29SRuslan Bukin  *
195474fe6c29SRuslan Bukin  * Further updates @decoder as follows:
195574fe6c29SRuslan Bukin  *
195674fe6c29SRuslan Bukin  *   - set time tracking to @time and @tcal
195774fe6c29SRuslan Bukin  *   - set the position to @offset
195874fe6c29SRuslan Bukin  *   - set tracing to be disabled
195974fe6c29SRuslan Bukin  *
196074fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
196174fe6c29SRuslan Bukin  */
skd010_recover_disabled(struct pt_query_decoder * decoder,const struct pt_time_cal * tcal,const struct pt_time * time,uint64_t offset)196274fe6c29SRuslan Bukin static int skd010_recover_disabled(struct pt_query_decoder *decoder,
196374fe6c29SRuslan Bukin 				   const struct pt_time_cal *tcal,
196474fe6c29SRuslan Bukin 				   const struct pt_time *time, uint64_t offset)
196574fe6c29SRuslan Bukin {
196674fe6c29SRuslan Bukin 	if (!decoder || !tcal || !time)
196774fe6c29SRuslan Bukin 		return -pte_internal;
196874fe6c29SRuslan Bukin 
196974fe6c29SRuslan Bukin 	decoder->time = *time;
197074fe6c29SRuslan Bukin 	decoder->tcal = *tcal;
197174fe6c29SRuslan Bukin 
197274fe6c29SRuslan Bukin 	/* We continue decoding at the given offset. */
197374fe6c29SRuslan Bukin 	decoder->pos = decoder->config.begin + offset;
197474fe6c29SRuslan Bukin 
197574fe6c29SRuslan Bukin 	return pt_qry_event_ovf_disabled(decoder);
197674fe6c29SRuslan Bukin }
197774fe6c29SRuslan Bukin 
197874fe6c29SRuslan Bukin /* Scan ahead for a packet at which to resume after an overflow.
197974fe6c29SRuslan Bukin  *
198074fe6c29SRuslan Bukin  * This function is called after an OVF without a corresponding FUP.  This
198174fe6c29SRuslan Bukin  * normally means that the overflow resolved while tracing was disabled.
198274fe6c29SRuslan Bukin  *
198374fe6c29SRuslan Bukin  * With erratum SKD010 it might also mean that the FUP (or TIP.PGE) was dropped.
198474fe6c29SRuslan Bukin  * The overflow thus resolved while tracing was enabled (or tracing was enabled
198574fe6c29SRuslan Bukin  * after the overflow resolved).  Search for an indication whether tracing is
198674fe6c29SRuslan Bukin  * enabled or disabled by scanning upcoming packets.
198774fe6c29SRuslan Bukin  *
198874fe6c29SRuslan Bukin  * If we can confirm that tracing is disabled, the erratum does not apply and we
198974fe6c29SRuslan Bukin  * can continue normally.
199074fe6c29SRuslan Bukin  *
199174fe6c29SRuslan Bukin  * If we can confirm that tracing is enabled, the erratum applies and we try to
199274fe6c29SRuslan Bukin  * recover by synchronizing at a later packet and a different IP.  If we can't
199374fe6c29SRuslan Bukin  * recover, pretend the erratum didn't apply so we run into the error later.
199474fe6c29SRuslan Bukin  * Since this assumes that tracing is disabled, no harm should be done, i.e. no
199574fe6c29SRuslan Bukin  * bad trace should be generated.
199674fe6c29SRuslan Bukin  *
199774fe6c29SRuslan Bukin  * Returns zero if the overflow is handled.
199874fe6c29SRuslan Bukin  * Returns a positive value if the overflow is not yet handled.
199974fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
200074fe6c29SRuslan Bukin  */
skd010_scan_for_ovf_resume(struct pt_packet_decoder * pkt,struct pt_query_decoder * decoder)200174fe6c29SRuslan Bukin static int skd010_scan_for_ovf_resume(struct pt_packet_decoder *pkt,
200274fe6c29SRuslan Bukin 				      struct pt_query_decoder *decoder)
200374fe6c29SRuslan Bukin {
200474fe6c29SRuslan Bukin 	struct pt_time_cal tcal;
200574fe6c29SRuslan Bukin 	struct pt_time time;
200674fe6c29SRuslan Bukin 	struct {
200774fe6c29SRuslan Bukin 		struct pt_time_cal tcal;
200874fe6c29SRuslan Bukin 		struct pt_time time;
200974fe6c29SRuslan Bukin 		uint64_t offset;
201074fe6c29SRuslan Bukin 	} mode_tsx;
201174fe6c29SRuslan Bukin 	int errcode;
201274fe6c29SRuslan Bukin 
201374fe6c29SRuslan Bukin 	if (!decoder)
201474fe6c29SRuslan Bukin 		return -pte_internal;
201574fe6c29SRuslan Bukin 
201674fe6c29SRuslan Bukin 	/* Keep track of time as we skip packets. */
201774fe6c29SRuslan Bukin 	time = decoder->time;
201874fe6c29SRuslan Bukin 	tcal = decoder->tcal;
201974fe6c29SRuslan Bukin 
202074fe6c29SRuslan Bukin 	/* Keep track of a potential recovery point at MODE.TSX. */
202174fe6c29SRuslan Bukin 	memset(&mode_tsx, 0, sizeof(mode_tsx));
202274fe6c29SRuslan Bukin 
202374fe6c29SRuslan Bukin 	for (;;) {
202474fe6c29SRuslan Bukin 		struct pt_packet packet;
202574fe6c29SRuslan Bukin 		uint64_t offset;
202674fe6c29SRuslan Bukin 
202774fe6c29SRuslan Bukin 		errcode = pt_pkt_get_offset(pkt, &offset);
202874fe6c29SRuslan Bukin 		if (errcode < 0)
202974fe6c29SRuslan Bukin 			return errcode;
203074fe6c29SRuslan Bukin 
203174fe6c29SRuslan Bukin 		errcode = pt_pkt_next(pkt, &packet, sizeof(packet));
203274fe6c29SRuslan Bukin 		if (errcode < 0) {
203374fe6c29SRuslan Bukin 			/* Let's assume the trace is correct if we run out
203474fe6c29SRuslan Bukin 			 * of packets.
203574fe6c29SRuslan Bukin 			 */
203674fe6c29SRuslan Bukin 			if (errcode == -pte_eos)
203774fe6c29SRuslan Bukin 				errcode = 1;
203874fe6c29SRuslan Bukin 
203974fe6c29SRuslan Bukin 			return errcode;
204074fe6c29SRuslan Bukin 		}
204174fe6c29SRuslan Bukin 
204274fe6c29SRuslan Bukin 		switch (packet.type) {
204374fe6c29SRuslan Bukin 		case ppt_tip_pge:
204474fe6c29SRuslan Bukin 			/* Everything is fine.  There is nothing to do. */
204574fe6c29SRuslan Bukin 			return 1;
204674fe6c29SRuslan Bukin 
204774fe6c29SRuslan Bukin 		case ppt_tip_pgd:
204874fe6c29SRuslan Bukin 			/* This is a clear indication that the erratum
204974fe6c29SRuslan Bukin 			 * applies.
205074fe6c29SRuslan Bukin 			 *
205174fe6c29SRuslan Bukin 			 * We synchronize after the disable.
205274fe6c29SRuslan Bukin 			 */
205374fe6c29SRuslan Bukin 			return skd010_recover_disabled(decoder, &tcal, &time,
205474fe6c29SRuslan Bukin 						       offset + packet.size);
205574fe6c29SRuslan Bukin 
205674fe6c29SRuslan Bukin 		case ppt_tnt_8:
205774fe6c29SRuslan Bukin 		case ppt_tnt_64:
205874fe6c29SRuslan Bukin 			/* This is a clear indication that the erratum
205974fe6c29SRuslan Bukin 			 * apllies.
206074fe6c29SRuslan Bukin 			 *
206174fe6c29SRuslan Bukin 			 * Yet, we can't recover from it as we wouldn't know how
206274fe6c29SRuslan Bukin 			 * many TNT bits will have been used when we eventually
206374fe6c29SRuslan Bukin 			 * find an IP packet at which to resume tracing.
206474fe6c29SRuslan Bukin 			 */
206574fe6c29SRuslan Bukin 			return 1;
206674fe6c29SRuslan Bukin 
206774fe6c29SRuslan Bukin 		case ppt_pip:
206874fe6c29SRuslan Bukin 		case ppt_vmcs:
206974fe6c29SRuslan Bukin 			/* We could track those changes and synthesize extra
207074fe6c29SRuslan Bukin 			 * events after the overflow event when recovering from
207174fe6c29SRuslan Bukin 			 * the erratum.  This requires infrastructure that we
207274fe6c29SRuslan Bukin 			 * don't currently have, though, so we're not going to
207374fe6c29SRuslan Bukin 			 * do it.
207474fe6c29SRuslan Bukin 			 *
207574fe6c29SRuslan Bukin 			 * Instead, we ignore those changes.  We already don't
207674fe6c29SRuslan Bukin 			 * know how many other changes were lost in the
207774fe6c29SRuslan Bukin 			 * overflow.
207874fe6c29SRuslan Bukin 			 */
207974fe6c29SRuslan Bukin 			break;
208074fe6c29SRuslan Bukin 
208174fe6c29SRuslan Bukin 		case ppt_mode:
208274fe6c29SRuslan Bukin 			switch (packet.payload.mode.leaf) {
208374fe6c29SRuslan Bukin 			case pt_mol_exec:
208474fe6c29SRuslan Bukin 				/* A MODE.EXEC packet binds to TIP, i.e.
208574fe6c29SRuslan Bukin 				 *
208674fe6c29SRuslan Bukin 				 *   TIP.PGE:  everything is fine
208774fe6c29SRuslan Bukin 				 *   TIP:      the erratum applies
208874fe6c29SRuslan Bukin 				 *
208974fe6c29SRuslan Bukin 				 * In the TIP.PGE case, we may just follow the
209074fe6c29SRuslan Bukin 				 * normal code flow.
209174fe6c29SRuslan Bukin 				 *
209274fe6c29SRuslan Bukin 				 * In the TIP case, we'd be able to re-sync at
209374fe6c29SRuslan Bukin 				 * the TIP IP but have to skip packets up to and
209474fe6c29SRuslan Bukin 				 * including the TIP.
209574fe6c29SRuslan Bukin 				 *
209674fe6c29SRuslan Bukin 				 * We'd need to synthesize the MODE.EXEC event
209774fe6c29SRuslan Bukin 				 * after the overflow event when recovering at
209874fe6c29SRuslan Bukin 				 * the TIP.  We lack the infrastructure for this
209974fe6c29SRuslan Bukin 				 * - it's getting too complicated.
210074fe6c29SRuslan Bukin 				 *
210174fe6c29SRuslan Bukin 				 * Instead, we ignore the execution mode change;
210274fe6c29SRuslan Bukin 				 * we already don't know how many more such
210374fe6c29SRuslan Bukin 				 * changes were lost in the overflow.
210474fe6c29SRuslan Bukin 				 */
210574fe6c29SRuslan Bukin 				break;
210674fe6c29SRuslan Bukin 
210774fe6c29SRuslan Bukin 			case pt_mol_tsx:
210874fe6c29SRuslan Bukin 				/* A MODE.TSX packet may be standalone or bind
210974fe6c29SRuslan Bukin 				 * to FUP.
211074fe6c29SRuslan Bukin 				 *
211174fe6c29SRuslan Bukin 				 * If this is the second MODE.TSX, we're sure
211274fe6c29SRuslan Bukin 				 * that tracing is disabled and everything is
211374fe6c29SRuslan Bukin 				 * fine.
211474fe6c29SRuslan Bukin 				 */
211574fe6c29SRuslan Bukin 				if (mode_tsx.offset)
211674fe6c29SRuslan Bukin 					return 1;
211774fe6c29SRuslan Bukin 
211874fe6c29SRuslan Bukin 				/* If we find the FUP this packet binds to, we
211974fe6c29SRuslan Bukin 				 * may recover at the FUP IP and restart
212074fe6c29SRuslan Bukin 				 * processing packets from here.  Remember the
212174fe6c29SRuslan Bukin 				 * current state.
212274fe6c29SRuslan Bukin 				 */
212374fe6c29SRuslan Bukin 				mode_tsx.offset = offset;
212474fe6c29SRuslan Bukin 				mode_tsx.time = time;
212574fe6c29SRuslan Bukin 				mode_tsx.tcal = tcal;
212674fe6c29SRuslan Bukin 
212774fe6c29SRuslan Bukin 				break;
212874fe6c29SRuslan Bukin 			}
212974fe6c29SRuslan Bukin 
213074fe6c29SRuslan Bukin 			break;
213174fe6c29SRuslan Bukin 
213274fe6c29SRuslan Bukin 		case ppt_fup:
213374fe6c29SRuslan Bukin 			/* This is a pretty good indication that tracing
213474fe6c29SRuslan Bukin 			 * is indeed enabled and the erratum applies.
213574fe6c29SRuslan Bukin 			 */
213674fe6c29SRuslan Bukin 
213774fe6c29SRuslan Bukin 			/* If we got a MODE.TSX packet before, we synchronize at
213874fe6c29SRuslan Bukin 			 * the FUP IP but continue decoding packets starting
213974fe6c29SRuslan Bukin 			 * from the MODE.TSX.
214074fe6c29SRuslan Bukin 			 */
214174fe6c29SRuslan Bukin 			if (mode_tsx.offset)
214274fe6c29SRuslan Bukin 				return skd010_recover(decoder,
214374fe6c29SRuslan Bukin 						      &packet.payload.ip,
214474fe6c29SRuslan Bukin 						      &mode_tsx.tcal,
214574fe6c29SRuslan Bukin 						      &mode_tsx.time,
214674fe6c29SRuslan Bukin 						      mode_tsx.offset);
214774fe6c29SRuslan Bukin 
214874fe6c29SRuslan Bukin 			/* Without a preceding MODE.TSX, this FUP is the start
214974fe6c29SRuslan Bukin 			 * of an async branch or disable.  We synchronize at the
215074fe6c29SRuslan Bukin 			 * FUP IP and continue decoding packets from here.
215174fe6c29SRuslan Bukin 			 */
215274fe6c29SRuslan Bukin 			return skd010_recover(decoder, &packet.payload.ip,
215374fe6c29SRuslan Bukin 					      &tcal, &time, offset);
215474fe6c29SRuslan Bukin 
215574fe6c29SRuslan Bukin 		case ppt_tip:
215674fe6c29SRuslan Bukin 			/* We syhchronize at the TIP IP and continue decoding
215774fe6c29SRuslan Bukin 			 * packets after the TIP packet.
215874fe6c29SRuslan Bukin 			 */
215974fe6c29SRuslan Bukin 			return skd010_recover(decoder, &packet.payload.ip,
216074fe6c29SRuslan Bukin 					      &tcal, &time,
216174fe6c29SRuslan Bukin 					      offset + packet.size);
216274fe6c29SRuslan Bukin 
216374fe6c29SRuslan Bukin 		case ppt_psb:
216474fe6c29SRuslan Bukin 			/* We reached a synchronization point.  Tracing is
216574fe6c29SRuslan Bukin 			 * enabled if and only if the PSB+ contains a FUP.
216674fe6c29SRuslan Bukin 			 */
216774fe6c29SRuslan Bukin 			errcode = pt_qry_find_header_fup(&packet, pkt);
216874fe6c29SRuslan Bukin 			if (errcode < 0) {
216974fe6c29SRuslan Bukin 				/* If we ran out of packets, we can't tell.
217074fe6c29SRuslan Bukin 				 * Let's assume the trace is correct.
217174fe6c29SRuslan Bukin 				 */
217274fe6c29SRuslan Bukin 				if (errcode == -pte_eos)
217374fe6c29SRuslan Bukin 					errcode = 1;
217474fe6c29SRuslan Bukin 
217574fe6c29SRuslan Bukin 				return errcode;
217674fe6c29SRuslan Bukin 			}
217774fe6c29SRuslan Bukin 
217874fe6c29SRuslan Bukin 			/* If there is no FUP, tracing is disabled and
217974fe6c29SRuslan Bukin 			 * everything is fine.
218074fe6c29SRuslan Bukin 			 */
218174fe6c29SRuslan Bukin 			if (!errcode)
218274fe6c29SRuslan Bukin 				return 1;
218374fe6c29SRuslan Bukin 
218474fe6c29SRuslan Bukin 			/* We should have a FUP. */
218574fe6c29SRuslan Bukin 			if (packet.type != ppt_fup)
218674fe6c29SRuslan Bukin 				return -pte_internal;
218774fe6c29SRuslan Bukin 
218874fe6c29SRuslan Bukin 			/* Otherwise, we may synchronize at the FUP IP and
218974fe6c29SRuslan Bukin 			 * continue decoding packets at the PSB.
219074fe6c29SRuslan Bukin 			 */
219174fe6c29SRuslan Bukin 			return skd010_recover(decoder, &packet.payload.ip,
219274fe6c29SRuslan Bukin 					      &tcal, &time, offset);
219374fe6c29SRuslan Bukin 
219474fe6c29SRuslan Bukin 		case ppt_psbend:
219574fe6c29SRuslan Bukin 			/* We shouldn't see this. */
219674fe6c29SRuslan Bukin 			return -pte_bad_context;
219774fe6c29SRuslan Bukin 
219874fe6c29SRuslan Bukin 		case ppt_ovf:
219974fe6c29SRuslan Bukin 		case ppt_stop:
220074fe6c29SRuslan Bukin 			/* It doesn't matter if it had been enabled or disabled
220174fe6c29SRuslan Bukin 			 * before.  We may resume normally.
220274fe6c29SRuslan Bukin 			 */
220374fe6c29SRuslan Bukin 			return 1;
220474fe6c29SRuslan Bukin 
220574fe6c29SRuslan Bukin 		case ppt_unknown:
220674fe6c29SRuslan Bukin 		case ppt_invalid:
220774fe6c29SRuslan Bukin 			/* We can't skip this packet. */
220874fe6c29SRuslan Bukin 			return 1;
220974fe6c29SRuslan Bukin 
221074fe6c29SRuslan Bukin 		case ppt_pad:
221174fe6c29SRuslan Bukin 		case ppt_mnt:
221274fe6c29SRuslan Bukin 		case ppt_pwre:
221374fe6c29SRuslan Bukin 		case ppt_pwrx:
221474fe6c29SRuslan Bukin 			/* Ignore this packet. */
221574fe6c29SRuslan Bukin 			break;
221674fe6c29SRuslan Bukin 
221774fe6c29SRuslan Bukin 		case ppt_exstop:
221874fe6c29SRuslan Bukin 			/* We may skip a stand-alone EXSTOP. */
221974fe6c29SRuslan Bukin 			if (!packet.payload.exstop.ip)
222074fe6c29SRuslan Bukin 				break;
222174fe6c29SRuslan Bukin 
222274fe6c29SRuslan Bukin 			fallthrough;
222374fe6c29SRuslan Bukin 		case ppt_mwait:
222474fe6c29SRuslan Bukin 			/* To skip this packet, we'd need to take care of the
222574fe6c29SRuslan Bukin 			 * FUP it binds to.  This is getting complicated.
222674fe6c29SRuslan Bukin 			 */
222774fe6c29SRuslan Bukin 			return 1;
222874fe6c29SRuslan Bukin 
222974fe6c29SRuslan Bukin 		case ppt_ptw:
223074fe6c29SRuslan Bukin 			/* We may skip a stand-alone PTW. */
223174fe6c29SRuslan Bukin 			if (!packet.payload.ptw.ip)
223274fe6c29SRuslan Bukin 				break;
223374fe6c29SRuslan Bukin 
223474fe6c29SRuslan Bukin 			/* To skip this packet, we'd need to take care of the
223574fe6c29SRuslan Bukin 			 * FUP it binds to.  This is getting complicated.
223674fe6c29SRuslan Bukin 			 */
223774fe6c29SRuslan Bukin 			return 1;
223874fe6c29SRuslan Bukin 
223974fe6c29SRuslan Bukin 		case ppt_tsc:
224074fe6c29SRuslan Bukin 			/* Keep track of time. */
224174fe6c29SRuslan Bukin 			errcode = pt_qry_apply_tsc(&time, &tcal,
224274fe6c29SRuslan Bukin 						   &packet.payload.tsc,
224374fe6c29SRuslan Bukin 						   &decoder->config);
224474fe6c29SRuslan Bukin 			if (errcode < 0)
224574fe6c29SRuslan Bukin 				return errcode;
224674fe6c29SRuslan Bukin 
224774fe6c29SRuslan Bukin 			break;
224874fe6c29SRuslan Bukin 
224974fe6c29SRuslan Bukin 		case ppt_cbr:
225074fe6c29SRuslan Bukin 			/* Keep track of time. */
225174fe6c29SRuslan Bukin 			errcode = pt_qry_apply_cbr(&time, &tcal,
225274fe6c29SRuslan Bukin 						   &packet.payload.cbr,
225374fe6c29SRuslan Bukin 						   &decoder->config);
225474fe6c29SRuslan Bukin 			if (errcode < 0)
225574fe6c29SRuslan Bukin 				return errcode;
225674fe6c29SRuslan Bukin 
225774fe6c29SRuslan Bukin 			break;
225874fe6c29SRuslan Bukin 
225974fe6c29SRuslan Bukin 		case ppt_tma:
226074fe6c29SRuslan Bukin 			/* Keep track of time. */
226174fe6c29SRuslan Bukin 			errcode = pt_qry_apply_tma(&time, &tcal,
226274fe6c29SRuslan Bukin 						   &packet.payload.tma,
226374fe6c29SRuslan Bukin 						   &decoder->config);
226474fe6c29SRuslan Bukin 			if (errcode < 0)
226574fe6c29SRuslan Bukin 				return errcode;
226674fe6c29SRuslan Bukin 
226774fe6c29SRuslan Bukin 			break;
226874fe6c29SRuslan Bukin 
226974fe6c29SRuslan Bukin 		case ppt_mtc:
227074fe6c29SRuslan Bukin 			/* Keep track of time. */
227174fe6c29SRuslan Bukin 			errcode = pt_qry_apply_mtc(&time, &tcal,
227274fe6c29SRuslan Bukin 						   &packet.payload.mtc,
227374fe6c29SRuslan Bukin 						   &decoder->config);
227474fe6c29SRuslan Bukin 			if (errcode < 0)
227574fe6c29SRuslan Bukin 				return errcode;
227674fe6c29SRuslan Bukin 
227774fe6c29SRuslan Bukin 			break;
227874fe6c29SRuslan Bukin 
227974fe6c29SRuslan Bukin 		case ppt_cyc:
228074fe6c29SRuslan Bukin 			/* Keep track of time. */
228174fe6c29SRuslan Bukin 			errcode = pt_qry_apply_cyc(&time, &tcal,
228274fe6c29SRuslan Bukin 						   &packet.payload.cyc,
228374fe6c29SRuslan Bukin 						   &decoder->config);
228474fe6c29SRuslan Bukin 			if (errcode < 0)
228574fe6c29SRuslan Bukin 				return errcode;
228674fe6c29SRuslan Bukin 
228774fe6c29SRuslan Bukin 			break;
228874fe6c29SRuslan Bukin 		}
228974fe6c29SRuslan Bukin 	}
229074fe6c29SRuslan Bukin }
229174fe6c29SRuslan Bukin 
pt_qry_handle_skd010(struct pt_query_decoder * decoder)229274fe6c29SRuslan Bukin static int pt_qry_handle_skd010(struct pt_query_decoder *decoder)
229374fe6c29SRuslan Bukin {
229474fe6c29SRuslan Bukin 	struct pt_packet_decoder pkt;
229574fe6c29SRuslan Bukin 	uint64_t offset;
229674fe6c29SRuslan Bukin 	int errcode;
229774fe6c29SRuslan Bukin 
229874fe6c29SRuslan Bukin 	if (!decoder)
229974fe6c29SRuslan Bukin 		return -pte_internal;
230074fe6c29SRuslan Bukin 
230174fe6c29SRuslan Bukin 	errcode = pt_qry_get_offset(decoder, &offset);
230274fe6c29SRuslan Bukin 	if (errcode < 0)
230374fe6c29SRuslan Bukin 		return errcode;
230474fe6c29SRuslan Bukin 
230574fe6c29SRuslan Bukin 	errcode = pt_pkt_decoder_init(&pkt, &decoder->config);
230674fe6c29SRuslan Bukin 	if (errcode < 0)
230774fe6c29SRuslan Bukin 		return errcode;
230874fe6c29SRuslan Bukin 
230974fe6c29SRuslan Bukin 	errcode = pt_pkt_sync_set(&pkt, offset);
231074fe6c29SRuslan Bukin 	if (errcode >= 0)
231174fe6c29SRuslan Bukin 		errcode = skd010_scan_for_ovf_resume(&pkt, decoder);
231274fe6c29SRuslan Bukin 
231374fe6c29SRuslan Bukin 	pt_pkt_decoder_fini(&pkt);
231474fe6c29SRuslan Bukin 	return errcode;
231574fe6c29SRuslan Bukin }
231674fe6c29SRuslan Bukin 
231774fe6c29SRuslan Bukin /* Scan ahead for an indication whether tracing is enabled or disabled.
231874fe6c29SRuslan Bukin  *
231974fe6c29SRuslan Bukin  * Returns zero if tracing is clearly disabled.
232074fe6c29SRuslan Bukin  * Returns a positive integer if tracing is enabled or if we can't tell.
232174fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
232274fe6c29SRuslan Bukin  */
apl12_tracing_is_disabled(struct pt_packet_decoder * decoder)232374fe6c29SRuslan Bukin static int apl12_tracing_is_disabled(struct pt_packet_decoder *decoder)
232474fe6c29SRuslan Bukin {
232574fe6c29SRuslan Bukin 	if (!decoder)
232674fe6c29SRuslan Bukin 		return -pte_internal;
232774fe6c29SRuslan Bukin 
232874fe6c29SRuslan Bukin 	for (;;) {
232974fe6c29SRuslan Bukin 		struct pt_packet packet;
233074fe6c29SRuslan Bukin 		int status;
233174fe6c29SRuslan Bukin 
233274fe6c29SRuslan Bukin 		status = pt_pkt_next(decoder, &packet, sizeof(packet));
233374fe6c29SRuslan Bukin 		if (status < 0) {
233474fe6c29SRuslan Bukin 			/* Running out of packets is not an error. */
233574fe6c29SRuslan Bukin 			if (status == -pte_eos)
233674fe6c29SRuslan Bukin 				status = 1;
233774fe6c29SRuslan Bukin 
233874fe6c29SRuslan Bukin 			return status;
233974fe6c29SRuslan Bukin 		}
234074fe6c29SRuslan Bukin 
234174fe6c29SRuslan Bukin 		switch (packet.type) {
234274fe6c29SRuslan Bukin 		default:
234374fe6c29SRuslan Bukin 			/* Skip other packets. */
234474fe6c29SRuslan Bukin 			break;
234574fe6c29SRuslan Bukin 
234674fe6c29SRuslan Bukin 		case ppt_stop:
234774fe6c29SRuslan Bukin 			/* Tracing is disabled before a stop. */
234874fe6c29SRuslan Bukin 			return 0;
234974fe6c29SRuslan Bukin 
235074fe6c29SRuslan Bukin 		case ppt_tip_pge:
235174fe6c29SRuslan Bukin 			/* Tracing gets enabled - it must have been disabled. */
235274fe6c29SRuslan Bukin 			return 0;
235374fe6c29SRuslan Bukin 
235474fe6c29SRuslan Bukin 		case ppt_tnt_8:
235574fe6c29SRuslan Bukin 		case ppt_tnt_64:
235674fe6c29SRuslan Bukin 		case ppt_tip:
235774fe6c29SRuslan Bukin 		case ppt_tip_pgd:
235874fe6c29SRuslan Bukin 			/* Those packets are only generated when tracing is
235974fe6c29SRuslan Bukin 			 * enabled.  We're done.
236074fe6c29SRuslan Bukin 			 */
236174fe6c29SRuslan Bukin 			return 1;
236274fe6c29SRuslan Bukin 
236374fe6c29SRuslan Bukin 		case ppt_psb:
236474fe6c29SRuslan Bukin 			/* We reached a synchronization point.  Tracing is
236574fe6c29SRuslan Bukin 			 * enabled if and only if the PSB+ contains a FUP.
236674fe6c29SRuslan Bukin 			 */
236774fe6c29SRuslan Bukin 			status = pt_qry_find_header_fup(&packet, decoder);
236874fe6c29SRuslan Bukin 
236974fe6c29SRuslan Bukin 			/* If we ran out of packets, we can't tell. */
237074fe6c29SRuslan Bukin 			if (status == -pte_eos)
237174fe6c29SRuslan Bukin 				status = 1;
237274fe6c29SRuslan Bukin 
237374fe6c29SRuslan Bukin 			return status;
237474fe6c29SRuslan Bukin 
237574fe6c29SRuslan Bukin 		case ppt_psbend:
237674fe6c29SRuslan Bukin 			/* We shouldn't see this. */
237774fe6c29SRuslan Bukin 			return -pte_bad_context;
237874fe6c29SRuslan Bukin 
237974fe6c29SRuslan Bukin 		case ppt_ovf:
238074fe6c29SRuslan Bukin 			/* It doesn't matter - we run into the next overflow. */
238174fe6c29SRuslan Bukin 			return 1;
238274fe6c29SRuslan Bukin 
238374fe6c29SRuslan Bukin 		case ppt_unknown:
238474fe6c29SRuslan Bukin 		case ppt_invalid:
238574fe6c29SRuslan Bukin 			/* We can't skip this packet. */
238674fe6c29SRuslan Bukin 			return 1;
238774fe6c29SRuslan Bukin 		}
238874fe6c29SRuslan Bukin 	}
238974fe6c29SRuslan Bukin }
239074fe6c29SRuslan Bukin 
239174fe6c29SRuslan Bukin /* Apply workaround for erratum APL12.
239274fe6c29SRuslan Bukin  *
239374fe6c29SRuslan Bukin  * We resume from @offset (relative to @decoder->pos) with tracing disabled.  On
239474fe6c29SRuslan Bukin  * our way to the resume location we process packets to update our state.
239574fe6c29SRuslan Bukin  *
239674fe6c29SRuslan Bukin  * Any event will be dropped.
239774fe6c29SRuslan Bukin  *
239874fe6c29SRuslan Bukin  * Returns zero on success, a negative pt_error_code otherwise.
239974fe6c29SRuslan Bukin  */
apl12_resume_disabled(struct pt_query_decoder * decoder,struct pt_packet_decoder * pkt,unsigned int offset)240074fe6c29SRuslan Bukin static int apl12_resume_disabled(struct pt_query_decoder *decoder,
240174fe6c29SRuslan Bukin 				 struct pt_packet_decoder *pkt,
240274fe6c29SRuslan Bukin 				 unsigned int offset)
240374fe6c29SRuslan Bukin {
240474fe6c29SRuslan Bukin 	uint64_t begin, end;
240574fe6c29SRuslan Bukin 	int errcode;
240674fe6c29SRuslan Bukin 
240774fe6c29SRuslan Bukin 	if (!decoder)
240874fe6c29SRuslan Bukin 		return -pte_internal;
240974fe6c29SRuslan Bukin 
241074fe6c29SRuslan Bukin 	errcode = pt_qry_get_offset(decoder, &begin);
241174fe6c29SRuslan Bukin 	if (errcode < 0)
241274fe6c29SRuslan Bukin 		return errcode;
241374fe6c29SRuslan Bukin 
241474fe6c29SRuslan Bukin 	errcode = pt_pkt_sync_set(pkt, begin);
241574fe6c29SRuslan Bukin 	if (errcode < 0)
241674fe6c29SRuslan Bukin 		return errcode;
241774fe6c29SRuslan Bukin 
241874fe6c29SRuslan Bukin 	end = begin + offset;
241974fe6c29SRuslan Bukin 	for (;;) {
242074fe6c29SRuslan Bukin 		struct pt_packet packet;
242174fe6c29SRuslan Bukin 		uint64_t next;
242274fe6c29SRuslan Bukin 
242374fe6c29SRuslan Bukin 		errcode = pt_pkt_next(pkt, &packet, sizeof(packet));
242474fe6c29SRuslan Bukin 		if (errcode < 0) {
242574fe6c29SRuslan Bukin 			/* Running out of packets is not an error. */
242674fe6c29SRuslan Bukin 			if (errcode == -pte_eos)
242774fe6c29SRuslan Bukin 				errcode = 0;
242874fe6c29SRuslan Bukin 
242974fe6c29SRuslan Bukin 			return errcode;
243074fe6c29SRuslan Bukin 		}
243174fe6c29SRuslan Bukin 
243274fe6c29SRuslan Bukin 		/* The offset is the start of the next packet. */
243374fe6c29SRuslan Bukin 		errcode = pt_pkt_get_offset(pkt, &next);
243474fe6c29SRuslan Bukin 		if (errcode < 0)
243574fe6c29SRuslan Bukin 			return errcode;
243674fe6c29SRuslan Bukin 
243774fe6c29SRuslan Bukin 		/* We're done when we reach @offset.
243874fe6c29SRuslan Bukin 		 *
243974fe6c29SRuslan Bukin 		 * The current @packet will be the FUP after which we started
244074fe6c29SRuslan Bukin 		 * our search.  We skip it.
244174fe6c29SRuslan Bukin 		 *
244274fe6c29SRuslan Bukin 		 * Check that we're not accidentally proceeding past @offset.
244374fe6c29SRuslan Bukin 		 */
244474fe6c29SRuslan Bukin 		if (end <= next) {
244574fe6c29SRuslan Bukin 			if (end < next)
244674fe6c29SRuslan Bukin 				return -pte_internal;
244774fe6c29SRuslan Bukin 
244874fe6c29SRuslan Bukin 			break;
244974fe6c29SRuslan Bukin 		}
245074fe6c29SRuslan Bukin 
245174fe6c29SRuslan Bukin 		switch (packet.type) {
245274fe6c29SRuslan Bukin 		default:
245374fe6c29SRuslan Bukin 			/* Skip other packets. */
245474fe6c29SRuslan Bukin 			break;
245574fe6c29SRuslan Bukin 
245674fe6c29SRuslan Bukin 		case ppt_mode:
245774fe6c29SRuslan Bukin 		case ppt_pip:
245874fe6c29SRuslan Bukin 		case ppt_vmcs:
245974fe6c29SRuslan Bukin 			/* We should not encounter those.
246074fe6c29SRuslan Bukin 			 *
246174fe6c29SRuslan Bukin 			 * We should not encounter a lot of packets but those
246274fe6c29SRuslan Bukin 			 * are state-relevant; let's check them explicitly.
246374fe6c29SRuslan Bukin 			 */
246474fe6c29SRuslan Bukin 			return -pte_internal;
246574fe6c29SRuslan Bukin 
246674fe6c29SRuslan Bukin 		case ppt_tsc:
246774fe6c29SRuslan Bukin 			/* Keep track of time. */
246874fe6c29SRuslan Bukin 			errcode = pt_qry_apply_tsc(&decoder->time,
246974fe6c29SRuslan Bukin 						   &decoder->tcal,
247074fe6c29SRuslan Bukin 						   &packet.payload.tsc,
247174fe6c29SRuslan Bukin 						   &decoder->config);
247274fe6c29SRuslan Bukin 			if (errcode < 0)
247374fe6c29SRuslan Bukin 				return errcode;
247474fe6c29SRuslan Bukin 
247574fe6c29SRuslan Bukin 			break;
247674fe6c29SRuslan Bukin 
247774fe6c29SRuslan Bukin 		case ppt_cbr:
247874fe6c29SRuslan Bukin 			/* Keep track of time. */
247974fe6c29SRuslan Bukin 			errcode = pt_qry_apply_cbr(&decoder->time,
248074fe6c29SRuslan Bukin 						   &decoder->tcal,
248174fe6c29SRuslan Bukin 						   &packet.payload.cbr,
248274fe6c29SRuslan Bukin 						   &decoder->config);
248374fe6c29SRuslan Bukin 			if (errcode < 0)
248474fe6c29SRuslan Bukin 				return errcode;
248574fe6c29SRuslan Bukin 
248674fe6c29SRuslan Bukin 			break;
248774fe6c29SRuslan Bukin 
248874fe6c29SRuslan Bukin 		case ppt_tma:
248974fe6c29SRuslan Bukin 			/* Keep track of time. */
249074fe6c29SRuslan Bukin 			errcode = pt_qry_apply_tma(&decoder->time,
249174fe6c29SRuslan Bukin 						   &decoder->tcal,
249274fe6c29SRuslan Bukin 						   &packet.payload.tma,
249374fe6c29SRuslan Bukin 						   &decoder->config);
249474fe6c29SRuslan Bukin 			if (errcode < 0)
249574fe6c29SRuslan Bukin 				return errcode;
249674fe6c29SRuslan Bukin 
249774fe6c29SRuslan Bukin 			break;
249874fe6c29SRuslan Bukin 
249974fe6c29SRuslan Bukin 		case ppt_mtc:
250074fe6c29SRuslan Bukin 			/* Keep track of time. */
250174fe6c29SRuslan Bukin 			errcode = pt_qry_apply_mtc(&decoder->time,
250274fe6c29SRuslan Bukin 						   &decoder->tcal,
250374fe6c29SRuslan Bukin 						   &packet.payload.mtc,
250474fe6c29SRuslan Bukin 						   &decoder->config);
250574fe6c29SRuslan Bukin 			if (errcode < 0)
250674fe6c29SRuslan Bukin 				return errcode;
250774fe6c29SRuslan Bukin 
250874fe6c29SRuslan Bukin 			break;
250974fe6c29SRuslan Bukin 
251074fe6c29SRuslan Bukin 		case ppt_cyc:
251174fe6c29SRuslan Bukin 			/* Keep track of time. */
251274fe6c29SRuslan Bukin 			errcode = pt_qry_apply_cyc(&decoder->time,
251374fe6c29SRuslan Bukin 						   &decoder->tcal,
251474fe6c29SRuslan Bukin 						   &packet.payload.cyc,
251574fe6c29SRuslan Bukin 						   &decoder->config);
251674fe6c29SRuslan Bukin 			if (errcode < 0)
251774fe6c29SRuslan Bukin 				return errcode;
251874fe6c29SRuslan Bukin 
251974fe6c29SRuslan Bukin 			break;
252074fe6c29SRuslan Bukin 		}
252174fe6c29SRuslan Bukin 	}
252274fe6c29SRuslan Bukin 
252374fe6c29SRuslan Bukin 	decoder->pos += offset;
252474fe6c29SRuslan Bukin 
252574fe6c29SRuslan Bukin 	return pt_qry_event_ovf_disabled(decoder);
252674fe6c29SRuslan Bukin }
252774fe6c29SRuslan Bukin 
252874fe6c29SRuslan Bukin /* Handle erratum APL12.
252974fe6c29SRuslan Bukin  *
253074fe6c29SRuslan Bukin  * This function is called when a FUP is found after an OVF.  The @offset
253174fe6c29SRuslan Bukin  * argument gives the relative offset from @decoder->pos to after the FUP.
253274fe6c29SRuslan Bukin  *
253374fe6c29SRuslan Bukin  * A FUP after OVF normally indicates that the overflow resolved while tracing
253474fe6c29SRuslan Bukin  * is enabled.  Due to erratum APL12, however, the overflow may have resolved
253574fe6c29SRuslan Bukin  * while tracing is disabled and still generate a FUP.
253674fe6c29SRuslan Bukin  *
253774fe6c29SRuslan Bukin  * We scan ahead for an indication whether tracing is actually disabled.  If we
253874fe6c29SRuslan Bukin  * find one, the erratum applies and we proceed from after the FUP packet.
253974fe6c29SRuslan Bukin  *
254074fe6c29SRuslan Bukin  * This will drop any CBR or MTC events.  We will update @decoder's timing state
254174fe6c29SRuslan Bukin  * on CBR but drop the event.
254274fe6c29SRuslan Bukin  *
254374fe6c29SRuslan Bukin  * Returns zero if the erratum was handled.
254474fe6c29SRuslan Bukin  * Returns a positive integer if the erratum was not handled.
254574fe6c29SRuslan Bukin  * Returns a negative pt_error_code otherwise.
254674fe6c29SRuslan Bukin  */
pt_qry_handle_apl12(struct pt_query_decoder * decoder,unsigned int offset)254774fe6c29SRuslan Bukin static int pt_qry_handle_apl12(struct pt_query_decoder *decoder,
254874fe6c29SRuslan Bukin 			       unsigned int offset)
254974fe6c29SRuslan Bukin {
255074fe6c29SRuslan Bukin 	struct pt_packet_decoder pkt;
255174fe6c29SRuslan Bukin 	uint64_t here;
255274fe6c29SRuslan Bukin 	int status;
255374fe6c29SRuslan Bukin 
255474fe6c29SRuslan Bukin 	if (!decoder)
255574fe6c29SRuslan Bukin 		return -pte_internal;
255674fe6c29SRuslan Bukin 
255774fe6c29SRuslan Bukin 	status = pt_qry_get_offset(decoder, &here);
255874fe6c29SRuslan Bukin 	if (status < 0)
255974fe6c29SRuslan Bukin 		return status;
256074fe6c29SRuslan Bukin 
256174fe6c29SRuslan Bukin 	status = pt_pkt_decoder_init(&pkt, &decoder->config);
256274fe6c29SRuslan Bukin 	if (status < 0)
256374fe6c29SRuslan Bukin 		return status;
256474fe6c29SRuslan Bukin 
256574fe6c29SRuslan Bukin 	status = pt_pkt_sync_set(&pkt, here + offset);
256674fe6c29SRuslan Bukin 	if (status >= 0) {
256774fe6c29SRuslan Bukin 		status = apl12_tracing_is_disabled(&pkt);
256874fe6c29SRuslan Bukin 		if (!status)
256974fe6c29SRuslan Bukin 			status = apl12_resume_disabled(decoder, &pkt, offset);
257074fe6c29SRuslan Bukin 	}
257174fe6c29SRuslan Bukin 
257274fe6c29SRuslan Bukin 	pt_pkt_decoder_fini(&pkt);
257374fe6c29SRuslan Bukin 	return status;
257474fe6c29SRuslan Bukin }
257574fe6c29SRuslan Bukin 
257674fe6c29SRuslan Bukin /* Apply workaround for erratum APL11.
257774fe6c29SRuslan Bukin  *
257874fe6c29SRuslan Bukin  * We search for a TIP.PGD and, if we found one, resume from after that packet
257974fe6c29SRuslan Bukin  * with tracing disabled.  On our way to the resume location we process packets
258074fe6c29SRuslan Bukin  * to update our state.
258174fe6c29SRuslan Bukin  *
258274fe6c29SRuslan Bukin  * If we don't find a TIP.PGD but instead some other packet that indicates that
258374fe6c29SRuslan Bukin  * tracing is disabled, indicate that the erratum does not apply.
258474fe6c29SRuslan Bukin  *
258574fe6c29SRuslan Bukin  * Any event will be dropped.
258674fe6c29SRuslan Bukin  *
258774fe6c29SRuslan Bukin  * Returns zero if the erratum was handled.
258874fe6c29SRuslan Bukin  * Returns a positive integer if the erratum was not handled.
258974fe6c29SRuslan Bukin  * Returns a negative pt_error_code otherwise.
259074fe6c29SRuslan Bukin  */
apl11_apply(struct pt_query_decoder * decoder,struct pt_packet_decoder * pkt)259174fe6c29SRuslan Bukin static int apl11_apply(struct pt_query_decoder *decoder,
259274fe6c29SRuslan Bukin 		       struct pt_packet_decoder *pkt)
259374fe6c29SRuslan Bukin {
259474fe6c29SRuslan Bukin 	struct pt_time_cal tcal;
259574fe6c29SRuslan Bukin 	struct pt_time time;
259674fe6c29SRuslan Bukin 
259774fe6c29SRuslan Bukin 	if (!decoder)
259874fe6c29SRuslan Bukin 		return -pte_internal;
259974fe6c29SRuslan Bukin 
260074fe6c29SRuslan Bukin 	time = decoder->time;
260174fe6c29SRuslan Bukin 	tcal = decoder->tcal;
260274fe6c29SRuslan Bukin 	for (;;) {
260374fe6c29SRuslan Bukin 		struct pt_packet packet;
260474fe6c29SRuslan Bukin 		int errcode;
260574fe6c29SRuslan Bukin 
260674fe6c29SRuslan Bukin 		errcode = pt_pkt_next(pkt, &packet, sizeof(packet));
260774fe6c29SRuslan Bukin 		if (errcode < 0)
260874fe6c29SRuslan Bukin 			return errcode;
260974fe6c29SRuslan Bukin 
261074fe6c29SRuslan Bukin 		switch (packet.type) {
261174fe6c29SRuslan Bukin 		case ppt_tip_pgd: {
261274fe6c29SRuslan Bukin 			uint64_t offset;
261374fe6c29SRuslan Bukin 
261474fe6c29SRuslan Bukin 			/* We found a TIP.PGD.  The erratum applies.
261574fe6c29SRuslan Bukin 			 *
261674fe6c29SRuslan Bukin 			 * Resume from here with tracing disabled.
261774fe6c29SRuslan Bukin 			 */
261874fe6c29SRuslan Bukin 			errcode = pt_pkt_get_offset(pkt, &offset);
261974fe6c29SRuslan Bukin 			if (errcode < 0)
262074fe6c29SRuslan Bukin 				return errcode;
262174fe6c29SRuslan Bukin 
262274fe6c29SRuslan Bukin 			decoder->time = time;
262374fe6c29SRuslan Bukin 			decoder->tcal = tcal;
262474fe6c29SRuslan Bukin 			decoder->pos = decoder->config.begin + offset;
262574fe6c29SRuslan Bukin 
262674fe6c29SRuslan Bukin 			return pt_qry_event_ovf_disabled(decoder);
262774fe6c29SRuslan Bukin 		}
262874fe6c29SRuslan Bukin 
262974fe6c29SRuslan Bukin 		case ppt_invalid:
263074fe6c29SRuslan Bukin 			return -pte_bad_opc;
263174fe6c29SRuslan Bukin 
263274fe6c29SRuslan Bukin 		case ppt_fup:
263374fe6c29SRuslan Bukin 		case ppt_psb:
263474fe6c29SRuslan Bukin 		case ppt_tip_pge:
263574fe6c29SRuslan Bukin 		case ppt_stop:
263674fe6c29SRuslan Bukin 		case ppt_ovf:
263774fe6c29SRuslan Bukin 		case ppt_mode:
263874fe6c29SRuslan Bukin 		case ppt_pip:
263974fe6c29SRuslan Bukin 		case ppt_vmcs:
264074fe6c29SRuslan Bukin 		case ppt_exstop:
264174fe6c29SRuslan Bukin 		case ppt_mwait:
264274fe6c29SRuslan Bukin 		case ppt_pwre:
264374fe6c29SRuslan Bukin 		case ppt_pwrx:
264474fe6c29SRuslan Bukin 		case ppt_ptw:
264574fe6c29SRuslan Bukin 			/* The erratum does not apply. */
264674fe6c29SRuslan Bukin 			return 1;
264774fe6c29SRuslan Bukin 
264874fe6c29SRuslan Bukin 		case ppt_unknown:
264974fe6c29SRuslan Bukin 		case ppt_pad:
265074fe6c29SRuslan Bukin 		case ppt_mnt:
265174fe6c29SRuslan Bukin 			/* Skip those packets. */
265274fe6c29SRuslan Bukin 			break;
265374fe6c29SRuslan Bukin 
265474fe6c29SRuslan Bukin 		case ppt_psbend:
265574fe6c29SRuslan Bukin 		case ppt_tip:
265674fe6c29SRuslan Bukin 		case ppt_tnt_8:
265774fe6c29SRuslan Bukin 		case ppt_tnt_64:
265874fe6c29SRuslan Bukin 			return -pte_bad_context;
265974fe6c29SRuslan Bukin 
266074fe6c29SRuslan Bukin 
266174fe6c29SRuslan Bukin 		case ppt_tsc:
266274fe6c29SRuslan Bukin 			/* Keep track of time. */
266374fe6c29SRuslan Bukin 			errcode = pt_qry_apply_tsc(&time, &tcal,
266474fe6c29SRuslan Bukin 						   &packet.payload.tsc,
266574fe6c29SRuslan Bukin 						   &decoder->config);
266674fe6c29SRuslan Bukin 			if (errcode < 0)
266774fe6c29SRuslan Bukin 				return errcode;
266874fe6c29SRuslan Bukin 
266974fe6c29SRuslan Bukin 			break;
267074fe6c29SRuslan Bukin 
267174fe6c29SRuslan Bukin 		case ppt_cbr:
267274fe6c29SRuslan Bukin 			/* Keep track of time. */
267374fe6c29SRuslan Bukin 			errcode = pt_qry_apply_cbr(&time, &tcal,
267474fe6c29SRuslan Bukin 						   &packet.payload.cbr,
267574fe6c29SRuslan Bukin 						   &decoder->config);
267674fe6c29SRuslan Bukin 			if (errcode < 0)
267774fe6c29SRuslan Bukin 				return errcode;
267874fe6c29SRuslan Bukin 
267974fe6c29SRuslan Bukin 			break;
268074fe6c29SRuslan Bukin 
268174fe6c29SRuslan Bukin 		case ppt_tma:
268274fe6c29SRuslan Bukin 			/* Keep track of time. */
268374fe6c29SRuslan Bukin 			errcode = pt_qry_apply_tma(&time, &tcal,
268474fe6c29SRuslan Bukin 						   &packet.payload.tma,
268574fe6c29SRuslan Bukin 						   &decoder->config);
268674fe6c29SRuslan Bukin 			if (errcode < 0)
268774fe6c29SRuslan Bukin 				return errcode;
268874fe6c29SRuslan Bukin 
268974fe6c29SRuslan Bukin 			break;
269074fe6c29SRuslan Bukin 
269174fe6c29SRuslan Bukin 		case ppt_mtc:
269274fe6c29SRuslan Bukin 			/* Keep track of time. */
269374fe6c29SRuslan Bukin 			errcode = pt_qry_apply_mtc(&time, &tcal,
269474fe6c29SRuslan Bukin 						   &packet.payload.mtc,
269574fe6c29SRuslan Bukin 						   &decoder->config);
269674fe6c29SRuslan Bukin 			if (errcode < 0)
269774fe6c29SRuslan Bukin 				return errcode;
269874fe6c29SRuslan Bukin 
269974fe6c29SRuslan Bukin 			break;
270074fe6c29SRuslan Bukin 
270174fe6c29SRuslan Bukin 		case ppt_cyc:
270274fe6c29SRuslan Bukin 			/* Keep track of time. */
270374fe6c29SRuslan Bukin 			errcode = pt_qry_apply_cyc(&time, &tcal,
270474fe6c29SRuslan Bukin 						   &packet.payload.cyc,
270574fe6c29SRuslan Bukin 						   &decoder->config);
270674fe6c29SRuslan Bukin 			if (errcode < 0)
270774fe6c29SRuslan Bukin 				return errcode;
270874fe6c29SRuslan Bukin 
270974fe6c29SRuslan Bukin 			break;
271074fe6c29SRuslan Bukin 		}
271174fe6c29SRuslan Bukin 	}
271274fe6c29SRuslan Bukin }
271374fe6c29SRuslan Bukin 
271474fe6c29SRuslan Bukin /* Handle erratum APL11.
271574fe6c29SRuslan Bukin  *
271674fe6c29SRuslan Bukin  * This function is called when we diagnose a bad packet while searching for a
271774fe6c29SRuslan Bukin  * FUP after an OVF.
271874fe6c29SRuslan Bukin  *
271974fe6c29SRuslan Bukin  * Due to erratum APL11 we may get an extra TIP.PGD after the OVF.  Find that
272074fe6c29SRuslan Bukin  * TIP.PGD and resume from there with tracing disabled.
272174fe6c29SRuslan Bukin  *
272274fe6c29SRuslan Bukin  * This will drop any CBR or MTC events.  We will update @decoder's timing state
272374fe6c29SRuslan Bukin  * on CBR but drop the event.
272474fe6c29SRuslan Bukin  *
272574fe6c29SRuslan Bukin  * Returns zero if the erratum was handled.
272674fe6c29SRuslan Bukin  * Returns a positive integer if the erratum was not handled.
272774fe6c29SRuslan Bukin  * Returns a negative pt_error_code otherwise.
272874fe6c29SRuslan Bukin  */
pt_qry_handle_apl11(struct pt_query_decoder * decoder)272974fe6c29SRuslan Bukin static int pt_qry_handle_apl11(struct pt_query_decoder *decoder)
273074fe6c29SRuslan Bukin {
273174fe6c29SRuslan Bukin 	struct pt_packet_decoder pkt;
273274fe6c29SRuslan Bukin 	uint64_t offset;
273374fe6c29SRuslan Bukin 	int status;
273474fe6c29SRuslan Bukin 
273574fe6c29SRuslan Bukin 	if (!decoder)
273674fe6c29SRuslan Bukin 		return -pte_internal;
273774fe6c29SRuslan Bukin 
273874fe6c29SRuslan Bukin 	status = pt_qry_get_offset(decoder, &offset);
273974fe6c29SRuslan Bukin 	if (status < 0)
274074fe6c29SRuslan Bukin 		return status;
274174fe6c29SRuslan Bukin 
274274fe6c29SRuslan Bukin 	status = pt_pkt_decoder_init(&pkt, &decoder->config);
274374fe6c29SRuslan Bukin 	if (status < 0)
274474fe6c29SRuslan Bukin 		return status;
274574fe6c29SRuslan Bukin 
274674fe6c29SRuslan Bukin 	status = pt_pkt_sync_set(&pkt, offset);
274774fe6c29SRuslan Bukin 	if (status >= 0)
274874fe6c29SRuslan Bukin 		status = apl11_apply(decoder, &pkt);
274974fe6c29SRuslan Bukin 
275074fe6c29SRuslan Bukin 	pt_pkt_decoder_fini(&pkt);
275174fe6c29SRuslan Bukin 	return status;
275274fe6c29SRuslan Bukin }
275374fe6c29SRuslan Bukin 
pt_pkt_find_ovf_fup(struct pt_packet_decoder * decoder)275474fe6c29SRuslan Bukin static int pt_pkt_find_ovf_fup(struct pt_packet_decoder *decoder)
275574fe6c29SRuslan Bukin {
275674fe6c29SRuslan Bukin 	for (;;) {
275774fe6c29SRuslan Bukin 		struct pt_packet packet;
275874fe6c29SRuslan Bukin 		int errcode;
275974fe6c29SRuslan Bukin 
276074fe6c29SRuslan Bukin 		errcode = pt_pkt_next(decoder, &packet, sizeof(packet));
276174fe6c29SRuslan Bukin 		if (errcode < 0)
276274fe6c29SRuslan Bukin 			return errcode;
276374fe6c29SRuslan Bukin 
276474fe6c29SRuslan Bukin 		switch (packet.type) {
276574fe6c29SRuslan Bukin 		case ppt_fup:
276674fe6c29SRuslan Bukin 			return 1;
276774fe6c29SRuslan Bukin 
276874fe6c29SRuslan Bukin 		case ppt_invalid:
276974fe6c29SRuslan Bukin 			return -pte_bad_opc;
277074fe6c29SRuslan Bukin 
277174fe6c29SRuslan Bukin 		case ppt_unknown:
277274fe6c29SRuslan Bukin 		case ppt_pad:
277374fe6c29SRuslan Bukin 		case ppt_mnt:
277474fe6c29SRuslan Bukin 		case ppt_cbr:
277574fe6c29SRuslan Bukin 		case ppt_tsc:
277674fe6c29SRuslan Bukin 		case ppt_tma:
277774fe6c29SRuslan Bukin 		case ppt_mtc:
277874fe6c29SRuslan Bukin 		case ppt_cyc:
277974fe6c29SRuslan Bukin 			continue;
278074fe6c29SRuslan Bukin 
278174fe6c29SRuslan Bukin 		case ppt_psb:
278274fe6c29SRuslan Bukin 		case ppt_tip_pge:
278374fe6c29SRuslan Bukin 		case ppt_mode:
278474fe6c29SRuslan Bukin 		case ppt_pip:
278574fe6c29SRuslan Bukin 		case ppt_vmcs:
278674fe6c29SRuslan Bukin 		case ppt_stop:
278774fe6c29SRuslan Bukin 		case ppt_ovf:
278874fe6c29SRuslan Bukin 		case ppt_exstop:
278974fe6c29SRuslan Bukin 		case ppt_mwait:
279074fe6c29SRuslan Bukin 		case ppt_pwre:
279174fe6c29SRuslan Bukin 		case ppt_pwrx:
279274fe6c29SRuslan Bukin 		case ppt_ptw:
279374fe6c29SRuslan Bukin 			return 0;
279474fe6c29SRuslan Bukin 
279574fe6c29SRuslan Bukin 		case ppt_psbend:
279674fe6c29SRuslan Bukin 		case ppt_tip:
279774fe6c29SRuslan Bukin 		case ppt_tip_pgd:
279874fe6c29SRuslan Bukin 		case ppt_tnt_8:
279974fe6c29SRuslan Bukin 		case ppt_tnt_64:
280074fe6c29SRuslan Bukin 			return -pte_bad_context;
280174fe6c29SRuslan Bukin 		}
280274fe6c29SRuslan Bukin 	}
280374fe6c29SRuslan Bukin }
280474fe6c29SRuslan Bukin 
280574fe6c29SRuslan Bukin /* Find a FUP to which the current OVF may bind.
280674fe6c29SRuslan Bukin  *
280774fe6c29SRuslan Bukin  * Scans the trace for a FUP or for a packet that indicates that tracing is
280874fe6c29SRuslan Bukin  * disabled.
280974fe6c29SRuslan Bukin  *
281074fe6c29SRuslan Bukin  * Return the relative offset of the packet following the found FUP on success.
281174fe6c29SRuslan Bukin  * Returns zero if no FUP is found and tracing is assumed to be disabled.
281274fe6c29SRuslan Bukin  * Returns a negative pt_error_code otherwise.
281374fe6c29SRuslan Bukin  */
pt_qry_find_ovf_fup(const struct pt_query_decoder * decoder)281474fe6c29SRuslan Bukin static int pt_qry_find_ovf_fup(const struct pt_query_decoder *decoder)
281574fe6c29SRuslan Bukin {
281674fe6c29SRuslan Bukin 	struct pt_packet_decoder pkt;
281774fe6c29SRuslan Bukin 	uint64_t begin, end, offset;
281874fe6c29SRuslan Bukin 	int status;
281974fe6c29SRuslan Bukin 
282074fe6c29SRuslan Bukin 	if (!decoder)
282174fe6c29SRuslan Bukin 		return -pte_internal;
282274fe6c29SRuslan Bukin 
282374fe6c29SRuslan Bukin 	status = pt_qry_get_offset(decoder, &begin);
282474fe6c29SRuslan Bukin 	if (status < 0)
282574fe6c29SRuslan Bukin 		return status;
282674fe6c29SRuslan Bukin 
282774fe6c29SRuslan Bukin 	status = pt_pkt_decoder_init(&pkt, &decoder->config);
282874fe6c29SRuslan Bukin 	if (status < 0)
282974fe6c29SRuslan Bukin 		return status;
283074fe6c29SRuslan Bukin 
283174fe6c29SRuslan Bukin 	status = pt_pkt_sync_set(&pkt, begin);
283274fe6c29SRuslan Bukin 	if (status >= 0) {
283374fe6c29SRuslan Bukin 		status = pt_pkt_find_ovf_fup(&pkt);
283474fe6c29SRuslan Bukin 		if (status > 0) {
283574fe6c29SRuslan Bukin 			status = pt_pkt_get_offset(&pkt, &end);
283674fe6c29SRuslan Bukin 			if (status < 0)
283774fe6c29SRuslan Bukin 				return status;
283874fe6c29SRuslan Bukin 
283974fe6c29SRuslan Bukin 			if (end <= begin)
284074fe6c29SRuslan Bukin 				return -pte_overflow;
284174fe6c29SRuslan Bukin 
284274fe6c29SRuslan Bukin 			offset = end - begin;
284374fe6c29SRuslan Bukin 			if (INT_MAX < offset)
284474fe6c29SRuslan Bukin 				return -pte_overflow;
284574fe6c29SRuslan Bukin 
284674fe6c29SRuslan Bukin 			status = (int) offset;
284774fe6c29SRuslan Bukin 		}
284874fe6c29SRuslan Bukin 	}
284974fe6c29SRuslan Bukin 
285074fe6c29SRuslan Bukin 	pt_pkt_decoder_fini(&pkt);
285174fe6c29SRuslan Bukin 	return status;
285274fe6c29SRuslan Bukin }
285374fe6c29SRuslan Bukin 
pt_qry_decode_ovf(struct pt_query_decoder * decoder)285474fe6c29SRuslan Bukin int pt_qry_decode_ovf(struct pt_query_decoder *decoder)
285574fe6c29SRuslan Bukin {
2856*85f87cf4SRuslan Bukin 	struct pt_time_cal tcal;
285774fe6c29SRuslan Bukin 	struct pt_time time;
285874fe6c29SRuslan Bukin 	int status, offset;
285974fe6c29SRuslan Bukin 
286074fe6c29SRuslan Bukin 	if (!decoder)
286174fe6c29SRuslan Bukin 		return -pte_internal;
286274fe6c29SRuslan Bukin 
286374fe6c29SRuslan Bukin 	status = pt_qry_process_pending_psb_events(decoder);
286474fe6c29SRuslan Bukin 	if (status < 0)
286574fe6c29SRuslan Bukin 		return status;
286674fe6c29SRuslan Bukin 
286774fe6c29SRuslan Bukin 	/* If we have any pending psbend events, we're done for now. */
286874fe6c29SRuslan Bukin 	if (status)
286974fe6c29SRuslan Bukin 		return 0;
287074fe6c29SRuslan Bukin 
287174fe6c29SRuslan Bukin 	/* Reset the decoder state but preserve timing. */
287274fe6c29SRuslan Bukin 	time = decoder->time;
2873*85f87cf4SRuslan Bukin 	tcal = decoder->tcal;
2874*85f87cf4SRuslan Bukin 
287574fe6c29SRuslan Bukin 	pt_qry_reset(decoder);
2876*85f87cf4SRuslan Bukin 
287774fe6c29SRuslan Bukin 	decoder->time = time;
2878*85f87cf4SRuslan Bukin 	if (decoder->config.flags.variant.query.keep_tcal_on_ovf) {
2879*85f87cf4SRuslan Bukin 		status = pt_tcal_update_ovf(&tcal, &decoder->config);
2880*85f87cf4SRuslan Bukin 		if (status < 0)
2881*85f87cf4SRuslan Bukin 			return status;
2882*85f87cf4SRuslan Bukin 
2883*85f87cf4SRuslan Bukin 		decoder->tcal = tcal;
2884*85f87cf4SRuslan Bukin 	}
288574fe6c29SRuslan Bukin 
288674fe6c29SRuslan Bukin 	/* We must consume the OVF before we search for the binding packet. */
288774fe6c29SRuslan Bukin 	decoder->pos += ptps_ovf;
288874fe6c29SRuslan Bukin 
288974fe6c29SRuslan Bukin 	/* Overflow binds to either FUP or TIP.PGE.
289074fe6c29SRuslan Bukin 	 *
289174fe6c29SRuslan Bukin 	 * If the overflow can be resolved while PacketEn=1 it binds to FUP.  We
289274fe6c29SRuslan Bukin 	 * can see timing packets between OVF anf FUP but that's it.
289374fe6c29SRuslan Bukin 	 *
289474fe6c29SRuslan Bukin 	 * Otherwise, PacketEn will be zero when the overflow resolves and OVF
289574fe6c29SRuslan Bukin 	 * binds to TIP.PGE.  There can be packets between OVF and TIP.PGE that
289674fe6c29SRuslan Bukin 	 * do not depend on PacketEn.
289774fe6c29SRuslan Bukin 	 *
289874fe6c29SRuslan Bukin 	 * We don't need to decode everything until TIP.PGE, however.  As soon
289974fe6c29SRuslan Bukin 	 * as we see a non-timing non-FUP packet, we know that tracing has been
290074fe6c29SRuslan Bukin 	 * disabled before the overflow resolves.
290174fe6c29SRuslan Bukin 	 */
290274fe6c29SRuslan Bukin 	offset = pt_qry_find_ovf_fup(decoder);
290374fe6c29SRuslan Bukin 	if (offset <= 0) {
290474fe6c29SRuslan Bukin 		/* Check for erratum SKD010.
290574fe6c29SRuslan Bukin 		 *
290674fe6c29SRuslan Bukin 		 * The FUP may have been dropped.  If we can figure out that
290774fe6c29SRuslan Bukin 		 * tracing is enabled and hence the FUP is missing, we resume
290874fe6c29SRuslan Bukin 		 * at a later packet and a different IP.
290974fe6c29SRuslan Bukin 		 */
291074fe6c29SRuslan Bukin 		if (decoder->config.errata.skd010) {
291174fe6c29SRuslan Bukin 			status = pt_qry_handle_skd010(decoder);
291274fe6c29SRuslan Bukin 			if (status <= 0)
291374fe6c29SRuslan Bukin 				return status;
291474fe6c29SRuslan Bukin 		}
291574fe6c29SRuslan Bukin 
291674fe6c29SRuslan Bukin 		/* Check for erratum APL11.
291774fe6c29SRuslan Bukin 		 *
291874fe6c29SRuslan Bukin 		 * We may have gotten an extra TIP.PGD, which should be
291974fe6c29SRuslan Bukin 		 * diagnosed by our search for a subsequent FUP.
292074fe6c29SRuslan Bukin 		 */
292174fe6c29SRuslan Bukin 		if (decoder->config.errata.apl11 &&
292274fe6c29SRuslan Bukin 		    (offset == -pte_bad_context)) {
292374fe6c29SRuslan Bukin 			status = pt_qry_handle_apl11(decoder);
292474fe6c29SRuslan Bukin 			if (status <= 0)
292574fe6c29SRuslan Bukin 				return status;
292674fe6c29SRuslan Bukin 		}
292774fe6c29SRuslan Bukin 
292874fe6c29SRuslan Bukin 		/* Report the original error from searching for the FUP packet
292974fe6c29SRuslan Bukin 		 * if we were not able to fix the trace.
293074fe6c29SRuslan Bukin 		 *
293174fe6c29SRuslan Bukin 		 * We treat an overflow at the end of the trace as standalone.
293274fe6c29SRuslan Bukin 		 */
293374fe6c29SRuslan Bukin 		if (offset < 0 && offset != -pte_eos)
293474fe6c29SRuslan Bukin 			return offset;
293574fe6c29SRuslan Bukin 
293674fe6c29SRuslan Bukin 		return pt_qry_event_ovf_disabled(decoder);
293774fe6c29SRuslan Bukin 	} else {
293874fe6c29SRuslan Bukin 		/* Check for erratum APL12.
293974fe6c29SRuslan Bukin 		 *
294074fe6c29SRuslan Bukin 		 * We may get an extra FUP even though the overflow resolved
294174fe6c29SRuslan Bukin 		 * with tracing disabled.
294274fe6c29SRuslan Bukin 		 */
294374fe6c29SRuslan Bukin 		if (decoder->config.errata.apl12) {
294474fe6c29SRuslan Bukin 			status = pt_qry_handle_apl12(decoder,
294574fe6c29SRuslan Bukin 						     (unsigned int) offset);
294674fe6c29SRuslan Bukin 			if (status <= 0)
294774fe6c29SRuslan Bukin 				return status;
294874fe6c29SRuslan Bukin 		}
294974fe6c29SRuslan Bukin 
295074fe6c29SRuslan Bukin 		return pt_qry_event_ovf_enabled(decoder);
295174fe6c29SRuslan Bukin 	}
295274fe6c29SRuslan Bukin }
295374fe6c29SRuslan Bukin 
pt_qry_decode_mode_exec(struct pt_query_decoder * decoder,const struct pt_packet_mode_exec * packet)295474fe6c29SRuslan Bukin static int pt_qry_decode_mode_exec(struct pt_query_decoder *decoder,
295574fe6c29SRuslan Bukin 				   const struct pt_packet_mode_exec *packet)
295674fe6c29SRuslan Bukin {
295774fe6c29SRuslan Bukin 	struct pt_event *event;
295874fe6c29SRuslan Bukin 
295974fe6c29SRuslan Bukin 	if (!decoder || !packet)
296074fe6c29SRuslan Bukin 		return -pte_internal;
296174fe6c29SRuslan Bukin 
296274fe6c29SRuslan Bukin 	/* MODE.EXEC binds to TIP. */
296374fe6c29SRuslan Bukin 	event = pt_evq_enqueue(&decoder->evq, evb_tip);
296474fe6c29SRuslan Bukin 	if (!event)
296574fe6c29SRuslan Bukin 		return -pte_nomem;
296674fe6c29SRuslan Bukin 
296774fe6c29SRuslan Bukin 	event->type = ptev_exec_mode;
296874fe6c29SRuslan Bukin 	event->variant.exec_mode.mode = pt_get_exec_mode(packet);
296974fe6c29SRuslan Bukin 
297074fe6c29SRuslan Bukin 	return pt_qry_event_time(event, decoder);
297174fe6c29SRuslan Bukin }
297274fe6c29SRuslan Bukin 
pt_qry_decode_mode_tsx(struct pt_query_decoder * decoder,const struct pt_packet_mode_tsx * packet)297374fe6c29SRuslan Bukin static int pt_qry_decode_mode_tsx(struct pt_query_decoder *decoder,
297474fe6c29SRuslan Bukin 				  const struct pt_packet_mode_tsx *packet)
297574fe6c29SRuslan Bukin {
297674fe6c29SRuslan Bukin 	struct pt_event *event;
297774fe6c29SRuslan Bukin 
297874fe6c29SRuslan Bukin 	if (!decoder || !packet)
297974fe6c29SRuslan Bukin 		return -pte_internal;
298074fe6c29SRuslan Bukin 
298174fe6c29SRuslan Bukin 	/* MODE.TSX is standalone if tracing is disabled. */
298274fe6c29SRuslan Bukin 	if (!decoder->enabled) {
298374fe6c29SRuslan Bukin 		event = pt_evq_standalone(&decoder->evq);
298474fe6c29SRuslan Bukin 		if (!event)
298574fe6c29SRuslan Bukin 			return -pte_internal;
298674fe6c29SRuslan Bukin 
298774fe6c29SRuslan Bukin 		/* We don't have an IP in this case. */
298874fe6c29SRuslan Bukin 		event->variant.tsx.ip = 0;
298974fe6c29SRuslan Bukin 		event->ip_suppressed = 1;
299074fe6c29SRuslan Bukin 
299174fe6c29SRuslan Bukin 		/* Publish the event. */
299274fe6c29SRuslan Bukin 		decoder->event = event;
299374fe6c29SRuslan Bukin 	} else {
299474fe6c29SRuslan Bukin 		/* MODE.TSX binds to FUP. */
299574fe6c29SRuslan Bukin 		event = pt_evq_enqueue(&decoder->evq, evb_fup);
299674fe6c29SRuslan Bukin 		if (!event)
299774fe6c29SRuslan Bukin 			return -pte_nomem;
299874fe6c29SRuslan Bukin 	}
299974fe6c29SRuslan Bukin 
300074fe6c29SRuslan Bukin 	event->type = ptev_tsx;
300174fe6c29SRuslan Bukin 	event->variant.tsx.speculative = packet->intx;
300274fe6c29SRuslan Bukin 	event->variant.tsx.aborted = packet->abrt;
300374fe6c29SRuslan Bukin 
300474fe6c29SRuslan Bukin 	return pt_qry_event_time(event, decoder);
300574fe6c29SRuslan Bukin }
300674fe6c29SRuslan Bukin 
pt_qry_decode_mode(struct pt_query_decoder * decoder)300774fe6c29SRuslan Bukin int pt_qry_decode_mode(struct pt_query_decoder *decoder)
300874fe6c29SRuslan Bukin {
300974fe6c29SRuslan Bukin 	struct pt_packet_mode packet;
301074fe6c29SRuslan Bukin 	int size, errcode;
301174fe6c29SRuslan Bukin 
301274fe6c29SRuslan Bukin 	if (!decoder)
301374fe6c29SRuslan Bukin 		return -pte_internal;
301474fe6c29SRuslan Bukin 
301574fe6c29SRuslan Bukin 	size = pt_pkt_read_mode(&packet, decoder->pos, &decoder->config);
301674fe6c29SRuslan Bukin 	if (size < 0)
301774fe6c29SRuslan Bukin 		return size;
301874fe6c29SRuslan Bukin 
301974fe6c29SRuslan Bukin 	errcode = 0;
302074fe6c29SRuslan Bukin 	switch (packet.leaf) {
302174fe6c29SRuslan Bukin 	case pt_mol_exec:
302274fe6c29SRuslan Bukin 		errcode = pt_qry_decode_mode_exec(decoder, &packet.bits.exec);
302374fe6c29SRuslan Bukin 		break;
302474fe6c29SRuslan Bukin 
302574fe6c29SRuslan Bukin 	case pt_mol_tsx:
302674fe6c29SRuslan Bukin 		errcode = pt_qry_decode_mode_tsx(decoder, &packet.bits.tsx);
302774fe6c29SRuslan Bukin 		break;
302874fe6c29SRuslan Bukin 	}
302974fe6c29SRuslan Bukin 
303074fe6c29SRuslan Bukin 	if (errcode < 0)
303174fe6c29SRuslan Bukin 		return errcode;
303274fe6c29SRuslan Bukin 
303374fe6c29SRuslan Bukin 	decoder->pos += size;
303474fe6c29SRuslan Bukin 	return 0;
303574fe6c29SRuslan Bukin }
303674fe6c29SRuslan Bukin 
pt_qry_header_mode(struct pt_query_decoder * decoder)303774fe6c29SRuslan Bukin int pt_qry_header_mode(struct pt_query_decoder *decoder)
303874fe6c29SRuslan Bukin {
303974fe6c29SRuslan Bukin 	struct pt_packet_mode packet;
304074fe6c29SRuslan Bukin 	struct pt_event *event;
304174fe6c29SRuslan Bukin 	int size;
304274fe6c29SRuslan Bukin 
304374fe6c29SRuslan Bukin 	if (!decoder)
304474fe6c29SRuslan Bukin 		return -pte_internal;
304574fe6c29SRuslan Bukin 
304674fe6c29SRuslan Bukin 	size = pt_pkt_read_mode(&packet, decoder->pos, &decoder->config);
304774fe6c29SRuslan Bukin 	if (size < 0)
304874fe6c29SRuslan Bukin 		return size;
304974fe6c29SRuslan Bukin 
305074fe6c29SRuslan Bukin 	/* Inside the header, events are reported at the end. */
305174fe6c29SRuslan Bukin 	event = pt_evq_enqueue(&decoder->evq, evb_psbend);
305274fe6c29SRuslan Bukin 	if (!event)
305374fe6c29SRuslan Bukin 		return -pte_nomem;
305474fe6c29SRuslan Bukin 
305574fe6c29SRuslan Bukin 	switch (packet.leaf) {
305674fe6c29SRuslan Bukin 	case pt_mol_exec:
305774fe6c29SRuslan Bukin 		event->type = ptev_exec_mode;
305874fe6c29SRuslan Bukin 		event->variant.exec_mode.mode =
305974fe6c29SRuslan Bukin 			pt_get_exec_mode(&packet.bits.exec);
306074fe6c29SRuslan Bukin 		break;
306174fe6c29SRuslan Bukin 
306274fe6c29SRuslan Bukin 	case pt_mol_tsx:
306374fe6c29SRuslan Bukin 		event->type = ptev_tsx;
306474fe6c29SRuslan Bukin 		event->variant.tsx.speculative = packet.bits.tsx.intx;
306574fe6c29SRuslan Bukin 		event->variant.tsx.aborted = packet.bits.tsx.abrt;
306674fe6c29SRuslan Bukin 		break;
306774fe6c29SRuslan Bukin 	}
306874fe6c29SRuslan Bukin 
306974fe6c29SRuslan Bukin 	decoder->pos += size;
307074fe6c29SRuslan Bukin 	return 0;
307174fe6c29SRuslan Bukin }
307274fe6c29SRuslan Bukin 
pt_qry_decode_psbend(struct pt_query_decoder * decoder)307374fe6c29SRuslan Bukin int pt_qry_decode_psbend(struct pt_query_decoder *decoder)
307474fe6c29SRuslan Bukin {
307574fe6c29SRuslan Bukin 	int status;
307674fe6c29SRuslan Bukin 
307774fe6c29SRuslan Bukin 	if (!decoder)
307874fe6c29SRuslan Bukin 		return -pte_internal;
307974fe6c29SRuslan Bukin 
308074fe6c29SRuslan Bukin 	status = pt_qry_process_pending_psb_events(decoder);
308174fe6c29SRuslan Bukin 	if (status < 0)
308274fe6c29SRuslan Bukin 		return status;
308374fe6c29SRuslan Bukin 
308474fe6c29SRuslan Bukin 	/* If we had any psb events, we're done for now. */
308574fe6c29SRuslan Bukin 	if (status)
308674fe6c29SRuslan Bukin 		return 0;
308774fe6c29SRuslan Bukin 
308874fe6c29SRuslan Bukin 	/* Skip the psbend extended opcode that we fetched before if no more
308974fe6c29SRuslan Bukin 	 * psbend events are pending.
309074fe6c29SRuslan Bukin 	 */
309174fe6c29SRuslan Bukin 	decoder->pos += ptps_psbend;
309274fe6c29SRuslan Bukin 	return 0;
309374fe6c29SRuslan Bukin }
309474fe6c29SRuslan Bukin 
pt_qry_decode_tsc(struct pt_query_decoder * decoder)309574fe6c29SRuslan Bukin int pt_qry_decode_tsc(struct pt_query_decoder *decoder)
309674fe6c29SRuslan Bukin {
309774fe6c29SRuslan Bukin 	struct pt_packet_tsc packet;
309874fe6c29SRuslan Bukin 	int size, errcode;
309974fe6c29SRuslan Bukin 
310074fe6c29SRuslan Bukin 	if (!decoder)
310174fe6c29SRuslan Bukin 		return -pte_internal;
310274fe6c29SRuslan Bukin 
310374fe6c29SRuslan Bukin 	size = pt_pkt_read_tsc(&packet, decoder->pos, &decoder->config);
310474fe6c29SRuslan Bukin 	if (size < 0)
310574fe6c29SRuslan Bukin 		return size;
310674fe6c29SRuslan Bukin 
310774fe6c29SRuslan Bukin 	errcode = pt_qry_apply_tsc(&decoder->time, &decoder->tcal,
310874fe6c29SRuslan Bukin 				   &packet, &decoder->config);
310974fe6c29SRuslan Bukin 	if (errcode < 0)
311074fe6c29SRuslan Bukin 		return errcode;
311174fe6c29SRuslan Bukin 
311274fe6c29SRuslan Bukin 	decoder->pos += size;
311374fe6c29SRuslan Bukin 	return 0;
311474fe6c29SRuslan Bukin }
311574fe6c29SRuslan Bukin 
pt_qry_header_tsc(struct pt_query_decoder * decoder)311674fe6c29SRuslan Bukin int pt_qry_header_tsc(struct pt_query_decoder *decoder)
311774fe6c29SRuslan Bukin {
311874fe6c29SRuslan Bukin 	struct pt_packet_tsc packet;
311974fe6c29SRuslan Bukin 	int size, errcode;
312074fe6c29SRuslan Bukin 
312174fe6c29SRuslan Bukin 	if (!decoder)
312274fe6c29SRuslan Bukin 		return -pte_internal;
312374fe6c29SRuslan Bukin 
312474fe6c29SRuslan Bukin 	size = pt_pkt_read_tsc(&packet, decoder->pos, &decoder->config);
312574fe6c29SRuslan Bukin 	if (size < 0)
312674fe6c29SRuslan Bukin 		return size;
312774fe6c29SRuslan Bukin 
312874fe6c29SRuslan Bukin 	errcode = pt_qry_apply_header_tsc(&decoder->time, &decoder->tcal,
312974fe6c29SRuslan Bukin 					  &packet, &decoder->config);
313074fe6c29SRuslan Bukin 	if (errcode < 0)
313174fe6c29SRuslan Bukin 		return errcode;
313274fe6c29SRuslan Bukin 
313374fe6c29SRuslan Bukin 	decoder->pos += size;
313474fe6c29SRuslan Bukin 	return 0;
313574fe6c29SRuslan Bukin }
313674fe6c29SRuslan Bukin 
pt_qry_decode_cbr(struct pt_query_decoder * decoder)313774fe6c29SRuslan Bukin int pt_qry_decode_cbr(struct pt_query_decoder *decoder)
313874fe6c29SRuslan Bukin {
313974fe6c29SRuslan Bukin 	struct pt_packet_cbr packet;
314074fe6c29SRuslan Bukin 	struct pt_event *event;
314174fe6c29SRuslan Bukin 	int size, errcode;
314274fe6c29SRuslan Bukin 
314374fe6c29SRuslan Bukin 	if (!decoder)
314474fe6c29SRuslan Bukin 		return -pte_internal;
314574fe6c29SRuslan Bukin 
314674fe6c29SRuslan Bukin 	size = pt_pkt_read_cbr(&packet, decoder->pos, &decoder->config);
314774fe6c29SRuslan Bukin 	if (size < 0)
314874fe6c29SRuslan Bukin 		return size;
314974fe6c29SRuslan Bukin 
315074fe6c29SRuslan Bukin 	errcode = pt_qry_apply_cbr(&decoder->time, &decoder->tcal,
315174fe6c29SRuslan Bukin 				   &packet, &decoder->config);
315274fe6c29SRuslan Bukin 	if (errcode < 0)
315374fe6c29SRuslan Bukin 		return errcode;
315474fe6c29SRuslan Bukin 
315574fe6c29SRuslan Bukin 	event = pt_evq_standalone(&decoder->evq);
315674fe6c29SRuslan Bukin 	if (!event)
315774fe6c29SRuslan Bukin 		return -pte_internal;
315874fe6c29SRuslan Bukin 
315974fe6c29SRuslan Bukin 	event->type = ptev_cbr;
316074fe6c29SRuslan Bukin 	event->variant.cbr.ratio = packet.ratio;
316174fe6c29SRuslan Bukin 
316274fe6c29SRuslan Bukin 	decoder->event = event;
316374fe6c29SRuslan Bukin 
316474fe6c29SRuslan Bukin 	errcode = pt_qry_event_time(event, decoder);
316574fe6c29SRuslan Bukin 	if (errcode < 0)
316674fe6c29SRuslan Bukin 		return errcode;
316774fe6c29SRuslan Bukin 
316874fe6c29SRuslan Bukin 	decoder->pos += size;
316974fe6c29SRuslan Bukin 	return 0;
317074fe6c29SRuslan Bukin }
317174fe6c29SRuslan Bukin 
pt_qry_header_cbr(struct pt_query_decoder * decoder)317274fe6c29SRuslan Bukin int pt_qry_header_cbr(struct pt_query_decoder *decoder)
317374fe6c29SRuslan Bukin {
317474fe6c29SRuslan Bukin 	struct pt_packet_cbr packet;
317574fe6c29SRuslan Bukin 	struct pt_event *event;
317674fe6c29SRuslan Bukin 	int size, errcode;
317774fe6c29SRuslan Bukin 
317874fe6c29SRuslan Bukin 	if (!decoder)
317974fe6c29SRuslan Bukin 		return -pte_internal;
318074fe6c29SRuslan Bukin 
318174fe6c29SRuslan Bukin 	size = pt_pkt_read_cbr(&packet, decoder->pos, &decoder->config);
318274fe6c29SRuslan Bukin 	if (size < 0)
318374fe6c29SRuslan Bukin 		return size;
318474fe6c29SRuslan Bukin 
318574fe6c29SRuslan Bukin 	errcode = pt_qry_apply_header_cbr(&decoder->time, &decoder->tcal,
318674fe6c29SRuslan Bukin 					  &packet, &decoder->config);
318774fe6c29SRuslan Bukin 	if (errcode < 0)
318874fe6c29SRuslan Bukin 		return errcode;
318974fe6c29SRuslan Bukin 
319074fe6c29SRuslan Bukin 	event = pt_evq_enqueue(&decoder->evq, evb_psbend);
319174fe6c29SRuslan Bukin 	if (!event)
319274fe6c29SRuslan Bukin 		return -pte_nomem;
319374fe6c29SRuslan Bukin 
319474fe6c29SRuslan Bukin 	event->type = ptev_cbr;
319574fe6c29SRuslan Bukin 	event->variant.cbr.ratio = packet.ratio;
319674fe6c29SRuslan Bukin 
319774fe6c29SRuslan Bukin 	decoder->pos += size;
319874fe6c29SRuslan Bukin 	return 0;
319974fe6c29SRuslan Bukin }
320074fe6c29SRuslan Bukin 
pt_qry_decode_tma(struct pt_query_decoder * decoder)320174fe6c29SRuslan Bukin int pt_qry_decode_tma(struct pt_query_decoder *decoder)
320274fe6c29SRuslan Bukin {
320374fe6c29SRuslan Bukin 	struct pt_packet_tma packet;
320474fe6c29SRuslan Bukin 	int size, errcode;
320574fe6c29SRuslan Bukin 
320674fe6c29SRuslan Bukin 	if (!decoder)
320774fe6c29SRuslan Bukin 		return -pte_internal;
320874fe6c29SRuslan Bukin 
320974fe6c29SRuslan Bukin 	size = pt_pkt_read_tma(&packet, decoder->pos, &decoder->config);
321074fe6c29SRuslan Bukin 	if (size < 0)
321174fe6c29SRuslan Bukin 		return size;
321274fe6c29SRuslan Bukin 
321374fe6c29SRuslan Bukin 	errcode = pt_qry_apply_tma(&decoder->time, &decoder->tcal,
321474fe6c29SRuslan Bukin 				   &packet, &decoder->config);
321574fe6c29SRuslan Bukin 	if (errcode < 0)
321674fe6c29SRuslan Bukin 		return errcode;
321774fe6c29SRuslan Bukin 
321874fe6c29SRuslan Bukin 	decoder->pos += size;
321974fe6c29SRuslan Bukin 	return 0;
322074fe6c29SRuslan Bukin }
322174fe6c29SRuslan Bukin 
pt_qry_decode_mtc(struct pt_query_decoder * decoder)322274fe6c29SRuslan Bukin int pt_qry_decode_mtc(struct pt_query_decoder *decoder)
322374fe6c29SRuslan Bukin {
322474fe6c29SRuslan Bukin 	struct pt_packet_mtc packet;
322574fe6c29SRuslan Bukin 	int size, errcode;
322674fe6c29SRuslan Bukin 
322774fe6c29SRuslan Bukin 	if (!decoder)
322874fe6c29SRuslan Bukin 		return -pte_internal;
322974fe6c29SRuslan Bukin 
323074fe6c29SRuslan Bukin 	size = pt_pkt_read_mtc(&packet, decoder->pos, &decoder->config);
323174fe6c29SRuslan Bukin 	if (size < 0)
323274fe6c29SRuslan Bukin 		return size;
323374fe6c29SRuslan Bukin 
323474fe6c29SRuslan Bukin 	errcode = pt_qry_apply_mtc(&decoder->time, &decoder->tcal,
323574fe6c29SRuslan Bukin 				   &packet, &decoder->config);
323674fe6c29SRuslan Bukin 	if (errcode < 0)
323774fe6c29SRuslan Bukin 		return errcode;
323874fe6c29SRuslan Bukin 
323974fe6c29SRuslan Bukin 	decoder->pos += size;
324074fe6c29SRuslan Bukin 	return 0;
324174fe6c29SRuslan Bukin }
324274fe6c29SRuslan Bukin 
check_erratum_skd007(struct pt_query_decoder * decoder,const struct pt_packet_cyc * packet,int size)324374fe6c29SRuslan Bukin static int check_erratum_skd007(struct pt_query_decoder *decoder,
324474fe6c29SRuslan Bukin 				const struct pt_packet_cyc *packet, int size)
324574fe6c29SRuslan Bukin {
324674fe6c29SRuslan Bukin 	const uint8_t *pos;
324774fe6c29SRuslan Bukin 	uint16_t payload;
324874fe6c29SRuslan Bukin 
324974fe6c29SRuslan Bukin 	if (!decoder || !packet || size < 0)
325074fe6c29SRuslan Bukin 		return -pte_internal;
325174fe6c29SRuslan Bukin 
325274fe6c29SRuslan Bukin 	/* It must be a 2-byte CYC. */
325374fe6c29SRuslan Bukin 	if (size != 2)
325474fe6c29SRuslan Bukin 		return 0;
325574fe6c29SRuslan Bukin 
325674fe6c29SRuslan Bukin 	payload = (uint16_t) packet->value;
325774fe6c29SRuslan Bukin 
325874fe6c29SRuslan Bukin 	/* The 2nd byte of the CYC payload must look like an ext opcode. */
325974fe6c29SRuslan Bukin 	if ((payload & ~0x1f) != 0x20)
326074fe6c29SRuslan Bukin 		return 0;
326174fe6c29SRuslan Bukin 
326274fe6c29SRuslan Bukin 	/* Skip this CYC packet. */
326374fe6c29SRuslan Bukin 	pos = decoder->pos + size;
326474fe6c29SRuslan Bukin 	if (decoder->config.end <= pos)
326574fe6c29SRuslan Bukin 		return 0;
326674fe6c29SRuslan Bukin 
326774fe6c29SRuslan Bukin 	/* See if we got a second CYC that looks like an OVF ext opcode. */
326874fe6c29SRuslan Bukin 	if (*pos != pt_ext_ovf)
326974fe6c29SRuslan Bukin 		return 0;
327074fe6c29SRuslan Bukin 
327174fe6c29SRuslan Bukin 	/* We shouldn't get back-to-back CYCs unless they are sent when the
327274fe6c29SRuslan Bukin 	 * counter wraps around.  In this case, we'd expect a full payload.
327374fe6c29SRuslan Bukin 	 *
327474fe6c29SRuslan Bukin 	 * Since we got two non-full CYC packets, we assume the erratum hit.
327574fe6c29SRuslan Bukin 	 */
327674fe6c29SRuslan Bukin 
327774fe6c29SRuslan Bukin 	return 1;
327874fe6c29SRuslan Bukin }
327974fe6c29SRuslan Bukin 
pt_qry_decode_cyc(struct pt_query_decoder * decoder)328074fe6c29SRuslan Bukin int pt_qry_decode_cyc(struct pt_query_decoder *decoder)
328174fe6c29SRuslan Bukin {
328274fe6c29SRuslan Bukin 	struct pt_packet_cyc packet;
328374fe6c29SRuslan Bukin 	struct pt_config *config;
328474fe6c29SRuslan Bukin 	int size, errcode;
328574fe6c29SRuslan Bukin 
328674fe6c29SRuslan Bukin 	if (!decoder)
328774fe6c29SRuslan Bukin 		return -pte_internal;
328874fe6c29SRuslan Bukin 
328974fe6c29SRuslan Bukin 	config = &decoder->config;
329074fe6c29SRuslan Bukin 
329174fe6c29SRuslan Bukin 	size = pt_pkt_read_cyc(&packet, decoder->pos, config);
329274fe6c29SRuslan Bukin 	if (size < 0)
329374fe6c29SRuslan Bukin 		return size;
329474fe6c29SRuslan Bukin 
329574fe6c29SRuslan Bukin 	if (config->errata.skd007) {
329674fe6c29SRuslan Bukin 		errcode = check_erratum_skd007(decoder, &packet, size);
329774fe6c29SRuslan Bukin 		if (errcode < 0)
329874fe6c29SRuslan Bukin 			return errcode;
329974fe6c29SRuslan Bukin 
330074fe6c29SRuslan Bukin 		/* If the erratum hits, we ignore the partial CYC and instead
330174fe6c29SRuslan Bukin 		 * process the OVF following/overlapping it.
330274fe6c29SRuslan Bukin 		 */
330374fe6c29SRuslan Bukin 		if (errcode) {
330474fe6c29SRuslan Bukin 			/* We skip the first byte of the CYC, which brings us
330574fe6c29SRuslan Bukin 			 * to the beginning of the OVF packet.
330674fe6c29SRuslan Bukin 			 */
330774fe6c29SRuslan Bukin 			decoder->pos += 1;
330874fe6c29SRuslan Bukin 			return 0;
330974fe6c29SRuslan Bukin 		}
331074fe6c29SRuslan Bukin 	}
331174fe6c29SRuslan Bukin 
331274fe6c29SRuslan Bukin 	errcode = pt_qry_apply_cyc(&decoder->time, &decoder->tcal,
331374fe6c29SRuslan Bukin 				   &packet, config);
331474fe6c29SRuslan Bukin 	if (errcode < 0)
331574fe6c29SRuslan Bukin 		return errcode;
331674fe6c29SRuslan Bukin 
331774fe6c29SRuslan Bukin 	decoder->pos += size;
331874fe6c29SRuslan Bukin 	return 0;
331974fe6c29SRuslan Bukin }
332074fe6c29SRuslan Bukin 
pt_qry_decode_stop(struct pt_query_decoder * decoder)332174fe6c29SRuslan Bukin int pt_qry_decode_stop(struct pt_query_decoder *decoder)
332274fe6c29SRuslan Bukin {
332374fe6c29SRuslan Bukin 	struct pt_event *event;
332474fe6c29SRuslan Bukin 	int errcode;
332574fe6c29SRuslan Bukin 
332674fe6c29SRuslan Bukin 	if (!decoder)
332774fe6c29SRuslan Bukin 		return -pte_internal;
332874fe6c29SRuslan Bukin 
332974fe6c29SRuslan Bukin 	/* Stop events are reported immediately. */
333074fe6c29SRuslan Bukin 	event = pt_evq_standalone(&decoder->evq);
333174fe6c29SRuslan Bukin 	if (!event)
333274fe6c29SRuslan Bukin 		return -pte_internal;
333374fe6c29SRuslan Bukin 
333474fe6c29SRuslan Bukin 	event->type = ptev_stop;
333574fe6c29SRuslan Bukin 
333674fe6c29SRuslan Bukin 	decoder->event = event;
333774fe6c29SRuslan Bukin 
333874fe6c29SRuslan Bukin 	errcode = pt_qry_event_time(event, decoder);
333974fe6c29SRuslan Bukin 	if (errcode < 0)
334074fe6c29SRuslan Bukin 		return errcode;
334174fe6c29SRuslan Bukin 
334274fe6c29SRuslan Bukin 	decoder->pos += ptps_stop;
334374fe6c29SRuslan Bukin 	return 0;
334474fe6c29SRuslan Bukin }
334574fe6c29SRuslan Bukin 
pt_qry_header_vmcs(struct pt_query_decoder * decoder)334674fe6c29SRuslan Bukin int pt_qry_header_vmcs(struct pt_query_decoder *decoder)
334774fe6c29SRuslan Bukin {
334874fe6c29SRuslan Bukin 	struct pt_packet_vmcs packet;
334974fe6c29SRuslan Bukin 	struct pt_event *event;
335074fe6c29SRuslan Bukin 	int size;
335174fe6c29SRuslan Bukin 
335274fe6c29SRuslan Bukin 	if (!decoder)
335374fe6c29SRuslan Bukin 		return -pte_internal;
335474fe6c29SRuslan Bukin 
335574fe6c29SRuslan Bukin 	size = pt_pkt_read_vmcs(&packet, decoder->pos, &decoder->config);
335674fe6c29SRuslan Bukin 	if (size < 0)
335774fe6c29SRuslan Bukin 		return size;
335874fe6c29SRuslan Bukin 
335974fe6c29SRuslan Bukin 	event = pt_evq_enqueue(&decoder->evq, evb_psbend);
336074fe6c29SRuslan Bukin 	if (!event)
336174fe6c29SRuslan Bukin 		return -pte_nomem;
336274fe6c29SRuslan Bukin 
336374fe6c29SRuslan Bukin 	event->type = ptev_async_vmcs;
336474fe6c29SRuslan Bukin 	event->variant.async_vmcs.base = packet.base;
336574fe6c29SRuslan Bukin 
336674fe6c29SRuslan Bukin 	decoder->pos += size;
336774fe6c29SRuslan Bukin 	return 0;
336874fe6c29SRuslan Bukin }
336974fe6c29SRuslan Bukin 
pt_qry_decode_vmcs(struct pt_query_decoder * decoder)337074fe6c29SRuslan Bukin int pt_qry_decode_vmcs(struct pt_query_decoder *decoder)
337174fe6c29SRuslan Bukin {
337274fe6c29SRuslan Bukin 	struct pt_packet_vmcs packet;
337374fe6c29SRuslan Bukin 	struct pt_event *event;
337474fe6c29SRuslan Bukin 	int size, errcode;
337574fe6c29SRuslan Bukin 
337674fe6c29SRuslan Bukin 	if (!decoder)
337774fe6c29SRuslan Bukin 		return -pte_internal;
337874fe6c29SRuslan Bukin 
337974fe6c29SRuslan Bukin 	size = pt_pkt_read_vmcs(&packet, decoder->pos, &decoder->config);
338074fe6c29SRuslan Bukin 	if (size < 0)
338174fe6c29SRuslan Bukin 		return size;
338274fe6c29SRuslan Bukin 
338374fe6c29SRuslan Bukin 	/* VMCS events bind to the same IP as an in-flight async paging event.
338474fe6c29SRuslan Bukin 	 *
338574fe6c29SRuslan Bukin 	 * In that case, the VMCS event should be applied first.  We reorder
338674fe6c29SRuslan Bukin 	 * events here to simplify the life of higher layers.
338774fe6c29SRuslan Bukin 	 */
338874fe6c29SRuslan Bukin 	event = pt_evq_find(&decoder->evq, evb_tip, ptev_async_paging);
338974fe6c29SRuslan Bukin 	if (event) {
339074fe6c29SRuslan Bukin 		struct pt_event *paging;
339174fe6c29SRuslan Bukin 
339274fe6c29SRuslan Bukin 		paging = pt_evq_enqueue(&decoder->evq, evb_tip);
339374fe6c29SRuslan Bukin 		if (!paging)
339474fe6c29SRuslan Bukin 			return -pte_nomem;
339574fe6c29SRuslan Bukin 
339674fe6c29SRuslan Bukin 		*paging = *event;
339774fe6c29SRuslan Bukin 
339874fe6c29SRuslan Bukin 		event->type = ptev_async_vmcs;
339974fe6c29SRuslan Bukin 		event->variant.async_vmcs.base = packet.base;
340074fe6c29SRuslan Bukin 
340174fe6c29SRuslan Bukin 		decoder->pos += size;
340274fe6c29SRuslan Bukin 		return 0;
340374fe6c29SRuslan Bukin 	}
340474fe6c29SRuslan Bukin 
340574fe6c29SRuslan Bukin 	/* VMCS events bind to the same TIP packet as an in-flight async
340674fe6c29SRuslan Bukin 	 * branch event.
340774fe6c29SRuslan Bukin 	 */
340874fe6c29SRuslan Bukin 	event = pt_evq_find(&decoder->evq, evb_tip, ptev_async_branch);
340974fe6c29SRuslan Bukin 	if (event) {
341074fe6c29SRuslan Bukin 		event = pt_evq_enqueue(&decoder->evq, evb_tip);
341174fe6c29SRuslan Bukin 		if (!event)
341274fe6c29SRuslan Bukin 			return -pte_nomem;
341374fe6c29SRuslan Bukin 
341474fe6c29SRuslan Bukin 		event->type = ptev_async_vmcs;
341574fe6c29SRuslan Bukin 		event->variant.async_vmcs.base = packet.base;
341674fe6c29SRuslan Bukin 
341774fe6c29SRuslan Bukin 		decoder->pos += size;
341874fe6c29SRuslan Bukin 		return 0;
341974fe6c29SRuslan Bukin 	}
342074fe6c29SRuslan Bukin 
342174fe6c29SRuslan Bukin 	/* VMCS events that do not bind to an in-flight async event are
342274fe6c29SRuslan Bukin 	 * stand-alone.
342374fe6c29SRuslan Bukin 	 */
342474fe6c29SRuslan Bukin 	event = pt_evq_standalone(&decoder->evq);
342574fe6c29SRuslan Bukin 	if (!event)
342674fe6c29SRuslan Bukin 		return -pte_internal;
342774fe6c29SRuslan Bukin 
342874fe6c29SRuslan Bukin 	event->type = ptev_vmcs;
342974fe6c29SRuslan Bukin 	event->variant.vmcs.base = packet.base;
343074fe6c29SRuslan Bukin 
343174fe6c29SRuslan Bukin 	decoder->event = event;
343274fe6c29SRuslan Bukin 
343374fe6c29SRuslan Bukin 	errcode = pt_qry_event_time(event, decoder);
343474fe6c29SRuslan Bukin 	if (errcode < 0)
343574fe6c29SRuslan Bukin 		return errcode;
343674fe6c29SRuslan Bukin 
343774fe6c29SRuslan Bukin 	decoder->pos += size;
343874fe6c29SRuslan Bukin 	return 0;
343974fe6c29SRuslan Bukin }
344074fe6c29SRuslan Bukin 
pt_qry_decode_mnt(struct pt_query_decoder * decoder)344174fe6c29SRuslan Bukin int pt_qry_decode_mnt(struct pt_query_decoder *decoder)
344274fe6c29SRuslan Bukin {
344374fe6c29SRuslan Bukin 	struct pt_packet_mnt packet;
344474fe6c29SRuslan Bukin 	struct pt_event *event;
344574fe6c29SRuslan Bukin 	int size, errcode;
344674fe6c29SRuslan Bukin 
344774fe6c29SRuslan Bukin 	if (!decoder)
344874fe6c29SRuslan Bukin 		return -pte_internal;
344974fe6c29SRuslan Bukin 
345074fe6c29SRuslan Bukin 	size = pt_pkt_read_mnt(&packet, decoder->pos, &decoder->config);
345174fe6c29SRuslan Bukin 	if (size < 0)
345274fe6c29SRuslan Bukin 		return size;
345374fe6c29SRuslan Bukin 
345474fe6c29SRuslan Bukin 	event = pt_evq_standalone(&decoder->evq);
345574fe6c29SRuslan Bukin 	if (!event)
345674fe6c29SRuslan Bukin 		return -pte_internal;
345774fe6c29SRuslan Bukin 
345874fe6c29SRuslan Bukin 	event->type = ptev_mnt;
345974fe6c29SRuslan Bukin 	event->variant.mnt.payload = packet.payload;
346074fe6c29SRuslan Bukin 
346174fe6c29SRuslan Bukin 	decoder->event = event;
346274fe6c29SRuslan Bukin 
346374fe6c29SRuslan Bukin 	errcode = pt_qry_event_time(event, decoder);
346474fe6c29SRuslan Bukin 	if (errcode < 0)
346574fe6c29SRuslan Bukin 		return errcode;
346674fe6c29SRuslan Bukin 
346774fe6c29SRuslan Bukin 	decoder->pos += size;
346874fe6c29SRuslan Bukin 
346974fe6c29SRuslan Bukin 	return 0;
347074fe6c29SRuslan Bukin }
347174fe6c29SRuslan Bukin 
pt_qry_header_mnt(struct pt_query_decoder * decoder)347274fe6c29SRuslan Bukin int pt_qry_header_mnt(struct pt_query_decoder *decoder)
347374fe6c29SRuslan Bukin {
347474fe6c29SRuslan Bukin 	struct pt_packet_mnt packet;
347574fe6c29SRuslan Bukin 	struct pt_event *event;
347674fe6c29SRuslan Bukin 	int size;
347774fe6c29SRuslan Bukin 
347874fe6c29SRuslan Bukin 	if (!decoder)
347974fe6c29SRuslan Bukin 		return -pte_internal;
348074fe6c29SRuslan Bukin 
348174fe6c29SRuslan Bukin 	size = pt_pkt_read_mnt(&packet, decoder->pos, &decoder->config);
348274fe6c29SRuslan Bukin 	if (size < 0)
348374fe6c29SRuslan Bukin 		return size;
348474fe6c29SRuslan Bukin 
348574fe6c29SRuslan Bukin 	event = pt_evq_enqueue(&decoder->evq, evb_psbend);
348674fe6c29SRuslan Bukin 	if (!event)
348774fe6c29SRuslan Bukin 		return -pte_nomem;
348874fe6c29SRuslan Bukin 
348974fe6c29SRuslan Bukin 	event->type = ptev_mnt;
349074fe6c29SRuslan Bukin 	event->variant.mnt.payload = packet.payload;
349174fe6c29SRuslan Bukin 
349274fe6c29SRuslan Bukin 	decoder->pos += size;
349374fe6c29SRuslan Bukin 
349474fe6c29SRuslan Bukin 	return 0;
349574fe6c29SRuslan Bukin }
349674fe6c29SRuslan Bukin 
pt_qry_decode_exstop(struct pt_query_decoder * decoder)349774fe6c29SRuslan Bukin int pt_qry_decode_exstop(struct pt_query_decoder *decoder)
349874fe6c29SRuslan Bukin {
349974fe6c29SRuslan Bukin 	struct pt_packet_exstop packet;
350074fe6c29SRuslan Bukin 	struct pt_event *event;
350174fe6c29SRuslan Bukin 	int size;
350274fe6c29SRuslan Bukin 
350374fe6c29SRuslan Bukin 	if (!decoder)
350474fe6c29SRuslan Bukin 		return -pte_internal;
350574fe6c29SRuslan Bukin 
350674fe6c29SRuslan Bukin 	size = pt_pkt_read_exstop(&packet, decoder->pos, &decoder->config);
350774fe6c29SRuslan Bukin 	if (size < 0)
350874fe6c29SRuslan Bukin 		return size;
350974fe6c29SRuslan Bukin 
351074fe6c29SRuslan Bukin 	if (packet.ip) {
351174fe6c29SRuslan Bukin 		event = pt_evq_enqueue(&decoder->evq, evb_fup);
351274fe6c29SRuslan Bukin 		if (!event)
351374fe6c29SRuslan Bukin 			return -pte_internal;
351474fe6c29SRuslan Bukin 
351574fe6c29SRuslan Bukin 		event->type = ptev_exstop;
351674fe6c29SRuslan Bukin 	} else {
351774fe6c29SRuslan Bukin 		event = pt_evq_standalone(&decoder->evq);
351874fe6c29SRuslan Bukin 		if (!event)
351974fe6c29SRuslan Bukin 			return -pte_internal;
352074fe6c29SRuslan Bukin 
352174fe6c29SRuslan Bukin 		event->type = ptev_exstop;
352274fe6c29SRuslan Bukin 
352374fe6c29SRuslan Bukin 		event->ip_suppressed = 1;
352474fe6c29SRuslan Bukin 		event->variant.exstop.ip = 0ull;
352574fe6c29SRuslan Bukin 
352674fe6c29SRuslan Bukin 		decoder->event = event;
352774fe6c29SRuslan Bukin 	}
352874fe6c29SRuslan Bukin 
352974fe6c29SRuslan Bukin 	decoder->pos += size;
353074fe6c29SRuslan Bukin 	return 0;
353174fe6c29SRuslan Bukin }
353274fe6c29SRuslan Bukin 
pt_qry_decode_mwait(struct pt_query_decoder * decoder)353374fe6c29SRuslan Bukin int pt_qry_decode_mwait(struct pt_query_decoder *decoder)
353474fe6c29SRuslan Bukin {
353574fe6c29SRuslan Bukin 	struct pt_packet_mwait packet;
353674fe6c29SRuslan Bukin 	struct pt_event *event;
353774fe6c29SRuslan Bukin 	int size;
353874fe6c29SRuslan Bukin 
353974fe6c29SRuslan Bukin 	if (!decoder)
354074fe6c29SRuslan Bukin 		return -pte_internal;
354174fe6c29SRuslan Bukin 
354274fe6c29SRuslan Bukin 	size = pt_pkt_read_mwait(&packet, decoder->pos, &decoder->config);
354374fe6c29SRuslan Bukin 	if (size < 0)
354474fe6c29SRuslan Bukin 		return size;
354574fe6c29SRuslan Bukin 
354674fe6c29SRuslan Bukin 	event = pt_evq_enqueue(&decoder->evq, evb_fup);
354774fe6c29SRuslan Bukin 	if (!event)
354874fe6c29SRuslan Bukin 		return -pte_internal;
354974fe6c29SRuslan Bukin 
355074fe6c29SRuslan Bukin 	event->type = ptev_mwait;
355174fe6c29SRuslan Bukin 	event->variant.mwait.hints = packet.hints;
355274fe6c29SRuslan Bukin 	event->variant.mwait.ext = packet.ext;
355374fe6c29SRuslan Bukin 
355474fe6c29SRuslan Bukin 	decoder->pos += size;
355574fe6c29SRuslan Bukin 	return 0;
355674fe6c29SRuslan Bukin }
355774fe6c29SRuslan Bukin 
pt_qry_decode_pwre(struct pt_query_decoder * decoder)355874fe6c29SRuslan Bukin int pt_qry_decode_pwre(struct pt_query_decoder *decoder)
355974fe6c29SRuslan Bukin {
356074fe6c29SRuslan Bukin 	struct pt_packet_pwre packet;
356174fe6c29SRuslan Bukin 	struct pt_event *event;
356274fe6c29SRuslan Bukin 	int size;
356374fe6c29SRuslan Bukin 
356474fe6c29SRuslan Bukin 	if (!decoder)
356574fe6c29SRuslan Bukin 		return -pte_internal;
356674fe6c29SRuslan Bukin 
356774fe6c29SRuslan Bukin 	size = pt_pkt_read_pwre(&packet, decoder->pos, &decoder->config);
356874fe6c29SRuslan Bukin 	if (size < 0)
356974fe6c29SRuslan Bukin 		return size;
357074fe6c29SRuslan Bukin 
357174fe6c29SRuslan Bukin 	event = pt_evq_standalone(&decoder->evq);
357274fe6c29SRuslan Bukin 	if (!event)
357374fe6c29SRuslan Bukin 		return -pte_internal;
357474fe6c29SRuslan Bukin 
357574fe6c29SRuslan Bukin 	event->type = ptev_pwre;
357674fe6c29SRuslan Bukin 	event->variant.pwre.state = packet.state;
357774fe6c29SRuslan Bukin 	event->variant.pwre.sub_state = packet.sub_state;
357874fe6c29SRuslan Bukin 
357974fe6c29SRuslan Bukin 	if (packet.hw)
358074fe6c29SRuslan Bukin 		event->variant.pwre.hw = 1;
358174fe6c29SRuslan Bukin 
358274fe6c29SRuslan Bukin 	decoder->event = event;
358374fe6c29SRuslan Bukin 
358474fe6c29SRuslan Bukin 	decoder->pos += size;
358574fe6c29SRuslan Bukin 	return 0;
358674fe6c29SRuslan Bukin }
358774fe6c29SRuslan Bukin 
pt_qry_decode_pwrx(struct pt_query_decoder * decoder)358874fe6c29SRuslan Bukin int pt_qry_decode_pwrx(struct pt_query_decoder *decoder)
358974fe6c29SRuslan Bukin {
359074fe6c29SRuslan Bukin 	struct pt_packet_pwrx packet;
359174fe6c29SRuslan Bukin 	struct pt_event *event;
359274fe6c29SRuslan Bukin 	int size;
359374fe6c29SRuslan Bukin 
359474fe6c29SRuslan Bukin 	if (!decoder)
359574fe6c29SRuslan Bukin 		return -pte_internal;
359674fe6c29SRuslan Bukin 
359774fe6c29SRuslan Bukin 	size = pt_pkt_read_pwrx(&packet, decoder->pos, &decoder->config);
359874fe6c29SRuslan Bukin 	if (size < 0)
359974fe6c29SRuslan Bukin 		return size;
360074fe6c29SRuslan Bukin 
360174fe6c29SRuslan Bukin 	event = pt_evq_standalone(&decoder->evq);
360274fe6c29SRuslan Bukin 	if (!event)
360374fe6c29SRuslan Bukin 		return -pte_internal;
360474fe6c29SRuslan Bukin 
360574fe6c29SRuslan Bukin 	event->type = ptev_pwrx;
360674fe6c29SRuslan Bukin 	event->variant.pwrx.last = packet.last;
360774fe6c29SRuslan Bukin 	event->variant.pwrx.deepest = packet.deepest;
360874fe6c29SRuslan Bukin 
360974fe6c29SRuslan Bukin 	if (packet.interrupt)
361074fe6c29SRuslan Bukin 		event->variant.pwrx.interrupt = 1;
361174fe6c29SRuslan Bukin 	if (packet.store)
361274fe6c29SRuslan Bukin 		event->variant.pwrx.store = 1;
361374fe6c29SRuslan Bukin 	if (packet.autonomous)
361474fe6c29SRuslan Bukin 		event->variant.pwrx.autonomous = 1;
361574fe6c29SRuslan Bukin 
361674fe6c29SRuslan Bukin 	decoder->event = event;
361774fe6c29SRuslan Bukin 
361874fe6c29SRuslan Bukin 	decoder->pos += size;
361974fe6c29SRuslan Bukin 	return 0;
362074fe6c29SRuslan Bukin }
362174fe6c29SRuslan Bukin 
pt_qry_decode_ptw(struct pt_query_decoder * decoder)362274fe6c29SRuslan Bukin int pt_qry_decode_ptw(struct pt_query_decoder *decoder)
362374fe6c29SRuslan Bukin {
362474fe6c29SRuslan Bukin 	struct pt_packet_ptw packet;
362574fe6c29SRuslan Bukin 	struct pt_event *event;
362674fe6c29SRuslan Bukin 	int size, pls;
362774fe6c29SRuslan Bukin 
362874fe6c29SRuslan Bukin 	if (!decoder)
362974fe6c29SRuslan Bukin 		return -pte_internal;
363074fe6c29SRuslan Bukin 
363174fe6c29SRuslan Bukin 	size = pt_pkt_read_ptw(&packet, decoder->pos, &decoder->config);
363274fe6c29SRuslan Bukin 	if (size < 0)
363374fe6c29SRuslan Bukin 		return size;
363474fe6c29SRuslan Bukin 
363574fe6c29SRuslan Bukin 	pls = pt_ptw_size(packet.plc);
363674fe6c29SRuslan Bukin 	if (pls < 0)
363774fe6c29SRuslan Bukin 		return pls;
363874fe6c29SRuslan Bukin 
363974fe6c29SRuslan Bukin 	if (packet.ip) {
364074fe6c29SRuslan Bukin 		event = pt_evq_enqueue(&decoder->evq, evb_fup);
364174fe6c29SRuslan Bukin 		if (!event)
364274fe6c29SRuslan Bukin 			return -pte_internal;
364374fe6c29SRuslan Bukin 	} else {
364474fe6c29SRuslan Bukin 		event = pt_evq_standalone(&decoder->evq);
364574fe6c29SRuslan Bukin 		if (!event)
364674fe6c29SRuslan Bukin 			return -pte_internal;
364774fe6c29SRuslan Bukin 
364874fe6c29SRuslan Bukin 		event->ip_suppressed = 1;
364974fe6c29SRuslan Bukin 
365074fe6c29SRuslan Bukin 		decoder->event = event;
365174fe6c29SRuslan Bukin 	}
365274fe6c29SRuslan Bukin 
365374fe6c29SRuslan Bukin 	event->type = ptev_ptwrite;
365474fe6c29SRuslan Bukin 	event->variant.ptwrite.size = (uint8_t) pls;
365574fe6c29SRuslan Bukin 	event->variant.ptwrite.payload = packet.payload;
365674fe6c29SRuslan Bukin 
365774fe6c29SRuslan Bukin 	decoder->pos += size;
365874fe6c29SRuslan Bukin 	return 0;
365974fe6c29SRuslan Bukin }
3660