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