1 /*
2  * Copyright (c) 2015-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 "ptunit.h"
30 
31 #include "pt_config.h"
32 #include "pt_opcodes.h"
33 
34 #include "intel-pt.h"
35 
36 #include <stddef.h>
37 
38 
39 /* A global fake buffer to pacify static analyzers. */
40 static uint8_t buffer[8];
41 
42 static struct ptunit_result from_user_null(void)
43 {
44 	struct pt_config config;
45 	int errcode;
46 
47 	errcode = pt_config_from_user(NULL, &config);
48 	ptu_int_eq(errcode, -pte_internal);
49 
50 	errcode = pt_config_from_user(&config, NULL);
51 	ptu_int_eq(errcode, -pte_invalid);
52 
53 	return ptu_passed();
54 }
55 
56 static struct ptunit_result from_user_too_small(void)
57 {
58 	struct pt_config config, user;
59 	int errcode;
60 
61 	user.size = sizeof(config.size);
62 
63 	errcode = pt_config_from_user(&config, &user);
64 	ptu_int_eq(errcode, -pte_bad_config);
65 
66 	return ptu_passed();
67 }
68 
69 static struct ptunit_result from_user_bad_buffer(void)
70 {
71 	struct pt_config config, user;
72 	int errcode;
73 
74 	pt_config_init(&user);
75 
76 	errcode = pt_config_from_user(&config, &user);
77 	ptu_int_eq(errcode, -pte_bad_config);
78 
79 	user.begin = buffer;
80 
81 	errcode = pt_config_from_user(&config, &user);
82 	ptu_int_eq(errcode, -pte_bad_config);
83 
84 	user.begin = NULL;
85 	user.end = buffer;
86 
87 	errcode = pt_config_from_user(&config, &user);
88 	ptu_int_eq(errcode, -pte_bad_config);
89 
90 	user.begin = &buffer[1];
91 	user.end = buffer;
92 
93 	errcode = pt_config_from_user(&config, &user);
94 	ptu_int_eq(errcode, -pte_bad_config);
95 
96 	return ptu_passed();
97 }
98 
99 static struct ptunit_result from_user(void)
100 {
101 	struct pt_config config, user;
102 	int errcode;
103 
104 	user.size = sizeof(user);
105 	user.begin = buffer;
106 	user.end = &buffer[sizeof(buffer)];
107 	user.cpu.vendor = pcv_intel;
108 	user.errata.bdm70 = 1;
109 
110 	errcode = pt_config_from_user(&config, &user);
111 	ptu_int_eq(errcode, 0);
112 	ptu_uint_eq(config.size, sizeof(config));
113 	ptu_ptr_eq(config.begin, buffer);
114 	ptu_ptr_eq(config.end, &buffer[sizeof(buffer)]);
115 	ptu_int_eq(config.cpu.vendor, pcv_intel);
116 	ptu_uint_eq(config.errata.bdm70, 1);
117 
118 	return ptu_passed();
119 }
120 
121 static struct ptunit_result from_user_small(void)
122 {
123 	struct pt_config config, user;
124 	int errcode;
125 
126 	memset(&config, 0xcd, sizeof(config));
127 
128 	user.size = offsetof(struct pt_config, cpu);
129 	user.begin = buffer;
130 	user.end = &buffer[sizeof(buffer)];
131 
132 	errcode = pt_config_from_user(&config, &user);
133 	ptu_int_eq(errcode, 0);
134 	ptu_uint_eq(config.size, offsetof(struct pt_config, cpu));
135 	ptu_ptr_eq(config.begin, buffer);
136 	ptu_ptr_eq(config.end, &buffer[sizeof(buffer)]);
137 	ptu_int_eq(config.cpu.vendor, pcv_unknown);
138 	ptu_uint_eq(config.errata.bdm70, 0);
139 
140 	return ptu_passed();
141 }
142 
143 static struct ptunit_result from_user_big(void)
144 {
145 	struct pt_config config, user;
146 	int errcode;
147 
148 	user.size = sizeof(user) + 4;
149 	user.begin = buffer;
150 	user.end = &buffer[sizeof(buffer)];
151 	user.cpu.vendor = pcv_intel;
152 	user.errata.bdm70 = 1;
153 
154 	errcode = pt_config_from_user(&config, &user);
155 	ptu_int_eq(errcode, 0);
156 	ptu_uint_eq(config.size, sizeof(config));
157 	ptu_ptr_eq(config.begin, buffer);
158 	ptu_ptr_eq(config.end, &buffer[sizeof(buffer)]);
159 	ptu_int_eq(config.cpu.vendor, pcv_intel);
160 	ptu_uint_eq(config.errata.bdm70, 1);
161 
162 	return ptu_passed();
163 }
164 
165 static struct ptunit_result size(void)
166 {
167 	ptu_uint_eq(sizeof(struct pt_errata), 16 * 4);
168 
169 	return ptu_passed();
170 }
171 
172 static struct ptunit_result addr_filter_size(void)
173 {
174 	struct pt_conf_addr_filter conf;
175 
176 	ptu_uint_eq(sizeof(conf.config), 8);
177 
178 	return ptu_passed();
179 }
180 
181 static struct ptunit_result addr_filter_none(void)
182 {
183 	struct pt_config config;
184 	uint8_t filter;
185 
186 	pt_config_init(&config);
187 
188 	ptu_uint_eq(config.addr_filter.config.addr_cfg, 0ull);
189 
190 	for (filter = 0; filter < 4; ++filter) {
191 		uint32_t addr_cfg;
192 
193 		addr_cfg = pt_filter_addr_cfg(&config.addr_filter, filter);
194 
195 		ptu_uint_eq(addr_cfg, pt_addr_cfg_disabled);
196 	}
197 
198 	return ptu_passed();
199 }
200 
201 static struct ptunit_result addr_filter_0(void)
202 {
203 	struct pt_config config;
204 	uint64_t addr_a, addr_b;
205 	uint32_t addr_cfg;
206 	uint8_t filter;
207 
208 	pt_config_init(&config);
209 	config.addr_filter.config.ctl.addr0_cfg = pt_addr_cfg_filter;
210 	config.addr_filter.addr0_a = 0xa000ull;
211 	config.addr_filter.addr0_b = 0xb000ull;
212 
213 	ptu_uint_ne(config.addr_filter.config.addr_cfg, 0ull);
214 
215 	addr_cfg = pt_filter_addr_cfg(&config.addr_filter, 0);
216 	ptu_uint_eq(addr_cfg, pt_addr_cfg_filter);
217 
218 	addr_a = pt_filter_addr_a(&config.addr_filter, 0);
219 	ptu_uint_eq(addr_a, 0xa000ull);
220 
221 	addr_b = pt_filter_addr_b(&config.addr_filter, 0);
222 	ptu_uint_eq(addr_b, 0xb000ull);
223 
224 	for (filter = 1; filter < 4; ++filter) {
225 
226 		addr_cfg = pt_filter_addr_cfg(&config.addr_filter, filter);
227 
228 		ptu_uint_eq(addr_cfg, pt_addr_cfg_disabled);
229 	}
230 
231 	return ptu_passed();
232 }
233 
234 static struct ptunit_result addr_filter_1_3(void)
235 {
236 	struct pt_config config;
237 	uint64_t addr_a, addr_b;
238 	uint32_t addr_cfg;
239 
240 	pt_config_init(&config);
241 	config.addr_filter.config.ctl.addr1_cfg = pt_addr_cfg_filter;
242 	config.addr_filter.addr1_a = 0xa000ull;
243 	config.addr_filter.addr1_b = 0xb000ull;
244 	config.addr_filter.config.ctl.addr3_cfg = pt_addr_cfg_stop;
245 	config.addr_filter.addr3_a = 0x100a000ull;
246 	config.addr_filter.addr3_b = 0x100b000ull;
247 
248 	ptu_uint_ne(config.addr_filter.config.addr_cfg, 0ull);
249 
250 	addr_cfg = pt_filter_addr_cfg(&config.addr_filter, 0);
251 	ptu_uint_eq(addr_cfg, pt_addr_cfg_disabled);
252 
253 	addr_cfg = pt_filter_addr_cfg(&config.addr_filter, 1);
254 	ptu_uint_eq(addr_cfg, pt_addr_cfg_filter);
255 
256 	addr_a = pt_filter_addr_a(&config.addr_filter, 1);
257 	ptu_uint_eq(addr_a, 0xa000ull);
258 
259 	addr_b = pt_filter_addr_b(&config.addr_filter, 1);
260 	ptu_uint_eq(addr_b, 0xb000ull);
261 
262 	addr_cfg = pt_filter_addr_cfg(&config.addr_filter, 2);
263 	ptu_uint_eq(addr_cfg, pt_addr_cfg_disabled);
264 
265 	addr_cfg = pt_filter_addr_cfg(&config.addr_filter, 3);
266 	ptu_uint_eq(addr_cfg, pt_addr_cfg_stop);
267 
268 	addr_a = pt_filter_addr_a(&config.addr_filter, 3);
269 	ptu_uint_eq(addr_a, 0x100a000ull);
270 
271 	addr_b = pt_filter_addr_b(&config.addr_filter, 3);
272 	ptu_uint_eq(addr_b, 0x100b000ull);
273 
274 	return ptu_passed();
275 }
276 
277 static struct ptunit_result addr_filter_oob(uint8_t filter)
278 {
279 	struct pt_config config;
280 	uint64_t addr_a, addr_b;
281 	uint32_t addr_cfg;
282 
283 	pt_config_init(&config);
284 
285 	memset(&config.addr_filter, 0xcc, sizeof(config.addr_filter));
286 
287 	addr_cfg = pt_filter_addr_cfg(&config.addr_filter, filter);
288 	ptu_uint_eq(addr_cfg, pt_addr_cfg_disabled);
289 
290 	addr_a = pt_filter_addr_a(&config.addr_filter, filter);
291 	ptu_uint_eq(addr_a, 0ull);
292 
293 	addr_b = pt_filter_addr_b(&config.addr_filter, filter);
294 	ptu_uint_eq(addr_b, 0ull);
295 
296 	return ptu_passed();
297 }
298 
299 static struct ptunit_result addr_filter_ip_in(void)
300 {
301 	struct pt_config config;
302 	int status;
303 
304 	pt_config_init(&config);
305 	config.addr_filter.config.ctl.addr1_cfg = pt_addr_cfg_filter;
306 	config.addr_filter.addr1_a = 0xa000;
307 	config.addr_filter.addr1_b = 0xb000;
308 	config.addr_filter.config.ctl.addr3_cfg = pt_addr_cfg_filter;
309 	config.addr_filter.addr3_a = 0x10a000;
310 	config.addr_filter.addr3_b = 0x10b000;
311 
312 	status = pt_filter_addr_check(&config.addr_filter, 0xa000);
313 	ptu_int_eq(status, 1);
314 
315 	status = pt_filter_addr_check(&config.addr_filter, 0xaf00);
316 	ptu_int_eq(status, 1);
317 
318 	status = pt_filter_addr_check(&config.addr_filter, 0xb000);
319 	ptu_int_eq(status, 1);
320 
321 	status = pt_filter_addr_check(&config.addr_filter, 0x10a000);
322 	ptu_int_eq(status, 1);
323 
324 	status = pt_filter_addr_check(&config.addr_filter, 0x10af00);
325 	ptu_int_eq(status, 1);
326 
327 	status = pt_filter_addr_check(&config.addr_filter, 0x10b000);
328 	ptu_int_eq(status, 1);
329 
330 	return ptu_passed();
331 }
332 
333 static struct ptunit_result addr_filter_ip_out(void)
334 {
335 	struct pt_config config;
336 	int status;
337 
338 	pt_config_init(&config);
339 	config.addr_filter.config.ctl.addr1_cfg = pt_addr_cfg_filter;
340 	config.addr_filter.addr1_a = 0xa000;
341 	config.addr_filter.addr1_b = 0xb000;
342 	config.addr_filter.config.ctl.addr3_cfg = pt_addr_cfg_filter;
343 	config.addr_filter.addr3_a = 0x10a000;
344 	config.addr_filter.addr3_b = 0x10b000;
345 
346 	status = pt_filter_addr_check(&config.addr_filter, 0xfff);
347 	ptu_int_eq(status, 0);
348 
349 	status = pt_filter_addr_check(&config.addr_filter, 0xb001);
350 	ptu_int_eq(status, 0);
351 
352 	status = pt_filter_addr_check(&config.addr_filter, 0x100fff);
353 	ptu_int_eq(status, 0);
354 
355 	status = pt_filter_addr_check(&config.addr_filter, 0x10b001);
356 	ptu_int_eq(status, 0);
357 
358 	return ptu_passed();
359 }
360 
361 static struct ptunit_result addr_filter_stop_in(void)
362 {
363 	struct pt_config config;
364 	int status;
365 
366 	pt_config_init(&config);
367 	config.addr_filter.config.ctl.addr1_cfg = pt_addr_cfg_stop;
368 	config.addr_filter.addr1_a = 0xa000;
369 	config.addr_filter.addr1_b = 0xb000;
370 	config.addr_filter.config.ctl.addr3_cfg = pt_addr_cfg_stop;
371 	config.addr_filter.addr3_a = 0x10a000;
372 	config.addr_filter.addr3_b = 0x10b000;
373 
374 	status = pt_filter_addr_check(&config.addr_filter, 0xa000);
375 	ptu_int_eq(status, 0);
376 
377 	status = pt_filter_addr_check(&config.addr_filter, 0xaf00);
378 	ptu_int_eq(status, 0);
379 
380 	status = pt_filter_addr_check(&config.addr_filter, 0xb000);
381 	ptu_int_eq(status, 0);
382 
383 	status = pt_filter_addr_check(&config.addr_filter, 0x10a000);
384 	ptu_int_eq(status, 0);
385 
386 	status = pt_filter_addr_check(&config.addr_filter, 0x10af00);
387 	ptu_int_eq(status, 0);
388 
389 	status = pt_filter_addr_check(&config.addr_filter, 0x10b000);
390 	ptu_int_eq(status, 0);
391 
392 	return ptu_passed();
393 }
394 
395 static struct ptunit_result addr_filter_stop_out(void)
396 {
397 	struct pt_config config;
398 	int status;
399 
400 	pt_config_init(&config);
401 	config.addr_filter.config.ctl.addr1_cfg = pt_addr_cfg_stop;
402 	config.addr_filter.addr1_a = 0xa000;
403 	config.addr_filter.addr1_b = 0xb000;
404 	config.addr_filter.config.ctl.addr3_cfg = pt_addr_cfg_stop;
405 	config.addr_filter.addr3_a = 0x10a000;
406 	config.addr_filter.addr3_b = 0x10b000;
407 
408 	status = pt_filter_addr_check(&config.addr_filter, 0xfff);
409 	ptu_int_eq(status, 1);
410 
411 	status = pt_filter_addr_check(&config.addr_filter, 0xb001);
412 	ptu_int_eq(status, 1);
413 
414 	status = pt_filter_addr_check(&config.addr_filter, 0x100fff);
415 	ptu_int_eq(status, 1);
416 
417 	status = pt_filter_addr_check(&config.addr_filter, 0x10b001);
418 	ptu_int_eq(status, 1);
419 
420 	return ptu_passed();
421 }
422 
423 static struct ptunit_result addr_filter_ip_out_stop_in(void)
424 {
425 	struct pt_config config;
426 	int status;
427 
428 	pt_config_init(&config);
429 	config.addr_filter.config.ctl.addr1_cfg = pt_addr_cfg_filter;
430 	config.addr_filter.addr1_a = 0x100f00;
431 	config.addr_filter.addr1_b = 0x10af00;
432 	config.addr_filter.config.ctl.addr3_cfg = pt_addr_cfg_stop;
433 	config.addr_filter.addr3_a = 0x10a000;
434 	config.addr_filter.addr3_b = 0x10b000;
435 
436 	status = pt_filter_addr_check(&config.addr_filter, 0x10af01);
437 	ptu_int_eq(status, 0);
438 
439 	status = pt_filter_addr_check(&config.addr_filter, 0x10b000);
440 	ptu_int_eq(status, 0);
441 
442 	return ptu_passed();
443 }
444 
445 static struct ptunit_result addr_filter_ip_in_stop_in(void)
446 {
447 	struct pt_config config;
448 	int status;
449 
450 	pt_config_init(&config);
451 	config.addr_filter.config.ctl.addr1_cfg = pt_addr_cfg_filter;
452 	config.addr_filter.addr1_a = 0x100f00;
453 	config.addr_filter.addr1_b = 0x10af00;
454 	config.addr_filter.config.ctl.addr3_cfg = pt_addr_cfg_stop;
455 	config.addr_filter.addr3_a = 0x10a000;
456 	config.addr_filter.addr3_b = 0x10b000;
457 
458 	status = pt_filter_addr_check(&config.addr_filter, 0x10af00);
459 	ptu_int_eq(status, 0);
460 
461 	status = pt_filter_addr_check(&config.addr_filter, 0x10a0ff);
462 	ptu_int_eq(status, 0);
463 
464 	return ptu_passed();
465 }
466 
467 int main(int argc, char **argv)
468 {
469 	struct ptunit_suite suite;
470 
471 	suite = ptunit_mk_suite(argc, argv);
472 
473 	ptu_run(suite, from_user_null);
474 	ptu_run(suite, from_user_too_small);
475 	ptu_run(suite, from_user_bad_buffer);
476 	ptu_run(suite, from_user);
477 	ptu_run(suite, from_user_small);
478 	ptu_run(suite, from_user_big);
479 	ptu_run(suite, size);
480 
481 	ptu_run(suite, addr_filter_size);
482 	ptu_run(suite, addr_filter_none);
483 	ptu_run(suite, addr_filter_0);
484 	ptu_run(suite, addr_filter_1_3);
485 	ptu_run_p(suite, addr_filter_oob, 255);
486 	ptu_run_p(suite, addr_filter_oob, 8);
487 
488 	ptu_run(suite, addr_filter_ip_in);
489 	ptu_run(suite, addr_filter_ip_out);
490 	ptu_run(suite, addr_filter_stop_in);
491 	ptu_run(suite, addr_filter_stop_out);
492 	ptu_run(suite, addr_filter_ip_out_stop_in);
493 	ptu_run(suite, addr_filter_ip_in_stop_in);
494 
495 	return ptunit_report(&suite);
496 }
497