| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113 |
- // SPDX-License-Identifier: GPL-2.0-or-later
- #include "alloc_exact_nid_api.h"
- #include "alloc_nid_api.h"
- #define FUNC_NAME "memblock_alloc_exact_nid_raw"
- /*
- * contains the fraction of MEM_SIZE contained in each node in basis point
- * units (one hundredth of 1% or 1/10000)
- */
- static const unsigned int node_fractions[] = {
- 2500, /* 1/4 */
- 625, /* 1/16 */
- 1250, /* 1/8 */
- 1250, /* 1/8 */
- 625, /* 1/16 */
- 625, /* 1/16 */
- 2500, /* 1/4 */
- 625, /* 1/16 */
- };
- /*
- * A test that tries to allocate a memory region in a specific NUMA node that
- * has enough memory to allocate a region of the requested size.
- * Expect to allocate an aligned region at the end of the requested node.
- */
- static int alloc_exact_nid_top_down_numa_simple_check(void)
- {
- int nid_req = 3;
- struct memblock_region *new_rgn = &memblock.reserved.regions[0];
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- void *allocated_ptr = NULL;
- phys_addr_t size;
- phys_addr_t min_addr;
- phys_addr_t max_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- ASSERT_LE(SZ_4, req_node->size);
- size = req_node->size / SZ_4;
- min_addr = memblock_start_of_DRAM();
- max_addr = memblock_end_of_DRAM();
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_NE(allocated_ptr, NULL);
- ASSERT_MEM_NE(allocated_ptr, 0, size);
- ASSERT_EQ(new_rgn->size, size);
- ASSERT_EQ(new_rgn->base, region_end(req_node) - size);
- ASSERT_LE(req_node->base, new_rgn->base);
- ASSERT_EQ(memblock.reserved.cnt, 1);
- ASSERT_EQ(memblock.reserved.total_size, size);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate a memory region in a specific NUMA node that
- * is partially reserved but has enough memory for the allocated region:
- *
- * | +---------------------------------------+ |
- * | | requested | |
- * +-----------+---------------------------------------+----------+
- *
- * | +------------------+ +-----+ |
- * | | reserved | | new | |
- * +-----------+------------------+--------------+-----+----------+
- *
- * Expect to allocate an aligned region at the end of the requested node. The
- * region count and total size get updated.
- */
- static int alloc_exact_nid_top_down_numa_part_reserved_check(void)
- {
- int nid_req = 4;
- struct memblock_region *new_rgn = &memblock.reserved.regions[1];
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- void *allocated_ptr = NULL;
- struct region r1;
- phys_addr_t size;
- phys_addr_t min_addr;
- phys_addr_t max_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- ASSERT_LE(SZ_8, req_node->size);
- r1.base = req_node->base;
- r1.size = req_node->size / SZ_2;
- size = r1.size / SZ_4;
- min_addr = memblock_start_of_DRAM();
- max_addr = memblock_end_of_DRAM();
- memblock_reserve(r1.base, r1.size);
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_NE(allocated_ptr, NULL);
- ASSERT_MEM_NE(allocated_ptr, 0, size);
- ASSERT_EQ(new_rgn->size, size);
- ASSERT_EQ(new_rgn->base, region_end(req_node) - size);
- ASSERT_LE(req_node->base, new_rgn->base);
- ASSERT_EQ(memblock.reserved.cnt, 2);
- ASSERT_EQ(memblock.reserved.total_size, size + r1.size);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate a memory region that spans over the min_addr
- * and max_addr range and overlaps with two different nodes, where the first
- * node is the requested node:
- *
- * min_addr
- * | max_addr
- * | |
- * v v
- * | +-----------------------+-----------+ |
- * | | requested | node3 | |
- * +-----------+-----------------------+-----------+--------------+
- * + +
- * | +-----------+ |
- * | | rgn | |
- * +-----------------------+-----------+--------------------------+
- *
- * Expect to drop the lower limit and allocate a memory region that ends at
- * the end of the requested node.
- */
- static int alloc_exact_nid_top_down_numa_split_range_low_check(void)
- {
- int nid_req = 2;
- struct memblock_region *new_rgn = &memblock.reserved.regions[0];
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- void *allocated_ptr = NULL;
- phys_addr_t size = SZ_512;
- phys_addr_t min_addr;
- phys_addr_t max_addr;
- phys_addr_t req_node_end;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- req_node_end = region_end(req_node);
- min_addr = req_node_end - SZ_256;
- max_addr = min_addr + size;
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_NE(allocated_ptr, NULL);
- ASSERT_MEM_NE(allocated_ptr, 0, size);
- ASSERT_EQ(new_rgn->size, size);
- ASSERT_EQ(new_rgn->base, req_node_end - size);
- ASSERT_LE(req_node->base, new_rgn->base);
- ASSERT_EQ(memblock.reserved.cnt, 1);
- ASSERT_EQ(memblock.reserved.total_size, size);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate a memory region that spans over the min_addr
- * and max_addr range and overlaps with two different nodes, where the requested
- * node ends before min_addr:
- *
- * min_addr
- * | max_addr
- * | |
- * v v
- * | +---------------+ +-------------+---------+ |
- * | | requested | | node1 | node2 | |
- * +----+---------------+--------+-------------+---------+----------+
- * + +
- * | +---------+ |
- * | | rgn | |
- * +----------+---------+-------------------------------------------+
- *
- * Expect to drop the lower limit and allocate a memory region that ends at
- * the end of the requested node.
- */
- static int alloc_exact_nid_top_down_numa_no_overlap_split_check(void)
- {
- int nid_req = 2;
- struct memblock_region *new_rgn = &memblock.reserved.regions[0];
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- struct memblock_region *node2 = &memblock.memory.regions[6];
- void *allocated_ptr = NULL;
- phys_addr_t size;
- phys_addr_t min_addr;
- phys_addr_t max_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- size = SZ_512;
- min_addr = node2->base - SZ_256;
- max_addr = min_addr + size;
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_NE(allocated_ptr, NULL);
- ASSERT_MEM_NE(allocated_ptr, 0, size);
- ASSERT_EQ(new_rgn->size, size);
- ASSERT_EQ(new_rgn->base, region_end(req_node) - size);
- ASSERT_LE(req_node->base, new_rgn->base);
- ASSERT_EQ(memblock.reserved.cnt, 1);
- ASSERT_EQ(memblock.reserved.total_size, size);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate memory within min_addr and max_add range when
- * the requested node and the range do not overlap, and requested node ends
- * before min_addr. The range overlaps with multiple nodes along node
- * boundaries:
- *
- * min_addr
- * | max_addr
- * | |
- * v v
- * |-----------+ +----------+----...----+----------+ |
- * | requested | | min node | ... | max node | |
- * +-----------+-----------+----------+----...----+----------+------+
- * + +
- * | +-----+ |
- * | | rgn | |
- * +-----+-----+----------------------------------------------------+
- *
- * Expect to drop the lower limit and allocate a memory region that ends at
- * the end of the requested node.
- */
- static int alloc_exact_nid_top_down_numa_no_overlap_low_check(void)
- {
- int nid_req = 0;
- struct memblock_region *new_rgn = &memblock.reserved.regions[0];
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- struct memblock_region *min_node = &memblock.memory.regions[2];
- struct memblock_region *max_node = &memblock.memory.regions[5];
- void *allocated_ptr = NULL;
- phys_addr_t size = SZ_64;
- phys_addr_t max_addr;
- phys_addr_t min_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- min_addr = min_node->base;
- max_addr = region_end(max_node);
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_NE(allocated_ptr, NULL);
- ASSERT_MEM_NE(allocated_ptr, 0, size);
- ASSERT_EQ(new_rgn->size, size);
- ASSERT_EQ(new_rgn->base, region_end(req_node) - size);
- ASSERT_EQ(memblock.reserved.cnt, 1);
- ASSERT_EQ(memblock.reserved.total_size, size);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate a memory region in a specific NUMA node that
- * has enough memory to allocate a region of the requested size.
- * Expect to allocate an aligned region at the beginning of the requested node.
- */
- static int alloc_exact_nid_bottom_up_numa_simple_check(void)
- {
- int nid_req = 3;
- struct memblock_region *new_rgn = &memblock.reserved.regions[0];
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- void *allocated_ptr = NULL;
- phys_addr_t size;
- phys_addr_t min_addr;
- phys_addr_t max_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- ASSERT_LE(SZ_4, req_node->size);
- size = req_node->size / SZ_4;
- min_addr = memblock_start_of_DRAM();
- max_addr = memblock_end_of_DRAM();
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_NE(allocated_ptr, NULL);
- ASSERT_MEM_NE(allocated_ptr, 0, size);
- ASSERT_EQ(new_rgn->size, size);
- ASSERT_EQ(new_rgn->base, req_node->base);
- ASSERT_LE(region_end(new_rgn), region_end(req_node));
- ASSERT_EQ(memblock.reserved.cnt, 1);
- ASSERT_EQ(memblock.reserved.total_size, size);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate a memory region in a specific NUMA node that
- * is partially reserved but has enough memory for the allocated region:
- *
- * | +---------------------------------------+ |
- * | | requested | |
- * +-----------+---------------------------------------+---------+
- *
- * | +------------------+-----+ |
- * | | reserved | new | |
- * +-----------+------------------+-----+------------------------+
- *
- * Expect to allocate an aligned region in the requested node that merges with
- * the existing reserved region. The total size gets updated.
- */
- static int alloc_exact_nid_bottom_up_numa_part_reserved_check(void)
- {
- int nid_req = 4;
- struct memblock_region *new_rgn = &memblock.reserved.regions[0];
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- void *allocated_ptr = NULL;
- struct region r1;
- phys_addr_t size;
- phys_addr_t min_addr;
- phys_addr_t max_addr;
- phys_addr_t total_size;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- ASSERT_LE(SZ_8, req_node->size);
- r1.base = req_node->base;
- r1.size = req_node->size / SZ_2;
- size = r1.size / SZ_4;
- min_addr = memblock_start_of_DRAM();
- max_addr = memblock_end_of_DRAM();
- total_size = size + r1.size;
- memblock_reserve(r1.base, r1.size);
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_NE(allocated_ptr, NULL);
- ASSERT_MEM_NE(allocated_ptr, 0, size);
- ASSERT_EQ(new_rgn->size, total_size);
- ASSERT_EQ(new_rgn->base, req_node->base);
- ASSERT_LE(region_end(new_rgn), region_end(req_node));
- ASSERT_EQ(memblock.reserved.cnt, 1);
- ASSERT_EQ(memblock.reserved.total_size, total_size);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate a memory region that spans over the min_addr
- * and max_addr range and overlaps with two different nodes, where the first
- * node is the requested node:
- *
- * min_addr
- * | max_addr
- * | |
- * v v
- * | +-----------------------+-----------+ |
- * | | requested | node3 | |
- * +-----------+-----------------------+-----------+--------------+
- * + +
- * | +-----------+ |
- * | | rgn | |
- * +-----------+-----------+--------------------------------------+
- *
- * Expect to drop the lower limit and allocate a memory region at the beginning
- * of the requested node.
- */
- static int alloc_exact_nid_bottom_up_numa_split_range_low_check(void)
- {
- int nid_req = 2;
- struct memblock_region *new_rgn = &memblock.reserved.regions[0];
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- void *allocated_ptr = NULL;
- phys_addr_t size = SZ_512;
- phys_addr_t min_addr;
- phys_addr_t max_addr;
- phys_addr_t req_node_end;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- req_node_end = region_end(req_node);
- min_addr = req_node_end - SZ_256;
- max_addr = min_addr + size;
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_NE(allocated_ptr, NULL);
- ASSERT_MEM_NE(allocated_ptr, 0, size);
- ASSERT_EQ(new_rgn->size, size);
- ASSERT_EQ(new_rgn->base, req_node->base);
- ASSERT_LE(region_end(new_rgn), req_node_end);
- ASSERT_EQ(memblock.reserved.cnt, 1);
- ASSERT_EQ(memblock.reserved.total_size, size);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate a memory region that spans over the min_addr
- * and max_addr range and overlaps with two different nodes, where the requested
- * node ends before min_addr:
- *
- * min_addr
- * | max_addr
- * | |
- * v v
- * | +---------------+ +-------------+---------+ |
- * | | requested | | node1 | node2 | |
- * +----+---------------+--------+-------------+---------+---------+
- * + +
- * | +---------+ |
- * | | rgn | |
- * +----+---------+------------------------------------------------+
- *
- * Expect to drop the lower limit and allocate a memory region that starts at
- * the beginning of the requested node.
- */
- static int alloc_exact_nid_bottom_up_numa_no_overlap_split_check(void)
- {
- int nid_req = 2;
- struct memblock_region *new_rgn = &memblock.reserved.regions[0];
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- struct memblock_region *node2 = &memblock.memory.regions[6];
- void *allocated_ptr = NULL;
- phys_addr_t size;
- phys_addr_t min_addr;
- phys_addr_t max_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- size = SZ_512;
- min_addr = node2->base - SZ_256;
- max_addr = min_addr + size;
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_NE(allocated_ptr, NULL);
- ASSERT_MEM_NE(allocated_ptr, 0, size);
- ASSERT_EQ(new_rgn->size, size);
- ASSERT_EQ(new_rgn->base, req_node->base);
- ASSERT_LE(region_end(new_rgn), region_end(req_node));
- ASSERT_EQ(memblock.reserved.cnt, 1);
- ASSERT_EQ(memblock.reserved.total_size, size);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate memory within min_addr and max_add range when
- * the requested node and the range do not overlap, and requested node ends
- * before min_addr. The range overlaps with multiple nodes along node
- * boundaries:
- *
- * min_addr
- * | max_addr
- * | |
- * v v
- * |-----------+ +----------+----...----+----------+ |
- * | requested | | min node | ... | max node | |
- * +-----------+-----------+----------+----...----+----------+------+
- * + +
- * |-----+ |
- * | rgn | |
- * +-----+----------------------------------------------------------+
- *
- * Expect to drop the lower limit and allocate a memory region that starts at
- * the beginning of the requested node.
- */
- static int alloc_exact_nid_bottom_up_numa_no_overlap_low_check(void)
- {
- int nid_req = 0;
- struct memblock_region *new_rgn = &memblock.reserved.regions[0];
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- struct memblock_region *min_node = &memblock.memory.regions[2];
- struct memblock_region *max_node = &memblock.memory.regions[5];
- void *allocated_ptr = NULL;
- phys_addr_t size = SZ_64;
- phys_addr_t max_addr;
- phys_addr_t min_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- min_addr = min_node->base;
- max_addr = region_end(max_node);
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_NE(allocated_ptr, NULL);
- ASSERT_MEM_NE(allocated_ptr, 0, size);
- ASSERT_EQ(new_rgn->size, size);
- ASSERT_EQ(new_rgn->base, req_node->base);
- ASSERT_LE(region_end(new_rgn), region_end(req_node));
- ASSERT_EQ(memblock.reserved.cnt, 1);
- ASSERT_EQ(memblock.reserved.total_size, size);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate a memory region in a specific NUMA node that
- * does not have enough memory to allocate a region of the requested size:
- *
- * | +-----+ |
- * | | req | |
- * +---+-----+----------------------------+
- *
- * +---------+
- * | rgn |
- * +---------+
- *
- * Expect no allocation to happen.
- */
- static int alloc_exact_nid_numa_small_node_generic_check(void)
- {
- int nid_req = 1;
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- void *allocated_ptr = NULL;
- phys_addr_t size;
- phys_addr_t min_addr;
- phys_addr_t max_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- size = SZ_2 * req_node->size;
- min_addr = memblock_start_of_DRAM();
- max_addr = memblock_end_of_DRAM();
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_EQ(allocated_ptr, NULL);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate a memory region in a specific NUMA node that
- * is fully reserved:
- *
- * | +---------+ |
- * | |requested| |
- * +--------------+---------+-------------+
- *
- * | +---------+ |
- * | | reserved| |
- * +--------------+---------+-------------+
- *
- * Expect no allocation to happen.
- */
- static int alloc_exact_nid_numa_node_reserved_generic_check(void)
- {
- int nid_req = 2;
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- void *allocated_ptr = NULL;
- phys_addr_t size;
- phys_addr_t min_addr;
- phys_addr_t max_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- size = req_node->size;
- min_addr = memblock_start_of_DRAM();
- max_addr = memblock_end_of_DRAM();
- memblock_reserve(req_node->base, req_node->size);
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_EQ(allocated_ptr, NULL);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate a memory region in a specific NUMA node that
- * is partially reserved and does not have enough contiguous memory for the
- * allocated region:
- *
- * | +-----------------------+ |
- * | | requested | |
- * +-----------+-----------------------+----+
- *
- * | +----------+ |
- * | | reserved | |
- * +-----------------+----------+-----------+
- *
- * Expect no allocation to happen.
- */
- static int alloc_exact_nid_numa_part_reserved_fail_generic_check(void)
- {
- int nid_req = 4;
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- void *allocated_ptr = NULL;
- struct region r1;
- phys_addr_t size;
- phys_addr_t min_addr;
- phys_addr_t max_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- ASSERT_LE(SZ_4, req_node->size);
- size = req_node->size / SZ_2;
- r1.base = req_node->base + (size / SZ_2);
- r1.size = size;
- min_addr = memblock_start_of_DRAM();
- max_addr = memblock_end_of_DRAM();
- memblock_reserve(r1.base, r1.size);
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_EQ(allocated_ptr, NULL);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate a memory region that spans over the min_addr
- * and max_addr range and overlaps with two different nodes, where the second
- * node is the requested node:
- *
- * min_addr
- * | max_addr
- * | |
- * v v
- * | +--------------------------+---------+ |
- * | | first node |requested| |
- * +------+--------------------------+---------+----------------+
- *
- * Expect no allocation to happen.
- */
- static int alloc_exact_nid_numa_split_range_high_generic_check(void)
- {
- int nid_req = 3;
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- void *allocated_ptr = NULL;
- phys_addr_t size = SZ_512;
- phys_addr_t min_addr;
- phys_addr_t max_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- min_addr = req_node->base - SZ_256;
- max_addr = min_addr + size;
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_EQ(allocated_ptr, NULL);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate memory within min_addr and max_add range when
- * the requested node and the range do not overlap, and requested node starts
- * after max_addr. The range overlaps with multiple nodes along node
- * boundaries:
- *
- * min_addr
- * | max_addr
- * | |
- * v v
- * | +----------+----...----+----------+ +-----------+ |
- * | | min node | ... | max node | | requested | |
- * +-----+----------+----...----+----------+--------+-----------+---+
- *
- * Expect no allocation to happen.
- */
- static int alloc_exact_nid_numa_no_overlap_high_generic_check(void)
- {
- int nid_req = 7;
- struct memblock_region *min_node = &memblock.memory.regions[2];
- struct memblock_region *max_node = &memblock.memory.regions[5];
- void *allocated_ptr = NULL;
- phys_addr_t size = SZ_64;
- phys_addr_t max_addr;
- phys_addr_t min_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- min_addr = min_node->base;
- max_addr = region_end(max_node);
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_EQ(allocated_ptr, NULL);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate a memory region in a specific NUMA node that
- * does not have enough memory to allocate a region of the requested size.
- * Additionally, none of the nodes have enough memory to allocate the region:
- *
- * +-----------------------------------+
- * | new |
- * +-----------------------------------+
- * |-------+-------+-------+-------+-------+-------+-------+-------|
- * | node0 | node1 | node2 | node3 | node4 | node5 | node6 | node7 |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- *
- * Expect no allocation to happen.
- */
- static int alloc_exact_nid_numa_large_region_generic_check(void)
- {
- int nid_req = 3;
- void *allocated_ptr = NULL;
- phys_addr_t size = MEM_SIZE / SZ_2;
- phys_addr_t min_addr;
- phys_addr_t max_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- min_addr = memblock_start_of_DRAM();
- max_addr = memblock_end_of_DRAM();
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_EQ(allocated_ptr, NULL);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate memory within min_addr and max_addr range when
- * there are two reserved regions at the borders. The requested node starts at
- * min_addr and ends at max_addr and is the same size as the region to be
- * allocated:
- *
- * min_addr
- * | max_addr
- * | |
- * v v
- * | +-----------+-----------------------+-----------------------|
- * | | node5 | requested | node7 |
- * +------+-----------+-----------------------+-----------------------+
- * + +
- * | +----+-----------------------+----+ |
- * | | r2 | new | r1 | |
- * +-------------+----+-----------------------+----+------------------+
- *
- * Expect to merge all of the regions into one. The region counter and total
- * size fields get updated.
- */
- static int alloc_exact_nid_numa_reserved_full_merge_generic_check(void)
- {
- int nid_req = 6;
- int nid_next = nid_req + 1;
- struct memblock_region *new_rgn = &memblock.reserved.regions[0];
- struct memblock_region *req_node = &memblock.memory.regions[nid_req];
- struct memblock_region *next_node = &memblock.memory.regions[nid_next];
- void *allocated_ptr = NULL;
- struct region r1, r2;
- phys_addr_t size = req_node->size;
- phys_addr_t total_size;
- phys_addr_t max_addr;
- phys_addr_t min_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- r1.base = next_node->base;
- r1.size = SZ_128;
- r2.size = SZ_128;
- r2.base = r1.base - (size + r2.size);
- total_size = r1.size + r2.size + size;
- min_addr = r2.base + r2.size;
- max_addr = r1.base;
- memblock_reserve(r1.base, r1.size);
- memblock_reserve(r2.base, r2.size);
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- nid_req);
- ASSERT_NE(allocated_ptr, NULL);
- ASSERT_MEM_NE(allocated_ptr, 0, size);
- ASSERT_EQ(new_rgn->size, total_size);
- ASSERT_EQ(new_rgn->base, r2.base);
- ASSERT_LE(new_rgn->base, req_node->base);
- ASSERT_LE(region_end(req_node), region_end(new_rgn));
- ASSERT_EQ(memblock.reserved.cnt, 1);
- ASSERT_EQ(memblock.reserved.total_size, total_size);
- test_pass_pop();
- return 0;
- }
- /*
- * A test that tries to allocate memory within min_addr and max_add range,
- * where the total range can fit the region, but it is split between two nodes
- * and everything else is reserved. Additionally, nid is set to NUMA_NO_NODE
- * instead of requesting a specific node:
- *
- * +-----------+
- * | new |
- * +-----------+
- * | +---------------------+-----------|
- * | | prev node | next node |
- * +------+---------------------+-----------+
- * + +
- * |----------------------+ +-----|
- * | r1 | | r2 |
- * +----------------------+-----------+-----+
- * ^ ^
- * | |
- * | max_addr
- * |
- * min_addr
- *
- * Expect no allocation to happen.
- */
- static int alloc_exact_nid_numa_split_all_reserved_generic_check(void)
- {
- void *allocated_ptr = NULL;
- struct memblock_region *next_node = &memblock.memory.regions[7];
- struct region r1, r2;
- phys_addr_t size = SZ_256;
- phys_addr_t max_addr;
- phys_addr_t min_addr;
- PREFIX_PUSH();
- setup_numa_memblock(node_fractions);
- r2.base = next_node->base + SZ_128;
- r2.size = memblock_end_of_DRAM() - r2.base;
- r1.size = MEM_SIZE - (r2.size + size);
- r1.base = memblock_start_of_DRAM();
- min_addr = r1.base + r1.size;
- max_addr = r2.base;
- memblock_reserve(r1.base, r1.size);
- memblock_reserve(r2.base, r2.size);
- allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
- min_addr, max_addr,
- NUMA_NO_NODE);
- ASSERT_EQ(allocated_ptr, NULL);
- test_pass_pop();
- return 0;
- }
- /* Test case wrappers for NUMA tests */
- static int alloc_exact_nid_numa_simple_check(void)
- {
- test_print("\tRunning %s...\n", __func__);
- memblock_set_bottom_up(false);
- alloc_exact_nid_top_down_numa_simple_check();
- memblock_set_bottom_up(true);
- alloc_exact_nid_bottom_up_numa_simple_check();
- return 0;
- }
- static int alloc_exact_nid_numa_part_reserved_check(void)
- {
- test_print("\tRunning %s...\n", __func__);
- memblock_set_bottom_up(false);
- alloc_exact_nid_top_down_numa_part_reserved_check();
- memblock_set_bottom_up(true);
- alloc_exact_nid_bottom_up_numa_part_reserved_check();
- return 0;
- }
- static int alloc_exact_nid_numa_split_range_low_check(void)
- {
- test_print("\tRunning %s...\n", __func__);
- memblock_set_bottom_up(false);
- alloc_exact_nid_top_down_numa_split_range_low_check();
- memblock_set_bottom_up(true);
- alloc_exact_nid_bottom_up_numa_split_range_low_check();
- return 0;
- }
- static int alloc_exact_nid_numa_no_overlap_split_check(void)
- {
- test_print("\tRunning %s...\n", __func__);
- memblock_set_bottom_up(false);
- alloc_exact_nid_top_down_numa_no_overlap_split_check();
- memblock_set_bottom_up(true);
- alloc_exact_nid_bottom_up_numa_no_overlap_split_check();
- return 0;
- }
- static int alloc_exact_nid_numa_no_overlap_low_check(void)
- {
- test_print("\tRunning %s...\n", __func__);
- memblock_set_bottom_up(false);
- alloc_exact_nid_top_down_numa_no_overlap_low_check();
- memblock_set_bottom_up(true);
- alloc_exact_nid_bottom_up_numa_no_overlap_low_check();
- return 0;
- }
- static int alloc_exact_nid_numa_small_node_check(void)
- {
- test_print("\tRunning %s...\n", __func__);
- run_top_down(alloc_exact_nid_numa_small_node_generic_check);
- run_bottom_up(alloc_exact_nid_numa_small_node_generic_check);
- return 0;
- }
- static int alloc_exact_nid_numa_node_reserved_check(void)
- {
- test_print("\tRunning %s...\n", __func__);
- run_top_down(alloc_exact_nid_numa_node_reserved_generic_check);
- run_bottom_up(alloc_exact_nid_numa_node_reserved_generic_check);
- return 0;
- }
- static int alloc_exact_nid_numa_part_reserved_fail_check(void)
- {
- test_print("\tRunning %s...\n", __func__);
- run_top_down(alloc_exact_nid_numa_part_reserved_fail_generic_check);
- run_bottom_up(alloc_exact_nid_numa_part_reserved_fail_generic_check);
- return 0;
- }
- static int alloc_exact_nid_numa_split_range_high_check(void)
- {
- test_print("\tRunning %s...\n", __func__);
- run_top_down(alloc_exact_nid_numa_split_range_high_generic_check);
- run_bottom_up(alloc_exact_nid_numa_split_range_high_generic_check);
- return 0;
- }
- static int alloc_exact_nid_numa_no_overlap_high_check(void)
- {
- test_print("\tRunning %s...\n", __func__);
- run_top_down(alloc_exact_nid_numa_no_overlap_high_generic_check);
- run_bottom_up(alloc_exact_nid_numa_no_overlap_high_generic_check);
- return 0;
- }
- static int alloc_exact_nid_numa_large_region_check(void)
- {
- test_print("\tRunning %s...\n", __func__);
- run_top_down(alloc_exact_nid_numa_large_region_generic_check);
- run_bottom_up(alloc_exact_nid_numa_large_region_generic_check);
- return 0;
- }
- static int alloc_exact_nid_numa_reserved_full_merge_check(void)
- {
- test_print("\tRunning %s...\n", __func__);
- run_top_down(alloc_exact_nid_numa_reserved_full_merge_generic_check);
- run_bottom_up(alloc_exact_nid_numa_reserved_full_merge_generic_check);
- return 0;
- }
- static int alloc_exact_nid_numa_split_all_reserved_check(void)
- {
- test_print("\tRunning %s...\n", __func__);
- run_top_down(alloc_exact_nid_numa_split_all_reserved_generic_check);
- run_bottom_up(alloc_exact_nid_numa_split_all_reserved_generic_check);
- return 0;
- }
- int __memblock_alloc_exact_nid_numa_checks(void)
- {
- test_print("Running %s NUMA tests...\n", FUNC_NAME);
- alloc_exact_nid_numa_simple_check();
- alloc_exact_nid_numa_part_reserved_check();
- alloc_exact_nid_numa_split_range_low_check();
- alloc_exact_nid_numa_no_overlap_split_check();
- alloc_exact_nid_numa_no_overlap_low_check();
- alloc_exact_nid_numa_small_node_check();
- alloc_exact_nid_numa_node_reserved_check();
- alloc_exact_nid_numa_part_reserved_fail_check();
- alloc_exact_nid_numa_split_range_high_check();
- alloc_exact_nid_numa_no_overlap_high_check();
- alloc_exact_nid_numa_large_region_check();
- alloc_exact_nid_numa_reserved_full_merge_check();
- alloc_exact_nid_numa_split_all_reserved_check();
- return 0;
- }
- int memblock_alloc_exact_nid_checks(void)
- {
- prefix_reset();
- prefix_push(FUNC_NAME);
- reset_memblock_attributes();
- dummy_physical_memory_init();
- memblock_alloc_exact_nid_range_checks();
- memblock_alloc_exact_nid_numa_checks();
- dummy_physical_memory_cleanup();
- prefix_pop();
- return 0;
- }
|