// SPDX-License-Identifier: GPL-2.0-or-later#include <string.h>#include <linux/memblock.h>#include "basic_api.h" #define EXPECTED_MEMBLOCK_REGIONS 128#define FUNC_ADD "memblock_add"#define FUNC_RESERVE "memblock_reserve"#define FUNC_REMOVE "memblock_remove"#define FUNC_FREE "memblock_free" static int memblock_initialization_check(void){ PREFIX_PUSH(); ASSERT_NE(memblock.memory.regions, NULL); ASSERT_EQ(memblock.memory.cnt, 1); ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS); ASSERT_EQ(strcmp(memblock.memory.name, "memory"), 0); ASSERT_NE(memblock.reserved.regions, NULL); ASSERT_EQ(memblock.reserved.cnt, 1); ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS); ASSERT_EQ(strcmp(memblock.reserved.name, "reserved"), 0); ASSERT_EQ(memblock.bottom_up, false); ASSERT_EQ(memblock.current_limit, MEMBLOCK_ALLOC_ANYWHERE); test_pass_pop(); return 0;} /* * A simple test that adds a memory block of a specified base address * and size to the collection of available memory regions (memblock.memory). * Expect to create a new entry. The region counter and total memory get * updated. */static int memblock_add_simple_check(void){ struct memblock_region *rgn; rgn = &memblock.memory.regions[0]; struct region r = { .base = SZ_1G, .size = SZ_4M }; PREFIX_PUSH(); reset_memblock_regions(); memblock_add(r.base, r.size); ASSERT_EQ(rgn->base, r.base); ASSERT_EQ(rgn->size, r.size); ASSERT_EQ(memblock.memory.cnt, 1); ASSERT_EQ(memblock.memory.total_size, r.size); test_pass_pop(); return 0;} /* * A simple test that adds a memory block of a specified base address, size, * NUMA node and memory flags to the collection of available memory regions. * Expect to create a new entry. The region counter and total memory get * updated. */static int memblock_add_node_simple_check(void){ struct memblock_region *rgn; rgn = &memblock.memory.regions[0]; struct region r = { .base = SZ_1M, .size = SZ_16M }; PREFIX_PUSH(); reset_memblock_regions(); memblock_add_node(r.base, r.size, 1, MEMBLOCK_HOTPLUG); ASSERT_EQ(rgn->base, r.base); ASSERT_EQ(rgn->size, r.size);#ifdef CONFIG_NUMA ASSERT_EQ(rgn->nid, 1);#endif ASSERT_EQ(rgn->flags, MEMBLOCK_HOTPLUG); ASSERT_EQ(memblock.memory.cnt, 1); ASSERT_EQ(memblock.memory.total_size, r.size); test_pass_pop(); return 0;} /* * A test that tries to add two memory blocks that don't overlap with one * another: * * | +--------+ +--------+ | * | | r1 | | r2 | | * +--------+--------+--------+--------+--+ * * Expect to add two correctly initialized entries to the collection of * available memory regions (memblock.memory). The total size and * region counter fields get updated. */static int memblock_add_disjoint_check(void){ struct memblock_region *rgn1, *rgn2; rgn1 = &memblock.memory.regions[0]; rgn2 = &memblock.memory.regions[1]; struct region r1 = { .base = SZ_1G, .size = SZ_8K }; struct region r2 = { .base = SZ_1G + SZ_16K, .size = SZ_8K }; PREFIX_PUSH(); reset_memblock_regions(); memblock_add(r1.base, r1.size); memblock_add(r2.base, r2.size); ASSERT_EQ(rgn1->base, r1.base); ASSERT_EQ(rgn1->size, r1.size); ASSERT_EQ(rgn2->base, r2.base); ASSERT_EQ(rgn2->size, r2.size); ASSERT_EQ(memblock.memory.cnt, 2); ASSERT_EQ(memblock.memory.total_size, r1.size + r2.size); test_pass_pop(); return 0;} /* * A test that tries to add two memory blocks r1 and r2, where r2 overlaps * with the beginning of r1 (that is r1.base < r2.base + r2.size): * * | +----+----+------------+ | * | | |r2 | r1 | | * +----+----+----+------------+----------+ * ^ ^ * | | * | r1.base * | * r2.base * * Expect to merge the two entries into one region that starts at r2.base * and has size of two regions minus their intersection. The total size of * the available memory is updated, and the region counter stays the same. */static int memblock_add_overlap_top_check(void){ struct memblock_region *rgn; phys_addr_t total_size; rgn = &memblock.memory.regions[0]; struct region r1 = { .base = SZ_512M, .size = SZ_1G }; struct region r2 = { .base = SZ_256M, .size = SZ_512M }; PREFIX_PUSH(); total_size = (r1.base - r2.base) + r1.size; reset_memblock_regions(); memblock_add(r1.base, r1.size); memblock_add(r2.base, r2.size); ASSERT_EQ(rgn->base, r2.base); ASSERT_EQ(rgn->size, total_size); ASSERT_EQ(memblock.memory.cnt, 1); ASSERT_EQ(memblock.memory.total_size, total_size); test_pass_pop(); return 0;} /* * A test that tries to add two memory blocks r1 and r2, where r2 overlaps * with the end of r1 (that is r2.base < r1.base + r1.size): * * | +--+------+----------+ | * | | | r1 | r2 | | * +--+--+------+----------+--------------+ * ^ ^ * | | * | r2.base * | * r1.base * * Expect to merge the two entries into one region that starts at r1.base * and has size of two regions minus their intersection. The total size of * the available memory is updated, and the region counter stays the same. */static int memblock_add_overlap_bottom_check(void){ struct memblock_region *rgn; phys_addr_t total_size; rgn = &memblock.memory.regions[0]; struct region r1 = { .base = SZ_128M, .size = SZ_512M }; struct region r2 = { .base = SZ_256M, .size = SZ_1G }; PREFIX_PUSH(); total_size = (r2.base - r1.base) + r2.size; reset_memblock_regions(); memblock_add(r1.base, r1.size); memblock_add(r2.base, r2.size); ASSERT_EQ(rgn->base, r1.base); ASSERT_EQ(rgn->size, total_size); ASSERT_EQ(memblock.memory.cnt, 1); ASSERT_EQ(memblock.memory.total_size, total_size); test_pass_pop(); return 0;} /* * A test that tries to add two memory blocks r1 and r2, where r2 is * within the range of r1 (that is r1.base < r2.base && * r2.base + r2.size < r1.base + r1.size): * * | +-------+--+-----------------------+ * | | |r2| r1 | * +---+-------+--+-----------------------+ * ^ * | * r1.base * * Expect to merge two entries into one region that stays the same. * The counter and total size of available memory are not updated. */static int memblock_add_within_check(void){ struct memblock_region *rgn; rgn = &memblock.memory.regions[0]; struct region r1 = { .base = SZ_8M, .size = SZ_32M }; struct region r2 = { .base = SZ_16M, .size = SZ_1M }; PREFIX_PUSH(); reset_memblock_regions(); memblock_add(r1.base, r1.size); memblock_add(r2.base, r2.size); ASSERT_EQ(rgn->base, r1.base); ASSERT_EQ(rgn->size, r1.size); ASSERT_EQ(memblock.memory.cnt, 1); ASSERT_EQ(memblock.memory.total_size, r1.size); test_pass_pop(); return 0;} /* * A simple test that tries to add the same memory block twice. Expect * the counter and total size of available memory to not be updated. */static int memblock_add_twice_check(void){ struct region r = { .base = SZ_16K, .size = SZ_2M }; PREFIX_PUSH(); reset_memblock_regions(); memblock_add(r.base, r.size); memblock_add(r.base, r.size); ASSERT_EQ(memblock.memory.cnt, 1); ASSERT_EQ(memblock.memory.total_size, r.size); test_pass_pop(); return 0;} static int memblock_add_checks(void){ prefix_reset(); prefix_push(FUNC_ADD); test_print("Running %s tests...\n", FUNC_ADD); memblock_add_simple_check(); memblock_add_node_simple_check(); memblock_add_disjoint_check(); memblock_add_overlap_top_check(); memblock_add_overlap_bottom_check(); memblock_add_within_check(); memblock_add_twice_check(); prefix_pop(); return 0;} /* * A simple test that marks a memory block of a specified base address * and size as reserved and to the collection of reserved memory regions * (memblock.reserved). Expect to create a new entry. The region counter * and total memory size are updated. */static int memblock_reserve_simple_check(void){ struct memblock_region *rgn; rgn = &memblock.reserved.regions[0]; struct region r = { .base = SZ_2G, .size = SZ_128M }; PREFIX_PUSH(); reset_memblock_regions(); memblock_reserve(r.base, r.size); ASSERT_EQ(rgn->base, r.base); ASSERT_EQ(rgn->size, r.size); test_pass_pop(); return 0;} /* * A test that tries to mark two memory blocks that don't overlap as reserved: * * | +--+ +----------------+ | * | |r1| | r2 | | * +--------+--+------+----------------+--+ * * Expect to add two entries to the collection of reserved memory regions * (memblock.reserved). The total size and region counter for * memblock.reserved are updated. */static int memblock_reserve_disjoint_check(void){ struct memblock_region *rgn1, *rgn2; rgn1 = &memblock.reserved.regions[0]; rgn2 = &memblock.reserved.regions[1]; struct region r1 = { .base = SZ_256M, .size = SZ_16M }; struct region r2 = { .base = SZ_512M, .size = SZ_512M }; PREFIX_PUSH(); reset_memblock_regions(); memblock_reserve(r1.base, r1.size); memblock_reserve(r2.base, r2.size); ASSERT_EQ(rgn1->base, r1.base); ASSERT_EQ(rgn1->size, r1.size); ASSERT_EQ(rgn2->base, r2.base); ASSERT_EQ(rgn2->size, r2.size); ASSERT_EQ(memblock.reserved.cnt, 2); ASSERT_EQ(memblock.reserved.total_size, r1.size + r2.size); test_pass_pop(); return 0;} /* * A test that tries to mark two memory blocks r1 and r2 as reserved, * where r2 overlaps with the beginning of r1 (that is * r1.base < r2.base + r2.size): * * | +--------------+--+--------------+ | * | | r2 | | r1 | | * +--+--------------+--+--------------+--+ * ^ ^ * | | * | r1.base * | * r2.base * * Expect to merge two entries into one region that starts at r2.base and * has size of two regions minus their intersection. The total size of the * reserved memory is updated, and the region counter is not updated. */static int memblock_reserve_overlap_top_check(void){ struct memblock_region *rgn; phys_addr_t total_size; rgn = &memblock.reserved.regions[0]; struct region r1 = { .base = SZ_1G, .size = SZ_1G }; struct region r2 = { .base = SZ_128M, .size = SZ_1G }; PREFIX_PUSH(); total_size = (r1.base - r2.base) + r1.size; reset_memblock_regions(); memblock_reserve(r1.base, r1.size); memblock_reserve(r2.base, r2.size); ASSERT_EQ(rgn->base, r2.base); ASSERT_EQ(rgn->size, total_size); ASSERT_EQ(memblock.reserved.cnt, 1); ASSERT_EQ(memblock.reserved.total_size, total_size); test_pass_pop(); return 0;} /* * A test that tries to mark two memory blocks r1 and r2 as reserved, * where r2 overlaps with the end of r1 (that is * r2.base < r1.base + r1.size): * * | +--------------+--+--------------+ | * | | r1 | | r2 | | * +--+--------------+--+--------------+--+ * ^ ^ * | | * | r2.base * | * r1.base * * Expect to merge two entries into one region that starts at r1.base and * has size of two regions minus their intersection. The total size of the * reserved memory is updated, and the region counter is not updated. */static int memblock_reserve_overlap_bottom_check(void){ struct memblock_region *rgn; phys_addr_t total_size; Lines 1–500 of 1192. Load more
// SPDX-License-Identifier: GPL-2.0-or-later #include <string.h> #include <linux/memblock.h> #include "basic_api.h" #define EXPECTED_MEMBLOCK_REGIONS 128 #define FUNC_ADD "memblock_add" #define FUNC_RESERVE "memblock_reserve" #define FUNC_REMOVE "memblock_remove" #define FUNC_FREE "memblock_free" static int memblock_initialization_check(void) { PREFIX_PUSH(); ASSERT_NE(memblock.memory.regions, NULL); ASSERT_EQ(memblock.memory.cnt, 1); ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS); ASSERT_EQ(strcmp(memblock.memory.name, "memory"), 0); ASSERT_NE(memblock.reserved.regions, NULL); ASSERT_EQ(memblock.reserved.cnt, 1); ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS); ASSERT_EQ(strcmp(memblock.reserved.name, "reserved"), 0); ASSERT_EQ(memblock.bottom_up, false); ASSERT_EQ(memblock.current_limit, MEMBLOCK_ALLOC_ANYWHERE); test_pass_pop(); return 0; } /* * A simple test that adds a memory block of a specified base address * and size to the collection of available memory regions (memblock.memory). * Expect to create a new entry. The region counter and total memory get * updated. */ static int memblock_add_simple_check(void) { struct memblock_region *rgn; rgn = &memblock.memory.regions[0]; struct region r = { .base = SZ_1G, .size = SZ_4M }; PREFIX_PUSH(); reset_memblock_regions(); memblock_add(r.base, r.size); ASSERT_EQ(rgn->base, r.base); ASSERT_EQ(rgn->size, r.size); ASSERT_EQ(memblock.memory.cnt, 1); ASSERT_EQ(memblock.memory.total_size, r.size); test_pass_pop(); return 0; } /* * A simple test that adds a memory block of a specified base address, size, * NUMA node and memory flags to the collection of available memory regions. * Expect to create a new entry. The region counter and total memory get * updated. */ static int memblock_add_node_simple_check(void) { struct memblock_region *rgn; rgn = &memblock.memory.regions[0]; struct region r = { .base = SZ_1M, .size = SZ_16M }; PREFIX_PUSH(); reset_memblock_regions(); memblock_add_node(r.base, r.size, 1, MEMBLOCK_HOTPLUG); ASSERT_EQ(rgn->base, r.base); ASSERT_EQ(rgn->size, r.size); #ifdef CONFIG_NUMA ASSERT_EQ(rgn->nid, 1); #endif ASSERT_EQ(rgn->flags, MEMBLOCK_HOTPLUG); ASSERT_EQ(memblock.memory.cnt, 1); ASSERT_EQ(memblock.memory.total_size, r.size); test_pass_pop(); return 0; } /* * A test that tries to add two memory blocks that don't overlap with one * another: * * | +--------+ +--------+ | * | | r1 | | r2 | | * +--------+--------+--------+--------+--+ * * Expect to add two correctly initialized entries to the collection of * available memory regions (memblock.memory). The total size and * region counter fields get updated. */ static int memblock_add_disjoint_check(void) { struct memblock_region *rgn1, *rgn2; rgn1 = &memblock.memory.regions[0]; rgn2 = &memblock.memory.regions[1]; struct region r1 = { .base = SZ_1G, .size = SZ_8K }; struct region r2 = { .base = SZ_1G + SZ_16K, .size = SZ_8K }; PREFIX_PUSH(); reset_memblock_regions(); memblock_add(r1.base, r1.size); memblock_add(r2.base, r2.size); ASSERT_EQ(rgn1->base, r1.base); ASSERT_EQ(rgn1->size, r1.size); ASSERT_EQ(rgn2->base, r2.base); ASSERT_EQ(rgn2->size, r2.size); ASSERT_EQ(memblock.memory.cnt, 2); ASSERT_EQ(memblock.memory.total_size, r1.size + r2.size); test_pass_pop(); return 0; } /* * A test that tries to add two memory blocks r1 and r2, where r2 overlaps * with the beginning of r1 (that is r1.base < r2.base + r2.size): * * | +----+----+------------+ | * | | |r2 | r1 | | * +----+----+----+------------+----------+ * ^ ^ * | | * | r1.base * | * r2.base * * Expect to merge the two entries into one region that starts at r2.base * and has size of two regions minus their intersection. The total size of * the available memory is updated, and the region counter stays the same. */ static int memblock_add_overlap_top_check(void) { struct memblock_region *rgn; phys_addr_t total_size; rgn = &memblock.memory.regions[0]; struct region r1 = { .base = SZ_512M, .size = SZ_1G }; struct region r2 = { .base = SZ_256M, .size = SZ_512M }; PREFIX_PUSH(); total_size = (r1.base - r2.base) + r1.size; reset_memblock_regions(); memblock_add(r1.base, r1.size); memblock_add(r2.base, r2.size); ASSERT_EQ(rgn->base, r2.base); ASSERT_EQ(rgn->size, total_size); ASSERT_EQ(memblock.memory.cnt, 1); ASSERT_EQ(memblock.memory.total_size, total_size); test_pass_pop(); return 0; } /* * A test that tries to add two memory blocks r1 and r2, where r2 overlaps * with the end of r1 (that is r2.base < r1.base + r1.size): * * | +--+------+----------+ | * | | | r1 | r2 | | * +--+--+------+----------+--------------+ * ^ ^ * | | * | r2.base * | * r1.base * * Expect to merge the two entries into one region that starts at r1.base * and has size of two regions minus their intersection. The total size of * the available memory is updated, and the region counter stays the same. */ static int memblock_add_overlap_bottom_check(void) { struct memblock_region *rgn; phys_addr_t total_size; rgn = &memblock.memory.regions[0]; struct region r1 = { .base = SZ_128M, .size = SZ_512M }; struct region r2 = { .base = SZ_256M, .size = SZ_1G }; PREFIX_PUSH(); total_size = (r2.base - r1.base) + r2.size; reset_memblock_regions(); memblock_add(r1.base, r1.size); memblock_add(r2.base, r2.size); ASSERT_EQ(rgn->base, r1.base); ASSERT_EQ(rgn->size, total_size); ASSERT_EQ(memblock.memory.cnt, 1); ASSERT_EQ(memblock.memory.total_size, total_size); test_pass_pop(); return 0; } /* * A test that tries to add two memory blocks r1 and r2, where r2 is * within the range of r1 (that is r1.base < r2.base && * r2.base + r2.size < r1.base + r1.size): * * | +-------+--+-----------------------+ * | | |r2| r1 | * +---+-------+--+-----------------------+ * ^ * | * r1.base * * Expect to merge two entries into one region that stays the same. * The counter and total size of available memory are not updated. */ static int memblock_add_within_check(void) { struct memblock_region *rgn; rgn = &memblock.memory.regions[0]; struct region r1 = { .base = SZ_8M, .size = SZ_32M }; struct region r2 = { .base = SZ_16M, .size = SZ_1M }; PREFIX_PUSH(); reset_memblock_regions(); memblock_add(r1.base, r1.size); memblock_add(r2.base, r2.size); ASSERT_EQ(rgn->base, r1.base); ASSERT_EQ(rgn->size, r1.size); ASSERT_EQ(memblock.memory.cnt, 1); ASSERT_EQ(memblock.memory.total_size, r1.size); test_pass_pop(); return 0; } /* * A simple test that tries to add the same memory block twice. Expect * the counter and total size of available memory to not be updated. */ static int memblock_add_twice_check(void) { struct region r = { .base = SZ_16K, .size = SZ_2M }; PREFIX_PUSH(); reset_memblock_regions(); memblock_add(r.base, r.size); memblock_add(r.base, r.size); ASSERT_EQ(memblock.memory.cnt, 1); ASSERT_EQ(memblock.memory.total_size, r.size); test_pass_pop(); return 0; } static int memblock_add_checks(void) { prefix_reset(); prefix_push(FUNC_ADD); test_print("Running %s tests...\n", FUNC_ADD); memblock_add_simple_check(); memblock_add_node_simple_check(); memblock_add_disjoint_check(); memblock_add_overlap_top_check(); memblock_add_overlap_bottom_check(); memblock_add_within_check(); memblock_add_twice_check(); prefix_pop(); return 0; } /* * A simple test that marks a memory block of a specified base address * and size as reserved and to the collection of reserved memory regions * (memblock.reserved). Expect to create a new entry. The region counter * and total memory size are updated. */ static int memblock_reserve_simple_check(void) { struct memblock_region *rgn; rgn = &memblock.reserved.regions[0]; struct region r = { .base = SZ_2G, .size = SZ_128M }; PREFIX_PUSH(); reset_memblock_regions(); memblock_reserve(r.base, r.size); ASSERT_EQ(rgn->base, r.base); ASSERT_EQ(rgn->size, r.size); test_pass_pop(); return 0; } /* * A test that tries to mark two memory blocks that don't overlap as reserved: * * | +--+ +----------------+ | * | |r1| | r2 | | * +--------+--+------+----------------+--+ * * Expect to add two entries to the collection of reserved memory regions * (memblock.reserved). The total size and region counter for * memblock.reserved are updated. */ static int memblock_reserve_disjoint_check(void) { struct memblock_region *rgn1, *rgn2; rgn1 = &memblock.reserved.regions[0]; rgn2 = &memblock.reserved.regions[1]; struct region r1 = { .base = SZ_256M, .size = SZ_16M }; struct region r2 = { .base = SZ_512M, .size = SZ_512M }; PREFIX_PUSH(); reset_memblock_regions(); memblock_reserve(r1.base, r1.size); memblock_reserve(r2.base, r2.size); ASSERT_EQ(rgn1->base, r1.base); ASSERT_EQ(rgn1->size, r1.size); ASSERT_EQ(rgn2->base, r2.base); ASSERT_EQ(rgn2->size, r2.size); ASSERT_EQ(memblock.reserved.cnt, 2); ASSERT_EQ(memblock.reserved.total_size, r1.size + r2.size); test_pass_pop(); return 0; } /* * A test that tries to mark two memory blocks r1 and r2 as reserved, * where r2 overlaps with the beginning of r1 (that is * r1.base < r2.base + r2.size): * * | +--------------+--+--------------+ | * | | r2 | | r1 | | * +--+--------------+--+--------------+--+ * ^ ^ * | | * | r1.base * | * r2.base * * Expect to merge two entries into one region that starts at r2.base and * has size of two regions minus their intersection. The total size of the * reserved memory is updated, and the region counter is not updated. */ static int memblock_reserve_overlap_top_check(void) { struct memblock_region *rgn; phys_addr_t total_size; rgn = &memblock.reserved.regions[0]; struct region r1 = { .base = SZ_1G, .size = SZ_1G }; struct region r2 = { .base = SZ_128M, .size = SZ_1G }; PREFIX_PUSH(); total_size = (r1.base - r2.base) + r1.size; reset_memblock_regions(); memblock_reserve(r1.base, r1.size); memblock_reserve(r2.base, r2.size); ASSERT_EQ(rgn->base, r2.base); ASSERT_EQ(rgn->size, total_size); ASSERT_EQ(memblock.reserved.cnt, 1); ASSERT_EQ(memblock.reserved.total_size, total_size); test_pass_pop(); return 0; } /* * A test that tries to mark two memory blocks r1 and r2 as reserved, * where r2 overlaps with the end of r1 (that is * r2.base < r1.base + r1.size): * * | +--------------+--+--------------+ | * | | r1 | | r2 | | * +--+--------------+--+--------------+--+ * ^ ^ * | | * | r2.base * | * r1.base * * Expect to merge two entries into one region that starts at r1.base and * has size of two regions minus their intersection. The total size of the * reserved memory is updated, and the region counter is not updated. */ static int memblock_reserve_overlap_bottom_check(void) { struct memblock_region *rgn; phys_addr_t total_size;