xref: /freebsd/contrib/processor-trace/libipt/src/pt_time.c (revision 74ca7bf1d4c7173d5575ba168bc4b5f6d181ff5a)
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 
38 void pt_time_init(struct pt_time *time)
39 {
40 	if (!time)
41 		return;
42 
43 	memset(time, 0, sizeof(*time));
44 }
45 
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 
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  */
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  */
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 
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 
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 
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 
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  */
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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