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