@@ -177,6 +177,7 @@ static void pt_blk_reset(struct pt_block_decoder *decoder)
177
177
decoder -> process_event = 0 ;
178
178
decoder -> speculative = 0 ;
179
179
180
+ memset (& decoder -> event , 0 , sizeof (decoder -> event ));
180
181
pt_retstack_init (& decoder -> retstack );
181
182
pt_asid_init (& decoder -> asid );
182
183
}
@@ -269,6 +270,126 @@ void pt_blk_free_decoder(struct pt_block_decoder *decoder)
269
270
free (decoder );
270
271
}
271
272
273
+ /* Maybe synthesize a tick event.
274
+ *
275
+ * If we're not already processing events, check the current time against the
276
+ * last event's time. If it changed, synthesize a tick event with the new time.
277
+ *
278
+ * Returns zero if no tick event has been created.
279
+ * Returns a positive integer if a tick event has been created.
280
+ * Returns a negative error code otherwise.
281
+ */
282
+ static int pt_blk_tick (struct pt_block_decoder * decoder , uint64_t ip )
283
+ {
284
+ struct pt_event * ev ;
285
+ uint64_t tsc ;
286
+ uint32_t lost_mtc , lost_cyc ;
287
+ int errcode ;
288
+
289
+ if (!decoder )
290
+ return - pte_internal ;
291
+
292
+ /* We're not generating tick events if tracing is disabled. */
293
+ if (!decoder -> enabled )
294
+ return - pte_internal ;
295
+
296
+ /* Events already provide a timestamp so there is no need to synthesize
297
+ * an artificial tick event. There's no room, either, since this would
298
+ * overwrite the in-progress event.
299
+ *
300
+ * In rare cases where we need to proceed to an event location using
301
+ * trace this may cause us to miss a timing update if the event is not
302
+ * forwarded to the user.
303
+ *
304
+ * The only case I can come up with at the moment is a MODE.EXEC binding
305
+ * to the TIP IP of a far branch.
306
+ */
307
+ if (decoder -> process_event )
308
+ return 0 ;
309
+
310
+ errcode = pt_qry_time (& decoder -> query , & tsc , & lost_mtc , & lost_cyc );
311
+ if (errcode < 0 ) {
312
+ /* If we don't have wall-clock time, we use relative time. */
313
+ if (errcode != - pte_no_time )
314
+ return errcode ;
315
+ }
316
+
317
+ ev = & decoder -> event ;
318
+
319
+ /* We're done if time has not changed since the last event. */
320
+ if (tsc == ev -> tsc )
321
+ return 0 ;
322
+
323
+ /* Time has changed so we create a new tick event. */
324
+ memset (ev , 0 , sizeof (* ev ));
325
+ ev -> type = ptev_tick ;
326
+ ev -> variant .tick .ip = ip ;
327
+
328
+ /* Indicate if we have wall-clock time or only relative time. */
329
+ if (errcode != - pte_no_time )
330
+ ev -> has_tsc = 1 ;
331
+ ev -> tsc = tsc ;
332
+ ev -> lost_mtc = lost_mtc ;
333
+ ev -> lost_cyc = lost_cyc ;
334
+
335
+ /* We now have an event to process. */
336
+ decoder -> process_event = 1 ;
337
+
338
+ return 1 ;
339
+ }
340
+
341
+ /* Query an indirect branch.
342
+ *
343
+ * Returns zero on success, a negative error code otherwise.
344
+ */
345
+ static int pt_blk_indirect_branch (struct pt_block_decoder * decoder ,
346
+ uint64_t * ip )
347
+ {
348
+ uint64_t evip ;
349
+ int status , errcode ;
350
+
351
+ if (!decoder )
352
+ return - pte_internal ;
353
+
354
+ evip = decoder -> ip ;
355
+
356
+ status = pt_qry_indirect_branch (& decoder -> query , ip );
357
+ if (status < 0 )
358
+ return status ;
359
+
360
+ if (decoder -> flags .variant .block .enable_tick_events ) {
361
+ errcode = pt_blk_tick (decoder , evip );
362
+ if (errcode < 0 )
363
+ return errcode ;
364
+ }
365
+
366
+ return status ;
367
+ }
368
+
369
+ /* Query a conditional branch.
370
+ *
371
+ * Returns zero on success, a negative error code otherwise.
372
+ */
373
+ static int pt_blk_cond_branch (struct pt_block_decoder * decoder , int * taken )
374
+ {
375
+ int status , errcode ;
376
+
377
+ if (!decoder )
378
+ return - pte_internal ;
379
+
380
+ status = pt_qry_cond_branch (& decoder -> query , taken );
381
+ if (status < 0 )
382
+ return status ;
383
+
384
+ if (decoder -> flags .variant .block .enable_tick_events ) {
385
+ errcode = pt_blk_tick (decoder , decoder -> ip );
386
+ if (errcode < 0 )
387
+ return errcode ;
388
+ }
389
+
390
+ return status ;
391
+ }
392
+
272
393
static int pt_blk_start (struct pt_block_decoder * decoder , int status )
273
394
{
274
395
if (!decoder )
@@ -281,6 +402,14 @@ static int pt_blk_start(struct pt_block_decoder *decoder, int status)
281
402
if (!(status & pts_ip_suppressed ))
282
403
decoder -> enabled = 1 ;
283
404
405
+ /* We will always have an event.
406
+ *
407
+ * If we synchronized onto an empty PSB+, tracing is disabled and we'll
408
+ * process events until the enabled event.
409
+ *
410
+ * If tracing is enabled, PSB+ must at least provide the execution mode,
411
+ * which we're going to forward to the user.
412
+ */
284
413
return pt_blk_proceed_trailing_event (decoder , NULL );
285
414
}
286
415
@@ -506,7 +635,7 @@ static int pt_blk_next_ip(uint64_t *pip, struct pt_block_decoder *decoder,
506
635
const struct pt_insn * insn ,
507
636
const struct pt_insn_ext * iext )
508
637
{
509
- int status ;
638
+ int status , errcode ;
510
639
511
640
if (!pip || !decoder || !insn || !iext )
512
641
return - pte_internal ;
@@ -521,7 +650,7 @@ static int pt_blk_next_ip(uint64_t *pip, struct pt_block_decoder *decoder,
521
650
uint64_t ip ;
522
651
int taken ;
523
652
524
- status = pt_qry_cond_branch ( & decoder -> query , & taken );
653
+ status = pt_blk_cond_branch ( decoder , & taken );
525
654
if (status < 0 )
526
655
return status ;
527
656
@@ -534,10 +663,10 @@ static int pt_blk_next_ip(uint64_t *pip, struct pt_block_decoder *decoder,
534
663
}
535
664
536
665
case ptic_return : {
537
- int taken , errcode ;
666
+ int taken ;
538
667
539
668
/* Check for a compressed return. */
540
- status = pt_qry_cond_branch ( & decoder -> query , & taken );
669
+ status = pt_blk_cond_branch ( decoder , & taken );
541
670
if (status < 0 ) {
542
671
if (status != - pte_bad_query )
543
672
return status ;
@@ -584,7 +713,7 @@ static int pt_blk_next_ip(uint64_t *pip, struct pt_block_decoder *decoder,
584
713
* This covers indirect jumps and calls, non-compressed returns, and all
585
714
* flavors of far transfers.
586
715
*/
587
- return pt_qry_indirect_branch ( & decoder -> query , pip );
716
+ return pt_blk_indirect_branch ( decoder , pip );
588
717
}
589
718
590
719
/* Proceed to the next IP using trace.
@@ -1929,7 +2058,7 @@ static int pt_blk_proceed_no_event_cached(struct pt_block_decoder *decoder,
1929
2058
* We can't use the normal decode and proceed-with-trace
1930
2059
* flow since we already consumed the TNT bit.
1931
2060
*/
1932
- status = pt_qry_cond_branch ( & decoder -> query , & taken );
2061
+ status = pt_blk_cond_branch ( decoder , & taken );
1933
2062
if (status < 0 )
1934
2063
return status ;
1935
2064
@@ -2072,7 +2201,7 @@ static int pt_blk_proceed_no_event_cached(struct pt_block_decoder *decoder,
2072
2201
if (status < 0 )
2073
2202
return status ;
2074
2203
2075
- status = pt_qry_indirect_branch ( & decoder -> query , & decoder -> ip );
2204
+ status = pt_blk_indirect_branch ( decoder , & decoder -> ip );
2076
2205
if (status < 0 )
2077
2206
return status ;
2078
2207
@@ -2090,16 +2219,15 @@ static int pt_blk_proceed_no_event_cached(struct pt_block_decoder *decoder,
2090
2219
block -> iclass = ptic_return ;
2091
2220
2092
2221
/* Check for a compressed return. */
2093
- status = pt_qry_cond_branch ( & decoder -> query , & taken );
2222
+ status = pt_blk_cond_branch ( decoder , & taken );
2094
2223
if (status < 0 ) {
2095
2224
if (status != - pte_bad_query )
2096
2225
return status ;
2097
2226
2098
2227
/* The return is not compressed. We need another query
2099
2228
* to determine the destination IP.
2100
2229
*/
2101
- status = pt_qry_indirect_branch (& decoder -> query ,
2102
- & decoder -> ip );
2230
+ status = pt_blk_indirect_branch (decoder , & decoder -> ip );
2103
2231
if (status < 0 )
2104
2232
return status ;
2105
2233
@@ -2140,7 +2268,7 @@ static int pt_blk_proceed_no_event_cached(struct pt_block_decoder *decoder,
2140
2268
*
2141
2269
* Just query the destination IP.
2142
2270
*/
2143
- status = pt_qry_indirect_branch ( & decoder -> query , & decoder -> ip );
2271
+ status = pt_blk_indirect_branch ( decoder , & decoder -> ip );
2144
2272
if (status < 0 )
2145
2273
return status ;
2146
2274
0 commit comments