Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.14.15.
  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 */
 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 address
 57 *                       boundary
 58 *
 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 too
 92 * close to the end of the memory:
 93 *
 94 *              +        +
 95 *  |           +--------+---+      |
 96 *  |           |   rgn  +   |      |
 97 *  +-----------+--------+---+------+
 98 *              ^        ^
 99 *              |        |
100 *              |        min_addr
101 *              |
102 *              Aligned address
103 *              boundary
104 *
105 * Expect to prioritize granting memory over satisfying the minimal address
106 * 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 space
137 * available above the minimal address above a certain address:
138 *
139 *                     +
140 *  |        +---------+-------------|
141 *  |        |   rgn   |             |
142 *  +--------+---------+-------------+
143 *                     ^
144 *                     |
145 *                     min_addr
146 *
147 * Expect to prioritize granting memory over satisfying the minimal address
148 * requirement and to allocate next to the previously reserved region. The
149 * 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 below
184 * 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 too
220 * close to the end of the memory:
221 *
222 *                             +
223 *  |-----------+              +     |
224 *  |    rgn    |              |     |
225 *  +-----------+--------------+-----+
226 *  ^                          ^
227 *  |                          |
228 *  Aligned address            min_addr
229 *  boundary
230 *
231 * Expect to prioritize granting memory over satisfying the minimal address
232 * 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 space
263 * available above the minimal address above a certain address:
264 *
265 *                   +
266 *  |-----------+    +-------------------|
267 *  |    rgn    |    |                   |
268 *  +-----------+----+-------------------+
269 *                   ^
270 *                   |
271 *                   min_addr
272 *
273 * Expect to prioritize granting memory over satisfying the minimal address
274 * 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 below
309 * the start address of the available memory. Expect to allocate a region
310 * 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}