162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci#include "basic_api.h" 362306a36Sopenharmony_ci#include <string.h> 462306a36Sopenharmony_ci#include <linux/memblock.h> 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#define EXPECTED_MEMBLOCK_REGIONS 128 762306a36Sopenharmony_ci#define FUNC_ADD "memblock_add" 862306a36Sopenharmony_ci#define FUNC_RESERVE "memblock_reserve" 962306a36Sopenharmony_ci#define FUNC_REMOVE "memblock_remove" 1062306a36Sopenharmony_ci#define FUNC_FREE "memblock_free" 1162306a36Sopenharmony_ci#define FUNC_TRIM "memblock_trim_memory" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic int memblock_initialization_check(void) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci PREFIX_PUSH(); 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci ASSERT_NE(memblock.memory.regions, NULL); 1862306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 1962306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS); 2062306a36Sopenharmony_ci ASSERT_EQ(strcmp(memblock.memory.name, "memory"), 0); 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci ASSERT_NE(memblock.reserved.regions, NULL); 2362306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 1); 2462306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS); 2562306a36Sopenharmony_ci ASSERT_EQ(strcmp(memblock.reserved.name, "reserved"), 0); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci ASSERT_EQ(memblock.bottom_up, false); 2862306a36Sopenharmony_ci ASSERT_EQ(memblock.current_limit, MEMBLOCK_ALLOC_ANYWHERE); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci test_pass_pop(); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci return 0; 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* 3662306a36Sopenharmony_ci * A simple test that adds a memory block of a specified base address 3762306a36Sopenharmony_ci * and size to the collection of available memory regions (memblock.memory). 3862306a36Sopenharmony_ci * Expect to create a new entry. The region counter and total memory get 3962306a36Sopenharmony_ci * updated. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_cistatic int memblock_add_simple_check(void) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci struct memblock_region *rgn; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci struct region r = { 4862306a36Sopenharmony_ci .base = SZ_1G, 4962306a36Sopenharmony_ci .size = SZ_4M 5062306a36Sopenharmony_ci }; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci PREFIX_PUSH(); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci reset_memblock_regions(); 5562306a36Sopenharmony_ci memblock_add(r.base, r.size); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r.base); 5862306a36Sopenharmony_ci ASSERT_EQ(rgn->size, r.size); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 6162306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, r.size); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci test_pass_pop(); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci return 0; 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* 6962306a36Sopenharmony_ci * A simple test that adds a memory block of a specified base address, size, 7062306a36Sopenharmony_ci * NUMA node and memory flags to the collection of available memory regions. 7162306a36Sopenharmony_ci * Expect to create a new entry. The region counter and total memory get 7262306a36Sopenharmony_ci * updated. 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_cistatic int memblock_add_node_simple_check(void) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci struct memblock_region *rgn; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci struct region r = { 8162306a36Sopenharmony_ci .base = SZ_1M, 8262306a36Sopenharmony_ci .size = SZ_16M 8362306a36Sopenharmony_ci }; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci PREFIX_PUSH(); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci reset_memblock_regions(); 8862306a36Sopenharmony_ci memblock_add_node(r.base, r.size, 1, MEMBLOCK_HOTPLUG); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r.base); 9162306a36Sopenharmony_ci ASSERT_EQ(rgn->size, r.size); 9262306a36Sopenharmony_ci#ifdef CONFIG_NUMA 9362306a36Sopenharmony_ci ASSERT_EQ(rgn->nid, 1); 9462306a36Sopenharmony_ci#endif 9562306a36Sopenharmony_ci ASSERT_EQ(rgn->flags, MEMBLOCK_HOTPLUG); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 9862306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, r.size); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci test_pass_pop(); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci return 0; 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/* 10662306a36Sopenharmony_ci * A test that tries to add two memory blocks that don't overlap with one 10762306a36Sopenharmony_ci * another: 10862306a36Sopenharmony_ci * 10962306a36Sopenharmony_ci * | +--------+ +--------+ | 11062306a36Sopenharmony_ci * | | r1 | | r2 | | 11162306a36Sopenharmony_ci * +--------+--------+--------+--------+--+ 11262306a36Sopenharmony_ci * 11362306a36Sopenharmony_ci * Expect to add two correctly initialized entries to the collection of 11462306a36Sopenharmony_ci * available memory regions (memblock.memory). The total size and 11562306a36Sopenharmony_ci * region counter fields get updated. 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_cistatic int memblock_add_disjoint_check(void) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci struct memblock_region *rgn1, *rgn2; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci rgn1 = &memblock.memory.regions[0]; 12262306a36Sopenharmony_ci rgn2 = &memblock.memory.regions[1]; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci struct region r1 = { 12562306a36Sopenharmony_ci .base = SZ_1G, 12662306a36Sopenharmony_ci .size = SZ_8K 12762306a36Sopenharmony_ci }; 12862306a36Sopenharmony_ci struct region r2 = { 12962306a36Sopenharmony_ci .base = SZ_1G + SZ_16K, 13062306a36Sopenharmony_ci .size = SZ_8K 13162306a36Sopenharmony_ci }; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci PREFIX_PUSH(); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci reset_memblock_regions(); 13662306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 13762306a36Sopenharmony_ci memblock_add(r2.base, r2.size); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci ASSERT_EQ(rgn1->base, r1.base); 14062306a36Sopenharmony_ci ASSERT_EQ(rgn1->size, r1.size); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci ASSERT_EQ(rgn2->base, r2.base); 14362306a36Sopenharmony_ci ASSERT_EQ(rgn2->size, r2.size); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 2); 14662306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, r1.size + r2.size); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci test_pass_pop(); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci return 0; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/* 15462306a36Sopenharmony_ci * A test that tries to add two memory blocks r1 and r2, where r2 overlaps 15562306a36Sopenharmony_ci * with the beginning of r1 (that is r1.base < r2.base + r2.size): 15662306a36Sopenharmony_ci * 15762306a36Sopenharmony_ci * | +----+----+------------+ | 15862306a36Sopenharmony_ci * | | |r2 | r1 | | 15962306a36Sopenharmony_ci * +----+----+----+------------+----------+ 16062306a36Sopenharmony_ci * ^ ^ 16162306a36Sopenharmony_ci * | | 16262306a36Sopenharmony_ci * | r1.base 16362306a36Sopenharmony_ci * | 16462306a36Sopenharmony_ci * r2.base 16562306a36Sopenharmony_ci * 16662306a36Sopenharmony_ci * Expect to merge the two entries into one region that starts at r2.base 16762306a36Sopenharmony_ci * and has size of two regions minus their intersection. The total size of 16862306a36Sopenharmony_ci * the available memory is updated, and the region counter stays the same. 16962306a36Sopenharmony_ci */ 17062306a36Sopenharmony_cistatic int memblock_add_overlap_top_check(void) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci struct memblock_region *rgn; 17362306a36Sopenharmony_ci phys_addr_t total_size; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci struct region r1 = { 17862306a36Sopenharmony_ci .base = SZ_512M, 17962306a36Sopenharmony_ci .size = SZ_1G 18062306a36Sopenharmony_ci }; 18162306a36Sopenharmony_ci struct region r2 = { 18262306a36Sopenharmony_ci .base = SZ_256M, 18362306a36Sopenharmony_ci .size = SZ_512M 18462306a36Sopenharmony_ci }; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci PREFIX_PUSH(); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci total_size = (r1.base - r2.base) + r1.size; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci reset_memblock_regions(); 19162306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 19262306a36Sopenharmony_ci memblock_add(r2.base, r2.size); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r2.base); 19562306a36Sopenharmony_ci ASSERT_EQ(rgn->size, total_size); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 19862306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, total_size); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci test_pass_pop(); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci return 0; 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci/* 20662306a36Sopenharmony_ci * A test that tries to add two memory blocks r1 and r2, where r2 overlaps 20762306a36Sopenharmony_ci * with the end of r1 (that is r2.base < r1.base + r1.size): 20862306a36Sopenharmony_ci * 20962306a36Sopenharmony_ci * | +--+------+----------+ | 21062306a36Sopenharmony_ci * | | | r1 | r2 | | 21162306a36Sopenharmony_ci * +--+--+------+----------+--------------+ 21262306a36Sopenharmony_ci * ^ ^ 21362306a36Sopenharmony_ci * | | 21462306a36Sopenharmony_ci * | r2.base 21562306a36Sopenharmony_ci * | 21662306a36Sopenharmony_ci * r1.base 21762306a36Sopenharmony_ci * 21862306a36Sopenharmony_ci * Expect to merge the two entries into one region that starts at r1.base 21962306a36Sopenharmony_ci * and has size of two regions minus their intersection. The total size of 22062306a36Sopenharmony_ci * the available memory is updated, and the region counter stays the same. 22162306a36Sopenharmony_ci */ 22262306a36Sopenharmony_cistatic int memblock_add_overlap_bottom_check(void) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci struct memblock_region *rgn; 22562306a36Sopenharmony_ci phys_addr_t total_size; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci struct region r1 = { 23062306a36Sopenharmony_ci .base = SZ_128M, 23162306a36Sopenharmony_ci .size = SZ_512M 23262306a36Sopenharmony_ci }; 23362306a36Sopenharmony_ci struct region r2 = { 23462306a36Sopenharmony_ci .base = SZ_256M, 23562306a36Sopenharmony_ci .size = SZ_1G 23662306a36Sopenharmony_ci }; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci PREFIX_PUSH(); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci total_size = (r2.base - r1.base) + r2.size; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci reset_memblock_regions(); 24362306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 24462306a36Sopenharmony_ci memblock_add(r2.base, r2.size); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r1.base); 24762306a36Sopenharmony_ci ASSERT_EQ(rgn->size, total_size); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 25062306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, total_size); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci test_pass_pop(); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci return 0; 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci/* 25862306a36Sopenharmony_ci * A test that tries to add two memory blocks r1 and r2, where r2 is 25962306a36Sopenharmony_ci * within the range of r1 (that is r1.base < r2.base && 26062306a36Sopenharmony_ci * r2.base + r2.size < r1.base + r1.size): 26162306a36Sopenharmony_ci * 26262306a36Sopenharmony_ci * | +-------+--+-----------------------+ 26362306a36Sopenharmony_ci * | | |r2| r1 | 26462306a36Sopenharmony_ci * +---+-------+--+-----------------------+ 26562306a36Sopenharmony_ci * ^ 26662306a36Sopenharmony_ci * | 26762306a36Sopenharmony_ci * r1.base 26862306a36Sopenharmony_ci * 26962306a36Sopenharmony_ci * Expect to merge two entries into one region that stays the same. 27062306a36Sopenharmony_ci * The counter and total size of available memory are not updated. 27162306a36Sopenharmony_ci */ 27262306a36Sopenharmony_cistatic int memblock_add_within_check(void) 27362306a36Sopenharmony_ci{ 27462306a36Sopenharmony_ci struct memblock_region *rgn; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci struct region r1 = { 27962306a36Sopenharmony_ci .base = SZ_8M, 28062306a36Sopenharmony_ci .size = SZ_32M 28162306a36Sopenharmony_ci }; 28262306a36Sopenharmony_ci struct region r2 = { 28362306a36Sopenharmony_ci .base = SZ_16M, 28462306a36Sopenharmony_ci .size = SZ_1M 28562306a36Sopenharmony_ci }; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci PREFIX_PUSH(); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci reset_memblock_regions(); 29062306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 29162306a36Sopenharmony_ci memblock_add(r2.base, r2.size); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r1.base); 29462306a36Sopenharmony_ci ASSERT_EQ(rgn->size, r1.size); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 29762306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, r1.size); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci test_pass_pop(); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci return 0; 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci/* 30562306a36Sopenharmony_ci * A simple test that tries to add the same memory block twice. Expect 30662306a36Sopenharmony_ci * the counter and total size of available memory to not be updated. 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_cistatic int memblock_add_twice_check(void) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci struct region r = { 31162306a36Sopenharmony_ci .base = SZ_16K, 31262306a36Sopenharmony_ci .size = SZ_2M 31362306a36Sopenharmony_ci }; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci PREFIX_PUSH(); 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci reset_memblock_regions(); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci memblock_add(r.base, r.size); 32062306a36Sopenharmony_ci memblock_add(r.base, r.size); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 32362306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, r.size); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci test_pass_pop(); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci return 0; 32862306a36Sopenharmony_ci} 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci/* 33162306a36Sopenharmony_ci * A test that tries to add two memory blocks that don't overlap with one 33262306a36Sopenharmony_ci * another and then add a third memory block in the space between the first two: 33362306a36Sopenharmony_ci * 33462306a36Sopenharmony_ci * | +--------+--------+--------+ | 33562306a36Sopenharmony_ci * | | r1 | r3 | r2 | | 33662306a36Sopenharmony_ci * +--------+--------+--------+--------+--+ 33762306a36Sopenharmony_ci * 33862306a36Sopenharmony_ci * Expect to merge the three entries into one region that starts at r1.base 33962306a36Sopenharmony_ci * and has size of r1.size + r2.size + r3.size. The region counter and total 34062306a36Sopenharmony_ci * size of the available memory are updated. 34162306a36Sopenharmony_ci */ 34262306a36Sopenharmony_cistatic int memblock_add_between_check(void) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci struct memblock_region *rgn; 34562306a36Sopenharmony_ci phys_addr_t total_size; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci struct region r1 = { 35062306a36Sopenharmony_ci .base = SZ_1G, 35162306a36Sopenharmony_ci .size = SZ_8K 35262306a36Sopenharmony_ci }; 35362306a36Sopenharmony_ci struct region r2 = { 35462306a36Sopenharmony_ci .base = SZ_1G + SZ_16K, 35562306a36Sopenharmony_ci .size = SZ_8K 35662306a36Sopenharmony_ci }; 35762306a36Sopenharmony_ci struct region r3 = { 35862306a36Sopenharmony_ci .base = SZ_1G + SZ_8K, 35962306a36Sopenharmony_ci .size = SZ_8K 36062306a36Sopenharmony_ci }; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci PREFIX_PUSH(); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci total_size = r1.size + r2.size + r3.size; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci reset_memblock_regions(); 36762306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 36862306a36Sopenharmony_ci memblock_add(r2.base, r2.size); 36962306a36Sopenharmony_ci memblock_add(r3.base, r3.size); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r1.base); 37262306a36Sopenharmony_ci ASSERT_EQ(rgn->size, total_size); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 37562306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, total_size); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci test_pass_pop(); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci return 0; 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci/* 38362306a36Sopenharmony_ci * A simple test that tries to add a memory block r when r extends past 38462306a36Sopenharmony_ci * PHYS_ADDR_MAX: 38562306a36Sopenharmony_ci * 38662306a36Sopenharmony_ci * +--------+ 38762306a36Sopenharmony_ci * | r | 38862306a36Sopenharmony_ci * +--------+ 38962306a36Sopenharmony_ci * | +----+ 39062306a36Sopenharmony_ci * | | rgn| 39162306a36Sopenharmony_ci * +----------------------------+----+ 39262306a36Sopenharmony_ci * 39362306a36Sopenharmony_ci * Expect to add a memory block of size PHYS_ADDR_MAX - r.base. Expect the 39462306a36Sopenharmony_ci * total size of available memory and the counter to be updated. 39562306a36Sopenharmony_ci */ 39662306a36Sopenharmony_cistatic int memblock_add_near_max_check(void) 39762306a36Sopenharmony_ci{ 39862306a36Sopenharmony_ci struct memblock_region *rgn; 39962306a36Sopenharmony_ci phys_addr_t total_size; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci struct region r = { 40462306a36Sopenharmony_ci .base = PHYS_ADDR_MAX - SZ_1M, 40562306a36Sopenharmony_ci .size = SZ_2M 40662306a36Sopenharmony_ci }; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci PREFIX_PUSH(); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci total_size = PHYS_ADDR_MAX - r.base; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci reset_memblock_regions(); 41362306a36Sopenharmony_ci memblock_add(r.base, r.size); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r.base); 41662306a36Sopenharmony_ci ASSERT_EQ(rgn->size, total_size); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 41962306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, total_size); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci test_pass_pop(); 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci return 0; 42462306a36Sopenharmony_ci} 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci/* 42762306a36Sopenharmony_ci * A test that trying to add the 129th memory block. 42862306a36Sopenharmony_ci * Expect to trigger memblock_double_array() to double the 42962306a36Sopenharmony_ci * memblock.memory.max, find a new valid memory as 43062306a36Sopenharmony_ci * memory.regions. 43162306a36Sopenharmony_ci */ 43262306a36Sopenharmony_cistatic int memblock_add_many_check(void) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci int i; 43562306a36Sopenharmony_ci void *orig_region; 43662306a36Sopenharmony_ci struct region r = { 43762306a36Sopenharmony_ci .base = SZ_16K, 43862306a36Sopenharmony_ci .size = SZ_16K, 43962306a36Sopenharmony_ci }; 44062306a36Sopenharmony_ci phys_addr_t new_memory_regions_size; 44162306a36Sopenharmony_ci phys_addr_t base, size = SZ_64; 44262306a36Sopenharmony_ci phys_addr_t gap_size = SZ_64; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci PREFIX_PUSH(); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci reset_memblock_regions(); 44762306a36Sopenharmony_ci memblock_allow_resize(); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci dummy_physical_memory_init(); 45062306a36Sopenharmony_ci /* 45162306a36Sopenharmony_ci * We allocated enough memory by using dummy_physical_memory_init(), and 45262306a36Sopenharmony_ci * split it into small block. First we split a large enough memory block 45362306a36Sopenharmony_ci * as the memory region which will be choosed by memblock_double_array(). 45462306a36Sopenharmony_ci */ 45562306a36Sopenharmony_ci base = PAGE_ALIGN(dummy_physical_memory_base()); 45662306a36Sopenharmony_ci new_memory_regions_size = PAGE_ALIGN(INIT_MEMBLOCK_REGIONS * 2 * 45762306a36Sopenharmony_ci sizeof(struct memblock_region)); 45862306a36Sopenharmony_ci memblock_add(base, new_memory_regions_size); 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci /* This is the base of small memory block. */ 46162306a36Sopenharmony_ci base += new_memory_regions_size + gap_size; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci orig_region = memblock.memory.regions; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci for (i = 0; i < INIT_MEMBLOCK_REGIONS; i++) { 46662306a36Sopenharmony_ci /* 46762306a36Sopenharmony_ci * Add these small block to fulfill the memblock. We keep a 46862306a36Sopenharmony_ci * gap between the nearby memory to avoid being merged. 46962306a36Sopenharmony_ci */ 47062306a36Sopenharmony_ci memblock_add(base, size); 47162306a36Sopenharmony_ci base += size + gap_size; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, i + 2); 47462306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, new_memory_regions_size + 47562306a36Sopenharmony_ci (i + 1) * size); 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci /* 47962306a36Sopenharmony_ci * At there, memblock_double_array() has been succeed, check if it 48062306a36Sopenharmony_ci * update the memory.max. 48162306a36Sopenharmony_ci */ 48262306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.max, INIT_MEMBLOCK_REGIONS * 2); 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci /* memblock_double_array() will reserve the memory it used. Check it. */ 48562306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 1); 48662306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, new_memory_regions_size); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci /* 48962306a36Sopenharmony_ci * Now memblock_double_array() works fine. Let's check after the 49062306a36Sopenharmony_ci * double_array(), the memblock_add() still works as normal. 49162306a36Sopenharmony_ci */ 49262306a36Sopenharmony_ci memblock_add(r.base, r.size); 49362306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.regions[0].base, r.base); 49462306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.regions[0].size, r.size); 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, INIT_MEMBLOCK_REGIONS + 2); 49762306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, INIT_MEMBLOCK_REGIONS * size + 49862306a36Sopenharmony_ci new_memory_regions_size + 49962306a36Sopenharmony_ci r.size); 50062306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.max, INIT_MEMBLOCK_REGIONS * 2); 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci dummy_physical_memory_cleanup(); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci /* 50562306a36Sopenharmony_ci * The current memory.regions is occupying a range of memory that 50662306a36Sopenharmony_ci * allocated from dummy_physical_memory_init(). After free the memory, 50762306a36Sopenharmony_ci * we must not use it. So restore the origin memory region to make sure 50862306a36Sopenharmony_ci * the tests can run as normal and not affected by the double array. 50962306a36Sopenharmony_ci */ 51062306a36Sopenharmony_ci memblock.memory.regions = orig_region; 51162306a36Sopenharmony_ci memblock.memory.cnt = INIT_MEMBLOCK_REGIONS; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci test_pass_pop(); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci return 0; 51662306a36Sopenharmony_ci} 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_cistatic int memblock_add_checks(void) 51962306a36Sopenharmony_ci{ 52062306a36Sopenharmony_ci prefix_reset(); 52162306a36Sopenharmony_ci prefix_push(FUNC_ADD); 52262306a36Sopenharmony_ci test_print("Running %s tests...\n", FUNC_ADD); 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci memblock_add_simple_check(); 52562306a36Sopenharmony_ci memblock_add_node_simple_check(); 52662306a36Sopenharmony_ci memblock_add_disjoint_check(); 52762306a36Sopenharmony_ci memblock_add_overlap_top_check(); 52862306a36Sopenharmony_ci memblock_add_overlap_bottom_check(); 52962306a36Sopenharmony_ci memblock_add_within_check(); 53062306a36Sopenharmony_ci memblock_add_twice_check(); 53162306a36Sopenharmony_ci memblock_add_between_check(); 53262306a36Sopenharmony_ci memblock_add_near_max_check(); 53362306a36Sopenharmony_ci memblock_add_many_check(); 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci prefix_pop(); 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci return 0; 53862306a36Sopenharmony_ci} 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci/* 54162306a36Sopenharmony_ci * A simple test that marks a memory block of a specified base address 54262306a36Sopenharmony_ci * and size as reserved and to the collection of reserved memory regions 54362306a36Sopenharmony_ci * (memblock.reserved). Expect to create a new entry. The region counter 54462306a36Sopenharmony_ci * and total memory size are updated. 54562306a36Sopenharmony_ci */ 54662306a36Sopenharmony_cistatic int memblock_reserve_simple_check(void) 54762306a36Sopenharmony_ci{ 54862306a36Sopenharmony_ci struct memblock_region *rgn; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci rgn = &memblock.reserved.regions[0]; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci struct region r = { 55362306a36Sopenharmony_ci .base = SZ_2G, 55462306a36Sopenharmony_ci .size = SZ_128M 55562306a36Sopenharmony_ci }; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci PREFIX_PUSH(); 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci reset_memblock_regions(); 56062306a36Sopenharmony_ci memblock_reserve(r.base, r.size); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r.base); 56362306a36Sopenharmony_ci ASSERT_EQ(rgn->size, r.size); 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci test_pass_pop(); 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci return 0; 56862306a36Sopenharmony_ci} 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci/* 57162306a36Sopenharmony_ci * A test that tries to mark two memory blocks that don't overlap as reserved: 57262306a36Sopenharmony_ci * 57362306a36Sopenharmony_ci * | +--+ +----------------+ | 57462306a36Sopenharmony_ci * | |r1| | r2 | | 57562306a36Sopenharmony_ci * +--------+--+------+----------------+--+ 57662306a36Sopenharmony_ci * 57762306a36Sopenharmony_ci * Expect to add two entries to the collection of reserved memory regions 57862306a36Sopenharmony_ci * (memblock.reserved). The total size and region counter for 57962306a36Sopenharmony_ci * memblock.reserved are updated. 58062306a36Sopenharmony_ci */ 58162306a36Sopenharmony_cistatic int memblock_reserve_disjoint_check(void) 58262306a36Sopenharmony_ci{ 58362306a36Sopenharmony_ci struct memblock_region *rgn1, *rgn2; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci rgn1 = &memblock.reserved.regions[0]; 58662306a36Sopenharmony_ci rgn2 = &memblock.reserved.regions[1]; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci struct region r1 = { 58962306a36Sopenharmony_ci .base = SZ_256M, 59062306a36Sopenharmony_ci .size = SZ_16M 59162306a36Sopenharmony_ci }; 59262306a36Sopenharmony_ci struct region r2 = { 59362306a36Sopenharmony_ci .base = SZ_512M, 59462306a36Sopenharmony_ci .size = SZ_512M 59562306a36Sopenharmony_ci }; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci PREFIX_PUSH(); 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci reset_memblock_regions(); 60062306a36Sopenharmony_ci memblock_reserve(r1.base, r1.size); 60162306a36Sopenharmony_ci memblock_reserve(r2.base, r2.size); 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci ASSERT_EQ(rgn1->base, r1.base); 60462306a36Sopenharmony_ci ASSERT_EQ(rgn1->size, r1.size); 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci ASSERT_EQ(rgn2->base, r2.base); 60762306a36Sopenharmony_ci ASSERT_EQ(rgn2->size, r2.size); 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 2); 61062306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, r1.size + r2.size); 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci test_pass_pop(); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci return 0; 61562306a36Sopenharmony_ci} 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci/* 61862306a36Sopenharmony_ci * A test that tries to mark two memory blocks r1 and r2 as reserved, 61962306a36Sopenharmony_ci * where r2 overlaps with the beginning of r1 (that is 62062306a36Sopenharmony_ci * r1.base < r2.base + r2.size): 62162306a36Sopenharmony_ci * 62262306a36Sopenharmony_ci * | +--------------+--+--------------+ | 62362306a36Sopenharmony_ci * | | r2 | | r1 | | 62462306a36Sopenharmony_ci * +--+--------------+--+--------------+--+ 62562306a36Sopenharmony_ci * ^ ^ 62662306a36Sopenharmony_ci * | | 62762306a36Sopenharmony_ci * | r1.base 62862306a36Sopenharmony_ci * | 62962306a36Sopenharmony_ci * r2.base 63062306a36Sopenharmony_ci * 63162306a36Sopenharmony_ci * Expect to merge two entries into one region that starts at r2.base and 63262306a36Sopenharmony_ci * has size of two regions minus their intersection. The total size of the 63362306a36Sopenharmony_ci * reserved memory is updated, and the region counter is not updated. 63462306a36Sopenharmony_ci */ 63562306a36Sopenharmony_cistatic int memblock_reserve_overlap_top_check(void) 63662306a36Sopenharmony_ci{ 63762306a36Sopenharmony_ci struct memblock_region *rgn; 63862306a36Sopenharmony_ci phys_addr_t total_size; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci rgn = &memblock.reserved.regions[0]; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci struct region r1 = { 64362306a36Sopenharmony_ci .base = SZ_1G, 64462306a36Sopenharmony_ci .size = SZ_1G 64562306a36Sopenharmony_ci }; 64662306a36Sopenharmony_ci struct region r2 = { 64762306a36Sopenharmony_ci .base = SZ_128M, 64862306a36Sopenharmony_ci .size = SZ_1G 64962306a36Sopenharmony_ci }; 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci PREFIX_PUSH(); 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci total_size = (r1.base - r2.base) + r1.size; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci reset_memblock_regions(); 65662306a36Sopenharmony_ci memblock_reserve(r1.base, r1.size); 65762306a36Sopenharmony_ci memblock_reserve(r2.base, r2.size); 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r2.base); 66062306a36Sopenharmony_ci ASSERT_EQ(rgn->size, total_size); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 1); 66362306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, total_size); 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci test_pass_pop(); 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci return 0; 66862306a36Sopenharmony_ci} 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci/* 67162306a36Sopenharmony_ci * A test that tries to mark two memory blocks r1 and r2 as reserved, 67262306a36Sopenharmony_ci * where r2 overlaps with the end of r1 (that is 67362306a36Sopenharmony_ci * r2.base < r1.base + r1.size): 67462306a36Sopenharmony_ci * 67562306a36Sopenharmony_ci * | +--------------+--+--------------+ | 67662306a36Sopenharmony_ci * | | r1 | | r2 | | 67762306a36Sopenharmony_ci * +--+--------------+--+--------------+--+ 67862306a36Sopenharmony_ci * ^ ^ 67962306a36Sopenharmony_ci * | | 68062306a36Sopenharmony_ci * | r2.base 68162306a36Sopenharmony_ci * | 68262306a36Sopenharmony_ci * r1.base 68362306a36Sopenharmony_ci * 68462306a36Sopenharmony_ci * Expect to merge two entries into one region that starts at r1.base and 68562306a36Sopenharmony_ci * has size of two regions minus their intersection. The total size of the 68662306a36Sopenharmony_ci * reserved memory is updated, and the region counter is not updated. 68762306a36Sopenharmony_ci */ 68862306a36Sopenharmony_cistatic int memblock_reserve_overlap_bottom_check(void) 68962306a36Sopenharmony_ci{ 69062306a36Sopenharmony_ci struct memblock_region *rgn; 69162306a36Sopenharmony_ci phys_addr_t total_size; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci rgn = &memblock.reserved.regions[0]; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci struct region r1 = { 69662306a36Sopenharmony_ci .base = SZ_2K, 69762306a36Sopenharmony_ci .size = SZ_128K 69862306a36Sopenharmony_ci }; 69962306a36Sopenharmony_ci struct region r2 = { 70062306a36Sopenharmony_ci .base = SZ_128K, 70162306a36Sopenharmony_ci .size = SZ_128K 70262306a36Sopenharmony_ci }; 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci PREFIX_PUSH(); 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci total_size = (r2.base - r1.base) + r2.size; 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci reset_memblock_regions(); 70962306a36Sopenharmony_ci memblock_reserve(r1.base, r1.size); 71062306a36Sopenharmony_ci memblock_reserve(r2.base, r2.size); 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r1.base); 71362306a36Sopenharmony_ci ASSERT_EQ(rgn->size, total_size); 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 1); 71662306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, total_size); 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci test_pass_pop(); 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci return 0; 72162306a36Sopenharmony_ci} 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci/* 72462306a36Sopenharmony_ci * A test that tries to mark two memory blocks r1 and r2 as reserved, 72562306a36Sopenharmony_ci * where r2 is within the range of r1 (that is 72662306a36Sopenharmony_ci * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)): 72762306a36Sopenharmony_ci * 72862306a36Sopenharmony_ci * | +-----+--+---------------------------| 72962306a36Sopenharmony_ci * | | |r2| r1 | 73062306a36Sopenharmony_ci * +-+-----+--+---------------------------+ 73162306a36Sopenharmony_ci * ^ ^ 73262306a36Sopenharmony_ci * | | 73362306a36Sopenharmony_ci * | r2.base 73462306a36Sopenharmony_ci * | 73562306a36Sopenharmony_ci * r1.base 73662306a36Sopenharmony_ci * 73762306a36Sopenharmony_ci * Expect to merge two entries into one region that stays the same. The 73862306a36Sopenharmony_ci * counter and total size of available memory are not updated. 73962306a36Sopenharmony_ci */ 74062306a36Sopenharmony_cistatic int memblock_reserve_within_check(void) 74162306a36Sopenharmony_ci{ 74262306a36Sopenharmony_ci struct memblock_region *rgn; 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci rgn = &memblock.reserved.regions[0]; 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci struct region r1 = { 74762306a36Sopenharmony_ci .base = SZ_1M, 74862306a36Sopenharmony_ci .size = SZ_8M 74962306a36Sopenharmony_ci }; 75062306a36Sopenharmony_ci struct region r2 = { 75162306a36Sopenharmony_ci .base = SZ_2M, 75262306a36Sopenharmony_ci .size = SZ_64K 75362306a36Sopenharmony_ci }; 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci PREFIX_PUSH(); 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci reset_memblock_regions(); 75862306a36Sopenharmony_ci memblock_reserve(r1.base, r1.size); 75962306a36Sopenharmony_ci memblock_reserve(r2.base, r2.size); 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r1.base); 76262306a36Sopenharmony_ci ASSERT_EQ(rgn->size, r1.size); 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 1); 76562306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, r1.size); 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci test_pass_pop(); 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci return 0; 77062306a36Sopenharmony_ci} 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci/* 77362306a36Sopenharmony_ci * A simple test that tries to reserve the same memory block twice. 77462306a36Sopenharmony_ci * Expect the region counter and total size of reserved memory to not 77562306a36Sopenharmony_ci * be updated. 77662306a36Sopenharmony_ci */ 77762306a36Sopenharmony_cistatic int memblock_reserve_twice_check(void) 77862306a36Sopenharmony_ci{ 77962306a36Sopenharmony_ci struct region r = { 78062306a36Sopenharmony_ci .base = SZ_16K, 78162306a36Sopenharmony_ci .size = SZ_2M 78262306a36Sopenharmony_ci }; 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci PREFIX_PUSH(); 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci reset_memblock_regions(); 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci memblock_reserve(r.base, r.size); 78962306a36Sopenharmony_ci memblock_reserve(r.base, r.size); 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 1); 79262306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, r.size); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci test_pass_pop(); 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci return 0; 79762306a36Sopenharmony_ci} 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci/* 80062306a36Sopenharmony_ci * A test that tries to mark two memory blocks that don't overlap as reserved 80162306a36Sopenharmony_ci * and then reserve a third memory block in the space between the first two: 80262306a36Sopenharmony_ci * 80362306a36Sopenharmony_ci * | +--------+--------+--------+ | 80462306a36Sopenharmony_ci * | | r1 | r3 | r2 | | 80562306a36Sopenharmony_ci * +--------+--------+--------+--------+--+ 80662306a36Sopenharmony_ci * 80762306a36Sopenharmony_ci * Expect to merge the three entries into one reserved region that starts at 80862306a36Sopenharmony_ci * r1.base and has size of r1.size + r2.size + r3.size. The region counter and 80962306a36Sopenharmony_ci * total for memblock.reserved are updated. 81062306a36Sopenharmony_ci */ 81162306a36Sopenharmony_cistatic int memblock_reserve_between_check(void) 81262306a36Sopenharmony_ci{ 81362306a36Sopenharmony_ci struct memblock_region *rgn; 81462306a36Sopenharmony_ci phys_addr_t total_size; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci rgn = &memblock.reserved.regions[0]; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci struct region r1 = { 81962306a36Sopenharmony_ci .base = SZ_1G, 82062306a36Sopenharmony_ci .size = SZ_8K 82162306a36Sopenharmony_ci }; 82262306a36Sopenharmony_ci struct region r2 = { 82362306a36Sopenharmony_ci .base = SZ_1G + SZ_16K, 82462306a36Sopenharmony_ci .size = SZ_8K 82562306a36Sopenharmony_ci }; 82662306a36Sopenharmony_ci struct region r3 = { 82762306a36Sopenharmony_ci .base = SZ_1G + SZ_8K, 82862306a36Sopenharmony_ci .size = SZ_8K 82962306a36Sopenharmony_ci }; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci PREFIX_PUSH(); 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci total_size = r1.size + r2.size + r3.size; 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci reset_memblock_regions(); 83662306a36Sopenharmony_ci memblock_reserve(r1.base, r1.size); 83762306a36Sopenharmony_ci memblock_reserve(r2.base, r2.size); 83862306a36Sopenharmony_ci memblock_reserve(r3.base, r3.size); 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r1.base); 84162306a36Sopenharmony_ci ASSERT_EQ(rgn->size, total_size); 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 1); 84462306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, total_size); 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci test_pass_pop(); 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci return 0; 84962306a36Sopenharmony_ci} 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci/* 85262306a36Sopenharmony_ci * A simple test that tries to reserve a memory block r when r extends past 85362306a36Sopenharmony_ci * PHYS_ADDR_MAX: 85462306a36Sopenharmony_ci * 85562306a36Sopenharmony_ci * +--------+ 85662306a36Sopenharmony_ci * | r | 85762306a36Sopenharmony_ci * +--------+ 85862306a36Sopenharmony_ci * | +----+ 85962306a36Sopenharmony_ci * | | rgn| 86062306a36Sopenharmony_ci * +----------------------------+----+ 86162306a36Sopenharmony_ci * 86262306a36Sopenharmony_ci * Expect to reserve a memory block of size PHYS_ADDR_MAX - r.base. Expect the 86362306a36Sopenharmony_ci * total size of reserved memory and the counter to be updated. 86462306a36Sopenharmony_ci */ 86562306a36Sopenharmony_cistatic int memblock_reserve_near_max_check(void) 86662306a36Sopenharmony_ci{ 86762306a36Sopenharmony_ci struct memblock_region *rgn; 86862306a36Sopenharmony_ci phys_addr_t total_size; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci rgn = &memblock.reserved.regions[0]; 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci struct region r = { 87362306a36Sopenharmony_ci .base = PHYS_ADDR_MAX - SZ_1M, 87462306a36Sopenharmony_ci .size = SZ_2M 87562306a36Sopenharmony_ci }; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci PREFIX_PUSH(); 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci total_size = PHYS_ADDR_MAX - r.base; 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci reset_memblock_regions(); 88262306a36Sopenharmony_ci memblock_reserve(r.base, r.size); 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r.base); 88562306a36Sopenharmony_ci ASSERT_EQ(rgn->size, total_size); 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 1); 88862306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, total_size); 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci test_pass_pop(); 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci return 0; 89362306a36Sopenharmony_ci} 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci/* 89662306a36Sopenharmony_ci * A test that trying to reserve the 129th memory block. 89762306a36Sopenharmony_ci * Expect to trigger memblock_double_array() to double the 89862306a36Sopenharmony_ci * memblock.memory.max, find a new valid memory as 89962306a36Sopenharmony_ci * reserved.regions. 90062306a36Sopenharmony_ci */ 90162306a36Sopenharmony_cistatic int memblock_reserve_many_check(void) 90262306a36Sopenharmony_ci{ 90362306a36Sopenharmony_ci int i; 90462306a36Sopenharmony_ci void *orig_region; 90562306a36Sopenharmony_ci struct region r = { 90662306a36Sopenharmony_ci .base = SZ_16K, 90762306a36Sopenharmony_ci .size = SZ_16K, 90862306a36Sopenharmony_ci }; 90962306a36Sopenharmony_ci phys_addr_t memory_base = SZ_128K; 91062306a36Sopenharmony_ci phys_addr_t new_reserved_regions_size; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci PREFIX_PUSH(); 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci reset_memblock_regions(); 91562306a36Sopenharmony_ci memblock_allow_resize(); 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci /* Add a valid memory region used by double_array(). */ 91862306a36Sopenharmony_ci dummy_physical_memory_init(); 91962306a36Sopenharmony_ci memblock_add(dummy_physical_memory_base(), MEM_SIZE); 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci for (i = 0; i < INIT_MEMBLOCK_REGIONS; i++) { 92262306a36Sopenharmony_ci /* Reserve some fakes memory region to fulfill the memblock. */ 92362306a36Sopenharmony_ci memblock_reserve(memory_base, MEM_SIZE); 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, i + 1); 92662306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, (i + 1) * MEM_SIZE); 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci /* Keep the gap so these memory region will not be merged. */ 92962306a36Sopenharmony_ci memory_base += MEM_SIZE * 2; 93062306a36Sopenharmony_ci } 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci orig_region = memblock.reserved.regions; 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci /* This reserve the 129 memory_region, and makes it double array. */ 93562306a36Sopenharmony_ci memblock_reserve(memory_base, MEM_SIZE); 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci /* 93862306a36Sopenharmony_ci * This is the memory region size used by the doubled reserved.regions, 93962306a36Sopenharmony_ci * and it has been reserved due to it has been used. The size is used to 94062306a36Sopenharmony_ci * calculate the total_size that the memblock.reserved have now. 94162306a36Sopenharmony_ci */ 94262306a36Sopenharmony_ci new_reserved_regions_size = PAGE_ALIGN((INIT_MEMBLOCK_REGIONS * 2) * 94362306a36Sopenharmony_ci sizeof(struct memblock_region)); 94462306a36Sopenharmony_ci /* 94562306a36Sopenharmony_ci * The double_array() will find a free memory region as the new 94662306a36Sopenharmony_ci * reserved.regions, and the used memory region will be reserved, so 94762306a36Sopenharmony_ci * there will be one more region exist in the reserved memblock. And the 94862306a36Sopenharmony_ci * one more reserved region's size is new_reserved_regions_size. 94962306a36Sopenharmony_ci */ 95062306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 2); 95162306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE + 95262306a36Sopenharmony_ci new_reserved_regions_size); 95362306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2); 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci /* 95662306a36Sopenharmony_ci * Now memblock_double_array() works fine. Let's check after the 95762306a36Sopenharmony_ci * double_array(), the memblock_reserve() still works as normal. 95862306a36Sopenharmony_ci */ 95962306a36Sopenharmony_ci memblock_reserve(r.base, r.size); 96062306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.regions[0].base, r.base); 96162306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.regions[0].size, r.size); 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 3); 96462306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE + 96562306a36Sopenharmony_ci new_reserved_regions_size + 96662306a36Sopenharmony_ci r.size); 96762306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2); 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci dummy_physical_memory_cleanup(); 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci /* 97262306a36Sopenharmony_ci * The current reserved.regions is occupying a range of memory that 97362306a36Sopenharmony_ci * allocated from dummy_physical_memory_init(). After free the memory, 97462306a36Sopenharmony_ci * we must not use it. So restore the origin memory region to make sure 97562306a36Sopenharmony_ci * the tests can run as normal and not affected by the double array. 97662306a36Sopenharmony_ci */ 97762306a36Sopenharmony_ci memblock.reserved.regions = orig_region; 97862306a36Sopenharmony_ci memblock.reserved.cnt = INIT_MEMBLOCK_RESERVED_REGIONS; 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci test_pass_pop(); 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci return 0; 98362306a36Sopenharmony_ci} 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_cistatic int memblock_reserve_checks(void) 98662306a36Sopenharmony_ci{ 98762306a36Sopenharmony_ci prefix_reset(); 98862306a36Sopenharmony_ci prefix_push(FUNC_RESERVE); 98962306a36Sopenharmony_ci test_print("Running %s tests...\n", FUNC_RESERVE); 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci memblock_reserve_simple_check(); 99262306a36Sopenharmony_ci memblock_reserve_disjoint_check(); 99362306a36Sopenharmony_ci memblock_reserve_overlap_top_check(); 99462306a36Sopenharmony_ci memblock_reserve_overlap_bottom_check(); 99562306a36Sopenharmony_ci memblock_reserve_within_check(); 99662306a36Sopenharmony_ci memblock_reserve_twice_check(); 99762306a36Sopenharmony_ci memblock_reserve_between_check(); 99862306a36Sopenharmony_ci memblock_reserve_near_max_check(); 99962306a36Sopenharmony_ci memblock_reserve_many_check(); 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci prefix_pop(); 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci return 0; 100462306a36Sopenharmony_ci} 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci/* 100762306a36Sopenharmony_ci * A simple test that tries to remove a region r1 from the array of 100862306a36Sopenharmony_ci * available memory regions. By "removing" a region we mean overwriting it 100962306a36Sopenharmony_ci * with the next region r2 in memblock.memory: 101062306a36Sopenharmony_ci * 101162306a36Sopenharmony_ci * | ...... +----------------+ | 101262306a36Sopenharmony_ci * | : r1 : | r2 | | 101362306a36Sopenharmony_ci * +--+----+----------+----------------+--+ 101462306a36Sopenharmony_ci * ^ 101562306a36Sopenharmony_ci * | 101662306a36Sopenharmony_ci * rgn.base 101762306a36Sopenharmony_ci * 101862306a36Sopenharmony_ci * Expect to add two memory blocks r1 and r2 and then remove r1 so that 101962306a36Sopenharmony_ci * r2 is the first available region. The region counter and total size 102062306a36Sopenharmony_ci * are updated. 102162306a36Sopenharmony_ci */ 102262306a36Sopenharmony_cistatic int memblock_remove_simple_check(void) 102362306a36Sopenharmony_ci{ 102462306a36Sopenharmony_ci struct memblock_region *rgn; 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci struct region r1 = { 102962306a36Sopenharmony_ci .base = SZ_2K, 103062306a36Sopenharmony_ci .size = SZ_4K 103162306a36Sopenharmony_ci }; 103262306a36Sopenharmony_ci struct region r2 = { 103362306a36Sopenharmony_ci .base = SZ_128K, 103462306a36Sopenharmony_ci .size = SZ_4M 103562306a36Sopenharmony_ci }; 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci PREFIX_PUSH(); 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci reset_memblock_regions(); 104062306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 104162306a36Sopenharmony_ci memblock_add(r2.base, r2.size); 104262306a36Sopenharmony_ci memblock_remove(r1.base, r1.size); 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r2.base); 104562306a36Sopenharmony_ci ASSERT_EQ(rgn->size, r2.size); 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 104862306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, r2.size); 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci test_pass_pop(); 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci return 0; 105362306a36Sopenharmony_ci} 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci/* 105662306a36Sopenharmony_ci * A test that tries to remove a region r2 that was not registered as 105762306a36Sopenharmony_ci * available memory (i.e. has no corresponding entry in memblock.memory): 105862306a36Sopenharmony_ci * 105962306a36Sopenharmony_ci * +----------------+ 106062306a36Sopenharmony_ci * | r2 | 106162306a36Sopenharmony_ci * +----------------+ 106262306a36Sopenharmony_ci * | +----+ | 106362306a36Sopenharmony_ci * | | r1 | | 106462306a36Sopenharmony_ci * +--+----+------------------------------+ 106562306a36Sopenharmony_ci * ^ 106662306a36Sopenharmony_ci * | 106762306a36Sopenharmony_ci * rgn.base 106862306a36Sopenharmony_ci * 106962306a36Sopenharmony_ci * Expect the array, regions counter and total size to not be modified. 107062306a36Sopenharmony_ci */ 107162306a36Sopenharmony_cistatic int memblock_remove_absent_check(void) 107262306a36Sopenharmony_ci{ 107362306a36Sopenharmony_ci struct memblock_region *rgn; 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci struct region r1 = { 107862306a36Sopenharmony_ci .base = SZ_512K, 107962306a36Sopenharmony_ci .size = SZ_4M 108062306a36Sopenharmony_ci }; 108162306a36Sopenharmony_ci struct region r2 = { 108262306a36Sopenharmony_ci .base = SZ_64M, 108362306a36Sopenharmony_ci .size = SZ_1G 108462306a36Sopenharmony_ci }; 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci PREFIX_PUSH(); 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci reset_memblock_regions(); 108962306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 109062306a36Sopenharmony_ci memblock_remove(r2.base, r2.size); 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r1.base); 109362306a36Sopenharmony_ci ASSERT_EQ(rgn->size, r1.size); 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 109662306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, r1.size); 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci test_pass_pop(); 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci return 0; 110162306a36Sopenharmony_ci} 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci/* 110462306a36Sopenharmony_ci * A test that tries to remove a region r2 that overlaps with the 110562306a36Sopenharmony_ci * beginning of the already existing entry r1 110662306a36Sopenharmony_ci * (that is r1.base < r2.base + r2.size): 110762306a36Sopenharmony_ci * 110862306a36Sopenharmony_ci * +-----------------+ 110962306a36Sopenharmony_ci * | r2 | 111062306a36Sopenharmony_ci * +-----------------+ 111162306a36Sopenharmony_ci * | .........+--------+ | 111262306a36Sopenharmony_ci * | : r1 | rgn | | 111362306a36Sopenharmony_ci * +-----------------+--------+--------+--+ 111462306a36Sopenharmony_ci * ^ ^ 111562306a36Sopenharmony_ci * | | 111662306a36Sopenharmony_ci * | rgn.base 111762306a36Sopenharmony_ci * r1.base 111862306a36Sopenharmony_ci * 111962306a36Sopenharmony_ci * Expect that only the intersection of both regions is removed from the 112062306a36Sopenharmony_ci * available memory pool. The regions counter and total size are updated. 112162306a36Sopenharmony_ci */ 112262306a36Sopenharmony_cistatic int memblock_remove_overlap_top_check(void) 112362306a36Sopenharmony_ci{ 112462306a36Sopenharmony_ci struct memblock_region *rgn; 112562306a36Sopenharmony_ci phys_addr_t r1_end, r2_end, total_size; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci struct region r1 = { 113062306a36Sopenharmony_ci .base = SZ_32M, 113162306a36Sopenharmony_ci .size = SZ_32M 113262306a36Sopenharmony_ci }; 113362306a36Sopenharmony_ci struct region r2 = { 113462306a36Sopenharmony_ci .base = SZ_16M, 113562306a36Sopenharmony_ci .size = SZ_32M 113662306a36Sopenharmony_ci }; 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci PREFIX_PUSH(); 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci r1_end = r1.base + r1.size; 114162306a36Sopenharmony_ci r2_end = r2.base + r2.size; 114262306a36Sopenharmony_ci total_size = r1_end - r2_end; 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci reset_memblock_regions(); 114562306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 114662306a36Sopenharmony_ci memblock_remove(r2.base, r2.size); 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r1.base + r2.base); 114962306a36Sopenharmony_ci ASSERT_EQ(rgn->size, total_size); 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 115262306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, total_size); 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci test_pass_pop(); 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci return 0; 115762306a36Sopenharmony_ci} 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci/* 116062306a36Sopenharmony_ci * A test that tries to remove a region r2 that overlaps with the end of 116162306a36Sopenharmony_ci * the already existing region r1 (that is r2.base < r1.base + r1.size): 116262306a36Sopenharmony_ci * 116362306a36Sopenharmony_ci * +--------------------------------+ 116462306a36Sopenharmony_ci * | r2 | 116562306a36Sopenharmony_ci * +--------------------------------+ 116662306a36Sopenharmony_ci * | +---+..... | 116762306a36Sopenharmony_ci * | |rgn| r1 : | 116862306a36Sopenharmony_ci * +-+---+----+---------------------------+ 116962306a36Sopenharmony_ci * ^ 117062306a36Sopenharmony_ci * | 117162306a36Sopenharmony_ci * r1.base 117262306a36Sopenharmony_ci * 117362306a36Sopenharmony_ci * Expect that only the intersection of both regions is removed from the 117462306a36Sopenharmony_ci * available memory pool. The regions counter and total size are updated. 117562306a36Sopenharmony_ci */ 117662306a36Sopenharmony_cistatic int memblock_remove_overlap_bottom_check(void) 117762306a36Sopenharmony_ci{ 117862306a36Sopenharmony_ci struct memblock_region *rgn; 117962306a36Sopenharmony_ci phys_addr_t total_size; 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci struct region r1 = { 118462306a36Sopenharmony_ci .base = SZ_2M, 118562306a36Sopenharmony_ci .size = SZ_64M 118662306a36Sopenharmony_ci }; 118762306a36Sopenharmony_ci struct region r2 = { 118862306a36Sopenharmony_ci .base = SZ_32M, 118962306a36Sopenharmony_ci .size = SZ_256M 119062306a36Sopenharmony_ci }; 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci PREFIX_PUSH(); 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci total_size = r2.base - r1.base; 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci reset_memblock_regions(); 119762306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 119862306a36Sopenharmony_ci memblock_remove(r2.base, r2.size); 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r1.base); 120162306a36Sopenharmony_ci ASSERT_EQ(rgn->size, total_size); 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 120462306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, total_size); 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci test_pass_pop(); 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci return 0; 120962306a36Sopenharmony_ci} 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci/* 121262306a36Sopenharmony_ci * A test that tries to remove a region r2 that is within the range of 121362306a36Sopenharmony_ci * the already existing entry r1 (that is 121462306a36Sopenharmony_ci * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)): 121562306a36Sopenharmony_ci * 121662306a36Sopenharmony_ci * +----+ 121762306a36Sopenharmony_ci * | r2 | 121862306a36Sopenharmony_ci * +----+ 121962306a36Sopenharmony_ci * | +-------------+....+---------------+ | 122062306a36Sopenharmony_ci * | | rgn1 | r1 | rgn2 | | 122162306a36Sopenharmony_ci * +-+-------------+----+---------------+-+ 122262306a36Sopenharmony_ci * ^ 122362306a36Sopenharmony_ci * | 122462306a36Sopenharmony_ci * r1.base 122562306a36Sopenharmony_ci * 122662306a36Sopenharmony_ci * Expect that the region is split into two - one that ends at r2.base and 122762306a36Sopenharmony_ci * another that starts at r2.base + r2.size, with appropriate sizes. The 122862306a36Sopenharmony_ci * region counter and total size are updated. 122962306a36Sopenharmony_ci */ 123062306a36Sopenharmony_cistatic int memblock_remove_within_check(void) 123162306a36Sopenharmony_ci{ 123262306a36Sopenharmony_ci struct memblock_region *rgn1, *rgn2; 123362306a36Sopenharmony_ci phys_addr_t r1_size, r2_size, total_size; 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci rgn1 = &memblock.memory.regions[0]; 123662306a36Sopenharmony_ci rgn2 = &memblock.memory.regions[1]; 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci struct region r1 = { 123962306a36Sopenharmony_ci .base = SZ_1M, 124062306a36Sopenharmony_ci .size = SZ_32M 124162306a36Sopenharmony_ci }; 124262306a36Sopenharmony_ci struct region r2 = { 124362306a36Sopenharmony_ci .base = SZ_16M, 124462306a36Sopenharmony_ci .size = SZ_1M 124562306a36Sopenharmony_ci }; 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci PREFIX_PUSH(); 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci r1_size = r2.base - r1.base; 125062306a36Sopenharmony_ci r2_size = (r1.base + r1.size) - (r2.base + r2.size); 125162306a36Sopenharmony_ci total_size = r1_size + r2_size; 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci reset_memblock_regions(); 125462306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 125562306a36Sopenharmony_ci memblock_remove(r2.base, r2.size); 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci ASSERT_EQ(rgn1->base, r1.base); 125862306a36Sopenharmony_ci ASSERT_EQ(rgn1->size, r1_size); 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci ASSERT_EQ(rgn2->base, r2.base + r2.size); 126162306a36Sopenharmony_ci ASSERT_EQ(rgn2->size, r2_size); 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 2); 126462306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, total_size); 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci test_pass_pop(); 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci return 0; 126962306a36Sopenharmony_ci} 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci/* 127262306a36Sopenharmony_ci * A simple test that tries to remove a region r1 from the array of 127362306a36Sopenharmony_ci * available memory regions when r1 is the only available region. 127462306a36Sopenharmony_ci * Expect to add a memory block r1 and then remove r1 so that a dummy 127562306a36Sopenharmony_ci * region is added. The region counter stays the same, and the total size 127662306a36Sopenharmony_ci * is updated. 127762306a36Sopenharmony_ci */ 127862306a36Sopenharmony_cistatic int memblock_remove_only_region_check(void) 127962306a36Sopenharmony_ci{ 128062306a36Sopenharmony_ci struct memblock_region *rgn; 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci struct region r1 = { 128562306a36Sopenharmony_ci .base = SZ_2K, 128662306a36Sopenharmony_ci .size = SZ_4K 128762306a36Sopenharmony_ci }; 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci PREFIX_PUSH(); 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci reset_memblock_regions(); 129262306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 129362306a36Sopenharmony_ci memblock_remove(r1.base, r1.size); 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci ASSERT_EQ(rgn->base, 0); 129662306a36Sopenharmony_ci ASSERT_EQ(rgn->size, 0); 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 129962306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, 0); 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci test_pass_pop(); 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci return 0; 130462306a36Sopenharmony_ci} 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci/* 130762306a36Sopenharmony_ci * A simple test that tries remove a region r2 from the array of available 130862306a36Sopenharmony_ci * memory regions when r2 extends past PHYS_ADDR_MAX: 130962306a36Sopenharmony_ci * 131062306a36Sopenharmony_ci * +--------+ 131162306a36Sopenharmony_ci * | r2 | 131262306a36Sopenharmony_ci * +--------+ 131362306a36Sopenharmony_ci * | +---+....+ 131462306a36Sopenharmony_ci * | |rgn| | 131562306a36Sopenharmony_ci * +------------------------+---+----+ 131662306a36Sopenharmony_ci * 131762306a36Sopenharmony_ci * Expect that only the portion between PHYS_ADDR_MAX and r2.base is removed. 131862306a36Sopenharmony_ci * Expect the total size of available memory to be updated and the counter to 131962306a36Sopenharmony_ci * not be updated. 132062306a36Sopenharmony_ci */ 132162306a36Sopenharmony_cistatic int memblock_remove_near_max_check(void) 132262306a36Sopenharmony_ci{ 132362306a36Sopenharmony_ci struct memblock_region *rgn; 132462306a36Sopenharmony_ci phys_addr_t total_size; 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci struct region r1 = { 132962306a36Sopenharmony_ci .base = PHYS_ADDR_MAX - SZ_2M, 133062306a36Sopenharmony_ci .size = SZ_2M 133162306a36Sopenharmony_ci }; 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci struct region r2 = { 133462306a36Sopenharmony_ci .base = PHYS_ADDR_MAX - SZ_1M, 133562306a36Sopenharmony_ci .size = SZ_2M 133662306a36Sopenharmony_ci }; 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci PREFIX_PUSH(); 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci total_size = r1.size - (PHYS_ADDR_MAX - r2.base); 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci reset_memblock_regions(); 134362306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 134462306a36Sopenharmony_ci memblock_remove(r2.base, r2.size); 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r1.base); 134762306a36Sopenharmony_ci ASSERT_EQ(rgn->size, total_size); 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 135062306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, total_size); 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci test_pass_pop(); 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci return 0; 135562306a36Sopenharmony_ci} 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci/* 135862306a36Sopenharmony_ci * A test that tries to remove a region r3 that overlaps with two existing 135962306a36Sopenharmony_ci * regions r1 and r2: 136062306a36Sopenharmony_ci * 136162306a36Sopenharmony_ci * +----------------+ 136262306a36Sopenharmony_ci * | r3 | 136362306a36Sopenharmony_ci * +----------------+ 136462306a36Sopenharmony_ci * | +----+..... ........+--------+ 136562306a36Sopenharmony_ci * | | |r1 : : |r2 | | 136662306a36Sopenharmony_ci * +----+----+----+---+-------+--------+-----+ 136762306a36Sopenharmony_ci * 136862306a36Sopenharmony_ci * Expect that only the intersections of r1 with r3 and r2 with r3 are removed 136962306a36Sopenharmony_ci * from the available memory pool. Expect the total size of available memory to 137062306a36Sopenharmony_ci * be updated and the counter to not be updated. 137162306a36Sopenharmony_ci */ 137262306a36Sopenharmony_cistatic int memblock_remove_overlap_two_check(void) 137362306a36Sopenharmony_ci{ 137462306a36Sopenharmony_ci struct memblock_region *rgn1, *rgn2; 137562306a36Sopenharmony_ci phys_addr_t new_r1_size, new_r2_size, r2_end, r3_end, total_size; 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci rgn1 = &memblock.memory.regions[0]; 137862306a36Sopenharmony_ci rgn2 = &memblock.memory.regions[1]; 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci struct region r1 = { 138162306a36Sopenharmony_ci .base = SZ_16M, 138262306a36Sopenharmony_ci .size = SZ_32M 138362306a36Sopenharmony_ci }; 138462306a36Sopenharmony_ci struct region r2 = { 138562306a36Sopenharmony_ci .base = SZ_64M, 138662306a36Sopenharmony_ci .size = SZ_64M 138762306a36Sopenharmony_ci }; 138862306a36Sopenharmony_ci struct region r3 = { 138962306a36Sopenharmony_ci .base = SZ_32M, 139062306a36Sopenharmony_ci .size = SZ_64M 139162306a36Sopenharmony_ci }; 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci PREFIX_PUSH(); 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci r2_end = r2.base + r2.size; 139662306a36Sopenharmony_ci r3_end = r3.base + r3.size; 139762306a36Sopenharmony_ci new_r1_size = r3.base - r1.base; 139862306a36Sopenharmony_ci new_r2_size = r2_end - r3_end; 139962306a36Sopenharmony_ci total_size = new_r1_size + new_r2_size; 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_ci reset_memblock_regions(); 140262306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 140362306a36Sopenharmony_ci memblock_add(r2.base, r2.size); 140462306a36Sopenharmony_ci memblock_remove(r3.base, r3.size); 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci ASSERT_EQ(rgn1->base, r1.base); 140762306a36Sopenharmony_ci ASSERT_EQ(rgn1->size, new_r1_size); 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci ASSERT_EQ(rgn2->base, r3_end); 141062306a36Sopenharmony_ci ASSERT_EQ(rgn2->size, new_r2_size); 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 2); 141362306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.total_size, total_size); 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_ci test_pass_pop(); 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci return 0; 141862306a36Sopenharmony_ci} 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_cistatic int memblock_remove_checks(void) 142162306a36Sopenharmony_ci{ 142262306a36Sopenharmony_ci prefix_reset(); 142362306a36Sopenharmony_ci prefix_push(FUNC_REMOVE); 142462306a36Sopenharmony_ci test_print("Running %s tests...\n", FUNC_REMOVE); 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci memblock_remove_simple_check(); 142762306a36Sopenharmony_ci memblock_remove_absent_check(); 142862306a36Sopenharmony_ci memblock_remove_overlap_top_check(); 142962306a36Sopenharmony_ci memblock_remove_overlap_bottom_check(); 143062306a36Sopenharmony_ci memblock_remove_within_check(); 143162306a36Sopenharmony_ci memblock_remove_only_region_check(); 143262306a36Sopenharmony_ci memblock_remove_near_max_check(); 143362306a36Sopenharmony_ci memblock_remove_overlap_two_check(); 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci prefix_pop(); 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci return 0; 143862306a36Sopenharmony_ci} 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci/* 144162306a36Sopenharmony_ci * A simple test that tries to free a memory block r1 that was marked 144262306a36Sopenharmony_ci * earlier as reserved. By "freeing" a region we mean overwriting it with 144362306a36Sopenharmony_ci * the next entry r2 in memblock.reserved: 144462306a36Sopenharmony_ci * 144562306a36Sopenharmony_ci * | ...... +----+ | 144662306a36Sopenharmony_ci * | : r1 : | r2 | | 144762306a36Sopenharmony_ci * +--------------+----+-----------+----+-+ 144862306a36Sopenharmony_ci * ^ 144962306a36Sopenharmony_ci * | 145062306a36Sopenharmony_ci * rgn.base 145162306a36Sopenharmony_ci * 145262306a36Sopenharmony_ci * Expect to reserve two memory regions and then erase r1 region with the 145362306a36Sopenharmony_ci * value of r2. The region counter and total size are updated. 145462306a36Sopenharmony_ci */ 145562306a36Sopenharmony_cistatic int memblock_free_simple_check(void) 145662306a36Sopenharmony_ci{ 145762306a36Sopenharmony_ci struct memblock_region *rgn; 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci rgn = &memblock.reserved.regions[0]; 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci struct region r1 = { 146262306a36Sopenharmony_ci .base = SZ_4M, 146362306a36Sopenharmony_ci .size = SZ_1M 146462306a36Sopenharmony_ci }; 146562306a36Sopenharmony_ci struct region r2 = { 146662306a36Sopenharmony_ci .base = SZ_8M, 146762306a36Sopenharmony_ci .size = SZ_1M 146862306a36Sopenharmony_ci }; 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci PREFIX_PUSH(); 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci reset_memblock_regions(); 147362306a36Sopenharmony_ci memblock_reserve(r1.base, r1.size); 147462306a36Sopenharmony_ci memblock_reserve(r2.base, r2.size); 147562306a36Sopenharmony_ci memblock_free((void *)r1.base, r1.size); 147662306a36Sopenharmony_ci 147762306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r2.base); 147862306a36Sopenharmony_ci ASSERT_EQ(rgn->size, r2.size); 147962306a36Sopenharmony_ci 148062306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 1); 148162306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, r2.size); 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci test_pass_pop(); 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci return 0; 148662306a36Sopenharmony_ci} 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci/* 148962306a36Sopenharmony_ci * A test that tries to free a region r2 that was not marked as reserved 149062306a36Sopenharmony_ci * (i.e. has no corresponding entry in memblock.reserved): 149162306a36Sopenharmony_ci * 149262306a36Sopenharmony_ci * +----------------+ 149362306a36Sopenharmony_ci * | r2 | 149462306a36Sopenharmony_ci * +----------------+ 149562306a36Sopenharmony_ci * | +----+ | 149662306a36Sopenharmony_ci * | | r1 | | 149762306a36Sopenharmony_ci * +--+----+------------------------------+ 149862306a36Sopenharmony_ci * ^ 149962306a36Sopenharmony_ci * | 150062306a36Sopenharmony_ci * rgn.base 150162306a36Sopenharmony_ci * 150262306a36Sopenharmony_ci * The array, regions counter and total size are not modified. 150362306a36Sopenharmony_ci */ 150462306a36Sopenharmony_cistatic int memblock_free_absent_check(void) 150562306a36Sopenharmony_ci{ 150662306a36Sopenharmony_ci struct memblock_region *rgn; 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci rgn = &memblock.reserved.regions[0]; 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci struct region r1 = { 151162306a36Sopenharmony_ci .base = SZ_2M, 151262306a36Sopenharmony_ci .size = SZ_8K 151362306a36Sopenharmony_ci }; 151462306a36Sopenharmony_ci struct region r2 = { 151562306a36Sopenharmony_ci .base = SZ_16M, 151662306a36Sopenharmony_ci .size = SZ_128M 151762306a36Sopenharmony_ci }; 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci PREFIX_PUSH(); 152062306a36Sopenharmony_ci 152162306a36Sopenharmony_ci reset_memblock_regions(); 152262306a36Sopenharmony_ci memblock_reserve(r1.base, r1.size); 152362306a36Sopenharmony_ci memblock_free((void *)r2.base, r2.size); 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r1.base); 152662306a36Sopenharmony_ci ASSERT_EQ(rgn->size, r1.size); 152762306a36Sopenharmony_ci 152862306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 1); 152962306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, r1.size); 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_ci test_pass_pop(); 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_ci return 0; 153462306a36Sopenharmony_ci} 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_ci/* 153762306a36Sopenharmony_ci * A test that tries to free a region r2 that overlaps with the beginning 153862306a36Sopenharmony_ci * of the already existing entry r1 (that is r1.base < r2.base + r2.size): 153962306a36Sopenharmony_ci * 154062306a36Sopenharmony_ci * +----+ 154162306a36Sopenharmony_ci * | r2 | 154262306a36Sopenharmony_ci * +----+ 154362306a36Sopenharmony_ci * | ...+--------------+ | 154462306a36Sopenharmony_ci * | : | r1 | | 154562306a36Sopenharmony_ci * +----+--+--------------+---------------+ 154662306a36Sopenharmony_ci * ^ ^ 154762306a36Sopenharmony_ci * | | 154862306a36Sopenharmony_ci * | rgn.base 154962306a36Sopenharmony_ci * | 155062306a36Sopenharmony_ci * r1.base 155162306a36Sopenharmony_ci * 155262306a36Sopenharmony_ci * Expect that only the intersection of both regions is freed. The 155362306a36Sopenharmony_ci * regions counter and total size are updated. 155462306a36Sopenharmony_ci */ 155562306a36Sopenharmony_cistatic int memblock_free_overlap_top_check(void) 155662306a36Sopenharmony_ci{ 155762306a36Sopenharmony_ci struct memblock_region *rgn; 155862306a36Sopenharmony_ci phys_addr_t total_size; 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci rgn = &memblock.reserved.regions[0]; 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_ci struct region r1 = { 156362306a36Sopenharmony_ci .base = SZ_8M, 156462306a36Sopenharmony_ci .size = SZ_32M 156562306a36Sopenharmony_ci }; 156662306a36Sopenharmony_ci struct region r2 = { 156762306a36Sopenharmony_ci .base = SZ_1M, 156862306a36Sopenharmony_ci .size = SZ_8M 156962306a36Sopenharmony_ci }; 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci PREFIX_PUSH(); 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ci total_size = (r1.size + r1.base) - (r2.base + r2.size); 157462306a36Sopenharmony_ci 157562306a36Sopenharmony_ci reset_memblock_regions(); 157662306a36Sopenharmony_ci memblock_reserve(r1.base, r1.size); 157762306a36Sopenharmony_ci memblock_free((void *)r2.base, r2.size); 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r2.base + r2.size); 158062306a36Sopenharmony_ci ASSERT_EQ(rgn->size, total_size); 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 1); 158362306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, total_size); 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_ci test_pass_pop(); 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_ci return 0; 158862306a36Sopenharmony_ci} 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_ci/* 159162306a36Sopenharmony_ci * A test that tries to free a region r2 that overlaps with the end of 159262306a36Sopenharmony_ci * the already existing entry r1 (that is r2.base < r1.base + r1.size): 159362306a36Sopenharmony_ci * 159462306a36Sopenharmony_ci * +----------------+ 159562306a36Sopenharmony_ci * | r2 | 159662306a36Sopenharmony_ci * +----------------+ 159762306a36Sopenharmony_ci * | +-----------+..... | 159862306a36Sopenharmony_ci * | | r1 | : | 159962306a36Sopenharmony_ci * +----+-----------+----+----------------+ 160062306a36Sopenharmony_ci * 160162306a36Sopenharmony_ci * Expect that only the intersection of both regions is freed. The 160262306a36Sopenharmony_ci * regions counter and total size are updated. 160362306a36Sopenharmony_ci */ 160462306a36Sopenharmony_cistatic int memblock_free_overlap_bottom_check(void) 160562306a36Sopenharmony_ci{ 160662306a36Sopenharmony_ci struct memblock_region *rgn; 160762306a36Sopenharmony_ci phys_addr_t total_size; 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci rgn = &memblock.reserved.regions[0]; 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_ci struct region r1 = { 161262306a36Sopenharmony_ci .base = SZ_8M, 161362306a36Sopenharmony_ci .size = SZ_32M 161462306a36Sopenharmony_ci }; 161562306a36Sopenharmony_ci struct region r2 = { 161662306a36Sopenharmony_ci .base = SZ_32M, 161762306a36Sopenharmony_ci .size = SZ_32M 161862306a36Sopenharmony_ci }; 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci PREFIX_PUSH(); 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci total_size = r2.base - r1.base; 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_ci reset_memblock_regions(); 162562306a36Sopenharmony_ci memblock_reserve(r1.base, r1.size); 162662306a36Sopenharmony_ci memblock_free((void *)r2.base, r2.size); 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r1.base); 162962306a36Sopenharmony_ci ASSERT_EQ(rgn->size, total_size); 163062306a36Sopenharmony_ci 163162306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 1); 163262306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, total_size); 163362306a36Sopenharmony_ci 163462306a36Sopenharmony_ci test_pass_pop(); 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_ci return 0; 163762306a36Sopenharmony_ci} 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci/* 164062306a36Sopenharmony_ci * A test that tries to free a region r2 that is within the range of the 164162306a36Sopenharmony_ci * already existing entry r1 (that is 164262306a36Sopenharmony_ci * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)): 164362306a36Sopenharmony_ci * 164462306a36Sopenharmony_ci * +----+ 164562306a36Sopenharmony_ci * | r2 | 164662306a36Sopenharmony_ci * +----+ 164762306a36Sopenharmony_ci * | +------------+....+---------------+ 164862306a36Sopenharmony_ci * | | rgn1 | r1 | rgn2 | 164962306a36Sopenharmony_ci * +----+------------+----+---------------+ 165062306a36Sopenharmony_ci * ^ 165162306a36Sopenharmony_ci * | 165262306a36Sopenharmony_ci * r1.base 165362306a36Sopenharmony_ci * 165462306a36Sopenharmony_ci * Expect that the region is split into two - one that ends at r2.base and 165562306a36Sopenharmony_ci * another that starts at r2.base + r2.size, with appropriate sizes. The 165662306a36Sopenharmony_ci * region counter and total size fields are updated. 165762306a36Sopenharmony_ci */ 165862306a36Sopenharmony_cistatic int memblock_free_within_check(void) 165962306a36Sopenharmony_ci{ 166062306a36Sopenharmony_ci struct memblock_region *rgn1, *rgn2; 166162306a36Sopenharmony_ci phys_addr_t r1_size, r2_size, total_size; 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci rgn1 = &memblock.reserved.regions[0]; 166462306a36Sopenharmony_ci rgn2 = &memblock.reserved.regions[1]; 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci struct region r1 = { 166762306a36Sopenharmony_ci .base = SZ_1M, 166862306a36Sopenharmony_ci .size = SZ_8M 166962306a36Sopenharmony_ci }; 167062306a36Sopenharmony_ci struct region r2 = { 167162306a36Sopenharmony_ci .base = SZ_4M, 167262306a36Sopenharmony_ci .size = SZ_1M 167362306a36Sopenharmony_ci }; 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_ci PREFIX_PUSH(); 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci r1_size = r2.base - r1.base; 167862306a36Sopenharmony_ci r2_size = (r1.base + r1.size) - (r2.base + r2.size); 167962306a36Sopenharmony_ci total_size = r1_size + r2_size; 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ci reset_memblock_regions(); 168262306a36Sopenharmony_ci memblock_reserve(r1.base, r1.size); 168362306a36Sopenharmony_ci memblock_free((void *)r2.base, r2.size); 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci ASSERT_EQ(rgn1->base, r1.base); 168662306a36Sopenharmony_ci ASSERT_EQ(rgn1->size, r1_size); 168762306a36Sopenharmony_ci 168862306a36Sopenharmony_ci ASSERT_EQ(rgn2->base, r2.base + r2.size); 168962306a36Sopenharmony_ci ASSERT_EQ(rgn2->size, r2_size); 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 2); 169262306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, total_size); 169362306a36Sopenharmony_ci 169462306a36Sopenharmony_ci test_pass_pop(); 169562306a36Sopenharmony_ci 169662306a36Sopenharmony_ci return 0; 169762306a36Sopenharmony_ci} 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ci/* 170062306a36Sopenharmony_ci * A simple test that tries to free a memory block r1 that was marked 170162306a36Sopenharmony_ci * earlier as reserved when r1 is the only available region. 170262306a36Sopenharmony_ci * Expect to reserve a memory block r1 and then free r1 so that r1 is 170362306a36Sopenharmony_ci * overwritten with a dummy region. The region counter stays the same, 170462306a36Sopenharmony_ci * and the total size is updated. 170562306a36Sopenharmony_ci */ 170662306a36Sopenharmony_cistatic int memblock_free_only_region_check(void) 170762306a36Sopenharmony_ci{ 170862306a36Sopenharmony_ci struct memblock_region *rgn; 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_ci rgn = &memblock.reserved.regions[0]; 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_ci struct region r1 = { 171362306a36Sopenharmony_ci .base = SZ_2K, 171462306a36Sopenharmony_ci .size = SZ_4K 171562306a36Sopenharmony_ci }; 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci PREFIX_PUSH(); 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci reset_memblock_regions(); 172062306a36Sopenharmony_ci memblock_reserve(r1.base, r1.size); 172162306a36Sopenharmony_ci memblock_free((void *)r1.base, r1.size); 172262306a36Sopenharmony_ci 172362306a36Sopenharmony_ci ASSERT_EQ(rgn->base, 0); 172462306a36Sopenharmony_ci ASSERT_EQ(rgn->size, 0); 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 1); 172762306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, 0); 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci test_pass_pop(); 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci return 0; 173262306a36Sopenharmony_ci} 173362306a36Sopenharmony_ci 173462306a36Sopenharmony_ci/* 173562306a36Sopenharmony_ci * A simple test that tries free a region r2 when r2 extends past PHYS_ADDR_MAX: 173662306a36Sopenharmony_ci * 173762306a36Sopenharmony_ci * +--------+ 173862306a36Sopenharmony_ci * | r2 | 173962306a36Sopenharmony_ci * +--------+ 174062306a36Sopenharmony_ci * | +---+....+ 174162306a36Sopenharmony_ci * | |rgn| | 174262306a36Sopenharmony_ci * +------------------------+---+----+ 174362306a36Sopenharmony_ci * 174462306a36Sopenharmony_ci * Expect that only the portion between PHYS_ADDR_MAX and r2.base is freed. 174562306a36Sopenharmony_ci * Expect the total size of reserved memory to be updated and the counter to 174662306a36Sopenharmony_ci * not be updated. 174762306a36Sopenharmony_ci */ 174862306a36Sopenharmony_cistatic int memblock_free_near_max_check(void) 174962306a36Sopenharmony_ci{ 175062306a36Sopenharmony_ci struct memblock_region *rgn; 175162306a36Sopenharmony_ci phys_addr_t total_size; 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_ci rgn = &memblock.reserved.regions[0]; 175462306a36Sopenharmony_ci 175562306a36Sopenharmony_ci struct region r1 = { 175662306a36Sopenharmony_ci .base = PHYS_ADDR_MAX - SZ_2M, 175762306a36Sopenharmony_ci .size = SZ_2M 175862306a36Sopenharmony_ci }; 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci struct region r2 = { 176162306a36Sopenharmony_ci .base = PHYS_ADDR_MAX - SZ_1M, 176262306a36Sopenharmony_ci .size = SZ_2M 176362306a36Sopenharmony_ci }; 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci PREFIX_PUSH(); 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_ci total_size = r1.size - (PHYS_ADDR_MAX - r2.base); 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci reset_memblock_regions(); 177062306a36Sopenharmony_ci memblock_reserve(r1.base, r1.size); 177162306a36Sopenharmony_ci memblock_free((void *)r2.base, r2.size); 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r1.base); 177462306a36Sopenharmony_ci ASSERT_EQ(rgn->size, total_size); 177562306a36Sopenharmony_ci 177662306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 1); 177762306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, total_size); 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci test_pass_pop(); 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci return 0; 178262306a36Sopenharmony_ci} 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci/* 178562306a36Sopenharmony_ci * A test that tries to free a reserved region r3 that overlaps with two 178662306a36Sopenharmony_ci * existing reserved regions r1 and r2: 178762306a36Sopenharmony_ci * 178862306a36Sopenharmony_ci * +----------------+ 178962306a36Sopenharmony_ci * | r3 | 179062306a36Sopenharmony_ci * +----------------+ 179162306a36Sopenharmony_ci * | +----+..... ........+--------+ 179262306a36Sopenharmony_ci * | | |r1 : : |r2 | | 179362306a36Sopenharmony_ci * +----+----+----+---+-------+--------+-----+ 179462306a36Sopenharmony_ci * 179562306a36Sopenharmony_ci * Expect that only the intersections of r1 with r3 and r2 with r3 are freed 179662306a36Sopenharmony_ci * from the collection of reserved memory. Expect the total size of reserved 179762306a36Sopenharmony_ci * memory to be updated and the counter to not be updated. 179862306a36Sopenharmony_ci */ 179962306a36Sopenharmony_cistatic int memblock_free_overlap_two_check(void) 180062306a36Sopenharmony_ci{ 180162306a36Sopenharmony_ci struct memblock_region *rgn1, *rgn2; 180262306a36Sopenharmony_ci phys_addr_t new_r1_size, new_r2_size, r2_end, r3_end, total_size; 180362306a36Sopenharmony_ci 180462306a36Sopenharmony_ci rgn1 = &memblock.reserved.regions[0]; 180562306a36Sopenharmony_ci rgn2 = &memblock.reserved.regions[1]; 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci struct region r1 = { 180862306a36Sopenharmony_ci .base = SZ_16M, 180962306a36Sopenharmony_ci .size = SZ_32M 181062306a36Sopenharmony_ci }; 181162306a36Sopenharmony_ci struct region r2 = { 181262306a36Sopenharmony_ci .base = SZ_64M, 181362306a36Sopenharmony_ci .size = SZ_64M 181462306a36Sopenharmony_ci }; 181562306a36Sopenharmony_ci struct region r3 = { 181662306a36Sopenharmony_ci .base = SZ_32M, 181762306a36Sopenharmony_ci .size = SZ_64M 181862306a36Sopenharmony_ci }; 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci PREFIX_PUSH(); 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_ci r2_end = r2.base + r2.size; 182362306a36Sopenharmony_ci r3_end = r3.base + r3.size; 182462306a36Sopenharmony_ci new_r1_size = r3.base - r1.base; 182562306a36Sopenharmony_ci new_r2_size = r2_end - r3_end; 182662306a36Sopenharmony_ci total_size = new_r1_size + new_r2_size; 182762306a36Sopenharmony_ci 182862306a36Sopenharmony_ci reset_memblock_regions(); 182962306a36Sopenharmony_ci memblock_reserve(r1.base, r1.size); 183062306a36Sopenharmony_ci memblock_reserve(r2.base, r2.size); 183162306a36Sopenharmony_ci memblock_free((void *)r3.base, r3.size); 183262306a36Sopenharmony_ci 183362306a36Sopenharmony_ci ASSERT_EQ(rgn1->base, r1.base); 183462306a36Sopenharmony_ci ASSERT_EQ(rgn1->size, new_r1_size); 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci ASSERT_EQ(rgn2->base, r3_end); 183762306a36Sopenharmony_ci ASSERT_EQ(rgn2->size, new_r2_size); 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.cnt, 2); 184062306a36Sopenharmony_ci ASSERT_EQ(memblock.reserved.total_size, total_size); 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_ci test_pass_pop(); 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_ci return 0; 184562306a36Sopenharmony_ci} 184662306a36Sopenharmony_ci 184762306a36Sopenharmony_cistatic int memblock_free_checks(void) 184862306a36Sopenharmony_ci{ 184962306a36Sopenharmony_ci prefix_reset(); 185062306a36Sopenharmony_ci prefix_push(FUNC_FREE); 185162306a36Sopenharmony_ci test_print("Running %s tests...\n", FUNC_FREE); 185262306a36Sopenharmony_ci 185362306a36Sopenharmony_ci memblock_free_simple_check(); 185462306a36Sopenharmony_ci memblock_free_absent_check(); 185562306a36Sopenharmony_ci memblock_free_overlap_top_check(); 185662306a36Sopenharmony_ci memblock_free_overlap_bottom_check(); 185762306a36Sopenharmony_ci memblock_free_within_check(); 185862306a36Sopenharmony_ci memblock_free_only_region_check(); 185962306a36Sopenharmony_ci memblock_free_near_max_check(); 186062306a36Sopenharmony_ci memblock_free_overlap_two_check(); 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci prefix_pop(); 186362306a36Sopenharmony_ci 186462306a36Sopenharmony_ci return 0; 186562306a36Sopenharmony_ci} 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_cistatic int memblock_set_bottom_up_check(void) 186862306a36Sopenharmony_ci{ 186962306a36Sopenharmony_ci prefix_push("memblock_set_bottom_up"); 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci memblock_set_bottom_up(false); 187262306a36Sopenharmony_ci ASSERT_EQ(memblock.bottom_up, false); 187362306a36Sopenharmony_ci memblock_set_bottom_up(true); 187462306a36Sopenharmony_ci ASSERT_EQ(memblock.bottom_up, true); 187562306a36Sopenharmony_ci 187662306a36Sopenharmony_ci reset_memblock_attributes(); 187762306a36Sopenharmony_ci test_pass_pop(); 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_ci return 0; 188062306a36Sopenharmony_ci} 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_cistatic int memblock_bottom_up_check(void) 188362306a36Sopenharmony_ci{ 188462306a36Sopenharmony_ci prefix_push("memblock_bottom_up"); 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci memblock_set_bottom_up(false); 188762306a36Sopenharmony_ci ASSERT_EQ(memblock_bottom_up(), memblock.bottom_up); 188862306a36Sopenharmony_ci ASSERT_EQ(memblock_bottom_up(), false); 188962306a36Sopenharmony_ci memblock_set_bottom_up(true); 189062306a36Sopenharmony_ci ASSERT_EQ(memblock_bottom_up(), memblock.bottom_up); 189162306a36Sopenharmony_ci ASSERT_EQ(memblock_bottom_up(), true); 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_ci reset_memblock_attributes(); 189462306a36Sopenharmony_ci test_pass_pop(); 189562306a36Sopenharmony_ci 189662306a36Sopenharmony_ci return 0; 189762306a36Sopenharmony_ci} 189862306a36Sopenharmony_ci 189962306a36Sopenharmony_cistatic int memblock_bottom_up_checks(void) 190062306a36Sopenharmony_ci{ 190162306a36Sopenharmony_ci test_print("Running memblock_*bottom_up tests...\n"); 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_ci prefix_reset(); 190462306a36Sopenharmony_ci memblock_set_bottom_up_check(); 190562306a36Sopenharmony_ci prefix_reset(); 190662306a36Sopenharmony_ci memblock_bottom_up_check(); 190762306a36Sopenharmony_ci 190862306a36Sopenharmony_ci return 0; 190962306a36Sopenharmony_ci} 191062306a36Sopenharmony_ci 191162306a36Sopenharmony_ci/* 191262306a36Sopenharmony_ci * A test that tries to trim memory when both ends of the memory region are 191362306a36Sopenharmony_ci * aligned. Expect that the memory will not be trimmed. Expect the counter to 191462306a36Sopenharmony_ci * not be updated. 191562306a36Sopenharmony_ci */ 191662306a36Sopenharmony_cistatic int memblock_trim_memory_aligned_check(void) 191762306a36Sopenharmony_ci{ 191862306a36Sopenharmony_ci struct memblock_region *rgn; 191962306a36Sopenharmony_ci const phys_addr_t alignment = SMP_CACHE_BYTES; 192062306a36Sopenharmony_ci 192162306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_ci struct region r = { 192462306a36Sopenharmony_ci .base = alignment, 192562306a36Sopenharmony_ci .size = alignment * 4 192662306a36Sopenharmony_ci }; 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci PREFIX_PUSH(); 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci reset_memblock_regions(); 193162306a36Sopenharmony_ci memblock_add(r.base, r.size); 193262306a36Sopenharmony_ci memblock_trim_memory(alignment); 193362306a36Sopenharmony_ci 193462306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r.base); 193562306a36Sopenharmony_ci ASSERT_EQ(rgn->size, r.size); 193662306a36Sopenharmony_ci 193762306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 193862306a36Sopenharmony_ci 193962306a36Sopenharmony_ci test_pass_pop(); 194062306a36Sopenharmony_ci 194162306a36Sopenharmony_ci return 0; 194262306a36Sopenharmony_ci} 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci/* 194562306a36Sopenharmony_ci * A test that tries to trim memory when there are two available regions, r1 and 194662306a36Sopenharmony_ci * r2. Region r1 is aligned on both ends and region r2 is unaligned on one end 194762306a36Sopenharmony_ci * and smaller than the alignment: 194862306a36Sopenharmony_ci * 194962306a36Sopenharmony_ci * alignment 195062306a36Sopenharmony_ci * |--------| 195162306a36Sopenharmony_ci * | +-----------------+ +------+ | 195262306a36Sopenharmony_ci * | | r1 | | r2 | | 195362306a36Sopenharmony_ci * +--------+-----------------+--------+------+---+ 195462306a36Sopenharmony_ci * ^ ^ ^ ^ ^ 195562306a36Sopenharmony_ci * |________|________|________| | 195662306a36Sopenharmony_ci * | Unaligned address 195762306a36Sopenharmony_ci * Aligned addresses 195862306a36Sopenharmony_ci * 195962306a36Sopenharmony_ci * Expect that r1 will not be trimmed and r2 will be removed. Expect the 196062306a36Sopenharmony_ci * counter to be updated. 196162306a36Sopenharmony_ci */ 196262306a36Sopenharmony_cistatic int memblock_trim_memory_too_small_check(void) 196362306a36Sopenharmony_ci{ 196462306a36Sopenharmony_ci struct memblock_region *rgn; 196562306a36Sopenharmony_ci const phys_addr_t alignment = SMP_CACHE_BYTES; 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci rgn = &memblock.memory.regions[0]; 196862306a36Sopenharmony_ci 196962306a36Sopenharmony_ci struct region r1 = { 197062306a36Sopenharmony_ci .base = alignment, 197162306a36Sopenharmony_ci .size = alignment * 2 197262306a36Sopenharmony_ci }; 197362306a36Sopenharmony_ci struct region r2 = { 197462306a36Sopenharmony_ci .base = alignment * 4, 197562306a36Sopenharmony_ci .size = alignment - SZ_2 197662306a36Sopenharmony_ci }; 197762306a36Sopenharmony_ci 197862306a36Sopenharmony_ci PREFIX_PUSH(); 197962306a36Sopenharmony_ci 198062306a36Sopenharmony_ci reset_memblock_regions(); 198162306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 198262306a36Sopenharmony_ci memblock_add(r2.base, r2.size); 198362306a36Sopenharmony_ci memblock_trim_memory(alignment); 198462306a36Sopenharmony_ci 198562306a36Sopenharmony_ci ASSERT_EQ(rgn->base, r1.base); 198662306a36Sopenharmony_ci ASSERT_EQ(rgn->size, r1.size); 198762306a36Sopenharmony_ci 198862306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 1); 198962306a36Sopenharmony_ci 199062306a36Sopenharmony_ci test_pass_pop(); 199162306a36Sopenharmony_ci 199262306a36Sopenharmony_ci return 0; 199362306a36Sopenharmony_ci} 199462306a36Sopenharmony_ci 199562306a36Sopenharmony_ci/* 199662306a36Sopenharmony_ci * A test that tries to trim memory when there are two available regions, r1 and 199762306a36Sopenharmony_ci * r2. Region r1 is aligned on both ends and region r2 is unaligned at the base 199862306a36Sopenharmony_ci * and aligned at the end: 199962306a36Sopenharmony_ci * 200062306a36Sopenharmony_ci * Unaligned address 200162306a36Sopenharmony_ci * | 200262306a36Sopenharmony_ci * v 200362306a36Sopenharmony_ci * | +-----------------+ +---------------+ | 200462306a36Sopenharmony_ci * | | r1 | | r2 | | 200562306a36Sopenharmony_ci * +--------+-----------------+----------+---------------+---+ 200662306a36Sopenharmony_ci * ^ ^ ^ ^ ^ ^ 200762306a36Sopenharmony_ci * |________|________|________|________|________| 200862306a36Sopenharmony_ci * | 200962306a36Sopenharmony_ci * Aligned addresses 201062306a36Sopenharmony_ci * 201162306a36Sopenharmony_ci * Expect that r1 will not be trimmed and r2 will be trimmed at the base. 201262306a36Sopenharmony_ci * Expect the counter to not be updated. 201362306a36Sopenharmony_ci */ 201462306a36Sopenharmony_cistatic int memblock_trim_memory_unaligned_base_check(void) 201562306a36Sopenharmony_ci{ 201662306a36Sopenharmony_ci struct memblock_region *rgn1, *rgn2; 201762306a36Sopenharmony_ci const phys_addr_t alignment = SMP_CACHE_BYTES; 201862306a36Sopenharmony_ci phys_addr_t offset = SZ_2; 201962306a36Sopenharmony_ci phys_addr_t new_r2_base, new_r2_size; 202062306a36Sopenharmony_ci 202162306a36Sopenharmony_ci rgn1 = &memblock.memory.regions[0]; 202262306a36Sopenharmony_ci rgn2 = &memblock.memory.regions[1]; 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_ci struct region r1 = { 202562306a36Sopenharmony_ci .base = alignment, 202662306a36Sopenharmony_ci .size = alignment * 2 202762306a36Sopenharmony_ci }; 202862306a36Sopenharmony_ci struct region r2 = { 202962306a36Sopenharmony_ci .base = alignment * 4 + offset, 203062306a36Sopenharmony_ci .size = alignment * 2 - offset 203162306a36Sopenharmony_ci }; 203262306a36Sopenharmony_ci 203362306a36Sopenharmony_ci PREFIX_PUSH(); 203462306a36Sopenharmony_ci 203562306a36Sopenharmony_ci new_r2_base = r2.base + (alignment - offset); 203662306a36Sopenharmony_ci new_r2_size = r2.size - (alignment - offset); 203762306a36Sopenharmony_ci 203862306a36Sopenharmony_ci reset_memblock_regions(); 203962306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 204062306a36Sopenharmony_ci memblock_add(r2.base, r2.size); 204162306a36Sopenharmony_ci memblock_trim_memory(alignment); 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_ci ASSERT_EQ(rgn1->base, r1.base); 204462306a36Sopenharmony_ci ASSERT_EQ(rgn1->size, r1.size); 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci ASSERT_EQ(rgn2->base, new_r2_base); 204762306a36Sopenharmony_ci ASSERT_EQ(rgn2->size, new_r2_size); 204862306a36Sopenharmony_ci 204962306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 2); 205062306a36Sopenharmony_ci 205162306a36Sopenharmony_ci test_pass_pop(); 205262306a36Sopenharmony_ci 205362306a36Sopenharmony_ci return 0; 205462306a36Sopenharmony_ci} 205562306a36Sopenharmony_ci 205662306a36Sopenharmony_ci/* 205762306a36Sopenharmony_ci * A test that tries to trim memory when there are two available regions, r1 and 205862306a36Sopenharmony_ci * r2. Region r1 is aligned on both ends and region r2 is aligned at the base 205962306a36Sopenharmony_ci * and unaligned at the end: 206062306a36Sopenharmony_ci * 206162306a36Sopenharmony_ci * Unaligned address 206262306a36Sopenharmony_ci * | 206362306a36Sopenharmony_ci * v 206462306a36Sopenharmony_ci * | +-----------------+ +---------------+ | 206562306a36Sopenharmony_ci * | | r1 | | r2 | | 206662306a36Sopenharmony_ci * +--------+-----------------+--------+---------------+---+ 206762306a36Sopenharmony_ci * ^ ^ ^ ^ ^ ^ 206862306a36Sopenharmony_ci * |________|________|________|________|________| 206962306a36Sopenharmony_ci * | 207062306a36Sopenharmony_ci * Aligned addresses 207162306a36Sopenharmony_ci * 207262306a36Sopenharmony_ci * Expect that r1 will not be trimmed and r2 will be trimmed at the end. 207362306a36Sopenharmony_ci * Expect the counter to not be updated. 207462306a36Sopenharmony_ci */ 207562306a36Sopenharmony_cistatic int memblock_trim_memory_unaligned_end_check(void) 207662306a36Sopenharmony_ci{ 207762306a36Sopenharmony_ci struct memblock_region *rgn1, *rgn2; 207862306a36Sopenharmony_ci const phys_addr_t alignment = SMP_CACHE_BYTES; 207962306a36Sopenharmony_ci phys_addr_t offset = SZ_2; 208062306a36Sopenharmony_ci phys_addr_t new_r2_size; 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_ci rgn1 = &memblock.memory.regions[0]; 208362306a36Sopenharmony_ci rgn2 = &memblock.memory.regions[1]; 208462306a36Sopenharmony_ci 208562306a36Sopenharmony_ci struct region r1 = { 208662306a36Sopenharmony_ci .base = alignment, 208762306a36Sopenharmony_ci .size = alignment * 2 208862306a36Sopenharmony_ci }; 208962306a36Sopenharmony_ci struct region r2 = { 209062306a36Sopenharmony_ci .base = alignment * 4, 209162306a36Sopenharmony_ci .size = alignment * 2 - offset 209262306a36Sopenharmony_ci }; 209362306a36Sopenharmony_ci 209462306a36Sopenharmony_ci PREFIX_PUSH(); 209562306a36Sopenharmony_ci 209662306a36Sopenharmony_ci new_r2_size = r2.size - (alignment - offset); 209762306a36Sopenharmony_ci 209862306a36Sopenharmony_ci reset_memblock_regions(); 209962306a36Sopenharmony_ci memblock_add(r1.base, r1.size); 210062306a36Sopenharmony_ci memblock_add(r2.base, r2.size); 210162306a36Sopenharmony_ci memblock_trim_memory(alignment); 210262306a36Sopenharmony_ci 210362306a36Sopenharmony_ci ASSERT_EQ(rgn1->base, r1.base); 210462306a36Sopenharmony_ci ASSERT_EQ(rgn1->size, r1.size); 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_ci ASSERT_EQ(rgn2->base, r2.base); 210762306a36Sopenharmony_ci ASSERT_EQ(rgn2->size, new_r2_size); 210862306a36Sopenharmony_ci 210962306a36Sopenharmony_ci ASSERT_EQ(memblock.memory.cnt, 2); 211062306a36Sopenharmony_ci 211162306a36Sopenharmony_ci test_pass_pop(); 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_ci return 0; 211462306a36Sopenharmony_ci} 211562306a36Sopenharmony_ci 211662306a36Sopenharmony_cistatic int memblock_trim_memory_checks(void) 211762306a36Sopenharmony_ci{ 211862306a36Sopenharmony_ci prefix_reset(); 211962306a36Sopenharmony_ci prefix_push(FUNC_TRIM); 212062306a36Sopenharmony_ci test_print("Running %s tests...\n", FUNC_TRIM); 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_ci memblock_trim_memory_aligned_check(); 212362306a36Sopenharmony_ci memblock_trim_memory_too_small_check(); 212462306a36Sopenharmony_ci memblock_trim_memory_unaligned_base_check(); 212562306a36Sopenharmony_ci memblock_trim_memory_unaligned_end_check(); 212662306a36Sopenharmony_ci 212762306a36Sopenharmony_ci prefix_pop(); 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci return 0; 213062306a36Sopenharmony_ci} 213162306a36Sopenharmony_ci 213262306a36Sopenharmony_ciint memblock_basic_checks(void) 213362306a36Sopenharmony_ci{ 213462306a36Sopenharmony_ci memblock_initialization_check(); 213562306a36Sopenharmony_ci memblock_add_checks(); 213662306a36Sopenharmony_ci memblock_reserve_checks(); 213762306a36Sopenharmony_ci memblock_remove_checks(); 213862306a36Sopenharmony_ci memblock_free_checks(); 213962306a36Sopenharmony_ci memblock_bottom_up_checks(); 214062306a36Sopenharmony_ci memblock_trim_memory_checks(); 214162306a36Sopenharmony_ci 214262306a36Sopenharmony_ci return 0; 214362306a36Sopenharmony_ci} 2144