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