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  /*
458   * A simple test that tries to remove the first entry of the array of
459   * available memory regions. By "removing" a region we mean overwriting it
460   * with the next region in memblock.memory. To check this is the case, the
461   * test adds two memory blocks and verifies that the value of the latter
462   * was used to erase r1 region.  It also checks if the region counter and
463   * total size were updated to expected values.
464   */
465 static int memblock_remove_simple_check(void)
466 {
467 	struct memblock_region *rgn;
468 
469 	rgn = &memblock.memory.regions[0];
470 
471 	struct region r1 = {
472 		.base = SZ_2K,
473 		.size = SZ_4K
474 	};
475 	struct region r2 = {
476 		.base = SZ_128K,
477 		.size = SZ_4M
478 	};
479 
480 	reset_memblock();
481 	memblock_add(r1.base, r1.size);
482 	memblock_add(r2.base, r2.size);
483 	memblock_remove(r1.base, r1.size);
484 
485 	assert(rgn->base == r2.base);
486 	assert(rgn->size == r2.size);
487 
488 	assert(memblock.memory.cnt == 1);
489 	assert(memblock.memory.total_size == r2.size);
490 
491 	return 0;
492 }
493 
494  /*
495   * A test that tries to remove a region that was not registered as available
496   * memory (i.e. has no corresponding entry in memblock.memory). It verifies
497   * that array, regions counter and total size were not modified.
498   */
499 static int memblock_remove_absent_check(void)
500 {
501 	struct memblock_region *rgn;
502 
503 	rgn = &memblock.memory.regions[0];
504 
505 	struct region r1 = {
506 		.base = SZ_512K,
507 		.size = SZ_4M
508 	};
509 	struct region r2 = {
510 		.base = SZ_64M,
511 		.size = SZ_1G
512 	};
513 
514 	reset_memblock();
515 	memblock_add(r1.base, r1.size);
516 	memblock_remove(r2.base, r2.size);
517 
518 	assert(rgn->base == r1.base);
519 	assert(rgn->size == r1.size);
520 
521 	assert(memblock.memory.cnt == 1);
522 	assert(memblock.memory.total_size == r1.size);
523 
524 	return 0;
525 }
526 
527 /*
528  * A test that tries to remove a region which overlaps with the beginning of
529  * the already existing entry r1 (that is r1.base < r2.base + r2.size). It
530  * checks if only the intersection of both regions is removed from the available
531  * memory pool. The test also checks if the regions counter and total size are
532  * updated to expected values.
533  */
534 static int memblock_remove_overlap_top_check(void)
535 {
536 	struct memblock_region *rgn;
537 	phys_addr_t r1_end, r2_end, total_size;
538 
539 	rgn = &memblock.memory.regions[0];
540 
541 	struct region r1 = {
542 		.base = SZ_32M,
543 		.size = SZ_32M
544 	};
545 	struct region r2 = {
546 		.base = SZ_16M,
547 		.size = SZ_32M
548 	};
549 
550 	r1_end = r1.base + r1.size;
551 	r2_end = r2.base + r2.size;
552 	total_size = r1_end - r2_end;
553 
554 	reset_memblock();
555 	memblock_add(r1.base, r1.size);
556 	memblock_remove(r2.base, r2.size);
557 
558 	assert(rgn->base == r1.base + r2.base);
559 	assert(rgn->size == total_size);
560 
561 	assert(memblock.memory.cnt == 1);
562 	assert(memblock.memory.total_size == total_size);
563 
564 	return 0;
565 }
566 
567 /*
568  * A test that tries to remove a region which overlaps with the end of the
569  * first entry (that is r2.base < r1.base + r1.size). It checks if only the
570  * intersection of both regions is removed from the available memory pool.
571  * The test also checks if the regions counter and total size are updated to
572  * expected values.
573  */
574 static int memblock_remove_overlap_bottom_check(void)
575 {
576 	struct memblock_region *rgn;
577 	phys_addr_t total_size;
578 
579 	rgn = &memblock.memory.regions[0];
580 
581 	struct region r1 = {
582 		.base = SZ_2M,
583 		.size = SZ_64M
584 	};
585 	struct region r2 = {
586 		.base = SZ_32M,
587 		.size = SZ_256M
588 	};
589 
590 	total_size = r2.base - r1.base;
591 
592 	reset_memblock();
593 	memblock_add(r1.base, r1.size);
594 	memblock_remove(r2.base, r2.size);
595 
596 	assert(rgn->base == r1.base);
597 	assert(rgn->size == total_size);
598 
599 	assert(memblock.memory.cnt == 1);
600 	assert(memblock.memory.total_size == total_size);
601 	return 0;
602 }
603 
604 /*
605  * A test that tries to remove a region which is within the range of the
606  * already existing entry (that is
607  * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)).
608  * It checks if the region is split into two - one that ends at r2.base and
609  * second that starts at r2.base + size, with appropriate sizes. The test
610  * also checks if the region counter and total size were updated to
611  * expected values.
612  */
613 static int memblock_remove_within_check(void)
614 {
615 	struct memblock_region *rgn1, *rgn2;
616 	phys_addr_t r1_size, r2_size, total_size;
617 
618 	rgn1 = &memblock.memory.regions[0];
619 	rgn2 = &memblock.memory.regions[1];
620 
621 	struct region r1 = {
622 		.base = SZ_1M,
623 		.size = SZ_32M
624 	};
625 	struct region r2 = {
626 		.base = SZ_16M,
627 		.size = SZ_1M
628 	};
629 
630 	r1_size = r2.base - r1.base;
631 	r2_size = (r1.base + r1.size) - (r2.base + r2.size);
632 	total_size = r1_size + r2_size;
633 
634 	reset_memblock();
635 	memblock_add(r1.base, r1.size);
636 	memblock_remove(r2.base, r2.size);
637 
638 	assert(rgn1->base == r1.base);
639 	assert(rgn1->size == r1_size);
640 
641 	assert(rgn2->base == r2.base + r2.size);
642 	assert(rgn2->size == r2_size);
643 
644 	assert(memblock.memory.cnt == 2);
645 	assert(memblock.memory.total_size == total_size);
646 
647 	return 0;
648 }
649 
650 static int memblock_remove_checks(void)
651 {
652 	memblock_remove_simple_check();
653 	memblock_remove_absent_check();
654 	memblock_remove_overlap_top_check();
655 	memblock_remove_overlap_bottom_check();
656 	memblock_remove_within_check();
657 
658 	return 0;
659 }
660 
661 int memblock_basic_checks(void)
662 {
663 	memblock_initialization_check();
664 	memblock_add_checks();
665 	memblock_reserve_checks();
666 	memblock_remove_checks();
667 
668 	return 0;
669 }
670