1 // SPDX-License-Identifier: GPL-2.0-or-later 2 #include <string.h> 3 #include <linux/memblock.h> 4 #include "basic_api.h" 5 6 #define EXPECTED_MEMBLOCK_REGIONS 128 7 #define FUNC_ADD "memblock_add" 8 #define FUNC_RESERVE "memblock_reserve" 9 #define FUNC_REMOVE "memblock_remove" 10 #define FUNC_FREE "memblock_free" 11 12 static int memblock_initialization_check(void) 13 { 14 PREFIX_PUSH(); 15 16 ASSERT_NE(memblock.memory.regions, NULL); 17 ASSERT_EQ(memblock.memory.cnt, 1); 18 ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS); 19 ASSERT_EQ(strcmp(memblock.memory.name, "memory"), 0); 20 21 ASSERT_NE(memblock.reserved.regions, NULL); 22 ASSERT_EQ(memblock.reserved.cnt, 1); 23 ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS); 24 ASSERT_EQ(strcmp(memblock.reserved.name, "reserved"), 0); 25 26 ASSERT_EQ(memblock.bottom_up, false); 27 ASSERT_EQ(memblock.current_limit, MEMBLOCK_ALLOC_ANYWHERE); 28 29 test_pass_pop(); 30 31 return 0; 32 } 33 34 /* 35 * A simple test that adds a memory block of a specified base address 36 * and size to the collection of available memory regions (memblock.memory). 37 * Expect to create a new entry. The region counter and total memory get 38 * updated. 39 */ 40 static int memblock_add_simple_check(void) 41 { 42 struct memblock_region *rgn; 43 44 rgn = &memblock.memory.regions[0]; 45 46 struct region r = { 47 .base = SZ_1G, 48 .size = SZ_4M 49 }; 50 51 PREFIX_PUSH(); 52 53 reset_memblock_regions(); 54 memblock_add(r.base, r.size); 55 56 ASSERT_EQ(rgn->base, r.base); 57 ASSERT_EQ(rgn->size, r.size); 58 59 ASSERT_EQ(memblock.memory.cnt, 1); 60 ASSERT_EQ(memblock.memory.total_size, r.size); 61 62 test_pass_pop(); 63 64 return 0; 65 } 66 67 /* 68 * A simple test that adds a memory block of a specified base address, size, 69 * NUMA node and memory flags to the collection of available memory regions. 70 * Expect to create a new entry. The region counter and total memory get 71 * updated. 72 */ 73 static int memblock_add_node_simple_check(void) 74 { 75 struct memblock_region *rgn; 76 77 rgn = &memblock.memory.regions[0]; 78 79 struct region r = { 80 .base = SZ_1M, 81 .size = SZ_16M 82 }; 83 84 PREFIX_PUSH(); 85 86 reset_memblock_regions(); 87 memblock_add_node(r.base, r.size, 1, MEMBLOCK_HOTPLUG); 88 89 ASSERT_EQ(rgn->base, r.base); 90 ASSERT_EQ(rgn->size, r.size); 91 #ifdef CONFIG_NUMA 92 ASSERT_EQ(rgn->nid, 1); 93 #endif 94 ASSERT_EQ(rgn->flags, MEMBLOCK_HOTPLUG); 95 96 ASSERT_EQ(memblock.memory.cnt, 1); 97 ASSERT_EQ(memblock.memory.total_size, r.size); 98 99 test_pass_pop(); 100 101 return 0; 102 } 103 104 /* 105 * A test that tries to add two memory blocks that don't overlap with one 106 * another: 107 * 108 * | +--------+ +--------+ | 109 * | | r1 | | r2 | | 110 * +--------+--------+--------+--------+--+ 111 * 112 * Expect to add two correctly initialized entries to the collection of 113 * available memory regions (memblock.memory). The total size and 114 * region counter fields get updated. 115 */ 116 static int memblock_add_disjoint_check(void) 117 { 118 struct memblock_region *rgn1, *rgn2; 119 120 rgn1 = &memblock.memory.regions[0]; 121 rgn2 = &memblock.memory.regions[1]; 122 123 struct region r1 = { 124 .base = SZ_1G, 125 .size = SZ_8K 126 }; 127 struct region r2 = { 128 .base = SZ_1G + SZ_16K, 129 .size = SZ_8K 130 }; 131 132 PREFIX_PUSH(); 133 134 reset_memblock_regions(); 135 memblock_add(r1.base, r1.size); 136 memblock_add(r2.base, r2.size); 137 138 ASSERT_EQ(rgn1->base, r1.base); 139 ASSERT_EQ(rgn1->size, r1.size); 140 141 ASSERT_EQ(rgn2->base, r2.base); 142 ASSERT_EQ(rgn2->size, r2.size); 143 144 ASSERT_EQ(memblock.memory.cnt, 2); 145 ASSERT_EQ(memblock.memory.total_size, r1.size + r2.size); 146 147 test_pass_pop(); 148 149 return 0; 150 } 151 152 /* 153 * A test that tries to add two memory blocks r1 and r2, where r2 overlaps 154 * with the beginning of r1 (that is r1.base < r2.base + r2.size): 155 * 156 * | +----+----+------------+ | 157 * | | |r2 | r1 | | 158 * +----+----+----+------------+----------+ 159 * ^ ^ 160 * | | 161 * | r1.base 162 * | 163 * r2.base 164 * 165 * Expect to merge the two entries into one region that starts at r2.base 166 * and has size of two regions minus their intersection. The total size of 167 * the available memory is updated, and the region counter stays the same. 168 */ 169 static int memblock_add_overlap_top_check(void) 170 { 171 struct memblock_region *rgn; 172 phys_addr_t total_size; 173 174 rgn = &memblock.memory.regions[0]; 175 176 struct region r1 = { 177 .base = SZ_512M, 178 .size = SZ_1G 179 }; 180 struct region r2 = { 181 .base = SZ_256M, 182 .size = SZ_512M 183 }; 184 185 PREFIX_PUSH(); 186 187 total_size = (r1.base - r2.base) + r1.size; 188 189 reset_memblock_regions(); 190 memblock_add(r1.base, r1.size); 191 memblock_add(r2.base, r2.size); 192 193 ASSERT_EQ(rgn->base, r2.base); 194 ASSERT_EQ(rgn->size, total_size); 195 196 ASSERT_EQ(memblock.memory.cnt, 1); 197 ASSERT_EQ(memblock.memory.total_size, total_size); 198 199 test_pass_pop(); 200 201 return 0; 202 } 203 204 /* 205 * A test that tries to add two memory blocks r1 and r2, where r2 overlaps 206 * with the end of r1 (that is r2.base < r1.base + r1.size): 207 * 208 * | +--+------+----------+ | 209 * | | | r1 | r2 | | 210 * +--+--+------+----------+--------------+ 211 * ^ ^ 212 * | | 213 * | r2.base 214 * | 215 * r1.base 216 * 217 * Expect to merge the two entries into one region that starts at r1.base 218 * and has size of two regions minus their intersection. The total size of 219 * the available memory is updated, and the region counter stays the same. 220 */ 221 static int memblock_add_overlap_bottom_check(void) 222 { 223 struct memblock_region *rgn; 224 phys_addr_t total_size; 225 226 rgn = &memblock.memory.regions[0]; 227 228 struct region r1 = { 229 .base = SZ_128M, 230 .size = SZ_512M 231 }; 232 struct region r2 = { 233 .base = SZ_256M, 234 .size = SZ_1G 235 }; 236 237 PREFIX_PUSH(); 238 239 total_size = (r2.base - r1.base) + r2.size; 240 241 reset_memblock_regions(); 242 memblock_add(r1.base, r1.size); 243 memblock_add(r2.base, r2.size); 244 245 ASSERT_EQ(rgn->base, r1.base); 246 ASSERT_EQ(rgn->size, total_size); 247 248 ASSERT_EQ(memblock.memory.cnt, 1); 249 ASSERT_EQ(memblock.memory.total_size, total_size); 250 251 test_pass_pop(); 252 253 return 0; 254 } 255 256 /* 257 * A test that tries to add two memory blocks r1 and r2, where r2 is 258 * within the range of r1 (that is r1.base < r2.base && 259 * r2.base + r2.size < r1.base + r1.size): 260 * 261 * | +-------+--+-----------------------+ 262 * | | |r2| r1 | 263 * +---+-------+--+-----------------------+ 264 * ^ 265 * | 266 * r1.base 267 * 268 * Expect to merge two entries into one region that stays the same. 269 * The counter and total size of available memory are not updated. 270 */ 271 static int memblock_add_within_check(void) 272 { 273 struct memblock_region *rgn; 274 275 rgn = &memblock.memory.regions[0]; 276 277 struct region r1 = { 278 .base = SZ_8M, 279 .size = SZ_32M 280 }; 281 struct region r2 = { 282 .base = SZ_16M, 283 .size = SZ_1M 284 }; 285 286 PREFIX_PUSH(); 287 288 reset_memblock_regions(); 289 memblock_add(r1.base, r1.size); 290 memblock_add(r2.base, r2.size); 291 292 ASSERT_EQ(rgn->base, r1.base); 293 ASSERT_EQ(rgn->size, r1.size); 294 295 ASSERT_EQ(memblock.memory.cnt, 1); 296 ASSERT_EQ(memblock.memory.total_size, r1.size); 297 298 test_pass_pop(); 299 300 return 0; 301 } 302 303 /* 304 * A simple test that tries to add the same memory block twice. Expect 305 * the counter and total size of available memory to not be updated. 306 */ 307 static int memblock_add_twice_check(void) 308 { 309 struct region r = { 310 .base = SZ_16K, 311 .size = SZ_2M 312 }; 313 314 PREFIX_PUSH(); 315 316 reset_memblock_regions(); 317 318 memblock_add(r.base, r.size); 319 memblock_add(r.base, r.size); 320 321 ASSERT_EQ(memblock.memory.cnt, 1); 322 ASSERT_EQ(memblock.memory.total_size, r.size); 323 324 test_pass_pop(); 325 326 return 0; 327 } 328 329 static int memblock_add_checks(void) 330 { 331 prefix_reset(); 332 prefix_push(FUNC_ADD); 333 test_print("Running %s tests...\n", FUNC_ADD); 334 335 memblock_add_simple_check(); 336 memblock_add_node_simple_check(); 337 memblock_add_disjoint_check(); 338 memblock_add_overlap_top_check(); 339 memblock_add_overlap_bottom_check(); 340 memblock_add_within_check(); 341 memblock_add_twice_check(); 342 343 prefix_pop(); 344 345 return 0; 346 } 347 348 /* 349 * A simple test that marks a memory block of a specified base address 350 * and size as reserved and to the collection of reserved memory regions 351 * (memblock.reserved). Expect to create a new entry. The region counter 352 * and total memory size are updated. 353 */ 354 static int memblock_reserve_simple_check(void) 355 { 356 struct memblock_region *rgn; 357 358 rgn = &memblock.reserved.regions[0]; 359 360 struct region r = { 361 .base = SZ_2G, 362 .size = SZ_128M 363 }; 364 365 PREFIX_PUSH(); 366 367 reset_memblock_regions(); 368 memblock_reserve(r.base, r.size); 369 370 ASSERT_EQ(rgn->base, r.base); 371 ASSERT_EQ(rgn->size, r.size); 372 373 test_pass_pop(); 374 375 return 0; 376 } 377 378 /* 379 * A test that tries to mark two memory blocks that don't overlap as reserved: 380 * 381 * | +--+ +----------------+ | 382 * | |r1| | r2 | | 383 * +--------+--+------+----------------+--+ 384 * 385 * Expect to add two entries to the collection of reserved memory regions 386 * (memblock.reserved). The total size and region counter for 387 * memblock.reserved are updated. 388 */ 389 static int memblock_reserve_disjoint_check(void) 390 { 391 struct memblock_region *rgn1, *rgn2; 392 393 rgn1 = &memblock.reserved.regions[0]; 394 rgn2 = &memblock.reserved.regions[1]; 395 396 struct region r1 = { 397 .base = SZ_256M, 398 .size = SZ_16M 399 }; 400 struct region r2 = { 401 .base = SZ_512M, 402 .size = SZ_512M 403 }; 404 405 PREFIX_PUSH(); 406 407 reset_memblock_regions(); 408 memblock_reserve(r1.base, r1.size); 409 memblock_reserve(r2.base, r2.size); 410 411 ASSERT_EQ(rgn1->base, r1.base); 412 ASSERT_EQ(rgn1->size, r1.size); 413 414 ASSERT_EQ(rgn2->base, r2.base); 415 ASSERT_EQ(rgn2->size, r2.size); 416 417 ASSERT_EQ(memblock.reserved.cnt, 2); 418 ASSERT_EQ(memblock.reserved.total_size, r1.size + r2.size); 419 420 test_pass_pop(); 421 422 return 0; 423 } 424 425 /* 426 * A test that tries to mark two memory blocks r1 and r2 as reserved, 427 * where r2 overlaps with the beginning of r1 (that is 428 * r1.base < r2.base + r2.size): 429 * 430 * | +--------------+--+--------------+ | 431 * | | r2 | | r1 | | 432 * +--+--------------+--+--------------+--+ 433 * ^ ^ 434 * | | 435 * | r1.base 436 * | 437 * r2.base 438 * 439 * Expect to merge two entries into one region that starts at r2.base and 440 * has size of two regions minus their intersection. The total size of the 441 * reserved memory is updated, and the region counter is not updated. 442 */ 443 static int memblock_reserve_overlap_top_check(void) 444 { 445 struct memblock_region *rgn; 446 phys_addr_t total_size; 447 448 rgn = &memblock.reserved.regions[0]; 449 450 struct region r1 = { 451 .base = SZ_1G, 452 .size = SZ_1G 453 }; 454 struct region r2 = { 455 .base = SZ_128M, 456 .size = SZ_1G 457 }; 458 459 PREFIX_PUSH(); 460 461 total_size = (r1.base - r2.base) + r1.size; 462 463 reset_memblock_regions(); 464 memblock_reserve(r1.base, r1.size); 465 memblock_reserve(r2.base, r2.size); 466 467 ASSERT_EQ(rgn->base, r2.base); 468 ASSERT_EQ(rgn->size, total_size); 469 470 ASSERT_EQ(memblock.reserved.cnt, 1); 471 ASSERT_EQ(memblock.reserved.total_size, total_size); 472 473 test_pass_pop(); 474 475 return 0; 476 } 477 478 /* 479 * A test that tries to mark two memory blocks r1 and r2 as reserved, 480 * where r2 overlaps with the end of r1 (that is 481 * r2.base < r1.base + r1.size): 482 * 483 * | +--------------+--+--------------+ | 484 * | | r1 | | r2 | | 485 * +--+--------------+--+--------------+--+ 486 * ^ ^ 487 * | | 488 * | r2.base 489 * | 490 * r1.base 491 * 492 * Expect to merge two entries into one region that starts at r1.base and 493 * has size of two regions minus their intersection. The total size of the 494 * reserved memory is updated, and the region counter is not updated. 495 */ 496 static int memblock_reserve_overlap_bottom_check(void) 497 { 498 struct memblock_region *rgn; 499 phys_addr_t total_size; 500 501 rgn = &memblock.reserved.regions[0]; 502 503 struct region r1 = { 504 .base = SZ_2K, 505 .size = SZ_128K 506 }; 507 struct region r2 = { 508 .base = SZ_128K, 509 .size = SZ_128K 510 }; 511 512 PREFIX_PUSH(); 513 514 total_size = (r2.base - r1.base) + r2.size; 515 516 reset_memblock_regions(); 517 memblock_reserve(r1.base, r1.size); 518 memblock_reserve(r2.base, r2.size); 519 520 ASSERT_EQ(rgn->base, r1.base); 521 ASSERT_EQ(rgn->size, total_size); 522 523 ASSERT_EQ(memblock.reserved.cnt, 1); 524 ASSERT_EQ(memblock.reserved.total_size, total_size); 525 526 test_pass_pop(); 527 528 return 0; 529 } 530 531 /* 532 * A test that tries to mark two memory blocks r1 and r2 as reserved, 533 * where r2 is within the range of r1 (that is 534 * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)): 535 * 536 * | +-----+--+---------------------------| 537 * | | |r2| r1 | 538 * +-+-----+--+---------------------------+ 539 * ^ ^ 540 * | | 541 * | r2.base 542 * | 543 * r1.base 544 * 545 * Expect to merge two entries into one region that stays the same. The 546 * counter and total size of available memory are not updated. 547 */ 548 static int memblock_reserve_within_check(void) 549 { 550 struct memblock_region *rgn; 551 552 rgn = &memblock.reserved.regions[0]; 553 554 struct region r1 = { 555 .base = SZ_1M, 556 .size = SZ_8M 557 }; 558 struct region r2 = { 559 .base = SZ_2M, 560 .size = SZ_64K 561 }; 562 563 PREFIX_PUSH(); 564 565 reset_memblock_regions(); 566 memblock_reserve(r1.base, r1.size); 567 memblock_reserve(r2.base, r2.size); 568 569 ASSERT_EQ(rgn->base, r1.base); 570 ASSERT_EQ(rgn->size, r1.size); 571 572 ASSERT_EQ(memblock.reserved.cnt, 1); 573 ASSERT_EQ(memblock.reserved.total_size, r1.size); 574 575 test_pass_pop(); 576 577 return 0; 578 } 579 580 /* 581 * A simple test that tries to reserve the same memory block twice. 582 * Expect the region counter and total size of reserved memory to not 583 * be updated. 584 */ 585 static int memblock_reserve_twice_check(void) 586 { 587 struct region r = { 588 .base = SZ_16K, 589 .size = SZ_2M 590 }; 591 592 PREFIX_PUSH(); 593 594 reset_memblock_regions(); 595 596 memblock_reserve(r.base, r.size); 597 memblock_reserve(r.base, r.size); 598 599 ASSERT_EQ(memblock.reserved.cnt, 1); 600 ASSERT_EQ(memblock.reserved.total_size, r.size); 601 602 test_pass_pop(); 603 604 return 0; 605 } 606 607 static int memblock_reserve_checks(void) 608 { 609 prefix_reset(); 610 prefix_push(FUNC_RESERVE); 611 test_print("Running %s tests...\n", FUNC_RESERVE); 612 613 memblock_reserve_simple_check(); 614 memblock_reserve_disjoint_check(); 615 memblock_reserve_overlap_top_check(); 616 memblock_reserve_overlap_bottom_check(); 617 memblock_reserve_within_check(); 618 memblock_reserve_twice_check(); 619 620 prefix_pop(); 621 622 return 0; 623 } 624 625 /* 626 * A simple test that tries to remove a region r1 from the array of 627 * available memory regions. By "removing" a region we mean overwriting it 628 * with the next region r2 in memblock.memory: 629 * 630 * | ...... +----------------+ | 631 * | : r1 : | r2 | | 632 * +--+----+----------+----------------+--+ 633 * ^ 634 * | 635 * rgn.base 636 * 637 * Expect to add two memory blocks r1 and r2 and then remove r1 so that 638 * r2 is the first available region. The region counter and total size 639 * are updated. 640 */ 641 static int memblock_remove_simple_check(void) 642 { 643 struct memblock_region *rgn; 644 645 rgn = &memblock.memory.regions[0]; 646 647 struct region r1 = { 648 .base = SZ_2K, 649 .size = SZ_4K 650 }; 651 struct region r2 = { 652 .base = SZ_128K, 653 .size = SZ_4M 654 }; 655 656 PREFIX_PUSH(); 657 658 reset_memblock_regions(); 659 memblock_add(r1.base, r1.size); 660 memblock_add(r2.base, r2.size); 661 memblock_remove(r1.base, r1.size); 662 663 ASSERT_EQ(rgn->base, r2.base); 664 ASSERT_EQ(rgn->size, r2.size); 665 666 ASSERT_EQ(memblock.memory.cnt, 1); 667 ASSERT_EQ(memblock.memory.total_size, r2.size); 668 669 test_pass_pop(); 670 671 return 0; 672 } 673 674 /* 675 * A test that tries to remove a region r2 that was not registered as 676 * available memory (i.e. has no corresponding entry in memblock.memory): 677 * 678 * +----------------+ 679 * | r2 | 680 * +----------------+ 681 * | +----+ | 682 * | | r1 | | 683 * +--+----+------------------------------+ 684 * ^ 685 * | 686 * rgn.base 687 * 688 * Expect the array, regions counter and total size to not be modified. 689 */ 690 static int memblock_remove_absent_check(void) 691 { 692 struct memblock_region *rgn; 693 694 rgn = &memblock.memory.regions[0]; 695 696 struct region r1 = { 697 .base = SZ_512K, 698 .size = SZ_4M 699 }; 700 struct region r2 = { 701 .base = SZ_64M, 702 .size = SZ_1G 703 }; 704 705 PREFIX_PUSH(); 706 707 reset_memblock_regions(); 708 memblock_add(r1.base, r1.size); 709 memblock_remove(r2.base, r2.size); 710 711 ASSERT_EQ(rgn->base, r1.base); 712 ASSERT_EQ(rgn->size, r1.size); 713 714 ASSERT_EQ(memblock.memory.cnt, 1); 715 ASSERT_EQ(memblock.memory.total_size, r1.size); 716 717 test_pass_pop(); 718 719 return 0; 720 } 721 722 /* 723 * A test that tries to remove a region r2 that overlaps with the 724 * beginning of the already existing entry r1 725 * (that is r1.base < r2.base + r2.size): 726 * 727 * +-----------------+ 728 * | r2 | 729 * +-----------------+ 730 * | .........+--------+ | 731 * | : r1 | rgn | | 732 * +-----------------+--------+--------+--+ 733 * ^ ^ 734 * | | 735 * | rgn.base 736 * r1.base 737 * 738 * Expect that only the intersection of both regions is removed from the 739 * available memory pool. The regions counter and total size are updated. 740 */ 741 static int memblock_remove_overlap_top_check(void) 742 { 743 struct memblock_region *rgn; 744 phys_addr_t r1_end, r2_end, total_size; 745 746 rgn = &memblock.memory.regions[0]; 747 748 struct region r1 = { 749 .base = SZ_32M, 750 .size = SZ_32M 751 }; 752 struct region r2 = { 753 .base = SZ_16M, 754 .size = SZ_32M 755 }; 756 757 PREFIX_PUSH(); 758 759 r1_end = r1.base + r1.size; 760 r2_end = r2.base + r2.size; 761 total_size = r1_end - r2_end; 762 763 reset_memblock_regions(); 764 memblock_add(r1.base, r1.size); 765 memblock_remove(r2.base, r2.size); 766 767 ASSERT_EQ(rgn->base, r1.base + r2.base); 768 ASSERT_EQ(rgn->size, total_size); 769 770 ASSERT_EQ(memblock.memory.cnt, 1); 771 ASSERT_EQ(memblock.memory.total_size, total_size); 772 773 test_pass_pop(); 774 775 return 0; 776 } 777 778 /* 779 * A test that tries to remove a region r2 that overlaps with the end of 780 * the already existing region r1 (that is r2.base < r1.base + r1.size): 781 * 782 * +--------------------------------+ 783 * | r2 | 784 * +--------------------------------+ 785 * | +---+..... | 786 * | |rgn| r1 : | 787 * +-+---+----+---------------------------+ 788 * ^ 789 * | 790 * r1.base 791 * 792 * Expect that only the intersection of both regions is removed from the 793 * available memory pool. The regions counter and total size are updated. 794 */ 795 static int memblock_remove_overlap_bottom_check(void) 796 { 797 struct memblock_region *rgn; 798 phys_addr_t total_size; 799 800 rgn = &memblock.memory.regions[0]; 801 802 struct region r1 = { 803 .base = SZ_2M, 804 .size = SZ_64M 805 }; 806 struct region r2 = { 807 .base = SZ_32M, 808 .size = SZ_256M 809 }; 810 811 PREFIX_PUSH(); 812 813 total_size = r2.base - r1.base; 814 815 reset_memblock_regions(); 816 memblock_add(r1.base, r1.size); 817 memblock_remove(r2.base, r2.size); 818 819 ASSERT_EQ(rgn->base, r1.base); 820 ASSERT_EQ(rgn->size, total_size); 821 822 ASSERT_EQ(memblock.memory.cnt, 1); 823 ASSERT_EQ(memblock.memory.total_size, total_size); 824 825 test_pass_pop(); 826 827 return 0; 828 } 829 830 /* 831 * A test that tries to remove a region r2 that is within the range of 832 * the already existing entry r1 (that is 833 * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)): 834 * 835 * +----+ 836 * | r2 | 837 * +----+ 838 * | +-------------+....+---------------+ | 839 * | | rgn1 | r1 | rgn2 | | 840 * +-+-------------+----+---------------+-+ 841 * ^ 842 * | 843 * r1.base 844 * 845 * Expect that the region is split into two - one that ends at r2.base and 846 * another that starts at r2.base + r2.size, with appropriate sizes. The 847 * region counter and total size are updated. 848 */ 849 static int memblock_remove_within_check(void) 850 { 851 struct memblock_region *rgn1, *rgn2; 852 phys_addr_t r1_size, r2_size, total_size; 853 854 rgn1 = &memblock.memory.regions[0]; 855 rgn2 = &memblock.memory.regions[1]; 856 857 struct region r1 = { 858 .base = SZ_1M, 859 .size = SZ_32M 860 }; 861 struct region r2 = { 862 .base = SZ_16M, 863 .size = SZ_1M 864 }; 865 866 PREFIX_PUSH(); 867 868 r1_size = r2.base - r1.base; 869 r2_size = (r1.base + r1.size) - (r2.base + r2.size); 870 total_size = r1_size + r2_size; 871 872 reset_memblock_regions(); 873 memblock_add(r1.base, r1.size); 874 memblock_remove(r2.base, r2.size); 875 876 ASSERT_EQ(rgn1->base, r1.base); 877 ASSERT_EQ(rgn1->size, r1_size); 878 879 ASSERT_EQ(rgn2->base, r2.base + r2.size); 880 ASSERT_EQ(rgn2->size, r2_size); 881 882 ASSERT_EQ(memblock.memory.cnt, 2); 883 ASSERT_EQ(memblock.memory.total_size, total_size); 884 885 test_pass_pop(); 886 887 return 0; 888 } 889 890 static int memblock_remove_checks(void) 891 { 892 prefix_reset(); 893 prefix_push(FUNC_REMOVE); 894 test_print("Running %s tests...\n", FUNC_REMOVE); 895 896 memblock_remove_simple_check(); 897 memblock_remove_absent_check(); 898 memblock_remove_overlap_top_check(); 899 memblock_remove_overlap_bottom_check(); 900 memblock_remove_within_check(); 901 902 prefix_pop(); 903 904 return 0; 905 } 906 907 /* 908 * A simple test that tries to free a memory block r1 that was marked 909 * earlier as reserved. By "freeing" a region we mean overwriting it with 910 * the next entry r2 in memblock.reserved: 911 * 912 * | ...... +----+ | 913 * | : r1 : | r2 | | 914 * +--------------+----+-----------+----+-+ 915 * ^ 916 * | 917 * rgn.base 918 * 919 * Expect to reserve two memory regions and then erase r1 region with the 920 * value of r2. The region counter and total size are updated. 921 */ 922 static int memblock_free_simple_check(void) 923 { 924 struct memblock_region *rgn; 925 926 rgn = &memblock.reserved.regions[0]; 927 928 struct region r1 = { 929 .base = SZ_4M, 930 .size = SZ_1M 931 }; 932 struct region r2 = { 933 .base = SZ_8M, 934 .size = SZ_1M 935 }; 936 937 PREFIX_PUSH(); 938 939 reset_memblock_regions(); 940 memblock_reserve(r1.base, r1.size); 941 memblock_reserve(r2.base, r2.size); 942 memblock_free((void *)r1.base, r1.size); 943 944 ASSERT_EQ(rgn->base, r2.base); 945 ASSERT_EQ(rgn->size, r2.size); 946 947 ASSERT_EQ(memblock.reserved.cnt, 1); 948 ASSERT_EQ(memblock.reserved.total_size, r2.size); 949 950 test_pass_pop(); 951 952 return 0; 953 } 954 955 /* 956 * A test that tries to free a region r2 that was not marked as reserved 957 * (i.e. has no corresponding entry in memblock.reserved): 958 * 959 * +----------------+ 960 * | r2 | 961 * +----------------+ 962 * | +----+ | 963 * | | r1 | | 964 * +--+----+------------------------------+ 965 * ^ 966 * | 967 * rgn.base 968 * 969 * The array, regions counter and total size are not modified. 970 */ 971 static int memblock_free_absent_check(void) 972 { 973 struct memblock_region *rgn; 974 975 rgn = &memblock.reserved.regions[0]; 976 977 struct region r1 = { 978 .base = SZ_2M, 979 .size = SZ_8K 980 }; 981 struct region r2 = { 982 .base = SZ_16M, 983 .size = SZ_128M 984 }; 985 986 PREFIX_PUSH(); 987 988 reset_memblock_regions(); 989 memblock_reserve(r1.base, r1.size); 990 memblock_free((void *)r2.base, r2.size); 991 992 ASSERT_EQ(rgn->base, r1.base); 993 ASSERT_EQ(rgn->size, r1.size); 994 995 ASSERT_EQ(memblock.reserved.cnt, 1); 996 ASSERT_EQ(memblock.reserved.total_size, r1.size); 997 998 test_pass_pop(); 999 1000 return 0; 1001 } 1002 1003 /* 1004 * A test that tries to free a region r2 that overlaps with the beginning 1005 * of the already existing entry r1 (that is r1.base < r2.base + r2.size): 1006 * 1007 * +----+ 1008 * | r2 | 1009 * +----+ 1010 * | ...+--------------+ | 1011 * | : | r1 | | 1012 * +----+--+--------------+---------------+ 1013 * ^ ^ 1014 * | | 1015 * | rgn.base 1016 * | 1017 * r1.base 1018 * 1019 * Expect that only the intersection of both regions is freed. The 1020 * regions counter and total size are updated. 1021 */ 1022 static int memblock_free_overlap_top_check(void) 1023 { 1024 struct memblock_region *rgn; 1025 phys_addr_t total_size; 1026 1027 rgn = &memblock.reserved.regions[0]; 1028 1029 struct region r1 = { 1030 .base = SZ_8M, 1031 .size = SZ_32M 1032 }; 1033 struct region r2 = { 1034 .base = SZ_1M, 1035 .size = SZ_8M 1036 }; 1037 1038 PREFIX_PUSH(); 1039 1040 total_size = (r1.size + r1.base) - (r2.base + r2.size); 1041 1042 reset_memblock_regions(); 1043 memblock_reserve(r1.base, r1.size); 1044 memblock_free((void *)r2.base, r2.size); 1045 1046 ASSERT_EQ(rgn->base, r2.base + r2.size); 1047 ASSERT_EQ(rgn->size, total_size); 1048 1049 ASSERT_EQ(memblock.reserved.cnt, 1); 1050 ASSERT_EQ(memblock.reserved.total_size, total_size); 1051 1052 test_pass_pop(); 1053 1054 return 0; 1055 } 1056 1057 /* 1058 * A test that tries to free a region r2 that overlaps with the end of 1059 * the already existing entry r1 (that is r2.base < r1.base + r1.size): 1060 * 1061 * +----------------+ 1062 * | r2 | 1063 * +----------------+ 1064 * | +-----------+..... | 1065 * | | r1 | : | 1066 * +----+-----------+----+----------------+ 1067 * 1068 * Expect that only the intersection of both regions is freed. The 1069 * regions counter and total size are updated. 1070 */ 1071 static int memblock_free_overlap_bottom_check(void) 1072 { 1073 struct memblock_region *rgn; 1074 phys_addr_t total_size; 1075 1076 rgn = &memblock.reserved.regions[0]; 1077 1078 struct region r1 = { 1079 .base = SZ_8M, 1080 .size = SZ_32M 1081 }; 1082 struct region r2 = { 1083 .base = SZ_32M, 1084 .size = SZ_32M 1085 }; 1086 1087 PREFIX_PUSH(); 1088 1089 total_size = r2.base - r1.base; 1090 1091 reset_memblock_regions(); 1092 memblock_reserve(r1.base, r1.size); 1093 memblock_free((void *)r2.base, r2.size); 1094 1095 ASSERT_EQ(rgn->base, r1.base); 1096 ASSERT_EQ(rgn->size, total_size); 1097 1098 ASSERT_EQ(memblock.reserved.cnt, 1); 1099 ASSERT_EQ(memblock.reserved.total_size, total_size); 1100 1101 test_pass_pop(); 1102 1103 return 0; 1104 } 1105 1106 /* 1107 * A test that tries to free a region r2 that is within the range of the 1108 * already existing entry r1 (that is 1109 * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)): 1110 * 1111 * +----+ 1112 * | r2 | 1113 * +----+ 1114 * | +------------+....+---------------+ 1115 * | | rgn1 | r1 | rgn2 | 1116 * +----+------------+----+---------------+ 1117 * ^ 1118 * | 1119 * r1.base 1120 * 1121 * Expect that the region is split into two - one that ends at r2.base and 1122 * another that starts at r2.base + r2.size, with appropriate sizes. The 1123 * region counter and total size fields are updated. 1124 */ 1125 static int memblock_free_within_check(void) 1126 { 1127 struct memblock_region *rgn1, *rgn2; 1128 phys_addr_t r1_size, r2_size, total_size; 1129 1130 rgn1 = &memblock.reserved.regions[0]; 1131 rgn2 = &memblock.reserved.regions[1]; 1132 1133 struct region r1 = { 1134 .base = SZ_1M, 1135 .size = SZ_8M 1136 }; 1137 struct region r2 = { 1138 .base = SZ_4M, 1139 .size = SZ_1M 1140 }; 1141 1142 PREFIX_PUSH(); 1143 1144 r1_size = r2.base - r1.base; 1145 r2_size = (r1.base + r1.size) - (r2.base + r2.size); 1146 total_size = r1_size + r2_size; 1147 1148 reset_memblock_regions(); 1149 memblock_reserve(r1.base, r1.size); 1150 memblock_free((void *)r2.base, r2.size); 1151 1152 ASSERT_EQ(rgn1->base, r1.base); 1153 ASSERT_EQ(rgn1->size, r1_size); 1154 1155 ASSERT_EQ(rgn2->base, r2.base + r2.size); 1156 ASSERT_EQ(rgn2->size, r2_size); 1157 1158 ASSERT_EQ(memblock.reserved.cnt, 2); 1159 ASSERT_EQ(memblock.reserved.total_size, total_size); 1160 1161 test_pass_pop(); 1162 1163 return 0; 1164 } 1165 1166 static int memblock_free_checks(void) 1167 { 1168 prefix_reset(); 1169 prefix_push(FUNC_FREE); 1170 test_print("Running %s tests...\n", FUNC_FREE); 1171 1172 memblock_free_simple_check(); 1173 memblock_free_absent_check(); 1174 memblock_free_overlap_top_check(); 1175 memblock_free_overlap_bottom_check(); 1176 memblock_free_within_check(); 1177 1178 prefix_pop(); 1179 1180 return 0; 1181 } 1182 1183 int memblock_basic_checks(void) 1184 { 1185 memblock_initialization_check(); 1186 memblock_add_checks(); 1187 memblock_reserve_checks(); 1188 memblock_remove_checks(); 1189 memblock_free_checks(); 1190 1191 return 0; 1192 } 1193