brintos

brintos / linux-shallow public Read only

0
0
Text · 10.5 KiB · 3ef9486 Raw
415 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2#include "alloc_helpers_api.h"3 4/*5 * A simple test that tries to allocate a memory region above a specified,6 * aligned address:7 *8 *             +9 *  |          +-----------+         |10 *  |          |    rgn    |         |11 *  +----------+-----------+---------+12 *             ^13 *             |14 *             Aligned min_addr15 *16 * Expect to allocate a cleared region at the minimal memory address.17 */18static int alloc_from_simple_generic_check(void)19{20	struct memblock_region *rgn = &memblock.reserved.regions[0];21	void *allocated_ptr = NULL;22	phys_addr_t size = SZ_16;23	phys_addr_t min_addr;24 25	PREFIX_PUSH();26	setup_memblock();27 28	min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES;29 30	allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);31 32	ASSERT_NE(allocated_ptr, NULL);33	ASSERT_MEM_EQ(allocated_ptr, 0, size);34 35	ASSERT_EQ(rgn->size, size);36	ASSERT_EQ(rgn->base, min_addr);37 38	ASSERT_EQ(memblock.reserved.cnt, 1);39	ASSERT_EQ(memblock.reserved.total_size, size);40 41	test_pass_pop();42 43	return 0;44}45 46/*47 * A test that tries to allocate a memory region above a certain address.48 * The minimal address here is not aligned:49 *50 *         +      +51 *  |      +      +---------+            |52 *  |      |      |   rgn   |            |53 *  +------+------+---------+------------+54 *         ^      ^------.55 *         |             |56 *       min_addr        Aligned address57 *                       boundary58 *59 * Expect to allocate a cleared region at the closest aligned memory address.60 */61static int alloc_from_misaligned_generic_check(void)62{63	struct memblock_region *rgn = &memblock.reserved.regions[0];64	void *allocated_ptr = NULL;65	phys_addr_t size = SZ_32;66	phys_addr_t min_addr;67 68	PREFIX_PUSH();69	setup_memblock();70 71	/* A misaligned address */72	min_addr = memblock_end_of_DRAM() - (SMP_CACHE_BYTES * 2 - 1);73 74	allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);75 76	ASSERT_NE(allocated_ptr, NULL);77	ASSERT_MEM_EQ(allocated_ptr, 0, size);78 79	ASSERT_EQ(rgn->size, size);80	ASSERT_EQ(rgn->base, memblock_end_of_DRAM() - SMP_CACHE_BYTES);81 82	ASSERT_EQ(memblock.reserved.cnt, 1);83	ASSERT_EQ(memblock.reserved.total_size, size);84 85	test_pass_pop();86 87	return 0;88}89 90/*91 * A test that tries to allocate a memory region above an address that is too92 * close to the end of the memory:93 *94 *              +        +95 *  |           +--------+---+      |96 *  |           |   rgn  +   |      |97 *  +-----------+--------+---+------+98 *              ^        ^99 *              |        |100 *              |        min_addr101 *              |102 *              Aligned address103 *              boundary104 *105 * Expect to prioritize granting memory over satisfying the minimal address106 * requirement.107 */108static int alloc_from_top_down_high_addr_check(void)109{110	struct memblock_region *rgn = &memblock.reserved.regions[0];111	void *allocated_ptr = NULL;112	phys_addr_t size = SZ_32;113	phys_addr_t min_addr;114 115	PREFIX_PUSH();116	setup_memblock();117 118	/* The address is too close to the end of the memory */119	min_addr = memblock_end_of_DRAM() - SZ_16;120 121	allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);122 123	ASSERT_NE(allocated_ptr, NULL);124	ASSERT_EQ(rgn->size, size);125	ASSERT_EQ(rgn->base, memblock_end_of_DRAM() - SMP_CACHE_BYTES);126 127	ASSERT_EQ(memblock.reserved.cnt, 1);128	ASSERT_EQ(memblock.reserved.total_size, size);129 130	test_pass_pop();131 132	return 0;133}134 135/*136 * A test that tries to allocate a memory region when there is no space137 * available above the minimal address above a certain address:138 *139 *                     +140 *  |        +---------+-------------|141 *  |        |   rgn   |             |142 *  +--------+---------+-------------+143 *                     ^144 *                     |145 *                     min_addr146 *147 * Expect to prioritize granting memory over satisfying the minimal address148 * requirement and to allocate next to the previously reserved region. The149 * regions get merged into one.150 */151static int alloc_from_top_down_no_space_above_check(void)152{153	struct memblock_region *rgn = &memblock.reserved.regions[0];154	void *allocated_ptr = NULL;155	phys_addr_t r1_size = SZ_64;156	phys_addr_t r2_size = SZ_2;157	phys_addr_t total_size = r1_size + r2_size;158	phys_addr_t min_addr;159 160	PREFIX_PUSH();161	setup_memblock();162 163	min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES * 2;164 165	/* No space above this address */166	memblock_reserve(min_addr, r2_size);167 168	allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);169 170	ASSERT_NE(allocated_ptr, NULL);171	ASSERT_EQ(rgn->base, min_addr - r1_size);172	ASSERT_EQ(rgn->size, total_size);173 174	ASSERT_EQ(memblock.reserved.cnt, 1);175	ASSERT_EQ(memblock.reserved.total_size, total_size);176 177	test_pass_pop();178 179	return 0;180}181 182/*183 * A test that tries to allocate a memory region with a minimal address below184 * the start address of the available memory. As the allocation is top-down,185 * first reserve a region that will force allocation near the start.186 * Expect successful allocation and merge of both regions.187 */188static int alloc_from_top_down_min_addr_cap_check(void)189{190	struct memblock_region *rgn = &memblock.reserved.regions[0];191	void *allocated_ptr = NULL;192	phys_addr_t r1_size = SZ_64;193	phys_addr_t min_addr;194	phys_addr_t start_addr;195 196	PREFIX_PUSH();197	setup_memblock();198 199	start_addr = (phys_addr_t)memblock_start_of_DRAM();200	min_addr = start_addr - SMP_CACHE_BYTES * 3;201 202	memblock_reserve(start_addr + r1_size, MEM_SIZE - r1_size);203 204	allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);205 206	ASSERT_NE(allocated_ptr, NULL);207	ASSERT_EQ(rgn->base, start_addr);208	ASSERT_EQ(rgn->size, MEM_SIZE);209 210	ASSERT_EQ(memblock.reserved.cnt, 1);211	ASSERT_EQ(memblock.reserved.total_size, MEM_SIZE);212 213	test_pass_pop();214 215	return 0;216}217 218/*219 * A test that tries to allocate a memory region above an address that is too220 * close to the end of the memory:221 *222 *                             +223 *  |-----------+              +     |224 *  |    rgn    |              |     |225 *  +-----------+--------------+-----+226 *  ^                          ^227 *  |                          |228 *  Aligned address            min_addr229 *  boundary230 *231 * Expect to prioritize granting memory over satisfying the minimal address232 * requirement. Allocation happens at beginning of the available memory.233 */234static int alloc_from_bottom_up_high_addr_check(void)235{236	struct memblock_region *rgn = &memblock.reserved.regions[0];237	void *allocated_ptr = NULL;238	phys_addr_t size = SZ_32;239	phys_addr_t min_addr;240 241	PREFIX_PUSH();242	setup_memblock();243 244	/* The address is too close to the end of the memory */245	min_addr = memblock_end_of_DRAM() - SZ_8;246 247	allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);248 249	ASSERT_NE(allocated_ptr, NULL);250	ASSERT_EQ(rgn->size, size);251	ASSERT_EQ(rgn->base, memblock_start_of_DRAM());252 253	ASSERT_EQ(memblock.reserved.cnt, 1);254	ASSERT_EQ(memblock.reserved.total_size, size);255 256	test_pass_pop();257 258	return 0;259}260 261/*262 * A test that tries to allocate a memory region when there is no space263 * available above the minimal address above a certain address:264 *265 *                   +266 *  |-----------+    +-------------------|267 *  |    rgn    |    |                   |268 *  +-----------+----+-------------------+269 *                   ^270 *                   |271 *                   min_addr272 *273 * Expect to prioritize granting memory over satisfying the minimal address274 * requirement and to allocate at the beginning of the available memory.275 */276static int alloc_from_bottom_up_no_space_above_check(void)277{278	struct memblock_region *rgn = &memblock.reserved.regions[0];279	void *allocated_ptr = NULL;280	phys_addr_t r1_size = SZ_64;281	phys_addr_t min_addr;282	phys_addr_t r2_size;283 284	PREFIX_PUSH();285	setup_memblock();286 287	min_addr = memblock_start_of_DRAM() + SZ_128;288	r2_size = memblock_end_of_DRAM() - min_addr;289 290	/* No space above this address */291	memblock_reserve(min_addr - SMP_CACHE_BYTES, r2_size);292 293	allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);294 295	ASSERT_NE(allocated_ptr, NULL);296	ASSERT_EQ(rgn->base, memblock_start_of_DRAM());297	ASSERT_EQ(rgn->size, r1_size);298 299	ASSERT_EQ(memblock.reserved.cnt, 2);300	ASSERT_EQ(memblock.reserved.total_size, r1_size + r2_size);301 302	test_pass_pop();303 304	return 0;305}306 307/*308 * A test that tries to allocate a memory region with a minimal address below309 * the start address of the available memory. Expect to allocate a region310 * at the beginning of the available memory.311 */312static int alloc_from_bottom_up_min_addr_cap_check(void)313{314	struct memblock_region *rgn = &memblock.reserved.regions[0];315	void *allocated_ptr = NULL;316	phys_addr_t r1_size = SZ_64;317	phys_addr_t min_addr;318	phys_addr_t start_addr;319 320	PREFIX_PUSH();321	setup_memblock();322 323	start_addr = (phys_addr_t)memblock_start_of_DRAM();324	min_addr = start_addr - SMP_CACHE_BYTES * 3;325 326	allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);327 328	ASSERT_NE(allocated_ptr, NULL);329	ASSERT_EQ(rgn->base, start_addr);330	ASSERT_EQ(rgn->size, r1_size);331 332	ASSERT_EQ(memblock.reserved.cnt, 1);333	ASSERT_EQ(memblock.reserved.total_size, r1_size);334 335	test_pass_pop();336 337	return 0;338}339 340/* Test case wrappers */341static int alloc_from_simple_check(void)342{343	test_print("\tRunning %s...\n", __func__);344	run_top_down(alloc_from_simple_generic_check);345	run_bottom_up(alloc_from_simple_generic_check);346 347	return 0;348}349 350static int alloc_from_misaligned_check(void)351{352	test_print("\tRunning %s...\n", __func__);353	run_top_down(alloc_from_misaligned_generic_check);354	run_bottom_up(alloc_from_misaligned_generic_check);355 356	return 0;357}358 359static int alloc_from_high_addr_check(void)360{361	test_print("\tRunning %s...\n", __func__);362	memblock_set_bottom_up(false);363	alloc_from_top_down_high_addr_check();364	memblock_set_bottom_up(true);365	alloc_from_bottom_up_high_addr_check();366 367	return 0;368}369 370static int alloc_from_no_space_above_check(void)371{372	test_print("\tRunning %s...\n", __func__);373	memblock_set_bottom_up(false);374	alloc_from_top_down_no_space_above_check();375	memblock_set_bottom_up(true);376	alloc_from_bottom_up_no_space_above_check();377 378	return 0;379}380 381static int alloc_from_min_addr_cap_check(void)382{383	test_print("\tRunning %s...\n", __func__);384	memblock_set_bottom_up(false);385	alloc_from_top_down_min_addr_cap_check();386	memblock_set_bottom_up(true);387	alloc_from_bottom_up_min_addr_cap_check();388 389	return 0;390}391 392int memblock_alloc_helpers_checks(void)393{394	const char *func_testing = "memblock_alloc_from";395 396	prefix_reset();397	prefix_push(func_testing);398	test_print("Running %s tests...\n", func_testing);399 400	reset_memblock_attributes();401	dummy_physical_memory_init();402 403	alloc_from_simple_check();404	alloc_from_misaligned_check();405	alloc_from_high_addr_check();406	alloc_from_no_space_above_check();407	alloc_from_min_addr_cap_check();408 409	dummy_physical_memory_cleanup();410 411	prefix_pop();412 413	return 0;414}415