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 #include "pt_time.h"
30
31 #include "intel-pt.h"
32
33 #include "ptunit.h"
34
35
36 /* A time unit test fixture. */
37
38 struct time_fixture {
39 /* The configuration to use. */
40 struct pt_config config;
41
42 /* The calibration to use. */
43 struct pt_time_cal tcal;
44
45 /* The time struct to update. */
46 struct pt_time time;
47
48 /* The test fixture initialization and finalization functions. */
49 struct ptunit_result (*init)(struct time_fixture *);
50 struct ptunit_result (*fini)(struct time_fixture *);
51 };
52
tfix_init(struct time_fixture * tfix)53 static struct ptunit_result tfix_init(struct time_fixture *tfix)
54 {
55 memset(&tfix->config, 0, sizeof(tfix->config));
56 tfix->config.size = sizeof(tfix->config);
57 tfix->config.cpuid_0x15_eax = 2;
58 tfix->config.cpuid_0x15_ebx = 1;
59 tfix->config.mtc_freq = 4;
60
61 pt_tcal_init(&tfix->tcal);
62 pt_tcal_set_fcr(&tfix->tcal, 0x2ull << pt_tcal_fcr_shr);
63
64 pt_time_init(&tfix->time);
65
66 return ptu_passed();
67 }
68
69
tsc_null(struct time_fixture * tfix)70 static struct ptunit_result tsc_null(struct time_fixture *tfix)
71 {
72 struct pt_packet_tsc packet;
73 int errcode;
74
75 errcode = pt_time_update_tsc(NULL, &packet, &tfix->config);
76 ptu_int_eq(errcode, -pte_internal);
77
78 errcode = pt_time_update_tsc(&tfix->time, NULL, &tfix->config);
79 ptu_int_eq(errcode, -pte_internal);
80
81 return ptu_passed();
82 }
83
cbr_null(struct time_fixture * tfix)84 static struct ptunit_result cbr_null(struct time_fixture *tfix)
85 {
86 struct pt_packet_cbr packet;
87 int errcode;
88
89 errcode = pt_time_update_cbr(NULL, &packet, &tfix->config);
90 ptu_int_eq(errcode, -pte_internal);
91
92 errcode = pt_time_update_cbr(&tfix->time, NULL, &tfix->config);
93 ptu_int_eq(errcode, -pte_internal);
94
95 return ptu_passed();
96 }
97
tma_null(struct time_fixture * tfix)98 static struct ptunit_result tma_null(struct time_fixture *tfix)
99 {
100 struct pt_packet_tma packet;
101 int errcode;
102
103 errcode = pt_time_update_tma(NULL, &packet, &tfix->config);
104 ptu_int_eq(errcode, -pte_internal);
105
106 errcode = pt_time_update_tma(&tfix->time, NULL, &tfix->config);
107 ptu_int_eq(errcode, -pte_internal);
108
109 errcode = pt_time_update_tma(&tfix->time, &packet, NULL);
110 ptu_int_eq(errcode, -pte_internal);
111
112 return ptu_passed();
113 }
114
mtc_null(struct time_fixture * tfix)115 static struct ptunit_result mtc_null(struct time_fixture *tfix)
116 {
117 struct pt_packet_mtc packet;
118 int errcode;
119
120 errcode = pt_time_update_mtc(NULL, &packet, &tfix->config);
121 ptu_int_eq(errcode, -pte_internal);
122
123 errcode = pt_time_update_mtc(&tfix->time, NULL, &tfix->config);
124 ptu_int_eq(errcode, -pte_internal);
125
126 errcode = pt_time_update_mtc(&tfix->time, &packet, NULL);
127 ptu_int_eq(errcode, -pte_internal);
128
129 return ptu_passed();
130 }
131
cyc_null(struct time_fixture * tfix)132 static struct ptunit_result cyc_null(struct time_fixture *tfix)
133 {
134 struct pt_packet_cyc packet;
135 int errcode;
136
137 errcode = pt_time_update_cyc(NULL, &packet, &tfix->config, 0ull);
138 ptu_int_eq(errcode, -pte_internal);
139
140 errcode = pt_time_update_cyc(&tfix->time, NULL, &tfix->config, 0ull);
141 ptu_int_eq(errcode, -pte_internal);
142
143 errcode = pt_time_update_cyc(&tfix->time, &packet, NULL, 0ull);
144 ptu_int_eq(errcode, -pte_internal);
145
146 return ptu_passed();
147 }
148
query_tsc_null(struct time_fixture * tfix)149 static struct ptunit_result query_tsc_null(struct time_fixture *tfix)
150 {
151 uint64_t tsc;
152 int errcode;
153
154 errcode = pt_time_query_tsc(NULL, NULL, NULL, &tfix->time);
155 ptu_int_eq(errcode, -pte_internal);
156
157 errcode = pt_time_query_tsc(&tsc, NULL, NULL, NULL);
158 ptu_int_eq(errcode, -pte_internal);
159
160 return ptu_passed();
161 }
162
query_tsc_none(struct time_fixture * tfix)163 static struct ptunit_result query_tsc_none(struct time_fixture *tfix)
164 {
165 uint64_t tsc;
166 int errcode;
167
168 errcode = pt_time_query_tsc(&tsc, NULL, NULL, &tfix->time);
169 ptu_int_eq(errcode, -pte_no_time);
170
171 return ptu_passed();
172 }
173
query_cbr_null(struct time_fixture * tfix)174 static struct ptunit_result query_cbr_null(struct time_fixture *tfix)
175 {
176 uint32_t cbr;
177 int errcode;
178
179 errcode = pt_time_query_cbr(NULL, &tfix->time);
180 ptu_int_eq(errcode, -pte_internal);
181
182 errcode = pt_time_query_cbr(&cbr, NULL);
183 ptu_int_eq(errcode, -pte_internal);
184
185 return ptu_passed();
186 }
187
query_cbr_none(struct time_fixture * tfix)188 static struct ptunit_result query_cbr_none(struct time_fixture *tfix)
189 {
190 uint32_t cbr;
191 int errcode;
192
193 errcode = pt_time_query_cbr(&cbr, &tfix->time);
194 ptu_int_eq(errcode, -pte_no_cbr);
195
196 return ptu_passed();
197 }
198
tcal_cbr_null(struct time_fixture * tfix)199 static struct ptunit_result tcal_cbr_null(struct time_fixture *tfix)
200 {
201 struct pt_packet_cbr packet;
202 int errcode;
203
204 errcode = pt_tcal_update_cbr(NULL, &packet, &tfix->config);
205 ptu_int_eq(errcode, -pte_internal);
206
207 return ptu_passed();
208 }
209
tcal_cbr_zero(struct time_fixture * tfix)210 static struct ptunit_result tcal_cbr_zero(struct time_fixture *tfix)
211 {
212 struct pt_packet_cbr packet;
213 struct pt_config config;
214 int errcode;
215
216 config = tfix->config;
217 config.nom_freq = 1;
218 packet.ratio = 0;
219
220 errcode = pt_tcal_update_cbr(&tfix->tcal, &packet, &config);
221 ptu_int_eq(errcode, -pte_bad_packet);
222
223 return ptu_passed();
224 }
225
tcal_mtc_null(struct time_fixture * tfix)226 static struct ptunit_result tcal_mtc_null(struct time_fixture *tfix)
227 {
228 struct pt_packet_mtc packet;
229 int errcode;
230
231 errcode = pt_tcal_update_mtc(NULL, &packet, &tfix->config);
232 ptu_int_eq(errcode, -pte_internal);
233
234 errcode = pt_tcal_update_mtc(&tfix->tcal, NULL, &tfix->config);
235 ptu_int_eq(errcode, -pte_internal);
236
237 errcode = pt_tcal_update_mtc(&tfix->tcal, &packet, NULL);
238 ptu_int_eq(errcode, -pte_internal);
239
240 return ptu_passed();
241 }
242
tcal_cyc_null(struct time_fixture * tfix)243 static struct ptunit_result tcal_cyc_null(struct time_fixture *tfix)
244 {
245 struct pt_packet_cyc packet;
246 int errcode;
247
248 errcode = pt_tcal_update_cyc(NULL, &packet, &tfix->config);
249 ptu_int_eq(errcode, -pte_internal);
250
251 errcode = pt_tcal_update_cyc(&tfix->tcal, NULL, &tfix->config);
252 ptu_int_eq(errcode, -pte_internal);
253
254 return ptu_passed();
255 }
256
tsc(struct time_fixture * tfix)257 static struct ptunit_result tsc(struct time_fixture *tfix)
258 {
259 struct pt_packet_tsc packet;
260 uint64_t tsc;
261 uint32_t lost_mtc, lost_cyc;
262 int errcode;
263
264 packet.tsc = 0xdedededeull;
265
266 errcode = pt_time_update_tsc(&tfix->time, &packet, &tfix->config);
267 ptu_int_eq(errcode, 0);
268
269 errcode = pt_time_query_tsc(&tsc, &lost_mtc, &lost_cyc, &tfix->time);
270 ptu_int_eq(errcode, 0);
271
272 ptu_uint_eq(tsc, 0xdedededeull);
273 ptu_uint_eq(lost_mtc, 0);
274 ptu_uint_eq(lost_cyc, 0);
275
276 return ptu_passed();
277 }
278
cbr(struct time_fixture * tfix)279 static struct ptunit_result cbr(struct time_fixture *tfix)
280 {
281 struct pt_packet_cbr packet;
282 uint32_t cbr;
283 int errcode;
284
285 packet.ratio = 0x38;
286
287 errcode = pt_time_update_cbr(&tfix->time, &packet, &tfix->config);
288 ptu_int_eq(errcode, 0);
289
290 errcode = pt_time_query_cbr(&cbr, &tfix->time);
291 ptu_int_eq(errcode, 0);
292
293 ptu_uint_eq(cbr, 0x38);
294
295 return ptu_passed();
296 }
297
cbr_zero(struct time_fixture * tfix)298 static struct ptunit_result cbr_zero(struct time_fixture *tfix)
299 {
300 struct pt_packet_cbr packet;
301 int errcode;
302
303 packet.ratio = 0;
304
305 errcode = pt_time_update_cbr(&tfix->time, &packet, &tfix->config);
306 ptu_int_eq(errcode, -pte_bad_packet);
307
308 return ptu_passed();
309 }
310
tma(struct time_fixture * tfix)311 static struct ptunit_result tma(struct time_fixture *tfix)
312 {
313 struct pt_packet_tma packet;
314 int errcode;
315
316 packet.ctc = 0xdc;
317 packet.fc = 0xf;
318
319 errcode = pt_time_update_tma(&tfix->time, &packet, &tfix->config);
320 ptu_int_eq(errcode, -pte_bad_context);
321
322 return ptu_passed();
323 }
324
mtc(struct time_fixture * tfix)325 static struct ptunit_result mtc(struct time_fixture *tfix)
326 {
327 struct pt_packet_mtc packet;
328 uint64_t tsc;
329 int errcode;
330
331 packet.ctc = 0xdc;
332
333 errcode = pt_time_update_mtc(&tfix->time, &packet, &tfix->config);
334 ptu_int_eq(errcode, 0);
335
336 errcode = pt_time_query_tsc(&tsc, NULL, NULL, &tfix->time);
337 ptu_int_eq(errcode, -pte_no_time);
338
339 return ptu_passed();
340 }
341
cyc(struct time_fixture * tfix)342 static struct ptunit_result cyc(struct time_fixture *tfix)
343 {
344 struct pt_packet_cyc packet;
345 uint64_t fcr, tsc;
346 int errcode;
347
348 errcode = pt_tcal_fcr(&fcr, &tfix->tcal);
349 ptu_int_eq(errcode, 0);
350
351 packet.value = 0xdc;
352
353 errcode = pt_time_update_cyc(&tfix->time, &packet, &tfix->config, fcr);
354 ptu_int_eq(errcode, 0);
355
356 errcode = pt_time_query_tsc(&tsc, NULL, NULL, &tfix->time);
357 ptu_int_eq(errcode, -pte_no_time);
358
359 return ptu_passed();
360 }
361
362
main(int argc,char ** argv)363 int main(int argc, char **argv)
364 {
365 struct ptunit_suite suite;
366 struct time_fixture tfix;
367
368 suite = ptunit_mk_suite(argc, argv);
369
370 tfix.init = tfix_init;
371 tfix.fini = NULL;
372
373 ptu_run_f(suite, tsc_null, tfix);
374 ptu_run_f(suite, cbr_null, tfix);
375 ptu_run_f(suite, tma_null, tfix);
376 ptu_run_f(suite, mtc_null, tfix);
377 ptu_run_f(suite, cyc_null, tfix);
378
379 ptu_run_f(suite, query_tsc_null, tfix);
380 ptu_run_f(suite, query_tsc_none, tfix);
381 ptu_run_f(suite, query_cbr_null, tfix);
382 ptu_run_f(suite, query_cbr_none, tfix);
383
384 ptu_run_f(suite, tcal_cbr_null, tfix);
385 ptu_run_f(suite, tcal_cbr_zero, tfix);
386 ptu_run_f(suite, tcal_mtc_null, tfix);
387 ptu_run_f(suite, tcal_cyc_null, tfix);
388
389 ptu_run_f(suite, tsc, tfix);
390 ptu_run_f(suite, cbr, tfix);
391 ptu_run_f(suite, cbr_zero, tfix);
392 ptu_run_f(suite, tma, tfix);
393 ptu_run_f(suite, mtc, tfix);
394 ptu_run_f(suite, cyc, tfix);
395
396 /* The bulk is covered in ptt tests. */
397
398 return ptunit_report(&suite);
399 }
400