1*74fe6c29SRuslan Bukin /*
2*74fe6c29SRuslan Bukin  * Copyright (c) 2016-2018, Intel Corporation
3*74fe6c29SRuslan Bukin  *
4*74fe6c29SRuslan Bukin  * Redistribution and use in source and binary forms, with or without
5*74fe6c29SRuslan Bukin  * modification, are permitted provided that the following conditions are met:
6*74fe6c29SRuslan Bukin  *
7*74fe6c29SRuslan Bukin  *  * Redistributions of source code must retain the above copyright notice,
8*74fe6c29SRuslan Bukin  *    this list of conditions and the following disclaimer.
9*74fe6c29SRuslan Bukin  *  * Redistributions in binary form must reproduce the above copyright notice,
10*74fe6c29SRuslan Bukin  *    this list of conditions and the following disclaimer in the documentation
11*74fe6c29SRuslan Bukin  *    and/or other materials provided with the distribution.
12*74fe6c29SRuslan Bukin  *  * Neither the name of Intel Corporation nor the names of its contributors
13*74fe6c29SRuslan Bukin  *    may be used to endorse or promote products derived from this software
14*74fe6c29SRuslan Bukin  *    without specific prior written permission.
15*74fe6c29SRuslan Bukin  *
16*74fe6c29SRuslan Bukin  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*74fe6c29SRuslan Bukin  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*74fe6c29SRuslan Bukin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*74fe6c29SRuslan Bukin  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20*74fe6c29SRuslan Bukin  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*74fe6c29SRuslan Bukin  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*74fe6c29SRuslan Bukin  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*74fe6c29SRuslan Bukin  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*74fe6c29SRuslan Bukin  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*74fe6c29SRuslan Bukin  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*74fe6c29SRuslan Bukin  * POSSIBILITY OF SUCH DAMAGE.
27*74fe6c29SRuslan Bukin  */
28*74fe6c29SRuslan Bukin 
29*74fe6c29SRuslan Bukin #include "pt_block_decoder.h"
30*74fe6c29SRuslan Bukin #include "pt_block_cache.h"
31*74fe6c29SRuslan Bukin #include "pt_section.h"
32*74fe6c29SRuslan Bukin #include "pt_image.h"
33*74fe6c29SRuslan Bukin #include "pt_insn.h"
34*74fe6c29SRuslan Bukin #include "pt_config.h"
35*74fe6c29SRuslan Bukin #include "pt_asid.h"
36*74fe6c29SRuslan Bukin #include "pt_compiler.h"
37*74fe6c29SRuslan Bukin 
38*74fe6c29SRuslan Bukin #include "intel-pt.h"
39*74fe6c29SRuslan Bukin 
40*74fe6c29SRuslan Bukin #include <string.h>
41*74fe6c29SRuslan Bukin #include <stdlib.h>
42*74fe6c29SRuslan Bukin 
43*74fe6c29SRuslan Bukin 
44*74fe6c29SRuslan Bukin static int pt_blk_proceed_trailing_event(struct pt_block_decoder *,
45*74fe6c29SRuslan Bukin 					 struct pt_block *);
46*74fe6c29SRuslan Bukin 
47*74fe6c29SRuslan Bukin 
pt_blk_status(const struct pt_block_decoder * decoder,int flags)48*74fe6c29SRuslan Bukin static int pt_blk_status(const struct pt_block_decoder *decoder, int flags)
49*74fe6c29SRuslan Bukin {
50*74fe6c29SRuslan Bukin 	int status;
51*74fe6c29SRuslan Bukin 
52*74fe6c29SRuslan Bukin 	if (!decoder)
53*74fe6c29SRuslan Bukin 		return -pte_internal;
54*74fe6c29SRuslan Bukin 
55*74fe6c29SRuslan Bukin 	status = decoder->status;
56*74fe6c29SRuslan Bukin 
57*74fe6c29SRuslan Bukin 	/* Indicate whether tracing is disabled or enabled.
58*74fe6c29SRuslan Bukin 	 *
59*74fe6c29SRuslan Bukin 	 * This duplicates the indication in struct pt_insn and covers the case
60*74fe6c29SRuslan Bukin 	 * where we indicate the status after synchronizing.
61*74fe6c29SRuslan Bukin 	 */
62*74fe6c29SRuslan Bukin 	if (!decoder->enabled)
63*74fe6c29SRuslan Bukin 		flags |= pts_ip_suppressed;
64*74fe6c29SRuslan Bukin 
65*74fe6c29SRuslan Bukin 	/* Forward end-of-trace indications.
66*74fe6c29SRuslan Bukin 	 *
67*74fe6c29SRuslan Bukin 	 * Postpone it as long as we're still processing events, though.
68*74fe6c29SRuslan Bukin 	 */
69*74fe6c29SRuslan Bukin 	if ((status & pts_eos) && !decoder->process_event)
70*74fe6c29SRuslan Bukin 		flags |= pts_eos;
71*74fe6c29SRuslan Bukin 
72*74fe6c29SRuslan Bukin 	return flags;
73*74fe6c29SRuslan Bukin }
74*74fe6c29SRuslan Bukin 
pt_blk_reset(struct pt_block_decoder * decoder)75*74fe6c29SRuslan Bukin static void pt_blk_reset(struct pt_block_decoder *decoder)
76*74fe6c29SRuslan Bukin {
77*74fe6c29SRuslan Bukin 	if (!decoder)
78*74fe6c29SRuslan Bukin 		return;
79*74fe6c29SRuslan Bukin 
80*74fe6c29SRuslan Bukin 	decoder->mode = ptem_unknown;
81*74fe6c29SRuslan Bukin 	decoder->ip = 0ull;
82*74fe6c29SRuslan Bukin 	decoder->status = 0;
83*74fe6c29SRuslan Bukin 	decoder->enabled = 0;
84*74fe6c29SRuslan Bukin 	decoder->process_event = 0;
85*74fe6c29SRuslan Bukin 	decoder->speculative = 0;
86*74fe6c29SRuslan Bukin 	decoder->process_insn = 0;
87*74fe6c29SRuslan Bukin 	decoder->bound_paging = 0;
88*74fe6c29SRuslan Bukin 	decoder->bound_vmcs = 0;
89*74fe6c29SRuslan Bukin 	decoder->bound_ptwrite = 0;
90*74fe6c29SRuslan Bukin 
91*74fe6c29SRuslan Bukin 	memset(&decoder->event, 0, sizeof(decoder->event));
92*74fe6c29SRuslan Bukin 	pt_retstack_init(&decoder->retstack);
93*74fe6c29SRuslan Bukin 	pt_asid_init(&decoder->asid);
94*74fe6c29SRuslan Bukin }
95*74fe6c29SRuslan Bukin 
96*74fe6c29SRuslan Bukin /* Initialize the query decoder flags based on our flags. */
97*74fe6c29SRuslan Bukin 
pt_blk_init_qry_flags(struct pt_conf_flags * qflags,const struct pt_conf_flags * flags)98*74fe6c29SRuslan Bukin static int pt_blk_init_qry_flags(struct pt_conf_flags *qflags,
99*74fe6c29SRuslan Bukin 				 const struct pt_conf_flags *flags)
100*74fe6c29SRuslan Bukin {
101*74fe6c29SRuslan Bukin 	if (!qflags || !flags)
102*74fe6c29SRuslan Bukin 		return -pte_internal;
103*74fe6c29SRuslan Bukin 
104*74fe6c29SRuslan Bukin 	memset(qflags, 0, sizeof(*qflags));
105*74fe6c29SRuslan Bukin 
106*74fe6c29SRuslan Bukin 	return 0;
107*74fe6c29SRuslan Bukin }
108*74fe6c29SRuslan Bukin 
pt_blk_decoder_init(struct pt_block_decoder * decoder,const struct pt_config * uconfig)109*74fe6c29SRuslan Bukin int pt_blk_decoder_init(struct pt_block_decoder *decoder,
110*74fe6c29SRuslan Bukin 			const struct pt_config *uconfig)
111*74fe6c29SRuslan Bukin {
112*74fe6c29SRuslan Bukin 	struct pt_config config;
113*74fe6c29SRuslan Bukin 	int errcode;
114*74fe6c29SRuslan Bukin 
115*74fe6c29SRuslan Bukin 	if (!decoder)
116*74fe6c29SRuslan Bukin 		return -pte_internal;
117*74fe6c29SRuslan Bukin 
118*74fe6c29SRuslan Bukin 	errcode = pt_config_from_user(&config, uconfig);
119*74fe6c29SRuslan Bukin 	if (errcode < 0)
120*74fe6c29SRuslan Bukin 		return errcode;
121*74fe6c29SRuslan Bukin 
122*74fe6c29SRuslan Bukin 	/* The user supplied decoder flags. */
123*74fe6c29SRuslan Bukin 	decoder->flags = config.flags;
124*74fe6c29SRuslan Bukin 
125*74fe6c29SRuslan Bukin 	/* Set the flags we need for the query decoder we use. */
126*74fe6c29SRuslan Bukin 	errcode = pt_blk_init_qry_flags(&config.flags, &decoder->flags);
127*74fe6c29SRuslan Bukin 	if (errcode < 0)
128*74fe6c29SRuslan Bukin 		return errcode;
129*74fe6c29SRuslan Bukin 
130*74fe6c29SRuslan Bukin 	errcode = pt_qry_decoder_init(&decoder->query, &config);
131*74fe6c29SRuslan Bukin 	if (errcode < 0)
132*74fe6c29SRuslan Bukin 		return errcode;
133*74fe6c29SRuslan Bukin 
134*74fe6c29SRuslan Bukin 	pt_image_init(&decoder->default_image, NULL);
135*74fe6c29SRuslan Bukin 	decoder->image = &decoder->default_image;
136*74fe6c29SRuslan Bukin 
137*74fe6c29SRuslan Bukin 	errcode = pt_msec_cache_init(&decoder->scache);
138*74fe6c29SRuslan Bukin 	if (errcode < 0)
139*74fe6c29SRuslan Bukin 		return errcode;
140*74fe6c29SRuslan Bukin 
141*74fe6c29SRuslan Bukin 	pt_blk_reset(decoder);
142*74fe6c29SRuslan Bukin 
143*74fe6c29SRuslan Bukin 	return 0;
144*74fe6c29SRuslan Bukin }
145*74fe6c29SRuslan Bukin 
pt_blk_decoder_fini(struct pt_block_decoder * decoder)146*74fe6c29SRuslan Bukin void pt_blk_decoder_fini(struct pt_block_decoder *decoder)
147*74fe6c29SRuslan Bukin {
148*74fe6c29SRuslan Bukin 	if (!decoder)
149*74fe6c29SRuslan Bukin 		return;
150*74fe6c29SRuslan Bukin 
151*74fe6c29SRuslan Bukin 	pt_msec_cache_fini(&decoder->scache);
152*74fe6c29SRuslan Bukin 	pt_image_fini(&decoder->default_image);
153*74fe6c29SRuslan Bukin 	pt_qry_decoder_fini(&decoder->query);
154*74fe6c29SRuslan Bukin }
155*74fe6c29SRuslan Bukin 
156*74fe6c29SRuslan Bukin struct pt_block_decoder *
pt_blk_alloc_decoder(const struct pt_config * config)157*74fe6c29SRuslan Bukin pt_blk_alloc_decoder(const struct pt_config *config)
158*74fe6c29SRuslan Bukin {
159*74fe6c29SRuslan Bukin 	struct pt_block_decoder *decoder;
160*74fe6c29SRuslan Bukin 	int errcode;
161*74fe6c29SRuslan Bukin 
162*74fe6c29SRuslan Bukin 	decoder = malloc(sizeof(*decoder));
163*74fe6c29SRuslan Bukin 	if (!decoder)
164*74fe6c29SRuslan Bukin 		return NULL;
165*74fe6c29SRuslan Bukin 
166*74fe6c29SRuslan Bukin 	errcode = pt_blk_decoder_init(decoder, config);
167*74fe6c29SRuslan Bukin 	if (errcode < 0) {
168*74fe6c29SRuslan Bukin 		free(decoder);
169*74fe6c29SRuslan Bukin 		return NULL;
170*74fe6c29SRuslan Bukin 	}
171*74fe6c29SRuslan Bukin 
172*74fe6c29SRuslan Bukin 	return decoder;
173*74fe6c29SRuslan Bukin }
174*74fe6c29SRuslan Bukin 
pt_blk_free_decoder(struct pt_block_decoder * decoder)175*74fe6c29SRuslan Bukin void pt_blk_free_decoder(struct pt_block_decoder *decoder)
176*74fe6c29SRuslan Bukin {
177*74fe6c29SRuslan Bukin 	if (!decoder)
178*74fe6c29SRuslan Bukin 		return;
179*74fe6c29SRuslan Bukin 
180*74fe6c29SRuslan Bukin 	pt_blk_decoder_fini(decoder);
181*74fe6c29SRuslan Bukin 	free(decoder);
182*74fe6c29SRuslan Bukin }
183*74fe6c29SRuslan Bukin 
184*74fe6c29SRuslan Bukin /* Maybe synthesize a tick event.
185*74fe6c29SRuslan Bukin  *
186*74fe6c29SRuslan Bukin  * If we're not already processing events, check the current time against the
187*74fe6c29SRuslan Bukin  * last event's time.  If it changed, synthesize a tick event with the new time.
188*74fe6c29SRuslan Bukin  *
189*74fe6c29SRuslan Bukin  * Returns zero if no tick event has been created.
190*74fe6c29SRuslan Bukin  * Returns a positive integer if a tick event has been created.
191*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
192*74fe6c29SRuslan Bukin  */
pt_blk_tick(struct pt_block_decoder * decoder,uint64_t ip)193*74fe6c29SRuslan Bukin static int pt_blk_tick(struct pt_block_decoder *decoder, uint64_t ip)
194*74fe6c29SRuslan Bukin {
195*74fe6c29SRuslan Bukin 	struct pt_event *ev;
196*74fe6c29SRuslan Bukin 	uint64_t tsc;
197*74fe6c29SRuslan Bukin 	uint32_t lost_mtc, lost_cyc;
198*74fe6c29SRuslan Bukin 	int errcode;
199*74fe6c29SRuslan Bukin 
200*74fe6c29SRuslan Bukin 	if (!decoder)
201*74fe6c29SRuslan Bukin 		return -pte_internal;
202*74fe6c29SRuslan Bukin 
203*74fe6c29SRuslan Bukin 	/* We're not generating tick events if tracing is disabled. */
204*74fe6c29SRuslan Bukin 	if (!decoder->enabled)
205*74fe6c29SRuslan Bukin 		return -pte_internal;
206*74fe6c29SRuslan Bukin 
207*74fe6c29SRuslan Bukin 	/* Events already provide a timestamp so there is no need to synthesize
208*74fe6c29SRuslan Bukin 	 * an artificial tick event.  There's no room, either, since this would
209*74fe6c29SRuslan Bukin 	 * overwrite the in-progress event.
210*74fe6c29SRuslan Bukin 	 *
211*74fe6c29SRuslan Bukin 	 * In rare cases where we need to proceed to an event location using
212*74fe6c29SRuslan Bukin 	 * trace this may cause us to miss a timing update if the event is not
213*74fe6c29SRuslan Bukin 	 * forwarded to the user.
214*74fe6c29SRuslan Bukin 	 *
215*74fe6c29SRuslan Bukin 	 * The only case I can come up with at the moment is a MODE.EXEC binding
216*74fe6c29SRuslan Bukin 	 * to the TIP IP of a far branch.
217*74fe6c29SRuslan Bukin 	 */
218*74fe6c29SRuslan Bukin 	if (decoder->process_event)
219*74fe6c29SRuslan Bukin 		return 0;
220*74fe6c29SRuslan Bukin 
221*74fe6c29SRuslan Bukin 	errcode = pt_qry_time(&decoder->query, &tsc, &lost_mtc, &lost_cyc);
222*74fe6c29SRuslan Bukin 	if (errcode < 0) {
223*74fe6c29SRuslan Bukin 		/* If we don't have wall-clock time, we use relative time. */
224*74fe6c29SRuslan Bukin 		if (errcode != -pte_no_time)
225*74fe6c29SRuslan Bukin 			return errcode;
226*74fe6c29SRuslan Bukin 	}
227*74fe6c29SRuslan Bukin 
228*74fe6c29SRuslan Bukin 	ev = &decoder->event;
229*74fe6c29SRuslan Bukin 
230*74fe6c29SRuslan Bukin 	/* We're done if time has not changed since the last event. */
231*74fe6c29SRuslan Bukin 	if (tsc == ev->tsc)
232*74fe6c29SRuslan Bukin 		return 0;
233*74fe6c29SRuslan Bukin 
234*74fe6c29SRuslan Bukin 	/* Time has changed so we create a new tick event. */
235*74fe6c29SRuslan Bukin 	memset(ev, 0, sizeof(*ev));
236*74fe6c29SRuslan Bukin 	ev->type = ptev_tick;
237*74fe6c29SRuslan Bukin 	ev->variant.tick.ip = ip;
238*74fe6c29SRuslan Bukin 
239*74fe6c29SRuslan Bukin 	/* Indicate if we have wall-clock time or only relative time. */
240*74fe6c29SRuslan Bukin 	if (errcode != -pte_no_time)
241*74fe6c29SRuslan Bukin 		ev->has_tsc = 1;
242*74fe6c29SRuslan Bukin 	ev->tsc = tsc;
243*74fe6c29SRuslan Bukin 	ev->lost_mtc = lost_mtc;
244*74fe6c29SRuslan Bukin 	ev->lost_cyc = lost_cyc;
245*74fe6c29SRuslan Bukin 
246*74fe6c29SRuslan Bukin 	/* We now have an event to process. */
247*74fe6c29SRuslan Bukin 	decoder->process_event = 1;
248*74fe6c29SRuslan Bukin 
249*74fe6c29SRuslan Bukin 	return 1;
250*74fe6c29SRuslan Bukin }
251*74fe6c29SRuslan Bukin 
252*74fe6c29SRuslan Bukin /* Query an indirect branch.
253*74fe6c29SRuslan Bukin  *
254*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
255*74fe6c29SRuslan Bukin  */
pt_blk_indirect_branch(struct pt_block_decoder * decoder,uint64_t * ip)256*74fe6c29SRuslan Bukin static int pt_blk_indirect_branch(struct pt_block_decoder *decoder,
257*74fe6c29SRuslan Bukin 				  uint64_t *ip)
258*74fe6c29SRuslan Bukin {
259*74fe6c29SRuslan Bukin 	uint64_t evip;
260*74fe6c29SRuslan Bukin 	int status, errcode;
261*74fe6c29SRuslan Bukin 
262*74fe6c29SRuslan Bukin 	if (!decoder)
263*74fe6c29SRuslan Bukin 		return -pte_internal;
264*74fe6c29SRuslan Bukin 
265*74fe6c29SRuslan Bukin 	evip = decoder->ip;
266*74fe6c29SRuslan Bukin 
267*74fe6c29SRuslan Bukin 	status = pt_qry_indirect_branch(&decoder->query, ip);
268*74fe6c29SRuslan Bukin 	if (status < 0)
269*74fe6c29SRuslan Bukin 		return status;
270*74fe6c29SRuslan Bukin 
271*74fe6c29SRuslan Bukin 	if (decoder->flags.variant.block.enable_tick_events) {
272*74fe6c29SRuslan Bukin 		errcode = pt_blk_tick(decoder, evip);
273*74fe6c29SRuslan Bukin 		if (errcode < 0)
274*74fe6c29SRuslan Bukin 			return errcode;
275*74fe6c29SRuslan Bukin 	}
276*74fe6c29SRuslan Bukin 
277*74fe6c29SRuslan Bukin 	return status;
278*74fe6c29SRuslan Bukin }
279*74fe6c29SRuslan Bukin 
280*74fe6c29SRuslan Bukin /* Query a conditional branch.
281*74fe6c29SRuslan Bukin  *
282*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
283*74fe6c29SRuslan Bukin  */
pt_blk_cond_branch(struct pt_block_decoder * decoder,int * taken)284*74fe6c29SRuslan Bukin static int pt_blk_cond_branch(struct pt_block_decoder *decoder, int *taken)
285*74fe6c29SRuslan Bukin {
286*74fe6c29SRuslan Bukin 	int status, errcode;
287*74fe6c29SRuslan Bukin 
288*74fe6c29SRuslan Bukin 	if (!decoder)
289*74fe6c29SRuslan Bukin 		return -pte_internal;
290*74fe6c29SRuslan Bukin 
291*74fe6c29SRuslan Bukin 	status = pt_qry_cond_branch(&decoder->query, taken);
292*74fe6c29SRuslan Bukin 	if (status < 0)
293*74fe6c29SRuslan Bukin 		return status;
294*74fe6c29SRuslan Bukin 
295*74fe6c29SRuslan Bukin 	if (decoder->flags.variant.block.enable_tick_events) {
296*74fe6c29SRuslan Bukin 		errcode = pt_blk_tick(decoder, decoder->ip);
297*74fe6c29SRuslan Bukin 		if (errcode < 0)
298*74fe6c29SRuslan Bukin 			return errcode;
299*74fe6c29SRuslan Bukin 	}
300*74fe6c29SRuslan Bukin 
301*74fe6c29SRuslan Bukin 	return status;
302*74fe6c29SRuslan Bukin }
303*74fe6c29SRuslan Bukin 
pt_blk_start(struct pt_block_decoder * decoder,int status)304*74fe6c29SRuslan Bukin static int pt_blk_start(struct pt_block_decoder *decoder, int status)
305*74fe6c29SRuslan Bukin {
306*74fe6c29SRuslan Bukin 	if (!decoder)
307*74fe6c29SRuslan Bukin 		return -pte_internal;
308*74fe6c29SRuslan Bukin 
309*74fe6c29SRuslan Bukin 	if (status < 0)
310*74fe6c29SRuslan Bukin 		return status;
311*74fe6c29SRuslan Bukin 
312*74fe6c29SRuslan Bukin 	decoder->status = status;
313*74fe6c29SRuslan Bukin 	if (!(status & pts_ip_suppressed))
314*74fe6c29SRuslan Bukin 		decoder->enabled = 1;
315*74fe6c29SRuslan Bukin 
316*74fe6c29SRuslan Bukin 	/* We will always have an event.
317*74fe6c29SRuslan Bukin 	 *
318*74fe6c29SRuslan Bukin 	 * If we synchronized onto an empty PSB+, tracing is disabled and we'll
319*74fe6c29SRuslan Bukin 	 * process events until the enabled event.
320*74fe6c29SRuslan Bukin 	 *
321*74fe6c29SRuslan Bukin 	 * If tracing is enabled, PSB+ must at least provide the execution mode,
322*74fe6c29SRuslan Bukin 	 * which we're going to forward to the user.
323*74fe6c29SRuslan Bukin 	 */
324*74fe6c29SRuslan Bukin 	return pt_blk_proceed_trailing_event(decoder, NULL);
325*74fe6c29SRuslan Bukin }
326*74fe6c29SRuslan Bukin 
pt_blk_sync_reset(struct pt_block_decoder * decoder)327*74fe6c29SRuslan Bukin static int pt_blk_sync_reset(struct pt_block_decoder *decoder)
328*74fe6c29SRuslan Bukin {
329*74fe6c29SRuslan Bukin 	if (!decoder)
330*74fe6c29SRuslan Bukin 		return -pte_internal;
331*74fe6c29SRuslan Bukin 
332*74fe6c29SRuslan Bukin 	pt_blk_reset(decoder);
333*74fe6c29SRuslan Bukin 
334*74fe6c29SRuslan Bukin 	return 0;
335*74fe6c29SRuslan Bukin }
336*74fe6c29SRuslan Bukin 
pt_blk_sync_forward(struct pt_block_decoder * decoder)337*74fe6c29SRuslan Bukin int pt_blk_sync_forward(struct pt_block_decoder *decoder)
338*74fe6c29SRuslan Bukin {
339*74fe6c29SRuslan Bukin 	int errcode, status;
340*74fe6c29SRuslan Bukin 
341*74fe6c29SRuslan Bukin 	if (!decoder)
342*74fe6c29SRuslan Bukin 		return -pte_invalid;
343*74fe6c29SRuslan Bukin 
344*74fe6c29SRuslan Bukin 	errcode = pt_blk_sync_reset(decoder);
345*74fe6c29SRuslan Bukin 	if (errcode < 0)
346*74fe6c29SRuslan Bukin 		return errcode;
347*74fe6c29SRuslan Bukin 
348*74fe6c29SRuslan Bukin 	status = pt_qry_sync_forward(&decoder->query, &decoder->ip);
349*74fe6c29SRuslan Bukin 
350*74fe6c29SRuslan Bukin 	return pt_blk_start(decoder, status);
351*74fe6c29SRuslan Bukin }
352*74fe6c29SRuslan Bukin 
pt_blk_sync_backward(struct pt_block_decoder * decoder)353*74fe6c29SRuslan Bukin int pt_blk_sync_backward(struct pt_block_decoder *decoder)
354*74fe6c29SRuslan Bukin {
355*74fe6c29SRuslan Bukin 	int errcode, status;
356*74fe6c29SRuslan Bukin 
357*74fe6c29SRuslan Bukin 	if (!decoder)
358*74fe6c29SRuslan Bukin 		return -pte_invalid;
359*74fe6c29SRuslan Bukin 
360*74fe6c29SRuslan Bukin 	errcode = pt_blk_sync_reset(decoder);
361*74fe6c29SRuslan Bukin 	if (errcode < 0)
362*74fe6c29SRuslan Bukin 		return errcode;
363*74fe6c29SRuslan Bukin 
364*74fe6c29SRuslan Bukin 	status = pt_qry_sync_backward(&decoder->query, &decoder->ip);
365*74fe6c29SRuslan Bukin 
366*74fe6c29SRuslan Bukin 	return pt_blk_start(decoder, status);
367*74fe6c29SRuslan Bukin }
368*74fe6c29SRuslan Bukin 
pt_blk_sync_set(struct pt_block_decoder * decoder,uint64_t offset)369*74fe6c29SRuslan Bukin int pt_blk_sync_set(struct pt_block_decoder *decoder, uint64_t offset)
370*74fe6c29SRuslan Bukin {
371*74fe6c29SRuslan Bukin 	int errcode, status;
372*74fe6c29SRuslan Bukin 
373*74fe6c29SRuslan Bukin 	if (!decoder)
374*74fe6c29SRuslan Bukin 		return -pte_invalid;
375*74fe6c29SRuslan Bukin 
376*74fe6c29SRuslan Bukin 	errcode = pt_blk_sync_reset(decoder);
377*74fe6c29SRuslan Bukin 	if (errcode < 0)
378*74fe6c29SRuslan Bukin 		return errcode;
379*74fe6c29SRuslan Bukin 
380*74fe6c29SRuslan Bukin 	status = pt_qry_sync_set(&decoder->query, &decoder->ip, offset);
381*74fe6c29SRuslan Bukin 
382*74fe6c29SRuslan Bukin 	return pt_blk_start(decoder, status);
383*74fe6c29SRuslan Bukin }
384*74fe6c29SRuslan Bukin 
pt_blk_get_offset(const struct pt_block_decoder * decoder,uint64_t * offset)385*74fe6c29SRuslan Bukin int pt_blk_get_offset(const struct pt_block_decoder *decoder, uint64_t *offset)
386*74fe6c29SRuslan Bukin {
387*74fe6c29SRuslan Bukin 	if (!decoder)
388*74fe6c29SRuslan Bukin 		return -pte_invalid;
389*74fe6c29SRuslan Bukin 
390*74fe6c29SRuslan Bukin 	return pt_qry_get_offset(&decoder->query, offset);
391*74fe6c29SRuslan Bukin }
392*74fe6c29SRuslan Bukin 
pt_blk_get_sync_offset(const struct pt_block_decoder * decoder,uint64_t * offset)393*74fe6c29SRuslan Bukin int pt_blk_get_sync_offset(const struct pt_block_decoder *decoder,
394*74fe6c29SRuslan Bukin 			   uint64_t *offset)
395*74fe6c29SRuslan Bukin {
396*74fe6c29SRuslan Bukin 	if (!decoder)
397*74fe6c29SRuslan Bukin 		return -pte_invalid;
398*74fe6c29SRuslan Bukin 
399*74fe6c29SRuslan Bukin 	return pt_qry_get_sync_offset(&decoder->query, offset);
400*74fe6c29SRuslan Bukin }
401*74fe6c29SRuslan Bukin 
pt_blk_get_image(struct pt_block_decoder * decoder)402*74fe6c29SRuslan Bukin struct pt_image *pt_blk_get_image(struct pt_block_decoder *decoder)
403*74fe6c29SRuslan Bukin {
404*74fe6c29SRuslan Bukin 	if (!decoder)
405*74fe6c29SRuslan Bukin 		return NULL;
406*74fe6c29SRuslan Bukin 
407*74fe6c29SRuslan Bukin 	return decoder->image;
408*74fe6c29SRuslan Bukin }
409*74fe6c29SRuslan Bukin 
pt_blk_set_image(struct pt_block_decoder * decoder,struct pt_image * image)410*74fe6c29SRuslan Bukin int pt_blk_set_image(struct pt_block_decoder *decoder, struct pt_image *image)
411*74fe6c29SRuslan Bukin {
412*74fe6c29SRuslan Bukin 	if (!decoder)
413*74fe6c29SRuslan Bukin 		return -pte_invalid;
414*74fe6c29SRuslan Bukin 
415*74fe6c29SRuslan Bukin 	if (!image)
416*74fe6c29SRuslan Bukin 		image = &decoder->default_image;
417*74fe6c29SRuslan Bukin 
418*74fe6c29SRuslan Bukin 	decoder->image = image;
419*74fe6c29SRuslan Bukin 	return 0;
420*74fe6c29SRuslan Bukin }
421*74fe6c29SRuslan Bukin 
422*74fe6c29SRuslan Bukin const struct pt_config *
pt_blk_get_config(const struct pt_block_decoder * decoder)423*74fe6c29SRuslan Bukin pt_blk_get_config(const struct pt_block_decoder *decoder)
424*74fe6c29SRuslan Bukin {
425*74fe6c29SRuslan Bukin 	if (!decoder)
426*74fe6c29SRuslan Bukin 		return NULL;
427*74fe6c29SRuslan Bukin 
428*74fe6c29SRuslan Bukin 	return pt_qry_get_config(&decoder->query);
429*74fe6c29SRuslan Bukin }
430*74fe6c29SRuslan Bukin 
pt_blk_time(struct pt_block_decoder * decoder,uint64_t * time,uint32_t * lost_mtc,uint32_t * lost_cyc)431*74fe6c29SRuslan Bukin int pt_blk_time(struct pt_block_decoder *decoder, uint64_t *time,
432*74fe6c29SRuslan Bukin 		uint32_t *lost_mtc, uint32_t *lost_cyc)
433*74fe6c29SRuslan Bukin {
434*74fe6c29SRuslan Bukin 	if (!decoder || !time)
435*74fe6c29SRuslan Bukin 		return -pte_invalid;
436*74fe6c29SRuslan Bukin 
437*74fe6c29SRuslan Bukin 	return pt_qry_time(&decoder->query, time, lost_mtc, lost_cyc);
438*74fe6c29SRuslan Bukin }
439*74fe6c29SRuslan Bukin 
pt_blk_core_bus_ratio(struct pt_block_decoder * decoder,uint32_t * cbr)440*74fe6c29SRuslan Bukin int pt_blk_core_bus_ratio(struct pt_block_decoder *decoder, uint32_t *cbr)
441*74fe6c29SRuslan Bukin {
442*74fe6c29SRuslan Bukin 	if (!decoder || !cbr)
443*74fe6c29SRuslan Bukin 		return -pte_invalid;
444*74fe6c29SRuslan Bukin 
445*74fe6c29SRuslan Bukin 	return pt_qry_core_bus_ratio(&decoder->query, cbr);
446*74fe6c29SRuslan Bukin }
447*74fe6c29SRuslan Bukin 
pt_blk_asid(const struct pt_block_decoder * decoder,struct pt_asid * asid,size_t size)448*74fe6c29SRuslan Bukin int pt_blk_asid(const struct pt_block_decoder *decoder, struct pt_asid *asid,
449*74fe6c29SRuslan Bukin 		size_t size)
450*74fe6c29SRuslan Bukin {
451*74fe6c29SRuslan Bukin 	if (!decoder || !asid)
452*74fe6c29SRuslan Bukin 		return -pte_invalid;
453*74fe6c29SRuslan Bukin 
454*74fe6c29SRuslan Bukin 	return pt_asid_to_user(asid, &decoder->asid, size);
455*74fe6c29SRuslan Bukin }
456*74fe6c29SRuslan Bukin 
457*74fe6c29SRuslan Bukin /* Fetch the next pending event.
458*74fe6c29SRuslan Bukin  *
459*74fe6c29SRuslan Bukin  * Checks for pending events.  If an event is pending, fetches it (if not
460*74fe6c29SRuslan Bukin  * already in process).
461*74fe6c29SRuslan Bukin  *
462*74fe6c29SRuslan Bukin  * Returns zero if no event is pending.
463*74fe6c29SRuslan Bukin  * Returns a positive integer if an event is pending or in process.
464*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
465*74fe6c29SRuslan Bukin  */
pt_blk_fetch_event(struct pt_block_decoder * decoder)466*74fe6c29SRuslan Bukin static inline int pt_blk_fetch_event(struct pt_block_decoder *decoder)
467*74fe6c29SRuslan Bukin {
468*74fe6c29SRuslan Bukin 	int status;
469*74fe6c29SRuslan Bukin 
470*74fe6c29SRuslan Bukin 	if (!decoder)
471*74fe6c29SRuslan Bukin 		return -pte_internal;
472*74fe6c29SRuslan Bukin 
473*74fe6c29SRuslan Bukin 	if (decoder->process_event)
474*74fe6c29SRuslan Bukin 		return 1;
475*74fe6c29SRuslan Bukin 
476*74fe6c29SRuslan Bukin 	if (!(decoder->status & pts_event_pending))
477*74fe6c29SRuslan Bukin 		return 0;
478*74fe6c29SRuslan Bukin 
479*74fe6c29SRuslan Bukin 	status = pt_qry_event(&decoder->query, &decoder->event,
480*74fe6c29SRuslan Bukin 			      sizeof(decoder->event));
481*74fe6c29SRuslan Bukin 	if (status < 0)
482*74fe6c29SRuslan Bukin 		return status;
483*74fe6c29SRuslan Bukin 
484*74fe6c29SRuslan Bukin 	decoder->process_event = 1;
485*74fe6c29SRuslan Bukin 	decoder->status = status;
486*74fe6c29SRuslan Bukin 
487*74fe6c29SRuslan Bukin 	return 1;
488*74fe6c29SRuslan Bukin }
489*74fe6c29SRuslan Bukin 
pt_blk_block_is_empty(const struct pt_block * block)490*74fe6c29SRuslan Bukin static inline int pt_blk_block_is_empty(const struct pt_block *block)
491*74fe6c29SRuslan Bukin {
492*74fe6c29SRuslan Bukin 	if (!block)
493*74fe6c29SRuslan Bukin 		return 1;
494*74fe6c29SRuslan Bukin 
495*74fe6c29SRuslan Bukin 	return !block->ninsn;
496*74fe6c29SRuslan Bukin }
497*74fe6c29SRuslan Bukin 
block_to_user(struct pt_block * ublock,size_t size,const struct pt_block * block)498*74fe6c29SRuslan Bukin static inline int block_to_user(struct pt_block *ublock, size_t size,
499*74fe6c29SRuslan Bukin 				const struct pt_block *block)
500*74fe6c29SRuslan Bukin {
501*74fe6c29SRuslan Bukin 	if (!ublock || !block)
502*74fe6c29SRuslan Bukin 		return -pte_internal;
503*74fe6c29SRuslan Bukin 
504*74fe6c29SRuslan Bukin 	if (ublock == block)
505*74fe6c29SRuslan Bukin 		return 0;
506*74fe6c29SRuslan Bukin 
507*74fe6c29SRuslan Bukin 	/* Zero out any unknown bytes. */
508*74fe6c29SRuslan Bukin 	if (sizeof(*block) < size) {
509*74fe6c29SRuslan Bukin 		memset(ublock + sizeof(*block), 0, size - sizeof(*block));
510*74fe6c29SRuslan Bukin 
511*74fe6c29SRuslan Bukin 		size = sizeof(*block);
512*74fe6c29SRuslan Bukin 	}
513*74fe6c29SRuslan Bukin 
514*74fe6c29SRuslan Bukin 	memcpy(ublock, block, size);
515*74fe6c29SRuslan Bukin 
516*74fe6c29SRuslan Bukin 	return 0;
517*74fe6c29SRuslan Bukin }
518*74fe6c29SRuslan Bukin 
pt_insn_false(const struct pt_insn * insn,const struct pt_insn_ext * iext)519*74fe6c29SRuslan Bukin static int pt_insn_false(const struct pt_insn *insn,
520*74fe6c29SRuslan Bukin 			 const struct pt_insn_ext *iext)
521*74fe6c29SRuslan Bukin {
522*74fe6c29SRuslan Bukin 	(void) insn;
523*74fe6c29SRuslan Bukin 	(void) iext;
524*74fe6c29SRuslan Bukin 
525*74fe6c29SRuslan Bukin 	return 0;
526*74fe6c29SRuslan Bukin }
527*74fe6c29SRuslan Bukin 
528*74fe6c29SRuslan Bukin /* Determine the next IP using trace.
529*74fe6c29SRuslan Bukin  *
530*74fe6c29SRuslan Bukin  * Tries to determine the IP of the next instruction using trace and provides it
531*74fe6c29SRuslan Bukin  * in @pip.
532*74fe6c29SRuslan Bukin  *
533*74fe6c29SRuslan Bukin  * Not requiring trace to determine the IP is treated as an internal error.
534*74fe6c29SRuslan Bukin  *
535*74fe6c29SRuslan Bukin  * Does not update the return compression stack for indirect calls.  This is
536*74fe6c29SRuslan Bukin  * expected to have been done, already, when trying to determine the next IP
537*74fe6c29SRuslan Bukin  * without using trace.
538*74fe6c29SRuslan Bukin  *
539*74fe6c29SRuslan Bukin  * Does not update @decoder->status.  The caller is expected to do that.
540*74fe6c29SRuslan Bukin  *
541*74fe6c29SRuslan Bukin  * Returns a non-negative pt_status_flag bit-vector on success, a negative error
542*74fe6c29SRuslan Bukin  * code otherwise.
543*74fe6c29SRuslan Bukin  * Returns -pte_internal if @pip, @decoder, @insn, or @iext are NULL.
544*74fe6c29SRuslan Bukin  * Returns -pte_internal if no trace is required.
545*74fe6c29SRuslan Bukin  */
pt_blk_next_ip(uint64_t * pip,struct pt_block_decoder * decoder,const struct pt_insn * insn,const struct pt_insn_ext * iext)546*74fe6c29SRuslan Bukin static int pt_blk_next_ip(uint64_t *pip, struct pt_block_decoder *decoder,
547*74fe6c29SRuslan Bukin 			  const struct pt_insn *insn,
548*74fe6c29SRuslan Bukin 			  const struct pt_insn_ext *iext)
549*74fe6c29SRuslan Bukin {
550*74fe6c29SRuslan Bukin 	int status, errcode;
551*74fe6c29SRuslan Bukin 
552*74fe6c29SRuslan Bukin 	if (!pip || !decoder || !insn || !iext)
553*74fe6c29SRuslan Bukin 		return -pte_internal;
554*74fe6c29SRuslan Bukin 
555*74fe6c29SRuslan Bukin 	/* We handle non-taken conditional branches, and compressed returns
556*74fe6c29SRuslan Bukin 	 * directly in the switch.
557*74fe6c29SRuslan Bukin 	 *
558*74fe6c29SRuslan Bukin 	 * All kinds of branches are handled below the switch.
559*74fe6c29SRuslan Bukin 	 */
560*74fe6c29SRuslan Bukin 	switch (insn->iclass) {
561*74fe6c29SRuslan Bukin 	case ptic_cond_jump: {
562*74fe6c29SRuslan Bukin 		uint64_t ip;
563*74fe6c29SRuslan Bukin 		int taken;
564*74fe6c29SRuslan Bukin 
565*74fe6c29SRuslan Bukin 		status = pt_blk_cond_branch(decoder, &taken);
566*74fe6c29SRuslan Bukin 		if (status < 0)
567*74fe6c29SRuslan Bukin 			return status;
568*74fe6c29SRuslan Bukin 
569*74fe6c29SRuslan Bukin 		ip = insn->ip + insn->size;
570*74fe6c29SRuslan Bukin 		if (taken)
571*74fe6c29SRuslan Bukin 			ip += iext->variant.branch.displacement;
572*74fe6c29SRuslan Bukin 
573*74fe6c29SRuslan Bukin 		*pip = ip;
574*74fe6c29SRuslan Bukin 		return status;
575*74fe6c29SRuslan Bukin 	}
576*74fe6c29SRuslan Bukin 
577*74fe6c29SRuslan Bukin 	case ptic_return: {
578*74fe6c29SRuslan Bukin 		int taken;
579*74fe6c29SRuslan Bukin 
580*74fe6c29SRuslan Bukin 		/* Check for a compressed return. */
581*74fe6c29SRuslan Bukin 		status = pt_blk_cond_branch(decoder, &taken);
582*74fe6c29SRuslan Bukin 		if (status < 0) {
583*74fe6c29SRuslan Bukin 			if (status != -pte_bad_query)
584*74fe6c29SRuslan Bukin 				return status;
585*74fe6c29SRuslan Bukin 
586*74fe6c29SRuslan Bukin 			break;
587*74fe6c29SRuslan Bukin 		}
588*74fe6c29SRuslan Bukin 
589*74fe6c29SRuslan Bukin 		/* A compressed return is indicated by a taken conditional
590*74fe6c29SRuslan Bukin 		 * branch.
591*74fe6c29SRuslan Bukin 		 */
592*74fe6c29SRuslan Bukin 		if (!taken)
593*74fe6c29SRuslan Bukin 			return -pte_bad_retcomp;
594*74fe6c29SRuslan Bukin 
595*74fe6c29SRuslan Bukin 		errcode = pt_retstack_pop(&decoder->retstack, pip);
596*74fe6c29SRuslan Bukin 		if (errcode < 0)
597*74fe6c29SRuslan Bukin 			return errcode;
598*74fe6c29SRuslan Bukin 
599*74fe6c29SRuslan Bukin 		return status;
600*74fe6c29SRuslan Bukin 	}
601*74fe6c29SRuslan Bukin 
602*74fe6c29SRuslan Bukin 	case ptic_jump:
603*74fe6c29SRuslan Bukin 	case ptic_call:
604*74fe6c29SRuslan Bukin 		/* A direct jump or call wouldn't require trace. */
605*74fe6c29SRuslan Bukin 		if (iext->variant.branch.is_direct)
606*74fe6c29SRuslan Bukin 			return -pte_internal;
607*74fe6c29SRuslan Bukin 
608*74fe6c29SRuslan Bukin 		break;
609*74fe6c29SRuslan Bukin 
610*74fe6c29SRuslan Bukin 	case ptic_far_call:
611*74fe6c29SRuslan Bukin 	case ptic_far_return:
612*74fe6c29SRuslan Bukin 	case ptic_far_jump:
613*74fe6c29SRuslan Bukin 		break;
614*74fe6c29SRuslan Bukin 
615*74fe6c29SRuslan Bukin 	case ptic_ptwrite:
616*74fe6c29SRuslan Bukin 	case ptic_other:
617*74fe6c29SRuslan Bukin 		return -pte_internal;
618*74fe6c29SRuslan Bukin 
619*74fe6c29SRuslan Bukin 	case ptic_error:
620*74fe6c29SRuslan Bukin 		return -pte_bad_insn;
621*74fe6c29SRuslan Bukin 	}
622*74fe6c29SRuslan Bukin 
623*74fe6c29SRuslan Bukin 	/* Process an indirect branch.
624*74fe6c29SRuslan Bukin 	 *
625*74fe6c29SRuslan Bukin 	 * This covers indirect jumps and calls, non-compressed returns, and all
626*74fe6c29SRuslan Bukin 	 * flavors of far transfers.
627*74fe6c29SRuslan Bukin 	 */
628*74fe6c29SRuslan Bukin 	return pt_blk_indirect_branch(decoder, pip);
629*74fe6c29SRuslan Bukin }
630*74fe6c29SRuslan Bukin 
631*74fe6c29SRuslan Bukin /* Proceed to the next IP using trace.
632*74fe6c29SRuslan Bukin  *
633*74fe6c29SRuslan Bukin  * We failed to proceed without trace.  This ends the current block.  Now use
634*74fe6c29SRuslan Bukin  * trace to do one final step to determine the start IP of the next block.
635*74fe6c29SRuslan Bukin  *
636*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
637*74fe6c29SRuslan Bukin  */
pt_blk_proceed_with_trace(struct pt_block_decoder * decoder,const struct pt_insn * insn,const struct pt_insn_ext * iext)638*74fe6c29SRuslan Bukin static int pt_blk_proceed_with_trace(struct pt_block_decoder *decoder,
639*74fe6c29SRuslan Bukin 				     const struct pt_insn *insn,
640*74fe6c29SRuslan Bukin 				     const struct pt_insn_ext *iext)
641*74fe6c29SRuslan Bukin {
642*74fe6c29SRuslan Bukin 	int status;
643*74fe6c29SRuslan Bukin 
644*74fe6c29SRuslan Bukin 	if (!decoder)
645*74fe6c29SRuslan Bukin 		return -pte_internal;
646*74fe6c29SRuslan Bukin 
647*74fe6c29SRuslan Bukin 	status = pt_blk_next_ip(&decoder->ip, decoder, insn, iext);
648*74fe6c29SRuslan Bukin 	if (status < 0)
649*74fe6c29SRuslan Bukin 		return status;
650*74fe6c29SRuslan Bukin 
651*74fe6c29SRuslan Bukin 	/* Preserve the query decoder's response which indicates upcoming
652*74fe6c29SRuslan Bukin 	 * events.
653*74fe6c29SRuslan Bukin 	 */
654*74fe6c29SRuslan Bukin 	decoder->status = status;
655*74fe6c29SRuslan Bukin 
656*74fe6c29SRuslan Bukin 	/* We do need an IP in order to proceed. */
657*74fe6c29SRuslan Bukin 	if (status & pts_ip_suppressed)
658*74fe6c29SRuslan Bukin 		return -pte_noip;
659*74fe6c29SRuslan Bukin 
660*74fe6c29SRuslan Bukin 	return 0;
661*74fe6c29SRuslan Bukin }
662*74fe6c29SRuslan Bukin 
663*74fe6c29SRuslan Bukin /* Decode one instruction in a known section.
664*74fe6c29SRuslan Bukin  *
665*74fe6c29SRuslan Bukin  * Decode the instruction at @insn->ip in @msec assuming execution mode
666*74fe6c29SRuslan Bukin  * @insn->mode.
667*74fe6c29SRuslan Bukin  *
668*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
669*74fe6c29SRuslan Bukin  */
pt_blk_decode_in_section(struct pt_insn * insn,struct pt_insn_ext * iext,const struct pt_mapped_section * msec)670*74fe6c29SRuslan Bukin static int pt_blk_decode_in_section(struct pt_insn *insn,
671*74fe6c29SRuslan Bukin 				    struct pt_insn_ext *iext,
672*74fe6c29SRuslan Bukin 				    const struct pt_mapped_section *msec)
673*74fe6c29SRuslan Bukin {
674*74fe6c29SRuslan Bukin 	int status;
675*74fe6c29SRuslan Bukin 
676*74fe6c29SRuslan Bukin 	if (!insn || !iext)
677*74fe6c29SRuslan Bukin 		return -pte_internal;
678*74fe6c29SRuslan Bukin 
679*74fe6c29SRuslan Bukin 	/* We know that @ip is contained in @section.
680*74fe6c29SRuslan Bukin 	 *
681*74fe6c29SRuslan Bukin 	 * Note that we need to translate @ip into a section offset.
682*74fe6c29SRuslan Bukin 	 */
683*74fe6c29SRuslan Bukin 	status = pt_msec_read(msec, insn->raw, sizeof(insn->raw), insn->ip);
684*74fe6c29SRuslan Bukin 	if (status < 0)
685*74fe6c29SRuslan Bukin 		return status;
686*74fe6c29SRuslan Bukin 
687*74fe6c29SRuslan Bukin 	/* We initialize @insn->size to the maximal possible size.  It will be
688*74fe6c29SRuslan Bukin 	 * set to the actual size during instruction decode.
689*74fe6c29SRuslan Bukin 	 */
690*74fe6c29SRuslan Bukin 	insn->size = (uint8_t) status;
691*74fe6c29SRuslan Bukin 
692*74fe6c29SRuslan Bukin 	return pt_ild_decode(insn, iext);
693*74fe6c29SRuslan Bukin }
694*74fe6c29SRuslan Bukin 
695*74fe6c29SRuslan Bukin /* Update the return-address stack if @insn is a near call.
696*74fe6c29SRuslan Bukin  *
697*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
698*74fe6c29SRuslan Bukin  */
pt_blk_log_call(struct pt_block_decoder * decoder,const struct pt_insn * insn,const struct pt_insn_ext * iext)699*74fe6c29SRuslan Bukin static inline int pt_blk_log_call(struct pt_block_decoder *decoder,
700*74fe6c29SRuslan Bukin 				  const struct pt_insn *insn,
701*74fe6c29SRuslan Bukin 				  const struct pt_insn_ext *iext)
702*74fe6c29SRuslan Bukin {
703*74fe6c29SRuslan Bukin 	if (!decoder || !insn || !iext)
704*74fe6c29SRuslan Bukin 		return -pte_internal;
705*74fe6c29SRuslan Bukin 
706*74fe6c29SRuslan Bukin 	if (insn->iclass != ptic_call)
707*74fe6c29SRuslan Bukin 		return 0;
708*74fe6c29SRuslan Bukin 
709*74fe6c29SRuslan Bukin 	/* Ignore direct calls to the next instruction that are used for
710*74fe6c29SRuslan Bukin 	 * position independent code.
711*74fe6c29SRuslan Bukin 	 */
712*74fe6c29SRuslan Bukin 	if (iext->variant.branch.is_direct &&
713*74fe6c29SRuslan Bukin 	    !iext->variant.branch.displacement)
714*74fe6c29SRuslan Bukin 		return 0;
715*74fe6c29SRuslan Bukin 
716*74fe6c29SRuslan Bukin 	return pt_retstack_push(&decoder->retstack, insn->ip + insn->size);
717*74fe6c29SRuslan Bukin }
718*74fe6c29SRuslan Bukin 
719*74fe6c29SRuslan Bukin /* Proceed by one instruction.
720*74fe6c29SRuslan Bukin  *
721*74fe6c29SRuslan Bukin  * Tries to decode the instruction at @decoder->ip and, on success, adds it to
722*74fe6c29SRuslan Bukin  * @block and provides it in @pinsn and @piext.
723*74fe6c29SRuslan Bukin  *
724*74fe6c29SRuslan Bukin  * The instruction will not be added if:
725*74fe6c29SRuslan Bukin  *
726*74fe6c29SRuslan Bukin  *   - the memory could not be read:  return error
727*74fe6c29SRuslan Bukin  *   - it could not be decoded:       return error
728*74fe6c29SRuslan Bukin  *   - @block is already full:        return zero
729*74fe6c29SRuslan Bukin  *   - @block would switch sections:  return zero
730*74fe6c29SRuslan Bukin  *
731*74fe6c29SRuslan Bukin  * Returns a positive integer if the instruction was added.
732*74fe6c29SRuslan Bukin  * Returns zero if the instruction didn't fit into @block.
733*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
734*74fe6c29SRuslan Bukin  */
pt_blk_proceed_one_insn(struct pt_block_decoder * decoder,struct pt_block * block,struct pt_insn * pinsn,struct pt_insn_ext * piext)735*74fe6c29SRuslan Bukin static int pt_blk_proceed_one_insn(struct pt_block_decoder *decoder,
736*74fe6c29SRuslan Bukin 				   struct pt_block *block,
737*74fe6c29SRuslan Bukin 				   struct pt_insn *pinsn,
738*74fe6c29SRuslan Bukin 				   struct pt_insn_ext *piext)
739*74fe6c29SRuslan Bukin {
740*74fe6c29SRuslan Bukin 	struct pt_insn_ext iext;
741*74fe6c29SRuslan Bukin 	struct pt_insn insn;
742*74fe6c29SRuslan Bukin 	uint16_t ninsn;
743*74fe6c29SRuslan Bukin 	int status;
744*74fe6c29SRuslan Bukin 
745*74fe6c29SRuslan Bukin 	if (!decoder || !block || !pinsn || !piext)
746*74fe6c29SRuslan Bukin 		return -pte_internal;
747*74fe6c29SRuslan Bukin 
748*74fe6c29SRuslan Bukin 	/* There's nothing to do if there is no room in @block. */
749*74fe6c29SRuslan Bukin 	ninsn = block->ninsn + 1;
750*74fe6c29SRuslan Bukin 	if (!ninsn)
751*74fe6c29SRuslan Bukin 		return 0;
752*74fe6c29SRuslan Bukin 
753*74fe6c29SRuslan Bukin 	/* The truncated instruction must be last. */
754*74fe6c29SRuslan Bukin 	if (block->truncated)
755*74fe6c29SRuslan Bukin 		return 0;
756*74fe6c29SRuslan Bukin 
757*74fe6c29SRuslan Bukin 	memset(&insn, 0, sizeof(insn));
758*74fe6c29SRuslan Bukin 	memset(&iext, 0, sizeof(iext));
759*74fe6c29SRuslan Bukin 
760*74fe6c29SRuslan Bukin 	insn.mode = decoder->mode;
761*74fe6c29SRuslan Bukin 	insn.ip = decoder->ip;
762*74fe6c29SRuslan Bukin 
763*74fe6c29SRuslan Bukin 	status = pt_insn_decode(&insn, &iext, decoder->image, &decoder->asid);
764*74fe6c29SRuslan Bukin 	if (status < 0)
765*74fe6c29SRuslan Bukin 		return status;
766*74fe6c29SRuslan Bukin 
767*74fe6c29SRuslan Bukin 	/* We do not switch sections inside a block. */
768*74fe6c29SRuslan Bukin 	if (insn.isid != block->isid) {
769*74fe6c29SRuslan Bukin 		if (!pt_blk_block_is_empty(block))
770*74fe6c29SRuslan Bukin 			return 0;
771*74fe6c29SRuslan Bukin 
772*74fe6c29SRuslan Bukin 		block->isid = insn.isid;
773*74fe6c29SRuslan Bukin 	}
774*74fe6c29SRuslan Bukin 
775*74fe6c29SRuslan Bukin 	/* If we couldn't read @insn's memory in one chunk from @insn.isid, we
776*74fe6c29SRuslan Bukin 	 * provide the memory in @block.
777*74fe6c29SRuslan Bukin 	 */
778*74fe6c29SRuslan Bukin 	if (insn.truncated) {
779*74fe6c29SRuslan Bukin 		memcpy(block->raw, insn.raw, insn.size);
780*74fe6c29SRuslan Bukin 		block->size = insn.size;
781*74fe6c29SRuslan Bukin 		block->truncated = 1;
782*74fe6c29SRuslan Bukin 	}
783*74fe6c29SRuslan Bukin 
784*74fe6c29SRuslan Bukin 	/* Log calls' return addresses for return compression. */
785*74fe6c29SRuslan Bukin 	status = pt_blk_log_call(decoder, &insn, &iext);
786*74fe6c29SRuslan Bukin 	if (status < 0)
787*74fe6c29SRuslan Bukin 		return status;
788*74fe6c29SRuslan Bukin 
789*74fe6c29SRuslan Bukin 	/* We have a new instruction. */
790*74fe6c29SRuslan Bukin 	block->iclass = insn.iclass;
791*74fe6c29SRuslan Bukin 	block->end_ip = insn.ip;
792*74fe6c29SRuslan Bukin 	block->ninsn = ninsn;
793*74fe6c29SRuslan Bukin 
794*74fe6c29SRuslan Bukin 	*pinsn = insn;
795*74fe6c29SRuslan Bukin 	*piext = iext;
796*74fe6c29SRuslan Bukin 
797*74fe6c29SRuslan Bukin 	return 1;
798*74fe6c29SRuslan Bukin }
799*74fe6c29SRuslan Bukin 
800*74fe6c29SRuslan Bukin 
801*74fe6c29SRuslan Bukin /* Proceed to a particular type of instruction without using trace.
802*74fe6c29SRuslan Bukin  *
803*74fe6c29SRuslan Bukin  * Proceed until we reach an instruction for which @predicate returns a positive
804*74fe6c29SRuslan Bukin  * integer or until:
805*74fe6c29SRuslan Bukin  *
806*74fe6c29SRuslan Bukin  *   - @predicate returns an error:  return error
807*74fe6c29SRuslan Bukin  *   - @block is full:               return zero
808*74fe6c29SRuslan Bukin  *   - @block would switch sections: return zero
809*74fe6c29SRuslan Bukin  *   - we would need trace:          return -pte_bad_query
810*74fe6c29SRuslan Bukin  *
811*74fe6c29SRuslan Bukin  * Provide the last instruction that was reached in @insn and @iext.
812*74fe6c29SRuslan Bukin  *
813*74fe6c29SRuslan Bukin  * Update @decoder->ip to point to the last IP that was reached.  If we fail due
814*74fe6c29SRuslan Bukin  * to lack of trace or if we reach a desired instruction, this is @insn->ip;
815*74fe6c29SRuslan Bukin  * otherwise this is the next instruction's IP.
816*74fe6c29SRuslan Bukin  *
817*74fe6c29SRuslan Bukin  * Returns a positive integer if a suitable instruction was reached.
818*74fe6c29SRuslan Bukin  * Returns zero if no such instruction was reached.
819*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
820*74fe6c29SRuslan Bukin  */
pt_blk_proceed_to_insn(struct pt_block_decoder * decoder,struct pt_block * block,struct pt_insn * insn,struct pt_insn_ext * iext,int (* predicate)(const struct pt_insn *,const struct pt_insn_ext *))821*74fe6c29SRuslan Bukin static int pt_blk_proceed_to_insn(struct pt_block_decoder *decoder,
822*74fe6c29SRuslan Bukin 				  struct pt_block *block,
823*74fe6c29SRuslan Bukin 				  struct pt_insn *insn,
824*74fe6c29SRuslan Bukin 				  struct pt_insn_ext *iext,
825*74fe6c29SRuslan Bukin 				  int (*predicate)(const struct pt_insn *,
826*74fe6c29SRuslan Bukin 						   const struct pt_insn_ext *))
827*74fe6c29SRuslan Bukin {
828*74fe6c29SRuslan Bukin 	int status;
829*74fe6c29SRuslan Bukin 
830*74fe6c29SRuslan Bukin 	if (!decoder || !insn || !predicate)
831*74fe6c29SRuslan Bukin 		return -pte_internal;
832*74fe6c29SRuslan Bukin 
833*74fe6c29SRuslan Bukin 	for (;;) {
834*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_one_insn(decoder, block, insn, iext);
835*74fe6c29SRuslan Bukin 		if (status <= 0)
836*74fe6c29SRuslan Bukin 			return status;
837*74fe6c29SRuslan Bukin 
838*74fe6c29SRuslan Bukin 		/* We're done if this instruction matches the spec (positive
839*74fe6c29SRuslan Bukin 		 * status) or we run into an error (negative status).
840*74fe6c29SRuslan Bukin 		 */
841*74fe6c29SRuslan Bukin 		status = predicate(insn, iext);
842*74fe6c29SRuslan Bukin 		if (status != 0)
843*74fe6c29SRuslan Bukin 			return status;
844*74fe6c29SRuslan Bukin 
845*74fe6c29SRuslan Bukin 		/* Let's see if we can proceed to the next IP without trace. */
846*74fe6c29SRuslan Bukin 		status = pt_insn_next_ip(&decoder->ip, insn, iext);
847*74fe6c29SRuslan Bukin 		if (status < 0)
848*74fe6c29SRuslan Bukin 			return status;
849*74fe6c29SRuslan Bukin 
850*74fe6c29SRuslan Bukin 		/* End the block if the user asked us to.
851*74fe6c29SRuslan Bukin 		 *
852*74fe6c29SRuslan Bukin 		 * We only need to take care about direct near branches.
853*74fe6c29SRuslan Bukin 		 * Indirect and far branches require trace and will naturally
854*74fe6c29SRuslan Bukin 		 * end a block.
855*74fe6c29SRuslan Bukin 		 */
856*74fe6c29SRuslan Bukin 		if ((decoder->flags.variant.block.end_on_call &&
857*74fe6c29SRuslan Bukin 		     (insn->iclass == ptic_call)) ||
858*74fe6c29SRuslan Bukin 		    (decoder->flags.variant.block.end_on_jump &&
859*74fe6c29SRuslan Bukin 		     (insn->iclass == ptic_jump)))
860*74fe6c29SRuslan Bukin 			return 0;
861*74fe6c29SRuslan Bukin 	}
862*74fe6c29SRuslan Bukin }
863*74fe6c29SRuslan Bukin 
864*74fe6c29SRuslan Bukin /* Proceed to a particular IP without using trace.
865*74fe6c29SRuslan Bukin  *
866*74fe6c29SRuslan Bukin  * Proceed until we reach @ip or until:
867*74fe6c29SRuslan Bukin  *
868*74fe6c29SRuslan Bukin  *   - @block is full:               return zero
869*74fe6c29SRuslan Bukin  *   - @block would switch sections: return zero
870*74fe6c29SRuslan Bukin  *   - we would need trace:          return -pte_bad_query
871*74fe6c29SRuslan Bukin  *
872*74fe6c29SRuslan Bukin  * Provide the last instruction that was reached in @insn and @iext.  If we
873*74fe6c29SRuslan Bukin  * reached @ip, this is the instruction preceding it.
874*74fe6c29SRuslan Bukin  *
875*74fe6c29SRuslan Bukin  * Update @decoder->ip to point to the last IP that was reached.  If we fail due
876*74fe6c29SRuslan Bukin  * to lack of trace, this is @insn->ip; otherwise this is the next instruction's
877*74fe6c29SRuslan Bukin  * IP.
878*74fe6c29SRuslan Bukin  *
879*74fe6c29SRuslan Bukin  * Returns a positive integer if @ip was reached.
880*74fe6c29SRuslan Bukin  * Returns zero if no such instruction was reached.
881*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
882*74fe6c29SRuslan Bukin  */
pt_blk_proceed_to_ip(struct pt_block_decoder * decoder,struct pt_block * block,struct pt_insn * insn,struct pt_insn_ext * iext,uint64_t ip)883*74fe6c29SRuslan Bukin static int pt_blk_proceed_to_ip(struct pt_block_decoder *decoder,
884*74fe6c29SRuslan Bukin 				struct pt_block *block, struct pt_insn *insn,
885*74fe6c29SRuslan Bukin 				struct pt_insn_ext *iext, uint64_t ip)
886*74fe6c29SRuslan Bukin {
887*74fe6c29SRuslan Bukin 	int status;
888*74fe6c29SRuslan Bukin 
889*74fe6c29SRuslan Bukin 	if (!decoder || !insn)
890*74fe6c29SRuslan Bukin 		return -pte_internal;
891*74fe6c29SRuslan Bukin 
892*74fe6c29SRuslan Bukin 	for (;;) {
893*74fe6c29SRuslan Bukin 		/* We're done when we reach @ip.  We may not even have to decode
894*74fe6c29SRuslan Bukin 		 * a single instruction in some cases.
895*74fe6c29SRuslan Bukin 		 */
896*74fe6c29SRuslan Bukin 		if (decoder->ip == ip)
897*74fe6c29SRuslan Bukin 			return 1;
898*74fe6c29SRuslan Bukin 
899*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_one_insn(decoder, block, insn, iext);
900*74fe6c29SRuslan Bukin 		if (status <= 0)
901*74fe6c29SRuslan Bukin 			return status;
902*74fe6c29SRuslan Bukin 
903*74fe6c29SRuslan Bukin 		/* Let's see if we can proceed to the next IP without trace. */
904*74fe6c29SRuslan Bukin 		status = pt_insn_next_ip(&decoder->ip, insn, iext);
905*74fe6c29SRuslan Bukin 		if (status < 0)
906*74fe6c29SRuslan Bukin 			return status;
907*74fe6c29SRuslan Bukin 
908*74fe6c29SRuslan Bukin 		/* End the block if the user asked us to.
909*74fe6c29SRuslan Bukin 		 *
910*74fe6c29SRuslan Bukin 		 * We only need to take care about direct near branches.
911*74fe6c29SRuslan Bukin 		 * Indirect and far branches require trace and will naturally
912*74fe6c29SRuslan Bukin 		 * end a block.
913*74fe6c29SRuslan Bukin 		 *
914*74fe6c29SRuslan Bukin 		 * The call at the end of the block may have reached @ip; make
915*74fe6c29SRuslan Bukin 		 * sure to indicate that.
916*74fe6c29SRuslan Bukin 		 */
917*74fe6c29SRuslan Bukin 		if ((decoder->flags.variant.block.end_on_call &&
918*74fe6c29SRuslan Bukin 		     (insn->iclass == ptic_call)) ||
919*74fe6c29SRuslan Bukin 		    (decoder->flags.variant.block.end_on_jump &&
920*74fe6c29SRuslan Bukin 		     (insn->iclass == ptic_jump))) {
921*74fe6c29SRuslan Bukin 			return (decoder->ip == ip ? 1 : 0);
922*74fe6c29SRuslan Bukin 		}
923*74fe6c29SRuslan Bukin 	}
924*74fe6c29SRuslan Bukin }
925*74fe6c29SRuslan Bukin 
926*74fe6c29SRuslan Bukin /* Proceed to a particular IP with trace, if necessary.
927*74fe6c29SRuslan Bukin  *
928*74fe6c29SRuslan Bukin  * Proceed until we reach @ip or until:
929*74fe6c29SRuslan Bukin  *
930*74fe6c29SRuslan Bukin  *   - @block is full:               return zero
931*74fe6c29SRuslan Bukin  *   - @block would switch sections: return zero
932*74fe6c29SRuslan Bukin  *   - we need trace:                return zero
933*74fe6c29SRuslan Bukin  *
934*74fe6c29SRuslan Bukin  * Update @decoder->ip to point to the last IP that was reached.
935*74fe6c29SRuslan Bukin  *
936*74fe6c29SRuslan Bukin  * A return of zero ends @block.
937*74fe6c29SRuslan Bukin  *
938*74fe6c29SRuslan Bukin  * Returns a positive integer if @ip was reached.
939*74fe6c29SRuslan Bukin  * Returns zero if no such instruction was reached.
940*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
941*74fe6c29SRuslan Bukin  */
pt_blk_proceed_to_ip_with_trace(struct pt_block_decoder * decoder,struct pt_block * block,uint64_t ip)942*74fe6c29SRuslan Bukin static int pt_blk_proceed_to_ip_with_trace(struct pt_block_decoder *decoder,
943*74fe6c29SRuslan Bukin 					   struct pt_block *block,
944*74fe6c29SRuslan Bukin 					   uint64_t ip)
945*74fe6c29SRuslan Bukin {
946*74fe6c29SRuslan Bukin 	struct pt_insn_ext iext;
947*74fe6c29SRuslan Bukin 	struct pt_insn insn;
948*74fe6c29SRuslan Bukin 	int status;
949*74fe6c29SRuslan Bukin 
950*74fe6c29SRuslan Bukin 	/* Try to reach @ip without trace.
951*74fe6c29SRuslan Bukin 	 *
952*74fe6c29SRuslan Bukin 	 * We're also OK if @block overflowed or we switched sections and we
953*74fe6c29SRuslan Bukin 	 * have to try again in the next iteration.
954*74fe6c29SRuslan Bukin 	 */
955*74fe6c29SRuslan Bukin 	status = pt_blk_proceed_to_ip(decoder, block, &insn, &iext, ip);
956*74fe6c29SRuslan Bukin 	if (status != -pte_bad_query)
957*74fe6c29SRuslan Bukin 		return status;
958*74fe6c29SRuslan Bukin 
959*74fe6c29SRuslan Bukin 	/* Needing trace is not an error.  We use trace to determine the next
960*74fe6c29SRuslan Bukin 	 * start IP and end the block.
961*74fe6c29SRuslan Bukin 	 */
962*74fe6c29SRuslan Bukin 	return pt_blk_proceed_with_trace(decoder, &insn, &iext);
963*74fe6c29SRuslan Bukin }
964*74fe6c29SRuslan Bukin 
pt_insn_skl014(const struct pt_insn * insn,const struct pt_insn_ext * iext)965*74fe6c29SRuslan Bukin static int pt_insn_skl014(const struct pt_insn *insn,
966*74fe6c29SRuslan Bukin 			  const struct pt_insn_ext *iext)
967*74fe6c29SRuslan Bukin {
968*74fe6c29SRuslan Bukin 	if (!insn || !iext)
969*74fe6c29SRuslan Bukin 		return 0;
970*74fe6c29SRuslan Bukin 
971*74fe6c29SRuslan Bukin 	switch (insn->iclass) {
972*74fe6c29SRuslan Bukin 	default:
973*74fe6c29SRuslan Bukin 		return 0;
974*74fe6c29SRuslan Bukin 
975*74fe6c29SRuslan Bukin 	case ptic_call:
976*74fe6c29SRuslan Bukin 	case ptic_jump:
977*74fe6c29SRuslan Bukin 		return iext->variant.branch.is_direct;
978*74fe6c29SRuslan Bukin 
979*74fe6c29SRuslan Bukin 	case ptic_other:
980*74fe6c29SRuslan Bukin 		return pt_insn_changes_cr3(insn, iext);
981*74fe6c29SRuslan Bukin 	}
982*74fe6c29SRuslan Bukin }
983*74fe6c29SRuslan Bukin 
984*74fe6c29SRuslan Bukin /* Proceed to the location of a synchronous disabled event with suppressed IP
985*74fe6c29SRuslan Bukin  * considering SKL014.
986*74fe6c29SRuslan Bukin  *
987*74fe6c29SRuslan Bukin  * We have a (synchronous) disabled event pending.  Proceed to the event
988*74fe6c29SRuslan Bukin  * location and indicate whether we were able to reach it.
989*74fe6c29SRuslan Bukin  *
990*74fe6c29SRuslan Bukin  * With SKL014 a TIP.PGD with suppressed IP may also be generated by a direct
991*74fe6c29SRuslan Bukin  * unconditional branch that clears FilterEn by jumping out of a filter region
992*74fe6c29SRuslan Bukin  * or into a TraceStop region.  Use the filter configuration to determine the
993*74fe6c29SRuslan Bukin  * exact branch the event binds to.
994*74fe6c29SRuslan Bukin  *
995*74fe6c29SRuslan Bukin  * The last instruction that was reached is stored in @insn/@iext.
996*74fe6c29SRuslan Bukin  *
997*74fe6c29SRuslan Bukin  * Returns a positive integer if the event location was reached.
998*74fe6c29SRuslan Bukin  * Returns zero if the event location was not reached.
999*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
1000*74fe6c29SRuslan Bukin  */
pt_blk_proceed_skl014(struct pt_block_decoder * decoder,struct pt_block * block,struct pt_insn * insn,struct pt_insn_ext * iext)1001*74fe6c29SRuslan Bukin static int pt_blk_proceed_skl014(struct pt_block_decoder *decoder,
1002*74fe6c29SRuslan Bukin 				 struct pt_block *block, struct pt_insn *insn,
1003*74fe6c29SRuslan Bukin 				 struct pt_insn_ext *iext)
1004*74fe6c29SRuslan Bukin {
1005*74fe6c29SRuslan Bukin 	const struct pt_conf_addr_filter *addr_filter;
1006*74fe6c29SRuslan Bukin 	int status;
1007*74fe6c29SRuslan Bukin 
1008*74fe6c29SRuslan Bukin 	if (!decoder || !block || !insn || !iext)
1009*74fe6c29SRuslan Bukin 		return -pte_internal;
1010*74fe6c29SRuslan Bukin 
1011*74fe6c29SRuslan Bukin 	addr_filter = &decoder->query.config.addr_filter;
1012*74fe6c29SRuslan Bukin 	for (;;) {
1013*74fe6c29SRuslan Bukin 		uint64_t ip;
1014*74fe6c29SRuslan Bukin 
1015*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_insn(decoder, block, insn, iext,
1016*74fe6c29SRuslan Bukin 						pt_insn_skl014);
1017*74fe6c29SRuslan Bukin 		if (status <= 0)
1018*74fe6c29SRuslan Bukin 			break;
1019*74fe6c29SRuslan Bukin 
1020*74fe6c29SRuslan Bukin 		/* The erratum doesn't apply if we can bind the event to a
1021*74fe6c29SRuslan Bukin 		 * CR3-changing instruction.
1022*74fe6c29SRuslan Bukin 		 */
1023*74fe6c29SRuslan Bukin 		if (pt_insn_changes_cr3(insn, iext))
1024*74fe6c29SRuslan Bukin 			break;
1025*74fe6c29SRuslan Bukin 
1026*74fe6c29SRuslan Bukin 		/* Check the filter against the branch target. */
1027*74fe6c29SRuslan Bukin 		status = pt_insn_next_ip(&ip, insn, iext);
1028*74fe6c29SRuslan Bukin 		if (status < 0)
1029*74fe6c29SRuslan Bukin 			break;
1030*74fe6c29SRuslan Bukin 
1031*74fe6c29SRuslan Bukin 		status = pt_filter_addr_check(addr_filter, ip);
1032*74fe6c29SRuslan Bukin 		if (status <= 0) {
1033*74fe6c29SRuslan Bukin 			/* We need to flip the indication.
1034*74fe6c29SRuslan Bukin 			 *
1035*74fe6c29SRuslan Bukin 			 * We reached the event location when @ip lies inside a
1036*74fe6c29SRuslan Bukin 			 * tracing-disabled region.
1037*74fe6c29SRuslan Bukin 			 */
1038*74fe6c29SRuslan Bukin 			if (!status)
1039*74fe6c29SRuslan Bukin 				status = 1;
1040*74fe6c29SRuslan Bukin 
1041*74fe6c29SRuslan Bukin 			break;
1042*74fe6c29SRuslan Bukin 		}
1043*74fe6c29SRuslan Bukin 
1044*74fe6c29SRuslan Bukin 		/* This is not the correct instruction.  Proceed past it and try
1045*74fe6c29SRuslan Bukin 		 * again.
1046*74fe6c29SRuslan Bukin 		 */
1047*74fe6c29SRuslan Bukin 		decoder->ip = ip;
1048*74fe6c29SRuslan Bukin 
1049*74fe6c29SRuslan Bukin 		/* End the block if the user asked us to.
1050*74fe6c29SRuslan Bukin 		 *
1051*74fe6c29SRuslan Bukin 		 * We only need to take care about direct near branches.
1052*74fe6c29SRuslan Bukin 		 * Indirect and far branches require trace and will naturally
1053*74fe6c29SRuslan Bukin 		 * end a block.
1054*74fe6c29SRuslan Bukin 		 */
1055*74fe6c29SRuslan Bukin 		if ((decoder->flags.variant.block.end_on_call &&
1056*74fe6c29SRuslan Bukin 		    (insn->iclass == ptic_call)) ||
1057*74fe6c29SRuslan Bukin 		    (decoder->flags.variant.block.end_on_jump &&
1058*74fe6c29SRuslan Bukin 		    (insn->iclass == ptic_jump)))
1059*74fe6c29SRuslan Bukin 			break;
1060*74fe6c29SRuslan Bukin 	}
1061*74fe6c29SRuslan Bukin 
1062*74fe6c29SRuslan Bukin 	return status;
1063*74fe6c29SRuslan Bukin }
1064*74fe6c29SRuslan Bukin 
1065*74fe6c29SRuslan Bukin /* Proceed to the event location for a disabled event.
1066*74fe6c29SRuslan Bukin  *
1067*74fe6c29SRuslan Bukin  * We have a (synchronous) disabled event pending.  Proceed to the event
1068*74fe6c29SRuslan Bukin  * location and indicate whether we were able to reach it.
1069*74fe6c29SRuslan Bukin  *
1070*74fe6c29SRuslan Bukin  * The last instruction that was reached is stored in @insn/@iext.
1071*74fe6c29SRuslan Bukin  *
1072*74fe6c29SRuslan Bukin  * Returns a positive integer if the event location was reached.
1073*74fe6c29SRuslan Bukin  * Returns zero if the event location was not reached.
1074*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
1075*74fe6c29SRuslan Bukin  */
pt_blk_proceed_to_disabled(struct pt_block_decoder * decoder,struct pt_block * block,struct pt_insn * insn,struct pt_insn_ext * iext,const struct pt_event * ev)1076*74fe6c29SRuslan Bukin static int pt_blk_proceed_to_disabled(struct pt_block_decoder *decoder,
1077*74fe6c29SRuslan Bukin 				      struct pt_block *block,
1078*74fe6c29SRuslan Bukin 				      struct pt_insn *insn,
1079*74fe6c29SRuslan Bukin 				      struct pt_insn_ext *iext,
1080*74fe6c29SRuslan Bukin 				      const struct pt_event *ev)
1081*74fe6c29SRuslan Bukin {
1082*74fe6c29SRuslan Bukin 	if (!decoder || !block || !ev)
1083*74fe6c29SRuslan Bukin 		return -pte_internal;
1084*74fe6c29SRuslan Bukin 
1085*74fe6c29SRuslan Bukin 	if (ev->ip_suppressed) {
1086*74fe6c29SRuslan Bukin 		/* Due to SKL014 the TIP.PGD payload may be suppressed also for
1087*74fe6c29SRuslan Bukin 		 * direct branches.
1088*74fe6c29SRuslan Bukin 		 *
1089*74fe6c29SRuslan Bukin 		 * If we don't have a filter configuration we assume that no
1090*74fe6c29SRuslan Bukin 		 * address filters were used and the erratum does not apply.
1091*74fe6c29SRuslan Bukin 		 *
1092*74fe6c29SRuslan Bukin 		 * We might otherwise disable tracing too early.
1093*74fe6c29SRuslan Bukin 		 */
1094*74fe6c29SRuslan Bukin 		if (decoder->query.config.addr_filter.config.addr_cfg &&
1095*74fe6c29SRuslan Bukin 		    decoder->query.config.errata.skl014)
1096*74fe6c29SRuslan Bukin 			return pt_blk_proceed_skl014(decoder, block, insn,
1097*74fe6c29SRuslan Bukin 						     iext);
1098*74fe6c29SRuslan Bukin 
1099*74fe6c29SRuslan Bukin 		/* A synchronous disabled event also binds to far branches and
1100*74fe6c29SRuslan Bukin 		 * CPL-changing instructions.  Both would require trace,
1101*74fe6c29SRuslan Bukin 		 * however, and are thus implicitly handled by erroring out.
1102*74fe6c29SRuslan Bukin 		 *
1103*74fe6c29SRuslan Bukin 		 * The would-require-trace error is handled by our caller.
1104*74fe6c29SRuslan Bukin 		 */
1105*74fe6c29SRuslan Bukin 		return pt_blk_proceed_to_insn(decoder, block, insn, iext,
1106*74fe6c29SRuslan Bukin 					      pt_insn_changes_cr3);
1107*74fe6c29SRuslan Bukin 	} else
1108*74fe6c29SRuslan Bukin 		return pt_blk_proceed_to_ip(decoder, block, insn, iext,
1109*74fe6c29SRuslan Bukin 					    ev->variant.disabled.ip);
1110*74fe6c29SRuslan Bukin }
1111*74fe6c29SRuslan Bukin 
1112*74fe6c29SRuslan Bukin /* Set the expected resume address for a synchronous disable.
1113*74fe6c29SRuslan Bukin  *
1114*74fe6c29SRuslan Bukin  * On a synchronous disable, @decoder->ip still points to the instruction to
1115*74fe6c29SRuslan Bukin  * which the event bound.  That's not where we expect tracing to resume.
1116*74fe6c29SRuslan Bukin  *
1117*74fe6c29SRuslan Bukin  * For calls, a fair assumption is that tracing resumes after returning from the
1118*74fe6c29SRuslan Bukin  * called function.  For other types of instructions, we simply don't know.
1119*74fe6c29SRuslan Bukin  *
1120*74fe6c29SRuslan Bukin  * Returns zero on success, a negative pt_error_code otherwise.
1121*74fe6c29SRuslan Bukin  */
pt_blk_set_disable_resume_ip(struct pt_block_decoder * decoder,const struct pt_insn * insn)1122*74fe6c29SRuslan Bukin static int pt_blk_set_disable_resume_ip(struct pt_block_decoder *decoder,
1123*74fe6c29SRuslan Bukin 					const struct pt_insn *insn)
1124*74fe6c29SRuslan Bukin {
1125*74fe6c29SRuslan Bukin 	if (!decoder || !insn)
1126*74fe6c29SRuslan Bukin 		return -pte_internal;
1127*74fe6c29SRuslan Bukin 
1128*74fe6c29SRuslan Bukin 	switch (insn->iclass) {
1129*74fe6c29SRuslan Bukin 	case ptic_call:
1130*74fe6c29SRuslan Bukin 	case ptic_far_call:
1131*74fe6c29SRuslan Bukin 		decoder->ip = insn->ip + insn->size;
1132*74fe6c29SRuslan Bukin 		break;
1133*74fe6c29SRuslan Bukin 
1134*74fe6c29SRuslan Bukin 	default:
1135*74fe6c29SRuslan Bukin 		decoder->ip = 0ull;
1136*74fe6c29SRuslan Bukin 		break;
1137*74fe6c29SRuslan Bukin 	}
1138*74fe6c29SRuslan Bukin 
1139*74fe6c29SRuslan Bukin 	return 0;
1140*74fe6c29SRuslan Bukin }
1141*74fe6c29SRuslan Bukin 
1142*74fe6c29SRuslan Bukin /* Proceed to the event location for an async paging event.
1143*74fe6c29SRuslan Bukin  *
1144*74fe6c29SRuslan Bukin  * We have an async paging event pending.  Proceed to the event location and
1145*74fe6c29SRuslan Bukin  * indicate whether we were able to reach it.  Needing trace in order to proceed
1146*74fe6c29SRuslan Bukin  * is not an error in this case but ends the block.
1147*74fe6c29SRuslan Bukin  *
1148*74fe6c29SRuslan Bukin  * Returns a positive integer if the event location was reached.
1149*74fe6c29SRuslan Bukin  * Returns zero if the event location was not reached.
1150*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
1151*74fe6c29SRuslan Bukin  */
pt_blk_proceed_to_async_paging(struct pt_block_decoder * decoder,struct pt_block * block,const struct pt_event * ev)1152*74fe6c29SRuslan Bukin static int pt_blk_proceed_to_async_paging(struct pt_block_decoder *decoder,
1153*74fe6c29SRuslan Bukin 					  struct pt_block *block,
1154*74fe6c29SRuslan Bukin 					  const struct pt_event *ev)
1155*74fe6c29SRuslan Bukin {
1156*74fe6c29SRuslan Bukin 	int status;
1157*74fe6c29SRuslan Bukin 
1158*74fe6c29SRuslan Bukin 	if (!decoder || !ev)
1159*74fe6c29SRuslan Bukin 		return -pte_internal;
1160*74fe6c29SRuslan Bukin 
1161*74fe6c29SRuslan Bukin 	/* Apply the event immediately if we don't have an IP. */
1162*74fe6c29SRuslan Bukin 	if (ev->ip_suppressed)
1163*74fe6c29SRuslan Bukin 		return 1;
1164*74fe6c29SRuslan Bukin 
1165*74fe6c29SRuslan Bukin 	status = pt_blk_proceed_to_ip_with_trace(decoder, block,
1166*74fe6c29SRuslan Bukin 						 ev->variant.async_paging.ip);
1167*74fe6c29SRuslan Bukin 	if (status < 0)
1168*74fe6c29SRuslan Bukin 		return status;
1169*74fe6c29SRuslan Bukin 
1170*74fe6c29SRuslan Bukin 	/* We may have reached the IP. */
1171*74fe6c29SRuslan Bukin 	return (decoder->ip == ev->variant.async_paging.ip ? 1 : 0);
1172*74fe6c29SRuslan Bukin }
1173*74fe6c29SRuslan Bukin 
1174*74fe6c29SRuslan Bukin /* Proceed to the event location for an async vmcs event.
1175*74fe6c29SRuslan Bukin  *
1176*74fe6c29SRuslan Bukin  * We have an async vmcs event pending.  Proceed to the event location and
1177*74fe6c29SRuslan Bukin  * indicate whether we were able to reach it.  Needing trace in order to proceed
1178*74fe6c29SRuslan Bukin  * is not an error in this case but ends the block.
1179*74fe6c29SRuslan Bukin  *
1180*74fe6c29SRuslan Bukin  * Returns a positive integer if the event location was reached.
1181*74fe6c29SRuslan Bukin  * Returns zero if the event location was not reached.
1182*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
1183*74fe6c29SRuslan Bukin  */
pt_blk_proceed_to_async_vmcs(struct pt_block_decoder * decoder,struct pt_block * block,const struct pt_event * ev)1184*74fe6c29SRuslan Bukin static int pt_blk_proceed_to_async_vmcs(struct pt_block_decoder *decoder,
1185*74fe6c29SRuslan Bukin 					struct pt_block *block,
1186*74fe6c29SRuslan Bukin 					const struct pt_event *ev)
1187*74fe6c29SRuslan Bukin {
1188*74fe6c29SRuslan Bukin 	int status;
1189*74fe6c29SRuslan Bukin 
1190*74fe6c29SRuslan Bukin 	if (!decoder || !ev)
1191*74fe6c29SRuslan Bukin 		return -pte_internal;
1192*74fe6c29SRuslan Bukin 
1193*74fe6c29SRuslan Bukin 	/* Apply the event immediately if we don't have an IP. */
1194*74fe6c29SRuslan Bukin 	if (ev->ip_suppressed)
1195*74fe6c29SRuslan Bukin 		return 1;
1196*74fe6c29SRuslan Bukin 
1197*74fe6c29SRuslan Bukin 	status = pt_blk_proceed_to_ip_with_trace(decoder, block,
1198*74fe6c29SRuslan Bukin 						 ev->variant.async_vmcs.ip);
1199*74fe6c29SRuslan Bukin 	if (status < 0)
1200*74fe6c29SRuslan Bukin 		return status;
1201*74fe6c29SRuslan Bukin 
1202*74fe6c29SRuslan Bukin 	/* We may have reached the IP. */
1203*74fe6c29SRuslan Bukin 	return (decoder->ip == ev->variant.async_vmcs.ip ? 1 : 0);
1204*74fe6c29SRuslan Bukin }
1205*74fe6c29SRuslan Bukin 
1206*74fe6c29SRuslan Bukin /* Proceed to the event location for an exec mode event.
1207*74fe6c29SRuslan Bukin  *
1208*74fe6c29SRuslan Bukin  * We have an exec mode event pending.  Proceed to the event location and
1209*74fe6c29SRuslan Bukin  * indicate whether we were able to reach it.  Needing trace in order to proceed
1210*74fe6c29SRuslan Bukin  * is not an error in this case but ends the block.
1211*74fe6c29SRuslan Bukin  *
1212*74fe6c29SRuslan Bukin  * Returns a positive integer if the event location was reached.
1213*74fe6c29SRuslan Bukin  * Returns zero if the event location was not reached.
1214*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
1215*74fe6c29SRuslan Bukin  */
pt_blk_proceed_to_exec_mode(struct pt_block_decoder * decoder,struct pt_block * block,const struct pt_event * ev)1216*74fe6c29SRuslan Bukin static int pt_blk_proceed_to_exec_mode(struct pt_block_decoder *decoder,
1217*74fe6c29SRuslan Bukin 				       struct pt_block *block,
1218*74fe6c29SRuslan Bukin 				       const struct pt_event *ev)
1219*74fe6c29SRuslan Bukin {
1220*74fe6c29SRuslan Bukin 	int status;
1221*74fe6c29SRuslan Bukin 
1222*74fe6c29SRuslan Bukin 	if (!decoder || !ev)
1223*74fe6c29SRuslan Bukin 		return -pte_internal;
1224*74fe6c29SRuslan Bukin 
1225*74fe6c29SRuslan Bukin 	/* Apply the event immediately if we don't have an IP. */
1226*74fe6c29SRuslan Bukin 	if (ev->ip_suppressed)
1227*74fe6c29SRuslan Bukin 		return 1;
1228*74fe6c29SRuslan Bukin 
1229*74fe6c29SRuslan Bukin 	status = pt_blk_proceed_to_ip_with_trace(decoder, block,
1230*74fe6c29SRuslan Bukin 						 ev->variant.exec_mode.ip);
1231*74fe6c29SRuslan Bukin 	if (status < 0)
1232*74fe6c29SRuslan Bukin 		return status;
1233*74fe6c29SRuslan Bukin 
1234*74fe6c29SRuslan Bukin 	/* We may have reached the IP. */
1235*74fe6c29SRuslan Bukin 	return (decoder->ip == ev->variant.exec_mode.ip ? 1 : 0);
1236*74fe6c29SRuslan Bukin }
1237*74fe6c29SRuslan Bukin 
1238*74fe6c29SRuslan Bukin /* Proceed to the event location for a ptwrite event.
1239*74fe6c29SRuslan Bukin  *
1240*74fe6c29SRuslan Bukin  * We have a ptwrite event pending.  Proceed to the event location and indicate
1241*74fe6c29SRuslan Bukin  * whether we were able to reach it.
1242*74fe6c29SRuslan Bukin  *
1243*74fe6c29SRuslan Bukin  * In case of the event binding to a ptwrite instruction, we pass beyond that
1244*74fe6c29SRuslan Bukin  * instruction and update the event to provide the instruction's IP.
1245*74fe6c29SRuslan Bukin  *
1246*74fe6c29SRuslan Bukin  * In the case of the event binding to an IP provided in the event, we move
1247*74fe6c29SRuslan Bukin  * beyond the instruction at that IP.
1248*74fe6c29SRuslan Bukin  *
1249*74fe6c29SRuslan Bukin  * Returns a positive integer if the event location was reached.
1250*74fe6c29SRuslan Bukin  * Returns zero if the event location was not reached.
1251*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
1252*74fe6c29SRuslan Bukin  */
pt_blk_proceed_to_ptwrite(struct pt_block_decoder * decoder,struct pt_block * block,struct pt_insn * insn,struct pt_insn_ext * iext,struct pt_event * ev)1253*74fe6c29SRuslan Bukin static int pt_blk_proceed_to_ptwrite(struct pt_block_decoder *decoder,
1254*74fe6c29SRuslan Bukin 				     struct pt_block *block,
1255*74fe6c29SRuslan Bukin 				     struct pt_insn *insn,
1256*74fe6c29SRuslan Bukin 				     struct pt_insn_ext *iext,
1257*74fe6c29SRuslan Bukin 				     struct pt_event *ev)
1258*74fe6c29SRuslan Bukin {
1259*74fe6c29SRuslan Bukin 	int status;
1260*74fe6c29SRuslan Bukin 
1261*74fe6c29SRuslan Bukin 	if (!insn || !ev)
1262*74fe6c29SRuslan Bukin 		return -pte_internal;
1263*74fe6c29SRuslan Bukin 
1264*74fe6c29SRuslan Bukin 	/* If we don't have an IP, the event binds to the next PTWRITE
1265*74fe6c29SRuslan Bukin 	 * instruction.
1266*74fe6c29SRuslan Bukin 	 *
1267*74fe6c29SRuslan Bukin 	 * If we have an IP it still binds to the next PTWRITE instruction but
1268*74fe6c29SRuslan Bukin 	 * now the IP tells us where that instruction is.  This makes most sense
1269*74fe6c29SRuslan Bukin 	 * when tracing is disabled and we don't have any other means of finding
1270*74fe6c29SRuslan Bukin 	 * the PTWRITE instruction.  We nevertheless distinguish the two cases,
1271*74fe6c29SRuslan Bukin 	 * here.
1272*74fe6c29SRuslan Bukin 	 *
1273*74fe6c29SRuslan Bukin 	 * In both cases, we move beyond the PTWRITE instruction, so it will be
1274*74fe6c29SRuslan Bukin 	 * the last instruction in the current block and @decoder->ip will point
1275*74fe6c29SRuslan Bukin 	 * to the instruction following it.
1276*74fe6c29SRuslan Bukin 	 */
1277*74fe6c29SRuslan Bukin 	if (ev->ip_suppressed) {
1278*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_insn(decoder, block, insn, iext,
1279*74fe6c29SRuslan Bukin 						pt_insn_is_ptwrite);
1280*74fe6c29SRuslan Bukin 		if (status <= 0)
1281*74fe6c29SRuslan Bukin 			return status;
1282*74fe6c29SRuslan Bukin 
1283*74fe6c29SRuslan Bukin 		/* We now know the IP of the PTWRITE instruction corresponding
1284*74fe6c29SRuslan Bukin 		 * to this event.  Fill it in to make it more convenient for the
1285*74fe6c29SRuslan Bukin 		 * user to process the event.
1286*74fe6c29SRuslan Bukin 		 */
1287*74fe6c29SRuslan Bukin 		ev->variant.ptwrite.ip = insn->ip;
1288*74fe6c29SRuslan Bukin 		ev->ip_suppressed = 0;
1289*74fe6c29SRuslan Bukin 	} else {
1290*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_ip(decoder, block, insn, iext,
1291*74fe6c29SRuslan Bukin 					      ev->variant.ptwrite.ip);
1292*74fe6c29SRuslan Bukin 		if (status <= 0)
1293*74fe6c29SRuslan Bukin 			return status;
1294*74fe6c29SRuslan Bukin 
1295*74fe6c29SRuslan Bukin 		/* We reached the PTWRITE instruction and @decoder->ip points to
1296*74fe6c29SRuslan Bukin 		 * it; @insn/@iext still contain the preceding instruction.
1297*74fe6c29SRuslan Bukin 		 *
1298*74fe6c29SRuslan Bukin 		 * Proceed beyond the PTWRITE to account for it.  Note that we
1299*74fe6c29SRuslan Bukin 		 * may still overflow the block, which would cause us to
1300*74fe6c29SRuslan Bukin 		 * postpone both instruction and event to the next block.
1301*74fe6c29SRuslan Bukin 		 */
1302*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_one_insn(decoder, block, insn, iext);
1303*74fe6c29SRuslan Bukin 		if (status <= 0)
1304*74fe6c29SRuslan Bukin 			return status;
1305*74fe6c29SRuslan Bukin 	}
1306*74fe6c29SRuslan Bukin 
1307*74fe6c29SRuslan Bukin 	return 1;
1308*74fe6c29SRuslan Bukin }
1309*74fe6c29SRuslan Bukin 
1310*74fe6c29SRuslan Bukin /* Try to work around erratum SKD022.
1311*74fe6c29SRuslan Bukin  *
1312*74fe6c29SRuslan Bukin  * If we get an asynchronous disable on VMLAUNCH or VMRESUME, the FUP that
1313*74fe6c29SRuslan Bukin  * caused the disable to be asynchronous might have been bogous.
1314*74fe6c29SRuslan Bukin  *
1315*74fe6c29SRuslan Bukin  * Returns a positive integer if the erratum has been handled.
1316*74fe6c29SRuslan Bukin  * Returns zero if the erratum does not apply.
1317*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
1318*74fe6c29SRuslan Bukin  */
pt_blk_handle_erratum_skd022(struct pt_block_decoder * decoder,struct pt_event * ev)1319*74fe6c29SRuslan Bukin static int pt_blk_handle_erratum_skd022(struct pt_block_decoder *decoder,
1320*74fe6c29SRuslan Bukin 					struct pt_event *ev)
1321*74fe6c29SRuslan Bukin {
1322*74fe6c29SRuslan Bukin 	struct pt_insn_ext iext;
1323*74fe6c29SRuslan Bukin 	struct pt_insn insn;
1324*74fe6c29SRuslan Bukin 	int errcode;
1325*74fe6c29SRuslan Bukin 
1326*74fe6c29SRuslan Bukin 	if (!decoder || !ev)
1327*74fe6c29SRuslan Bukin 		return -pte_internal;
1328*74fe6c29SRuslan Bukin 
1329*74fe6c29SRuslan Bukin 	insn.mode = decoder->mode;
1330*74fe6c29SRuslan Bukin 	insn.ip = ev->variant.async_disabled.at;
1331*74fe6c29SRuslan Bukin 
1332*74fe6c29SRuslan Bukin 	errcode = pt_insn_decode(&insn, &iext, decoder->image, &decoder->asid);
1333*74fe6c29SRuslan Bukin 	if (errcode < 0)
1334*74fe6c29SRuslan Bukin 		return 0;
1335*74fe6c29SRuslan Bukin 
1336*74fe6c29SRuslan Bukin 	switch (iext.iclass) {
1337*74fe6c29SRuslan Bukin 	default:
1338*74fe6c29SRuslan Bukin 		/* The erratum does not apply. */
1339*74fe6c29SRuslan Bukin 		return 0;
1340*74fe6c29SRuslan Bukin 
1341*74fe6c29SRuslan Bukin 	case PTI_INST_VMLAUNCH:
1342*74fe6c29SRuslan Bukin 	case PTI_INST_VMRESUME:
1343*74fe6c29SRuslan Bukin 		/* The erratum may apply.  We can't be sure without a lot more
1344*74fe6c29SRuslan Bukin 		 * analysis.  Let's assume it does.
1345*74fe6c29SRuslan Bukin 		 *
1346*74fe6c29SRuslan Bukin 		 * We turn the async disable into a sync disable.  Our caller
1347*74fe6c29SRuslan Bukin 		 * will restart event processing.
1348*74fe6c29SRuslan Bukin 		 */
1349*74fe6c29SRuslan Bukin 		ev->type = ptev_disabled;
1350*74fe6c29SRuslan Bukin 		ev->variant.disabled.ip = ev->variant.async_disabled.ip;
1351*74fe6c29SRuslan Bukin 
1352*74fe6c29SRuslan Bukin 		return 1;
1353*74fe6c29SRuslan Bukin 	}
1354*74fe6c29SRuslan Bukin }
1355*74fe6c29SRuslan Bukin 
1356*74fe6c29SRuslan Bukin /* Postpone proceeding past @insn/@iext and indicate a pending event.
1357*74fe6c29SRuslan Bukin  *
1358*74fe6c29SRuslan Bukin  * There may be further events pending on @insn/@iext.  Postpone proceeding past
1359*74fe6c29SRuslan Bukin  * @insn/@iext until we processed all events that bind to it.
1360*74fe6c29SRuslan Bukin  *
1361*74fe6c29SRuslan Bukin  * Returns a non-negative pt_status_flag bit-vector indicating a pending event
1362*74fe6c29SRuslan Bukin  * on success, a negative pt_error_code otherwise.
1363*74fe6c29SRuslan Bukin  */
pt_blk_postpone_insn(struct pt_block_decoder * decoder,const struct pt_insn * insn,const struct pt_insn_ext * iext)1364*74fe6c29SRuslan Bukin static int pt_blk_postpone_insn(struct pt_block_decoder *decoder,
1365*74fe6c29SRuslan Bukin 				const struct pt_insn *insn,
1366*74fe6c29SRuslan Bukin 				const struct pt_insn_ext *iext)
1367*74fe6c29SRuslan Bukin {
1368*74fe6c29SRuslan Bukin 	if (!decoder || !insn || !iext)
1369*74fe6c29SRuslan Bukin 		return -pte_internal;
1370*74fe6c29SRuslan Bukin 
1371*74fe6c29SRuslan Bukin 	/* Only one can be active. */
1372*74fe6c29SRuslan Bukin 	if (decoder->process_insn)
1373*74fe6c29SRuslan Bukin 		return -pte_internal;
1374*74fe6c29SRuslan Bukin 
1375*74fe6c29SRuslan Bukin 	decoder->process_insn = 1;
1376*74fe6c29SRuslan Bukin 	decoder->insn = *insn;
1377*74fe6c29SRuslan Bukin 	decoder->iext = *iext;
1378*74fe6c29SRuslan Bukin 
1379*74fe6c29SRuslan Bukin 	return pt_blk_status(decoder, pts_event_pending);
1380*74fe6c29SRuslan Bukin }
1381*74fe6c29SRuslan Bukin 
1382*74fe6c29SRuslan Bukin /* Remove any postponed instruction from @decoder.
1383*74fe6c29SRuslan Bukin  *
1384*74fe6c29SRuslan Bukin  * Returns zero on success, a negative pt_error_code otherwise.
1385*74fe6c29SRuslan Bukin  */
pt_blk_clear_postponed_insn(struct pt_block_decoder * decoder)1386*74fe6c29SRuslan Bukin static int pt_blk_clear_postponed_insn(struct pt_block_decoder *decoder)
1387*74fe6c29SRuslan Bukin {
1388*74fe6c29SRuslan Bukin 	if (!decoder)
1389*74fe6c29SRuslan Bukin 		return -pte_internal;
1390*74fe6c29SRuslan Bukin 
1391*74fe6c29SRuslan Bukin 	decoder->process_insn = 0;
1392*74fe6c29SRuslan Bukin 	decoder->bound_paging = 0;
1393*74fe6c29SRuslan Bukin 	decoder->bound_vmcs = 0;
1394*74fe6c29SRuslan Bukin 	decoder->bound_ptwrite = 0;
1395*74fe6c29SRuslan Bukin 
1396*74fe6c29SRuslan Bukin 	return 0;
1397*74fe6c29SRuslan Bukin }
1398*74fe6c29SRuslan Bukin 
1399*74fe6c29SRuslan Bukin /* Proceed past a postponed instruction.
1400*74fe6c29SRuslan Bukin  *
1401*74fe6c29SRuslan Bukin  * If an instruction has been postponed in @decoder, proceed past it.
1402*74fe6c29SRuslan Bukin  *
1403*74fe6c29SRuslan Bukin  * Returns zero on success, a negative pt_error_code otherwise.
1404*74fe6c29SRuslan Bukin  */
pt_blk_proceed_postponed_insn(struct pt_block_decoder * decoder)1405*74fe6c29SRuslan Bukin static int pt_blk_proceed_postponed_insn(struct pt_block_decoder *decoder)
1406*74fe6c29SRuslan Bukin {
1407*74fe6c29SRuslan Bukin 	int status;
1408*74fe6c29SRuslan Bukin 
1409*74fe6c29SRuslan Bukin 	if (!decoder)
1410*74fe6c29SRuslan Bukin 		return -pte_internal;
1411*74fe6c29SRuslan Bukin 
1412*74fe6c29SRuslan Bukin 	/* There's nothing to do if we have no postponed instruction. */
1413*74fe6c29SRuslan Bukin 	if (!decoder->process_insn)
1414*74fe6c29SRuslan Bukin 		return 0;
1415*74fe6c29SRuslan Bukin 
1416*74fe6c29SRuslan Bukin 	/* There's nothing to do if tracing got disabled. */
1417*74fe6c29SRuslan Bukin 	if (!decoder->enabled)
1418*74fe6c29SRuslan Bukin 		return pt_blk_clear_postponed_insn(decoder);
1419*74fe6c29SRuslan Bukin 
1420*74fe6c29SRuslan Bukin 	status = pt_insn_next_ip(&decoder->ip, &decoder->insn, &decoder->iext);
1421*74fe6c29SRuslan Bukin 	if (status < 0) {
1422*74fe6c29SRuslan Bukin 		if (status != -pte_bad_query)
1423*74fe6c29SRuslan Bukin 			return status;
1424*74fe6c29SRuslan Bukin 
1425*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_with_trace(decoder, &decoder->insn,
1426*74fe6c29SRuslan Bukin 						   &decoder->iext);
1427*74fe6c29SRuslan Bukin 		if (status < 0)
1428*74fe6c29SRuslan Bukin 			return status;
1429*74fe6c29SRuslan Bukin 	}
1430*74fe6c29SRuslan Bukin 
1431*74fe6c29SRuslan Bukin 	return pt_blk_clear_postponed_insn(decoder);
1432*74fe6c29SRuslan Bukin }
1433*74fe6c29SRuslan Bukin 
1434*74fe6c29SRuslan Bukin /* Proceed to the next event.
1435*74fe6c29SRuslan Bukin  *
1436*74fe6c29SRuslan Bukin  * We have an event pending.  Proceed to the event location and indicate the
1437*74fe6c29SRuslan Bukin  * event to the user.
1438*74fe6c29SRuslan Bukin  *
1439*74fe6c29SRuslan Bukin  * On our way to the event location we may also be forced to postpone the event
1440*74fe6c29SRuslan Bukin  * to the next block, e.g. if we overflow the number of instructions in the
1441*74fe6c29SRuslan Bukin  * block or if we need trace in order to reach the event location.
1442*74fe6c29SRuslan Bukin  *
1443*74fe6c29SRuslan Bukin  * If we're not able to reach the event location, we return zero.  This is what
1444*74fe6c29SRuslan Bukin  * pt_blk_status() would return since:
1445*74fe6c29SRuslan Bukin  *
1446*74fe6c29SRuslan Bukin  *   - we suppress pts_eos as long as we're processing events
1447*74fe6c29SRuslan Bukin  *   - we do not set pts_ip_suppressed since tracing must be enabled
1448*74fe6c29SRuslan Bukin  *
1449*74fe6c29SRuslan Bukin  * Returns a non-negative pt_status_flag bit-vector on success, a negative error
1450*74fe6c29SRuslan Bukin  * code otherwise.
1451*74fe6c29SRuslan Bukin  */
pt_blk_proceed_event(struct pt_block_decoder * decoder,struct pt_block * block)1452*74fe6c29SRuslan Bukin static int pt_blk_proceed_event(struct pt_block_decoder *decoder,
1453*74fe6c29SRuslan Bukin 				struct pt_block *block)
1454*74fe6c29SRuslan Bukin {
1455*74fe6c29SRuslan Bukin 	struct pt_insn_ext iext;
1456*74fe6c29SRuslan Bukin 	struct pt_insn insn;
1457*74fe6c29SRuslan Bukin 	struct pt_event *ev;
1458*74fe6c29SRuslan Bukin 	int status;
1459*74fe6c29SRuslan Bukin 
1460*74fe6c29SRuslan Bukin 	if (!decoder || !decoder->process_event || !block)
1461*74fe6c29SRuslan Bukin 		return -pte_internal;
1462*74fe6c29SRuslan Bukin 
1463*74fe6c29SRuslan Bukin 	ev = &decoder->event;
1464*74fe6c29SRuslan Bukin 	switch (ev->type) {
1465*74fe6c29SRuslan Bukin 	case ptev_enabled:
1466*74fe6c29SRuslan Bukin 		break;
1467*74fe6c29SRuslan Bukin 
1468*74fe6c29SRuslan Bukin 	case ptev_disabled:
1469*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_disabled(decoder, block, &insn,
1470*74fe6c29SRuslan Bukin 						    &iext, ev);
1471*74fe6c29SRuslan Bukin 		if (status <= 0) {
1472*74fe6c29SRuslan Bukin 			/* A synchronous disable event also binds to the next
1473*74fe6c29SRuslan Bukin 			 * indirect or conditional branch, i.e. to any branch
1474*74fe6c29SRuslan Bukin 			 * that would have required trace.
1475*74fe6c29SRuslan Bukin 			 */
1476*74fe6c29SRuslan Bukin 			if (status != -pte_bad_query)
1477*74fe6c29SRuslan Bukin 				return status;
1478*74fe6c29SRuslan Bukin 
1479*74fe6c29SRuslan Bukin 			status = pt_blk_set_disable_resume_ip(decoder, &insn);
1480*74fe6c29SRuslan Bukin 			if (status < 0)
1481*74fe6c29SRuslan Bukin 				return status;
1482*74fe6c29SRuslan Bukin 		}
1483*74fe6c29SRuslan Bukin 
1484*74fe6c29SRuslan Bukin 		break;
1485*74fe6c29SRuslan Bukin 
1486*74fe6c29SRuslan Bukin 	case ptev_async_disabled:
1487*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_ip(decoder, block, &insn, &iext,
1488*74fe6c29SRuslan Bukin 					      ev->variant.async_disabled.at);
1489*74fe6c29SRuslan Bukin 		if (status <= 0)
1490*74fe6c29SRuslan Bukin 			return status;
1491*74fe6c29SRuslan Bukin 
1492*74fe6c29SRuslan Bukin 		if (decoder->query.config.errata.skd022) {
1493*74fe6c29SRuslan Bukin 			status = pt_blk_handle_erratum_skd022(decoder, ev);
1494*74fe6c29SRuslan Bukin 			if (status != 0) {
1495*74fe6c29SRuslan Bukin 				if (status < 0)
1496*74fe6c29SRuslan Bukin 					return status;
1497*74fe6c29SRuslan Bukin 
1498*74fe6c29SRuslan Bukin 				/* If the erratum hits, we modify the event.
1499*74fe6c29SRuslan Bukin 				 * Try again.
1500*74fe6c29SRuslan Bukin 				 */
1501*74fe6c29SRuslan Bukin 				return pt_blk_proceed_event(decoder, block);
1502*74fe6c29SRuslan Bukin 			}
1503*74fe6c29SRuslan Bukin 		}
1504*74fe6c29SRuslan Bukin 
1505*74fe6c29SRuslan Bukin 		break;
1506*74fe6c29SRuslan Bukin 
1507*74fe6c29SRuslan Bukin 	case ptev_async_branch:
1508*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_ip(decoder, block, &insn, &iext,
1509*74fe6c29SRuslan Bukin 					      ev->variant.async_branch.from);
1510*74fe6c29SRuslan Bukin 		if (status <= 0)
1511*74fe6c29SRuslan Bukin 			return status;
1512*74fe6c29SRuslan Bukin 
1513*74fe6c29SRuslan Bukin 		break;
1514*74fe6c29SRuslan Bukin 
1515*74fe6c29SRuslan Bukin 	case ptev_paging:
1516*74fe6c29SRuslan Bukin 		if (!decoder->enabled)
1517*74fe6c29SRuslan Bukin 			break;
1518*74fe6c29SRuslan Bukin 
1519*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_insn(decoder, block, &insn, &iext,
1520*74fe6c29SRuslan Bukin 						pt_insn_binds_to_pip);
1521*74fe6c29SRuslan Bukin 		if (status <= 0)
1522*74fe6c29SRuslan Bukin 			return status;
1523*74fe6c29SRuslan Bukin 
1524*74fe6c29SRuslan Bukin 		/* We bound a paging event.  Make sure we do not bind further
1525*74fe6c29SRuslan Bukin 		 * paging events to this instruction.
1526*74fe6c29SRuslan Bukin 		 */
1527*74fe6c29SRuslan Bukin 		decoder->bound_paging = 1;
1528*74fe6c29SRuslan Bukin 
1529*74fe6c29SRuslan Bukin 		return pt_blk_postpone_insn(decoder, &insn, &iext);
1530*74fe6c29SRuslan Bukin 
1531*74fe6c29SRuslan Bukin 	case ptev_async_paging:
1532*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_async_paging(decoder, block, ev);
1533*74fe6c29SRuslan Bukin 		if (status <= 0)
1534*74fe6c29SRuslan Bukin 			return status;
1535*74fe6c29SRuslan Bukin 
1536*74fe6c29SRuslan Bukin 		break;
1537*74fe6c29SRuslan Bukin 
1538*74fe6c29SRuslan Bukin 	case ptev_vmcs:
1539*74fe6c29SRuslan Bukin 		if (!decoder->enabled)
1540*74fe6c29SRuslan Bukin 			break;
1541*74fe6c29SRuslan Bukin 
1542*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_insn(decoder, block, &insn, &iext,
1543*74fe6c29SRuslan Bukin 						pt_insn_binds_to_vmcs);
1544*74fe6c29SRuslan Bukin 		if (status <= 0)
1545*74fe6c29SRuslan Bukin 			return status;
1546*74fe6c29SRuslan Bukin 
1547*74fe6c29SRuslan Bukin 		/* We bound a vmcs event.  Make sure we do not bind further vmcs
1548*74fe6c29SRuslan Bukin 		 * events to this instruction.
1549*74fe6c29SRuslan Bukin 		 */
1550*74fe6c29SRuslan Bukin 		decoder->bound_vmcs = 1;
1551*74fe6c29SRuslan Bukin 
1552*74fe6c29SRuslan Bukin 		return pt_blk_postpone_insn(decoder, &insn, &iext);
1553*74fe6c29SRuslan Bukin 
1554*74fe6c29SRuslan Bukin 	case ptev_async_vmcs:
1555*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_async_vmcs(decoder, block, ev);
1556*74fe6c29SRuslan Bukin 		if (status <= 0)
1557*74fe6c29SRuslan Bukin 			return status;
1558*74fe6c29SRuslan Bukin 
1559*74fe6c29SRuslan Bukin 		break;
1560*74fe6c29SRuslan Bukin 
1561*74fe6c29SRuslan Bukin 	case ptev_overflow:
1562*74fe6c29SRuslan Bukin 		break;
1563*74fe6c29SRuslan Bukin 
1564*74fe6c29SRuslan Bukin 	case ptev_exec_mode:
1565*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_exec_mode(decoder, block, ev);
1566*74fe6c29SRuslan Bukin 		if (status <= 0)
1567*74fe6c29SRuslan Bukin 			return status;
1568*74fe6c29SRuslan Bukin 
1569*74fe6c29SRuslan Bukin 		break;
1570*74fe6c29SRuslan Bukin 
1571*74fe6c29SRuslan Bukin 	case ptev_tsx:
1572*74fe6c29SRuslan Bukin 		if (ev->ip_suppressed)
1573*74fe6c29SRuslan Bukin 			break;
1574*74fe6c29SRuslan Bukin 
1575*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_ip(decoder, block, &insn, &iext,
1576*74fe6c29SRuslan Bukin 					      ev->variant.tsx.ip);
1577*74fe6c29SRuslan Bukin 		if (status <= 0)
1578*74fe6c29SRuslan Bukin 			return status;
1579*74fe6c29SRuslan Bukin 
1580*74fe6c29SRuslan Bukin 		break;
1581*74fe6c29SRuslan Bukin 
1582*74fe6c29SRuslan Bukin 	case ptev_stop:
1583*74fe6c29SRuslan Bukin 		break;
1584*74fe6c29SRuslan Bukin 
1585*74fe6c29SRuslan Bukin 	case ptev_exstop:
1586*74fe6c29SRuslan Bukin 		if (!decoder->enabled || ev->ip_suppressed)
1587*74fe6c29SRuslan Bukin 			break;
1588*74fe6c29SRuslan Bukin 
1589*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_ip(decoder, block, &insn, &iext,
1590*74fe6c29SRuslan Bukin 					      ev->variant.exstop.ip);
1591*74fe6c29SRuslan Bukin 		if (status <= 0)
1592*74fe6c29SRuslan Bukin 			return status;
1593*74fe6c29SRuslan Bukin 
1594*74fe6c29SRuslan Bukin 		break;
1595*74fe6c29SRuslan Bukin 
1596*74fe6c29SRuslan Bukin 	case ptev_mwait:
1597*74fe6c29SRuslan Bukin 		if (!decoder->enabled || ev->ip_suppressed)
1598*74fe6c29SRuslan Bukin 			break;
1599*74fe6c29SRuslan Bukin 
1600*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_ip(decoder, block, &insn, &iext,
1601*74fe6c29SRuslan Bukin 					      ev->variant.mwait.ip);
1602*74fe6c29SRuslan Bukin 		if (status <= 0)
1603*74fe6c29SRuslan Bukin 			return status;
1604*74fe6c29SRuslan Bukin 
1605*74fe6c29SRuslan Bukin 		break;
1606*74fe6c29SRuslan Bukin 
1607*74fe6c29SRuslan Bukin 	case ptev_pwre:
1608*74fe6c29SRuslan Bukin 	case ptev_pwrx:
1609*74fe6c29SRuslan Bukin 		break;
1610*74fe6c29SRuslan Bukin 
1611*74fe6c29SRuslan Bukin 	case ptev_ptwrite:
1612*74fe6c29SRuslan Bukin 		if (!decoder->enabled)
1613*74fe6c29SRuslan Bukin 			break;
1614*74fe6c29SRuslan Bukin 
1615*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_to_ptwrite(decoder, block, &insn,
1616*74fe6c29SRuslan Bukin 						   &iext, ev);
1617*74fe6c29SRuslan Bukin 		if (status <= 0)
1618*74fe6c29SRuslan Bukin 			return status;
1619*74fe6c29SRuslan Bukin 
1620*74fe6c29SRuslan Bukin 		/* We bound a ptwrite event.  Make sure we do not bind further
1621*74fe6c29SRuslan Bukin 		 * ptwrite events to this instruction.
1622*74fe6c29SRuslan Bukin 		 */
1623*74fe6c29SRuslan Bukin 		decoder->bound_ptwrite = 1;
1624*74fe6c29SRuslan Bukin 
1625*74fe6c29SRuslan Bukin 		return pt_blk_postpone_insn(decoder, &insn, &iext);
1626*74fe6c29SRuslan Bukin 
1627*74fe6c29SRuslan Bukin 	case ptev_tick:
1628*74fe6c29SRuslan Bukin 	case ptev_cbr:
1629*74fe6c29SRuslan Bukin 	case ptev_mnt:
1630*74fe6c29SRuslan Bukin 		break;
1631*74fe6c29SRuslan Bukin 	}
1632*74fe6c29SRuslan Bukin 
1633*74fe6c29SRuslan Bukin 	return pt_blk_status(decoder, pts_event_pending);
1634*74fe6c29SRuslan Bukin }
1635*74fe6c29SRuslan Bukin 
1636*74fe6c29SRuslan Bukin /* Proceed to the next decision point without using the block cache.
1637*74fe6c29SRuslan Bukin  *
1638*74fe6c29SRuslan Bukin  * Tracing is enabled and we don't have an event pending.  Proceed as far as
1639*74fe6c29SRuslan Bukin  * we get without trace.  Stop when we either:
1640*74fe6c29SRuslan Bukin  *
1641*74fe6c29SRuslan Bukin  *   - need trace in order to continue
1642*74fe6c29SRuslan Bukin  *   - overflow the max number of instructions in a block
1643*74fe6c29SRuslan Bukin  *
1644*74fe6c29SRuslan Bukin  * We actually proceed one instruction further to get the start IP for the next
1645*74fe6c29SRuslan Bukin  * block.  This only updates @decoder's internal state, though.
1646*74fe6c29SRuslan Bukin  *
1647*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
1648*74fe6c29SRuslan Bukin  */
pt_blk_proceed_no_event_uncached(struct pt_block_decoder * decoder,struct pt_block * block)1649*74fe6c29SRuslan Bukin static int pt_blk_proceed_no_event_uncached(struct pt_block_decoder *decoder,
1650*74fe6c29SRuslan Bukin 					    struct pt_block *block)
1651*74fe6c29SRuslan Bukin {
1652*74fe6c29SRuslan Bukin 	struct pt_insn_ext iext;
1653*74fe6c29SRuslan Bukin 	struct pt_insn insn;
1654*74fe6c29SRuslan Bukin 	int status;
1655*74fe6c29SRuslan Bukin 
1656*74fe6c29SRuslan Bukin 	if (!decoder || !block)
1657*74fe6c29SRuslan Bukin 		return -pte_internal;
1658*74fe6c29SRuslan Bukin 
1659*74fe6c29SRuslan Bukin 	/* This is overly conservative, really.  We shouldn't get a bad-query
1660*74fe6c29SRuslan Bukin 	 * status unless we decoded at least one instruction successfully.
1661*74fe6c29SRuslan Bukin 	 */
1662*74fe6c29SRuslan Bukin 	memset(&insn, 0, sizeof(insn));
1663*74fe6c29SRuslan Bukin 	memset(&iext, 0, sizeof(iext));
1664*74fe6c29SRuslan Bukin 
1665*74fe6c29SRuslan Bukin 	/* Proceed as far as we get without trace. */
1666*74fe6c29SRuslan Bukin 	status = pt_blk_proceed_to_insn(decoder, block, &insn, &iext,
1667*74fe6c29SRuslan Bukin 					pt_insn_false);
1668*74fe6c29SRuslan Bukin 	if (status < 0) {
1669*74fe6c29SRuslan Bukin 		if (status != -pte_bad_query)
1670*74fe6c29SRuslan Bukin 			return status;
1671*74fe6c29SRuslan Bukin 
1672*74fe6c29SRuslan Bukin 		return pt_blk_proceed_with_trace(decoder, &insn, &iext);
1673*74fe6c29SRuslan Bukin 	}
1674*74fe6c29SRuslan Bukin 
1675*74fe6c29SRuslan Bukin 	return 0;
1676*74fe6c29SRuslan Bukin }
1677*74fe6c29SRuslan Bukin 
1678*74fe6c29SRuslan Bukin /* Check if @ip is contained in @section loaded at @laddr.
1679*74fe6c29SRuslan Bukin  *
1680*74fe6c29SRuslan Bukin  * Returns non-zero if it is.
1681*74fe6c29SRuslan Bukin  * Returns zero if it isn't or of @section is NULL.
1682*74fe6c29SRuslan Bukin  */
pt_blk_is_in_section(const struct pt_mapped_section * msec,uint64_t ip)1683*74fe6c29SRuslan Bukin static inline int pt_blk_is_in_section(const struct pt_mapped_section *msec,
1684*74fe6c29SRuslan Bukin 				       uint64_t ip)
1685*74fe6c29SRuslan Bukin {
1686*74fe6c29SRuslan Bukin 	uint64_t begin, end;
1687*74fe6c29SRuslan Bukin 
1688*74fe6c29SRuslan Bukin 	begin = pt_msec_begin(msec);
1689*74fe6c29SRuslan Bukin 	end = pt_msec_end(msec);
1690*74fe6c29SRuslan Bukin 
1691*74fe6c29SRuslan Bukin 	return (begin <= ip && ip < end);
1692*74fe6c29SRuslan Bukin }
1693*74fe6c29SRuslan Bukin 
1694*74fe6c29SRuslan Bukin /* Insert a trampoline block cache entry.
1695*74fe6c29SRuslan Bukin  *
1696*74fe6c29SRuslan Bukin  * Add a trampoline block cache entry at @ip to continue at @nip, where @nip
1697*74fe6c29SRuslan Bukin  * must be the next instruction after @ip.
1698*74fe6c29SRuslan Bukin  *
1699*74fe6c29SRuslan Bukin  * Both @ip and @nip must be section-relative
1700*74fe6c29SRuslan Bukin  *
1701*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
1702*74fe6c29SRuslan Bukin  */
pt_blk_add_trampoline(struct pt_block_cache * bcache,uint64_t ip,uint64_t nip,enum pt_exec_mode mode)1703*74fe6c29SRuslan Bukin static inline int pt_blk_add_trampoline(struct pt_block_cache *bcache,
1704*74fe6c29SRuslan Bukin 					uint64_t ip, uint64_t nip,
1705*74fe6c29SRuslan Bukin 					enum pt_exec_mode mode)
1706*74fe6c29SRuslan Bukin {
1707*74fe6c29SRuslan Bukin 	struct pt_bcache_entry bce;
1708*74fe6c29SRuslan Bukin 	int64_t disp;
1709*74fe6c29SRuslan Bukin 
1710*74fe6c29SRuslan Bukin 	/* The displacement from @ip to @nip for the trampoline. */
1711*74fe6c29SRuslan Bukin 	disp = (int64_t) (nip - ip);
1712*74fe6c29SRuslan Bukin 
1713*74fe6c29SRuslan Bukin 	memset(&bce, 0, sizeof(bce));
1714*74fe6c29SRuslan Bukin 	bce.displacement = (int32_t) disp;
1715*74fe6c29SRuslan Bukin 	bce.ninsn = 1;
1716*74fe6c29SRuslan Bukin 	bce.mode = mode;
1717*74fe6c29SRuslan Bukin 	bce.qualifier = ptbq_again;
1718*74fe6c29SRuslan Bukin 
1719*74fe6c29SRuslan Bukin 	/* If we can't reach @nip without overflowing the displacement field, we
1720*74fe6c29SRuslan Bukin 	 * have to stop and re-decode the instruction at @ip.
1721*74fe6c29SRuslan Bukin 	 */
1722*74fe6c29SRuslan Bukin 	if ((int64_t) bce.displacement != disp) {
1723*74fe6c29SRuslan Bukin 
1724*74fe6c29SRuslan Bukin 		memset(&bce, 0, sizeof(bce));
1725*74fe6c29SRuslan Bukin 		bce.ninsn = 1;
1726*74fe6c29SRuslan Bukin 		bce.mode = mode;
1727*74fe6c29SRuslan Bukin 		bce.qualifier = ptbq_decode;
1728*74fe6c29SRuslan Bukin 	}
1729*74fe6c29SRuslan Bukin 
1730*74fe6c29SRuslan Bukin 	return pt_bcache_add(bcache, ip, bce);
1731*74fe6c29SRuslan Bukin }
1732*74fe6c29SRuslan Bukin 
1733*74fe6c29SRuslan Bukin /* Insert a decode block cache entry.
1734*74fe6c29SRuslan Bukin  *
1735*74fe6c29SRuslan Bukin  * Add a decode block cache entry at @ioff.
1736*74fe6c29SRuslan Bukin  *
1737*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
1738*74fe6c29SRuslan Bukin  */
pt_blk_add_decode(struct pt_block_cache * bcache,uint64_t ioff,enum pt_exec_mode mode)1739*74fe6c29SRuslan Bukin static inline int pt_blk_add_decode(struct pt_block_cache *bcache,
1740*74fe6c29SRuslan Bukin 				    uint64_t ioff, enum pt_exec_mode mode)
1741*74fe6c29SRuslan Bukin {
1742*74fe6c29SRuslan Bukin 	struct pt_bcache_entry bce;
1743*74fe6c29SRuslan Bukin 
1744*74fe6c29SRuslan Bukin 	memset(&bce, 0, sizeof(bce));
1745*74fe6c29SRuslan Bukin 	bce.ninsn = 1;
1746*74fe6c29SRuslan Bukin 	bce.mode = mode;
1747*74fe6c29SRuslan Bukin 	bce.qualifier = ptbq_decode;
1748*74fe6c29SRuslan Bukin 
1749*74fe6c29SRuslan Bukin 	return pt_bcache_add(bcache, ioff, bce);
1750*74fe6c29SRuslan Bukin }
1751*74fe6c29SRuslan Bukin 
1752*74fe6c29SRuslan Bukin enum {
1753*74fe6c29SRuslan Bukin 	/* The maximum number of steps when filling the block cache. */
1754*74fe6c29SRuslan Bukin 	bcache_fill_steps	= 0x400
1755*74fe6c29SRuslan Bukin };
1756*74fe6c29SRuslan Bukin 
1757*74fe6c29SRuslan Bukin /* Proceed to the next instruction and fill the block cache for @decoder->ip.
1758*74fe6c29SRuslan Bukin  *
1759*74fe6c29SRuslan Bukin  * Tracing is enabled and we don't have an event pending.  The current IP is not
1760*74fe6c29SRuslan Bukin  * yet cached.
1761*74fe6c29SRuslan Bukin  *
1762*74fe6c29SRuslan Bukin  * Proceed one instruction without using the block cache, then try to proceed
1763*74fe6c29SRuslan Bukin  * further using the block cache.
1764*74fe6c29SRuslan Bukin  *
1765*74fe6c29SRuslan Bukin  * On our way back, add a block cache entry for the IP before proceeding.  Note
1766*74fe6c29SRuslan Bukin  * that the recursion is bounded by @steps and ultimately by the maximum number
1767*74fe6c29SRuslan Bukin  * of instructions in a block.
1768*74fe6c29SRuslan Bukin  *
1769*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
1770*74fe6c29SRuslan Bukin  */
1771*74fe6c29SRuslan Bukin static int
pt_blk_proceed_no_event_fill_cache(struct pt_block_decoder * decoder,struct pt_block * block,struct pt_block_cache * bcache,const struct pt_mapped_section * msec,size_t steps)1772*74fe6c29SRuslan Bukin pt_blk_proceed_no_event_fill_cache(struct pt_block_decoder *decoder,
1773*74fe6c29SRuslan Bukin 				   struct pt_block *block,
1774*74fe6c29SRuslan Bukin 				   struct pt_block_cache *bcache,
1775*74fe6c29SRuslan Bukin 				   const struct pt_mapped_section *msec,
1776*74fe6c29SRuslan Bukin 				   size_t steps)
1777*74fe6c29SRuslan Bukin {
1778*74fe6c29SRuslan Bukin 	struct pt_bcache_entry bce;
1779*74fe6c29SRuslan Bukin 	struct pt_insn_ext iext;
1780*74fe6c29SRuslan Bukin 	struct pt_insn insn;
1781*74fe6c29SRuslan Bukin 	uint64_t nip, dip;
1782*74fe6c29SRuslan Bukin 	int64_t disp, ioff, noff;
1783*74fe6c29SRuslan Bukin 	int status;
1784*74fe6c29SRuslan Bukin 
1785*74fe6c29SRuslan Bukin 	if (!decoder || !steps)
1786*74fe6c29SRuslan Bukin 		return -pte_internal;
1787*74fe6c29SRuslan Bukin 
1788*74fe6c29SRuslan Bukin 	/* Proceed one instruction by decoding and examining it.
1789*74fe6c29SRuslan Bukin 	 *
1790*74fe6c29SRuslan Bukin 	 * Note that we also return on a status of zero that indicates that the
1791*74fe6c29SRuslan Bukin 	 * instruction didn't fit into @block.
1792*74fe6c29SRuslan Bukin 	 */
1793*74fe6c29SRuslan Bukin 	status = pt_blk_proceed_one_insn(decoder, block, &insn, &iext);
1794*74fe6c29SRuslan Bukin 	if (status <= 0)
1795*74fe6c29SRuslan Bukin 		return status;
1796*74fe6c29SRuslan Bukin 
1797*74fe6c29SRuslan Bukin 	ioff = pt_msec_unmap(msec, insn.ip);
1798*74fe6c29SRuslan Bukin 
1799*74fe6c29SRuslan Bukin 	/* Let's see if we can proceed to the next IP without trace.
1800*74fe6c29SRuslan Bukin 	 *
1801*74fe6c29SRuslan Bukin 	 * If we can't, this is certainly a decision point.
1802*74fe6c29SRuslan Bukin 	 */
1803*74fe6c29SRuslan Bukin 	status = pt_insn_next_ip(&decoder->ip, &insn, &iext);
1804*74fe6c29SRuslan Bukin 	if (status < 0) {
1805*74fe6c29SRuslan Bukin 		if (status != -pte_bad_query)
1806*74fe6c29SRuslan Bukin 			return status;
1807*74fe6c29SRuslan Bukin 
1808*74fe6c29SRuslan Bukin 		memset(&bce, 0, sizeof(bce));
1809*74fe6c29SRuslan Bukin 		bce.ninsn = 1;
1810*74fe6c29SRuslan Bukin 		bce.mode = insn.mode;
1811*74fe6c29SRuslan Bukin 		bce.isize = insn.size;
1812*74fe6c29SRuslan Bukin 
1813*74fe6c29SRuslan Bukin 		/* Clear the instruction size in case of overflows. */
1814*74fe6c29SRuslan Bukin 		if ((uint8_t) bce.isize != insn.size)
1815*74fe6c29SRuslan Bukin 			bce.isize = 0;
1816*74fe6c29SRuslan Bukin 
1817*74fe6c29SRuslan Bukin 		switch (insn.iclass) {
1818*74fe6c29SRuslan Bukin 		case ptic_ptwrite:
1819*74fe6c29SRuslan Bukin 		case ptic_error:
1820*74fe6c29SRuslan Bukin 		case ptic_other:
1821*74fe6c29SRuslan Bukin 			return -pte_internal;
1822*74fe6c29SRuslan Bukin 
1823*74fe6c29SRuslan Bukin 		case ptic_jump:
1824*74fe6c29SRuslan Bukin 			/* A direct jump doesn't require trace. */
1825*74fe6c29SRuslan Bukin 			if (iext.variant.branch.is_direct)
1826*74fe6c29SRuslan Bukin 				return -pte_internal;
1827*74fe6c29SRuslan Bukin 
1828*74fe6c29SRuslan Bukin 			bce.qualifier = ptbq_indirect;
1829*74fe6c29SRuslan Bukin 			break;
1830*74fe6c29SRuslan Bukin 
1831*74fe6c29SRuslan Bukin 		case ptic_call:
1832*74fe6c29SRuslan Bukin 			/* A direct call doesn't require trace. */
1833*74fe6c29SRuslan Bukin 			if (iext.variant.branch.is_direct)
1834*74fe6c29SRuslan Bukin 				return -pte_internal;
1835*74fe6c29SRuslan Bukin 
1836*74fe6c29SRuslan Bukin 			bce.qualifier = ptbq_ind_call;
1837*74fe6c29SRuslan Bukin 			break;
1838*74fe6c29SRuslan Bukin 
1839*74fe6c29SRuslan Bukin 		case ptic_return:
1840*74fe6c29SRuslan Bukin 			bce.qualifier = ptbq_return;
1841*74fe6c29SRuslan Bukin 			break;
1842*74fe6c29SRuslan Bukin 
1843*74fe6c29SRuslan Bukin 		case ptic_cond_jump:
1844*74fe6c29SRuslan Bukin 			bce.qualifier = ptbq_cond;
1845*74fe6c29SRuslan Bukin 			break;
1846*74fe6c29SRuslan Bukin 
1847*74fe6c29SRuslan Bukin 		case ptic_far_call:
1848*74fe6c29SRuslan Bukin 		case ptic_far_return:
1849*74fe6c29SRuslan Bukin 		case ptic_far_jump:
1850*74fe6c29SRuslan Bukin 			bce.qualifier = ptbq_indirect;
1851*74fe6c29SRuslan Bukin 			break;
1852*74fe6c29SRuslan Bukin 		}
1853*74fe6c29SRuslan Bukin 
1854*74fe6c29SRuslan Bukin 		/* If the block was truncated, we have to decode its last
1855*74fe6c29SRuslan Bukin 		 * instruction each time.
1856*74fe6c29SRuslan Bukin 		 *
1857*74fe6c29SRuslan Bukin 		 * We could have skipped the above switch and size assignment in
1858*74fe6c29SRuslan Bukin 		 * this case but this is already a slow and hopefully infrequent
1859*74fe6c29SRuslan Bukin 		 * path.
1860*74fe6c29SRuslan Bukin 		 */
1861*74fe6c29SRuslan Bukin 		if (block->truncated)
1862*74fe6c29SRuslan Bukin 			bce.qualifier = ptbq_decode;
1863*74fe6c29SRuslan Bukin 
1864*74fe6c29SRuslan Bukin 		status = pt_bcache_add(bcache, ioff, bce);
1865*74fe6c29SRuslan Bukin 		if (status < 0)
1866*74fe6c29SRuslan Bukin 			return status;
1867*74fe6c29SRuslan Bukin 
1868*74fe6c29SRuslan Bukin 		return pt_blk_proceed_with_trace(decoder, &insn, &iext);
1869*74fe6c29SRuslan Bukin 	}
1870*74fe6c29SRuslan Bukin 
1871*74fe6c29SRuslan Bukin 	/* The next instruction's IP. */
1872*74fe6c29SRuslan Bukin 	nip = decoder->ip;
1873*74fe6c29SRuslan Bukin 	noff = pt_msec_unmap(msec, nip);
1874*74fe6c29SRuslan Bukin 
1875*74fe6c29SRuslan Bukin 	/* Even if we were able to proceed without trace, we might have to stop
1876*74fe6c29SRuslan Bukin 	 * here for various reasons:
1877*74fe6c29SRuslan Bukin 	 *
1878*74fe6c29SRuslan Bukin 	 *   - at near direct calls to update the return-address stack
1879*74fe6c29SRuslan Bukin 	 *
1880*74fe6c29SRuslan Bukin 	 *     We are forced to re-decode @insn to get the branch displacement.
1881*74fe6c29SRuslan Bukin 	 *
1882*74fe6c29SRuslan Bukin 	 *     Even though it is constant, we don't cache it to avoid increasing
1883*74fe6c29SRuslan Bukin 	 *     the size of a cache entry.  Note that the displacement field is
1884*74fe6c29SRuslan Bukin 	 *     zero for this entry and we might be tempted to use it - but other
1885*74fe6c29SRuslan Bukin 	 *     entries that point to this decision point will have non-zero
1886*74fe6c29SRuslan Bukin 	 *     displacement.
1887*74fe6c29SRuslan Bukin 	 *
1888*74fe6c29SRuslan Bukin 	 *     We could proceed after a near direct call but we migh as well
1889*74fe6c29SRuslan Bukin 	 *     postpone it to the next iteration.  Make sure to end the block if
1890*74fe6c29SRuslan Bukin 	 *     @decoder->flags.variant.block.end_on_call is set, though.
1891*74fe6c29SRuslan Bukin 	 *
1892*74fe6c29SRuslan Bukin 	 *   - at near direct backwards jumps to detect section splits
1893*74fe6c29SRuslan Bukin 	 *
1894*74fe6c29SRuslan Bukin 	 *     In case the current section is split underneath us, we must take
1895*74fe6c29SRuslan Bukin 	 *     care to detect that split.
1896*74fe6c29SRuslan Bukin 	 *
1897*74fe6c29SRuslan Bukin 	 *     There is one corner case where the split is in the middle of a
1898*74fe6c29SRuslan Bukin 	 *     linear sequence of instructions that branches back into the
1899*74fe6c29SRuslan Bukin 	 *     originating section.
1900*74fe6c29SRuslan Bukin 	 *
1901*74fe6c29SRuslan Bukin 	 *     Calls, indirect branches, and far branches are already covered
1902*74fe6c29SRuslan Bukin 	 *     since they either require trace or already require us to stop
1903*74fe6c29SRuslan Bukin 	 *     (i.e. near direct calls) for other reasons.  That leaves near
1904*74fe6c29SRuslan Bukin 	 *     direct backward jumps.
1905*74fe6c29SRuslan Bukin 	 *
1906*74fe6c29SRuslan Bukin 	 *     Instead of the decode stop at the jump instruction we're using we
1907*74fe6c29SRuslan Bukin 	 *     could have made sure that other block cache entries that extend
1908*74fe6c29SRuslan Bukin 	 *     this one insert a trampoline to the jump's entry.  This would
1909*74fe6c29SRuslan Bukin 	 *     have been a bit more complicated.
1910*74fe6c29SRuslan Bukin 	 *
1911*74fe6c29SRuslan Bukin 	 *   - if we switched sections
1912*74fe6c29SRuslan Bukin 	 *
1913*74fe6c29SRuslan Bukin 	 *     This ends a block just like a branch that requires trace.
1914*74fe6c29SRuslan Bukin 	 *
1915*74fe6c29SRuslan Bukin 	 *     We need to re-decode @insn in order to determine the start IP of
1916*74fe6c29SRuslan Bukin 	 *     the next block.
1917*74fe6c29SRuslan Bukin 	 *
1918*74fe6c29SRuslan Bukin 	 *   - if the block is truncated
1919*74fe6c29SRuslan Bukin 	 *
1920*74fe6c29SRuslan Bukin 	 *     We need to read the last instruction's memory from multiple
1921*74fe6c29SRuslan Bukin 	 *     sections and provide it to the user.
1922*74fe6c29SRuslan Bukin 	 *
1923*74fe6c29SRuslan Bukin 	 *     We could still use the block cache but then we'd have to handle
1924*74fe6c29SRuslan Bukin 	 *     this case for each qualifier.  Truncation is hopefully rare and
1925*74fe6c29SRuslan Bukin 	 *     having to read the memory for the instruction from multiple
1926*74fe6c29SRuslan Bukin 	 *     sections is already slow.  Let's rather keep things simple and
1927*74fe6c29SRuslan Bukin 	 *     route it through the decode flow, where we already have
1928*74fe6c29SRuslan Bukin 	 *     everything in place.
1929*74fe6c29SRuslan Bukin 	 */
1930*74fe6c29SRuslan Bukin 	switch (insn.iclass) {
1931*74fe6c29SRuslan Bukin 	case ptic_call:
1932*74fe6c29SRuslan Bukin 		return pt_blk_add_decode(bcache, ioff, insn.mode);
1933*74fe6c29SRuslan Bukin 
1934*74fe6c29SRuslan Bukin 	case ptic_jump:
1935*74fe6c29SRuslan Bukin 		/* An indirect branch requires trace and should have been
1936*74fe6c29SRuslan Bukin 		 * handled above.
1937*74fe6c29SRuslan Bukin 		 */
1938*74fe6c29SRuslan Bukin 		if (!iext.variant.branch.is_direct)
1939*74fe6c29SRuslan Bukin 			return -pte_internal;
1940*74fe6c29SRuslan Bukin 
1941*74fe6c29SRuslan Bukin 		if (iext.variant.branch.displacement < 0 ||
1942*74fe6c29SRuslan Bukin 		    decoder->flags.variant.block.end_on_jump)
1943*74fe6c29SRuslan Bukin 			return pt_blk_add_decode(bcache, ioff, insn.mode);
1944*74fe6c29SRuslan Bukin 
1945*74fe6c29SRuslan Bukin 		fallthrough;
1946*74fe6c29SRuslan Bukin 	default:
1947*74fe6c29SRuslan Bukin 		if (!pt_blk_is_in_section(msec, nip) || block->truncated)
1948*74fe6c29SRuslan Bukin 			return pt_blk_add_decode(bcache, ioff, insn.mode);
1949*74fe6c29SRuslan Bukin 
1950*74fe6c29SRuslan Bukin 		break;
1951*74fe6c29SRuslan Bukin 	}
1952*74fe6c29SRuslan Bukin 
1953*74fe6c29SRuslan Bukin 	/* We proceeded one instruction.  Let's see if we have a cache entry for
1954*74fe6c29SRuslan Bukin 	 * the next instruction.
1955*74fe6c29SRuslan Bukin 	 */
1956*74fe6c29SRuslan Bukin 	status = pt_bcache_lookup(&bce, bcache, noff);
1957*74fe6c29SRuslan Bukin 	if (status < 0)
1958*74fe6c29SRuslan Bukin 		return status;
1959*74fe6c29SRuslan Bukin 
1960*74fe6c29SRuslan Bukin 	/* If we don't have a valid cache entry, yet, fill the cache some more.
1961*74fe6c29SRuslan Bukin 	 *
1962*74fe6c29SRuslan Bukin 	 * On our way back, we add a cache entry for this instruction based on
1963*74fe6c29SRuslan Bukin 	 * the cache entry of the succeeding instruction.
1964*74fe6c29SRuslan Bukin 	 */
1965*74fe6c29SRuslan Bukin 	if (!pt_bce_is_valid(bce)) {
1966*74fe6c29SRuslan Bukin 		/* If we exceeded the maximum number of allowed steps, we insert
1967*74fe6c29SRuslan Bukin 		 * a trampoline to the next instruction.
1968*74fe6c29SRuslan Bukin 		 *
1969*74fe6c29SRuslan Bukin 		 * The next time we encounter the same code, we will use the
1970*74fe6c29SRuslan Bukin 		 * trampoline to jump directly to where we left off this time
1971*74fe6c29SRuslan Bukin 		 * and continue from there.
1972*74fe6c29SRuslan Bukin 		 */
1973*74fe6c29SRuslan Bukin 		steps -= 1;
1974*74fe6c29SRuslan Bukin 		if (!steps)
1975*74fe6c29SRuslan Bukin 			return pt_blk_add_trampoline(bcache, ioff, noff,
1976*74fe6c29SRuslan Bukin 						     insn.mode);
1977*74fe6c29SRuslan Bukin 
1978*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_no_event_fill_cache(decoder, block,
1979*74fe6c29SRuslan Bukin 							    bcache, msec,
1980*74fe6c29SRuslan Bukin 							    steps);
1981*74fe6c29SRuslan Bukin 		if (status < 0)
1982*74fe6c29SRuslan Bukin 			return status;
1983*74fe6c29SRuslan Bukin 
1984*74fe6c29SRuslan Bukin 		/* Let's see if we have more luck this time. */
1985*74fe6c29SRuslan Bukin 		status = pt_bcache_lookup(&bce, bcache, noff);
1986*74fe6c29SRuslan Bukin 		if (status < 0)
1987*74fe6c29SRuslan Bukin 			return status;
1988*74fe6c29SRuslan Bukin 
1989*74fe6c29SRuslan Bukin 		/* If we still don't have a valid cache entry, we're done.  Most
1990*74fe6c29SRuslan Bukin 		 * likely, @block overflowed and we couldn't proceed past the
1991*74fe6c29SRuslan Bukin 		 * next instruction.
1992*74fe6c29SRuslan Bukin 		 */
1993*74fe6c29SRuslan Bukin 		if (!pt_bce_is_valid(bce))
1994*74fe6c29SRuslan Bukin 			return 0;
1995*74fe6c29SRuslan Bukin 	}
1996*74fe6c29SRuslan Bukin 
1997*74fe6c29SRuslan Bukin 	/* We must not have switched execution modes.
1998*74fe6c29SRuslan Bukin 	 *
1999*74fe6c29SRuslan Bukin 	 * This would require an event and we're on the no-event flow.
2000*74fe6c29SRuslan Bukin 	 */
2001*74fe6c29SRuslan Bukin 	if (pt_bce_exec_mode(bce) != insn.mode)
2002*74fe6c29SRuslan Bukin 		return -pte_internal;
2003*74fe6c29SRuslan Bukin 
2004*74fe6c29SRuslan Bukin 	/* The decision point IP and the displacement from @insn.ip. */
2005*74fe6c29SRuslan Bukin 	dip = nip + bce.displacement;
2006*74fe6c29SRuslan Bukin 	disp = (int64_t) (dip - insn.ip);
2007*74fe6c29SRuslan Bukin 
2008*74fe6c29SRuslan Bukin 	/* We may have switched sections if the section was split.  See
2009*74fe6c29SRuslan Bukin 	 * pt_blk_proceed_no_event_cached() for a more elaborate comment.
2010*74fe6c29SRuslan Bukin 	 *
2011*74fe6c29SRuslan Bukin 	 * We're not adding a block cache entry since this won't apply to the
2012*74fe6c29SRuslan Bukin 	 * original section which may be shared with other decoders.
2013*74fe6c29SRuslan Bukin 	 *
2014*74fe6c29SRuslan Bukin 	 * We will instead take the slow path until the end of the section.
2015*74fe6c29SRuslan Bukin 	 */
2016*74fe6c29SRuslan Bukin 	if (!pt_blk_is_in_section(msec, dip))
2017*74fe6c29SRuslan Bukin 		return 0;
2018*74fe6c29SRuslan Bukin 
2019*74fe6c29SRuslan Bukin 	/* Let's try to reach @nip's decision point from @insn.ip.
2020*74fe6c29SRuslan Bukin 	 *
2021*74fe6c29SRuslan Bukin 	 * There are two fields that may overflow: @bce.ninsn and
2022*74fe6c29SRuslan Bukin 	 * @bce.displacement.
2023*74fe6c29SRuslan Bukin 	 */
2024*74fe6c29SRuslan Bukin 	bce.ninsn += 1;
2025*74fe6c29SRuslan Bukin 	bce.displacement = (int32_t) disp;
2026*74fe6c29SRuslan Bukin 
2027*74fe6c29SRuslan Bukin 	/* If none of them overflowed, we're done.
2028*74fe6c29SRuslan Bukin 	 *
2029*74fe6c29SRuslan Bukin 	 * If one or both overflowed, let's try to insert a trampoline, i.e. we
2030*74fe6c29SRuslan Bukin 	 * try to reach @dip via a ptbq_again entry to @nip.
2031*74fe6c29SRuslan Bukin 	 */
2032*74fe6c29SRuslan Bukin 	if (!bce.ninsn || ((int64_t) bce.displacement != disp))
2033*74fe6c29SRuslan Bukin 		return pt_blk_add_trampoline(bcache, ioff, noff, insn.mode);
2034*74fe6c29SRuslan Bukin 
2035*74fe6c29SRuslan Bukin 	/* We're done.  Add the cache entry.
2036*74fe6c29SRuslan Bukin 	 *
2037*74fe6c29SRuslan Bukin 	 * There's a chance that other decoders updated the cache entry in the
2038*74fe6c29SRuslan Bukin 	 * meantime.  They should have come to the same conclusion as we,
2039*74fe6c29SRuslan Bukin 	 * though, and the cache entries should be identical.
2040*74fe6c29SRuslan Bukin 	 *
2041*74fe6c29SRuslan Bukin 	 * Cache updates are atomic so even if the two versions were not
2042*74fe6c29SRuslan Bukin 	 * identical, we wouldn't care because they are both correct.
2043*74fe6c29SRuslan Bukin 	 */
2044*74fe6c29SRuslan Bukin 	return pt_bcache_add(bcache, ioff, bce);
2045*74fe6c29SRuslan Bukin }
2046*74fe6c29SRuslan Bukin 
2047*74fe6c29SRuslan Bukin /* Proceed at a potentially truncated instruction.
2048*74fe6c29SRuslan Bukin  *
2049*74fe6c29SRuslan Bukin  * We were not able to decode the instruction at @decoder->ip in @decoder's
2050*74fe6c29SRuslan Bukin  * cached section.  This is typically caused by not having enough bytes.
2051*74fe6c29SRuslan Bukin  *
2052*74fe6c29SRuslan Bukin  * Try to decode the instruction again using the entire image.  If this succeeds
2053*74fe6c29SRuslan Bukin  * we expect to end up with an instruction that was truncated in the section it
2054*74fe6c29SRuslan Bukin  * started.  We provide the full instruction in this case and end the block.
2055*74fe6c29SRuslan Bukin  *
2056*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
2057*74fe6c29SRuslan Bukin  */
pt_blk_proceed_truncated(struct pt_block_decoder * decoder,struct pt_block * block)2058*74fe6c29SRuslan Bukin static int pt_blk_proceed_truncated(struct pt_block_decoder *decoder,
2059*74fe6c29SRuslan Bukin 				    struct pt_block *block)
2060*74fe6c29SRuslan Bukin {
2061*74fe6c29SRuslan Bukin 	struct pt_insn_ext iext;
2062*74fe6c29SRuslan Bukin 	struct pt_insn insn;
2063*74fe6c29SRuslan Bukin 	int errcode;
2064*74fe6c29SRuslan Bukin 
2065*74fe6c29SRuslan Bukin 	if (!decoder || !block)
2066*74fe6c29SRuslan Bukin 		return -pte_internal;
2067*74fe6c29SRuslan Bukin 
2068*74fe6c29SRuslan Bukin 	memset(&iext, 0, sizeof(iext));
2069*74fe6c29SRuslan Bukin 	memset(&insn, 0, sizeof(insn));
2070*74fe6c29SRuslan Bukin 
2071*74fe6c29SRuslan Bukin 	insn.mode = decoder->mode;
2072*74fe6c29SRuslan Bukin 	insn.ip = decoder->ip;
2073*74fe6c29SRuslan Bukin 
2074*74fe6c29SRuslan Bukin 	errcode = pt_insn_decode(&insn, &iext, decoder->image, &decoder->asid);
2075*74fe6c29SRuslan Bukin 	if (errcode < 0)
2076*74fe6c29SRuslan Bukin 		return errcode;
2077*74fe6c29SRuslan Bukin 
2078*74fe6c29SRuslan Bukin 	/* We shouldn't use this function if the instruction isn't truncated. */
2079*74fe6c29SRuslan Bukin 	if (!insn.truncated)
2080*74fe6c29SRuslan Bukin 		return -pte_internal;
2081*74fe6c29SRuslan Bukin 
2082*74fe6c29SRuslan Bukin 	/* Provide the instruction in the block.  This ends the block. */
2083*74fe6c29SRuslan Bukin 	memcpy(block->raw, insn.raw, insn.size);
2084*74fe6c29SRuslan Bukin 	block->iclass = insn.iclass;
2085*74fe6c29SRuslan Bukin 	block->size = insn.size;
2086*74fe6c29SRuslan Bukin 	block->truncated = 1;
2087*74fe6c29SRuslan Bukin 
2088*74fe6c29SRuslan Bukin 	/* Log calls' return addresses for return compression. */
2089*74fe6c29SRuslan Bukin 	errcode = pt_blk_log_call(decoder, &insn, &iext);
2090*74fe6c29SRuslan Bukin 	if (errcode < 0)
2091*74fe6c29SRuslan Bukin 		return errcode;
2092*74fe6c29SRuslan Bukin 
2093*74fe6c29SRuslan Bukin 	/* Let's see if we can proceed to the next IP without trace.
2094*74fe6c29SRuslan Bukin 	 *
2095*74fe6c29SRuslan Bukin 	 * The truncated instruction ends the block but we still need to get the
2096*74fe6c29SRuslan Bukin 	 * next block's start IP.
2097*74fe6c29SRuslan Bukin 	 */
2098*74fe6c29SRuslan Bukin 	errcode = pt_insn_next_ip(&decoder->ip, &insn, &iext);
2099*74fe6c29SRuslan Bukin 	if (errcode < 0) {
2100*74fe6c29SRuslan Bukin 		if (errcode != -pte_bad_query)
2101*74fe6c29SRuslan Bukin 			return errcode;
2102*74fe6c29SRuslan Bukin 
2103*74fe6c29SRuslan Bukin 		return pt_blk_proceed_with_trace(decoder, &insn, &iext);
2104*74fe6c29SRuslan Bukin 	}
2105*74fe6c29SRuslan Bukin 
2106*74fe6c29SRuslan Bukin 	return 0;
2107*74fe6c29SRuslan Bukin }
2108*74fe6c29SRuslan Bukin 
2109*74fe6c29SRuslan Bukin /* Proceed to the next decision point using the block cache.
2110*74fe6c29SRuslan Bukin  *
2111*74fe6c29SRuslan Bukin  * Tracing is enabled and we don't have an event pending.  We already set
2112*74fe6c29SRuslan Bukin  * @block's isid.  All reads are done within @msec as we're not switching
2113*74fe6c29SRuslan Bukin  * sections between blocks.
2114*74fe6c29SRuslan Bukin  *
2115*74fe6c29SRuslan Bukin  * Proceed as far as we get without trace.  Stop when we either:
2116*74fe6c29SRuslan Bukin  *
2117*74fe6c29SRuslan Bukin  *   - need trace in order to continue
2118*74fe6c29SRuslan Bukin  *   - overflow the max number of instructions in a block
2119*74fe6c29SRuslan Bukin  *
2120*74fe6c29SRuslan Bukin  * We actually proceed one instruction further to get the start IP for the next
2121*74fe6c29SRuslan Bukin  * block.  This only updates @decoder's internal state, though.
2122*74fe6c29SRuslan Bukin  *
2123*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
2124*74fe6c29SRuslan Bukin  */
pt_blk_proceed_no_event_cached(struct pt_block_decoder * decoder,struct pt_block * block,struct pt_block_cache * bcache,const struct pt_mapped_section * msec)2125*74fe6c29SRuslan Bukin static int pt_blk_proceed_no_event_cached(struct pt_block_decoder *decoder,
2126*74fe6c29SRuslan Bukin 					  struct pt_block *block,
2127*74fe6c29SRuslan Bukin 					  struct pt_block_cache *bcache,
2128*74fe6c29SRuslan Bukin 					  const struct pt_mapped_section *msec)
2129*74fe6c29SRuslan Bukin {
2130*74fe6c29SRuslan Bukin 	struct pt_bcache_entry bce;
2131*74fe6c29SRuslan Bukin 	uint16_t binsn, ninsn;
2132*74fe6c29SRuslan Bukin 	uint64_t offset, nip;
2133*74fe6c29SRuslan Bukin 	int status;
2134*74fe6c29SRuslan Bukin 
2135*74fe6c29SRuslan Bukin 	if (!decoder || !block)
2136*74fe6c29SRuslan Bukin 		return -pte_internal;
2137*74fe6c29SRuslan Bukin 
2138*74fe6c29SRuslan Bukin 	offset = pt_msec_unmap(msec, decoder->ip);
2139*74fe6c29SRuslan Bukin 	status = pt_bcache_lookup(&bce, bcache, offset);
2140*74fe6c29SRuslan Bukin 	if (status < 0)
2141*74fe6c29SRuslan Bukin 		return status;
2142*74fe6c29SRuslan Bukin 
2143*74fe6c29SRuslan Bukin 	/* If we don't find a valid cache entry, fill the cache. */
2144*74fe6c29SRuslan Bukin 	if (!pt_bce_is_valid(bce))
2145*74fe6c29SRuslan Bukin 		return pt_blk_proceed_no_event_fill_cache(decoder, block,
2146*74fe6c29SRuslan Bukin 							  bcache, msec,
2147*74fe6c29SRuslan Bukin 							  bcache_fill_steps);
2148*74fe6c29SRuslan Bukin 
2149*74fe6c29SRuslan Bukin 	/* If we switched sections, the origianl section must have been split
2150*74fe6c29SRuslan Bukin 	 * underneath us.  A split preserves the block cache of the original
2151*74fe6c29SRuslan Bukin 	 * section.
2152*74fe6c29SRuslan Bukin 	 *
2153*74fe6c29SRuslan Bukin 	 * Crossing sections requires ending the block so we can indicate the
2154*74fe6c29SRuslan Bukin 	 * proper isid for the entire block.
2155*74fe6c29SRuslan Bukin 	 *
2156*74fe6c29SRuslan Bukin 	 * Plus there's the chance that the new section that caused the original
2157*74fe6c29SRuslan Bukin 	 * section to split changed instructions.
2158*74fe6c29SRuslan Bukin 	 *
2159*74fe6c29SRuslan Bukin 	 * This check will also cover changes to a linear sequence of code we
2160*74fe6c29SRuslan Bukin 	 * would otherwise have jumped over as long as the start and end are in
2161*74fe6c29SRuslan Bukin 	 * different sub-sections.
2162*74fe6c29SRuslan Bukin 	 *
2163*74fe6c29SRuslan Bukin 	 * Since we stop on every (backwards) branch (through an artificial stop
2164*74fe6c29SRuslan Bukin 	 * in the case of a near direct backward branch) we will detect all
2165*74fe6c29SRuslan Bukin 	 * section splits.
2166*74fe6c29SRuslan Bukin 	 *
2167*74fe6c29SRuslan Bukin 	 * Switch to the slow path until we reach the end of this section.
2168*74fe6c29SRuslan Bukin 	 */
2169*74fe6c29SRuslan Bukin 	nip = decoder->ip + bce.displacement;
2170*74fe6c29SRuslan Bukin 	if (!pt_blk_is_in_section(msec, nip))
2171*74fe6c29SRuslan Bukin 		return pt_blk_proceed_no_event_uncached(decoder, block);
2172*74fe6c29SRuslan Bukin 
2173*74fe6c29SRuslan Bukin 	/* We have a valid cache entry.  Let's first check if the way to the
2174*74fe6c29SRuslan Bukin 	 * decision point still fits into @block.
2175*74fe6c29SRuslan Bukin 	 *
2176*74fe6c29SRuslan Bukin 	 * If it doesn't, we end the block without filling it as much as we
2177*74fe6c29SRuslan Bukin 	 * could since this would require us to switch to the slow path.
2178*74fe6c29SRuslan Bukin 	 *
2179*74fe6c29SRuslan Bukin 	 * On the next iteration, we will start with an empty block, which is
2180*74fe6c29SRuslan Bukin 	 * guaranteed to have enough room for at least one block cache entry.
2181*74fe6c29SRuslan Bukin 	 */
2182*74fe6c29SRuslan Bukin 	binsn = block->ninsn;
2183*74fe6c29SRuslan Bukin 	ninsn = binsn + (uint16_t) bce.ninsn;
2184*74fe6c29SRuslan Bukin 	if (ninsn < binsn)
2185*74fe6c29SRuslan Bukin 		return 0;
2186*74fe6c29SRuslan Bukin 
2187*74fe6c29SRuslan Bukin 	/* Jump ahead to the decision point and proceed from there.
2188*74fe6c29SRuslan Bukin 	 *
2189*74fe6c29SRuslan Bukin 	 * We're not switching execution modes so even if @block already has an
2190*74fe6c29SRuslan Bukin 	 * execution mode, it will be the one we're going to set.
2191*74fe6c29SRuslan Bukin 	 */
2192*74fe6c29SRuslan Bukin 	decoder->ip = nip;
2193*74fe6c29SRuslan Bukin 
2194*74fe6c29SRuslan Bukin 	/* We don't know the instruction class so we should be setting it to
2195*74fe6c29SRuslan Bukin 	 * ptic_error.  Since we will be able to fill it back in later in most
2196*74fe6c29SRuslan Bukin 	 * cases, we move the clearing to the switch cases that don't.
2197*74fe6c29SRuslan Bukin 	 */
2198*74fe6c29SRuslan Bukin 	block->end_ip = nip;
2199*74fe6c29SRuslan Bukin 	block->ninsn = ninsn;
2200*74fe6c29SRuslan Bukin 	block->mode = pt_bce_exec_mode(bce);
2201*74fe6c29SRuslan Bukin 
2202*74fe6c29SRuslan Bukin 
2203*74fe6c29SRuslan Bukin 	switch (pt_bce_qualifier(bce)) {
2204*74fe6c29SRuslan Bukin 	case ptbq_again:
2205*74fe6c29SRuslan Bukin 		/* We're not able to reach the actual decision point due to
2206*74fe6c29SRuslan Bukin 		 * overflows so we inserted a trampoline.
2207*74fe6c29SRuslan Bukin 		 *
2208*74fe6c29SRuslan Bukin 		 * We don't know the instruction and it is not guaranteed that
2209*74fe6c29SRuslan Bukin 		 * we will proceed further (e.g. if @block overflowed).  Let's
2210*74fe6c29SRuslan Bukin 		 * clear any previously stored instruction class which has
2211*74fe6c29SRuslan Bukin 		 * become invalid when we updated @block->ninsn.
2212*74fe6c29SRuslan Bukin 		 */
2213*74fe6c29SRuslan Bukin 		block->iclass = ptic_error;
2214*74fe6c29SRuslan Bukin 
2215*74fe6c29SRuslan Bukin 		return pt_blk_proceed_no_event_cached(decoder, block, bcache,
2216*74fe6c29SRuslan Bukin 						      msec);
2217*74fe6c29SRuslan Bukin 
2218*74fe6c29SRuslan Bukin 	case ptbq_cond:
2219*74fe6c29SRuslan Bukin 		/* We're at a conditional branch. */
2220*74fe6c29SRuslan Bukin 		block->iclass = ptic_cond_jump;
2221*74fe6c29SRuslan Bukin 
2222*74fe6c29SRuslan Bukin 		/* Let's first check whether we know the size of the
2223*74fe6c29SRuslan Bukin 		 * instruction.  If we do, we might get away without decoding
2224*74fe6c29SRuslan Bukin 		 * the instruction.
2225*74fe6c29SRuslan Bukin 		 *
2226*74fe6c29SRuslan Bukin 		 * If we don't know the size we might as well do the full decode
2227*74fe6c29SRuslan Bukin 		 * and proceed-with-trace flow we do for ptbq_decode.
2228*74fe6c29SRuslan Bukin 		 */
2229*74fe6c29SRuslan Bukin 		if (bce.isize) {
2230*74fe6c29SRuslan Bukin 			uint64_t ip;
2231*74fe6c29SRuslan Bukin 			int taken;
2232*74fe6c29SRuslan Bukin 
2233*74fe6c29SRuslan Bukin 			/* If the branch is not taken, we don't need to decode
2234*74fe6c29SRuslan Bukin 			 * the instruction at @decoder->ip.
2235*74fe6c29SRuslan Bukin 			 *
2236*74fe6c29SRuslan Bukin 			 * If it is taken, we have to implement everything here.
2237*74fe6c29SRuslan Bukin 			 * We can't use the normal decode and proceed-with-trace
2238*74fe6c29SRuslan Bukin 			 * flow since we already consumed the TNT bit.
2239*74fe6c29SRuslan Bukin 			 */
2240*74fe6c29SRuslan Bukin 			status = pt_blk_cond_branch(decoder, &taken);
2241*74fe6c29SRuslan Bukin 			if (status < 0)
2242*74fe6c29SRuslan Bukin 				return status;
2243*74fe6c29SRuslan Bukin 
2244*74fe6c29SRuslan Bukin 			/* Preserve the query decoder's response which indicates
2245*74fe6c29SRuslan Bukin 			 * upcoming events.
2246*74fe6c29SRuslan Bukin 			 */
2247*74fe6c29SRuslan Bukin 			decoder->status = status;
2248*74fe6c29SRuslan Bukin 
2249*74fe6c29SRuslan Bukin 			ip = decoder->ip;
2250*74fe6c29SRuslan Bukin 			if (taken) {
2251*74fe6c29SRuslan Bukin 				struct pt_insn_ext iext;
2252*74fe6c29SRuslan Bukin 				struct pt_insn insn;
2253*74fe6c29SRuslan Bukin 
2254*74fe6c29SRuslan Bukin 				memset(&iext, 0, sizeof(iext));
2255*74fe6c29SRuslan Bukin 				memset(&insn, 0, sizeof(insn));
2256*74fe6c29SRuslan Bukin 
2257*74fe6c29SRuslan Bukin 				insn.mode = pt_bce_exec_mode(bce);
2258*74fe6c29SRuslan Bukin 				insn.ip = ip;
2259*74fe6c29SRuslan Bukin 
2260*74fe6c29SRuslan Bukin 				status = pt_blk_decode_in_section(&insn, &iext,
2261*74fe6c29SRuslan Bukin 								  msec);
2262*74fe6c29SRuslan Bukin 				if (status < 0)
2263*74fe6c29SRuslan Bukin 					return status;
2264*74fe6c29SRuslan Bukin 
2265*74fe6c29SRuslan Bukin 				ip += iext.variant.branch.displacement;
2266*74fe6c29SRuslan Bukin 			}
2267*74fe6c29SRuslan Bukin 
2268*74fe6c29SRuslan Bukin 			decoder->ip = ip + bce.isize;
2269*74fe6c29SRuslan Bukin 			break;
2270*74fe6c29SRuslan Bukin 		}
2271*74fe6c29SRuslan Bukin 
2272*74fe6c29SRuslan Bukin 		fallthrough;
2273*74fe6c29SRuslan Bukin 	case ptbq_decode: {
2274*74fe6c29SRuslan Bukin 		struct pt_insn_ext iext;
2275*74fe6c29SRuslan Bukin 		struct pt_insn insn;
2276*74fe6c29SRuslan Bukin 
2277*74fe6c29SRuslan Bukin 		/* We need to decode the instruction at @decoder->ip and decide
2278*74fe6c29SRuslan Bukin 		 * what to do based on that.
2279*74fe6c29SRuslan Bukin 		 *
2280*74fe6c29SRuslan Bukin 		 * We already accounted for the instruction so we can't just
2281*74fe6c29SRuslan Bukin 		 * call pt_blk_proceed_one_insn().
2282*74fe6c29SRuslan Bukin 		 */
2283*74fe6c29SRuslan Bukin 
2284*74fe6c29SRuslan Bukin 		memset(&iext, 0, sizeof(iext));
2285*74fe6c29SRuslan Bukin 		memset(&insn, 0, sizeof(insn));
2286*74fe6c29SRuslan Bukin 
2287*74fe6c29SRuslan Bukin 		insn.mode = pt_bce_exec_mode(bce);
2288*74fe6c29SRuslan Bukin 		insn.ip = decoder->ip;
2289*74fe6c29SRuslan Bukin 
2290*74fe6c29SRuslan Bukin 		status = pt_blk_decode_in_section(&insn, &iext, msec);
2291*74fe6c29SRuslan Bukin 		if (status < 0) {
2292*74fe6c29SRuslan Bukin 			if (status != -pte_bad_insn)
2293*74fe6c29SRuslan Bukin 				return status;
2294*74fe6c29SRuslan Bukin 
2295*74fe6c29SRuslan Bukin 			return pt_blk_proceed_truncated(decoder, block);
2296*74fe6c29SRuslan Bukin 		}
2297*74fe6c29SRuslan Bukin 
2298*74fe6c29SRuslan Bukin 		/* We just decoded @insn so we know the instruction class. */
2299*74fe6c29SRuslan Bukin 		block->iclass = insn.iclass;
2300*74fe6c29SRuslan Bukin 
2301*74fe6c29SRuslan Bukin 		/* Log calls' return addresses for return compression. */
2302*74fe6c29SRuslan Bukin 		status = pt_blk_log_call(decoder, &insn, &iext);
2303*74fe6c29SRuslan Bukin 		if (status < 0)
2304*74fe6c29SRuslan Bukin 			return status;
2305*74fe6c29SRuslan Bukin 
2306*74fe6c29SRuslan Bukin 		/* Let's see if we can proceed to the next IP without trace.
2307*74fe6c29SRuslan Bukin 		 *
2308*74fe6c29SRuslan Bukin 		 * Note that we also stop due to displacement overflows or to
2309*74fe6c29SRuslan Bukin 		 * maintain the return-address stack for near direct calls.
2310*74fe6c29SRuslan Bukin 		 */
2311*74fe6c29SRuslan Bukin 		status = pt_insn_next_ip(&decoder->ip, &insn, &iext);
2312*74fe6c29SRuslan Bukin 		if (status < 0) {
2313*74fe6c29SRuslan Bukin 			if (status != -pte_bad_query)
2314*74fe6c29SRuslan Bukin 				return status;
2315*74fe6c29SRuslan Bukin 
2316*74fe6c29SRuslan Bukin 			/* We can't, so let's proceed with trace, which
2317*74fe6c29SRuslan Bukin 			 * completes the block.
2318*74fe6c29SRuslan Bukin 			 */
2319*74fe6c29SRuslan Bukin 			return pt_blk_proceed_with_trace(decoder, &insn, &iext);
2320*74fe6c29SRuslan Bukin 		}
2321*74fe6c29SRuslan Bukin 
2322*74fe6c29SRuslan Bukin 		/* End the block if the user asked us to.
2323*74fe6c29SRuslan Bukin 		 *
2324*74fe6c29SRuslan Bukin 		 * We only need to take care about direct near branches.
2325*74fe6c29SRuslan Bukin 		 * Indirect and far branches require trace and will naturally
2326*74fe6c29SRuslan Bukin 		 * end a block.
2327*74fe6c29SRuslan Bukin 		 */
2328*74fe6c29SRuslan Bukin 		if ((decoder->flags.variant.block.end_on_call &&
2329*74fe6c29SRuslan Bukin 		     (insn.iclass == ptic_call)) ||
2330*74fe6c29SRuslan Bukin 		    (decoder->flags.variant.block.end_on_jump &&
2331*74fe6c29SRuslan Bukin 		     (insn.iclass == ptic_jump)))
2332*74fe6c29SRuslan Bukin 			break;
2333*74fe6c29SRuslan Bukin 
2334*74fe6c29SRuslan Bukin 		/* If we can proceed without trace and we stay in @msec we may
2335*74fe6c29SRuslan Bukin 		 * proceed further.
2336*74fe6c29SRuslan Bukin 		 *
2337*74fe6c29SRuslan Bukin 		 * We're done if we switch sections, though.
2338*74fe6c29SRuslan Bukin 		 */
2339*74fe6c29SRuslan Bukin 		if (!pt_blk_is_in_section(msec, decoder->ip))
2340*74fe6c29SRuslan Bukin 			break;
2341*74fe6c29SRuslan Bukin 
2342*74fe6c29SRuslan Bukin 		return pt_blk_proceed_no_event_cached(decoder, block, bcache,
2343*74fe6c29SRuslan Bukin 						      msec);
2344*74fe6c29SRuslan Bukin 	}
2345*74fe6c29SRuslan Bukin 
2346*74fe6c29SRuslan Bukin 	case ptbq_ind_call: {
2347*74fe6c29SRuslan Bukin 		uint64_t ip;
2348*74fe6c29SRuslan Bukin 
2349*74fe6c29SRuslan Bukin 		/* We're at a near indirect call. */
2350*74fe6c29SRuslan Bukin 		block->iclass = ptic_call;
2351*74fe6c29SRuslan Bukin 
2352*74fe6c29SRuslan Bukin 		/* We need to update the return-address stack and query the
2353*74fe6c29SRuslan Bukin 		 * destination IP.
2354*74fe6c29SRuslan Bukin 		 */
2355*74fe6c29SRuslan Bukin 		ip = decoder->ip;
2356*74fe6c29SRuslan Bukin 
2357*74fe6c29SRuslan Bukin 		/* If we already know the size of the instruction, we don't need
2358*74fe6c29SRuslan Bukin 		 * to re-decode it.
2359*74fe6c29SRuslan Bukin 		 */
2360*74fe6c29SRuslan Bukin 		if (bce.isize)
2361*74fe6c29SRuslan Bukin 			ip += bce.isize;
2362*74fe6c29SRuslan Bukin 		else {
2363*74fe6c29SRuslan Bukin 			struct pt_insn_ext iext;
2364*74fe6c29SRuslan Bukin 			struct pt_insn insn;
2365*74fe6c29SRuslan Bukin 
2366*74fe6c29SRuslan Bukin 			memset(&iext, 0, sizeof(iext));
2367*74fe6c29SRuslan Bukin 			memset(&insn, 0, sizeof(insn));
2368*74fe6c29SRuslan Bukin 
2369*74fe6c29SRuslan Bukin 			insn.mode = pt_bce_exec_mode(bce);
2370*74fe6c29SRuslan Bukin 			insn.ip = ip;
2371*74fe6c29SRuslan Bukin 
2372*74fe6c29SRuslan Bukin 			status = pt_blk_decode_in_section(&insn, &iext, msec);
2373*74fe6c29SRuslan Bukin 			if (status < 0)
2374*74fe6c29SRuslan Bukin 				return status;
2375*74fe6c29SRuslan Bukin 
2376*74fe6c29SRuslan Bukin 			ip += insn.size;
2377*74fe6c29SRuslan Bukin 		}
2378*74fe6c29SRuslan Bukin 
2379*74fe6c29SRuslan Bukin 		status = pt_retstack_push(&decoder->retstack, ip);
2380*74fe6c29SRuslan Bukin 		if (status < 0)
2381*74fe6c29SRuslan Bukin 			return status;
2382*74fe6c29SRuslan Bukin 
2383*74fe6c29SRuslan Bukin 		status = pt_blk_indirect_branch(decoder, &decoder->ip);
2384*74fe6c29SRuslan Bukin 		if (status < 0)
2385*74fe6c29SRuslan Bukin 			return status;
2386*74fe6c29SRuslan Bukin 
2387*74fe6c29SRuslan Bukin 		/* Preserve the query decoder's response which indicates
2388*74fe6c29SRuslan Bukin 		 * upcoming events.
2389*74fe6c29SRuslan Bukin 		 */
2390*74fe6c29SRuslan Bukin 		decoder->status = status;
2391*74fe6c29SRuslan Bukin 		break;
2392*74fe6c29SRuslan Bukin 	}
2393*74fe6c29SRuslan Bukin 
2394*74fe6c29SRuslan Bukin 	case ptbq_return: {
2395*74fe6c29SRuslan Bukin 		int taken;
2396*74fe6c29SRuslan Bukin 
2397*74fe6c29SRuslan Bukin 		/* We're at a near return. */
2398*74fe6c29SRuslan Bukin 		block->iclass = ptic_return;
2399*74fe6c29SRuslan Bukin 
2400*74fe6c29SRuslan Bukin 		/* Check for a compressed return. */
2401*74fe6c29SRuslan Bukin 		status = pt_blk_cond_branch(decoder, &taken);
2402*74fe6c29SRuslan Bukin 		if (status < 0) {
2403*74fe6c29SRuslan Bukin 			if (status != -pte_bad_query)
2404*74fe6c29SRuslan Bukin 				return status;
2405*74fe6c29SRuslan Bukin 
2406*74fe6c29SRuslan Bukin 			/* The return is not compressed.  We need another query
2407*74fe6c29SRuslan Bukin 			 * to determine the destination IP.
2408*74fe6c29SRuslan Bukin 			 */
2409*74fe6c29SRuslan Bukin 			status = pt_blk_indirect_branch(decoder, &decoder->ip);
2410*74fe6c29SRuslan Bukin 			if (status < 0)
2411*74fe6c29SRuslan Bukin 				return status;
2412*74fe6c29SRuslan Bukin 
2413*74fe6c29SRuslan Bukin 			/* Preserve the query decoder's response which indicates
2414*74fe6c29SRuslan Bukin 			 * upcoming events.
2415*74fe6c29SRuslan Bukin 			 */
2416*74fe6c29SRuslan Bukin 			decoder->status = status;
2417*74fe6c29SRuslan Bukin 			break;
2418*74fe6c29SRuslan Bukin 		}
2419*74fe6c29SRuslan Bukin 
2420*74fe6c29SRuslan Bukin 		/* Preserve the query decoder's response which indicates
2421*74fe6c29SRuslan Bukin 		 * upcoming events.
2422*74fe6c29SRuslan Bukin 		 */
2423*74fe6c29SRuslan Bukin 		decoder->status = status;
2424*74fe6c29SRuslan Bukin 
2425*74fe6c29SRuslan Bukin 		/* A compressed return is indicated by a taken conditional
2426*74fe6c29SRuslan Bukin 		 * branch.
2427*74fe6c29SRuslan Bukin 		 */
2428*74fe6c29SRuslan Bukin 		if (!taken)
2429*74fe6c29SRuslan Bukin 			return -pte_bad_retcomp;
2430*74fe6c29SRuslan Bukin 
2431*74fe6c29SRuslan Bukin 		return pt_retstack_pop(&decoder->retstack, &decoder->ip);
2432*74fe6c29SRuslan Bukin 	}
2433*74fe6c29SRuslan Bukin 
2434*74fe6c29SRuslan Bukin 	case ptbq_indirect:
2435*74fe6c29SRuslan Bukin 		/* We're at an indirect jump or far transfer.
2436*74fe6c29SRuslan Bukin 		 *
2437*74fe6c29SRuslan Bukin 		 * We don't know the exact instruction class and there's no
2438*74fe6c29SRuslan Bukin 		 * reason to decode the instruction for any other purpose.
2439*74fe6c29SRuslan Bukin 		 *
2440*74fe6c29SRuslan Bukin 		 * Indicate that we don't know the instruction class and leave
2441*74fe6c29SRuslan Bukin 		 * it to our caller to decode the instruction if needed.
2442*74fe6c29SRuslan Bukin 		 */
2443*74fe6c29SRuslan Bukin 		block->iclass = ptic_error;
2444*74fe6c29SRuslan Bukin 
2445*74fe6c29SRuslan Bukin 		/* This is neither a near call nor return so we don't need to
2446*74fe6c29SRuslan Bukin 		 * touch the return-address stack.
2447*74fe6c29SRuslan Bukin 		 *
2448*74fe6c29SRuslan Bukin 		 * Just query the destination IP.
2449*74fe6c29SRuslan Bukin 		 */
2450*74fe6c29SRuslan Bukin 		status = pt_blk_indirect_branch(decoder, &decoder->ip);
2451*74fe6c29SRuslan Bukin 		if (status < 0)
2452*74fe6c29SRuslan Bukin 			return status;
2453*74fe6c29SRuslan Bukin 
2454*74fe6c29SRuslan Bukin 		/* Preserve the query decoder's response which indicates
2455*74fe6c29SRuslan Bukin 		 * upcoming events.
2456*74fe6c29SRuslan Bukin 		 */
2457*74fe6c29SRuslan Bukin 		decoder->status = status;
2458*74fe6c29SRuslan Bukin 		break;
2459*74fe6c29SRuslan Bukin 	}
2460*74fe6c29SRuslan Bukin 
2461*74fe6c29SRuslan Bukin 	return 0;
2462*74fe6c29SRuslan Bukin }
2463*74fe6c29SRuslan Bukin 
pt_blk_msec_fill(struct pt_block_decoder * decoder,const struct pt_mapped_section ** pmsec)2464*74fe6c29SRuslan Bukin static int pt_blk_msec_fill(struct pt_block_decoder *decoder,
2465*74fe6c29SRuslan Bukin 			    const struct pt_mapped_section **pmsec)
2466*74fe6c29SRuslan Bukin {
2467*74fe6c29SRuslan Bukin 	const struct pt_mapped_section *msec;
2468*74fe6c29SRuslan Bukin 	struct pt_section *section;
2469*74fe6c29SRuslan Bukin 	int isid, errcode;
2470*74fe6c29SRuslan Bukin 
2471*74fe6c29SRuslan Bukin 	if (!decoder || !pmsec)
2472*74fe6c29SRuslan Bukin 		return -pte_internal;
2473*74fe6c29SRuslan Bukin 
2474*74fe6c29SRuslan Bukin 	isid = pt_msec_cache_fill(&decoder->scache, &msec,  decoder->image,
2475*74fe6c29SRuslan Bukin 				  &decoder->asid, decoder->ip);
2476*74fe6c29SRuslan Bukin 	if (isid < 0)
2477*74fe6c29SRuslan Bukin 		return isid;
2478*74fe6c29SRuslan Bukin 
2479*74fe6c29SRuslan Bukin 	section = pt_msec_section(msec);
2480*74fe6c29SRuslan Bukin 	if (!section)
2481*74fe6c29SRuslan Bukin 		return -pte_internal;
2482*74fe6c29SRuslan Bukin 
2483*74fe6c29SRuslan Bukin 	*pmsec = msec;
2484*74fe6c29SRuslan Bukin 
2485*74fe6c29SRuslan Bukin 	errcode = pt_section_request_bcache(section);
2486*74fe6c29SRuslan Bukin 	if (errcode < 0)
2487*74fe6c29SRuslan Bukin 		return errcode;
2488*74fe6c29SRuslan Bukin 
2489*74fe6c29SRuslan Bukin 	return isid;
2490*74fe6c29SRuslan Bukin }
2491*74fe6c29SRuslan Bukin 
pt_blk_msec_lookup(struct pt_block_decoder * decoder,const struct pt_mapped_section ** pmsec)2492*74fe6c29SRuslan Bukin static inline int pt_blk_msec_lookup(struct pt_block_decoder *decoder,
2493*74fe6c29SRuslan Bukin 				     const struct pt_mapped_section **pmsec)
2494*74fe6c29SRuslan Bukin {
2495*74fe6c29SRuslan Bukin 	int isid;
2496*74fe6c29SRuslan Bukin 
2497*74fe6c29SRuslan Bukin 	if (!decoder)
2498*74fe6c29SRuslan Bukin 		return -pte_internal;
2499*74fe6c29SRuslan Bukin 
2500*74fe6c29SRuslan Bukin 	isid = pt_msec_cache_read(&decoder->scache, pmsec, decoder->image,
2501*74fe6c29SRuslan Bukin 				  decoder->ip);
2502*74fe6c29SRuslan Bukin 	if (isid < 0) {
2503*74fe6c29SRuslan Bukin 		if (isid != -pte_nomap)
2504*74fe6c29SRuslan Bukin 			return isid;
2505*74fe6c29SRuslan Bukin 
2506*74fe6c29SRuslan Bukin 		return pt_blk_msec_fill(decoder, pmsec);
2507*74fe6c29SRuslan Bukin 	}
2508*74fe6c29SRuslan Bukin 
2509*74fe6c29SRuslan Bukin 	return isid;
2510*74fe6c29SRuslan Bukin }
2511*74fe6c29SRuslan Bukin 
2512*74fe6c29SRuslan Bukin /* Proceed to the next decision point - try using the cache.
2513*74fe6c29SRuslan Bukin  *
2514*74fe6c29SRuslan Bukin  * Tracing is enabled and we don't have an event pending.  Proceed as far as
2515*74fe6c29SRuslan Bukin  * we get without trace.  Stop when we either:
2516*74fe6c29SRuslan Bukin  *
2517*74fe6c29SRuslan Bukin  *   - need trace in order to continue
2518*74fe6c29SRuslan Bukin  *   - overflow the max number of instructions in a block
2519*74fe6c29SRuslan Bukin  *
2520*74fe6c29SRuslan Bukin  * We actually proceed one instruction further to get the start IP for the next
2521*74fe6c29SRuslan Bukin  * block.  This only updates @decoder's internal state, though.
2522*74fe6c29SRuslan Bukin  *
2523*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
2524*74fe6c29SRuslan Bukin  */
pt_blk_proceed_no_event(struct pt_block_decoder * decoder,struct pt_block * block)2525*74fe6c29SRuslan Bukin static int pt_blk_proceed_no_event(struct pt_block_decoder *decoder,
2526*74fe6c29SRuslan Bukin 				   struct pt_block *block)
2527*74fe6c29SRuslan Bukin {
2528*74fe6c29SRuslan Bukin 	const struct pt_mapped_section *msec;
2529*74fe6c29SRuslan Bukin 	struct pt_block_cache *bcache;
2530*74fe6c29SRuslan Bukin 	struct pt_section *section;
2531*74fe6c29SRuslan Bukin 	int isid;
2532*74fe6c29SRuslan Bukin 
2533*74fe6c29SRuslan Bukin 	if (!decoder || !block)
2534*74fe6c29SRuslan Bukin 		return -pte_internal;
2535*74fe6c29SRuslan Bukin 
2536*74fe6c29SRuslan Bukin 	isid = pt_blk_msec_lookup(decoder, &msec);
2537*74fe6c29SRuslan Bukin 	if (isid < 0) {
2538*74fe6c29SRuslan Bukin 		if (isid != -pte_nomap)
2539*74fe6c29SRuslan Bukin 			return isid;
2540*74fe6c29SRuslan Bukin 
2541*74fe6c29SRuslan Bukin 		/* Even if there is no such section in the image, we may still
2542*74fe6c29SRuslan Bukin 		 * read the memory via the callback function.
2543*74fe6c29SRuslan Bukin 		 */
2544*74fe6c29SRuslan Bukin 		return pt_blk_proceed_no_event_uncached(decoder, block);
2545*74fe6c29SRuslan Bukin 	}
2546*74fe6c29SRuslan Bukin 
2547*74fe6c29SRuslan Bukin 	/* We do not switch sections inside a block. */
2548*74fe6c29SRuslan Bukin 	if (isid != block->isid) {
2549*74fe6c29SRuslan Bukin 		if (!pt_blk_block_is_empty(block))
2550*74fe6c29SRuslan Bukin 			return 0;
2551*74fe6c29SRuslan Bukin 
2552*74fe6c29SRuslan Bukin 		block->isid = isid;
2553*74fe6c29SRuslan Bukin 	}
2554*74fe6c29SRuslan Bukin 
2555*74fe6c29SRuslan Bukin 	section = pt_msec_section(msec);
2556*74fe6c29SRuslan Bukin 	if (!section)
2557*74fe6c29SRuslan Bukin 		return -pte_internal;
2558*74fe6c29SRuslan Bukin 
2559*74fe6c29SRuslan Bukin 	bcache = pt_section_bcache(section);
2560*74fe6c29SRuslan Bukin 	if (!bcache)
2561*74fe6c29SRuslan Bukin 		return pt_blk_proceed_no_event_uncached(decoder, block);
2562*74fe6c29SRuslan Bukin 
2563*74fe6c29SRuslan Bukin 	return pt_blk_proceed_no_event_cached(decoder, block, bcache, msec);
2564*74fe6c29SRuslan Bukin }
2565*74fe6c29SRuslan Bukin 
2566*74fe6c29SRuslan Bukin /* Proceed to the next event or decision point.
2567*74fe6c29SRuslan Bukin  *
2568*74fe6c29SRuslan Bukin  * Returns a non-negative pt_status_flag bit-vector on success, a negative error
2569*74fe6c29SRuslan Bukin  * code otherwise.
2570*74fe6c29SRuslan Bukin  */
pt_blk_proceed(struct pt_block_decoder * decoder,struct pt_block * block)2571*74fe6c29SRuslan Bukin static int pt_blk_proceed(struct pt_block_decoder *decoder,
2572*74fe6c29SRuslan Bukin 			  struct pt_block *block)
2573*74fe6c29SRuslan Bukin {
2574*74fe6c29SRuslan Bukin 	int status;
2575*74fe6c29SRuslan Bukin 
2576*74fe6c29SRuslan Bukin 	status = pt_blk_fetch_event(decoder);
2577*74fe6c29SRuslan Bukin 	if (status != 0) {
2578*74fe6c29SRuslan Bukin 		if (status < 0)
2579*74fe6c29SRuslan Bukin 			return status;
2580*74fe6c29SRuslan Bukin 
2581*74fe6c29SRuslan Bukin 		return pt_blk_proceed_event(decoder, block);
2582*74fe6c29SRuslan Bukin 	}
2583*74fe6c29SRuslan Bukin 
2584*74fe6c29SRuslan Bukin 	/* If tracing is disabled we should either be out of trace or we should
2585*74fe6c29SRuslan Bukin 	 * have taken the event flow above.
2586*74fe6c29SRuslan Bukin 	 */
2587*74fe6c29SRuslan Bukin 	if (!decoder->enabled) {
2588*74fe6c29SRuslan Bukin 		if (decoder->status & pts_eos)
2589*74fe6c29SRuslan Bukin 			return -pte_eos;
2590*74fe6c29SRuslan Bukin 
2591*74fe6c29SRuslan Bukin 		return -pte_no_enable;
2592*74fe6c29SRuslan Bukin 	}
2593*74fe6c29SRuslan Bukin 
2594*74fe6c29SRuslan Bukin 	status = pt_blk_proceed_no_event(decoder, block);
2595*74fe6c29SRuslan Bukin 	if (status < 0)
2596*74fe6c29SRuslan Bukin 		return status;
2597*74fe6c29SRuslan Bukin 
2598*74fe6c29SRuslan Bukin 	return pt_blk_proceed_trailing_event(decoder, block);
2599*74fe6c29SRuslan Bukin }
2600*74fe6c29SRuslan Bukin 
2601*74fe6c29SRuslan Bukin enum {
2602*74fe6c29SRuslan Bukin 	/* The maximum number of steps to take when determining whether the
2603*74fe6c29SRuslan Bukin 	 * event location can be reached.
2604*74fe6c29SRuslan Bukin 	 */
2605*74fe6c29SRuslan Bukin 	bdm64_max_steps	= 0x100
2606*74fe6c29SRuslan Bukin };
2607*74fe6c29SRuslan Bukin 
2608*74fe6c29SRuslan Bukin /* Try to work around erratum BDM64.
2609*74fe6c29SRuslan Bukin  *
2610*74fe6c29SRuslan Bukin  * If we got a transaction abort immediately following a branch that produced
2611*74fe6c29SRuslan Bukin  * trace, the trace for that branch might have been corrupted.
2612*74fe6c29SRuslan Bukin  *
2613*74fe6c29SRuslan Bukin  * Returns a positive integer if the erratum was handled.
2614*74fe6c29SRuslan Bukin  * Returns zero if the erratum does not seem to apply.
2615*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
2616*74fe6c29SRuslan Bukin  */
pt_blk_handle_erratum_bdm64(struct pt_block_decoder * decoder,const struct pt_block * block,const struct pt_event * ev)2617*74fe6c29SRuslan Bukin static int pt_blk_handle_erratum_bdm64(struct pt_block_decoder *decoder,
2618*74fe6c29SRuslan Bukin 				       const struct pt_block *block,
2619*74fe6c29SRuslan Bukin 				       const struct pt_event *ev)
2620*74fe6c29SRuslan Bukin {
2621*74fe6c29SRuslan Bukin 	struct pt_insn_ext iext;
2622*74fe6c29SRuslan Bukin 	struct pt_insn insn;
2623*74fe6c29SRuslan Bukin 	int status;
2624*74fe6c29SRuslan Bukin 
2625*74fe6c29SRuslan Bukin 	if (!decoder || !block || !ev)
2626*74fe6c29SRuslan Bukin 		return -pte_internal;
2627*74fe6c29SRuslan Bukin 
2628*74fe6c29SRuslan Bukin 	/* This only affects aborts. */
2629*74fe6c29SRuslan Bukin 	if (!ev->variant.tsx.aborted)
2630*74fe6c29SRuslan Bukin 		return 0;
2631*74fe6c29SRuslan Bukin 
2632*74fe6c29SRuslan Bukin 	/* This only affects branches that require trace.
2633*74fe6c29SRuslan Bukin 	 *
2634*74fe6c29SRuslan Bukin 	 * If the erratum hits, that branch ended the current block and brought
2635*74fe6c29SRuslan Bukin 	 * us to the trailing event flow.
2636*74fe6c29SRuslan Bukin 	 */
2637*74fe6c29SRuslan Bukin 	if (pt_blk_block_is_empty(block))
2638*74fe6c29SRuslan Bukin 		return 0;
2639*74fe6c29SRuslan Bukin 
2640*74fe6c29SRuslan Bukin 	insn.mode = block->mode;
2641*74fe6c29SRuslan Bukin 	insn.ip = block->end_ip;
2642*74fe6c29SRuslan Bukin 
2643*74fe6c29SRuslan Bukin 	status = pt_insn_decode(&insn, &iext, decoder->image, &decoder->asid);
2644*74fe6c29SRuslan Bukin 	if (status < 0)
2645*74fe6c29SRuslan Bukin 		return 0;
2646*74fe6c29SRuslan Bukin 
2647*74fe6c29SRuslan Bukin 	if (!pt_insn_is_branch(&insn, &iext))
2648*74fe6c29SRuslan Bukin 		return 0;
2649*74fe6c29SRuslan Bukin 
2650*74fe6c29SRuslan Bukin 	/* Let's check if we can reach the event location from here.
2651*74fe6c29SRuslan Bukin 	 *
2652*74fe6c29SRuslan Bukin 	 * If we can, let's assume the erratum did not hit.  We might still be
2653*74fe6c29SRuslan Bukin 	 * wrong but we're not able to tell.
2654*74fe6c29SRuslan Bukin 	 */
2655*74fe6c29SRuslan Bukin 	status = pt_insn_range_is_contiguous(decoder->ip, ev->variant.tsx.ip,
2656*74fe6c29SRuslan Bukin 					     decoder->mode, decoder->image,
2657*74fe6c29SRuslan Bukin 					     &decoder->asid, bdm64_max_steps);
2658*74fe6c29SRuslan Bukin 	if (status > 0)
2659*74fe6c29SRuslan Bukin 		return status;
2660*74fe6c29SRuslan Bukin 
2661*74fe6c29SRuslan Bukin 	/* We can't reach the event location.  This could either mean that we
2662*74fe6c29SRuslan Bukin 	 * stopped too early (and status is zero) or that the erratum hit.
2663*74fe6c29SRuslan Bukin 	 *
2664*74fe6c29SRuslan Bukin 	 * We assume the latter and pretend that the previous branch brought us
2665*74fe6c29SRuslan Bukin 	 * to the event location, instead.
2666*74fe6c29SRuslan Bukin 	 */
2667*74fe6c29SRuslan Bukin 	decoder->ip = ev->variant.tsx.ip;
2668*74fe6c29SRuslan Bukin 
2669*74fe6c29SRuslan Bukin 	return 1;
2670*74fe6c29SRuslan Bukin }
2671*74fe6c29SRuslan Bukin 
2672*74fe6c29SRuslan Bukin /* Check whether a trailing TSX event should be postponed.
2673*74fe6c29SRuslan Bukin  *
2674*74fe6c29SRuslan Bukin  * This involves handling erratum BDM64.
2675*74fe6c29SRuslan Bukin  *
2676*74fe6c29SRuslan Bukin  * Returns a positive integer if the event is to be postponed.
2677*74fe6c29SRuslan Bukin  * Returns zero if the event should be processed.
2678*74fe6c29SRuslan Bukin  * Returns a negative error code otherwise.
2679*74fe6c29SRuslan Bukin  */
pt_blk_postpone_trailing_tsx(struct pt_block_decoder * decoder,struct pt_block * block,const struct pt_event * ev)2680*74fe6c29SRuslan Bukin static inline int pt_blk_postpone_trailing_tsx(struct pt_block_decoder *decoder,
2681*74fe6c29SRuslan Bukin 					       struct pt_block *block,
2682*74fe6c29SRuslan Bukin 					       const struct pt_event *ev)
2683*74fe6c29SRuslan Bukin {
2684*74fe6c29SRuslan Bukin 	int status;
2685*74fe6c29SRuslan Bukin 
2686*74fe6c29SRuslan Bukin 	if (!decoder || !ev)
2687*74fe6c29SRuslan Bukin 		return -pte_internal;
2688*74fe6c29SRuslan Bukin 
2689*74fe6c29SRuslan Bukin 	if (ev->ip_suppressed)
2690*74fe6c29SRuslan Bukin 		return 0;
2691*74fe6c29SRuslan Bukin 
2692*74fe6c29SRuslan Bukin 	if (block && decoder->query.config.errata.bdm64) {
2693*74fe6c29SRuslan Bukin 		status = pt_blk_handle_erratum_bdm64(decoder, block, ev);
2694*74fe6c29SRuslan Bukin 		if (status < 0)
2695*74fe6c29SRuslan Bukin 			return 1;
2696*74fe6c29SRuslan Bukin 	}
2697*74fe6c29SRuslan Bukin 
2698*74fe6c29SRuslan Bukin 	if (decoder->ip != ev->variant.tsx.ip)
2699*74fe6c29SRuslan Bukin 		return 1;
2700*74fe6c29SRuslan Bukin 
2701*74fe6c29SRuslan Bukin 	return 0;
2702*74fe6c29SRuslan Bukin }
2703*74fe6c29SRuslan Bukin 
2704*74fe6c29SRuslan Bukin /* Proceed with events that bind to the current decoder IP.
2705*74fe6c29SRuslan Bukin  *
2706*74fe6c29SRuslan Bukin  * This function is used in the following scenarios:
2707*74fe6c29SRuslan Bukin  *
2708*74fe6c29SRuslan Bukin  *   - we just synchronized onto the trace stream
2709*74fe6c29SRuslan Bukin  *   - we ended a block and proceeded to the next IP
2710*74fe6c29SRuslan Bukin  *   - we processed an event that was indicated by this function
2711*74fe6c29SRuslan Bukin  *
2712*74fe6c29SRuslan Bukin  * Check if there is an event at the current IP that needs to be indicated to
2713*74fe6c29SRuslan Bukin  * the user.
2714*74fe6c29SRuslan Bukin  *
2715*74fe6c29SRuslan Bukin  * Returns a non-negative pt_status_flag bit-vector on success, a negative error
2716*74fe6c29SRuslan Bukin  * code otherwise.
2717*74fe6c29SRuslan Bukin  */
pt_blk_proceed_trailing_event(struct pt_block_decoder * decoder,struct pt_block * block)2718*74fe6c29SRuslan Bukin static int pt_blk_proceed_trailing_event(struct pt_block_decoder *decoder,
2719*74fe6c29SRuslan Bukin 					 struct pt_block *block)
2720*74fe6c29SRuslan Bukin {
2721*74fe6c29SRuslan Bukin 	struct pt_event *ev;
2722*74fe6c29SRuslan Bukin 	int status;
2723*74fe6c29SRuslan Bukin 
2724*74fe6c29SRuslan Bukin 	if (!decoder)
2725*74fe6c29SRuslan Bukin 		return -pte_internal;
2726*74fe6c29SRuslan Bukin 
2727*74fe6c29SRuslan Bukin 	status = pt_blk_fetch_event(decoder);
2728*74fe6c29SRuslan Bukin 	if (status <= 0) {
2729*74fe6c29SRuslan Bukin 		if (status < 0)
2730*74fe6c29SRuslan Bukin 			return status;
2731*74fe6c29SRuslan Bukin 
2732*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_postponed_insn(decoder);
2733*74fe6c29SRuslan Bukin 		if (status < 0)
2734*74fe6c29SRuslan Bukin 			return status;
2735*74fe6c29SRuslan Bukin 
2736*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, 0);
2737*74fe6c29SRuslan Bukin 	}
2738*74fe6c29SRuslan Bukin 
2739*74fe6c29SRuslan Bukin 	ev = &decoder->event;
2740*74fe6c29SRuslan Bukin 	switch (ev->type) {
2741*74fe6c29SRuslan Bukin 	case ptev_disabled:
2742*74fe6c29SRuslan Bukin 		/* Synchronous disable events are normally indicated on the
2743*74fe6c29SRuslan Bukin 		 * event flow.
2744*74fe6c29SRuslan Bukin 		 */
2745*74fe6c29SRuslan Bukin 		if (!decoder->process_insn)
2746*74fe6c29SRuslan Bukin 			break;
2747*74fe6c29SRuslan Bukin 
2748*74fe6c29SRuslan Bukin 		/* A sync disable may bind to a CR3 changing instruction. */
2749*74fe6c29SRuslan Bukin 		if (ev->ip_suppressed &&
2750*74fe6c29SRuslan Bukin 		    pt_insn_changes_cr3(&decoder->insn, &decoder->iext))
2751*74fe6c29SRuslan Bukin 			return pt_blk_status(decoder, pts_event_pending);
2752*74fe6c29SRuslan Bukin 
2753*74fe6c29SRuslan Bukin 		/* Or it binds to the next branch that would require trace.
2754*74fe6c29SRuslan Bukin 		 *
2755*74fe6c29SRuslan Bukin 		 * Try to complete processing the current instruction by
2756*74fe6c29SRuslan Bukin 		 * proceeding past it.  If that fails because it would require
2757*74fe6c29SRuslan Bukin 		 * trace, we can apply the disabled event.
2758*74fe6c29SRuslan Bukin 		 */
2759*74fe6c29SRuslan Bukin 		status = pt_insn_next_ip(&decoder->ip, &decoder->insn,
2760*74fe6c29SRuslan Bukin 					 &decoder->iext);
2761*74fe6c29SRuslan Bukin 		if (status < 0) {
2762*74fe6c29SRuslan Bukin 			if (status != -pte_bad_query)
2763*74fe6c29SRuslan Bukin 				return status;
2764*74fe6c29SRuslan Bukin 
2765*74fe6c29SRuslan Bukin 			status = pt_blk_set_disable_resume_ip(decoder,
2766*74fe6c29SRuslan Bukin 							      &decoder->insn);
2767*74fe6c29SRuslan Bukin 			if (status < 0)
2768*74fe6c29SRuslan Bukin 				return status;
2769*74fe6c29SRuslan Bukin 
2770*74fe6c29SRuslan Bukin 			return pt_blk_status(decoder, pts_event_pending);
2771*74fe6c29SRuslan Bukin 		}
2772*74fe6c29SRuslan Bukin 
2773*74fe6c29SRuslan Bukin 		/* We proceeded past the current instruction. */
2774*74fe6c29SRuslan Bukin 		status = pt_blk_clear_postponed_insn(decoder);
2775*74fe6c29SRuslan Bukin 		if (status < 0)
2776*74fe6c29SRuslan Bukin 			return status;
2777*74fe6c29SRuslan Bukin 
2778*74fe6c29SRuslan Bukin 		/* This might have brought us to the disable IP. */
2779*74fe6c29SRuslan Bukin 		if (!ev->ip_suppressed &&
2780*74fe6c29SRuslan Bukin 		    decoder->ip == ev->variant.disabled.ip)
2781*74fe6c29SRuslan Bukin 			return pt_blk_status(decoder, pts_event_pending);
2782*74fe6c29SRuslan Bukin 
2783*74fe6c29SRuslan Bukin 		break;
2784*74fe6c29SRuslan Bukin 
2785*74fe6c29SRuslan Bukin 	case ptev_enabled:
2786*74fe6c29SRuslan Bukin 		/* This event does not bind to an instruction. */
2787*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_postponed_insn(decoder);
2788*74fe6c29SRuslan Bukin 		if (status < 0)
2789*74fe6c29SRuslan Bukin 			return status;
2790*74fe6c29SRuslan Bukin 
2791*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
2792*74fe6c29SRuslan Bukin 
2793*74fe6c29SRuslan Bukin 	case ptev_async_disabled:
2794*74fe6c29SRuslan Bukin 		/* This event does not bind to an instruction. */
2795*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_postponed_insn(decoder);
2796*74fe6c29SRuslan Bukin 		if (status < 0)
2797*74fe6c29SRuslan Bukin 			return status;
2798*74fe6c29SRuslan Bukin 
2799*74fe6c29SRuslan Bukin 		if (decoder->ip != ev->variant.async_disabled.at)
2800*74fe6c29SRuslan Bukin 			break;
2801*74fe6c29SRuslan Bukin 
2802*74fe6c29SRuslan Bukin 		if (decoder->query.config.errata.skd022) {
2803*74fe6c29SRuslan Bukin 			status = pt_blk_handle_erratum_skd022(decoder, ev);
2804*74fe6c29SRuslan Bukin 			if (status != 0) {
2805*74fe6c29SRuslan Bukin 				if (status < 0)
2806*74fe6c29SRuslan Bukin 					return status;
2807*74fe6c29SRuslan Bukin 
2808*74fe6c29SRuslan Bukin 				/* If the erratum applies, the event is modified
2809*74fe6c29SRuslan Bukin 				 * to a synchronous disable event that will be
2810*74fe6c29SRuslan Bukin 				 * processed on the next pt_blk_proceed_event()
2811*74fe6c29SRuslan Bukin 				 * call.  We're done.
2812*74fe6c29SRuslan Bukin 				 */
2813*74fe6c29SRuslan Bukin 				break;
2814*74fe6c29SRuslan Bukin 			}
2815*74fe6c29SRuslan Bukin 		}
2816*74fe6c29SRuslan Bukin 
2817*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
2818*74fe6c29SRuslan Bukin 
2819*74fe6c29SRuslan Bukin 	case ptev_async_branch:
2820*74fe6c29SRuslan Bukin 		/* This event does not bind to an instruction. */
2821*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_postponed_insn(decoder);
2822*74fe6c29SRuslan Bukin 		if (status < 0)
2823*74fe6c29SRuslan Bukin 			return status;
2824*74fe6c29SRuslan Bukin 
2825*74fe6c29SRuslan Bukin 		if (decoder->ip != ev->variant.async_branch.from)
2826*74fe6c29SRuslan Bukin 			break;
2827*74fe6c29SRuslan Bukin 
2828*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
2829*74fe6c29SRuslan Bukin 
2830*74fe6c29SRuslan Bukin 	case ptev_paging:
2831*74fe6c29SRuslan Bukin 		/* We apply the event immediately if we're not tracing. */
2832*74fe6c29SRuslan Bukin 		if (!decoder->enabled)
2833*74fe6c29SRuslan Bukin 			return pt_blk_status(decoder, pts_event_pending);
2834*74fe6c29SRuslan Bukin 
2835*74fe6c29SRuslan Bukin 		/* Synchronous paging events are normally indicated on the event
2836*74fe6c29SRuslan Bukin 		 * flow, unless they bind to the same instruction as a previous
2837*74fe6c29SRuslan Bukin 		 * event.
2838*74fe6c29SRuslan Bukin 		 *
2839*74fe6c29SRuslan Bukin 		 * We bind at most one paging event to an instruction, though.
2840*74fe6c29SRuslan Bukin 		 */
2841*74fe6c29SRuslan Bukin 		if (!decoder->process_insn || decoder->bound_paging)
2842*74fe6c29SRuslan Bukin 			break;
2843*74fe6c29SRuslan Bukin 
2844*74fe6c29SRuslan Bukin 		/* We're done if we're not binding to the currently postponed
2845*74fe6c29SRuslan Bukin 		 * instruction.  We will process the event on the normal event
2846*74fe6c29SRuslan Bukin 		 * flow in the next iteration.
2847*74fe6c29SRuslan Bukin 		 */
2848*74fe6c29SRuslan Bukin 		if (!pt_insn_binds_to_pip(&decoder->insn, &decoder->iext))
2849*74fe6c29SRuslan Bukin 			break;
2850*74fe6c29SRuslan Bukin 
2851*74fe6c29SRuslan Bukin 		/* We bound a paging event.  Make sure we do not bind further
2852*74fe6c29SRuslan Bukin 		 * paging events to this instruction.
2853*74fe6c29SRuslan Bukin 		 */
2854*74fe6c29SRuslan Bukin 		decoder->bound_paging = 1;
2855*74fe6c29SRuslan Bukin 
2856*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
2857*74fe6c29SRuslan Bukin 
2858*74fe6c29SRuslan Bukin 	case ptev_async_paging:
2859*74fe6c29SRuslan Bukin 		/* This event does not bind to an instruction. */
2860*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_postponed_insn(decoder);
2861*74fe6c29SRuslan Bukin 		if (status < 0)
2862*74fe6c29SRuslan Bukin 			return status;
2863*74fe6c29SRuslan Bukin 
2864*74fe6c29SRuslan Bukin 		if (!ev->ip_suppressed &&
2865*74fe6c29SRuslan Bukin 		    decoder->ip != ev->variant.async_paging.ip)
2866*74fe6c29SRuslan Bukin 			break;
2867*74fe6c29SRuslan Bukin 
2868*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
2869*74fe6c29SRuslan Bukin 
2870*74fe6c29SRuslan Bukin 	case ptev_vmcs:
2871*74fe6c29SRuslan Bukin 		/* We apply the event immediately if we're not tracing. */
2872*74fe6c29SRuslan Bukin 		if (!decoder->enabled)
2873*74fe6c29SRuslan Bukin 			return pt_blk_status(decoder, pts_event_pending);
2874*74fe6c29SRuslan Bukin 
2875*74fe6c29SRuslan Bukin 		/* Synchronous vmcs events are normally indicated on the event
2876*74fe6c29SRuslan Bukin 		 * flow, unless they bind to the same instruction as a previous
2877*74fe6c29SRuslan Bukin 		 * event.
2878*74fe6c29SRuslan Bukin 		 *
2879*74fe6c29SRuslan Bukin 		 * We bind at most one vmcs event to an instruction, though.
2880*74fe6c29SRuslan Bukin 		 */
2881*74fe6c29SRuslan Bukin 		if (!decoder->process_insn || decoder->bound_vmcs)
2882*74fe6c29SRuslan Bukin 			break;
2883*74fe6c29SRuslan Bukin 
2884*74fe6c29SRuslan Bukin 		/* We're done if we're not binding to the currently postponed
2885*74fe6c29SRuslan Bukin 		 * instruction.  We will process the event on the normal event
2886*74fe6c29SRuslan Bukin 		 * flow in the next iteration.
2887*74fe6c29SRuslan Bukin 		 */
2888*74fe6c29SRuslan Bukin 		if (!pt_insn_binds_to_vmcs(&decoder->insn, &decoder->iext))
2889*74fe6c29SRuslan Bukin 			break;
2890*74fe6c29SRuslan Bukin 
2891*74fe6c29SRuslan Bukin 		/* We bound a vmcs event.  Make sure we do not bind further vmcs
2892*74fe6c29SRuslan Bukin 		 * events to this instruction.
2893*74fe6c29SRuslan Bukin 		 */
2894*74fe6c29SRuslan Bukin 		decoder->bound_vmcs = 1;
2895*74fe6c29SRuslan Bukin 
2896*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
2897*74fe6c29SRuslan Bukin 
2898*74fe6c29SRuslan Bukin 	case ptev_async_vmcs:
2899*74fe6c29SRuslan Bukin 		/* This event does not bind to an instruction. */
2900*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_postponed_insn(decoder);
2901*74fe6c29SRuslan Bukin 		if (status < 0)
2902*74fe6c29SRuslan Bukin 			return status;
2903*74fe6c29SRuslan Bukin 
2904*74fe6c29SRuslan Bukin 		if (!ev->ip_suppressed &&
2905*74fe6c29SRuslan Bukin 		    decoder->ip != ev->variant.async_vmcs.ip)
2906*74fe6c29SRuslan Bukin 			break;
2907*74fe6c29SRuslan Bukin 
2908*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
2909*74fe6c29SRuslan Bukin 
2910*74fe6c29SRuslan Bukin 	case ptev_overflow:
2911*74fe6c29SRuslan Bukin 		/* This event does not bind to an instruction. */
2912*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_postponed_insn(decoder);
2913*74fe6c29SRuslan Bukin 		if (status < 0)
2914*74fe6c29SRuslan Bukin 			return status;
2915*74fe6c29SRuslan Bukin 
2916*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
2917*74fe6c29SRuslan Bukin 
2918*74fe6c29SRuslan Bukin 	case ptev_exec_mode:
2919*74fe6c29SRuslan Bukin 		/* This event does not bind to an instruction. */
2920*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_postponed_insn(decoder);
2921*74fe6c29SRuslan Bukin 		if (status < 0)
2922*74fe6c29SRuslan Bukin 			return status;
2923*74fe6c29SRuslan Bukin 
2924*74fe6c29SRuslan Bukin 		if (!ev->ip_suppressed &&
2925*74fe6c29SRuslan Bukin 		    decoder->ip != ev->variant.exec_mode.ip)
2926*74fe6c29SRuslan Bukin 			break;
2927*74fe6c29SRuslan Bukin 
2928*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
2929*74fe6c29SRuslan Bukin 
2930*74fe6c29SRuslan Bukin 	case ptev_tsx:
2931*74fe6c29SRuslan Bukin 		/* This event does not bind to an instruction. */
2932*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_postponed_insn(decoder);
2933*74fe6c29SRuslan Bukin 		if (status < 0)
2934*74fe6c29SRuslan Bukin 			return status;
2935*74fe6c29SRuslan Bukin 
2936*74fe6c29SRuslan Bukin 		status = pt_blk_postpone_trailing_tsx(decoder, block, ev);
2937*74fe6c29SRuslan Bukin 		if (status != 0) {
2938*74fe6c29SRuslan Bukin 			if (status < 0)
2939*74fe6c29SRuslan Bukin 				return status;
2940*74fe6c29SRuslan Bukin 
2941*74fe6c29SRuslan Bukin 			break;
2942*74fe6c29SRuslan Bukin 		}
2943*74fe6c29SRuslan Bukin 
2944*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
2945*74fe6c29SRuslan Bukin 
2946*74fe6c29SRuslan Bukin 	case ptev_stop:
2947*74fe6c29SRuslan Bukin 		/* This event does not bind to an instruction. */
2948*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_postponed_insn(decoder);
2949*74fe6c29SRuslan Bukin 		if (status < 0)
2950*74fe6c29SRuslan Bukin 			return status;
2951*74fe6c29SRuslan Bukin 
2952*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
2953*74fe6c29SRuslan Bukin 
2954*74fe6c29SRuslan Bukin 	case ptev_exstop:
2955*74fe6c29SRuslan Bukin 		/* This event does not bind to an instruction. */
2956*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_postponed_insn(decoder);
2957*74fe6c29SRuslan Bukin 		if (status < 0)
2958*74fe6c29SRuslan Bukin 			return status;
2959*74fe6c29SRuslan Bukin 
2960*74fe6c29SRuslan Bukin 		if (!ev->ip_suppressed && decoder->enabled &&
2961*74fe6c29SRuslan Bukin 		    decoder->ip != ev->variant.exstop.ip)
2962*74fe6c29SRuslan Bukin 			break;
2963*74fe6c29SRuslan Bukin 
2964*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
2965*74fe6c29SRuslan Bukin 
2966*74fe6c29SRuslan Bukin 	case ptev_mwait:
2967*74fe6c29SRuslan Bukin 		/* This event does not bind to an instruction. */
2968*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_postponed_insn(decoder);
2969*74fe6c29SRuslan Bukin 		if (status < 0)
2970*74fe6c29SRuslan Bukin 			return status;
2971*74fe6c29SRuslan Bukin 
2972*74fe6c29SRuslan Bukin 		if (!ev->ip_suppressed && decoder->enabled &&
2973*74fe6c29SRuslan Bukin 		    decoder->ip != ev->variant.mwait.ip)
2974*74fe6c29SRuslan Bukin 			break;
2975*74fe6c29SRuslan Bukin 
2976*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
2977*74fe6c29SRuslan Bukin 
2978*74fe6c29SRuslan Bukin 	case ptev_pwre:
2979*74fe6c29SRuslan Bukin 	case ptev_pwrx:
2980*74fe6c29SRuslan Bukin 		/* This event does not bind to an instruction. */
2981*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_postponed_insn(decoder);
2982*74fe6c29SRuslan Bukin 		if (status < 0)
2983*74fe6c29SRuslan Bukin 			return status;
2984*74fe6c29SRuslan Bukin 
2985*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
2986*74fe6c29SRuslan Bukin 
2987*74fe6c29SRuslan Bukin 	case ptev_ptwrite:
2988*74fe6c29SRuslan Bukin 		/* We apply the event immediately if we're not tracing. */
2989*74fe6c29SRuslan Bukin 		if (!decoder->enabled)
2990*74fe6c29SRuslan Bukin 			return pt_blk_status(decoder, pts_event_pending);
2991*74fe6c29SRuslan Bukin 
2992*74fe6c29SRuslan Bukin 		/* Ptwrite events are normally indicated on the event flow,
2993*74fe6c29SRuslan Bukin 		 * unless they bind to the same instruction as a previous event.
2994*74fe6c29SRuslan Bukin 		 *
2995*74fe6c29SRuslan Bukin 		 * We bind at most one ptwrite event to an instruction, though.
2996*74fe6c29SRuslan Bukin 		 */
2997*74fe6c29SRuslan Bukin 		if (!decoder->process_insn || decoder->bound_ptwrite)
2998*74fe6c29SRuslan Bukin 			break;
2999*74fe6c29SRuslan Bukin 
3000*74fe6c29SRuslan Bukin 		/* We're done if we're not binding to the currently postponed
3001*74fe6c29SRuslan Bukin 		 * instruction.  We will process the event on the normal event
3002*74fe6c29SRuslan Bukin 		 * flow in the next iteration.
3003*74fe6c29SRuslan Bukin 		 */
3004*74fe6c29SRuslan Bukin 		if (!ev->ip_suppressed ||
3005*74fe6c29SRuslan Bukin 		    !pt_insn_is_ptwrite(&decoder->insn, &decoder->iext))
3006*74fe6c29SRuslan Bukin 			break;
3007*74fe6c29SRuslan Bukin 
3008*74fe6c29SRuslan Bukin 		/* We bound a ptwrite event.  Make sure we do not bind further
3009*74fe6c29SRuslan Bukin 		 * ptwrite events to this instruction.
3010*74fe6c29SRuslan Bukin 		 */
3011*74fe6c29SRuslan Bukin 		decoder->bound_ptwrite = 1;
3012*74fe6c29SRuslan Bukin 
3013*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
3014*74fe6c29SRuslan Bukin 
3015*74fe6c29SRuslan Bukin 	case ptev_tick:
3016*74fe6c29SRuslan Bukin 	case ptev_cbr:
3017*74fe6c29SRuslan Bukin 	case ptev_mnt:
3018*74fe6c29SRuslan Bukin 		/* This event does not bind to an instruction. */
3019*74fe6c29SRuslan Bukin 		status = pt_blk_proceed_postponed_insn(decoder);
3020*74fe6c29SRuslan Bukin 		if (status < 0)
3021*74fe6c29SRuslan Bukin 			return status;
3022*74fe6c29SRuslan Bukin 
3023*74fe6c29SRuslan Bukin 		return pt_blk_status(decoder, pts_event_pending);
3024*74fe6c29SRuslan Bukin 	}
3025*74fe6c29SRuslan Bukin 
3026*74fe6c29SRuslan Bukin 	/* No further events.  Proceed past any postponed instruction. */
3027*74fe6c29SRuslan Bukin 	status = pt_blk_proceed_postponed_insn(decoder);
3028*74fe6c29SRuslan Bukin 	if (status < 0)
3029*74fe6c29SRuslan Bukin 		return status;
3030*74fe6c29SRuslan Bukin 
3031*74fe6c29SRuslan Bukin 	return pt_blk_status(decoder, 0);
3032*74fe6c29SRuslan Bukin }
3033*74fe6c29SRuslan Bukin 
pt_blk_next(struct pt_block_decoder * decoder,struct pt_block * ublock,size_t size)3034*74fe6c29SRuslan Bukin int pt_blk_next(struct pt_block_decoder *decoder, struct pt_block *ublock,
3035*74fe6c29SRuslan Bukin 		size_t size)
3036*74fe6c29SRuslan Bukin {
3037*74fe6c29SRuslan Bukin 	struct pt_block block, *pblock;
3038*74fe6c29SRuslan Bukin 	int errcode, status;
3039*74fe6c29SRuslan Bukin 
3040*74fe6c29SRuslan Bukin 	if (!decoder || !ublock)
3041*74fe6c29SRuslan Bukin 		return -pte_invalid;
3042*74fe6c29SRuslan Bukin 
3043*74fe6c29SRuslan Bukin 	pblock = size == sizeof(block) ? ublock : &block;
3044*74fe6c29SRuslan Bukin 
3045*74fe6c29SRuslan Bukin 	/* Zero-initialize the block in case of error returns. */
3046*74fe6c29SRuslan Bukin 	memset(pblock, 0, sizeof(*pblock));
3047*74fe6c29SRuslan Bukin 
3048*74fe6c29SRuslan Bukin 	/* Fill in a few things from the current decode state.
3049*74fe6c29SRuslan Bukin 	 *
3050*74fe6c29SRuslan Bukin 	 * This reflects the state of the last pt_blk_next() or pt_blk_start()
3051*74fe6c29SRuslan Bukin 	 * call.  Note that, unless we stop with tracing disabled, we proceed
3052*74fe6c29SRuslan Bukin 	 * already to the start IP of the next block.
3053*74fe6c29SRuslan Bukin 	 *
3054*74fe6c29SRuslan Bukin 	 * Some of the state may later be overwritten as we process events.
3055*74fe6c29SRuslan Bukin 	 */
3056*74fe6c29SRuslan Bukin 	pblock->ip = decoder->ip;
3057*74fe6c29SRuslan Bukin 	pblock->mode = decoder->mode;
3058*74fe6c29SRuslan Bukin 	if (decoder->speculative)
3059*74fe6c29SRuslan Bukin 		pblock->speculative = 1;
3060*74fe6c29SRuslan Bukin 
3061*74fe6c29SRuslan Bukin 	/* Proceed one block. */
3062*74fe6c29SRuslan Bukin 	status = pt_blk_proceed(decoder, pblock);
3063*74fe6c29SRuslan Bukin 
3064*74fe6c29SRuslan Bukin 	errcode = block_to_user(ublock, size, pblock);
3065*74fe6c29SRuslan Bukin 	if (errcode < 0)
3066*74fe6c29SRuslan Bukin 		return errcode;
3067*74fe6c29SRuslan Bukin 
3068*74fe6c29SRuslan Bukin 	return status;
3069*74fe6c29SRuslan Bukin }
3070*74fe6c29SRuslan Bukin 
3071*74fe6c29SRuslan Bukin /* Process an enabled event.
3072*74fe6c29SRuslan Bukin  *
3073*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
3074*74fe6c29SRuslan Bukin  */
pt_blk_process_enabled(struct pt_block_decoder * decoder,const struct pt_event * ev)3075*74fe6c29SRuslan Bukin static int pt_blk_process_enabled(struct pt_block_decoder *decoder,
3076*74fe6c29SRuslan Bukin 				  const struct pt_event *ev)
3077*74fe6c29SRuslan Bukin {
3078*74fe6c29SRuslan Bukin 	if (!decoder || !ev)
3079*74fe6c29SRuslan Bukin 		return -pte_internal;
3080*74fe6c29SRuslan Bukin 
3081*74fe6c29SRuslan Bukin 	/* This event can't be a status update. */
3082*74fe6c29SRuslan Bukin 	if (ev->status_update)
3083*74fe6c29SRuslan Bukin 		return -pte_bad_context;
3084*74fe6c29SRuslan Bukin 
3085*74fe6c29SRuslan Bukin 	/* We must have an IP in order to start decoding. */
3086*74fe6c29SRuslan Bukin 	if (ev->ip_suppressed)
3087*74fe6c29SRuslan Bukin 		return -pte_noip;
3088*74fe6c29SRuslan Bukin 
3089*74fe6c29SRuslan Bukin 	/* We must currently be disabled. */
3090*74fe6c29SRuslan Bukin 	if (decoder->enabled)
3091*74fe6c29SRuslan Bukin 		return -pte_bad_context;
3092*74fe6c29SRuslan Bukin 
3093*74fe6c29SRuslan Bukin 	decoder->ip = ev->variant.enabled.ip;
3094*74fe6c29SRuslan Bukin 	decoder->enabled = 1;
3095*74fe6c29SRuslan Bukin 	decoder->process_event = 0;
3096*74fe6c29SRuslan Bukin 
3097*74fe6c29SRuslan Bukin 	return 0;
3098*74fe6c29SRuslan Bukin }
3099*74fe6c29SRuslan Bukin 
3100*74fe6c29SRuslan Bukin /* Process a disabled event.
3101*74fe6c29SRuslan Bukin  *
3102*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
3103*74fe6c29SRuslan Bukin  */
pt_blk_process_disabled(struct pt_block_decoder * decoder,const struct pt_event * ev)3104*74fe6c29SRuslan Bukin static int pt_blk_process_disabled(struct pt_block_decoder *decoder,
3105*74fe6c29SRuslan Bukin 				   const struct pt_event *ev)
3106*74fe6c29SRuslan Bukin {
3107*74fe6c29SRuslan Bukin 	if (!decoder || !ev)
3108*74fe6c29SRuslan Bukin 		return -pte_internal;
3109*74fe6c29SRuslan Bukin 
3110*74fe6c29SRuslan Bukin 	/* This event can't be a status update. */
3111*74fe6c29SRuslan Bukin 	if (ev->status_update)
3112*74fe6c29SRuslan Bukin 		return -pte_bad_context;
3113*74fe6c29SRuslan Bukin 
3114*74fe6c29SRuslan Bukin 	/* We must currently be enabled. */
3115*74fe6c29SRuslan Bukin 	if (!decoder->enabled)
3116*74fe6c29SRuslan Bukin 		return -pte_bad_context;
3117*74fe6c29SRuslan Bukin 
3118*74fe6c29SRuslan Bukin 	/* We preserve @decoder->ip.  This is where we expect tracing to resume
3119*74fe6c29SRuslan Bukin 	 * and we'll indicate that on the subsequent enabled event if tracing
3120*74fe6c29SRuslan Bukin 	 * actually does resume from there.
3121*74fe6c29SRuslan Bukin 	 */
3122*74fe6c29SRuslan Bukin 	decoder->enabled = 0;
3123*74fe6c29SRuslan Bukin 	decoder->process_event = 0;
3124*74fe6c29SRuslan Bukin 
3125*74fe6c29SRuslan Bukin 	return 0;
3126*74fe6c29SRuslan Bukin }
3127*74fe6c29SRuslan Bukin 
3128*74fe6c29SRuslan Bukin /* Process an asynchronous branch event.
3129*74fe6c29SRuslan Bukin  *
3130*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
3131*74fe6c29SRuslan Bukin  */
pt_blk_process_async_branch(struct pt_block_decoder * decoder,const struct pt_event * ev)3132*74fe6c29SRuslan Bukin static int pt_blk_process_async_branch(struct pt_block_decoder *decoder,
3133*74fe6c29SRuslan Bukin 				       const struct pt_event *ev)
3134*74fe6c29SRuslan Bukin {
3135*74fe6c29SRuslan Bukin 	if (!decoder || !ev)
3136*74fe6c29SRuslan Bukin 		return -pte_internal;
3137*74fe6c29SRuslan Bukin 
3138*74fe6c29SRuslan Bukin 	/* This event can't be a status update. */
3139*74fe6c29SRuslan Bukin 	if (ev->status_update)
3140*74fe6c29SRuslan Bukin 		return -pte_bad_context;
3141*74fe6c29SRuslan Bukin 
3142*74fe6c29SRuslan Bukin 	/* We must currently be enabled. */
3143*74fe6c29SRuslan Bukin 	if (!decoder->enabled)
3144*74fe6c29SRuslan Bukin 		return -pte_bad_context;
3145*74fe6c29SRuslan Bukin 
3146*74fe6c29SRuslan Bukin 	/* Jump to the branch destination.  We will continue from there in the
3147*74fe6c29SRuslan Bukin 	 * next iteration.
3148*74fe6c29SRuslan Bukin 	 */
3149*74fe6c29SRuslan Bukin 	decoder->ip = ev->variant.async_branch.to;
3150*74fe6c29SRuslan Bukin 	decoder->process_event = 0;
3151*74fe6c29SRuslan Bukin 
3152*74fe6c29SRuslan Bukin 	return 0;
3153*74fe6c29SRuslan Bukin }
3154*74fe6c29SRuslan Bukin 
3155*74fe6c29SRuslan Bukin /* Process a paging event.
3156*74fe6c29SRuslan Bukin  *
3157*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
3158*74fe6c29SRuslan Bukin  */
pt_blk_process_paging(struct pt_block_decoder * decoder,const struct pt_event * ev)3159*74fe6c29SRuslan Bukin static int pt_blk_process_paging(struct pt_block_decoder *decoder,
3160*74fe6c29SRuslan Bukin 				 const struct pt_event *ev)
3161*74fe6c29SRuslan Bukin {
3162*74fe6c29SRuslan Bukin 	uint64_t cr3;
3163*74fe6c29SRuslan Bukin 	int errcode;
3164*74fe6c29SRuslan Bukin 
3165*74fe6c29SRuslan Bukin 	if (!decoder || !ev)
3166*74fe6c29SRuslan Bukin 		return -pte_internal;
3167*74fe6c29SRuslan Bukin 
3168*74fe6c29SRuslan Bukin 	cr3 = ev->variant.paging.cr3;
3169*74fe6c29SRuslan Bukin 	if (decoder->asid.cr3 != cr3) {
3170*74fe6c29SRuslan Bukin 		errcode = pt_msec_cache_invalidate(&decoder->scache);
3171*74fe6c29SRuslan Bukin 		if (errcode < 0)
3172*74fe6c29SRuslan Bukin 			return errcode;
3173*74fe6c29SRuslan Bukin 
3174*74fe6c29SRuslan Bukin 		decoder->asid.cr3 = cr3;
3175*74fe6c29SRuslan Bukin 	}
3176*74fe6c29SRuslan Bukin 
3177*74fe6c29SRuslan Bukin 	decoder->process_event = 0;
3178*74fe6c29SRuslan Bukin 
3179*74fe6c29SRuslan Bukin 	return 0;
3180*74fe6c29SRuslan Bukin }
3181*74fe6c29SRuslan Bukin 
3182*74fe6c29SRuslan Bukin /* Process a vmcs event.
3183*74fe6c29SRuslan Bukin  *
3184*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
3185*74fe6c29SRuslan Bukin  */
pt_blk_process_vmcs(struct pt_block_decoder * decoder,const struct pt_event * ev)3186*74fe6c29SRuslan Bukin static int pt_blk_process_vmcs(struct pt_block_decoder *decoder,
3187*74fe6c29SRuslan Bukin 			       const struct pt_event *ev)
3188*74fe6c29SRuslan Bukin {
3189*74fe6c29SRuslan Bukin 	uint64_t vmcs;
3190*74fe6c29SRuslan Bukin 	int errcode;
3191*74fe6c29SRuslan Bukin 
3192*74fe6c29SRuslan Bukin 	if (!decoder || !ev)
3193*74fe6c29SRuslan Bukin 		return -pte_internal;
3194*74fe6c29SRuslan Bukin 
3195*74fe6c29SRuslan Bukin 	vmcs = ev->variant.vmcs.base;
3196*74fe6c29SRuslan Bukin 	if (decoder->asid.vmcs != vmcs) {
3197*74fe6c29SRuslan Bukin 		errcode = pt_msec_cache_invalidate(&decoder->scache);
3198*74fe6c29SRuslan Bukin 		if (errcode < 0)
3199*74fe6c29SRuslan Bukin 			return errcode;
3200*74fe6c29SRuslan Bukin 
3201*74fe6c29SRuslan Bukin 		decoder->asid.vmcs = vmcs;
3202*74fe6c29SRuslan Bukin 	}
3203*74fe6c29SRuslan Bukin 
3204*74fe6c29SRuslan Bukin 	decoder->process_event = 0;
3205*74fe6c29SRuslan Bukin 
3206*74fe6c29SRuslan Bukin 	return 0;
3207*74fe6c29SRuslan Bukin }
3208*74fe6c29SRuslan Bukin 
3209*74fe6c29SRuslan Bukin /* Process an overflow event.
3210*74fe6c29SRuslan Bukin  *
3211*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
3212*74fe6c29SRuslan Bukin  */
pt_blk_process_overflow(struct pt_block_decoder * decoder,const struct pt_event * ev)3213*74fe6c29SRuslan Bukin static int pt_blk_process_overflow(struct pt_block_decoder *decoder,
3214*74fe6c29SRuslan Bukin 				   const struct pt_event *ev)
3215*74fe6c29SRuslan Bukin {
3216*74fe6c29SRuslan Bukin 	if (!decoder || !ev)
3217*74fe6c29SRuslan Bukin 		return -pte_internal;
3218*74fe6c29SRuslan Bukin 
3219*74fe6c29SRuslan Bukin 	/* This event can't be a status update. */
3220*74fe6c29SRuslan Bukin 	if (ev->status_update)
3221*74fe6c29SRuslan Bukin 		return -pte_bad_context;
3222*74fe6c29SRuslan Bukin 
3223*74fe6c29SRuslan Bukin 	/* If the IP is suppressed, the overflow resolved while tracing was
3224*74fe6c29SRuslan Bukin 	 * disabled.  Otherwise it resolved while tracing was enabled.
3225*74fe6c29SRuslan Bukin 	 */
3226*74fe6c29SRuslan Bukin 	if (ev->ip_suppressed) {
3227*74fe6c29SRuslan Bukin 		/* Tracing is disabled.  It doesn't make sense to preserve the
3228*74fe6c29SRuslan Bukin 		 * previous IP.  This will just be misleading.  Even if tracing
3229*74fe6c29SRuslan Bukin 		 * had been disabled before, as well, we might have missed the
3230*74fe6c29SRuslan Bukin 		 * re-enable in the overflow.
3231*74fe6c29SRuslan Bukin 		 */
3232*74fe6c29SRuslan Bukin 		decoder->enabled = 0;
3233*74fe6c29SRuslan Bukin 		decoder->ip = 0ull;
3234*74fe6c29SRuslan Bukin 	} else {
3235*74fe6c29SRuslan Bukin 		/* Tracing is enabled and we're at the IP at which the overflow
3236*74fe6c29SRuslan Bukin 		 * resolved.
3237*74fe6c29SRuslan Bukin 		 */
3238*74fe6c29SRuslan Bukin 		decoder->enabled = 1;
3239*74fe6c29SRuslan Bukin 		decoder->ip = ev->variant.overflow.ip;
3240*74fe6c29SRuslan Bukin 	}
3241*74fe6c29SRuslan Bukin 
3242*74fe6c29SRuslan Bukin 	/* We don't know the TSX state.  Let's assume we execute normally.
3243*74fe6c29SRuslan Bukin 	 *
3244*74fe6c29SRuslan Bukin 	 * We also don't know the execution mode.  Let's keep what we have
3245*74fe6c29SRuslan Bukin 	 * in case we don't get an update before we have to decode the next
3246*74fe6c29SRuslan Bukin 	 * instruction.
3247*74fe6c29SRuslan Bukin 	 */
3248*74fe6c29SRuslan Bukin 	decoder->speculative = 0;
3249*74fe6c29SRuslan Bukin 	decoder->process_event = 0;
3250*74fe6c29SRuslan Bukin 
3251*74fe6c29SRuslan Bukin 	return 0;
3252*74fe6c29SRuslan Bukin }
3253*74fe6c29SRuslan Bukin 
3254*74fe6c29SRuslan Bukin /* Process an exec mode event.
3255*74fe6c29SRuslan Bukin  *
3256*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
3257*74fe6c29SRuslan Bukin  */
pt_blk_process_exec_mode(struct pt_block_decoder * decoder,const struct pt_event * ev)3258*74fe6c29SRuslan Bukin static int pt_blk_process_exec_mode(struct pt_block_decoder *decoder,
3259*74fe6c29SRuslan Bukin 				    const struct pt_event *ev)
3260*74fe6c29SRuslan Bukin {
3261*74fe6c29SRuslan Bukin 	enum pt_exec_mode mode;
3262*74fe6c29SRuslan Bukin 
3263*74fe6c29SRuslan Bukin 	if (!decoder || !ev)
3264*74fe6c29SRuslan Bukin 		return -pte_internal;
3265*74fe6c29SRuslan Bukin 
3266*74fe6c29SRuslan Bukin 	/* Use status update events to diagnose inconsistencies. */
3267*74fe6c29SRuslan Bukin 	mode = ev->variant.exec_mode.mode;
3268*74fe6c29SRuslan Bukin 	if (ev->status_update && decoder->enabled &&
3269*74fe6c29SRuslan Bukin 	    decoder->mode != ptem_unknown && decoder->mode != mode)
3270*74fe6c29SRuslan Bukin 		return -pte_bad_status_update;
3271*74fe6c29SRuslan Bukin 
3272*74fe6c29SRuslan Bukin 	decoder->mode = mode;
3273*74fe6c29SRuslan Bukin 	decoder->process_event = 0;
3274*74fe6c29SRuslan Bukin 
3275*74fe6c29SRuslan Bukin 	return 0;
3276*74fe6c29SRuslan Bukin }
3277*74fe6c29SRuslan Bukin 
3278*74fe6c29SRuslan Bukin /* Process a tsx event.
3279*74fe6c29SRuslan Bukin  *
3280*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
3281*74fe6c29SRuslan Bukin  */
pt_blk_process_tsx(struct pt_block_decoder * decoder,const struct pt_event * ev)3282*74fe6c29SRuslan Bukin static int pt_blk_process_tsx(struct pt_block_decoder *decoder,
3283*74fe6c29SRuslan Bukin 			      const struct pt_event *ev)
3284*74fe6c29SRuslan Bukin {
3285*74fe6c29SRuslan Bukin 	if (!decoder || !ev)
3286*74fe6c29SRuslan Bukin 		return -pte_internal;
3287*74fe6c29SRuslan Bukin 
3288*74fe6c29SRuslan Bukin 	decoder->speculative = ev->variant.tsx.speculative;
3289*74fe6c29SRuslan Bukin 	decoder->process_event = 0;
3290*74fe6c29SRuslan Bukin 
3291*74fe6c29SRuslan Bukin 	return 0;
3292*74fe6c29SRuslan Bukin }
3293*74fe6c29SRuslan Bukin 
3294*74fe6c29SRuslan Bukin /* Process a stop event.
3295*74fe6c29SRuslan Bukin  *
3296*74fe6c29SRuslan Bukin  * Returns zero on success, a negative error code otherwise.
3297*74fe6c29SRuslan Bukin  */
pt_blk_process_stop(struct pt_block_decoder * decoder,const struct pt_event * ev)3298*74fe6c29SRuslan Bukin static int pt_blk_process_stop(struct pt_block_decoder *decoder,
3299*74fe6c29SRuslan Bukin 			       const struct pt_event *ev)
3300*74fe6c29SRuslan Bukin {
3301*74fe6c29SRuslan Bukin 	if (!decoder || !ev)
3302*74fe6c29SRuslan Bukin 		return -pte_internal;
3303*74fe6c29SRuslan Bukin 
3304*74fe6c29SRuslan Bukin 	/* This event can't be a status update. */
3305*74fe6c29SRuslan Bukin 	if (ev->status_update)
3306*74fe6c29SRuslan Bukin 		return -pte_bad_context;
3307*74fe6c29SRuslan Bukin 
3308*74fe6c29SRuslan Bukin 	/* Tracing is always disabled before it is stopped. */
3309*74fe6c29SRuslan Bukin 	if (decoder->enabled)
3310*74fe6c29SRuslan Bukin 		return -pte_bad_context;
3311*74fe6c29SRuslan Bukin 
3312*74fe6c29SRuslan Bukin 	decoder->process_event = 0;
3313*74fe6c29SRuslan Bukin 
3314*74fe6c29SRuslan Bukin 	return 0;
3315*74fe6c29SRuslan Bukin }
3316*74fe6c29SRuslan Bukin 
pt_blk_event(struct pt_block_decoder * decoder,struct pt_event * uevent,size_t size)3317*74fe6c29SRuslan Bukin int pt_blk_event(struct pt_block_decoder *decoder, struct pt_event *uevent,
3318*74fe6c29SRuslan Bukin 		 size_t size)
3319*74fe6c29SRuslan Bukin {
3320*74fe6c29SRuslan Bukin 	struct pt_event *ev;
3321*74fe6c29SRuslan Bukin 	int status;
3322*74fe6c29SRuslan Bukin 
3323*74fe6c29SRuslan Bukin 	if (!decoder || !uevent)
3324*74fe6c29SRuslan Bukin 		return -pte_invalid;
3325*74fe6c29SRuslan Bukin 
3326*74fe6c29SRuslan Bukin 	/* We must currently process an event. */
3327*74fe6c29SRuslan Bukin 	if (!decoder->process_event)
3328*74fe6c29SRuslan Bukin 		return -pte_bad_query;
3329*74fe6c29SRuslan Bukin 
3330*74fe6c29SRuslan Bukin 	ev = &decoder->event;
3331*74fe6c29SRuslan Bukin 	switch (ev->type) {
3332*74fe6c29SRuslan Bukin 	case ptev_enabled:
3333*74fe6c29SRuslan Bukin 		/* Indicate that tracing resumes from the IP at which tracing
3334*74fe6c29SRuslan Bukin 		 * had been disabled before (with some special treatment for
3335*74fe6c29SRuslan Bukin 		 * calls).
3336*74fe6c29SRuslan Bukin 		 */
3337*74fe6c29SRuslan Bukin 		if (ev->variant.enabled.ip == decoder->ip)
3338*74fe6c29SRuslan Bukin 			ev->variant.enabled.resumed = 1;
3339*74fe6c29SRuslan Bukin 
3340*74fe6c29SRuslan Bukin 		status = pt_blk_process_enabled(decoder, ev);
3341*74fe6c29SRuslan Bukin 		if (status < 0)
3342*74fe6c29SRuslan Bukin 			return status;
3343*74fe6c29SRuslan Bukin 
3344*74fe6c29SRuslan Bukin 		break;
3345*74fe6c29SRuslan Bukin 
3346*74fe6c29SRuslan Bukin 	case ptev_async_disabled:
3347*74fe6c29SRuslan Bukin 		if (decoder->ip != ev->variant.async_disabled.at)
3348*74fe6c29SRuslan Bukin 			return -pte_bad_query;
3349*74fe6c29SRuslan Bukin 
3350*74fe6c29SRuslan Bukin 		fallthrough;
3351*74fe6c29SRuslan Bukin 	case ptev_disabled:
3352*74fe6c29SRuslan Bukin 
3353*74fe6c29SRuslan Bukin 		status = pt_blk_process_disabled(decoder, ev);
3354*74fe6c29SRuslan Bukin 		if (status < 0)
3355*74fe6c29SRuslan Bukin 			return status;
3356*74fe6c29SRuslan Bukin 
3357*74fe6c29SRuslan Bukin 		break;
3358*74fe6c29SRuslan Bukin 
3359*74fe6c29SRuslan Bukin 	case ptev_async_branch:
3360*74fe6c29SRuslan Bukin 		if (decoder->ip != ev->variant.async_branch.from)
3361*74fe6c29SRuslan Bukin 			return -pte_bad_query;
3362*74fe6c29SRuslan Bukin 
3363*74fe6c29SRuslan Bukin 		status = pt_blk_process_async_branch(decoder, ev);
3364*74fe6c29SRuslan Bukin 		if (status < 0)
3365*74fe6c29SRuslan Bukin 			return status;
3366*74fe6c29SRuslan Bukin 
3367*74fe6c29SRuslan Bukin 		break;
3368*74fe6c29SRuslan Bukin 
3369*74fe6c29SRuslan Bukin 	case ptev_async_paging:
3370*74fe6c29SRuslan Bukin 		if (!ev->ip_suppressed &&
3371*74fe6c29SRuslan Bukin 		    decoder->ip != ev->variant.async_paging.ip)
3372*74fe6c29SRuslan Bukin 			return -pte_bad_query;
3373*74fe6c29SRuslan Bukin 
3374*74fe6c29SRuslan Bukin 		fallthrough;
3375*74fe6c29SRuslan Bukin 	case ptev_paging:
3376*74fe6c29SRuslan Bukin 		status = pt_blk_process_paging(decoder, ev);
3377*74fe6c29SRuslan Bukin 		if (status < 0)
3378*74fe6c29SRuslan Bukin 			return status;
3379*74fe6c29SRuslan Bukin 
3380*74fe6c29SRuslan Bukin 		break;
3381*74fe6c29SRuslan Bukin 
3382*74fe6c29SRuslan Bukin 	case ptev_async_vmcs:
3383*74fe6c29SRuslan Bukin 		if (!ev->ip_suppressed &&
3384*74fe6c29SRuslan Bukin 		    decoder->ip != ev->variant.async_vmcs.ip)
3385*74fe6c29SRuslan Bukin 			return -pte_bad_query;
3386*74fe6c29SRuslan Bukin 
3387*74fe6c29SRuslan Bukin 		fallthrough;
3388*74fe6c29SRuslan Bukin 	case ptev_vmcs:
3389*74fe6c29SRuslan Bukin 		status = pt_blk_process_vmcs(decoder, ev);
3390*74fe6c29SRuslan Bukin 		if (status < 0)
3391*74fe6c29SRuslan Bukin 			return status;
3392*74fe6c29SRuslan Bukin 
3393*74fe6c29SRuslan Bukin 		break;
3394*74fe6c29SRuslan Bukin 
3395*74fe6c29SRuslan Bukin 	case ptev_overflow:
3396*74fe6c29SRuslan Bukin 		status = pt_blk_process_overflow(decoder, ev);
3397*74fe6c29SRuslan Bukin 		if (status < 0)
3398*74fe6c29SRuslan Bukin 			return status;
3399*74fe6c29SRuslan Bukin 
3400*74fe6c29SRuslan Bukin 		break;
3401*74fe6c29SRuslan Bukin 
3402*74fe6c29SRuslan Bukin 	case ptev_exec_mode:
3403*74fe6c29SRuslan Bukin 		if (!ev->ip_suppressed &&
3404*74fe6c29SRuslan Bukin 		    decoder->ip != ev->variant.exec_mode.ip)
3405*74fe6c29SRuslan Bukin 			return -pte_bad_query;
3406*74fe6c29SRuslan Bukin 
3407*74fe6c29SRuslan Bukin 		status = pt_blk_process_exec_mode(decoder, ev);
3408*74fe6c29SRuslan Bukin 		if (status < 0)
3409*74fe6c29SRuslan Bukin 			return status;
3410*74fe6c29SRuslan Bukin 
3411*74fe6c29SRuslan Bukin 		break;
3412*74fe6c29SRuslan Bukin 
3413*74fe6c29SRuslan Bukin 	case ptev_tsx:
3414*74fe6c29SRuslan Bukin 		if (!ev->ip_suppressed && decoder->ip != ev->variant.tsx.ip)
3415*74fe6c29SRuslan Bukin 			return -pte_bad_query;
3416*74fe6c29SRuslan Bukin 
3417*74fe6c29SRuslan Bukin 		status = pt_blk_process_tsx(decoder, ev);
3418*74fe6c29SRuslan Bukin 		if (status < 0)
3419*74fe6c29SRuslan Bukin 			return status;
3420*74fe6c29SRuslan Bukin 
3421*74fe6c29SRuslan Bukin 		break;
3422*74fe6c29SRuslan Bukin 
3423*74fe6c29SRuslan Bukin 	case ptev_stop:
3424*74fe6c29SRuslan Bukin 		status = pt_blk_process_stop(decoder, ev);
3425*74fe6c29SRuslan Bukin 		if (status < 0)
3426*74fe6c29SRuslan Bukin 			return status;
3427*74fe6c29SRuslan Bukin 
3428*74fe6c29SRuslan Bukin 		break;
3429*74fe6c29SRuslan Bukin 
3430*74fe6c29SRuslan Bukin 	case ptev_exstop:
3431*74fe6c29SRuslan Bukin 		if (!ev->ip_suppressed && decoder->enabled &&
3432*74fe6c29SRuslan Bukin 		    decoder->ip != ev->variant.exstop.ip)
3433*74fe6c29SRuslan Bukin 			return -pte_bad_query;
3434*74fe6c29SRuslan Bukin 
3435*74fe6c29SRuslan Bukin 		decoder->process_event = 0;
3436*74fe6c29SRuslan Bukin 		break;
3437*74fe6c29SRuslan Bukin 
3438*74fe6c29SRuslan Bukin 	case ptev_mwait:
3439*74fe6c29SRuslan Bukin 		if (!ev->ip_suppressed && decoder->enabled &&
3440*74fe6c29SRuslan Bukin 		    decoder->ip != ev->variant.mwait.ip)
3441*74fe6c29SRuslan Bukin 			return -pte_bad_query;
3442*74fe6c29SRuslan Bukin 
3443*74fe6c29SRuslan Bukin 		decoder->process_event = 0;
3444*74fe6c29SRuslan Bukin 		break;
3445*74fe6c29SRuslan Bukin 
3446*74fe6c29SRuslan Bukin 	case ptev_pwre:
3447*74fe6c29SRuslan Bukin 	case ptev_pwrx:
3448*74fe6c29SRuslan Bukin 	case ptev_ptwrite:
3449*74fe6c29SRuslan Bukin 	case ptev_tick:
3450*74fe6c29SRuslan Bukin 	case ptev_cbr:
3451*74fe6c29SRuslan Bukin 	case ptev_mnt:
3452*74fe6c29SRuslan Bukin 		decoder->process_event = 0;
3453*74fe6c29SRuslan Bukin 		break;
3454*74fe6c29SRuslan Bukin 	}
3455*74fe6c29SRuslan Bukin 
3456*74fe6c29SRuslan Bukin 	/* Copy the event to the user.  Make sure we're not writing beyond the
3457*74fe6c29SRuslan Bukin 	 * memory provided by the user.
3458*74fe6c29SRuslan Bukin 	 *
3459*74fe6c29SRuslan Bukin 	 * We might truncate details of an event but only for those events the
3460*74fe6c29SRuslan Bukin 	 * user can't know about, anyway.
3461*74fe6c29SRuslan Bukin 	 */
3462*74fe6c29SRuslan Bukin 	if (sizeof(*ev) < size)
3463*74fe6c29SRuslan Bukin 		size = sizeof(*ev);
3464*74fe6c29SRuslan Bukin 
3465*74fe6c29SRuslan Bukin 	memcpy(uevent, ev, size);
3466*74fe6c29SRuslan Bukin 
3467*74fe6c29SRuslan Bukin 	/* Indicate further events. */
3468*74fe6c29SRuslan Bukin 	return pt_blk_proceed_trailing_event(decoder, NULL);
3469*74fe6c29SRuslan Bukin }
3470