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