1 /*
2 * Copyright (c) 2015-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 "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
from_user_null(void)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
from_user_too_small(void)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
from_user_bad_buffer(void)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
from_user(void)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
from_user_small(void)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
from_user_big(void)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
size(void)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
addr_filter_size(void)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
addr_filter_none(void)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
addr_filter_0(void)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
addr_filter_1_3(void)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
addr_filter_oob(uint8_t filter)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
addr_filter_ip_in(void)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
addr_filter_ip_out(void)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
addr_filter_stop_in(void)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
addr_filter_stop_out(void)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
addr_filter_ip_out_stop_in(void)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
addr_filter_ip_in_stop_in(void)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
cpu_errata_null(void)467 static struct ptunit_result cpu_errata_null(void)
468 {
469 struct pt_errata errata;
470 struct pt_cpu cpu;
471 int errcode;
472
473 errcode = pt_cpu_errata(&errata, NULL);
474 ptu_int_eq(errcode, -pte_invalid);
475
476 errcode = pt_cpu_errata(NULL, &cpu);
477 ptu_int_eq(errcode, -pte_invalid);
478
479 return ptu_passed();
480 }
481
cpu_errata_unknown(void)482 static struct ptunit_result cpu_errata_unknown(void)
483 {
484 struct pt_errata errata;
485 struct pt_cpu cpu;
486 int errcode;
487
488 memset(&cpu, 0, sizeof(cpu));
489
490 errcode = pt_cpu_errata(&errata, &cpu);
491 ptu_int_eq(errcode, -pte_bad_cpu);
492
493 return ptu_passed();
494 }
495
cpu_errata_bad_vendor(void)496 static struct ptunit_result cpu_errata_bad_vendor(void)
497 {
498 struct pt_errata errata;
499 struct pt_cpu cpu;
500 int errcode;
501
502 memset(&cpu, 0, sizeof(cpu));
503 cpu.vendor = (enum pt_cpu_vendor) 0xffff;
504
505 errcode = pt_cpu_errata(&errata, &cpu);
506 ptu_int_eq(errcode, -pte_bad_cpu);
507
508 return ptu_passed();
509 }
510
cpu_errata_bad_cpuid(void)511 static struct ptunit_result cpu_errata_bad_cpuid(void)
512 {
513 struct pt_errata errata;
514 struct pt_cpu cpu;
515 int errcode;
516
517 memset(&cpu, 0, sizeof(cpu));
518 cpu.vendor = pcv_intel;
519 cpu.family = 6;
520 cpu.model = 63;
521
522 errcode = pt_cpu_errata(&errata, &cpu);
523 ptu_int_eq(errcode, -pte_bad_cpu);
524
525 return ptu_passed();
526 }
527
main(int argc,char ** argv)528 int main(int argc, char **argv)
529 {
530 struct ptunit_suite suite;
531
532 suite = ptunit_mk_suite(argc, argv);
533
534 ptu_run(suite, from_user_null);
535 ptu_run(suite, from_user_too_small);
536 ptu_run(suite, from_user_bad_buffer);
537 ptu_run(suite, from_user);
538 ptu_run(suite, from_user_small);
539 ptu_run(suite, from_user_big);
540 ptu_run(suite, size);
541
542 ptu_run(suite, addr_filter_size);
543 ptu_run(suite, addr_filter_none);
544 ptu_run(suite, addr_filter_0);
545 ptu_run(suite, addr_filter_1_3);
546 ptu_run_p(suite, addr_filter_oob, 255);
547 ptu_run_p(suite, addr_filter_oob, 8);
548
549 ptu_run(suite, addr_filter_ip_in);
550 ptu_run(suite, addr_filter_ip_out);
551 ptu_run(suite, addr_filter_stop_in);
552 ptu_run(suite, addr_filter_stop_out);
553 ptu_run(suite, addr_filter_ip_out_stop_in);
554 ptu_run(suite, addr_filter_ip_in_stop_in);
555
556 ptu_run(suite, cpu_errata_null);
557 ptu_run(suite, cpu_errata_unknown);
558 ptu_run(suite, cpu_errata_bad_vendor);
559 ptu_run(suite, cpu_errata_bad_cpuid);
560
561 return ptunit_report(&suite);
562 }
563