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
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_mtc_null(struct time_fixture * tfix)210 static struct ptunit_result tcal_mtc_null(struct time_fixture *tfix)
211 {
212 struct pt_packet_mtc packet;
213 int errcode;
214
215 errcode = pt_tcal_update_mtc(NULL, &packet, &tfix->config);
216 ptu_int_eq(errcode, -pte_internal);
217
218 errcode = pt_tcal_update_mtc(&tfix->tcal, NULL, &tfix->config);
219 ptu_int_eq(errcode, -pte_internal);
220
221 errcode = pt_tcal_update_mtc(&tfix->tcal, &packet, NULL);
222 ptu_int_eq(errcode, -pte_internal);
223
224 return ptu_passed();
225 }
226
tcal_cyc_null(struct time_fixture * tfix)227 static struct ptunit_result tcal_cyc_null(struct time_fixture *tfix)
228 {
229 struct pt_packet_cyc packet;
230 int errcode;
231
232 errcode = pt_tcal_update_cyc(NULL, &packet, &tfix->config);
233 ptu_int_eq(errcode, -pte_internal);
234
235 errcode = pt_tcal_update_cyc(&tfix->tcal, NULL, &tfix->config);
236 ptu_int_eq(errcode, -pte_internal);
237
238 return ptu_passed();
239 }
240
tsc(struct time_fixture * tfix)241 static struct ptunit_result tsc(struct time_fixture *tfix)
242 {
243 struct pt_packet_tsc packet;
244 uint64_t tsc;
245 uint32_t lost_mtc, lost_cyc;
246 int errcode;
247
248 packet.tsc = 0xdedededeull;
249
250 errcode = pt_time_update_tsc(&tfix->time, &packet, &tfix->config);
251 ptu_int_eq(errcode, 0);
252
253 errcode = pt_time_query_tsc(&tsc, &lost_mtc, &lost_cyc, &tfix->time);
254 ptu_int_eq(errcode, 0);
255
256 ptu_uint_eq(tsc, 0xdedededeull);
257 ptu_uint_eq(lost_mtc, 0);
258 ptu_uint_eq(lost_cyc, 0);
259
260 return ptu_passed();
261 }
262
cbr(struct time_fixture * tfix)263 static struct ptunit_result cbr(struct time_fixture *tfix)
264 {
265 struct pt_packet_cbr packet;
266 uint32_t cbr;
267 int errcode;
268
269 packet.ratio = 0x38;
270
271 errcode = pt_time_update_cbr(&tfix->time, &packet, &tfix->config);
272 ptu_int_eq(errcode, 0);
273
274 errcode = pt_time_query_cbr(&cbr, &tfix->time);
275 ptu_int_eq(errcode, 0);
276
277 ptu_uint_eq(cbr, 0x38);
278
279 return ptu_passed();
280 }
281
tma(struct time_fixture * tfix)282 static struct ptunit_result tma(struct time_fixture *tfix)
283 {
284 struct pt_packet_tma packet;
285 int errcode;
286
287 packet.ctc = 0xdc;
288 packet.fc = 0xf;
289
290 errcode = pt_time_update_tma(&tfix->time, &packet, &tfix->config);
291 ptu_int_eq(errcode, -pte_bad_context);
292
293 return ptu_passed();
294 }
295
mtc(struct time_fixture * tfix)296 static struct ptunit_result mtc(struct time_fixture *tfix)
297 {
298 struct pt_packet_mtc packet;
299 uint64_t tsc;
300 int errcode;
301
302 packet.ctc = 0xdc;
303
304 errcode = pt_time_update_mtc(&tfix->time, &packet, &tfix->config);
305 ptu_int_eq(errcode, 0);
306
307 errcode = pt_time_query_tsc(&tsc, NULL, NULL, &tfix->time);
308 ptu_int_eq(errcode, -pte_no_time);
309
310 return ptu_passed();
311 }
312
cyc(struct time_fixture * tfix)313 static struct ptunit_result cyc(struct time_fixture *tfix)
314 {
315 struct pt_packet_cyc packet;
316 uint64_t fcr, tsc;
317 int errcode;
318
319 errcode = pt_tcal_fcr(&fcr, &tfix->tcal);
320 ptu_int_eq(errcode, 0);
321
322 packet.value = 0xdc;
323
324 errcode = pt_time_update_cyc(&tfix->time, &packet, &tfix->config, fcr);
325 ptu_int_eq(errcode, 0);
326
327 errcode = pt_time_query_tsc(&tsc, NULL, NULL, &tfix->time);
328 ptu_int_eq(errcode, -pte_no_time);
329
330 return ptu_passed();
331 }
332
333
main(int argc,char ** argv)334 int main(int argc, char **argv)
335 {
336 struct ptunit_suite suite;
337 struct time_fixture tfix;
338
339 suite = ptunit_mk_suite(argc, argv);
340
341 tfix.init = tfix_init;
342 tfix.fini = NULL;
343
344 ptu_run_f(suite, tsc_null, tfix);
345 ptu_run_f(suite, cbr_null, tfix);
346 ptu_run_f(suite, tma_null, tfix);
347 ptu_run_f(suite, mtc_null, tfix);
348 ptu_run_f(suite, cyc_null, tfix);
349
350 ptu_run_f(suite, query_tsc_null, tfix);
351 ptu_run_f(suite, query_tsc_none, tfix);
352 ptu_run_f(suite, query_cbr_null, tfix);
353 ptu_run_f(suite, query_cbr_none, tfix);
354
355 ptu_run_f(suite, tcal_cbr_null, tfix);
356 ptu_run_f(suite, tcal_mtc_null, tfix);
357 ptu_run_f(suite, tcal_cyc_null, tfix);
358
359 ptu_run_f(suite, tsc, tfix);
360 ptu_run_f(suite, cbr, tfix);
361 ptu_run_f(suite, tma, tfix);
362 ptu_run_f(suite, mtc, tfix);
363 ptu_run_f(suite, cyc, tfix);
364
365 /* The bulk is covered in ptt tests. */
366
367 return ptunit_report(&suite);
368 }
369