Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/memblock/tests/alloc_helpers_api.c
26299 views
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
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
*/
61
static 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
*/
108
static 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
*/
151
static 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_kern(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
*/
188
static 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_kern(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
*/
234
static 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
*/
276
static 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
*/
312
static 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 */
341
static 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
350
static 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
359
static 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
370
static 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
381
static 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
392
int 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
416