Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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 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 */
65static 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 */
116static 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 */
161static 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 */
200static 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 */
248static 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 */
292static 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 */
330static 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 */
361static 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
372static 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
383static 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
394static 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
405static 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
416int 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}