cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

basic_api.c (25507B)


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