Path: blob/master/tools/testing/memblock/tests/alloc_helpers_api.c
26299 views
// SPDX-License-Identifier: GPL-2.0-or-later1#include "alloc_helpers_api.h"23/*4* A simple test that tries to allocate a memory region above a specified,5* aligned address:6*7* +8* | +-----------+ |9* | | rgn | |10* +----------+-----------+---------+11* ^12* |13* Aligned min_addr14*15* Expect to allocate a cleared region at the minimal memory address.16*/17static int alloc_from_simple_generic_check(void)18{19struct memblock_region *rgn = &memblock.reserved.regions[0];20void *allocated_ptr = NULL;21phys_addr_t size = SZ_16;22phys_addr_t min_addr;2324PREFIX_PUSH();25setup_memblock();2627min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES;2829allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);3031ASSERT_NE(allocated_ptr, NULL);32ASSERT_MEM_EQ(allocated_ptr, 0, size);3334ASSERT_EQ(rgn->size, size);35ASSERT_EQ(rgn->base, min_addr);3637ASSERT_EQ(memblock.reserved.cnt, 1);38ASSERT_EQ(memblock.reserved.total_size, size);3940test_pass_pop();4142return 0;43}4445/*46* A test that tries to allocate a memory region above a certain address.47* The minimal address here is not aligned:48*49* + +50* | + +---------+ |51* | | | rgn | |52* +------+------+---------+------------+53* ^ ^------.54* | |55* min_addr Aligned address56* boundary57*58* Expect to allocate a cleared region at the closest aligned memory address.59*/60static int alloc_from_misaligned_generic_check(void)61{62struct memblock_region *rgn = &memblock.reserved.regions[0];63void *allocated_ptr = NULL;64phys_addr_t size = SZ_32;65phys_addr_t min_addr;6667PREFIX_PUSH();68setup_memblock();6970/* A misaligned address */71min_addr = memblock_end_of_DRAM() - (SMP_CACHE_BYTES * 2 - 1);7273allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);7475ASSERT_NE(allocated_ptr, NULL);76ASSERT_MEM_EQ(allocated_ptr, 0, size);7778ASSERT_EQ(rgn->size, size);79ASSERT_EQ(rgn->base, memblock_end_of_DRAM() - SMP_CACHE_BYTES);8081ASSERT_EQ(memblock.reserved.cnt, 1);82ASSERT_EQ(memblock.reserved.total_size, size);8384test_pass_pop();8586return 0;87}8889/*90* A test that tries to allocate a memory region above an address that is too91* close to the end of the memory:92*93* + +94* | +--------+---+ |95* | | rgn + | |96* +-----------+--------+---+------+97* ^ ^98* | |99* | min_addr100* |101* Aligned address102* boundary103*104* Expect to prioritize granting memory over satisfying the minimal address105* requirement.106*/107static int alloc_from_top_down_high_addr_check(void)108{109struct memblock_region *rgn = &memblock.reserved.regions[0];110void *allocated_ptr = NULL;111phys_addr_t size = SZ_32;112phys_addr_t min_addr;113114PREFIX_PUSH();115setup_memblock();116117/* The address is too close to the end of the memory */118min_addr = memblock_end_of_DRAM() - SZ_16;119120allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);121122ASSERT_NE(allocated_ptr, NULL);123ASSERT_EQ(rgn->size, size);124ASSERT_EQ(rgn->base, memblock_end_of_DRAM() - SMP_CACHE_BYTES);125126ASSERT_EQ(memblock.reserved.cnt, 1);127ASSERT_EQ(memblock.reserved.total_size, size);128129test_pass_pop();130131return 0;132}133134/*135* A test that tries to allocate a memory region when there is no space136* available above the minimal address above a certain address:137*138* +139* | +---------+-------------|140* | | rgn | |141* +--------+---------+-------------+142* ^143* |144* min_addr145*146* Expect to prioritize granting memory over satisfying the minimal address147* requirement and to allocate next to the previously reserved region. The148* regions get merged into one.149*/150static int alloc_from_top_down_no_space_above_check(void)151{152struct memblock_region *rgn = &memblock.reserved.regions[0];153void *allocated_ptr = NULL;154phys_addr_t r1_size = SZ_64;155phys_addr_t r2_size = SZ_2;156phys_addr_t total_size = r1_size + r2_size;157phys_addr_t min_addr;158159PREFIX_PUSH();160setup_memblock();161162min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES * 2;163164/* No space above this address */165memblock_reserve_kern(min_addr, r2_size);166167allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);168169ASSERT_NE(allocated_ptr, NULL);170ASSERT_EQ(rgn->base, min_addr - r1_size);171ASSERT_EQ(rgn->size, total_size);172173ASSERT_EQ(memblock.reserved.cnt, 1);174ASSERT_EQ(memblock.reserved.total_size, total_size);175176test_pass_pop();177178return 0;179}180181/*182* A test that tries to allocate a memory region with a minimal address below183* the start address of the available memory. As the allocation is top-down,184* first reserve a region that will force allocation near the start.185* Expect successful allocation and merge of both regions.186*/187static int alloc_from_top_down_min_addr_cap_check(void)188{189struct memblock_region *rgn = &memblock.reserved.regions[0];190void *allocated_ptr = NULL;191phys_addr_t r1_size = SZ_64;192phys_addr_t min_addr;193phys_addr_t start_addr;194195PREFIX_PUSH();196setup_memblock();197198start_addr = (phys_addr_t)memblock_start_of_DRAM();199min_addr = start_addr - SMP_CACHE_BYTES * 3;200201memblock_reserve_kern(start_addr + r1_size, MEM_SIZE - r1_size);202203allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);204205ASSERT_NE(allocated_ptr, NULL);206ASSERT_EQ(rgn->base, start_addr);207ASSERT_EQ(rgn->size, MEM_SIZE);208209ASSERT_EQ(memblock.reserved.cnt, 1);210ASSERT_EQ(memblock.reserved.total_size, MEM_SIZE);211212test_pass_pop();213214return 0;215}216217/*218* A test that tries to allocate a memory region above an address that is too219* close to the end of the memory:220*221* +222* |-----------+ + |223* | rgn | | |224* +-----------+--------------+-----+225* ^ ^226* | |227* Aligned address min_addr228* boundary229*230* Expect to prioritize granting memory over satisfying the minimal address231* requirement. Allocation happens at beginning of the available memory.232*/233static int alloc_from_bottom_up_high_addr_check(void)234{235struct memblock_region *rgn = &memblock.reserved.regions[0];236void *allocated_ptr = NULL;237phys_addr_t size = SZ_32;238phys_addr_t min_addr;239240PREFIX_PUSH();241setup_memblock();242243/* The address is too close to the end of the memory */244min_addr = memblock_end_of_DRAM() - SZ_8;245246allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);247248ASSERT_NE(allocated_ptr, NULL);249ASSERT_EQ(rgn->size, size);250ASSERT_EQ(rgn->base, memblock_start_of_DRAM());251252ASSERT_EQ(memblock.reserved.cnt, 1);253ASSERT_EQ(memblock.reserved.total_size, size);254255test_pass_pop();256257return 0;258}259260/*261* A test that tries to allocate a memory region when there is no space262* available above the minimal address above a certain address:263*264* +265* |-----------+ +-------------------|266* | rgn | | |267* +-----------+----+-------------------+268* ^269* |270* min_addr271*272* Expect to prioritize granting memory over satisfying the minimal address273* requirement and to allocate at the beginning of the available memory.274*/275static int alloc_from_bottom_up_no_space_above_check(void)276{277struct memblock_region *rgn = &memblock.reserved.regions[0];278void *allocated_ptr = NULL;279phys_addr_t r1_size = SZ_64;280phys_addr_t min_addr;281phys_addr_t r2_size;282283PREFIX_PUSH();284setup_memblock();285286min_addr = memblock_start_of_DRAM() + SZ_128;287r2_size = memblock_end_of_DRAM() - min_addr;288289/* No space above this address */290memblock_reserve(min_addr - SMP_CACHE_BYTES, r2_size);291292allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);293294ASSERT_NE(allocated_ptr, NULL);295ASSERT_EQ(rgn->base, memblock_start_of_DRAM());296ASSERT_EQ(rgn->size, r1_size);297298ASSERT_EQ(memblock.reserved.cnt, 2);299ASSERT_EQ(memblock.reserved.total_size, r1_size + r2_size);300301test_pass_pop();302303return 0;304}305306/*307* A test that tries to allocate a memory region with a minimal address below308* the start address of the available memory. Expect to allocate a region309* at the beginning of the available memory.310*/311static int alloc_from_bottom_up_min_addr_cap_check(void)312{313struct memblock_region *rgn = &memblock.reserved.regions[0];314void *allocated_ptr = NULL;315phys_addr_t r1_size = SZ_64;316phys_addr_t min_addr;317phys_addr_t start_addr;318319PREFIX_PUSH();320setup_memblock();321322start_addr = (phys_addr_t)memblock_start_of_DRAM();323min_addr = start_addr - SMP_CACHE_BYTES * 3;324325allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);326327ASSERT_NE(allocated_ptr, NULL);328ASSERT_EQ(rgn->base, start_addr);329ASSERT_EQ(rgn->size, r1_size);330331ASSERT_EQ(memblock.reserved.cnt, 1);332ASSERT_EQ(memblock.reserved.total_size, r1_size);333334test_pass_pop();335336return 0;337}338339/* Test case wrappers */340static int alloc_from_simple_check(void)341{342test_print("\tRunning %s...\n", __func__);343run_top_down(alloc_from_simple_generic_check);344run_bottom_up(alloc_from_simple_generic_check);345346return 0;347}348349static int alloc_from_misaligned_check(void)350{351test_print("\tRunning %s...\n", __func__);352run_top_down(alloc_from_misaligned_generic_check);353run_bottom_up(alloc_from_misaligned_generic_check);354355return 0;356}357358static int alloc_from_high_addr_check(void)359{360test_print("\tRunning %s...\n", __func__);361memblock_set_bottom_up(false);362alloc_from_top_down_high_addr_check();363memblock_set_bottom_up(true);364alloc_from_bottom_up_high_addr_check();365366return 0;367}368369static int alloc_from_no_space_above_check(void)370{371test_print("\tRunning %s...\n", __func__);372memblock_set_bottom_up(false);373alloc_from_top_down_no_space_above_check();374memblock_set_bottom_up(true);375alloc_from_bottom_up_no_space_above_check();376377return 0;378}379380static int alloc_from_min_addr_cap_check(void)381{382test_print("\tRunning %s...\n", __func__);383memblock_set_bottom_up(false);384alloc_from_top_down_min_addr_cap_check();385memblock_set_bottom_up(true);386alloc_from_bottom_up_min_addr_cap_check();387388return 0;389}390391int memblock_alloc_helpers_checks(void)392{393const char *func_testing = "memblock_alloc_from";394395prefix_reset();396prefix_push(func_testing);397test_print("Running %s tests...\n", func_testing);398399reset_memblock_attributes();400dummy_physical_memory_init();401402alloc_from_simple_check();403alloc_from_misaligned_check();404alloc_from_high_addr_check();405alloc_from_no_space_above_check();406alloc_from_min_addr_cap_check();407408dummy_physical_memory_cleanup();409410prefix_pop();411412return 0;413}414415416