1 // SPDX-License-Identifier: GPL-2.0-or-later
2 #include <string.h>
3 #include <linux/memblock.h>
4 #include <linux/sizes.h>
5 #include "basic_api.h"
6 
7 #define EXPECTED_MEMBLOCK_REGIONS			128
8 
9 static int memblock_initialization_check(void)
10 {
11 	reset_memblock();
12 
13 	assert(memblock.memory.regions);
14 	assert(memblock.memory.cnt == 1);
15 	assert(memblock.memory.max == EXPECTED_MEMBLOCK_REGIONS);
16 	assert(strcmp(memblock.memory.name, "memory") == 0);
17 
18 	assert(memblock.reserved.regions);
19 	assert(memblock.reserved.cnt == 1);
20 	assert(memblock.memory.max == EXPECTED_MEMBLOCK_REGIONS);
21 	assert(strcmp(memblock.reserved.name, "reserved") == 0);
22 
23 	assert(!memblock.bottom_up);
24 	assert(memblock.current_limit == MEMBLOCK_ALLOC_ANYWHERE);
25 
26 	return 0;
27 }
28 
29 /*
30  * A simple test that adds a memory block of a specified base address
31  * and size to the collection of available memory regions (memblock.memory).
32  * It checks if a new entry was created and if region counter and total memory
33  * were correctly updated.
34  */
35 static int memblock_add_simple_check(void)
36 {
37 	struct memblock_region *rgn;
38 
39 	rgn = &memblock.memory.regions[0];
40 
41 	struct region r = {
42 		.base = SZ_1G,
43 		.size = SZ_4M
44 	};
45 
46 	reset_memblock();
47 	memblock_add(r.base, r.size);
48 
49 	assert(rgn->base == r.base);
50 	assert(rgn->size == r.size);
51 
52 	assert(memblock.memory.cnt == 1);
53 	assert(memblock.memory.total_size == r.size);
54 
55 	return 0;
56 }
57 
58 /*
59  * A test that tries to add two memory blocks that don't overlap with one
60  * another. It checks if two correctly initialized entries were added to the
61  * collection of available memory regions (memblock.memory) and if this
62  * change was reflected in memblock.memory's total size and region counter.
63  */
64 static int memblock_add_disjoint_check(void)
65 {
66 	struct memblock_region *rgn1, *rgn2;
67 
68 	rgn1 = &memblock.memory.regions[0];
69 	rgn2 = &memblock.memory.regions[1];
70 
71 	struct region r1 = {
72 		.base = SZ_1G,
73 		.size = SZ_8K
74 	};
75 	struct region r2 = {
76 		.base = SZ_1G + SZ_16K,
77 		.size = SZ_8K
78 	};
79 
80 	reset_memblock();
81 	memblock_add(r1.base, r1.size);
82 	memblock_add(r2.base, r2.size);
83 
84 	assert(rgn1->base == r1.base);
85 	assert(rgn1->size == r1.size);
86 
87 	assert(rgn2->base == r2.base);
88 	assert(rgn2->size == r2.size);
89 
90 	assert(memblock.memory.cnt == 2);
91 	assert(memblock.memory.total_size == r1.size + r2.size);
92 
93 	return 0;
94 }
95 
96 /*
97  * A test that tries to add two memory blocks, where the second one overlaps
98  * with the beginning of the first entry (that is r1.base < r2.base + r2.size).
99  * After this, it checks if two entries are merged into one region that starts
100  * at r2.base and has size of two regions minus their intersection. It also
101  * verifies the reported total size of the available memory and region counter.
102  */
103 static int memblock_add_overlap_top_check(void)
104 {
105 	struct memblock_region *rgn;
106 	phys_addr_t total_size;
107 
108 	rgn = &memblock.memory.regions[0];
109 
110 	struct region r1 = {
111 		.base = SZ_512M,
112 		.size = SZ_1G
113 	};
114 	struct region r2 = {
115 		.base = SZ_256M,
116 		.size = SZ_512M
117 	};
118 
119 	total_size = (r1.base - r2.base) + r1.size;
120 
121 	reset_memblock();
122 	memblock_add(r1.base, r1.size);
123 	memblock_add(r2.base, r2.size);
124 
125 	assert(rgn->base == r2.base);
126 	assert(rgn->size == total_size);
127 
128 	assert(memblock.memory.cnt == 1);
129 	assert(memblock.memory.total_size == total_size);
130 
131 	return 0;
132 }
133 
134 /*
135  * A test that tries to add two memory blocks, where the second one overlaps
136  * with the end of the first entry (that is r2.base < r1.base + r1.size).
137  * After this, it checks if two entries are merged into one region that starts
138  * at r1.base and has size of two regions minus their intersection. It verifies
139  * that memblock can still see only one entry and has a correct total size of
140  * the available memory.
141  */
142 static int memblock_add_overlap_bottom_check(void)
143 {
144 	struct memblock_region *rgn;
145 	phys_addr_t total_size;
146 
147 	rgn = &memblock.memory.regions[0];
148 
149 	struct region r1 = {
150 		.base = SZ_128M,
151 		.size = SZ_512M
152 	};
153 	struct region r2 = {
154 		.base = SZ_256M,
155 		.size = SZ_1G
156 	};
157 
158 	total_size = (r2.base - r1.base) + r2.size;
159 
160 	reset_memblock();
161 	memblock_add(r1.base, r1.size);
162 	memblock_add(r2.base, r2.size);
163 
164 	assert(rgn->base == r1.base);
165 	assert(rgn->size == total_size);
166 
167 	assert(memblock.memory.cnt == 1);
168 	assert(memblock.memory.total_size == total_size);
169 
170 	return 0;
171 }
172 
173 /*
174  * A test that tries to add two memory blocks, where the second one is
175  * within the range of the first entry (that is r1.base < r2.base &&
176  * r2.base + r2.size < r1.base + r1.size). It checks if two entries are merged
177  * into one region that stays the same. The counter and total size of available
178  * memory are expected to not be updated.
179  */
180 static int memblock_add_within_check(void)
181 {
182 	struct memblock_region *rgn;
183 
184 	rgn = &memblock.memory.regions[0];
185 
186 	struct region r1 = {
187 		.base = SZ_8M,
188 		.size = SZ_32M
189 	};
190 	struct region r2 = {
191 		.base = SZ_16M,
192 		.size = SZ_1M
193 	};
194 
195 	reset_memblock();
196 	memblock_add(r1.base, r1.size);
197 	memblock_add(r2.base, r2.size);
198 
199 	assert(rgn->base == r1.base);
200 	assert(rgn->size == r1.size);
201 
202 	assert(memblock.memory.cnt == 1);
203 	assert(memblock.memory.total_size == r1.size);
204 
205 	return 0;
206 }
207 
208 /*
209  * A simple test that tries to add the same memory block twice. The counter
210  * and total size of available memory are expected to not be updated.
211  */
212 static int memblock_add_twice_check(void)
213 {
214 	struct region r = {
215 		.base = SZ_16K,
216 		.size = SZ_2M
217 	};
218 
219 	reset_memblock();
220 
221 	memblock_add(r.base, r.size);
222 	memblock_add(r.base, r.size);
223 
224 	assert(memblock.memory.cnt == 1);
225 	assert(memblock.memory.total_size == r.size);
226 
227 	return 0;
228 }
229 
230 static int memblock_add_checks(void)
231 {
232 	memblock_add_simple_check();
233 	memblock_add_disjoint_check();
234 	memblock_add_overlap_top_check();
235 	memblock_add_overlap_bottom_check();
236 	memblock_add_within_check();
237 	memblock_add_twice_check();
238 
239 	return 0;
240 }
241 
242  /*
243   * A simple test that marks a memory block of a specified base address
244   * and size as reserved and to the collection of reserved memory regions
245   * (memblock.reserved). It checks if a new entry was created and if region
246   * counter and total memory size were correctly updated.
247   */
248 static int memblock_reserve_simple_check(void)
249 {
250 	struct memblock_region *rgn;
251 
252 	rgn =  &memblock.reserved.regions[0];
253 
254 	struct region r = {
255 		.base = SZ_2G,
256 		.size = SZ_128M
257 	};
258 
259 	reset_memblock();
260 	memblock_reserve(r.base, r.size);
261 
262 	assert(rgn->base == r.base);
263 	assert(rgn->size == r.size);
264 
265 	return 0;
266 }
267 
268 /*
269  * A test that tries to mark two memory blocks that don't overlap as reserved
270  * and checks if two entries were correctly added to the collection of reserved
271  * memory regions (memblock.reserved) and if this change was reflected in
272  * memblock.reserved's total size and region counter.
273  */
274 static int memblock_reserve_disjoint_check(void)
275 {
276 	struct memblock_region *rgn1, *rgn2;
277 
278 	rgn1 = &memblock.reserved.regions[0];
279 	rgn2 = &memblock.reserved.regions[1];
280 
281 	struct region r1 = {
282 		.base = SZ_256M,
283 		.size = SZ_16M
284 	};
285 	struct region r2 = {
286 		.base = SZ_512M,
287 		.size = SZ_512M
288 	};
289 
290 	reset_memblock();
291 	memblock_reserve(r1.base, r1.size);
292 	memblock_reserve(r2.base, r2.size);
293 
294 	assert(rgn1->base == r1.base);
295 	assert(rgn1->size == r1.size);
296 
297 	assert(rgn2->base == r2.base);
298 	assert(rgn2->size == r2.size);
299 
300 	assert(memblock.reserved.cnt == 2);
301 	assert(memblock.reserved.total_size == r1.size + r2.size);
302 
303 	return 0;
304 }
305 
306 /*
307  * A test that tries to mark two memory blocks as reserved, where the
308  * second one overlaps with the beginning of the first (that is
309  * r1.base < r2.base + r2.size).
310  * It checks if two entries are merged into one region that starts at r2.base
311  * and has size of two regions minus their intersection. The test also verifies
312  * that memblock can still see only one entry and has a correct total size of
313  * the reserved memory.
314  */
315 static int memblock_reserve_overlap_top_check(void)
316 {
317 	struct memblock_region *rgn;
318 	phys_addr_t total_size;
319 
320 	rgn = &memblock.reserved.regions[0];
321 
322 	struct region r1 = {
323 		.base = SZ_1G,
324 		.size = SZ_1G
325 	};
326 	struct region r2 = {
327 		.base = SZ_128M,
328 		.size = SZ_1G
329 	};
330 
331 	total_size = (r1.base - r2.base) + r1.size;
332 
333 	reset_memblock();
334 	memblock_reserve(r1.base, r1.size);
335 	memblock_reserve(r2.base, r2.size);
336 
337 	assert(rgn->base == r2.base);
338 	assert(rgn->size == total_size);
339 
340 	assert(memblock.reserved.cnt == 1);
341 	assert(memblock.reserved.total_size == total_size);
342 
343 	return 0;
344 }
345 
346 /*
347  * A test that tries to mark two memory blocks as reserved, where the
348  * second one overlaps with the end of the first entry (that is
349  * r2.base < r1.base + r1.size).
350  * It checks if two entries are merged into one region that starts at r1.base
351  * and has size of two regions minus their intersection. It verifies that
352  * memblock can still see only one entry and has a correct total size of the
353  * reserved memory.
354  */
355 static int memblock_reserve_overlap_bottom_check(void)
356 {
357 	struct memblock_region *rgn;
358 	phys_addr_t total_size;
359 
360 	rgn = &memblock.reserved.regions[0];
361 
362 	struct region r1 = {
363 		.base = SZ_2K,
364 		.size = SZ_128K
365 	};
366 	struct region r2 = {
367 		.base = SZ_128K,
368 		.size = SZ_128K
369 	};
370 
371 	total_size = (r2.base - r1.base) + r2.size;
372 
373 	reset_memblock();
374 	memblock_reserve(r1.base, r1.size);
375 	memblock_reserve(r2.base, r2.size);
376 
377 	assert(rgn->base == r1.base);
378 	assert(rgn->size == total_size);
379 
380 	assert(memblock.reserved.cnt == 1);
381 	assert(memblock.reserved.total_size == total_size);
382 
383 	return 0;
384 }
385 
386 /*
387  * A test that tries to mark two memory blocks as reserved, where the second
388  * one is within the range of the first entry (that is
389  * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)).
390  * It checks if two entries are merged into one region that stays the
391  * same. The counter and total size of available memory are expected to not be
392  * updated.
393  */
394 static int memblock_reserve_within_check(void)
395 {
396 	struct memblock_region *rgn;
397 
398 	rgn = &memblock.reserved.regions[0];
399 
400 	struct region r1 = {
401 		.base = SZ_1M,
402 		.size = SZ_8M
403 	};
404 	struct region r2 = {
405 		.base = SZ_2M,
406 		.size = SZ_64K
407 	};
408 
409 	reset_memblock();
410 	memblock_reserve(r1.base, r1.size);
411 	memblock_reserve(r2.base, r2.size);
412 
413 	assert(rgn->base == r1.base);
414 	assert(rgn->size == r1.size);
415 
416 	assert(memblock.reserved.cnt == 1);
417 	assert(memblock.reserved.total_size == r1.size);
418 
419 	return 0;
420 }
421 
422 /*
423  * A simple test that tries to reserve the same memory block twice.
424  * The region counter and total size of reserved memory are expected to not
425  * be updated.
426  */
427 static int memblock_reserve_twice_check(void)
428 {
429 	struct region r = {
430 		.base = SZ_16K,
431 		.size = SZ_2M
432 	};
433 
434 	reset_memblock();
435 
436 	memblock_reserve(r.base, r.size);
437 	memblock_reserve(r.base, r.size);
438 
439 	assert(memblock.reserved.cnt == 1);
440 	assert(memblock.reserved.total_size == r.size);
441 
442 	return 0;
443 }
444 
445 static int memblock_reserve_checks(void)
446 {
447 	memblock_reserve_simple_check();
448 	memblock_reserve_disjoint_check();
449 	memblock_reserve_overlap_top_check();
450 	memblock_reserve_overlap_bottom_check();
451 	memblock_reserve_within_check();
452 	memblock_reserve_twice_check();
453 
454 	return 0;
455 }
456 
457 int memblock_basic_checks(void)
458 {
459 	memblock_initialization_check();
460 	memblock_add_checks();
461 	memblock_reserve_checks();
462 
463 	return 0;
464 }
465