Skip to content

Commit 0237ee2

Browse files
drobnikrppt
authored andcommitted
memblock tests: Add memblock_alloc tests for bottom up
Add checks for memblock_alloc for bottom up allocation direction. The tested scenarios are: - Region can be allocated on the first fit (with and without region merging) - Region can be allocated on the second fit (with and without region merging) Add test case wrappers to test both directions in the same context. Signed-off-by: Karolina Drobnik <[email protected]> Signed-off-by: Mike Rapoport <[email protected]> Link: https://lore.kernel.org/r/426674eee20d99dca49caf1ee0142a83dccbc98d.1646055639.git.karolinadrobnik@gmail.com
1 parent 142eac6 commit 0237ee2

File tree

1 file changed

+320
-4
lines changed

1 file changed

+320
-4
lines changed

tools/testing/memblock/tests/alloc_api.c

Lines changed: 320 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -411,23 +411,339 @@ static int alloc_no_memory_generic_check(void)
411411
return 0;
412412
}
413413

414-
int memblock_alloc_checks(void)
414+
/*
415+
* A simple test that tries to allocate a small memory region.
416+
* Expect to allocate an aligned region at the beginning of the available
417+
* memory.
418+
*/
419+
static int alloc_bottom_up_simple_check(void)
415420
{
416-
reset_memblock_attributes();
417-
dummy_physical_memory_init();
421+
struct memblock_region *rgn = &memblock.reserved.regions[0];
422+
void *allocated_ptr = NULL;
423+
424+
setup_memblock();
425+
426+
allocated_ptr = memblock_alloc(SZ_2, SMP_CACHE_BYTES);
427+
428+
assert(allocated_ptr);
429+
assert(rgn->size == SZ_2);
430+
assert(rgn->base == memblock_start_of_DRAM());
431+
432+
assert(memblock.reserved.cnt == 1);
433+
assert(memblock.reserved.total_size == SZ_2);
434+
435+
return 0;
436+
}
437+
438+
/*
439+
* A test that tries to allocate memory next to a reserved region that starts at
440+
* the misaligned address. Expect to create two separate entries, with the new
441+
* entry aligned to the provided alignment:
442+
*
443+
* +
444+
* | +----------+ +----------+ |
445+
* | | rgn1 | | rgn2 | |
446+
* +----+----------+---+----------+-----+
447+
* ^
448+
* |
449+
* Aligned address boundary
450+
*
451+
* The allocation direction is bottom-up, so the new region will be the second
452+
* entry in memory.reserved array. The previously reserved region does not get
453+
* modified. Region counter and total size get updated.
454+
*/
455+
static int alloc_bottom_up_disjoint_check(void)
456+
{
457+
struct memblock_region *rgn1 = &memblock.reserved.regions[0];
458+
struct memblock_region *rgn2 = &memblock.reserved.regions[1];
459+
struct region r1;
460+
void *allocated_ptr = NULL;
461+
462+
phys_addr_t r2_size = SZ_16;
463+
/* Use custom alignment */
464+
phys_addr_t alignment = SMP_CACHE_BYTES * 2;
465+
phys_addr_t total_size;
466+
phys_addr_t expected_start;
467+
468+
setup_memblock();
469+
470+
r1.base = memblock_start_of_DRAM() + SZ_2;
471+
r1.size = SZ_2;
472+
473+
total_size = r1.size + r2_size;
474+
expected_start = memblock_start_of_DRAM() + alignment;
418475

476+
memblock_reserve(r1.base, r1.size);
477+
478+
allocated_ptr = memblock_alloc(r2_size, alignment);
479+
480+
assert(allocated_ptr);
481+
482+
assert(rgn1->size == r1.size);
483+
assert(rgn1->base == r1.base);
484+
485+
assert(rgn2->size == r2_size);
486+
assert(rgn2->base == expected_start);
487+
488+
assert(memblock.reserved.cnt == 2);
489+
assert(memblock.reserved.total_size == total_size);
490+
491+
return 0;
492+
}
493+
494+
/*
495+
* A test that tries to allocate memory when there is enough space at
496+
* the beginning of the previously reserved block (i.e. first fit):
497+
*
498+
* |------------------+--------+ |
499+
* | r1 | r2 | |
500+
* +------------------+--------+---------+
501+
*
502+
* Expect a merge of both regions. Only the region size gets updated.
503+
*/
504+
static int alloc_bottom_up_before_check(void)
505+
{
506+
struct memblock_region *rgn = &memblock.reserved.regions[0];
507+
void *allocated_ptr = NULL;
508+
509+
phys_addr_t r1_size = SZ_512;
510+
phys_addr_t r2_size = SZ_128;
511+
phys_addr_t total_size = r1_size + r2_size;
512+
513+
setup_memblock();
514+
515+
memblock_reserve(memblock_start_of_DRAM() + r1_size, r2_size);
516+
517+
allocated_ptr = memblock_alloc(r1_size, SMP_CACHE_BYTES);
518+
519+
assert(allocated_ptr);
520+
assert(rgn->size == total_size);
521+
assert(rgn->base == memblock_start_of_DRAM());
522+
523+
assert(memblock.reserved.cnt == 1);
524+
assert(memblock.reserved.total_size == total_size);
525+
526+
return 0;
527+
}
528+
529+
/*
530+
* A test that tries to allocate memory when there is not enough space at
531+
* the beginning of the previously reserved block (i.e. second fit):
532+
*
533+
* | +--------+--------------+ |
534+
* | | r1 | r2 | |
535+
* +----+--------+--------------+---------+
536+
*
537+
* Expect a merge of both regions. Only the region size gets updated.
538+
*/
539+
static int alloc_bottom_up_after_check(void)
540+
{
541+
struct memblock_region *rgn = &memblock.reserved.regions[0];
542+
struct region r1;
543+
void *allocated_ptr = NULL;
544+
545+
phys_addr_t r2_size = SZ_512;
546+
phys_addr_t total_size;
547+
548+
setup_memblock();
549+
550+
/*
551+
* The first region starts at the aligned address to test region merging
552+
*/
553+
r1.base = memblock_start_of_DRAM() + SMP_CACHE_BYTES;
554+
r1.size = SZ_64;
555+
556+
total_size = r1.size + r2_size;
557+
558+
memblock_reserve(r1.base, r1.size);
559+
560+
allocated_ptr = memblock_alloc(r2_size, SMP_CACHE_BYTES);
561+
562+
assert(allocated_ptr);
563+
assert(rgn->size == total_size);
564+
assert(rgn->base == r1.base);
565+
566+
assert(memblock.reserved.cnt == 1);
567+
assert(memblock.reserved.total_size == total_size);
568+
569+
return 0;
570+
}
571+
572+
/*
573+
* A test that tries to allocate memory when there are two reserved regions, the
574+
* first one starting at the beginning of the available memory, with a gap too
575+
* small to fit the new region:
576+
*
577+
* |------------+ +--------+--------+ |
578+
* | r1 | | r2 | r3 | |
579+
* +------------+-----+--------+--------+--+
580+
*
581+
* Expect to allocate after the second region, which starts at the higher
582+
* address, and merge them into one. The region counter and total size fields
583+
* get updated.
584+
*/
585+
static int alloc_bottom_up_second_fit_check(void)
586+
{
587+
struct memblock_region *rgn = &memblock.reserved.regions[1];
588+
struct region r1, r2;
589+
void *allocated_ptr = NULL;
590+
591+
phys_addr_t r3_size = SZ_1K;
592+
phys_addr_t total_size;
593+
594+
setup_memblock();
595+
596+
r1.base = memblock_start_of_DRAM();
597+
r1.size = SZ_512;
598+
599+
r2.base = r1.base + r1.size + SZ_512;
600+
r2.size = SZ_256;
601+
602+
total_size = r1.size + r2.size + r3_size;
603+
604+
memblock_reserve(r1.base, r1.size);
605+
memblock_reserve(r2.base, r2.size);
606+
607+
allocated_ptr = memblock_alloc(r3_size, SMP_CACHE_BYTES);
608+
609+
assert(allocated_ptr);
610+
assert(rgn->size == r2.size + r3_size);
611+
assert(rgn->base == r2.base);
612+
613+
assert(memblock.reserved.cnt == 2);
614+
assert(memblock.reserved.total_size == total_size);
615+
616+
return 0;
617+
}
618+
619+
/* Test case wrappers */
620+
static int alloc_simple_check(void)
621+
{
622+
memblock_set_bottom_up(false);
419623
alloc_top_down_simple_check();
624+
memblock_set_bottom_up(true);
625+
alloc_bottom_up_simple_check();
626+
627+
return 0;
628+
}
629+
630+
static int alloc_disjoint_check(void)
631+
{
632+
memblock_set_bottom_up(false);
420633
alloc_top_down_disjoint_check();
634+
memblock_set_bottom_up(true);
635+
alloc_bottom_up_disjoint_check();
636+
637+
return 0;
638+
}
639+
640+
static int alloc_before_check(void)
641+
{
642+
memblock_set_bottom_up(false);
421643
alloc_top_down_before_check();
644+
memblock_set_bottom_up(true);
645+
alloc_bottom_up_before_check();
646+
647+
return 0;
648+
}
649+
650+
static int alloc_after_check(void)
651+
{
652+
memblock_set_bottom_up(false);
422653
alloc_top_down_after_check();
423-
alloc_top_down_second_fit_check();
654+
memblock_set_bottom_up(true);
655+
alloc_bottom_up_after_check();
656+
657+
return 0;
658+
}
659+
660+
static int alloc_in_between_check(void)
661+
{
662+
memblock_set_bottom_up(false);
424663
alloc_in_between_generic_check();
664+
memblock_set_bottom_up(true);
665+
alloc_in_between_generic_check();
666+
667+
return 0;
668+
}
669+
670+
static int alloc_second_fit_check(void)
671+
{
672+
memblock_set_bottom_up(false);
673+
alloc_top_down_second_fit_check();
674+
memblock_set_bottom_up(true);
675+
alloc_bottom_up_second_fit_check();
676+
677+
return 0;
678+
}
679+
680+
static int alloc_small_gaps_check(void)
681+
{
682+
memblock_set_bottom_up(false);
425683
alloc_small_gaps_generic_check();
684+
memblock_set_bottom_up(true);
685+
alloc_small_gaps_generic_check();
686+
687+
return 0;
688+
}
689+
690+
static int alloc_all_reserved_check(void)
691+
{
692+
memblock_set_bottom_up(false);
693+
alloc_all_reserved_generic_check();
694+
memblock_set_bottom_up(true);
426695
alloc_all_reserved_generic_check();
696+
697+
return 0;
698+
}
699+
700+
static int alloc_no_space_check(void)
701+
{
702+
memblock_set_bottom_up(false);
703+
alloc_no_space_generic_check();
704+
memblock_set_bottom_up(true);
427705
alloc_no_space_generic_check();
706+
707+
return 0;
708+
}
709+
710+
static int alloc_limited_space_check(void)
711+
{
712+
memblock_set_bottom_up(false);
428713
alloc_limited_space_generic_check();
714+
memblock_set_bottom_up(true);
715+
alloc_limited_space_generic_check();
716+
717+
return 0;
718+
}
719+
720+
static int alloc_no_memory_check(void)
721+
{
722+
memblock_set_bottom_up(false);
723+
alloc_no_memory_generic_check();
724+
memblock_set_bottom_up(true);
429725
alloc_no_memory_generic_check();
430726

727+
return 0;
728+
}
729+
730+
int memblock_alloc_checks(void)
731+
{
732+
reset_memblock_attributes();
733+
dummy_physical_memory_init();
734+
735+
alloc_simple_check();
736+
alloc_disjoint_check();
737+
alloc_before_check();
738+
alloc_after_check();
739+
alloc_second_fit_check();
740+
alloc_small_gaps_check();
741+
alloc_in_between_check();
742+
alloc_all_reserved_check();
743+
alloc_no_space_check();
744+
alloc_limited_space_check();
745+
alloc_no_memory_check();
746+
431747
dummy_physical_memory_cleanup();
432748

433749
return 0;

0 commit comments

Comments
 (0)