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