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