1 // SPDX-License-Identifier: GPL-2.0-or-later 2 #include <string.h> 3 #include <linux/memblock.h> 4 #include <linux/sizes.h> 5 #include "basic_api.h" 6 7 #define EXPECTED_MEMBLOCK_REGIONS 128 8 9 static int memblock_initialization_check(void) 10 { 11 reset_memblock(); 12 13 assert(memblock.memory.regions); 14 assert(memblock.memory.cnt == 1); 15 assert(memblock.memory.max == EXPECTED_MEMBLOCK_REGIONS); 16 assert(strcmp(memblock.memory.name, "memory") == 0); 17 18 assert(memblock.reserved.regions); 19 assert(memblock.reserved.cnt == 1); 20 assert(memblock.memory.max == EXPECTED_MEMBLOCK_REGIONS); 21 assert(strcmp(memblock.reserved.name, "reserved") == 0); 22 23 assert(!memblock.bottom_up); 24 assert(memblock.current_limit == MEMBLOCK_ALLOC_ANYWHERE); 25 26 return 0; 27 } 28 29 /* 30 * A simple test that adds a memory block of a specified base address 31 * and size to the collection of available memory regions (memblock.memory). 32 * It checks if a new entry was created and if region counter and total memory 33 * were correctly updated. 34 */ 35 static int memblock_add_simple_check(void) 36 { 37 struct memblock_region *rgn; 38 39 rgn = &memblock.memory.regions[0]; 40 41 struct region r = { 42 .base = SZ_1G, 43 .size = SZ_4M 44 }; 45 46 reset_memblock(); 47 memblock_add(r.base, r.size); 48 49 assert(rgn->base == r.base); 50 assert(rgn->size == r.size); 51 52 assert(memblock.memory.cnt == 1); 53 assert(memblock.memory.total_size == r.size); 54 55 return 0; 56 } 57 58 /* 59 * A test that tries to add two memory blocks that don't overlap with one 60 * another. It checks if two correctly initialized entries were added to the 61 * collection of available memory regions (memblock.memory) and if this 62 * change was reflected in memblock.memory's total size and region counter. 63 */ 64 static int memblock_add_disjoint_check(void) 65 { 66 struct memblock_region *rgn1, *rgn2; 67 68 rgn1 = &memblock.memory.regions[0]; 69 rgn2 = &memblock.memory.regions[1]; 70 71 struct region r1 = { 72 .base = SZ_1G, 73 .size = SZ_8K 74 }; 75 struct region r2 = { 76 .base = SZ_1G + SZ_16K, 77 .size = SZ_8K 78 }; 79 80 reset_memblock(); 81 memblock_add(r1.base, r1.size); 82 memblock_add(r2.base, r2.size); 83 84 assert(rgn1->base == r1.base); 85 assert(rgn1->size == r1.size); 86 87 assert(rgn2->base == r2.base); 88 assert(rgn2->size == r2.size); 89 90 assert(memblock.memory.cnt == 2); 91 assert(memblock.memory.total_size == r1.size + r2.size); 92 93 return 0; 94 } 95 96 /* 97 * A test that tries to add two memory blocks, where the second one overlaps 98 * with the beginning of the first entry (that is r1.base < r2.base + r2.size). 99 * After this, it checks if two entries are merged into one region that starts 100 * at r2.base and has size of two regions minus their intersection. It also 101 * verifies the reported total size of the available memory and region counter. 102 */ 103 static int memblock_add_overlap_top_check(void) 104 { 105 struct memblock_region *rgn; 106 phys_addr_t total_size; 107 108 rgn = &memblock.memory.regions[0]; 109 110 struct region r1 = { 111 .base = SZ_512M, 112 .size = SZ_1G 113 }; 114 struct region r2 = { 115 .base = SZ_256M, 116 .size = SZ_512M 117 }; 118 119 total_size = (r1.base - r2.base) + r1.size; 120 121 reset_memblock(); 122 memblock_add(r1.base, r1.size); 123 memblock_add(r2.base, r2.size); 124 125 assert(rgn->base == r2.base); 126 assert(rgn->size == total_size); 127 128 assert(memblock.memory.cnt == 1); 129 assert(memblock.memory.total_size == total_size); 130 131 return 0; 132 } 133 134 /* 135 * A test that tries to add two memory blocks, where the second one overlaps 136 * with the end of the first entry (that is r2.base < r1.base + r1.size). 137 * After this, it checks if two entries are merged into one region that starts 138 * at r1.base and has size of two regions minus their intersection. It verifies 139 * that memblock can still see only one entry and has a correct total size of 140 * the available memory. 141 */ 142 static int memblock_add_overlap_bottom_check(void) 143 { 144 struct memblock_region *rgn; 145 phys_addr_t total_size; 146 147 rgn = &memblock.memory.regions[0]; 148 149 struct region r1 = { 150 .base = SZ_128M, 151 .size = SZ_512M 152 }; 153 struct region r2 = { 154 .base = SZ_256M, 155 .size = SZ_1G 156 }; 157 158 total_size = (r2.base - r1.base) + r2.size; 159 160 reset_memblock(); 161 memblock_add(r1.base, r1.size); 162 memblock_add(r2.base, r2.size); 163 164 assert(rgn->base == r1.base); 165 assert(rgn->size == total_size); 166 167 assert(memblock.memory.cnt == 1); 168 assert(memblock.memory.total_size == total_size); 169 170 return 0; 171 } 172 173 /* 174 * A test that tries to add two memory blocks, where the second one is 175 * within the range of the first entry (that is r1.base < r2.base && 176 * r2.base + r2.size < r1.base + r1.size). It checks if two entries are merged 177 * into one region that stays the same. The counter and total size of available 178 * memory are expected to not be updated. 179 */ 180 static int memblock_add_within_check(void) 181 { 182 struct memblock_region *rgn; 183 184 rgn = &memblock.memory.regions[0]; 185 186 struct region r1 = { 187 .base = SZ_8M, 188 .size = SZ_32M 189 }; 190 struct region r2 = { 191 .base = SZ_16M, 192 .size = SZ_1M 193 }; 194 195 reset_memblock(); 196 memblock_add(r1.base, r1.size); 197 memblock_add(r2.base, r2.size); 198 199 assert(rgn->base == r1.base); 200 assert(rgn->size == r1.size); 201 202 assert(memblock.memory.cnt == 1); 203 assert(memblock.memory.total_size == r1.size); 204 205 return 0; 206 } 207 208 /* 209 * A simple test that tries to add the same memory block twice. The counter 210 * and total size of available memory are expected to not be updated. 211 */ 212 static int memblock_add_twice_check(void) 213 { 214 struct region r = { 215 .base = SZ_16K, 216 .size = SZ_2M 217 }; 218 219 reset_memblock(); 220 221 memblock_add(r.base, r.size); 222 memblock_add(r.base, r.size); 223 224 assert(memblock.memory.cnt == 1); 225 assert(memblock.memory.total_size == r.size); 226 227 return 0; 228 } 229 230 static int memblock_add_checks(void) 231 { 232 memblock_add_simple_check(); 233 memblock_add_disjoint_check(); 234 memblock_add_overlap_top_check(); 235 memblock_add_overlap_bottom_check(); 236 memblock_add_within_check(); 237 memblock_add_twice_check(); 238 239 return 0; 240 } 241 242 /* 243 * A simple test that marks a memory block of a specified base address 244 * and size as reserved and to the collection of reserved memory regions 245 * (memblock.reserved). It checks if a new entry was created and if region 246 * counter and total memory size were correctly updated. 247 */ 248 static int memblock_reserve_simple_check(void) 249 { 250 struct memblock_region *rgn; 251 252 rgn = &memblock.reserved.regions[0]; 253 254 struct region r = { 255 .base = SZ_2G, 256 .size = SZ_128M 257 }; 258 259 reset_memblock(); 260 memblock_reserve(r.base, r.size); 261 262 assert(rgn->base == r.base); 263 assert(rgn->size == r.size); 264 265 return 0; 266 } 267 268 /* 269 * A test that tries to mark two memory blocks that don't overlap as reserved 270 * and checks if two entries were correctly added to the collection of reserved 271 * memory regions (memblock.reserved) and if this change was reflected in 272 * memblock.reserved's total size and region counter. 273 */ 274 static int memblock_reserve_disjoint_check(void) 275 { 276 struct memblock_region *rgn1, *rgn2; 277 278 rgn1 = &memblock.reserved.regions[0]; 279 rgn2 = &memblock.reserved.regions[1]; 280 281 struct region r1 = { 282 .base = SZ_256M, 283 .size = SZ_16M 284 }; 285 struct region r2 = { 286 .base = SZ_512M, 287 .size = SZ_512M 288 }; 289 290 reset_memblock(); 291 memblock_reserve(r1.base, r1.size); 292 memblock_reserve(r2.base, r2.size); 293 294 assert(rgn1->base == r1.base); 295 assert(rgn1->size == r1.size); 296 297 assert(rgn2->base == r2.base); 298 assert(rgn2->size == r2.size); 299 300 assert(memblock.reserved.cnt == 2); 301 assert(memblock.reserved.total_size == r1.size + r2.size); 302 303 return 0; 304 } 305 306 /* 307 * A test that tries to mark two memory blocks as reserved, where the 308 * second one overlaps with the beginning of the first (that is 309 * r1.base < r2.base + r2.size). 310 * It checks if two entries are merged into one region that starts at r2.base 311 * and has size of two regions minus their intersection. The test also verifies 312 * that memblock can still see only one entry and has a correct total size of 313 * the reserved memory. 314 */ 315 static int memblock_reserve_overlap_top_check(void) 316 { 317 struct memblock_region *rgn; 318 phys_addr_t total_size; 319 320 rgn = &memblock.reserved.regions[0]; 321 322 struct region r1 = { 323 .base = SZ_1G, 324 .size = SZ_1G 325 }; 326 struct region r2 = { 327 .base = SZ_128M, 328 .size = SZ_1G 329 }; 330 331 total_size = (r1.base - r2.base) + r1.size; 332 333 reset_memblock(); 334 memblock_reserve(r1.base, r1.size); 335 memblock_reserve(r2.base, r2.size); 336 337 assert(rgn->base == r2.base); 338 assert(rgn->size == total_size); 339 340 assert(memblock.reserved.cnt == 1); 341 assert(memblock.reserved.total_size == total_size); 342 343 return 0; 344 } 345 346 /* 347 * A test that tries to mark two memory blocks as reserved, where the 348 * second one overlaps with the end of the first entry (that is 349 * r2.base < r1.base + r1.size). 350 * It checks if two entries are merged into one region that starts at r1.base 351 * and has size of two regions minus their intersection. It verifies that 352 * memblock can still see only one entry and has a correct total size of the 353 * reserved memory. 354 */ 355 static int memblock_reserve_overlap_bottom_check(void) 356 { 357 struct memblock_region *rgn; 358 phys_addr_t total_size; 359 360 rgn = &memblock.reserved.regions[0]; 361 362 struct region r1 = { 363 .base = SZ_2K, 364 .size = SZ_128K 365 }; 366 struct region r2 = { 367 .base = SZ_128K, 368 .size = SZ_128K 369 }; 370 371 total_size = (r2.base - r1.base) + r2.size; 372 373 reset_memblock(); 374 memblock_reserve(r1.base, r1.size); 375 memblock_reserve(r2.base, r2.size); 376 377 assert(rgn->base == r1.base); 378 assert(rgn->size == total_size); 379 380 assert(memblock.reserved.cnt == 1); 381 assert(memblock.reserved.total_size == total_size); 382 383 return 0; 384 } 385 386 /* 387 * A test that tries to mark two memory blocks as reserved, where the second 388 * one is within the range of the first entry (that is 389 * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)). 390 * It checks if two entries are merged into one region that stays the 391 * same. The counter and total size of available memory are expected to not be 392 * updated. 393 */ 394 static int memblock_reserve_within_check(void) 395 { 396 struct memblock_region *rgn; 397 398 rgn = &memblock.reserved.regions[0]; 399 400 struct region r1 = { 401 .base = SZ_1M, 402 .size = SZ_8M 403 }; 404 struct region r2 = { 405 .base = SZ_2M, 406 .size = SZ_64K 407 }; 408 409 reset_memblock(); 410 memblock_reserve(r1.base, r1.size); 411 memblock_reserve(r2.base, r2.size); 412 413 assert(rgn->base == r1.base); 414 assert(rgn->size == r1.size); 415 416 assert(memblock.reserved.cnt == 1); 417 assert(memblock.reserved.total_size == r1.size); 418 419 return 0; 420 } 421 422 /* 423 * A simple test that tries to reserve the same memory block twice. 424 * The region counter and total size of reserved memory are expected to not 425 * be updated. 426 */ 427 static int memblock_reserve_twice_check(void) 428 { 429 struct region r = { 430 .base = SZ_16K, 431 .size = SZ_2M 432 }; 433 434 reset_memblock(); 435 436 memblock_reserve(r.base, r.size); 437 memblock_reserve(r.base, r.size); 438 439 assert(memblock.reserved.cnt == 1); 440 assert(memblock.reserved.total_size == r.size); 441 442 return 0; 443 } 444 445 static int memblock_reserve_checks(void) 446 { 447 memblock_reserve_simple_check(); 448 memblock_reserve_disjoint_check(); 449 memblock_reserve_overlap_top_check(); 450 memblock_reserve_overlap_bottom_check(); 451 memblock_reserve_within_check(); 452 memblock_reserve_twice_check(); 453 454 return 0; 455 } 456 457 /* 458 * A simple test that tries to remove the first entry of the array of 459 * available memory regions. By "removing" a region we mean overwriting it 460 * with the next region in memblock.memory. To check this is the case, the 461 * test adds two memory blocks and verifies that the value of the latter 462 * was used to erase r1 region. It also checks if the region counter and 463 * total size were updated to expected values. 464 */ 465 static int memblock_remove_simple_check(void) 466 { 467 struct memblock_region *rgn; 468 469 rgn = &memblock.memory.regions[0]; 470 471 struct region r1 = { 472 .base = SZ_2K, 473 .size = SZ_4K 474 }; 475 struct region r2 = { 476 .base = SZ_128K, 477 .size = SZ_4M 478 }; 479 480 reset_memblock(); 481 memblock_add(r1.base, r1.size); 482 memblock_add(r2.base, r2.size); 483 memblock_remove(r1.base, r1.size); 484 485 assert(rgn->base == r2.base); 486 assert(rgn->size == r2.size); 487 488 assert(memblock.memory.cnt == 1); 489 assert(memblock.memory.total_size == r2.size); 490 491 return 0; 492 } 493 494 /* 495 * A test that tries to remove a region that was not registered as available 496 * memory (i.e. has no corresponding entry in memblock.memory). It verifies 497 * that array, regions counter and total size were not modified. 498 */ 499 static int memblock_remove_absent_check(void) 500 { 501 struct memblock_region *rgn; 502 503 rgn = &memblock.memory.regions[0]; 504 505 struct region r1 = { 506 .base = SZ_512K, 507 .size = SZ_4M 508 }; 509 struct region r2 = { 510 .base = SZ_64M, 511 .size = SZ_1G 512 }; 513 514 reset_memblock(); 515 memblock_add(r1.base, r1.size); 516 memblock_remove(r2.base, r2.size); 517 518 assert(rgn->base == r1.base); 519 assert(rgn->size == r1.size); 520 521 assert(memblock.memory.cnt == 1); 522 assert(memblock.memory.total_size == r1.size); 523 524 return 0; 525 } 526 527 /* 528 * A test that tries to remove a region which overlaps with the beginning of 529 * the already existing entry r1 (that is r1.base < r2.base + r2.size). It 530 * checks if only the intersection of both regions is removed from the available 531 * memory pool. The test also checks if the regions counter and total size are 532 * updated to expected values. 533 */ 534 static int memblock_remove_overlap_top_check(void) 535 { 536 struct memblock_region *rgn; 537 phys_addr_t r1_end, r2_end, total_size; 538 539 rgn = &memblock.memory.regions[0]; 540 541 struct region r1 = { 542 .base = SZ_32M, 543 .size = SZ_32M 544 }; 545 struct region r2 = { 546 .base = SZ_16M, 547 .size = SZ_32M 548 }; 549 550 r1_end = r1.base + r1.size; 551 r2_end = r2.base + r2.size; 552 total_size = r1_end - r2_end; 553 554 reset_memblock(); 555 memblock_add(r1.base, r1.size); 556 memblock_remove(r2.base, r2.size); 557 558 assert(rgn->base == r1.base + r2.base); 559 assert(rgn->size == total_size); 560 561 assert(memblock.memory.cnt == 1); 562 assert(memblock.memory.total_size == total_size); 563 564 return 0; 565 } 566 567 /* 568 * A test that tries to remove a region which overlaps with the end of the 569 * first entry (that is r2.base < r1.base + r1.size). It checks if only the 570 * intersection of both regions is removed from the available memory pool. 571 * The test also checks if the regions counter and total size are updated to 572 * expected values. 573 */ 574 static int memblock_remove_overlap_bottom_check(void) 575 { 576 struct memblock_region *rgn; 577 phys_addr_t total_size; 578 579 rgn = &memblock.memory.regions[0]; 580 581 struct region r1 = { 582 .base = SZ_2M, 583 .size = SZ_64M 584 }; 585 struct region r2 = { 586 .base = SZ_32M, 587 .size = SZ_256M 588 }; 589 590 total_size = r2.base - r1.base; 591 592 reset_memblock(); 593 memblock_add(r1.base, r1.size); 594 memblock_remove(r2.base, r2.size); 595 596 assert(rgn->base == r1.base); 597 assert(rgn->size == total_size); 598 599 assert(memblock.memory.cnt == 1); 600 assert(memblock.memory.total_size == total_size); 601 return 0; 602 } 603 604 /* 605 * A test that tries to remove a region which is within the range of the 606 * already existing entry (that is 607 * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)). 608 * It checks if the region is split into two - one that ends at r2.base and 609 * second that starts at r2.base + size, with appropriate sizes. The test 610 * also checks if the region counter and total size were updated to 611 * expected values. 612 */ 613 static int memblock_remove_within_check(void) 614 { 615 struct memblock_region *rgn1, *rgn2; 616 phys_addr_t r1_size, r2_size, total_size; 617 618 rgn1 = &memblock.memory.regions[0]; 619 rgn2 = &memblock.memory.regions[1]; 620 621 struct region r1 = { 622 .base = SZ_1M, 623 .size = SZ_32M 624 }; 625 struct region r2 = { 626 .base = SZ_16M, 627 .size = SZ_1M 628 }; 629 630 r1_size = r2.base - r1.base; 631 r2_size = (r1.base + r1.size) - (r2.base + r2.size); 632 total_size = r1_size + r2_size; 633 634 reset_memblock(); 635 memblock_add(r1.base, r1.size); 636 memblock_remove(r2.base, r2.size); 637 638 assert(rgn1->base == r1.base); 639 assert(rgn1->size == r1_size); 640 641 assert(rgn2->base == r2.base + r2.size); 642 assert(rgn2->size == r2_size); 643 644 assert(memblock.memory.cnt == 2); 645 assert(memblock.memory.total_size == total_size); 646 647 return 0; 648 } 649 650 static int memblock_remove_checks(void) 651 { 652 memblock_remove_simple_check(); 653 memblock_remove_absent_check(); 654 memblock_remove_overlap_top_check(); 655 memblock_remove_overlap_bottom_check(); 656 memblock_remove_within_check(); 657 658 return 0; 659 } 660 661 int memblock_basic_checks(void) 662 { 663 memblock_initialization_check(); 664 memblock_add_checks(); 665 memblock_reserve_checks(); 666 memblock_remove_checks(); 667 668 return 0; 669 } 670