@@ -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