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

alloc_helpers_api.c (10135B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2#include "alloc_helpers_api.h"
      3
      4/*
      5 * A simple test that tries to allocate a memory region above a specified,
      6 * aligned address:
      7 *
      8 *             +
      9 *  |          +-----------+         |
     10 *  |          |    rgn    |         |
     11 *  +----------+-----------+---------+
     12 *             ^
     13 *             |
     14 *             Aligned min_addr
     15 *
     16 * Expect to allocate a cleared region at the minimal memory address.
     17 */
     18static int alloc_from_simple_generic_check(void)
     19{
     20	struct memblock_region *rgn = &memblock.reserved.regions[0];
     21	void *allocated_ptr = NULL;
     22	char *b;
     23
     24	phys_addr_t size = SZ_16;
     25	phys_addr_t min_addr;
     26
     27	setup_memblock();
     28
     29	min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES;
     30
     31	allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
     32	b = (char *)allocated_ptr;
     33
     34	assert(allocated_ptr);
     35	assert(*b == 0);
     36
     37	assert(rgn->size == size);
     38	assert(rgn->base == min_addr);
     39
     40	assert(memblock.reserved.cnt == 1);
     41	assert(memblock.reserved.total_size == size);
     42
     43	return 0;
     44}
     45
     46/*
     47 * A test that tries to allocate a memory region above a certain address.
     48 * The minimal address here is not aligned:
     49 *
     50 *         +      +
     51 *  |      +      +---------+            |
     52 *  |      |      |   rgn   |            |
     53 *  +------+------+---------+------------+
     54 *         ^      ^------.
     55 *         |             |
     56 *       min_addr        Aligned address
     57 *                       boundary
     58 *
     59 * Expect to allocate a cleared region at the closest aligned memory address.
     60 */
     61static int alloc_from_misaligned_generic_check(void)
     62{
     63	struct memblock_region *rgn = &memblock.reserved.regions[0];
     64	void *allocated_ptr = NULL;
     65	char *b;
     66
     67	phys_addr_t size = SZ_32;
     68	phys_addr_t min_addr;
     69
     70	setup_memblock();
     71
     72	/* A misaligned address */
     73	min_addr = memblock_end_of_DRAM() - (SMP_CACHE_BYTES * 2 - 1);
     74
     75	allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
     76	b = (char *)allocated_ptr;
     77
     78	assert(allocated_ptr);
     79	assert(*b == 0);
     80
     81	assert(rgn->size == size);
     82	assert(rgn->base == memblock_end_of_DRAM() - SMP_CACHE_BYTES);
     83
     84	assert(memblock.reserved.cnt == 1);
     85	assert(memblock.reserved.total_size == size);
     86
     87	return 0;
     88}
     89
     90/*
     91 * A test that tries to allocate a memory region above an address that is too
     92 * close to the end of the memory:
     93 *
     94 *              +        +
     95 *  |           +--------+---+      |
     96 *  |           |   rgn  +   |      |
     97 *  +-----------+--------+---+------+
     98 *              ^        ^
     99 *              |        |
    100 *              |        min_addr
    101 *              |
    102 *              Aligned address
    103 *              boundary
    104 *
    105 * Expect to prioritize granting memory over satisfying the minimal address
    106 * requirement.
    107 */
    108static int alloc_from_top_down_high_addr_check(void)
    109{
    110	struct memblock_region *rgn = &memblock.reserved.regions[0];
    111	void *allocated_ptr = NULL;
    112
    113	phys_addr_t size = SZ_32;
    114	phys_addr_t min_addr;
    115
    116	setup_memblock();
    117
    118	/* The address is too close to the end of the memory */
    119	min_addr = memblock_end_of_DRAM() - SZ_16;
    120
    121	allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
    122
    123	assert(allocated_ptr);
    124	assert(rgn->size == size);
    125	assert(rgn->base == memblock_end_of_DRAM() - SMP_CACHE_BYTES);
    126
    127	assert(memblock.reserved.cnt == 1);
    128	assert(memblock.reserved.total_size == size);
    129
    130	return 0;
    131}
    132
    133/*
    134 * A test that tries to allocate a memory region when there is no space
    135 * available above the minimal address above a certain address:
    136 *
    137 *                     +
    138 *  |        +---------+-------------|
    139 *  |        |   rgn   |             |
    140 *  +--------+---------+-------------+
    141 *                     ^
    142 *                     |
    143 *                     min_addr
    144 *
    145 * Expect to prioritize granting memory over satisfying the minimal address
    146 * requirement and to allocate next to the previously reserved region. The
    147 * regions get merged into one.
    148 */
    149static int alloc_from_top_down_no_space_above_check(void)
    150{
    151	struct memblock_region *rgn = &memblock.reserved.regions[0];
    152	void *allocated_ptr = NULL;
    153
    154	phys_addr_t r1_size = SZ_64;
    155	phys_addr_t r2_size = SZ_2;
    156	phys_addr_t total_size = r1_size + r2_size;
    157	phys_addr_t min_addr;
    158
    159	setup_memblock();
    160
    161	min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES * 2;
    162
    163	/* No space above this address */
    164	memblock_reserve(min_addr, r2_size);
    165
    166	allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
    167
    168	assert(allocated_ptr);
    169	assert(rgn->base == min_addr - r1_size);
    170	assert(rgn->size == total_size);
    171
    172	assert(memblock.reserved.cnt == 1);
    173	assert(memblock.reserved.total_size == total_size);
    174
    175	return 0;
    176}
    177
    178/*
    179 * A test that tries to allocate a memory region with a minimal address below
    180 * the start address of the available memory. As the allocation is top-down,
    181 * first reserve a region that will force allocation near the start.
    182 * Expect successful allocation and merge of both regions.
    183 */
    184static int alloc_from_top_down_min_addr_cap_check(void)
    185{
    186	struct memblock_region *rgn = &memblock.reserved.regions[0];
    187	void *allocated_ptr = NULL;
    188
    189	phys_addr_t r1_size = SZ_64;
    190	phys_addr_t min_addr;
    191	phys_addr_t start_addr;
    192
    193	setup_memblock();
    194
    195	start_addr = (phys_addr_t)memblock_start_of_DRAM();
    196	min_addr = start_addr - SMP_CACHE_BYTES * 3;
    197
    198	memblock_reserve(start_addr + r1_size, MEM_SIZE - r1_size);
    199
    200	allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
    201
    202	assert(allocated_ptr);
    203	assert(rgn->base == start_addr);
    204	assert(rgn->size == MEM_SIZE);
    205
    206	assert(memblock.reserved.cnt == 1);
    207	assert(memblock.reserved.total_size == MEM_SIZE);
    208
    209	return 0;
    210}
    211
    212/*
    213 * A test that tries to allocate a memory region above an address that is too
    214 * close to the end of the memory:
    215 *
    216 *                             +
    217 *  |-----------+              +     |
    218 *  |    rgn    |              |     |
    219 *  +-----------+--------------+-----+
    220 *  ^                          ^
    221 *  |                          |
    222 *  Aligned address            min_addr
    223 *  boundary
    224 *
    225 * Expect to prioritize granting memory over satisfying the minimal address
    226 * requirement. Allocation happens at beginning of the available memory.
    227 */
    228static int alloc_from_bottom_up_high_addr_check(void)
    229{
    230	struct memblock_region *rgn = &memblock.reserved.regions[0];
    231	void *allocated_ptr = NULL;
    232
    233	phys_addr_t size = SZ_32;
    234	phys_addr_t min_addr;
    235
    236	setup_memblock();
    237
    238	/* The address is too close to the end of the memory */
    239	min_addr = memblock_end_of_DRAM() - SZ_8;
    240
    241	allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
    242
    243	assert(allocated_ptr);
    244	assert(rgn->size == size);
    245	assert(rgn->base == memblock_start_of_DRAM());
    246
    247	assert(memblock.reserved.cnt == 1);
    248	assert(memblock.reserved.total_size == size);
    249
    250	return 0;
    251}
    252
    253/*
    254 * A test that tries to allocate a memory region when there is no space
    255 * available above the minimal address above a certain address:
    256 *
    257 *                   +
    258 *  |-----------+    +-------------------|
    259 *  |    rgn    |    |                   |
    260 *  +-----------+----+-------------------+
    261 *                   ^
    262 *                   |
    263 *                   min_addr
    264 *
    265 * Expect to prioritize granting memory over satisfying the minimal address
    266 * requirement and to allocate at the beginning of the available memory.
    267 */
    268static int alloc_from_bottom_up_no_space_above_check(void)
    269{
    270	struct memblock_region *rgn = &memblock.reserved.regions[0];
    271	void *allocated_ptr = NULL;
    272
    273	phys_addr_t r1_size = SZ_64;
    274	phys_addr_t min_addr;
    275	phys_addr_t r2_size;
    276
    277	setup_memblock();
    278
    279	min_addr = memblock_start_of_DRAM() + SZ_128;
    280	r2_size = memblock_end_of_DRAM() - min_addr;
    281
    282	/* No space above this address */
    283	memblock_reserve(min_addr - SMP_CACHE_BYTES, r2_size);
    284
    285	allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
    286
    287	assert(allocated_ptr);
    288	assert(rgn->base == memblock_start_of_DRAM());
    289	assert(rgn->size == r1_size);
    290
    291	assert(memblock.reserved.cnt == 2);
    292	assert(memblock.reserved.total_size == r1_size + r2_size);
    293
    294	return 0;
    295}
    296
    297/*
    298 * A test that tries to allocate a memory region with a minimal address below
    299 * the start address of the available memory. Expect to allocate a region
    300 * at the beginning of the available memory.
    301 */
    302static int alloc_from_bottom_up_min_addr_cap_check(void)
    303{
    304	struct memblock_region *rgn = &memblock.reserved.regions[0];
    305	void *allocated_ptr = NULL;
    306
    307	phys_addr_t r1_size = SZ_64;
    308	phys_addr_t min_addr;
    309	phys_addr_t start_addr;
    310
    311	setup_memblock();
    312
    313	start_addr = (phys_addr_t)memblock_start_of_DRAM();
    314	min_addr = start_addr - SMP_CACHE_BYTES * 3;
    315
    316	allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
    317
    318	assert(allocated_ptr);
    319	assert(rgn->base == start_addr);
    320	assert(rgn->size == r1_size);
    321
    322	assert(memblock.reserved.cnt == 1);
    323	assert(memblock.reserved.total_size == r1_size);
    324
    325	return 0;
    326}
    327
    328/* Test case wrappers */
    329static int alloc_from_simple_check(void)
    330{
    331	memblock_set_bottom_up(false);
    332	alloc_from_simple_generic_check();
    333	memblock_set_bottom_up(true);
    334	alloc_from_simple_generic_check();
    335
    336	return 0;
    337}
    338
    339static int alloc_from_misaligned_check(void)
    340{
    341	memblock_set_bottom_up(false);
    342	alloc_from_misaligned_generic_check();
    343	memblock_set_bottom_up(true);
    344	alloc_from_misaligned_generic_check();
    345
    346	return 0;
    347}
    348
    349static int alloc_from_high_addr_check(void)
    350{
    351	memblock_set_bottom_up(false);
    352	alloc_from_top_down_high_addr_check();
    353	memblock_set_bottom_up(true);
    354	alloc_from_bottom_up_high_addr_check();
    355
    356	return 0;
    357}
    358
    359static int alloc_from_no_space_above_check(void)
    360{
    361	memblock_set_bottom_up(false);
    362	alloc_from_top_down_no_space_above_check();
    363	memblock_set_bottom_up(true);
    364	alloc_from_bottom_up_no_space_above_check();
    365
    366	return 0;
    367}
    368
    369static int alloc_from_min_addr_cap_check(void)
    370{
    371	memblock_set_bottom_up(false);
    372	alloc_from_top_down_min_addr_cap_check();
    373	memblock_set_bottom_up(true);
    374	alloc_from_bottom_up_min_addr_cap_check();
    375
    376	return 0;
    377}
    378
    379int memblock_alloc_helpers_checks(void)
    380{
    381	reset_memblock_attributes();
    382	dummy_physical_memory_init();
    383
    384	alloc_from_simple_check();
    385	alloc_from_misaligned_check();
    386	alloc_from_high_addr_check();
    387	alloc_from_no_space_above_check();
    388	alloc_from_min_addr_cap_check();
    389
    390	dummy_physical_memory_cleanup();
    391
    392	return 0;
    393}