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 <string.h>
3#include <linux/memblock.h>
4#include "basic_api.h"
5
6#define EXPECTED_MEMBLOCK_REGIONS 128
7#define FUNC_ADD "memblock_add"
8#define FUNC_RESERVE "memblock_reserve"
9#define FUNC_REMOVE "memblock_remove"
10#define FUNC_FREE "memblock_free"
11
12static int memblock_initialization_check(void)
13{
14 PREFIX_PUSH();
15
16 ASSERT_NE(memblock.memory.regions, NULL);
17 ASSERT_EQ(memblock.memory.cnt, 1);
18 ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS);
19 ASSERT_EQ(strcmp(memblock.memory.name, "memory"), 0);
20
21 ASSERT_NE(memblock.reserved.regions, NULL);
22 ASSERT_EQ(memblock.reserved.cnt, 1);
23 ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS);
24 ASSERT_EQ(strcmp(memblock.reserved.name, "reserved"), 0);
25
26 ASSERT_EQ(memblock.bottom_up, false);
27 ASSERT_EQ(memblock.current_limit, MEMBLOCK_ALLOC_ANYWHERE);
28
29 test_pass_pop();
30
31 return 0;
32}
33
34/*
35 * A simple test that adds a memory block of a specified base address
36 * and size to the collection of available memory regions (memblock.memory).
37 * Expect to create a new entry. The region counter and total memory get
38 * updated.
39 */
40static int memblock_add_simple_check(void)
41{
42 struct memblock_region *rgn;
43
44 rgn = &memblock.memory.regions[0];
45
46 struct region r = {
47 .base = SZ_1G,
48 .size = SZ_4M
49 };
50
51 PREFIX_PUSH();
52
53 reset_memblock_regions();
54 memblock_add(r.base, r.size);
55
56 ASSERT_EQ(rgn->base, r.base);
57 ASSERT_EQ(rgn->size, r.size);
58
59 ASSERT_EQ(memblock.memory.cnt, 1);
60 ASSERT_EQ(memblock.memory.total_size, r.size);
61
62 test_pass_pop();
63
64 return 0;
65}
66
67/*
68 * A simple test that adds a memory block of a specified base address, size,
69 * NUMA node and memory flags to the collection of available memory regions.
70 * Expect to create a new entry. The region counter and total memory get
71 * updated.
72 */
73static int memblock_add_node_simple_check(void)
74{
75 struct memblock_region *rgn;
76
77 rgn = &memblock.memory.regions[0];
78
79 struct region r = {
80 .base = SZ_1M,
81 .size = SZ_16M
82 };
83
84 PREFIX_PUSH();
85
86 reset_memblock_regions();
87 memblock_add_node(r.base, r.size, 1, MEMBLOCK_HOTPLUG);
88
89 ASSERT_EQ(rgn->base, r.base);
90 ASSERT_EQ(rgn->size, r.size);
91#ifdef CONFIG_NUMA
92 ASSERT_EQ(rgn->nid, 1);
93#endif
94 ASSERT_EQ(rgn->flags, MEMBLOCK_HOTPLUG);
95
96 ASSERT_EQ(memblock.memory.cnt, 1);
97 ASSERT_EQ(memblock.memory.total_size, r.size);
98
99 test_pass_pop();
100
101 return 0;
102}
103
104/*
105 * A test that tries to add two memory blocks that don't overlap with one
106 * another:
107 *
108 * | +--------+ +--------+ |
109 * | | r1 | | r2 | |
110 * +--------+--------+--------+--------+--+
111 *
112 * Expect to add two correctly initialized entries to the collection of
113 * available memory regions (memblock.memory). The total size and
114 * region counter fields get updated.
115 */
116static int memblock_add_disjoint_check(void)
117{
118 struct memblock_region *rgn1, *rgn2;
119
120 rgn1 = &memblock.memory.regions[0];
121 rgn2 = &memblock.memory.regions[1];
122
123 struct region r1 = {
124 .base = SZ_1G,
125 .size = SZ_8K
126 };
127 struct region r2 = {
128 .base = SZ_1G + SZ_16K,
129 .size = SZ_8K
130 };
131
132 PREFIX_PUSH();
133
134 reset_memblock_regions();
135 memblock_add(r1.base, r1.size);
136 memblock_add(r2.base, r2.size);
137
138 ASSERT_EQ(rgn1->base, r1.base);
139 ASSERT_EQ(rgn1->size, r1.size);
140
141 ASSERT_EQ(rgn2->base, r2.base);
142 ASSERT_EQ(rgn2->size, r2.size);
143
144 ASSERT_EQ(memblock.memory.cnt, 2);
145 ASSERT_EQ(memblock.memory.total_size, r1.size + r2.size);
146
147 test_pass_pop();
148
149 return 0;
150}
151
152/*
153 * A test that tries to add two memory blocks r1 and r2, where r2 overlaps
154 * with the beginning of r1 (that is r1.base < r2.base + r2.size):
155 *
156 * | +----+----+------------+ |
157 * | | |r2 | r1 | |
158 * +----+----+----+------------+----------+
159 * ^ ^
160 * | |
161 * | r1.base
162 * |
163 * r2.base
164 *
165 * Expect to merge the two entries into one region that starts at r2.base
166 * and has size of two regions minus their intersection. The total size of
167 * the available memory is updated, and the region counter stays the same.
168 */
169static int memblock_add_overlap_top_check(void)
170{
171 struct memblock_region *rgn;
172 phys_addr_t total_size;
173
174 rgn = &memblock.memory.regions[0];
175
176 struct region r1 = {
177 .base = SZ_512M,
178 .size = SZ_1G
179 };
180 struct region r2 = {
181 .base = SZ_256M,
182 .size = SZ_512M
183 };
184
185 PREFIX_PUSH();
186
187 total_size = (r1.base - r2.base) + r1.size;
188
189 reset_memblock_regions();
190 memblock_add(r1.base, r1.size);
191 memblock_add(r2.base, r2.size);
192
193 ASSERT_EQ(rgn->base, r2.base);
194 ASSERT_EQ(rgn->size, total_size);
195
196 ASSERT_EQ(memblock.memory.cnt, 1);
197 ASSERT_EQ(memblock.memory.total_size, total_size);
198
199 test_pass_pop();
200
201 return 0;
202}
203
204/*
205 * A test that tries to add two memory blocks r1 and r2, where r2 overlaps
206 * with the end of r1 (that is r2.base < r1.base + r1.size):
207 *
208 * | +--+------+----------+ |
209 * | | | r1 | r2 | |
210 * +--+--+------+----------+--------------+
211 * ^ ^
212 * | |
213 * | r2.base
214 * |
215 * r1.base
216 *
217 * Expect to merge the two entries into one region that starts at r1.base
218 * and has size of two regions minus their intersection. The total size of
219 * the available memory is updated, and the region counter stays the same.
220 */
221static int memblock_add_overlap_bottom_check(void)
222{
223 struct memblock_region *rgn;
224 phys_addr_t total_size;
225
226 rgn = &memblock.memory.regions[0];
227
228 struct region r1 = {
229 .base = SZ_128M,
230 .size = SZ_512M
231 };
232 struct region r2 = {
233 .base = SZ_256M,
234 .size = SZ_1G
235 };
236
237 PREFIX_PUSH();
238
239 total_size = (r2.base - r1.base) + r2.size;
240
241 reset_memblock_regions();
242 memblock_add(r1.base, r1.size);
243 memblock_add(r2.base, r2.size);
244
245 ASSERT_EQ(rgn->base, r1.base);
246 ASSERT_EQ(rgn->size, total_size);
247
248 ASSERT_EQ(memblock.memory.cnt, 1);
249 ASSERT_EQ(memblock.memory.total_size, total_size);
250
251 test_pass_pop();
252
253 return 0;
254}
255
256/*
257 * A test that tries to add two memory blocks r1 and r2, where r2 is
258 * within the range of r1 (that is r1.base < r2.base &&
259 * r2.base + r2.size < r1.base + r1.size):
260 *
261 * | +-------+--+-----------------------+
262 * | | |r2| r1 |
263 * +---+-------+--+-----------------------+
264 * ^
265 * |
266 * r1.base
267 *
268 * Expect to merge two entries into one region that stays the same.
269 * The counter and total size of available memory are not updated.
270 */
271static int memblock_add_within_check(void)
272{
273 struct memblock_region *rgn;
274
275 rgn = &memblock.memory.regions[0];
276
277 struct region r1 = {
278 .base = SZ_8M,
279 .size = SZ_32M
280 };
281 struct region r2 = {
282 .base = SZ_16M,
283 .size = SZ_1M
284 };
285
286 PREFIX_PUSH();
287
288 reset_memblock_regions();
289 memblock_add(r1.base, r1.size);
290 memblock_add(r2.base, r2.size);
291
292 ASSERT_EQ(rgn->base, r1.base);
293 ASSERT_EQ(rgn->size, r1.size);
294
295 ASSERT_EQ(memblock.memory.cnt, 1);
296 ASSERT_EQ(memblock.memory.total_size, r1.size);
297
298 test_pass_pop();
299
300 return 0;
301}
302
303/*
304 * A simple test that tries to add the same memory block twice. Expect
305 * the counter and total size of available memory to not be updated.
306 */
307static int memblock_add_twice_check(void)
308{
309 struct region r = {
310 .base = SZ_16K,
311 .size = SZ_2M
312 };
313
314 PREFIX_PUSH();
315
316 reset_memblock_regions();
317
318 memblock_add(r.base, r.size);
319 memblock_add(r.base, r.size);
320
321 ASSERT_EQ(memblock.memory.cnt, 1);
322 ASSERT_EQ(memblock.memory.total_size, r.size);
323
324 test_pass_pop();
325
326 return 0;
327}
328
329static int memblock_add_checks(void)
330{
331 prefix_reset();
332 prefix_push(FUNC_ADD);
333 test_print("Running %s tests...\n", FUNC_ADD);
334
335 memblock_add_simple_check();
336 memblock_add_node_simple_check();
337 memblock_add_disjoint_check();
338 memblock_add_overlap_top_check();
339 memblock_add_overlap_bottom_check();
340 memblock_add_within_check();
341 memblock_add_twice_check();
342
343 prefix_pop();
344
345 return 0;
346}
347
348/*
349 * A simple test that marks a memory block of a specified base address
350 * and size as reserved and to the collection of reserved memory regions
351 * (memblock.reserved). Expect to create a new entry. The region counter
352 * and total memory size are updated.
353 */
354static int memblock_reserve_simple_check(void)
355{
356 struct memblock_region *rgn;
357
358 rgn = &memblock.reserved.regions[0];
359
360 struct region r = {
361 .base = SZ_2G,
362 .size = SZ_128M
363 };
364
365 PREFIX_PUSH();
366
367 reset_memblock_regions();
368 memblock_reserve(r.base, r.size);
369
370 ASSERT_EQ(rgn->base, r.base);
371 ASSERT_EQ(rgn->size, r.size);
372
373 test_pass_pop();
374
375 return 0;
376}
377
378/*
379 * A test that tries to mark two memory blocks that don't overlap as reserved:
380 *
381 * | +--+ +----------------+ |
382 * | |r1| | r2 | |
383 * +--------+--+------+----------------+--+
384 *
385 * Expect to add two entries to the collection of reserved memory regions
386 * (memblock.reserved). The total size and region counter for
387 * memblock.reserved are updated.
388 */
389static int memblock_reserve_disjoint_check(void)
390{
391 struct memblock_region *rgn1, *rgn2;
392
393 rgn1 = &memblock.reserved.regions[0];
394 rgn2 = &memblock.reserved.regions[1];
395
396 struct region r1 = {
397 .base = SZ_256M,
398 .size = SZ_16M
399 };
400 struct region r2 = {
401 .base = SZ_512M,
402 .size = SZ_512M
403 };
404
405 PREFIX_PUSH();
406
407 reset_memblock_regions();
408 memblock_reserve(r1.base, r1.size);
409 memblock_reserve(r2.base, r2.size);
410
411 ASSERT_EQ(rgn1->base, r1.base);
412 ASSERT_EQ(rgn1->size, r1.size);
413
414 ASSERT_EQ(rgn2->base, r2.base);
415 ASSERT_EQ(rgn2->size, r2.size);
416
417 ASSERT_EQ(memblock.reserved.cnt, 2);
418 ASSERT_EQ(memblock.reserved.total_size, r1.size + r2.size);
419
420 test_pass_pop();
421
422 return 0;
423}
424
425/*
426 * A test that tries to mark two memory blocks r1 and r2 as reserved,
427 * where r2 overlaps with the beginning of r1 (that is
428 * r1.base < r2.base + r2.size):
429 *
430 * | +--------------+--+--------------+ |
431 * | | r2 | | r1 | |
432 * +--+--------------+--+--------------+--+
433 * ^ ^
434 * | |
435 * | r1.base
436 * |
437 * r2.base
438 *
439 * Expect to merge two entries into one region that starts at r2.base and
440 * has size of two regions minus their intersection. The total size of the
441 * reserved memory is updated, and the region counter is not updated.
442 */
443static int memblock_reserve_overlap_top_check(void)
444{
445 struct memblock_region *rgn;
446 phys_addr_t total_size;
447
448 rgn = &memblock.reserved.regions[0];
449
450 struct region r1 = {
451 .base = SZ_1G,
452 .size = SZ_1G
453 };
454 struct region r2 = {
455 .base = SZ_128M,
456 .size = SZ_1G
457 };
458
459 PREFIX_PUSH();
460
461 total_size = (r1.base - r2.base) + r1.size;
462
463 reset_memblock_regions();
464 memblock_reserve(r1.base, r1.size);
465 memblock_reserve(r2.base, r2.size);
466
467 ASSERT_EQ(rgn->base, r2.base);
468 ASSERT_EQ(rgn->size, total_size);
469
470 ASSERT_EQ(memblock.reserved.cnt, 1);
471 ASSERT_EQ(memblock.reserved.total_size, total_size);
472
473 test_pass_pop();
474
475 return 0;
476}
477
478/*
479 * A test that tries to mark two memory blocks r1 and r2 as reserved,
480 * where r2 overlaps with the end of r1 (that is
481 * r2.base < r1.base + r1.size):
482 *
483 * | +--------------+--+--------------+ |
484 * | | r1 | | r2 | |
485 * +--+--------------+--+--------------+--+
486 * ^ ^
487 * | |
488 * | r2.base
489 * |
490 * r1.base
491 *
492 * Expect to merge two entries into one region that starts at r1.base and
493 * has size of two regions minus their intersection. The total size of the
494 * reserved memory is updated, and the region counter is not updated.
495 */
496static int memblock_reserve_overlap_bottom_check(void)
497{
498 struct memblock_region *rgn;
499 phys_addr_t total_size;
500
501 rgn = &memblock.reserved.regions[0];
502
503 struct region r1 = {
504 .base = SZ_2K,
505 .size = SZ_128K
506 };
507 struct region r2 = {
508 .base = SZ_128K,
509 .size = SZ_128K
510 };
511
512 PREFIX_PUSH();
513
514 total_size = (r2.base - r1.base) + r2.size;
515
516 reset_memblock_regions();
517 memblock_reserve(r1.base, r1.size);
518 memblock_reserve(r2.base, r2.size);
519
520 ASSERT_EQ(rgn->base, r1.base);
521 ASSERT_EQ(rgn->size, total_size);
522
523 ASSERT_EQ(memblock.reserved.cnt, 1);
524 ASSERT_EQ(memblock.reserved.total_size, total_size);
525
526 test_pass_pop();
527
528 return 0;
529}
530
531/*
532 * A test that tries to mark two memory blocks r1 and r2 as reserved,
533 * where r2 is within the range of r1 (that is
534 * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)):
535 *
536 * | +-----+--+---------------------------|
537 * | | |r2| r1 |
538 * +-+-----+--+---------------------------+
539 * ^ ^
540 * | |
541 * | r2.base
542 * |
543 * r1.base
544 *
545 * Expect to merge two entries into one region that stays the same. The
546 * counter and total size of available memory are not updated.
547 */
548static int memblock_reserve_within_check(void)
549{
550 struct memblock_region *rgn;
551
552 rgn = &memblock.reserved.regions[0];
553
554 struct region r1 = {
555 .base = SZ_1M,
556 .size = SZ_8M
557 };
558 struct region r2 = {
559 .base = SZ_2M,
560 .size = SZ_64K
561 };
562
563 PREFIX_PUSH();
564
565 reset_memblock_regions();
566 memblock_reserve(r1.base, r1.size);
567 memblock_reserve(r2.base, r2.size);
568
569 ASSERT_EQ(rgn->base, r1.base);
570 ASSERT_EQ(rgn->size, r1.size);
571
572 ASSERT_EQ(memblock.reserved.cnt, 1);
573 ASSERT_EQ(memblock.reserved.total_size, r1.size);
574
575 test_pass_pop();
576
577 return 0;
578}
579
580/*
581 * A simple test that tries to reserve the same memory block twice.
582 * Expect the region counter and total size of reserved memory to not
583 * be updated.
584 */
585static int memblock_reserve_twice_check(void)
586{
587 struct region r = {
588 .base = SZ_16K,
589 .size = SZ_2M
590 };
591
592 PREFIX_PUSH();
593
594 reset_memblock_regions();
595
596 memblock_reserve(r.base, r.size);
597 memblock_reserve(r.base, r.size);
598
599 ASSERT_EQ(memblock.reserved.cnt, 1);
600 ASSERT_EQ(memblock.reserved.total_size, r.size);
601
602 test_pass_pop();
603
604 return 0;
605}
606
607static int memblock_reserve_checks(void)
608{
609 prefix_reset();
610 prefix_push(FUNC_RESERVE);
611 test_print("Running %s tests...\n", FUNC_RESERVE);
612
613 memblock_reserve_simple_check();
614 memblock_reserve_disjoint_check();
615 memblock_reserve_overlap_top_check();
616 memblock_reserve_overlap_bottom_check();
617 memblock_reserve_within_check();
618 memblock_reserve_twice_check();
619
620 prefix_pop();
621
622 return 0;
623}
624
625/*
626 * A simple test that tries to remove a region r1 from the array of
627 * available memory regions. By "removing" a region we mean overwriting it
628 * with the next region r2 in memblock.memory:
629 *
630 * | ...... +----------------+ |
631 * | : r1 : | r2 | |
632 * +--+----+----------+----------------+--+
633 * ^
634 * |
635 * rgn.base
636 *
637 * Expect to add two memory blocks r1 and r2 and then remove r1 so that
638 * r2 is the first available region. The region counter and total size
639 * are updated.
640 */
641static int memblock_remove_simple_check(void)
642{
643 struct memblock_region *rgn;
644
645 rgn = &memblock.memory.regions[0];
646
647 struct region r1 = {
648 .base = SZ_2K,
649 .size = SZ_4K
650 };
651 struct region r2 = {
652 .base = SZ_128K,
653 .size = SZ_4M
654 };
655
656 PREFIX_PUSH();
657
658 reset_memblock_regions();
659 memblock_add(r1.base, r1.size);
660 memblock_add(r2.base, r2.size);
661 memblock_remove(r1.base, r1.size);
662
663 ASSERT_EQ(rgn->base, r2.base);
664 ASSERT_EQ(rgn->size, r2.size);
665
666 ASSERT_EQ(memblock.memory.cnt, 1);
667 ASSERT_EQ(memblock.memory.total_size, r2.size);
668
669 test_pass_pop();
670
671 return 0;
672}
673
674/*
675 * A test that tries to remove a region r2 that was not registered as
676 * available memory (i.e. has no corresponding entry in memblock.memory):
677 *
678 * +----------------+
679 * | r2 |
680 * +----------------+
681 * | +----+ |
682 * | | r1 | |
683 * +--+----+------------------------------+
684 * ^
685 * |
686 * rgn.base
687 *
688 * Expect the array, regions counter and total size to not be modified.
689 */
690static int memblock_remove_absent_check(void)
691{
692 struct memblock_region *rgn;
693
694 rgn = &memblock.memory.regions[0];
695
696 struct region r1 = {
697 .base = SZ_512K,
698 .size = SZ_4M
699 };
700 struct region r2 = {
701 .base = SZ_64M,
702 .size = SZ_1G
703 };
704
705 PREFIX_PUSH();
706
707 reset_memblock_regions();
708 memblock_add(r1.base, r1.size);
709 memblock_remove(r2.base, r2.size);
710
711 ASSERT_EQ(rgn->base, r1.base);
712 ASSERT_EQ(rgn->size, r1.size);
713
714 ASSERT_EQ(memblock.memory.cnt, 1);
715 ASSERT_EQ(memblock.memory.total_size, r1.size);
716
717 test_pass_pop();
718
719 return 0;
720}
721
722/*
723 * A test that tries to remove a region r2 that overlaps with the
724 * beginning of the already existing entry r1
725 * (that is r1.base < r2.base + r2.size):
726 *
727 * +-----------------+
728 * | r2 |
729 * +-----------------+
730 * | .........+--------+ |
731 * | : r1 | rgn | |
732 * +-----------------+--------+--------+--+
733 * ^ ^
734 * | |
735 * | rgn.base
736 * r1.base
737 *
738 * Expect that only the intersection of both regions is removed from the
739 * available memory pool. The regions counter and total size are updated.
740 */
741static int memblock_remove_overlap_top_check(void)
742{
743 struct memblock_region *rgn;
744 phys_addr_t r1_end, r2_end, total_size;
745
746 rgn = &memblock.memory.regions[0];
747
748 struct region r1 = {
749 .base = SZ_32M,
750 .size = SZ_32M
751 };
752 struct region r2 = {
753 .base = SZ_16M,
754 .size = SZ_32M
755 };
756
757 PREFIX_PUSH();
758
759 r1_end = r1.base + r1.size;
760 r2_end = r2.base + r2.size;
761 total_size = r1_end - r2_end;
762
763 reset_memblock_regions();
764 memblock_add(r1.base, r1.size);
765 memblock_remove(r2.base, r2.size);
766
767 ASSERT_EQ(rgn->base, r1.base + r2.base);
768 ASSERT_EQ(rgn->size, total_size);
769
770 ASSERT_EQ(memblock.memory.cnt, 1);
771 ASSERT_EQ(memblock.memory.total_size, total_size);
772
773 test_pass_pop();
774
775 return 0;
776}
777
778/*
779 * A test that tries to remove a region r2 that overlaps with the end of
780 * the already existing region r1 (that is r2.base < r1.base + r1.size):
781 *
782 * +--------------------------------+
783 * | r2 |
784 * +--------------------------------+
785 * | +---+..... |
786 * | |rgn| r1 : |
787 * +-+---+----+---------------------------+
788 * ^
789 * |
790 * r1.base
791 *
792 * Expect that only the intersection of both regions is removed from the
793 * available memory pool. The regions counter and total size are updated.
794 */
795static int memblock_remove_overlap_bottom_check(void)
796{
797 struct memblock_region *rgn;
798 phys_addr_t total_size;
799
800 rgn = &memblock.memory.regions[0];
801
802 struct region r1 = {
803 .base = SZ_2M,
804 .size = SZ_64M
805 };
806 struct region r2 = {
807 .base = SZ_32M,
808 .size = SZ_256M
809 };
810
811 PREFIX_PUSH();
812
813 total_size = r2.base - r1.base;
814
815 reset_memblock_regions();
816 memblock_add(r1.base, r1.size);
817 memblock_remove(r2.base, r2.size);
818
819 ASSERT_EQ(rgn->base, r1.base);
820 ASSERT_EQ(rgn->size, total_size);
821
822 ASSERT_EQ(memblock.memory.cnt, 1);
823 ASSERT_EQ(memblock.memory.total_size, total_size);
824
825 test_pass_pop();
826
827 return 0;
828}
829
830/*
831 * A test that tries to remove a region r2 that is within the range of
832 * the already existing entry r1 (that is
833 * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)):
834 *
835 * +----+
836 * | r2 |
837 * +----+
838 * | +-------------+....+---------------+ |
839 * | | rgn1 | r1 | rgn2 | |
840 * +-+-------------+----+---------------+-+
841 * ^
842 * |
843 * r1.base
844 *
845 * Expect that the region is split into two - one that ends at r2.base and
846 * another that starts at r2.base + r2.size, with appropriate sizes. The
847 * region counter and total size are updated.
848 */
849static int memblock_remove_within_check(void)
850{
851 struct memblock_region *rgn1, *rgn2;
852 phys_addr_t r1_size, r2_size, total_size;
853
854 rgn1 = &memblock.memory.regions[0];
855 rgn2 = &memblock.memory.regions[1];
856
857 struct region r1 = {
858 .base = SZ_1M,
859 .size = SZ_32M
860 };
861 struct region r2 = {
862 .base = SZ_16M,
863 .size = SZ_1M
864 };
865
866 PREFIX_PUSH();
867
868 r1_size = r2.base - r1.base;
869 r2_size = (r1.base + r1.size) - (r2.base + r2.size);
870 total_size = r1_size + r2_size;
871
872 reset_memblock_regions();
873 memblock_add(r1.base, r1.size);
874 memblock_remove(r2.base, r2.size);
875
876 ASSERT_EQ(rgn1->base, r1.base);
877 ASSERT_EQ(rgn1->size, r1_size);
878
879 ASSERT_EQ(rgn2->base, r2.base + r2.size);
880 ASSERT_EQ(rgn2->size, r2_size);
881
882 ASSERT_EQ(memblock.memory.cnt, 2);
883 ASSERT_EQ(memblock.memory.total_size, total_size);
884
885 test_pass_pop();
886
887 return 0;
888}
889
890static int memblock_remove_checks(void)
891{
892 prefix_reset();
893 prefix_push(FUNC_REMOVE);
894 test_print("Running %s tests...\n", FUNC_REMOVE);
895
896 memblock_remove_simple_check();
897 memblock_remove_absent_check();
898 memblock_remove_overlap_top_check();
899 memblock_remove_overlap_bottom_check();
900 memblock_remove_within_check();
901
902 prefix_pop();
903
904 return 0;
905}
906
907/*
908 * A simple test that tries to free a memory block r1 that was marked
909 * earlier as reserved. By "freeing" a region we mean overwriting it with
910 * the next entry r2 in memblock.reserved:
911 *
912 * | ...... +----+ |
913 * | : r1 : | r2 | |
914 * +--------------+----+-----------+----+-+
915 * ^
916 * |
917 * rgn.base
918 *
919 * Expect to reserve two memory regions and then erase r1 region with the
920 * value of r2. The region counter and total size are updated.
921 */
922static int memblock_free_simple_check(void)
923{
924 struct memblock_region *rgn;
925
926 rgn = &memblock.reserved.regions[0];
927
928 struct region r1 = {
929 .base = SZ_4M,
930 .size = SZ_1M
931 };
932 struct region r2 = {
933 .base = SZ_8M,
934 .size = SZ_1M
935 };
936
937 PREFIX_PUSH();
938
939 reset_memblock_regions();
940 memblock_reserve(r1.base, r1.size);
941 memblock_reserve(r2.base, r2.size);
942 memblock_free((void *)r1.base, r1.size);
943
944 ASSERT_EQ(rgn->base, r2.base);
945 ASSERT_EQ(rgn->size, r2.size);
946
947 ASSERT_EQ(memblock.reserved.cnt, 1);
948 ASSERT_EQ(memblock.reserved.total_size, r2.size);
949
950 test_pass_pop();
951
952 return 0;
953}
954
955/*
956 * A test that tries to free a region r2 that was not marked as reserved
957 * (i.e. has no corresponding entry in memblock.reserved):
958 *
959 * +----------------+
960 * | r2 |
961 * +----------------+
962 * | +----+ |
963 * | | r1 | |
964 * +--+----+------------------------------+
965 * ^
966 * |
967 * rgn.base
968 *
969 * The array, regions counter and total size are not modified.
970 */
971static int memblock_free_absent_check(void)
972{
973 struct memblock_region *rgn;
974
975 rgn = &memblock.reserved.regions[0];
976
977 struct region r1 = {
978 .base = SZ_2M,
979 .size = SZ_8K
980 };
981 struct region r2 = {
982 .base = SZ_16M,
983 .size = SZ_128M
984 };
985
986 PREFIX_PUSH();
987
988 reset_memblock_regions();
989 memblock_reserve(r1.base, r1.size);
990 memblock_free((void *)r2.base, r2.size);
991
992 ASSERT_EQ(rgn->base, r1.base);
993 ASSERT_EQ(rgn->size, r1.size);
994
995 ASSERT_EQ(memblock.reserved.cnt, 1);
996 ASSERT_EQ(memblock.reserved.total_size, r1.size);
997
998 test_pass_pop();
999
1000 return 0;
1001}
1002
1003/*
1004 * A test that tries to free a region r2 that overlaps with the beginning
1005 * of the already existing entry r1 (that is r1.base < r2.base + r2.size):
1006 *
1007 * +----+
1008 * | r2 |
1009 * +----+
1010 * | ...+--------------+ |
1011 * | : | r1 | |
1012 * +----+--+--------------+---------------+
1013 * ^ ^
1014 * | |
1015 * | rgn.base
1016 * |
1017 * r1.base
1018 *
1019 * Expect that only the intersection of both regions is freed. The
1020 * regions counter and total size are updated.
1021 */
1022static int memblock_free_overlap_top_check(void)
1023{
1024 struct memblock_region *rgn;
1025 phys_addr_t total_size;
1026
1027 rgn = &memblock.reserved.regions[0];
1028
1029 struct region r1 = {
1030 .base = SZ_8M,
1031 .size = SZ_32M
1032 };
1033 struct region r2 = {
1034 .base = SZ_1M,
1035 .size = SZ_8M
1036 };
1037
1038 PREFIX_PUSH();
1039
1040 total_size = (r1.size + r1.base) - (r2.base + r2.size);
1041
1042 reset_memblock_regions();
1043 memblock_reserve(r1.base, r1.size);
1044 memblock_free((void *)r2.base, r2.size);
1045
1046 ASSERT_EQ(rgn->base, r2.base + r2.size);
1047 ASSERT_EQ(rgn->size, total_size);
1048
1049 ASSERT_EQ(memblock.reserved.cnt, 1);
1050 ASSERT_EQ(memblock.reserved.total_size, total_size);
1051
1052 test_pass_pop();
1053
1054 return 0;
1055}
1056
1057/*
1058 * A test that tries to free a region r2 that overlaps with the end of
1059 * the already existing entry r1 (that is r2.base < r1.base + r1.size):
1060 *
1061 * +----------------+
1062 * | r2 |
1063 * +----------------+
1064 * | +-----------+..... |
1065 * | | r1 | : |
1066 * +----+-----------+----+----------------+
1067 *
1068 * Expect that only the intersection of both regions is freed. The
1069 * regions counter and total size are updated.
1070 */
1071static int memblock_free_overlap_bottom_check(void)
1072{
1073 struct memblock_region *rgn;
1074 phys_addr_t total_size;
1075
1076 rgn = &memblock.reserved.regions[0];
1077
1078 struct region r1 = {
1079 .base = SZ_8M,
1080 .size = SZ_32M
1081 };
1082 struct region r2 = {
1083 .base = SZ_32M,
1084 .size = SZ_32M
1085 };
1086
1087 PREFIX_PUSH();
1088
1089 total_size = r2.base - r1.base;
1090
1091 reset_memblock_regions();
1092 memblock_reserve(r1.base, r1.size);
1093 memblock_free((void *)r2.base, r2.size);
1094
1095 ASSERT_EQ(rgn->base, r1.base);
1096 ASSERT_EQ(rgn->size, total_size);
1097
1098 ASSERT_EQ(memblock.reserved.cnt, 1);
1099 ASSERT_EQ(memblock.reserved.total_size, total_size);
1100
1101 test_pass_pop();
1102
1103 return 0;
1104}
1105
1106/*
1107 * A test that tries to free a region r2 that is within the range of the
1108 * already existing entry r1 (that is
1109 * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)):
1110 *
1111 * +----+
1112 * | r2 |
1113 * +----+
1114 * | +------------+....+---------------+
1115 * | | rgn1 | r1 | rgn2 |
1116 * +----+------------+----+---------------+
1117 * ^
1118 * |
1119 * r1.base
1120 *
1121 * Expect that the region is split into two - one that ends at r2.base and
1122 * another that starts at r2.base + r2.size, with appropriate sizes. The
1123 * region counter and total size fields are updated.
1124 */
1125static int memblock_free_within_check(void)
1126{
1127 struct memblock_region *rgn1, *rgn2;
1128 phys_addr_t r1_size, r2_size, total_size;
1129
1130 rgn1 = &memblock.reserved.regions[0];
1131 rgn2 = &memblock.reserved.regions[1];
1132
1133 struct region r1 = {
1134 .base = SZ_1M,
1135 .size = SZ_8M
1136 };
1137 struct region r2 = {
1138 .base = SZ_4M,
1139 .size = SZ_1M
1140 };
1141
1142 PREFIX_PUSH();
1143
1144 r1_size = r2.base - r1.base;
1145 r2_size = (r1.base + r1.size) - (r2.base + r2.size);
1146 total_size = r1_size + r2_size;
1147
1148 reset_memblock_regions();
1149 memblock_reserve(r1.base, r1.size);
1150 memblock_free((void *)r2.base, r2.size);
1151
1152 ASSERT_EQ(rgn1->base, r1.base);
1153 ASSERT_EQ(rgn1->size, r1_size);
1154
1155 ASSERT_EQ(rgn2->base, r2.base + r2.size);
1156 ASSERT_EQ(rgn2->size, r2_size);
1157
1158 ASSERT_EQ(memblock.reserved.cnt, 2);
1159 ASSERT_EQ(memblock.reserved.total_size, total_size);
1160
1161 test_pass_pop();
1162
1163 return 0;
1164}
1165
1166static int memblock_free_checks(void)
1167{
1168 prefix_reset();
1169 prefix_push(FUNC_FREE);
1170 test_print("Running %s tests...\n", FUNC_FREE);
1171
1172 memblock_free_simple_check();
1173 memblock_free_absent_check();
1174 memblock_free_overlap_top_check();
1175 memblock_free_overlap_bottom_check();
1176 memblock_free_within_check();
1177
1178 prefix_pop();
1179
1180 return 0;
1181}
1182
1183int memblock_basic_checks(void)
1184{
1185 memblock_initialization_check();
1186 memblock_add_checks();
1187 memblock_reserve_checks();
1188 memblock_remove_checks();
1189 memblock_free_checks();
1190
1191 return 0;
1192}