1/*
2 * Copyright (c) 2014-2019, 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#ifndef PT_TIME_H
30#define PT_TIME_H
31
32#include <stdint.h>
33
34struct pt_config;
35struct pt_packet_tsc;
36struct pt_packet_cbr;
37struct pt_packet_tma;
38struct pt_packet_mtc;
39struct pt_packet_cyc;
40
41
42/* Intel(R) Processor Trace timing. */
43struct pt_time {
44	/* The estimated Time Stamp Count. */
45	uint64_t tsc;
46
47	/* The base Time Stamp Count (from TSC and MTC). */
48	uint64_t base;
49
50	/* The estimated Fast Counter. */
51	uint64_t fc;
52
53	/* The adjusted last CTC value (from MTC and TMA). */
54	uint32_t ctc;
55
56	/* The adjusted CTC value when @fc was cleared (from MTC and TMA). */
57	uint32_t ctc_cyc;
58
59	/* The number of lost MTC updates. */
60	uint32_t lost_mtc;
61
62	/* The number of lost CYC updates. */
63	uint32_t lost_cyc;
64
65	/* The core:bus ratio. */
66	uint8_t cbr;
67
68	/* A flag saying whether we have seen a TSC packet. */
69	uint32_t have_tsc:1;
70
71	/* A flag saying whether we have seen a CBR packet. */
72	uint32_t have_cbr:1;
73
74	/* A flag saying whether we have seen a TMA packet. */
75	uint32_t have_tma:1;
76
77	/* A flag saying whether we have seen a MTC packet. */
78	uint32_t have_mtc:1;
79};
80
81/* Initialize (or reset) the time. */
82extern void pt_time_init(struct pt_time *time);
83
84/* Query the current time.
85 *
86 * Provides the estimated Time Stamp Count value in @tsc.
87 *
88 * If @lost_mtc is not NULL, provides the number of lost MTC packets.
89 * If @lost_cyc is not NULL, provides the number of lost CYC packets.
90 *
91 * Returns zero on success; a negative error code, otherwise.
92 * Returns -pte_internal if @tsc or @time is NULL.
93 * Returns -pte_no_time if there has not been a TSC packet.
94 */
95extern int pt_time_query_tsc(uint64_t *tsc, uint32_t *lost_mtc,
96			     uint32_t *lost_cyc, const struct pt_time *time);
97
98/* Query the current core:bus ratio.
99 *
100 * Provides the core:bus ratio in @cbr.
101 *
102 * Returns zero on success; a negative error code, otherwise.
103 * Returns -pte_internal if @cbr or @time is NULL.
104 * Returns -pte_no_cbr if there has not been a CBR packet.
105 */
106extern int pt_time_query_cbr(uint32_t *cbr, const struct pt_time *time);
107
108/* Update the time based on an Intel PT packet.
109 *
110 * Returns zero on success.
111 * Returns a negative error code, otherwise.
112 */
113extern int pt_time_update_tsc(struct pt_time *, const struct pt_packet_tsc *,
114			      const struct pt_config *);
115extern int pt_time_update_cbr(struct pt_time *, const struct pt_packet_cbr *,
116			      const struct pt_config *);
117extern int pt_time_update_tma(struct pt_time *, const struct pt_packet_tma *,
118			      const struct pt_config *);
119extern int pt_time_update_mtc(struct pt_time *, const struct pt_packet_mtc *,
120			      const struct pt_config *);
121/* @fcr is the fast-counter:cycles ratio obtained by calibration. */
122extern int pt_time_update_cyc(struct pt_time *, const struct pt_packet_cyc *,
123			      const struct pt_config *, uint64_t fcr);
124
125
126/* Timing calibration.
127 *
128 * Used for estimating the Fast-Counter:Cycles ratio.
129 *
130 * Ideally, we calibrate by counting CYCs between MTCs.  Lacking MTCs, we
131 * use TSC, instead.
132 */
133struct pt_time_cal {
134	/* The estimated fast-counter:cycles ratio. */
135	uint64_t fcr;
136
137	/* The minimal and maximal @fcr values. */
138	uint64_t min_fcr, max_fcr;
139
140	/* The last TSC value.
141	 *
142	 * Used for calibrating at TSC.
143	 */
144	uint64_t tsc;
145
146	/* The number of cycles since the last TSC (from CYC).
147	 *
148	 * Used for calibrating at TSC.
149	 */
150	uint64_t cyc_tsc;
151
152	/* The number of cycles since the last MTC (from CYC).
153	 *
154	 * Used for calibrating at MTC.
155	 */
156	uint64_t cyc_mtc;
157
158	/* The adjusted last CTC value (from MTC).
159	 *
160	 * Used for calibrating at MTC.
161	 */
162	uint32_t ctc;
163
164	/* The number of lost MTC updates since the last successful update. */
165	uint32_t lost_mtc;
166
167	/* A flag saying whether we have seen a MTC packet. */
168	uint32_t have_mtc:1;
169
170	/* A flag saying whether we need to check for erratum SKL168. */
171	uint32_t check_skl168:1;
172};
173
174enum {
175	/* The amount by which the fcr value is right-shifted.
176	 *
177	 * Do not shift the value obtained by pt_tcal_fcr() when passing it to
178	 * pt_time_update_cyc().
179	 * Do shift the value passed to pt_tcal_set_fcr().
180	 */
181	pt_tcal_fcr_shr	= 8
182};
183
184/* Initialize of reset timing calibration. */
185extern void pt_tcal_init(struct pt_time_cal *tcal);
186
187/* Query the estimated fast-counter:cycles ratio.
188 *
189 * Provides the estimated ratio in @fcr unless -pte_internal or
190 * -pte_no_time is returned.
191 *
192 * Returns zero on success, a negative error code otherwise.
193 * Returns -pte_internal if @fcr or @tcal is NULL.
194 * Returns -pte_no_time if no information is available.
195 */
196extern int pt_tcal_fcr(uint64_t *fcr, const struct pt_time_cal *tcal);
197
198/* Set the fast-counter:cycles ratio.
199 *
200 * Timing calibration takes one CBR or two MTC packets before it can provide
201 * first estimations.  Use this to supply an initial value to be used in the
202 * meantime.
203 *
204 * Returns zero on success, a negative error code otherwise.
205 * Returns -pte_internal if @cal is NULL.
206 */
207extern int pt_tcal_set_fcr(struct pt_time_cal *tcal, uint64_t fcr);
208
209/* Update calibration based on an Intel PT packet.
210 *
211 * Returns zero on success, a negative error code otherwise.
212 */
213extern int pt_tcal_update_tsc(struct pt_time_cal *,
214			      const struct pt_packet_tsc *,
215			      const struct pt_config *);
216extern int pt_tcal_header_tsc(struct pt_time_cal *,
217			      const struct pt_packet_tsc *,
218			      const struct pt_config *);
219extern int pt_tcal_update_cbr(struct pt_time_cal *,
220			      const struct pt_packet_cbr *,
221			      const struct pt_config *);
222extern int pt_tcal_header_cbr(struct pt_time_cal *,
223			      const struct pt_packet_cbr *,
224			      const struct pt_config *);
225extern int pt_tcal_update_tma(struct pt_time_cal *,
226			      const struct pt_packet_tma *,
227			      const struct pt_config *);
228extern int pt_tcal_update_mtc(struct pt_time_cal *,
229			      const struct pt_packet_mtc *,
230			      const struct pt_config *);
231extern int pt_tcal_update_cyc(struct pt_time_cal *,
232			      const struct pt_packet_cyc *,
233			      const struct pt_config *);
234extern int pt_tcal_update_psb(struct pt_time_cal *,
235			      const struct pt_config *);
236extern int pt_tcal_update_ovf(struct pt_time_cal *,
237			      const struct pt_config *);
238
239#endif /* PT_TIME_H */
240