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 phys_addr_t size = SZ_16;
25 phys_addr_t min_addr;
26
27 setup_memblock();
28
29 min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES;
30
31 allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
32 b = (char *)allocated_ptr;
33
34 assert(allocated_ptr);
35 assert(*b == 0);
36
37 assert(rgn->size == size);
38 assert(rgn->base == min_addr);
39
40 assert(memblock.reserved.cnt == 1);
41 assert(memblock.reserved.total_size == size);
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 char *b;
66
67 phys_addr_t size = SZ_32;
68 phys_addr_t min_addr;
69
70 setup_memblock();
71
72 /* A misaligned address */
73 min_addr = memblock_end_of_DRAM() - (SMP_CACHE_BYTES * 2 - 1);
74
75 allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
76 b = (char *)allocated_ptr;
77
78 assert(allocated_ptr);
79 assert(*b == 0);
80
81 assert(rgn->size == size);
82 assert(rgn->base == memblock_end_of_DRAM() - SMP_CACHE_BYTES);
83
84 assert(memblock.reserved.cnt == 1);
85 assert(memblock.reserved.total_size == size);
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
113 phys_addr_t size = SZ_32;
114 phys_addr_t min_addr;
115
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(allocated_ptr);
124 assert(rgn->size == size);
125 assert(rgn->base == memblock_end_of_DRAM() - SMP_CACHE_BYTES);
126
127 assert(memblock.reserved.cnt == 1);
128 assert(memblock.reserved.total_size == size);
129
130 return 0;
131}
132
133/*
134 * A test that tries to allocate a memory region when there is no space
135 * available above the minimal address above a certain address:
136 *
137 * +
138 * | +---------+-------------|
139 * | | rgn | |
140 * +--------+---------+-------------+
141 * ^
142 * |
143 * min_addr
144 *
145 * Expect to prioritize granting memory over satisfying the minimal address
146 * requirement and to allocate next to the previously reserved region. The
147 * regions get merged into one.
148 */
149static int alloc_from_top_down_no_space_above_check(void)
150{
151 struct memblock_region *rgn = &memblock.reserved.regions[0];
152 void *allocated_ptr = NULL;
153
154 phys_addr_t r1_size = SZ_64;
155 phys_addr_t r2_size = SZ_2;
156 phys_addr_t total_size = r1_size + r2_size;
157 phys_addr_t min_addr;
158
159 setup_memblock();
160
161 min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES * 2;
162
163 /* No space above this address */
164 memblock_reserve(min_addr, r2_size);
165
166 allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
167
168 assert(allocated_ptr);
169 assert(rgn->base == min_addr - r1_size);
170 assert(rgn->size == total_size);
171
172 assert(memblock.reserved.cnt == 1);
173 assert(memblock.reserved.total_size == total_size);
174
175 return 0;
176}
177
178/*
179 * A test that tries to allocate a memory region with a minimal address below
180 * the start address of the available memory. As the allocation is top-down,
181 * first reserve a region that will force allocation near the start.
182 * Expect successful allocation and merge of both regions.
183 */
184static int alloc_from_top_down_min_addr_cap_check(void)
185{
186 struct memblock_region *rgn = &memblock.reserved.regions[0];
187 void *allocated_ptr = NULL;
188
189 phys_addr_t r1_size = SZ_64;
190 phys_addr_t min_addr;
191 phys_addr_t start_addr;
192
193 setup_memblock();
194
195 start_addr = (phys_addr_t)memblock_start_of_DRAM();
196 min_addr = start_addr - SMP_CACHE_BYTES * 3;
197
198 memblock_reserve(start_addr + r1_size, MEM_SIZE - r1_size);
199
200 allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
201
202 assert(allocated_ptr);
203 assert(rgn->base == start_addr);
204 assert(rgn->size == MEM_SIZE);
205
206 assert(memblock.reserved.cnt == 1);
207 assert(memblock.reserved.total_size == MEM_SIZE);
208
209 return 0;
210}
211
212/*
213 * A test that tries to allocate a memory region above an address that is too
214 * close to the end of the memory:
215 *
216 * +
217 * |-----------+ + |
218 * | rgn | | |
219 * +-----------+--------------+-----+
220 * ^ ^
221 * | |
222 * Aligned address min_addr
223 * boundary
224 *
225 * Expect to prioritize granting memory over satisfying the minimal address
226 * requirement. Allocation happens at beginning of the available memory.
227 */
228static int alloc_from_bottom_up_high_addr_check(void)
229{
230 struct memblock_region *rgn = &memblock.reserved.regions[0];
231 void *allocated_ptr = NULL;
232
233 phys_addr_t size = SZ_32;
234 phys_addr_t min_addr;
235
236 setup_memblock();
237
238 /* The address is too close to the end of the memory */
239 min_addr = memblock_end_of_DRAM() - SZ_8;
240
241 allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
242
243 assert(allocated_ptr);
244 assert(rgn->size == size);
245 assert(rgn->base == memblock_start_of_DRAM());
246
247 assert(memblock.reserved.cnt == 1);
248 assert(memblock.reserved.total_size == size);
249
250 return 0;
251}
252
253/*
254 * A test that tries to allocate a memory region when there is no space
255 * available above the minimal address above a certain address:
256 *
257 * +
258 * |-----------+ +-------------------|
259 * | rgn | | |
260 * +-----------+----+-------------------+
261 * ^
262 * |
263 * min_addr
264 *
265 * Expect to prioritize granting memory over satisfying the minimal address
266 * requirement and to allocate at the beginning of the available memory.
267 */
268static int alloc_from_bottom_up_no_space_above_check(void)
269{
270 struct memblock_region *rgn = &memblock.reserved.regions[0];
271 void *allocated_ptr = NULL;
272
273 phys_addr_t r1_size = SZ_64;
274 phys_addr_t min_addr;
275 phys_addr_t r2_size;
276
277 setup_memblock();
278
279 min_addr = memblock_start_of_DRAM() + SZ_128;
280 r2_size = memblock_end_of_DRAM() - min_addr;
281
282 /* No space above this address */
283 memblock_reserve(min_addr - SMP_CACHE_BYTES, r2_size);
284
285 allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
286
287 assert(allocated_ptr);
288 assert(rgn->base == memblock_start_of_DRAM());
289 assert(rgn->size == r1_size);
290
291 assert(memblock.reserved.cnt == 2);
292 assert(memblock.reserved.total_size == r1_size + r2_size);
293
294 return 0;
295}
296
297/*
298 * A test that tries to allocate a memory region with a minimal address below
299 * the start address of the available memory. Expect to allocate a region
300 * at the beginning of the available memory.
301 */
302static int alloc_from_bottom_up_min_addr_cap_check(void)
303{
304 struct memblock_region *rgn = &memblock.reserved.regions[0];
305 void *allocated_ptr = NULL;
306
307 phys_addr_t r1_size = SZ_64;
308 phys_addr_t min_addr;
309 phys_addr_t start_addr;
310
311 setup_memblock();
312
313 start_addr = (phys_addr_t)memblock_start_of_DRAM();
314 min_addr = start_addr - SMP_CACHE_BYTES * 3;
315
316 allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
317
318 assert(allocated_ptr);
319 assert(rgn->base == start_addr);
320 assert(rgn->size == r1_size);
321
322 assert(memblock.reserved.cnt == 1);
323 assert(memblock.reserved.total_size == r1_size);
324
325 return 0;
326}
327
328/* Test case wrappers */
329static int alloc_from_simple_check(void)
330{
331 memblock_set_bottom_up(false);
332 alloc_from_simple_generic_check();
333 memblock_set_bottom_up(true);
334 alloc_from_simple_generic_check();
335
336 return 0;
337}
338
339static int alloc_from_misaligned_check(void)
340{
341 memblock_set_bottom_up(false);
342 alloc_from_misaligned_generic_check();
343 memblock_set_bottom_up(true);
344 alloc_from_misaligned_generic_check();
345
346 return 0;
347}
348
349static int alloc_from_high_addr_check(void)
350{
351 memblock_set_bottom_up(false);
352 alloc_from_top_down_high_addr_check();
353 memblock_set_bottom_up(true);
354 alloc_from_bottom_up_high_addr_check();
355
356 return 0;
357}
358
359static int alloc_from_no_space_above_check(void)
360{
361 memblock_set_bottom_up(false);
362 alloc_from_top_down_no_space_above_check();
363 memblock_set_bottom_up(true);
364 alloc_from_bottom_up_no_space_above_check();
365
366 return 0;
367}
368
369static int alloc_from_min_addr_cap_check(void)
370{
371 memblock_set_bottom_up(false);
372 alloc_from_top_down_min_addr_cap_check();
373 memblock_set_bottom_up(true);
374 alloc_from_bottom_up_min_addr_cap_check();
375
376 return 0;
377}
378
379int memblock_alloc_helpers_checks(void)
380{
381 reset_memblock_attributes();
382 dummy_physical_memory_init();
383
384 alloc_from_simple_check();
385 alloc_from_misaligned_check();
386 alloc_from_high_addr_check();
387 alloc_from_no_space_above_check();
388 alloc_from_min_addr_cap_check();
389
390 dummy_physical_memory_cleanup();
391
392 return 0;
393}