1 /*
2 * Copyright (c) 2014-2018, Intel Corporation
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * * Neither the name of Intel Corporation nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "pt_time.h"
30 #include "pt_opcodes.h"
31
32 #include "intel-pt.h"
33
34 #include <string.h>
35 #include <limits.h>
36
37
pt_time_init(struct pt_time * time)38 void pt_time_init(struct pt_time *time)
39 {
40 if (!time)
41 return;
42
43 memset(time, 0, sizeof(*time));
44 }
45
pt_time_query_tsc(uint64_t * tsc,uint32_t * lost_mtc,uint32_t * lost_cyc,const struct pt_time * time)46 int pt_time_query_tsc(uint64_t *tsc, uint32_t *lost_mtc,
47 uint32_t *lost_cyc, const struct pt_time *time)
48 {
49 if (!tsc || !time)
50 return -pte_internal;
51
52 *tsc = time->tsc;
53
54 if (lost_mtc)
55 *lost_mtc = time->lost_mtc;
56 if (lost_cyc)
57 *lost_cyc = time->lost_cyc;
58
59 if (!time->have_tsc)
60 return -pte_no_time;
61
62 return 0;
63 }
64
pt_time_query_cbr(uint32_t * cbr,const struct pt_time * time)65 int pt_time_query_cbr(uint32_t *cbr, const struct pt_time *time)
66 {
67 if (!cbr || !time)
68 return -pte_internal;
69
70 if (!time->have_cbr)
71 return -pte_no_cbr;
72
73 *cbr = time->cbr;
74
75 return 0;
76 }
77
78 /* Compute the distance between two CTC sources.
79 *
80 * We adjust a single wrap-around but fail if the distance is bigger than that.
81 *
82 * Returns zero on success, a negative error code otherwise.
83 */
pt_time_ctc_delta(uint32_t * ctc_delta,uint32_t ctc,uint32_t last_ctc,const struct pt_config * config)84 static int pt_time_ctc_delta(uint32_t *ctc_delta, uint32_t ctc,
85 uint32_t last_ctc, const struct pt_config *config)
86 {
87 if (!config || !ctc_delta)
88 return -pte_internal;
89
90 /* Correct a single wrap-around. If we lost enough MTCs to wrap
91 * around twice, timing will be wrong until the next TSC.
92 */
93 if (ctc < last_ctc) {
94 ctc += 1u << (config->mtc_freq + pt_pl_mtc_bit_size);
95
96 /* Since we only store the CTC between TMA/MTC or MTC/TMC a
97 * single correction should suffice.
98 */
99 if (ctc < last_ctc)
100 return -pte_bad_packet;
101 }
102
103 *ctc_delta = ctc - last_ctc;
104 return 0;
105 }
106
107 /* Translate CTC into the same unit as the FastCounter by multiplying with P.
108 *
109 * Returns zero on success, a negative error code otherwise.
110 */
pt_time_ctc_fc(uint64_t * fc,uint64_t ctc,const struct pt_config * config)111 static int pt_time_ctc_fc(uint64_t *fc, uint64_t ctc,
112 const struct pt_config *config)
113 {
114 uint32_t eax, ebx;
115
116 if (!fc || !config)
117 return -pte_internal;
118
119 eax = config->cpuid_0x15_eax;
120 ebx = config->cpuid_0x15_ebx;
121
122 /* Neither multiply nor divide by zero. */
123 if (!eax || !ebx)
124 return -pte_bad_config;
125
126 *fc = (ctc * ebx) / eax;
127 return 0;
128 }
129
pt_time_update_tsc(struct pt_time * time,const struct pt_packet_tsc * packet,const struct pt_config * config)130 int pt_time_update_tsc(struct pt_time *time,
131 const struct pt_packet_tsc *packet,
132 const struct pt_config *config)
133 {
134 (void) config;
135
136 if (!time || !packet)
137 return -pte_internal;
138
139 time->have_tsc = 1;
140 time->have_tma = 0;
141 time->have_mtc = 0;
142 time->tsc = time->base = packet->tsc;
143 time->ctc = 0;
144 time->fc = 0ull;
145
146 /* We got the full time; we recover from previous losses. */
147 time->lost_mtc = 0;
148 time->lost_cyc = 0;
149
150 return 0;
151 }
152
pt_time_update_cbr(struct pt_time * time,const struct pt_packet_cbr * packet,const struct pt_config * config)153 int pt_time_update_cbr(struct pt_time *time,
154 const struct pt_packet_cbr *packet,
155 const struct pt_config *config)
156 {
157 (void) config;
158
159 if (!time || !packet)
160 return -pte_internal;
161
162 time->have_cbr = 1;
163 time->cbr = packet->ratio;
164
165 return 0;
166 }
167
pt_time_update_tma(struct pt_time * time,const struct pt_packet_tma * packet,const struct pt_config * config)168 int pt_time_update_tma(struct pt_time *time,
169 const struct pt_packet_tma *packet,
170 const struct pt_config *config)
171 {
172 uint32_t ctc, mtc_freq, mtc_hi, ctc_mask;
173 uint64_t fc;
174
175 if (!time || !packet || !config)
176 return -pte_internal;
177
178 /* Without a TSC something is seriously wrong. */
179 if (!time->have_tsc)
180 return -pte_bad_context;
181
182 /* We shouldn't have more than one TMA per TSC. */
183 if (time->have_tma)
184 return -pte_bad_context;
185
186 /* We're ignoring MTC between TSC and TMA. */
187 if (time->have_mtc)
188 return -pte_internal;
189
190 ctc = packet->ctc;
191 fc = packet->fc;
192
193 mtc_freq = config->mtc_freq;
194 mtc_hi = mtc_freq + pt_pl_mtc_bit_size;
195
196 /* A mask for the relevant CTC bits ignoring high-order bits that are
197 * not provided by MTC.
198 */
199 ctc_mask = (1u << mtc_hi) - 1u;
200
201 time->have_tma = 1;
202 time->base -= fc;
203 time->fc += fc;
204
205 /* If the MTC frequency is low enough that TMA provides the full CTC
206 * value, we can use the TMA as an MTC.
207 *
208 * If it isn't, we will estimate the preceding MTC based on the CTC bits
209 * the TMA provides at the next MTC. We forget about the previous MTC
210 * in this case.
211 *
212 * If no MTC packets are dropped around TMA, we will estimate the
213 * forgotten value again at the next MTC.
214 *
215 * If MTC packets are dropped, we can't really tell where in this
216 * extended MTC period the TSC occurred. The estimation will place it
217 * right before the next MTC.
218 */
219 if (mtc_hi <= pt_pl_tma_ctc_bit_size)
220 time->have_mtc = 1;
221
222 /* In both cases, we store the TMA's CTC bits until the next MTC. */
223 time->ctc = time->ctc_cyc = ctc & ctc_mask;
224
225 return 0;
226 }
227
pt_time_update_mtc(struct pt_time * time,const struct pt_packet_mtc * packet,const struct pt_config * config)228 int pt_time_update_mtc(struct pt_time *time,
229 const struct pt_packet_mtc *packet,
230 const struct pt_config *config)
231 {
232 uint32_t last_ctc, ctc, ctc_delta;
233 uint64_t tsc, base;
234 uint8_t mtc_freq;
235 int errcode, have_tsc, have_tma, have_mtc;
236
237 if (!time || !packet || !config)
238 return -pte_internal;
239
240 have_tsc = time->have_tsc;
241 have_tma = time->have_tma;
242 have_mtc = time->have_mtc;
243
244 /* We ignore MTCs between TSC and TMA to avoid apparent CTC overflows.
245 *
246 * Later MTCs will ensure that no time is lost - provided TMA provides
247 * enough bits. If TMA doesn't provide any of the MTC bits we may place
248 * the TSC into the wrong MTC period.
249 */
250 if (have_tsc && !have_tma)
251 return 0;
252
253 base = time->base;
254 last_ctc = time->ctc;
255 mtc_freq = config->mtc_freq;
256
257 ctc = packet->ctc << mtc_freq;
258
259 /* Store our CTC value if we have or would have reset FC. */
260 if (time->fc || time->lost_cyc || !have_mtc)
261 time->ctc_cyc = ctc;
262
263 /* Prepare for the next packet in case we error out below. */
264 time->have_mtc = 1;
265 time->fc = 0ull;
266 time->ctc = ctc;
267
268 /* We recover from previous CYC losses. */
269 time->lost_cyc = 0;
270
271 /* Avoid a big jump when we see the first MTC with an arbitrary CTC
272 * payload.
273 */
274 if (!have_mtc) {
275 uint32_t ctc_lo, ctc_hi;
276
277 /* If we have not seen a TMA, we ignore this first MTC.
278 *
279 * We have no idea where in this MTC period tracing started.
280 * We could lose an entire MTC period or just a tiny fraction.
281 *
282 * On the other hand, if we assumed a previous MTC value, we
283 * might make just the same error.
284 */
285 if (!have_tma)
286 return 0;
287
288 /* The TMA's CTC value didn't provide enough bits - otherwise,
289 * we would have treated the TMA as an MTC.
290 */
291 if (last_ctc & ~pt_pl_tma_ctc_mask)
292 return -pte_internal;
293
294 /* Split this MTC's CTC value into low and high parts with
295 * respect to the bits provided by TMA.
296 */
297 ctc_lo = ctc & pt_pl_tma_ctc_mask;
298 ctc_hi = ctc & ~pt_pl_tma_ctc_mask;
299
300 /* We estimate the high-order CTC bits that are not provided by
301 * TMA based on the CTC bits provided by this MTC.
302 *
303 * We assume that no MTC packets were dropped around TMA. If
304 * there are, we might place the TSC into the wrong MTC period
305 * depending on how many CTC bits TMA provides and how many MTC
306 * packets were dropped.
307 *
308 * Note that we may underflow which results in more bits to be
309 * set than MTC packets may provide. Drop those extra bits.
310 */
311 if (ctc_lo < last_ctc) {
312 ctc_hi -= 1u << pt_pl_tma_ctc_bit_size;
313 ctc_hi &= pt_pl_mtc_mask << mtc_freq;
314 }
315
316 last_ctc |= ctc_hi;
317 }
318
319 errcode = pt_time_ctc_delta(&ctc_delta, ctc, last_ctc, config);
320 if (errcode < 0) {
321 time->lost_mtc += 1;
322 return errcode;
323 }
324
325 errcode = pt_time_ctc_fc(&tsc, ctc_delta, config);
326 if (errcode < 0)
327 return errcode;
328
329 base += tsc;
330 time->tsc = time->base = base;
331
332 return 0;
333 }
334
335 /* Adjust a CYC packet's payload spanning multiple MTC periods.
336 *
337 * CYC packets measure the Fast Counter since the last CYC(-eligible) packet.
338 * Depending on the CYC threshold, we may not get a CYC for each MTC, so a CYC
339 * period may overlap with or even span multiple MTC periods.
340 *
341 * We can't do much about the overlap case without examining all packets in
342 * the respective periods. We leave this as expected imprecision.
343 *
344 * If we find a CYC packet to span multiple MTC packets, though, we try to
345 * approximate the portion for the current MTC period by subtracting the
346 * estimated portion for previous MTC periods using calibration information.
347 *
348 * We only consider MTC. For the first CYC after TSC, the corresponding TMA
349 * will contain the Fast Counter at TSC.
350 *
351 * Returns zero on success, a negative error code otherwise.
352 */
pt_time_adjust_cyc(uint64_t * cyc,const struct pt_time * time,const struct pt_config * config,uint64_t fcr)353 static int pt_time_adjust_cyc(uint64_t *cyc, const struct pt_time *time,
354 const struct pt_config *config, uint64_t fcr)
355 {
356 uint32_t last_ctc, ctc, ctc_delta;
357 uint64_t fc, total_cyc, old_cyc;
358 int errcode;
359
360 if (!time || !config || !fcr)
361 return -pte_internal;
362
363 last_ctc = time->ctc_cyc;
364 ctc = time->ctc;
365
366 /* There is nothing to do if this is the current MTC period. */
367 if (ctc == last_ctc)
368 return 0;
369
370 /* Calibration computes
371 *
372 * fc = (ctc_delta * cpuid[0x15].ebx) / cpuid[0x15].eax.
373 * fcr = (fc << pt_tcal_fcr_shr) / cyc
374 *
375 * So cyc = (fc << pt_tcal_fcr_shr) / fcr.
376 */
377
378 errcode = pt_time_ctc_delta(&ctc_delta, ctc, last_ctc, config);
379 if (errcode < 0)
380 return errcode;
381
382 errcode = pt_time_ctc_fc(&fc, ctc_delta, config);
383 if (errcode < 0)
384 return errcode;
385
386 old_cyc = (fc << pt_tcal_fcr_shr) / fcr;
387 total_cyc = *cyc;
388
389 /* Make sure we don't wrap around. If we would, attribute the entire
390 * CYC payload to any previous MTC period.
391 *
392 * We lost an unknown portion of the CYC payload for the current MTC
393 * period, but it's usually better to run too slow than too fast.
394 */
395 if (total_cyc < old_cyc)
396 total_cyc = old_cyc;
397
398 *cyc = total_cyc - old_cyc;
399 return 0;
400 }
401
pt_time_update_cyc(struct pt_time * time,const struct pt_packet_cyc * packet,const struct pt_config * config,uint64_t fcr)402 int pt_time_update_cyc(struct pt_time *time,
403 const struct pt_packet_cyc *packet,
404 const struct pt_config *config, uint64_t fcr)
405 {
406 uint64_t cyc, fc;
407
408 if (!time || !packet || !config)
409 return -pte_internal;
410
411 if (!fcr) {
412 time->lost_cyc += 1;
413 return 0;
414 }
415
416 cyc = packet->value;
417 fc = time->fc;
418 if (!fc) {
419 int errcode;
420
421 errcode = pt_time_adjust_cyc(&cyc, time, config, fcr);
422 if (errcode < 0)
423 return errcode;
424 }
425
426 fc += (cyc * fcr) >> pt_tcal_fcr_shr;
427
428 time->fc = fc;
429 time->tsc = time->base + fc;
430
431 return 0;
432 }
433
pt_tcal_init(struct pt_time_cal * tcal)434 void pt_tcal_init(struct pt_time_cal *tcal)
435 {
436 if (!tcal)
437 return;
438
439 memset(tcal, 0, sizeof(*tcal));
440
441 tcal->min_fcr = UINT64_MAX;
442 }
443
pt_tcal_have_fcr(const struct pt_time_cal * tcal)444 static int pt_tcal_have_fcr(const struct pt_time_cal *tcal)
445 {
446 if (!tcal)
447 return 0;
448
449 return (tcal->min_fcr <= tcal->max_fcr);
450 }
451
pt_tcal_fcr(uint64_t * fcr,const struct pt_time_cal * tcal)452 int pt_tcal_fcr(uint64_t *fcr, const struct pt_time_cal *tcal)
453 {
454 if (!fcr || !tcal)
455 return -pte_internal;
456
457 if (!pt_tcal_have_fcr(tcal))
458 return -pte_no_time;
459
460 *fcr = tcal->fcr;
461
462 return 0;
463 }
464
pt_tcal_set_fcr(struct pt_time_cal * tcal,uint64_t fcr)465 int pt_tcal_set_fcr(struct pt_time_cal *tcal, uint64_t fcr)
466 {
467 if (!tcal)
468 return -pte_internal;
469
470 tcal->fcr = fcr;
471
472 if (fcr < tcal->min_fcr)
473 tcal->min_fcr = fcr;
474
475 if (fcr > tcal->max_fcr)
476 tcal->max_fcr = fcr;
477
478 return 0;
479 }
480
pt_tcal_update_tsc(struct pt_time_cal * tcal,const struct pt_packet_tsc * packet,const struct pt_config * config)481 int pt_tcal_update_tsc(struct pt_time_cal *tcal,
482 const struct pt_packet_tsc *packet,
483 const struct pt_config *config)
484 {
485 (void) config;
486
487 if (!tcal || !packet)
488 return -pte_internal;
489
490 /* A TSC outside of PSB+ may indicate loss of time. We do not use it
491 * for calibration. We store the TSC value for calibration at the next
492 * TSC in PSB+, though.
493 */
494 tcal->tsc = packet->tsc;
495 tcal->cyc_tsc = 0ull;
496
497 return 0;
498 }
499
pt_tcal_header_tsc(struct pt_time_cal * tcal,const struct pt_packet_tsc * packet,const struct pt_config * config)500 int pt_tcal_header_tsc(struct pt_time_cal *tcal,
501 const struct pt_packet_tsc *packet,
502 const struct pt_config *config)
503 {
504 uint64_t tsc, last_tsc, tsc_delta, cyc, fcr;
505
506 (void) config;
507
508 if (!tcal || !packet)
509 return -pte_internal;
510
511 last_tsc = tcal->tsc;
512 cyc = tcal->cyc_tsc;
513
514 tsc = packet->tsc;
515
516 tcal->tsc = tsc;
517 tcal->cyc_tsc = 0ull;
518
519 if (!last_tsc || !cyc)
520 return 0;
521
522 /* Correct a single wrap-around. */
523 if (tsc < last_tsc) {
524 tsc += 1ull << pt_pl_tsc_bit_size;
525
526 if (tsc < last_tsc)
527 return -pte_bad_packet;
528 }
529
530 tsc_delta = tsc - last_tsc;
531
532 /* We shift the nominator to improve rounding precision.
533 *
534 * Since we're only collecting the CYCs between two TSC, we shouldn't
535 * overflow. Let's rather fail than overflow.
536 */
537 if (tsc_delta & ~(~0ull >> pt_tcal_fcr_shr))
538 return -pte_internal;
539
540 fcr = (tsc_delta << pt_tcal_fcr_shr) / cyc;
541
542 return pt_tcal_set_fcr(tcal, fcr);
543 }
544
pt_tcal_update_cbr(struct pt_time_cal * tcal,const struct pt_packet_cbr * packet,const struct pt_config * config)545 int pt_tcal_update_cbr(struct pt_time_cal *tcal,
546 const struct pt_packet_cbr *packet,
547 const struct pt_config *config)
548 {
549 /* A CBR outside of PSB+ indicates a frequency change. Reset our
550 * calibration state.
551 */
552 pt_tcal_init(tcal);
553
554 return pt_tcal_header_cbr(tcal, packet, config);
555 }
556
pt_tcal_header_cbr(struct pt_time_cal * tcal,const struct pt_packet_cbr * packet,const struct pt_config * config)557 int pt_tcal_header_cbr(struct pt_time_cal *tcal,
558 const struct pt_packet_cbr *packet,
559 const struct pt_config *config)
560 {
561 uint64_t cbr, p1, fcr;
562
563 if (!tcal || !packet || !config)
564 return -pte_internal;
565
566 p1 = config->nom_freq;
567 if (!p1)
568 return 0;
569
570 /* If we know the nominal frequency, we can use it for calibration. */
571 cbr = packet->ratio;
572
573 fcr = (p1 << pt_tcal_fcr_shr) / cbr;
574
575 return pt_tcal_set_fcr(tcal, fcr);
576 }
577
pt_tcal_update_tma(struct pt_time_cal * tcal,const struct pt_packet_tma * packet,const struct pt_config * config)578 int pt_tcal_update_tma(struct pt_time_cal *tcal,
579 const struct pt_packet_tma *packet,
580 const struct pt_config *config)
581 {
582 (void) tcal;
583 (void) packet;
584 (void) config;
585
586 /* Nothing to do. */
587 return 0;
588 }
589
pt_tcal_update_mtc(struct pt_time_cal * tcal,const struct pt_packet_mtc * packet,const struct pt_config * config)590 int pt_tcal_update_mtc(struct pt_time_cal *tcal,
591 const struct pt_packet_mtc *packet,
592 const struct pt_config *config)
593 {
594 uint32_t last_ctc, ctc, ctc_delta, have_mtc;
595 uint64_t cyc, fc, fcr;
596 int errcode;
597
598 if (!tcal || !packet || !config)
599 return -pte_internal;
600
601 last_ctc = tcal->ctc;
602 have_mtc = tcal->have_mtc;
603 cyc = tcal->cyc_mtc;
604
605 ctc = packet->ctc << config->mtc_freq;
606
607 /* We need at least two MTC (including this). */
608 if (!have_mtc) {
609 tcal->cyc_mtc = 0ull;
610 tcal->ctc = ctc;
611 tcal->have_mtc = 1;
612
613 return 0;
614 }
615
616 /* Without any cycles, we can't calibrate. Try again at the next
617 * MTC and distribute the cycles over the combined MTC period.
618 */
619 if (!cyc)
620 return 0;
621
622 /* Prepare for the next packet in case we error out below. */
623 tcal->have_mtc = 1;
624 tcal->cyc_mtc = 0ull;
625 tcal->ctc = ctc;
626
627 /* Let's pretend we will fail. We'll correct it at the end. */
628 tcal->lost_mtc += 1;
629
630 errcode = pt_time_ctc_delta(&ctc_delta, ctc, last_ctc, config);
631 if (errcode < 0)
632 return errcode;
633
634 errcode = pt_time_ctc_fc(&fc, ctc_delta, config);
635 if (errcode < 0)
636 return errcode;
637
638 /* We shift the nominator to improve rounding precision.
639 *
640 * Since we're only collecting the CYCs between two MTC, we shouldn't
641 * overflow. Let's rather fail than overflow.
642 */
643 if (fc & ~(~0ull >> pt_tcal_fcr_shr))
644 return -pte_internal;
645
646 fcr = (fc << pt_tcal_fcr_shr) / cyc;
647
648 errcode = pt_tcal_set_fcr(tcal, fcr);
649 if (errcode < 0)
650 return errcode;
651
652 /* We updated the FCR. This recovers from previous MTC losses. */
653 tcal->lost_mtc = 0;
654
655 return 0;
656 }
657
pt_tcal_update_cyc(struct pt_time_cal * tcal,const struct pt_packet_cyc * packet,const struct pt_config * config)658 int pt_tcal_update_cyc(struct pt_time_cal *tcal,
659 const struct pt_packet_cyc *packet,
660 const struct pt_config *config)
661 {
662 uint64_t cyc;
663
664 (void) config;
665
666 if (!tcal || !packet)
667 return -pte_internal;
668
669 cyc = packet->value;
670 tcal->cyc_mtc += cyc;
671 tcal->cyc_tsc += cyc;
672
673 return 0;
674 }
675