1 /* 2 * Copyright (c) 2016-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_image_section_cache.h" 30 31 #include "ptunit_threads.h" 32 33 #include "intel-pt.h" 34 35 #include <stdlib.h> 36 37 38 struct pt_section { 39 /* The filename. We only support string literals for testing. */ 40 const char *filename; 41 42 /* The file offset and size. */ 43 uint64_t offset; 44 uint64_t size; 45 46 /* The bcache size. */ 47 uint64_t bcsize; 48 49 /* The iscache back link. */ 50 struct pt_image_section_cache *iscache; 51 52 /* The file content. */ 53 uint8_t content[0x10]; 54 55 /* The use count. */ 56 int ucount; 57 58 /* The attach count. */ 59 int acount; 60 61 /* The map count. */ 62 int mcount; 63 64 #if defined(FEATURE_THREADS) 65 /* A lock protecting this section. */ 66 mtx_t lock; 67 /* A lock protecting the iscache and acount fields. */ 68 mtx_t alock; 69 #endif /* defined(FEATURE_THREADS) */ 70 }; 71 72 extern struct pt_section *pt_mk_section(const char *filename, uint64_t offset, 73 uint64_t size); 74 75 extern int pt_section_get(struct pt_section *section); 76 extern int pt_section_put(struct pt_section *section); 77 extern int pt_section_attach(struct pt_section *section, 78 struct pt_image_section_cache *iscache); 79 extern int pt_section_detach(struct pt_section *section, 80 struct pt_image_section_cache *iscache); 81 82 extern int pt_section_map(struct pt_section *section); 83 extern int pt_section_map_share(struct pt_section *section); 84 extern int pt_section_unmap(struct pt_section *section); 85 extern int pt_section_request_bcache(struct pt_section *section); 86 87 extern const char *pt_section_filename(const struct pt_section *section); 88 extern uint64_t pt_section_offset(const struct pt_section *section); 89 extern uint64_t pt_section_size(const struct pt_section *section); 90 extern int pt_section_memsize(struct pt_section *section, uint64_t *size); 91 92 extern int pt_section_read(const struct pt_section *section, uint8_t *buffer, 93 uint16_t size, uint64_t offset); 94 95 96 struct pt_section *pt_mk_section(const char *filename, uint64_t offset, 97 uint64_t size) 98 { 99 struct pt_section *section; 100 101 section = malloc(sizeof(*section)); 102 if (section) { 103 uint8_t idx; 104 105 memset(section, 0, sizeof(*section)); 106 section->filename = filename; 107 section->offset = offset; 108 section->size = size; 109 section->ucount = 1; 110 111 for (idx = 0; idx < sizeof(section->content); ++idx) 112 section->content[idx] = idx; 113 114 #if defined(FEATURE_THREADS) 115 { 116 int errcode; 117 118 errcode = mtx_init(§ion->lock, mtx_plain); 119 if (errcode != thrd_success) { 120 free(section); 121 section = NULL; 122 } 123 124 errcode = mtx_init(§ion->alock, mtx_plain); 125 if (errcode != thrd_success) { 126 mtx_destroy(§ion->lock); 127 free(section); 128 section = NULL; 129 } 130 } 131 #endif /* defined(FEATURE_THREADS) */ 132 } 133 134 return section; 135 } 136 137 static int pt_section_lock(struct pt_section *section) 138 { 139 if (!section) 140 return -pte_internal; 141 142 #if defined(FEATURE_THREADS) 143 { 144 int errcode; 145 146 errcode = mtx_lock(§ion->lock); 147 if (errcode != thrd_success) 148 return -pte_bad_lock; 149 } 150 #endif /* defined(FEATURE_THREADS) */ 151 152 return 0; 153 } 154 155 static int pt_section_unlock(struct pt_section *section) 156 { 157 if (!section) 158 return -pte_internal; 159 160 #if defined(FEATURE_THREADS) 161 { 162 int errcode; 163 164 errcode = mtx_unlock(§ion->lock); 165 if (errcode != thrd_success) 166 return -pte_bad_lock; 167 } 168 #endif /* defined(FEATURE_THREADS) */ 169 170 return 0; 171 } 172 173 static int pt_section_lock_attach(struct pt_section *section) 174 { 175 if (!section) 176 return -pte_internal; 177 178 #if defined(FEATURE_THREADS) 179 { 180 int errcode; 181 182 errcode = mtx_lock(§ion->alock); 183 if (errcode != thrd_success) 184 return -pte_bad_lock; 185 } 186 #endif /* defined(FEATURE_THREADS) */ 187 188 return 0; 189 } 190 191 static int pt_section_unlock_attach(struct pt_section *section) 192 { 193 if (!section) 194 return -pte_internal; 195 196 #if defined(FEATURE_THREADS) 197 { 198 int errcode; 199 200 errcode = mtx_unlock(§ion->alock); 201 if (errcode != thrd_success) 202 return -pte_bad_lock; 203 } 204 #endif /* defined(FEATURE_THREADS) */ 205 206 return 0; 207 } 208 209 int pt_section_get(struct pt_section *section) 210 { 211 int errcode, ucount; 212 213 if (!section) 214 return -pte_internal; 215 216 errcode = pt_section_lock(section); 217 if (errcode < 0) 218 return errcode; 219 220 ucount = ++section->ucount; 221 222 errcode = pt_section_unlock(section); 223 if (errcode < 0) 224 return errcode; 225 226 if (!ucount) 227 return -pte_internal; 228 229 return 0; 230 } 231 232 int pt_section_put(struct pt_section *section) 233 { 234 int errcode, ucount; 235 236 if (!section) 237 return -pte_internal; 238 239 errcode = pt_section_lock(section); 240 if (errcode < 0) 241 return errcode; 242 243 ucount = --section->ucount; 244 245 errcode = pt_section_unlock(section); 246 if (errcode < 0) 247 return errcode; 248 249 if (!ucount) { 250 #if defined(FEATURE_THREADS) 251 mtx_destroy(§ion->alock); 252 mtx_destroy(§ion->lock); 253 #endif /* defined(FEATURE_THREADS) */ 254 free(section); 255 } 256 257 return 0; 258 } 259 260 int pt_section_attach(struct pt_section *section, 261 struct pt_image_section_cache *iscache) 262 { 263 int errcode, ucount, acount; 264 265 if (!section || !iscache) 266 return -pte_internal; 267 268 errcode = pt_section_lock_attach(section); 269 if (errcode < 0) 270 return errcode; 271 272 ucount = section->ucount; 273 acount = section->acount; 274 if (!acount) { 275 if (section->iscache || !ucount) 276 goto out_unlock; 277 278 section->iscache = iscache; 279 section->acount = 1; 280 281 return pt_section_unlock_attach(section); 282 } 283 284 acount += 1; 285 if (!acount) { 286 (void) pt_section_unlock_attach(section); 287 return -pte_overflow; 288 } 289 290 if (ucount < acount) 291 goto out_unlock; 292 293 if (section->iscache != iscache) 294 goto out_unlock; 295 296 section->acount = acount; 297 298 return pt_section_unlock_attach(section); 299 300 out_unlock: 301 (void) pt_section_unlock_attach(section); 302 return -pte_internal; 303 } 304 305 int pt_section_detach(struct pt_section *section, 306 struct pt_image_section_cache *iscache) 307 { 308 int errcode, ucount, acount; 309 310 if (!section || !iscache) 311 return -pte_internal; 312 313 errcode = pt_section_lock_attach(section); 314 if (errcode < 0) 315 return errcode; 316 317 if (section->iscache != iscache) 318 goto out_unlock; 319 320 acount = section->acount; 321 if (!acount) 322 goto out_unlock; 323 324 acount -= 1; 325 ucount = section->ucount; 326 if (ucount < acount) 327 goto out_unlock; 328 329 section->acount = acount; 330 if (!acount) 331 section->iscache = NULL; 332 333 return pt_section_unlock_attach(section); 334 335 out_unlock: 336 (void) pt_section_unlock_attach(section); 337 return -pte_internal; 338 } 339 340 int pt_section_map(struct pt_section *section) 341 { 342 struct pt_image_section_cache *iscache; 343 int errcode, status; 344 345 if (!section) 346 return -pte_internal; 347 348 errcode = pt_section_map_share(section); 349 if (errcode < 0) 350 return errcode; 351 352 errcode = pt_section_lock_attach(section); 353 if (errcode < 0) 354 return errcode; 355 356 status = 0; 357 iscache = section->iscache; 358 if (iscache) 359 status = pt_iscache_notify_map(iscache, section); 360 361 errcode = pt_section_unlock_attach(section); 362 363 return (status < 0) ? status : errcode; 364 } 365 366 int pt_section_map_share(struct pt_section *section) 367 { 368 int errcode, mcount; 369 370 if (!section) 371 return -pte_internal; 372 373 errcode = pt_section_lock(section); 374 if (errcode < 0) 375 return errcode; 376 377 mcount = ++section->mcount; 378 379 errcode = pt_section_unlock(section); 380 if (errcode < 0) 381 return errcode; 382 383 if (mcount <= 0) 384 return -pte_internal; 385 386 return 0; 387 } 388 389 int pt_section_unmap(struct pt_section *section) 390 { 391 int errcode, mcount; 392 393 if (!section) 394 return -pte_internal; 395 396 errcode = pt_section_lock(section); 397 if (errcode < 0) 398 return errcode; 399 400 section->bcsize = 0ull; 401 mcount = --section->mcount; 402 403 errcode = pt_section_unlock(section); 404 if (errcode < 0) 405 return errcode; 406 407 if (mcount < 0) 408 return -pte_internal; 409 410 return 0; 411 } 412 413 int pt_section_request_bcache(struct pt_section *section) 414 { 415 struct pt_image_section_cache *iscache; 416 uint64_t memsize; 417 int errcode; 418 419 if (!section) 420 return -pte_internal; 421 422 errcode = pt_section_lock_attach(section); 423 if (errcode < 0) 424 return errcode; 425 426 errcode = pt_section_lock(section); 427 if (errcode < 0) 428 goto out_alock; 429 430 if (section->bcsize) 431 goto out_lock; 432 433 section->bcsize = section->size * 3; 434 memsize = section->size + section->bcsize; 435 436 errcode = pt_section_unlock(section); 437 if (errcode < 0) 438 goto out_alock; 439 440 iscache = section->iscache; 441 if (iscache) { 442 errcode = pt_iscache_notify_resize(iscache, section, memsize); 443 if (errcode < 0) 444 goto out_alock; 445 } 446 447 return pt_section_unlock_attach(section); 448 449 450 out_lock: 451 (void) pt_section_unlock(section); 452 453 out_alock: 454 (void) pt_section_unlock_attach(section); 455 return errcode; 456 } 457 458 const char *pt_section_filename(const struct pt_section *section) 459 { 460 if (!section) 461 return NULL; 462 463 return section->filename; 464 } 465 466 uint64_t pt_section_offset(const struct pt_section *section) 467 { 468 if (!section) 469 return 0ull; 470 471 return section->offset; 472 } 473 474 uint64_t pt_section_size(const struct pt_section *section) 475 { 476 if (!section) 477 return 0ull; 478 479 return section->size; 480 } 481 482 int pt_section_memsize(struct pt_section *section, uint64_t *size) 483 { 484 if (!section || !size) 485 return -pte_internal; 486 487 *size = section->mcount ? section->size + section->bcsize : 0ull; 488 489 return 0; 490 } 491 492 int pt_section_read(const struct pt_section *section, uint8_t *buffer, 493 uint16_t size, uint64_t offset) 494 { 495 uint64_t begin, end, max; 496 497 if (!section || !buffer) 498 return -pte_internal; 499 500 begin = offset; 501 end = begin + size; 502 max = sizeof(section->content); 503 504 if (max <= begin) 505 return -pte_nomap; 506 507 if (max < end) 508 end = max; 509 510 if (end <= begin) 511 return -pte_invalid; 512 513 memcpy(buffer, §ion->content[begin], (size_t) (end - begin)); 514 return (int) (end - begin); 515 } 516 517 enum { 518 /* The number of test sections. */ 519 num_sections = 8, 520 521 #if defined(FEATURE_THREADS) 522 523 num_threads = 8, 524 525 #endif /* defined(FEATURE_THREADS) */ 526 527 num_iterations = 0x1000 528 }; 529 530 struct iscache_fixture { 531 /* Threading support. */ 532 struct ptunit_thrd_fixture thrd; 533 534 /* The image section cache under test. */ 535 struct pt_image_section_cache iscache; 536 537 /* A bunch of test sections. */ 538 struct pt_section *section[num_sections]; 539 540 /* The test fixture initialization and finalization functions. */ 541 struct ptunit_result (*init)(struct iscache_fixture *); 542 struct ptunit_result (*fini)(struct iscache_fixture *); 543 }; 544 545 static struct ptunit_result dfix_init(struct iscache_fixture *cfix) 546 { 547 int idx; 548 549 ptu_test(ptunit_thrd_init, &cfix->thrd); 550 551 memset(cfix->section, 0, sizeof(cfix->section)); 552 553 for (idx = 0; idx < num_sections; ++idx) { 554 struct pt_section *section; 555 556 section = pt_mk_section("some-filename", 557 idx % 3 == 0 ? 0x1000 : 0x2000, 558 idx % 2 == 0 ? 0x1000 : 0x2000); 559 ptu_ptr(section); 560 561 cfix->section[idx] = section; 562 } 563 564 return ptu_passed(); 565 } 566 567 static struct ptunit_result cfix_init(struct iscache_fixture *cfix) 568 { 569 int errcode; 570 571 ptu_test(dfix_init, cfix); 572 573 errcode = pt_iscache_init(&cfix->iscache, NULL); 574 ptu_int_eq(errcode, 0); 575 576 return ptu_passed(); 577 } 578 579 static struct ptunit_result sfix_init(struct iscache_fixture *cfix) 580 { 581 int status, idx; 582 583 ptu_test(cfix_init, cfix); 584 585 cfix->iscache.limit = 0x7800; 586 587 for (idx = 0; idx < num_sections; ++idx) { 588 status = pt_iscache_add(&cfix->iscache, cfix->section[idx], 589 0ull); 590 ptu_int_ge(status, 0); 591 } 592 593 return ptu_passed(); 594 } 595 596 static struct ptunit_result cfix_fini(struct iscache_fixture *cfix) 597 { 598 int idx, errcode; 599 600 ptu_test(ptunit_thrd_fini, &cfix->thrd); 601 602 for (idx = 0; idx < cfix->thrd.nthreads; ++idx) 603 ptu_int_eq(cfix->thrd.result[idx], 0); 604 605 pt_iscache_fini(&cfix->iscache); 606 607 for (idx = 0; idx < num_sections; ++idx) { 608 ptu_int_eq(cfix->section[idx]->ucount, 1); 609 ptu_int_eq(cfix->section[idx]->acount, 0); 610 ptu_int_eq(cfix->section[idx]->mcount, 0); 611 ptu_null(cfix->section[idx]->iscache); 612 613 errcode = pt_section_put(cfix->section[idx]); 614 ptu_int_eq(errcode, 0); 615 } 616 617 return ptu_passed(); 618 } 619 620 621 static struct ptunit_result init_null(void) 622 { 623 int errcode; 624 625 errcode = pt_iscache_init(NULL, NULL); 626 ptu_int_eq(errcode, -pte_internal); 627 628 return ptu_passed(); 629 } 630 631 static struct ptunit_result fini_null(void) 632 { 633 pt_iscache_fini(NULL); 634 635 return ptu_passed(); 636 } 637 638 static struct ptunit_result name_null(void) 639 { 640 const char *name; 641 642 name = pt_iscache_name(NULL); 643 ptu_null(name); 644 645 return ptu_passed(); 646 } 647 648 static struct ptunit_result add_null(void) 649 { 650 struct pt_image_section_cache iscache; 651 struct pt_section section; 652 int errcode; 653 654 errcode = pt_iscache_add(NULL, §ion, 0ull); 655 ptu_int_eq(errcode, -pte_internal); 656 657 errcode = pt_iscache_add(&iscache, NULL, 0ull); 658 ptu_int_eq(errcode, -pte_internal); 659 660 return ptu_passed(); 661 } 662 663 static struct ptunit_result find_null(void) 664 { 665 int errcode; 666 667 errcode = pt_iscache_find(NULL, "filename", 0ull, 0ull, 0ull); 668 ptu_int_eq(errcode, -pte_internal); 669 670 return ptu_passed(); 671 } 672 673 static struct ptunit_result lookup_null(void) 674 { 675 struct pt_image_section_cache iscache; 676 struct pt_section *section; 677 uint64_t laddr; 678 int errcode; 679 680 errcode = pt_iscache_lookup(NULL, §ion, &laddr, 0); 681 ptu_int_eq(errcode, -pte_internal); 682 683 errcode = pt_iscache_lookup(&iscache, NULL, &laddr, 0); 684 ptu_int_eq(errcode, -pte_internal); 685 686 errcode = pt_iscache_lookup(&iscache, §ion, NULL, 0); 687 ptu_int_eq(errcode, -pte_internal); 688 689 return ptu_passed(); 690 } 691 692 static struct ptunit_result clear_null(void) 693 { 694 int errcode; 695 696 errcode = pt_iscache_clear(NULL); 697 ptu_int_eq(errcode, -pte_internal); 698 699 return ptu_passed(); 700 } 701 702 static struct ptunit_result free_null(void) 703 { 704 pt_iscache_free(NULL); 705 706 return ptu_passed(); 707 } 708 709 static struct ptunit_result add_file_null(void) 710 { 711 struct pt_image_section_cache iscache; 712 int errcode; 713 714 errcode = pt_iscache_add_file(NULL, "filename", 0ull, 0ull, 0ull); 715 ptu_int_eq(errcode, -pte_invalid); 716 717 errcode = pt_iscache_add_file(&iscache, NULL, 0ull, 0ull, 0ull); 718 ptu_int_eq(errcode, -pte_invalid); 719 720 return ptu_passed(); 721 } 722 723 static struct ptunit_result read_null(void) 724 { 725 struct pt_image_section_cache iscache; 726 uint8_t buffer; 727 int errcode; 728 729 errcode = pt_iscache_read(NULL, &buffer, sizeof(buffer), 1ull, 0ull); 730 ptu_int_eq(errcode, -pte_invalid); 731 732 errcode = pt_iscache_read(&iscache, NULL, sizeof(buffer), 1ull, 0ull); 733 ptu_int_eq(errcode, -pte_invalid); 734 735 errcode = pt_iscache_read(&iscache, &buffer, 0ull, 1, 0ull); 736 ptu_int_eq(errcode, -pte_invalid); 737 738 return ptu_passed(); 739 } 740 741 static struct ptunit_result init_fini(struct iscache_fixture *cfix) 742 { 743 (void) cfix; 744 745 /* The actual init and fini calls are in cfix_init() and cfix_fini(). */ 746 return ptu_passed(); 747 } 748 749 static struct ptunit_result name(struct iscache_fixture *cfix) 750 { 751 const char *name; 752 753 pt_iscache_init(&cfix->iscache, "iscache-name"); 754 755 name = pt_iscache_name(&cfix->iscache); 756 ptu_str_eq(name, "iscache-name"); 757 758 return ptu_passed(); 759 } 760 761 static struct ptunit_result name_none(struct iscache_fixture *cfix) 762 { 763 const char *name; 764 765 pt_iscache_init(&cfix->iscache, NULL); 766 767 name = pt_iscache_name(&cfix->iscache); 768 ptu_null(name); 769 770 return ptu_passed(); 771 } 772 773 static struct ptunit_result add(struct iscache_fixture *cfix) 774 { 775 int isid; 776 777 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull); 778 ptu_int_gt(isid, 0); 779 780 /* The cache attaches and gets a reference on success. */ 781 ptu_int_eq(cfix->section[0]->ucount, 2); 782 ptu_int_eq(cfix->section[0]->acount, 1); 783 784 /* The added section must be implicitly put in pt_iscache_fini. */ 785 return ptu_passed(); 786 } 787 788 static struct ptunit_result add_no_name(struct iscache_fixture *cfix) 789 { 790 struct pt_section section; 791 int errcode; 792 793 memset(§ion, 0, sizeof(section)); 794 795 errcode = pt_iscache_add(&cfix->iscache, §ion, 0ull); 796 ptu_int_eq(errcode, -pte_internal); 797 798 return ptu_passed(); 799 } 800 801 static struct ptunit_result add_file(struct iscache_fixture *cfix) 802 { 803 int isid; 804 805 isid = pt_iscache_add_file(&cfix->iscache, "name", 0ull, 1ull, 0ull); 806 ptu_int_gt(isid, 0); 807 808 return ptu_passed(); 809 } 810 811 static struct ptunit_result find(struct iscache_fixture *cfix) 812 { 813 struct pt_section *section; 814 int found, isid; 815 816 section = cfix->section[0]; 817 ptu_ptr(section); 818 819 isid = pt_iscache_add(&cfix->iscache, section, 0ull); 820 ptu_int_gt(isid, 0); 821 822 found = pt_iscache_find(&cfix->iscache, section->filename, 823 section->offset, section->size, 0ull); 824 ptu_int_eq(found, isid); 825 826 return ptu_passed(); 827 } 828 829 static struct ptunit_result find_empty(struct iscache_fixture *cfix) 830 { 831 struct pt_section *section; 832 int found; 833 834 section = cfix->section[0]; 835 ptu_ptr(section); 836 837 found = pt_iscache_find(&cfix->iscache, section->filename, 838 section->offset, section->size, 0ull); 839 ptu_int_eq(found, 0); 840 841 return ptu_passed(); 842 } 843 844 static struct ptunit_result find_bad_filename(struct iscache_fixture *cfix) 845 { 846 struct pt_section *section; 847 int found, isid; 848 849 section = cfix->section[0]; 850 ptu_ptr(section); 851 852 isid = pt_iscache_add(&cfix->iscache, section, 0ull); 853 ptu_int_gt(isid, 0); 854 855 found = pt_iscache_find(&cfix->iscache, "bad-filename", 856 section->offset, section->size, 0ull); 857 ptu_int_eq(found, 0); 858 859 return ptu_passed(); 860 } 861 862 static struct ptunit_result find_null_filename(struct iscache_fixture *cfix) 863 { 864 int errcode; 865 866 errcode = pt_iscache_find(&cfix->iscache, NULL, 0ull, 0ull, 0ull); 867 ptu_int_eq(errcode, -pte_internal); 868 869 return ptu_passed(); 870 } 871 872 static struct ptunit_result find_bad_offset(struct iscache_fixture *cfix) 873 { 874 struct pt_section *section; 875 int found, isid; 876 877 section = cfix->section[0]; 878 ptu_ptr(section); 879 880 isid = pt_iscache_add(&cfix->iscache, section, 0ull); 881 ptu_int_gt(isid, 0); 882 883 found = pt_iscache_find(&cfix->iscache, section->filename, 0ull, 884 section->size, 0ull); 885 ptu_int_eq(found, 0); 886 887 return ptu_passed(); 888 } 889 890 static struct ptunit_result find_bad_size(struct iscache_fixture *cfix) 891 { 892 struct pt_section *section; 893 int found, isid; 894 895 section = cfix->section[0]; 896 ptu_ptr(section); 897 898 isid = pt_iscache_add(&cfix->iscache, section, 0ull); 899 ptu_int_gt(isid, 0); 900 901 found = pt_iscache_find(&cfix->iscache, section->filename, 902 section->offset, 0ull, 0ull); 903 ptu_int_eq(found, 0); 904 905 return ptu_passed(); 906 } 907 908 static struct ptunit_result find_bad_laddr(struct iscache_fixture *cfix) 909 { 910 struct pt_section *section; 911 int found, isid; 912 913 section = cfix->section[0]; 914 ptu_ptr(section); 915 916 isid = pt_iscache_add(&cfix->iscache, section, 0ull); 917 ptu_int_gt(isid, 0); 918 919 found = pt_iscache_find(&cfix->iscache, section->filename, 920 section->offset, section->size, 1ull); 921 ptu_int_eq(found, 0); 922 923 return ptu_passed(); 924 } 925 926 static struct ptunit_result lookup(struct iscache_fixture *cfix) 927 { 928 struct pt_section *section; 929 uint64_t laddr; 930 int errcode, isid; 931 932 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull); 933 ptu_int_gt(isid, 0); 934 935 errcode = pt_iscache_lookup(&cfix->iscache, §ion, &laddr, isid); 936 ptu_int_eq(errcode, 0); 937 ptu_ptr_eq(section, cfix->section[0]); 938 ptu_uint_eq(laddr, 0ull); 939 940 errcode = pt_section_put(section); 941 ptu_int_eq(errcode, 0); 942 943 return ptu_passed(); 944 } 945 946 static struct ptunit_result lookup_bad_isid(struct iscache_fixture *cfix) 947 { 948 struct pt_section *section; 949 uint64_t laddr; 950 int errcode, isid; 951 952 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull); 953 ptu_int_gt(isid, 0); 954 955 errcode = pt_iscache_lookup(&cfix->iscache, §ion, &laddr, 0); 956 ptu_int_eq(errcode, -pte_bad_image); 957 958 errcode = pt_iscache_lookup(&cfix->iscache, §ion, &laddr, -isid); 959 ptu_int_eq(errcode, -pte_bad_image); 960 961 errcode = pt_iscache_lookup(&cfix->iscache, §ion, &laddr, isid + 1); 962 ptu_int_eq(errcode, -pte_bad_image); 963 964 return ptu_passed(); 965 } 966 967 static struct ptunit_result clear_empty(struct iscache_fixture *cfix) 968 { 969 int errcode; 970 971 errcode = pt_iscache_clear(&cfix->iscache); 972 ptu_int_eq(errcode, 0); 973 974 return ptu_passed(); 975 } 976 977 static struct ptunit_result clear_find(struct iscache_fixture *cfix) 978 { 979 struct pt_section *section; 980 int errcode, found, isid; 981 982 section = cfix->section[0]; 983 ptu_ptr(section); 984 985 isid = pt_iscache_add(&cfix->iscache, section, 0ull); 986 ptu_int_gt(isid, 0); 987 988 errcode = pt_iscache_clear(&cfix->iscache); 989 ptu_int_eq(errcode, 0); 990 991 992 found = pt_iscache_find(&cfix->iscache, section->filename, 993 section->offset, section->size, 0ull); 994 ptu_int_eq(found, 0); 995 996 return ptu_passed(); 997 } 998 999 static struct ptunit_result clear_lookup(struct iscache_fixture *cfix) 1000 { 1001 struct pt_section *section; 1002 uint64_t laddr; 1003 int errcode, isid; 1004 1005 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull); 1006 ptu_int_gt(isid, 0); 1007 1008 errcode = pt_iscache_clear(&cfix->iscache); 1009 ptu_int_eq(errcode, 0); 1010 1011 errcode = pt_iscache_lookup(&cfix->iscache, §ion, &laddr, isid); 1012 ptu_int_eq(errcode, -pte_bad_image); 1013 1014 return ptu_passed(); 1015 } 1016 1017 static struct ptunit_result add_twice(struct iscache_fixture *cfix) 1018 { 1019 int isid[2]; 1020 1021 isid[0] = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull); 1022 ptu_int_gt(isid[0], 0); 1023 1024 isid[1] = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull); 1025 ptu_int_gt(isid[1], 0); 1026 1027 /* The second add should be ignored. */ 1028 ptu_int_eq(isid[1], isid[0]); 1029 1030 return ptu_passed(); 1031 } 1032 1033 static struct ptunit_result add_same(struct iscache_fixture *cfix) 1034 { 1035 int isid[2]; 1036 1037 isid[0] = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull); 1038 ptu_int_gt(isid[0], 0); 1039 1040 cfix->section[1]->offset = cfix->section[0]->offset; 1041 cfix->section[1]->size = cfix->section[0]->size; 1042 1043 isid[1] = pt_iscache_add(&cfix->iscache, cfix->section[1], 0ull); 1044 ptu_int_gt(isid[1], 0); 1045 1046 /* The second add should be ignored. */ 1047 ptu_int_eq(isid[1], isid[0]); 1048 1049 return ptu_passed(); 1050 } 1051 1052 static struct ptunit_result 1053 add_twice_different_laddr(struct iscache_fixture *cfix) 1054 { 1055 int isid[2]; 1056 1057 isid[0] = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull); 1058 ptu_int_gt(isid[0], 0); 1059 1060 isid[1] = pt_iscache_add(&cfix->iscache, cfix->section[0], 1ull); 1061 ptu_int_gt(isid[1], 0); 1062 1063 /* We must get different identifiers. */ 1064 ptu_int_ne(isid[1], isid[0]); 1065 1066 /* We attach twice and take two references - one for each entry. */ 1067 ptu_int_eq(cfix->section[0]->ucount, 3); 1068 ptu_int_eq(cfix->section[0]->acount, 2); 1069 1070 return ptu_passed(); 1071 } 1072 1073 static struct ptunit_result 1074 add_same_different_laddr(struct iscache_fixture *cfix) 1075 { 1076 int isid[2]; 1077 1078 isid[0] = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull); 1079 ptu_int_gt(isid[0], 0); 1080 1081 cfix->section[1]->offset = cfix->section[0]->offset; 1082 cfix->section[1]->size = cfix->section[0]->size; 1083 1084 isid[1] = pt_iscache_add(&cfix->iscache, cfix->section[1], 1ull); 1085 ptu_int_gt(isid[1], 0); 1086 1087 /* We must get different identifiers. */ 1088 ptu_int_ne(isid[1], isid[0]); 1089 1090 return ptu_passed(); 1091 } 1092 1093 static struct ptunit_result 1094 add_different_same_laddr(struct iscache_fixture *cfix) 1095 { 1096 int isid[2]; 1097 1098 isid[0] = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull); 1099 ptu_int_gt(isid[0], 0); 1100 1101 isid[1] = pt_iscache_add(&cfix->iscache, cfix->section[1], 0ull); 1102 ptu_int_gt(isid[1], 0); 1103 1104 /* We must get different identifiers. */ 1105 ptu_int_ne(isid[1], isid[0]); 1106 1107 return ptu_passed(); 1108 } 1109 1110 static struct ptunit_result add_file_same(struct iscache_fixture *cfix) 1111 { 1112 int isid[2]; 1113 1114 isid[0] = pt_iscache_add_file(&cfix->iscache, "name", 0ull, 1ull, 0ull); 1115 ptu_int_gt(isid[0], 0); 1116 1117 isid[1] = pt_iscache_add_file(&cfix->iscache, "name", 0ull, 1ull, 0ull); 1118 ptu_int_gt(isid[1], 0); 1119 1120 /* The second add should be ignored. */ 1121 ptu_int_eq(isid[1], isid[0]); 1122 1123 return ptu_passed(); 1124 } 1125 1126 static struct ptunit_result 1127 add_file_same_different_laddr(struct iscache_fixture *cfix) 1128 { 1129 int isid[2]; 1130 1131 isid[0] = pt_iscache_add_file(&cfix->iscache, "name", 0ull, 1ull, 0ull); 1132 ptu_int_gt(isid[0], 0); 1133 1134 isid[1] = pt_iscache_add_file(&cfix->iscache, "name", 0ull, 1ull, 1ull); 1135 ptu_int_gt(isid[1], 0); 1136 1137 /* We must get different identifiers. */ 1138 ptu_int_ne(isid[1], isid[0]); 1139 1140 return ptu_passed(); 1141 } 1142 1143 static struct ptunit_result 1144 add_file_different_same_laddr(struct iscache_fixture *cfix) 1145 { 1146 int isid[2]; 1147 1148 isid[0] = pt_iscache_add_file(&cfix->iscache, "name", 0ull, 1ull, 0ull); 1149 ptu_int_gt(isid[0], 0); 1150 1151 isid[1] = pt_iscache_add_file(&cfix->iscache, "name", 1ull, 1ull, 0ull); 1152 ptu_int_gt(isid[1], 0); 1153 1154 /* We must get different identifiers. */ 1155 ptu_int_ne(isid[1], isid[0]); 1156 1157 return ptu_passed(); 1158 } 1159 1160 static struct ptunit_result read(struct iscache_fixture *cfix) 1161 { 1162 uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; 1163 int status, isid; 1164 1165 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1166 ptu_int_gt(isid, 0); 1167 1168 status = pt_iscache_read(&cfix->iscache, buffer, 2ull, isid, 0xa008ull); 1169 ptu_int_eq(status, 2); 1170 ptu_uint_eq(buffer[0], 0x8); 1171 ptu_uint_eq(buffer[1], 0x9); 1172 ptu_uint_eq(buffer[2], 0xcc); 1173 1174 return ptu_passed(); 1175 } 1176 1177 static struct ptunit_result read_truncate(struct iscache_fixture *cfix) 1178 { 1179 uint8_t buffer[] = { 0xcc, 0xcc }; 1180 int status, isid; 1181 1182 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1183 ptu_int_gt(isid, 0); 1184 1185 status = pt_iscache_read(&cfix->iscache, buffer, sizeof(buffer), isid, 1186 0xa00full); 1187 ptu_int_eq(status, 1); 1188 ptu_uint_eq(buffer[0], 0xf); 1189 ptu_uint_eq(buffer[1], 0xcc); 1190 1191 return ptu_passed(); 1192 } 1193 1194 static struct ptunit_result read_bad_vaddr(struct iscache_fixture *cfix) 1195 { 1196 uint8_t buffer[] = { 0xcc }; 1197 int status, isid; 1198 1199 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1200 ptu_int_gt(isid, 0); 1201 1202 status = pt_iscache_read(&cfix->iscache, buffer, 1ull, isid, 0xb000ull); 1203 ptu_int_eq(status, -pte_nomap); 1204 ptu_uint_eq(buffer[0], 0xcc); 1205 1206 return ptu_passed(); 1207 } 1208 1209 static struct ptunit_result read_bad_isid(struct iscache_fixture *cfix) 1210 { 1211 uint8_t buffer[] = { 0xcc }; 1212 int status, isid; 1213 1214 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1215 ptu_int_gt(isid, 0); 1216 1217 status = pt_iscache_read(&cfix->iscache, buffer, 1ull, isid + 1, 1218 0xa000ull); 1219 ptu_int_eq(status, -pte_bad_image); 1220 ptu_uint_eq(buffer[0], 0xcc); 1221 1222 return ptu_passed(); 1223 } 1224 1225 static struct ptunit_result lru_map(struct iscache_fixture *cfix) 1226 { 1227 int status, isid; 1228 1229 cfix->iscache.limit = cfix->section[0]->size; 1230 ptu_uint_eq(cfix->iscache.used, 0ull); 1231 ptu_null(cfix->iscache.lru); 1232 1233 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1234 ptu_int_gt(isid, 0); 1235 1236 status = pt_section_map(cfix->section[0]); 1237 ptu_int_eq(status, 0); 1238 1239 status = pt_section_unmap(cfix->section[0]); 1240 ptu_int_eq(status, 0); 1241 1242 ptu_ptr(cfix->iscache.lru); 1243 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[0]); 1244 ptu_null(cfix->iscache.lru->next); 1245 ptu_uint_eq(cfix->iscache.used, cfix->section[0]->size); 1246 1247 return ptu_passed(); 1248 } 1249 1250 static struct ptunit_result lru_read(struct iscache_fixture *cfix) 1251 { 1252 uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; 1253 int status, isid; 1254 1255 cfix->iscache.limit = cfix->section[0]->size; 1256 ptu_uint_eq(cfix->iscache.used, 0ull); 1257 ptu_null(cfix->iscache.lru); 1258 1259 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1260 ptu_int_gt(isid, 0); 1261 1262 status = pt_iscache_read(&cfix->iscache, buffer, 2ull, isid, 0xa008ull); 1263 ptu_int_eq(status, 2); 1264 1265 ptu_ptr(cfix->iscache.lru); 1266 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[0]); 1267 ptu_null(cfix->iscache.lru->next); 1268 ptu_uint_eq(cfix->iscache.used, cfix->section[0]->size); 1269 1270 return ptu_passed(); 1271 } 1272 1273 static struct ptunit_result lru_map_nodup(struct iscache_fixture *cfix) 1274 { 1275 int status, isid; 1276 1277 cfix->iscache.limit = 2 * cfix->section[0]->size; 1278 ptu_uint_eq(cfix->iscache.used, 0ull); 1279 ptu_null(cfix->iscache.lru); 1280 1281 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1282 ptu_int_gt(isid, 0); 1283 1284 status = pt_section_map(cfix->section[0]); 1285 ptu_int_eq(status, 0); 1286 1287 status = pt_section_unmap(cfix->section[0]); 1288 ptu_int_eq(status, 0); 1289 1290 status = pt_section_map(cfix->section[0]); 1291 ptu_int_eq(status, 0); 1292 1293 status = pt_section_unmap(cfix->section[0]); 1294 ptu_int_eq(status, 0); 1295 1296 ptu_ptr(cfix->iscache.lru); 1297 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[0]); 1298 ptu_null(cfix->iscache.lru->next); 1299 ptu_uint_eq(cfix->iscache.used, cfix->section[0]->size); 1300 1301 return ptu_passed(); 1302 } 1303 1304 static struct ptunit_result lru_map_too_big(struct iscache_fixture *cfix) 1305 { 1306 int status, isid; 1307 1308 cfix->iscache.limit = cfix->section[0]->size - 1; 1309 ptu_uint_eq(cfix->iscache.used, 0ull); 1310 ptu_null(cfix->iscache.lru); 1311 1312 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1313 ptu_int_gt(isid, 0); 1314 1315 status = pt_section_map(cfix->section[0]); 1316 ptu_int_eq(status, 0); 1317 1318 status = pt_section_unmap(cfix->section[0]); 1319 ptu_int_eq(status, 0); 1320 1321 ptu_null(cfix->iscache.lru); 1322 ptu_uint_eq(cfix->iscache.used, 0ull); 1323 1324 return ptu_passed(); 1325 } 1326 1327 static struct ptunit_result lru_map_add_front(struct iscache_fixture *cfix) 1328 { 1329 int status, isid; 1330 1331 cfix->iscache.limit = cfix->section[0]->size + cfix->section[1]->size; 1332 ptu_uint_eq(cfix->iscache.used, 0ull); 1333 ptu_null(cfix->iscache.lru); 1334 1335 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1336 ptu_int_gt(isid, 0); 1337 1338 isid = pt_iscache_add(&cfix->iscache, cfix->section[1], 0xa000ull); 1339 ptu_int_gt(isid, 0); 1340 1341 status = pt_section_map(cfix->section[0]); 1342 ptu_int_eq(status, 0); 1343 1344 status = pt_section_unmap(cfix->section[0]); 1345 ptu_int_eq(status, 0); 1346 1347 status = pt_section_map(cfix->section[1]); 1348 ptu_int_eq(status, 0); 1349 1350 status = pt_section_unmap(cfix->section[1]); 1351 ptu_int_eq(status, 0); 1352 1353 ptu_ptr(cfix->iscache.lru); 1354 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[1]); 1355 ptu_ptr(cfix->iscache.lru->next); 1356 ptu_ptr_eq(cfix->iscache.lru->next->section, cfix->section[0]); 1357 ptu_null(cfix->iscache.lru->next->next); 1358 ptu_uint_eq(cfix->iscache.used, 1359 cfix->section[0]->size + cfix->section[1]->size); 1360 1361 return ptu_passed(); 1362 } 1363 1364 static struct ptunit_result lru_map_move_front(struct iscache_fixture *cfix) 1365 { 1366 int status, isid; 1367 1368 cfix->iscache.limit = cfix->section[0]->size + cfix->section[1]->size; 1369 ptu_uint_eq(cfix->iscache.used, 0ull); 1370 ptu_null(cfix->iscache.lru); 1371 1372 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1373 ptu_int_gt(isid, 0); 1374 1375 isid = pt_iscache_add(&cfix->iscache, cfix->section[1], 0xa000ull); 1376 ptu_int_gt(isid, 0); 1377 1378 status = pt_section_map(cfix->section[0]); 1379 ptu_int_eq(status, 0); 1380 1381 status = pt_section_unmap(cfix->section[0]); 1382 ptu_int_eq(status, 0); 1383 1384 status = pt_section_map(cfix->section[1]); 1385 ptu_int_eq(status, 0); 1386 1387 status = pt_section_unmap(cfix->section[1]); 1388 ptu_int_eq(status, 0); 1389 1390 status = pt_section_map(cfix->section[0]); 1391 ptu_int_eq(status, 0); 1392 1393 status = pt_section_unmap(cfix->section[0]); 1394 ptu_int_eq(status, 0); 1395 1396 ptu_ptr(cfix->iscache.lru); 1397 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[0]); 1398 ptu_ptr(cfix->iscache.lru->next); 1399 ptu_ptr_eq(cfix->iscache.lru->next->section, cfix->section[1]); 1400 ptu_null(cfix->iscache.lru->next->next); 1401 ptu_uint_eq(cfix->iscache.used, 1402 cfix->section[0]->size + cfix->section[1]->size); 1403 1404 return ptu_passed(); 1405 } 1406 1407 static struct ptunit_result lru_map_evict(struct iscache_fixture *cfix) 1408 { 1409 int status, isid; 1410 1411 cfix->iscache.limit = cfix->section[0]->size + 1412 cfix->section[1]->size - 1; 1413 ptu_uint_eq(cfix->iscache.used, 0ull); 1414 ptu_null(cfix->iscache.lru); 1415 1416 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1417 ptu_int_gt(isid, 0); 1418 1419 isid = pt_iscache_add(&cfix->iscache, cfix->section[1], 0xa000ull); 1420 ptu_int_gt(isid, 0); 1421 1422 status = pt_section_map(cfix->section[0]); 1423 ptu_int_eq(status, 0); 1424 1425 status = pt_section_unmap(cfix->section[0]); 1426 ptu_int_eq(status, 0); 1427 1428 status = pt_section_map(cfix->section[1]); 1429 ptu_int_eq(status, 0); 1430 1431 status = pt_section_unmap(cfix->section[1]); 1432 ptu_int_eq(status, 0); 1433 1434 ptu_ptr(cfix->iscache.lru); 1435 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[1]); 1436 ptu_null(cfix->iscache.lru->next); 1437 ptu_uint_eq(cfix->iscache.used, cfix->section[1]->size); 1438 1439 return ptu_passed(); 1440 } 1441 1442 static struct ptunit_result lru_bcache_evict(struct iscache_fixture *cfix) 1443 { 1444 int status, isid; 1445 1446 cfix->iscache.limit = 4 * cfix->section[0]->size + 1447 cfix->section[1]->size - 1; 1448 ptu_uint_eq(cfix->iscache.used, 0ull); 1449 ptu_null(cfix->iscache.lru); 1450 1451 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1452 ptu_int_gt(isid, 0); 1453 1454 isid = pt_iscache_add(&cfix->iscache, cfix->section[1], 0xa000ull); 1455 ptu_int_gt(isid, 0); 1456 1457 status = pt_section_map(cfix->section[0]); 1458 ptu_int_eq(status, 0); 1459 1460 status = pt_section_unmap(cfix->section[0]); 1461 ptu_int_eq(status, 0); 1462 1463 status = pt_section_map(cfix->section[1]); 1464 ptu_int_eq(status, 0); 1465 1466 status = pt_section_unmap(cfix->section[1]); 1467 ptu_int_eq(status, 0); 1468 1469 status = pt_section_request_bcache(cfix->section[0]); 1470 ptu_int_eq(status, 0); 1471 1472 ptu_ptr(cfix->iscache.lru); 1473 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[0]); 1474 ptu_null(cfix->iscache.lru->next); 1475 ptu_uint_eq(cfix->iscache.used, 4 * cfix->section[0]->size); 1476 1477 return ptu_passed(); 1478 } 1479 1480 static struct ptunit_result lru_bcache_clear(struct iscache_fixture *cfix) 1481 { 1482 int status, isid; 1483 1484 cfix->iscache.limit = cfix->section[0]->size + cfix->section[1]->size; 1485 ptu_uint_eq(cfix->iscache.used, 0ull); 1486 ptu_null(cfix->iscache.lru); 1487 1488 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1489 ptu_int_gt(isid, 0); 1490 1491 isid = pt_iscache_add(&cfix->iscache, cfix->section[1], 0xa000ull); 1492 ptu_int_gt(isid, 0); 1493 1494 status = pt_section_map(cfix->section[0]); 1495 ptu_int_eq(status, 0); 1496 1497 status = pt_section_unmap(cfix->section[0]); 1498 ptu_int_eq(status, 0); 1499 1500 status = pt_section_map(cfix->section[1]); 1501 ptu_int_eq(status, 0); 1502 1503 status = pt_section_unmap(cfix->section[1]); 1504 ptu_int_eq(status, 0); 1505 1506 status = pt_section_request_bcache(cfix->section[0]); 1507 ptu_int_eq(status, 0); 1508 1509 ptu_null(cfix->iscache.lru); 1510 ptu_uint_eq(cfix->iscache.used, 0ull); 1511 1512 return ptu_passed(); 1513 } 1514 1515 static struct ptunit_result lru_limit_evict(struct iscache_fixture *cfix) 1516 { 1517 int status, isid; 1518 1519 cfix->iscache.limit = cfix->section[0]->size + cfix->section[1]->size; 1520 ptu_uint_eq(cfix->iscache.used, 0ull); 1521 ptu_null(cfix->iscache.lru); 1522 1523 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1524 ptu_int_gt(isid, 0); 1525 1526 isid = pt_iscache_add(&cfix->iscache, cfix->section[1], 0xa000ull); 1527 ptu_int_gt(isid, 0); 1528 1529 status = pt_section_map(cfix->section[0]); 1530 ptu_int_eq(status, 0); 1531 1532 status = pt_section_unmap(cfix->section[0]); 1533 ptu_int_eq(status, 0); 1534 1535 status = pt_section_map(cfix->section[1]); 1536 ptu_int_eq(status, 0); 1537 1538 status = pt_section_unmap(cfix->section[1]); 1539 ptu_int_eq(status, 0); 1540 1541 status = pt_iscache_set_limit(&cfix->iscache, 1542 cfix->section[0]->size + 1543 cfix->section[1]->size - 1); 1544 ptu_int_eq(status, 0); 1545 1546 ptu_ptr(cfix->iscache.lru); 1547 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[1]); 1548 ptu_null(cfix->iscache.lru->next); 1549 ptu_uint_eq(cfix->iscache.used, cfix->section[1]->size); 1550 1551 return ptu_passed(); 1552 } 1553 1554 static struct ptunit_result lru_clear(struct iscache_fixture *cfix) 1555 { 1556 int status, isid; 1557 1558 cfix->iscache.limit = cfix->section[0]->size; 1559 ptu_uint_eq(cfix->iscache.used, 0ull); 1560 ptu_null(cfix->iscache.lru); 1561 1562 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull); 1563 ptu_int_gt(isid, 0); 1564 1565 status = pt_section_map(cfix->section[0]); 1566 ptu_int_eq(status, 0); 1567 1568 status = pt_section_unmap(cfix->section[0]); 1569 ptu_int_eq(status, 0); 1570 1571 status = pt_iscache_clear(&cfix->iscache); 1572 ptu_int_eq(status, 0); 1573 1574 ptu_null(cfix->iscache.lru); 1575 ptu_uint_eq(cfix->iscache.used, 0ull); 1576 1577 return ptu_passed(); 1578 } 1579 1580 static int worker_add(void *arg) 1581 { 1582 struct iscache_fixture *cfix; 1583 int it; 1584 1585 cfix = arg; 1586 if (!cfix) 1587 return -pte_internal; 1588 1589 for (it = 0; it < num_iterations; ++it) { 1590 uint64_t laddr; 1591 int sec; 1592 1593 laddr = 0x1000ull * (it % 23); 1594 1595 for (sec = 0; sec < num_sections; ++sec) { 1596 struct pt_section *section; 1597 uint64_t addr; 1598 int isid, errcode; 1599 1600 isid = pt_iscache_add(&cfix->iscache, 1601 cfix->section[sec], laddr); 1602 if (isid < 0) 1603 return isid; 1604 1605 errcode = pt_iscache_lookup(&cfix->iscache, §ion, 1606 &addr, isid); 1607 if (errcode < 0) 1608 return errcode; 1609 1610 if (laddr != addr) 1611 return -pte_noip; 1612 1613 /* We may not get the image we added but the image we 1614 * get must have similar attributes. 1615 * 1616 * We're using the same filename string literal for all 1617 * sections, though. 1618 */ 1619 if (section->offset != cfix->section[sec]->offset) 1620 return -pte_bad_image; 1621 1622 if (section->size != cfix->section[sec]->size) 1623 return -pte_bad_image; 1624 1625 errcode = pt_section_put(section); 1626 if (errcode < 0) 1627 return errcode; 1628 } 1629 } 1630 1631 return 0; 1632 } 1633 1634 static int worker_add_file(void *arg) 1635 { 1636 struct iscache_fixture *cfix; 1637 int it; 1638 1639 cfix = arg; 1640 if (!cfix) 1641 return -pte_internal; 1642 1643 for (it = 0; it < num_iterations; ++it) { 1644 uint64_t offset, size, laddr; 1645 int sec; 1646 1647 offset = it % 7 == 0 ? 0x1000 : 0x2000; 1648 size = it % 5 == 0 ? 0x1000 : 0x2000; 1649 laddr = it % 3 == 0 ? 0x1000 : 0x2000; 1650 1651 for (sec = 0; sec < num_sections; ++sec) { 1652 struct pt_section *section; 1653 uint64_t addr; 1654 int isid, errcode; 1655 1656 isid = pt_iscache_add_file(&cfix->iscache, "name", 1657 offset, size, laddr); 1658 if (isid < 0) 1659 return isid; 1660 1661 errcode = pt_iscache_lookup(&cfix->iscache, §ion, 1662 &addr, isid); 1663 if (errcode < 0) 1664 return errcode; 1665 1666 if (laddr != addr) 1667 return -pte_noip; 1668 1669 if (section->offset != offset) 1670 return -pte_bad_image; 1671 1672 if (section->size != size) 1673 return -pte_bad_image; 1674 1675 errcode = pt_section_put(section); 1676 if (errcode < 0) 1677 return errcode; 1678 } 1679 } 1680 1681 return 0; 1682 } 1683 1684 static int worker_map(void *arg) 1685 { 1686 struct iscache_fixture *cfix; 1687 int it, sec, status; 1688 1689 cfix = arg; 1690 if (!cfix) 1691 return -pte_internal; 1692 1693 for (it = 0; it < num_iterations; ++it) { 1694 for (sec = 0; sec < num_sections; ++sec) { 1695 1696 status = pt_section_map(cfix->section[sec]); 1697 if (status < 0) 1698 return status; 1699 1700 status = pt_section_unmap(cfix->section[sec]); 1701 if (status < 0) 1702 return status; 1703 } 1704 } 1705 1706 return 0; 1707 } 1708 1709 static int worker_map_limit(void *arg) 1710 { 1711 struct iscache_fixture *cfix; 1712 uint64_t limits[] = { 0x8000, 0x3000, 0x12000, 0x0 }, limit; 1713 int it, sec, errcode, lim; 1714 1715 cfix = arg; 1716 if (!cfix) 1717 return -pte_internal; 1718 1719 lim = 0; 1720 for (it = 0; it < num_iterations; ++it) { 1721 for (sec = 0; sec < num_sections; ++sec) { 1722 1723 errcode = pt_section_map(cfix->section[sec]); 1724 if (errcode < 0) 1725 return errcode; 1726 1727 errcode = pt_section_unmap(cfix->section[sec]); 1728 if (errcode < 0) 1729 return errcode; 1730 } 1731 1732 if (it % 23 != 0) 1733 continue; 1734 1735 limit = limits[lim++]; 1736 lim %= sizeof(limits) / sizeof(*limits); 1737 1738 errcode = pt_iscache_set_limit(&cfix->iscache, limit); 1739 if (errcode < 0) 1740 return errcode; 1741 } 1742 1743 return 0; 1744 } 1745 1746 static int worker_map_bcache(void *arg) 1747 { 1748 struct iscache_fixture *cfix; 1749 int it, sec, status; 1750 1751 cfix = arg; 1752 if (!cfix) 1753 return -pte_internal; 1754 1755 for (it = 0; it < num_iterations; ++it) { 1756 for (sec = 0; sec < num_sections; ++sec) { 1757 struct pt_section *section; 1758 1759 section = cfix->section[sec]; 1760 1761 status = pt_section_map(section); 1762 if (status < 0) 1763 return status; 1764 1765 if (it % 13 == 0) { 1766 status = pt_section_request_bcache(section); 1767 if (status < 0) { 1768 (void) pt_section_unmap(section); 1769 return status; 1770 } 1771 } 1772 1773 status = pt_section_unmap(section); 1774 if (status < 0) 1775 return status; 1776 } 1777 } 1778 1779 return 0; 1780 } 1781 1782 static int worker_add_map(void *arg) 1783 { 1784 struct iscache_fixture *cfix; 1785 struct pt_section *section; 1786 int it; 1787 1788 cfix = arg; 1789 if (!cfix) 1790 return -pte_internal; 1791 1792 section = cfix->section[0]; 1793 for (it = 0; it < num_iterations; ++it) { 1794 uint64_t laddr; 1795 int isid, errcode; 1796 1797 laddr = (uint64_t) it << 3; 1798 1799 isid = pt_iscache_add(&cfix->iscache, section, laddr); 1800 if (isid < 0) 1801 return isid; 1802 1803 errcode = pt_section_map(section); 1804 if (errcode < 0) 1805 return errcode; 1806 1807 errcode = pt_section_unmap(section); 1808 if (errcode < 0) 1809 return errcode; 1810 } 1811 1812 return 0; 1813 } 1814 1815 static int worker_add_clear(void *arg) 1816 { 1817 struct iscache_fixture *cfix; 1818 struct pt_section *section; 1819 int it; 1820 1821 cfix = arg; 1822 if (!cfix) 1823 return -pte_internal; 1824 1825 section = cfix->section[0]; 1826 for (it = 0; it < num_iterations; ++it) { 1827 uint64_t laddr; 1828 int isid, errcode; 1829 1830 laddr = (uint64_t) it << 3; 1831 1832 isid = pt_iscache_add(&cfix->iscache, section, laddr); 1833 if (isid < 0) 1834 return isid; 1835 1836 errcode = pt_iscache_clear(&cfix->iscache); 1837 if (errcode < 0) 1838 return errcode; 1839 } 1840 1841 return 0; 1842 } 1843 1844 static int worker_add_file_map(void *arg) 1845 { 1846 struct iscache_fixture *cfix; 1847 int it; 1848 1849 cfix = arg; 1850 if (!cfix) 1851 return -pte_internal; 1852 1853 for (it = 0; it < num_iterations; ++it) { 1854 struct pt_section *section; 1855 uint64_t offset, size, laddr, addr; 1856 int isid, errcode; 1857 1858 offset = it % 7 < 4 ? 0x1000 : 0x2000; 1859 size = it % 5 < 3 ? 0x1000 : 0x2000; 1860 laddr = it % 3 < 2 ? 0x1000 : 0x2000; 1861 1862 isid = pt_iscache_add_file(&cfix->iscache, "name", 1863 offset, size, laddr); 1864 if (isid < 0) 1865 return isid; 1866 1867 errcode = pt_iscache_lookup(&cfix->iscache, §ion, 1868 &addr, isid); 1869 if (errcode < 0) 1870 return errcode; 1871 1872 if (addr != laddr) 1873 return -pte_internal; 1874 1875 errcode = pt_section_map(section); 1876 if (errcode < 0) 1877 return errcode; 1878 1879 errcode = pt_section_unmap(section); 1880 if (errcode < 0) 1881 return errcode; 1882 } 1883 1884 return 0; 1885 } 1886 1887 static int worker_add_file_clear(void *arg) 1888 { 1889 struct iscache_fixture *cfix; 1890 int it; 1891 1892 cfix = arg; 1893 if (!cfix) 1894 return -pte_internal; 1895 1896 for (it = 0; it < num_iterations; ++it) { 1897 uint64_t offset, size, laddr; 1898 int isid, errcode; 1899 1900 offset = it % 7 < 4 ? 0x1000 : 0x2000; 1901 size = it % 5 < 3 ? 0x1000 : 0x2000; 1902 laddr = it % 3 < 2 ? 0x1000 : 0x2000; 1903 1904 isid = pt_iscache_add_file(&cfix->iscache, "name", 1905 offset, size, laddr); 1906 if (isid < 0) 1907 return isid; 1908 1909 if (it % 11 < 9) 1910 continue; 1911 1912 errcode = pt_iscache_clear(&cfix->iscache); 1913 if (errcode < 0) 1914 return errcode; 1915 } 1916 1917 return 0; 1918 } 1919 1920 static struct ptunit_result stress(struct iscache_fixture *cfix, 1921 int (*worker)(void *)) 1922 { 1923 int errcode; 1924 1925 #if defined(FEATURE_THREADS) 1926 { 1927 int thrd; 1928 1929 for (thrd = 0; thrd < num_threads; ++thrd) 1930 ptu_test(ptunit_thrd_create, &cfix->thrd, worker, cfix); 1931 } 1932 #endif /* defined(FEATURE_THREADS) */ 1933 1934 errcode = worker(cfix); 1935 ptu_int_eq(errcode, 0); 1936 1937 return ptu_passed(); 1938 } 1939 int main(int argc, char **argv) 1940 { 1941 struct iscache_fixture cfix, dfix, sfix; 1942 struct ptunit_suite suite; 1943 1944 cfix.init = cfix_init; 1945 cfix.fini = cfix_fini; 1946 1947 dfix.init = dfix_init; 1948 dfix.fini = cfix_fini; 1949 1950 sfix.init = sfix_init; 1951 sfix.fini = cfix_fini; 1952 1953 suite = ptunit_mk_suite(argc, argv); 1954 1955 ptu_run(suite, init_null); 1956 ptu_run(suite, fini_null); 1957 ptu_run(suite, name_null); 1958 ptu_run(suite, add_null); 1959 ptu_run(suite, find_null); 1960 ptu_run(suite, lookup_null); 1961 ptu_run(suite, clear_null); 1962 ptu_run(suite, free_null); 1963 ptu_run(suite, add_file_null); 1964 ptu_run(suite, read_null); 1965 1966 ptu_run_f(suite, name, dfix); 1967 ptu_run_f(suite, name_none, dfix); 1968 1969 ptu_run_f(suite, init_fini, cfix); 1970 ptu_run_f(suite, add, cfix); 1971 ptu_run_f(suite, add_no_name, cfix); 1972 ptu_run_f(suite, add_file, cfix); 1973 1974 ptu_run_f(suite, find, cfix); 1975 ptu_run_f(suite, find_empty, cfix); 1976 ptu_run_f(suite, find_bad_filename, cfix); 1977 ptu_run_f(suite, find_null_filename, cfix); 1978 ptu_run_f(suite, find_bad_offset, cfix); 1979 ptu_run_f(suite, find_bad_size, cfix); 1980 ptu_run_f(suite, find_bad_laddr, cfix); 1981 1982 ptu_run_f(suite, lookup, cfix); 1983 ptu_run_f(suite, lookup_bad_isid, cfix); 1984 1985 ptu_run_f(suite, clear_empty, cfix); 1986 ptu_run_f(suite, clear_find, cfix); 1987 ptu_run_f(suite, clear_lookup, cfix); 1988 1989 ptu_run_f(suite, add_twice, cfix); 1990 ptu_run_f(suite, add_same, cfix); 1991 ptu_run_f(suite, add_twice_different_laddr, cfix); 1992 ptu_run_f(suite, add_same_different_laddr, cfix); 1993 ptu_run_f(suite, add_different_same_laddr, cfix); 1994 1995 ptu_run_f(suite, add_file_same, cfix); 1996 ptu_run_f(suite, add_file_same_different_laddr, cfix); 1997 ptu_run_f(suite, add_file_different_same_laddr, cfix); 1998 1999 ptu_run_f(suite, read, cfix); 2000 ptu_run_f(suite, read_truncate, cfix); 2001 ptu_run_f(suite, read_bad_vaddr, cfix); 2002 ptu_run_f(suite, read_bad_isid, cfix); 2003 2004 ptu_run_f(suite, lru_map, cfix); 2005 ptu_run_f(suite, lru_read, cfix); 2006 ptu_run_f(suite, lru_map_nodup, cfix); 2007 ptu_run_f(suite, lru_map_too_big, cfix); 2008 ptu_run_f(suite, lru_map_add_front, cfix); 2009 ptu_run_f(suite, lru_map_move_front, cfix); 2010 ptu_run_f(suite, lru_map_evict, cfix); 2011 ptu_run_f(suite, lru_limit_evict, cfix); 2012 ptu_run_f(suite, lru_bcache_evict, cfix); 2013 ptu_run_f(suite, lru_bcache_clear, cfix); 2014 ptu_run_f(suite, lru_clear, cfix); 2015 2016 ptu_run_fp(suite, stress, cfix, worker_add); 2017 ptu_run_fp(suite, stress, cfix, worker_add_file); 2018 ptu_run_fp(suite, stress, sfix, worker_map); 2019 ptu_run_fp(suite, stress, sfix, worker_map_limit); 2020 ptu_run_fp(suite, stress, sfix, worker_map_bcache); 2021 ptu_run_fp(suite, stress, cfix, worker_add_map); 2022 ptu_run_fp(suite, stress, cfix, worker_add_clear); 2023 ptu_run_fp(suite, stress, cfix, worker_add_file_map); 2024 ptu_run_fp(suite, stress, cfix, worker_add_file_clear); 2025 2026 return ptunit_report(&suite); 2027 } 2028