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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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