mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
memblock: updates for 7.4-rc1
Performance improvement:
* Use binary search in memblock_add_range() and memblock_isolate_range()
Cleanups:
* Several simplifications in memblock and mm_init that remvove redundand
code.
* After rework of sparsemem buffer preallocation, memmap_alloc() does not
require exact_nid parameter. Remove that parameter, drop now unused
memblock_alloc_exact_nid_raw() and ajust memblock tests accordingly.
memblock test updates:
* add coverage for lowmem allocations
* fix 32-bit build warinings
-----BEGIN PGP SIGNATURE-----
iQEzBAABCgAdFiEEeOVYVaWZL5900a/pOQOGJssO/ZEFAmrcgaQACgkQOQOGJssO
/ZHVcAf9HoX58N9mA76ESc5Aogkg1PKdTFweeR4nXLTTz10amxvH0O1aERyZE8nO
4lbqa7fUPV/0gPBtFVu7ZcBbgGZR0nmb5atKJWfKoZ373cXqdqVhN0brULLTyRPr
18dlOSX7CmU84m8WiKpVeSZX94xwF5YeCad577y2nmEyWyQ1aZ1iqjzV97cDTcg3
bAzWUEsLdiO2OYoyiasMQIJdk+xeFTtT61so8c3/W1gcUTZHwW1jh0gQ+hKj2E8G
GXfkafy+nUtuvzKP7iOqc8uUIW/j3dLlO3tVp+KFjcHVP+0TLWQzB80oAmvgxuxK
AZ7+xsxhwIxXiS9by2o5huV/oPhU3Q==
=A8E9
-----END PGP SIGNATURE-----
Merge tag 'memblock-v7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mm/memblock
Pull memblock updates from Mike Rapoport:
"Performance improvement:
- Use binary search in memblock_add_range() and
memblock_isolate_range()
Cleanups:
- Several simplifications in memblock and mm_init that remove
redundant code
- After rework of sparsemem buffer preallocation, memmap_alloc() does
not require exact_nid parameter. Remove that parameter, drop now
unused memblock_alloc_exact_nid_raw() and adjust memblock tests
accordingly
memblock test updates:
- add coverage for lowmem allocations
- fix 32-bit build warnings"
* tag 'memblock-v7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mm/memblock:
memblock: use binary search to locate candidate regions
memblock: drop for_each_memblock_type() and open code its users
memblock: Remove unused memblock_alloc_exact_nid_raw()
memblock tests: Move exact nid tests to memblock_alloc_range_nid()
mm: Remove unused exact_nid parameter from memmap_alloc()
memblock: initialize the region merge end index
tools: use __pa() in virt_to_phys()
memblock tests: zero-extend simulated memory addresses
memblock tests: use physical addresses for region removal
memblock: reject non-page-aligned reserve_mem regions
memblock tests: cover allocations below the low address limit
memblock tests: model the low allocation limit within dummy memory
mm/mm_init: remove zone_absent_pages_in_node()
memblock: remove conditional return with no effect
memblock: simplify reset_all_zones_managed_pages()
This commit is contained in:
commit
394023fbe3
|
|
@ -6611,6 +6611,9 @@ Kernel parameters
|
|||
|
||||
reserve_mem=12M:4096:oops ramoops.mem_name=oops
|
||||
|
||||
Both the size and the alignment must be multiples of
|
||||
the page size.
|
||||
|
||||
reservetop= [X86-32,EARLY]
|
||||
Format: nn[KMG]
|
||||
Reserves a hole at the top of the kernel virtual
|
||||
|
|
|
|||
|
|
@ -162,7 +162,6 @@ int memblock_mark_kho_scratch(phys_addr_t base, phys_addr_t size);
|
|||
int memblock_clear_kho_scratch(phys_addr_t base, phys_addr_t size);
|
||||
|
||||
void memblock_free(void *ptr, size_t size);
|
||||
void reset_all_zones_managed_pages(void);
|
||||
|
||||
/* Low level functions */
|
||||
void __next_mem_range(u64 *idx, int nid, enum memblock_flags flags,
|
||||
|
|
@ -413,9 +412,6 @@ static __always_inline phys_addr_t memblock_phys_alloc(phys_addr_t size,
|
|||
MEMBLOCK_ALLOC_ACCESSIBLE);
|
||||
}
|
||||
|
||||
void *memblock_alloc_exact_nid_raw(phys_addr_t size, phys_addr_t align,
|
||||
phys_addr_t min_addr, phys_addr_t max_addr,
|
||||
int nid);
|
||||
void *memblock_alloc_try_nid_raw(phys_addr_t size, phys_addr_t align,
|
||||
phys_addr_t min_addr, phys_addr_t max_addr,
|
||||
int nid);
|
||||
|
|
|
|||
127
mm/memblock.c
127
mm/memblock.c
|
|
@ -155,11 +155,6 @@ struct memblock_type physmem = {
|
|||
*/
|
||||
static __refdata struct memblock_type *memblock_memory = &memblock.memory;
|
||||
|
||||
#define for_each_memblock_type(i, memblock_type, rgn) \
|
||||
for (i = 0, rgn = &memblock_type->regions[0]; \
|
||||
i < memblock_type->cnt; \
|
||||
i++, rgn = &memblock_type->regions[i])
|
||||
|
||||
#define memblock_dbg(fmt, ...) \
|
||||
do { \
|
||||
if (memblock_debug) \
|
||||
|
|
@ -591,6 +586,29 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type,
|
|||
type->total_size += size;
|
||||
}
|
||||
|
||||
/**
|
||||
* __memblock_search - Find the first region index where rend > base
|
||||
* @type: memblock type to search
|
||||
* @base: base physical address of the candidate range
|
||||
*
|
||||
* Return: the first region index that could potentially overlap @base.
|
||||
*/
|
||||
static int __init_memblock __memblock_search(struct memblock_type *type,
|
||||
phys_addr_t base)
|
||||
{
|
||||
int mid, low = 0;
|
||||
int high = type->cnt;
|
||||
|
||||
while (low < high) {
|
||||
mid = (low + high) / 2;
|
||||
if (type->regions[mid].base + type->regions[mid].size <= base)
|
||||
low = mid + 1;
|
||||
else
|
||||
high = mid;
|
||||
}
|
||||
return low;
|
||||
}
|
||||
|
||||
/**
|
||||
* memblock_add_range - add new memblock region
|
||||
* @type: memblock type to add new region into
|
||||
|
|
@ -614,8 +632,7 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
|
|||
bool insert = false;
|
||||
phys_addr_t obase = base;
|
||||
phys_addr_t end = base + memblock_cap_size(base, &size);
|
||||
int idx, nr_new, start_rgn = -1, end_rgn;
|
||||
struct memblock_region *rgn;
|
||||
int idx, nr_new, start_rgn = -1, end_rgn = 0;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
|
|
@ -651,7 +668,8 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
|
|||
base = obase;
|
||||
nr_new = 0;
|
||||
|
||||
for_each_memblock_type(idx, type, rgn) {
|
||||
for (idx = __memblock_search(type, base); idx < type->cnt; idx++) {
|
||||
struct memblock_region *rgn = &type->regions[idx];
|
||||
phys_addr_t rbase = rgn->base;
|
||||
phys_addr_t rend = rbase + rgn->size;
|
||||
|
||||
|
|
@ -814,8 +832,6 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type,
|
|||
int *start_rgn, int *end_rgn)
|
||||
{
|
||||
phys_addr_t end = base + memblock_cap_size(base, &size);
|
||||
int idx;
|
||||
struct memblock_region *rgn;
|
||||
|
||||
*start_rgn = *end_rgn = 0;
|
||||
|
||||
|
|
@ -827,7 +843,8 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type,
|
|||
if (memblock_double_array(type, base, size) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_memblock_type(idx, type, rgn) {
|
||||
for (int idx = __memblock_search(type, base); idx < type->cnt; idx++) {
|
||||
struct memblock_region *rgn = &type->regions[idx];
|
||||
phys_addr_t rbase = rgn->base;
|
||||
phys_addr_t rend = rbase + rgn->size;
|
||||
|
||||
|
|
@ -1659,7 +1676,6 @@ phys_addr_t __init memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t ali
|
|||
* @min_addr: the lower bound of the memory region to allocate (phys address)
|
||||
* @max_addr: the upper bound of the memory region to allocate (phys address)
|
||||
* @nid: nid of the free area to find, %NUMA_NO_NODE for any node
|
||||
* @exact_nid: control the allocation fall back to other nodes
|
||||
*
|
||||
* Allocates memory block using memblock_alloc_range_nid() and
|
||||
* converts the returned physical address to virtual.
|
||||
|
|
@ -1675,7 +1691,7 @@ phys_addr_t __init memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t ali
|
|||
static void * __init memblock_alloc_internal(
|
||||
phys_addr_t size, phys_addr_t align,
|
||||
phys_addr_t min_addr, phys_addr_t max_addr,
|
||||
int nid, bool exact_nid)
|
||||
int nid)
|
||||
{
|
||||
phys_addr_t alloc;
|
||||
|
||||
|
|
@ -1684,12 +1700,12 @@ static void * __init memblock_alloc_internal(
|
|||
max_addr = memblock.current_limit;
|
||||
|
||||
alloc = memblock_alloc_range_nid(size, align, min_addr, max_addr, nid,
|
||||
exact_nid);
|
||||
false);
|
||||
|
||||
/* retry allocation without lower limit */
|
||||
if (!alloc && min_addr)
|
||||
alloc = memblock_alloc_range_nid(size, align, 0, max_addr, nid,
|
||||
exact_nid);
|
||||
false);
|
||||
|
||||
if (!alloc)
|
||||
return NULL;
|
||||
|
|
@ -1697,37 +1713,6 @@ static void * __init memblock_alloc_internal(
|
|||
return phys_to_virt(alloc);
|
||||
}
|
||||
|
||||
/**
|
||||
* memblock_alloc_exact_nid_raw - allocate boot memory block on the exact node
|
||||
* without zeroing memory
|
||||
* @size: size of memory block to be allocated in bytes
|
||||
* @align: alignment of the region and block's size
|
||||
* @min_addr: the lower bound of the memory region from where the allocation
|
||||
* is preferred (phys address)
|
||||
* @max_addr: the upper bound of the memory region from where the allocation
|
||||
* is preferred (phys address), or %MEMBLOCK_ALLOC_ACCESSIBLE to
|
||||
* allocate only from memory limited by memblock.current_limit value
|
||||
* @nid: nid of the free area to find, %NUMA_NO_NODE for any node
|
||||
*
|
||||
* Public function, provides additional debug information (including caller
|
||||
* info), if enabled. Does not zero allocated memory.
|
||||
*
|
||||
* Return:
|
||||
* Virtual address of allocated memory block on success, NULL on failure.
|
||||
*/
|
||||
void * __init memblock_alloc_exact_nid_raw(
|
||||
phys_addr_t size, phys_addr_t align,
|
||||
phys_addr_t min_addr, phys_addr_t max_addr,
|
||||
int nid)
|
||||
{
|
||||
memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa %pS\n",
|
||||
__func__, (u64)size, (u64)align, nid, &min_addr,
|
||||
&max_addr, (void *)_RET_IP_);
|
||||
|
||||
return memblock_alloc_internal(size, align, min_addr, max_addr, nid,
|
||||
true);
|
||||
}
|
||||
|
||||
/**
|
||||
* memblock_alloc_try_nid_raw - allocate boot memory block without zeroing
|
||||
* memory and without panicking
|
||||
|
|
@ -1756,8 +1741,7 @@ void * __init memblock_alloc_try_nid_raw(
|
|||
__func__, (u64)size, (u64)align, nid, &min_addr,
|
||||
&max_addr, (void *)_RET_IP_);
|
||||
|
||||
return memblock_alloc_internal(size, align, min_addr, max_addr, nid,
|
||||
false);
|
||||
return memblock_alloc_internal(size, align, min_addr, max_addr, nid);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1858,8 +1842,7 @@ void * __init memblock_alloc_try_nid(
|
|||
memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa %pS\n",
|
||||
__func__, (u64)size, (u64)align, nid, &min_addr,
|
||||
&max_addr, (void *)_RET_IP_);
|
||||
ptr = memblock_alloc_internal(size, align,
|
||||
min_addr, max_addr, nid, false);
|
||||
ptr = memblock_alloc_internal(size, align, min_addr, max_addr, nid);
|
||||
if (ptr)
|
||||
memset(ptr, 0, size);
|
||||
|
||||
|
|
@ -2067,19 +2050,10 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
|
|||
|
||||
static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
|
||||
{
|
||||
unsigned int left = 0, right = type->cnt;
|
||||
int idx = __memblock_search(type, addr);
|
||||
|
||||
do {
|
||||
unsigned int mid = (right + left) / 2;
|
||||
|
||||
if (addr < type->regions[mid].base)
|
||||
right = mid;
|
||||
else if (addr >= (type->regions[mid].base +
|
||||
type->regions[mid].size))
|
||||
left = mid + 1;
|
||||
else
|
||||
return mid;
|
||||
} while (left < right);
|
||||
if (idx < type->cnt && addr >= type->regions[idx].base)
|
||||
return idx;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -2194,11 +2168,11 @@ static void __init_memblock memblock_dump(struct memblock_type *type)
|
|||
phys_addr_t base, end, size;
|
||||
enum memblock_flags flags;
|
||||
int idx;
|
||||
struct memblock_region *rgn;
|
||||
|
||||
pr_info(" %s.cnt = 0x%lx\n", type->name, type->cnt);
|
||||
|
||||
for_each_memblock_type(idx, type, rgn) {
|
||||
for (idx = 0; idx < type->cnt; idx++) {
|
||||
struct memblock_region *rgn = &type->regions[idx];
|
||||
char nid_buf[32] = "";
|
||||
|
||||
base = rgn->base;
|
||||
|
|
@ -2465,8 +2439,6 @@ static unsigned long __init free_low_memory_core_early(void)
|
|||
return count;
|
||||
}
|
||||
|
||||
static int reset_managed_pages_done __initdata;
|
||||
|
||||
static void __init reset_node_managed_pages(pg_data_t *pgdat)
|
||||
{
|
||||
struct zone *z;
|
||||
|
|
@ -2475,17 +2447,12 @@ static void __init reset_node_managed_pages(pg_data_t *pgdat)
|
|||
atomic_long_set(&z->managed_pages, 0);
|
||||
}
|
||||
|
||||
void __init reset_all_zones_managed_pages(void)
|
||||
static void __init reset_all_zones_managed_pages(void)
|
||||
{
|
||||
struct pglist_data *pgdat;
|
||||
|
||||
if (reset_managed_pages_done)
|
||||
return;
|
||||
|
||||
for_each_online_pgdat(pgdat)
|
||||
reset_node_managed_pages(pgdat);
|
||||
|
||||
reset_managed_pages_done = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2700,15 +2667,10 @@ static int __init prepare_kho_fdt(void)
|
|||
|
||||
static int __init reserve_mem_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!kho_is_enabled() || !reserved_mem_count)
|
||||
return 0;
|
||||
|
||||
err = prepare_kho_fdt();
|
||||
if (err)
|
||||
return err;
|
||||
return err;
|
||||
return prepare_kho_fdt();
|
||||
}
|
||||
late_initcall(reserve_mem_init);
|
||||
|
||||
|
|
@ -2828,12 +2790,17 @@ static int __init reserve_mem(char *p)
|
|||
if (*p != ':')
|
||||
goto err_param;
|
||||
|
||||
if (!IS_ALIGNED(size, PAGE_SIZE) || !IS_ALIGNED(align, PAGE_SIZE)) {
|
||||
pr_err("reserve_mem: size and align must be multiples of the page size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* memblock_phys_alloc() doesn't like a zero size align,
|
||||
* but it is OK for this command to have it.
|
||||
*/
|
||||
if (align < SMP_CACHE_BYTES)
|
||||
align = SMP_CACHE_BYTES;
|
||||
if (!align)
|
||||
align = PAGE_SIZE;
|
||||
|
||||
name = p + 1;
|
||||
len = strlen(name);
|
||||
|
|
|
|||
38
mm/mm_init.c
38
mm/mm_init.c
|
|
@ -1243,6 +1243,10 @@ static unsigned long __init __absent_pages_in_range(int nid,
|
|||
unsigned long start_pfn, end_pfn;
|
||||
int i;
|
||||
|
||||
/* range is empty, nothing to do */
|
||||
if (!nr_absent)
|
||||
return 0;
|
||||
|
||||
for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
|
||||
start_pfn = clamp(start_pfn, range_start_pfn, range_end_pfn);
|
||||
end_pfn = clamp(end_pfn, range_start_pfn, range_end_pfn);
|
||||
|
|
@ -1264,22 +1268,9 @@ unsigned long __init absent_pages_in_range(unsigned long start_pfn,
|
|||
return __absent_pages_in_range(MAX_NUMNODES, start_pfn, end_pfn);
|
||||
}
|
||||
|
||||
/* Return the number of page frames in holes in a zone on a node */
|
||||
static unsigned long __init zone_absent_pages_in_node(int nid,
|
||||
unsigned long zone_type,
|
||||
unsigned long zone_start_pfn,
|
||||
unsigned long zone_end_pfn)
|
||||
{
|
||||
/* zone is empty, we don't have any absent pages */
|
||||
if (zone_start_pfn == zone_end_pfn)
|
||||
return 0;
|
||||
|
||||
return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of pages a zone spans in a node, including holes
|
||||
* present_pages = zone_spanned_pages_in_node() - zone_absent_pages_in_node()
|
||||
* present_pages = zone_spanned_pages_in_node() - __absent_pages_in_range()
|
||||
*/
|
||||
static unsigned long __init zone_spanned_pages_in_node(int nid,
|
||||
unsigned long zone_type,
|
||||
|
|
@ -1369,9 +1360,8 @@ static void __init calculate_node_totalpages(struct pglist_data *pgdat,
|
|||
node_end_pfn,
|
||||
&zone_start_pfn,
|
||||
&zone_end_pfn);
|
||||
absent = zone_absent_pages_in_node(pgdat->node_id, i,
|
||||
zone_start_pfn,
|
||||
zone_end_pfn);
|
||||
absent = __absent_pages_in_range(pgdat->node_id, zone_start_pfn,
|
||||
zone_end_pfn);
|
||||
|
||||
real_size = spanned - absent;
|
||||
|
||||
|
|
@ -1636,7 +1626,7 @@ static void __init free_area_init_core(struct pglist_data *pgdat)
|
|||
}
|
||||
|
||||
void __init *memmap_alloc(phys_addr_t size, phys_addr_t align,
|
||||
phys_addr_t min_addr, int nid, bool exact_nid)
|
||||
phys_addr_t min_addr, int nid)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
|
|
@ -1644,14 +1634,8 @@ void __init *memmap_alloc(phys_addr_t size, phys_addr_t align,
|
|||
* Kmemleak will explicitly scan mem_map by traversing all valid
|
||||
* `struct *page`,so memblock does not need to be added to the scan list.
|
||||
*/
|
||||
if (exact_nid)
|
||||
ptr = memblock_alloc_exact_nid_raw(size, align, min_addr,
|
||||
MEMBLOCK_ALLOC_NOLEAKTRACE,
|
||||
nid);
|
||||
else
|
||||
ptr = memblock_alloc_try_nid_raw(size, align, min_addr,
|
||||
MEMBLOCK_ALLOC_NOLEAKTRACE,
|
||||
nid);
|
||||
ptr = memblock_alloc_try_nid_raw(size, align, min_addr,
|
||||
MEMBLOCK_ALLOC_NOLEAKTRACE, nid);
|
||||
|
||||
if (ptr && size > 0)
|
||||
page_init_poison(ptr, size);
|
||||
|
|
@ -1679,7 +1663,7 @@ static void __init alloc_node_mem_map(struct pglist_data *pgdat)
|
|||
end = ALIGN(pgdat_end_pfn(pgdat), MAX_ORDER_NR_PAGES);
|
||||
size = (end - start) * sizeof(struct page);
|
||||
map = memmap_alloc(size, SMP_CACHE_BYTES, MEMBLOCK_LOW_LIMIT,
|
||||
pgdat->node_id, false);
|
||||
pgdat->node_id);
|
||||
if (!map)
|
||||
panic("Failed to allocate %ld bytes for node %d memory map\n",
|
||||
size, pgdat->node_id);
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ bool pfn_range_intersects_zones(int nid, unsigned long start_pfn,
|
|||
|
||||
void memblock_free_pages(unsigned long pfn, unsigned int order);
|
||||
|
||||
void *memmap_alloc(phys_addr_t size, phys_addr_t align, phys_addr_t min_addr,
|
||||
int nid, bool exact_nid);
|
||||
void *memmap_alloc(phys_addr_t size, phys_addr_t align,
|
||||
phys_addr_t min_addr, int nid);
|
||||
|
||||
void memmap_init_range(unsigned long size, int nid, unsigned long zone,
|
||||
unsigned long start_pfn, unsigned long zone_end_pfn,
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ void __ref *vmemmap_alloc_block(unsigned long size, int node)
|
|||
}
|
||||
return NULL;
|
||||
} else
|
||||
return memmap_alloc(size, size, __pa(MAX_DMA_ADDRESS), node, false);
|
||||
return memmap_alloc(size, size, __pa(MAX_DMA_ADDRESS), node);
|
||||
}
|
||||
|
||||
static void * __meminit altmap_alloc_block_buf(unsigned long size,
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ struct page __init *__populate_section_memmap(unsigned long pfn,
|
|||
{
|
||||
const unsigned long size = PAGE_ALIGN(sizeof(struct page) * PAGES_PER_SECTION);
|
||||
|
||||
return memmap_alloc(size, size, __pa(MAX_DMA_ADDRESS), nid, false);
|
||||
return memmap_alloc(size, size, __pa(MAX_DMA_ADDRESS), nid);
|
||||
}
|
||||
#endif /* !CONFIG_SPARSEMEM_VMEMMAP */
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ static inline void *phys_to_virt(unsigned long address)
|
|||
#define virt_to_phys virt_to_phys
|
||||
static inline phys_addr_t virt_to_phys(volatile void *address)
|
||||
{
|
||||
return (phys_addr_t)address;
|
||||
return __pa(address);
|
||||
}
|
||||
|
||||
static inline void totalram_pages_add(long count)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ CFLAGS += -I. -I../../include -Wall -O2 -fsanitize=address \
|
|||
LDFLAGS += -fsanitize=address -fsanitize=undefined
|
||||
TARGETS = main
|
||||
TEST_OFILES = tests/alloc_nid_api.o tests/alloc_helpers_api.o tests/alloc_api.o \
|
||||
tests/basic_api.o tests/common.o tests/alloc_exact_nid_api.o
|
||||
tests/basic_api.o tests/common.o tests/alloc_exact_nid_api.o \
|
||||
tests/alloc_low_api.o
|
||||
DEP_OFILES = memblock.o lib/slab.o mmzone.o slab.o cmdline.o
|
||||
OFILES = main.o $(DEP_OFILES) $(TEST_OFILES)
|
||||
EXTR_SRC = ../../../mm/memblock.c
|
||||
|
|
|
|||
|
|
@ -67,13 +67,13 @@ memblock
|
|||
|-- tests
|
||||
| |-- alloc_api.(c|h) -- memblock_alloc tests
|
||||
| |-- alloc_helpers_api.(c|h) -- memblock_alloc_from tests
|
||||
| |-- alloc_low_api.(c|h) -- memblock_alloc_low tests
|
||||
| |-- alloc_nid_api.(c|h) -- memblock_alloc_try_nid tests
|
||||
| |-- basic_api.(c|h) -- memblock_add/memblock_reserve/... tests
|
||||
| |-- common.(c|h) -- helper functions for resetting memblock;
|
||||
|-- main.c --------------. dummy physical memory definition
|
||||
|-- Makefile `- test runner
|
||||
|-- README
|
||||
|-- TODO
|
||||
|-- .gitignore
|
||||
|
||||
Simulating physical memory
|
||||
|
|
@ -101,12 +101,10 @@ There's no need to explicitly free the dummy memory from memblock via
|
|||
memblock_free() call. The entry will be erased by reset_memblock_regions(),
|
||||
called at the beginning of each test.
|
||||
|
||||
Known issues
|
||||
============
|
||||
|
||||
1. Tests for memblock_alloc_low() can't be easily implemented. The function uses
|
||||
ARCH_LOW_ADDRESS_LIMIT marco, which can't be changed to point at the low
|
||||
memory of the memory_block.
|
||||
The simulator defines ARCH_LOW_ADDRESS_LIMIT in asm/dma.h using the midpoint
|
||||
of the MEM_SIZE range registered by setup_memblock(). This leaves registered
|
||||
memory both below and above the limit. The limit is the first address an
|
||||
allocation must not use; an allocation's base plus its size may equal the limit.
|
||||
|
||||
References
|
||||
==========
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
TODO
|
||||
=====
|
||||
|
||||
1. Add tests for memblock_alloc_low() once the simulator can model
|
||||
ARCH_LOW_ADDRESS_LIMIT against the low memory in memory_block
|
||||
|
|
@ -2,4 +2,10 @@
|
|||
#ifndef _TOOLS_DMA_H
|
||||
#define _TOOLS_DMA_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
phys_addr_t dummy_physical_memory_low_limit(void);
|
||||
|
||||
#define ARCH_LOW_ADDRESS_LIMIT dummy_physical_memory_low_limit()
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "tests/alloc_helpers_api.h"
|
||||
#include "tests/alloc_nid_api.h"
|
||||
#include "tests/alloc_exact_nid_api.h"
|
||||
#include "tests/alloc_low_api.h"
|
||||
#include "tests/common.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
|
@ -12,6 +13,7 @@ int main(int argc, char **argv)
|
|||
memblock_basic_checks();
|
||||
memblock_alloc_checks();
|
||||
memblock_alloc_helpers_checks();
|
||||
memblock_alloc_low_checks();
|
||||
memblock_alloc_nid_checks();
|
||||
memblock_alloc_exact_nid_checks();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
// 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"
|
||||
#define FUNC_NAME "memblock_alloc_range_nid(exact)"
|
||||
|
||||
/*
|
||||
* contains the fraction of MEM_SIZE contained in each node in basis point
|
||||
|
|
@ -19,6 +18,18 @@ static const unsigned int node_fractions[] = {
|
|||
625, /* 1/16 */
|
||||
};
|
||||
|
||||
static void *alloc_range_exact_nid(phys_addr_t size, phys_addr_t align,
|
||||
phys_addr_t min_addr,
|
||||
phys_addr_t max_addr, int nid)
|
||||
{
|
||||
phys_addr_t addr;
|
||||
|
||||
addr = memblock_alloc_range_nid(size, align, min_addr, max_addr, nid,
|
||||
true);
|
||||
|
||||
return addr ? phys_to_virt(addr) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
|
|
@ -42,9 +53,8 @@ static int alloc_exact_nid_top_down_numa_simple_check(void)
|
|||
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);
|
||||
allocated_ptr = alloc_range_exact_nid(size, SMP_CACHE_BYTES,
|
||||
min_addr, max_addr, nid_req);
|
||||
|
||||
ASSERT_NE(allocated_ptr, NULL);
|
||||
ASSERT_MEM_NE(allocated_ptr, 0, size);
|
||||
|
|
@ -98,9 +108,8 @@ static int alloc_exact_nid_top_down_numa_part_reserved_check(void)
|
|||
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);
|
||||
allocated_ptr = alloc_range_exact_nid(size, SMP_CACHE_BYTES,
|
||||
min_addr, max_addr, nid_req);
|
||||
|
||||
ASSERT_NE(allocated_ptr, NULL);
|
||||
ASSERT_MEM_NE(allocated_ptr, 0, size);
|
||||
|
|
@ -117,177 +126,6 @@ static int alloc_exact_nid_top_down_numa_part_reserved_check(void)
|
|||
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.
|
||||
|
|
@ -311,9 +149,8 @@ static int alloc_exact_nid_bottom_up_numa_simple_check(void)
|
|||
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);
|
||||
allocated_ptr = alloc_range_exact_nid(size, SMP_CACHE_BYTES,
|
||||
min_addr, max_addr, nid_req);
|
||||
|
||||
ASSERT_NE(allocated_ptr, NULL);
|
||||
ASSERT_MEM_NE(allocated_ptr, 0, size);
|
||||
|
|
@ -369,9 +206,8 @@ static int alloc_exact_nid_bottom_up_numa_part_reserved_check(void)
|
|||
total_size = size + r1.size;
|
||||
|
||||
__memblock_reserve(r1.base, r1.size, nid_req, MEMBLOCK_RSRV_KERN);
|
||||
allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
|
||||
min_addr, max_addr,
|
||||
nid_req);
|
||||
allocated_ptr = alloc_range_exact_nid(size, SMP_CACHE_BYTES,
|
||||
min_addr, max_addr, nid_req);
|
||||
|
||||
ASSERT_NE(allocated_ptr, NULL);
|
||||
ASSERT_MEM_NE(allocated_ptr, 0, size);
|
||||
|
|
@ -388,178 +224,6 @@ static int alloc_exact_nid_bottom_up_numa_part_reserved_check(void)
|
|||
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:
|
||||
|
|
@ -590,9 +254,8 @@ static int alloc_exact_nid_numa_small_node_generic_check(void)
|
|||
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);
|
||||
allocated_ptr = alloc_range_exact_nid(size, SMP_CACHE_BYTES,
|
||||
min_addr, max_addr, nid_req);
|
||||
|
||||
ASSERT_EQ(allocated_ptr, NULL);
|
||||
|
||||
|
|
@ -632,9 +295,8 @@ static int alloc_exact_nid_numa_node_reserved_generic_check(void)
|
|||
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);
|
||||
allocated_ptr = alloc_range_exact_nid(size, SMP_CACHE_BYTES,
|
||||
min_addr, max_addr, nid_req);
|
||||
|
||||
ASSERT_EQ(allocated_ptr, NULL);
|
||||
|
||||
|
|
@ -680,9 +342,8 @@ static int alloc_exact_nid_numa_part_reserved_fail_generic_check(void)
|
|||
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);
|
||||
allocated_ptr = alloc_range_exact_nid(size, SMP_CACHE_BYTES,
|
||||
min_addr, max_addr, nid_req);
|
||||
|
||||
ASSERT_EQ(allocated_ptr, NULL);
|
||||
|
||||
|
|
@ -721,9 +382,8 @@ static int alloc_exact_nid_numa_split_range_high_generic_check(void)
|
|||
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);
|
||||
allocated_ptr = alloc_range_exact_nid(size, SMP_CACHE_BYTES,
|
||||
min_addr, max_addr, nid_req);
|
||||
|
||||
ASSERT_EQ(allocated_ptr, NULL);
|
||||
|
||||
|
|
@ -764,9 +424,8 @@ static int alloc_exact_nid_numa_no_overlap_high_generic_check(void)
|
|||
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);
|
||||
allocated_ptr = alloc_range_exact_nid(size, SMP_CACHE_BYTES,
|
||||
min_addr, max_addr, nid_req);
|
||||
|
||||
ASSERT_EQ(allocated_ptr, NULL);
|
||||
|
||||
|
|
@ -803,9 +462,8 @@ static int alloc_exact_nid_numa_large_region_generic_check(void)
|
|||
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);
|
||||
allocated_ptr = alloc_range_exact_nid(size, SMP_CACHE_BYTES,
|
||||
min_addr, max_addr, nid_req);
|
||||
ASSERT_EQ(allocated_ptr, NULL);
|
||||
|
||||
test_pass_pop();
|
||||
|
|
@ -864,9 +522,8 @@ static int alloc_exact_nid_numa_reserved_full_merge_generic_check(void)
|
|||
__memblock_reserve(r1.base, r1.size, nid_req, MEMBLOCK_RSRV_KERN);
|
||||
__memblock_reserve(r2.base, r2.size, nid_req, MEMBLOCK_RSRV_KERN);
|
||||
|
||||
allocated_ptr = memblock_alloc_exact_nid_raw(size, SMP_CACHE_BYTES,
|
||||
min_addr, max_addr,
|
||||
nid_req);
|
||||
allocated_ptr = alloc_range_exact_nid(size, SMP_CACHE_BYTES,
|
||||
min_addr, max_addr, nid_req);
|
||||
|
||||
ASSERT_NE(allocated_ptr, NULL);
|
||||
ASSERT_MEM_NE(allocated_ptr, 0, size);
|
||||
|
|
@ -933,9 +590,8 @@ static int alloc_exact_nid_numa_split_all_reserved_generic_check(void)
|
|||
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);
|
||||
allocated_ptr = alloc_range_exact_nid(size, SMP_CACHE_BYTES,
|
||||
min_addr, max_addr, NUMA_NO_NODE);
|
||||
|
||||
ASSERT_EQ(allocated_ptr, NULL);
|
||||
|
||||
|
|
@ -967,38 +623,6 @@ static int alloc_exact_nid_numa_part_reserved_check(void)
|
|||
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)
|
||||
{
|
||||
|
|
@ -1078,9 +702,6 @@ int __memblock_alloc_exact_nid_numa_checks(void)
|
|||
|
||||
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();
|
||||
|
|
@ -1102,7 +723,6 @@ int memblock_alloc_exact_nid_checks(void)
|
|||
reset_memblock_attributes();
|
||||
dummy_physical_memory_init();
|
||||
|
||||
memblock_alloc_exact_nid_range_checks();
|
||||
memblock_alloc_exact_nid_numa_checks();
|
||||
|
||||
dummy_physical_memory_cleanup();
|
||||
|
|
|
|||
148
tools/testing/memblock/tests/alloc_low_api.c
Normal file
148
tools/testing/memblock/tests/alloc_low_api.c
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#include "alloc_low_api.h"
|
||||
#include <linux/align.h>
|
||||
|
||||
/* Allocate at the first or last aligned address below the low limit. */
|
||||
static int alloc_low_simple_check(void)
|
||||
{
|
||||
struct memblock_region *rgn = &memblock.reserved.regions[0];
|
||||
phys_addr_t size = SZ_64;
|
||||
phys_addr_t expected;
|
||||
void *allocated_ptr;
|
||||
|
||||
PREFIX_PUSH();
|
||||
setup_memblock();
|
||||
|
||||
/* Simulated physical RAM is not necessarily SMP_CACHE_BYTES aligned. */
|
||||
if (memblock_bottom_up())
|
||||
expected = ALIGN(memblock_start_of_DRAM(), SMP_CACHE_BYTES);
|
||||
else
|
||||
expected = ALIGN_DOWN(ARCH_LOW_ADDRESS_LIMIT - size,
|
||||
SMP_CACHE_BYTES);
|
||||
|
||||
allocated_ptr = memblock_alloc_low(size, SMP_CACHE_BYTES);
|
||||
|
||||
ASSERT_NE(allocated_ptr, NULL);
|
||||
ASSERT_EQ((phys_addr_t)(uintptr_t)allocated_ptr, expected);
|
||||
ASSERT_MEM_EQ(allocated_ptr, 0, size);
|
||||
ASSERT_EQ(rgn->base, expected);
|
||||
ASSERT_EQ(rgn->size, size);
|
||||
ASSERT_LE(region_end(rgn), ARCH_LOW_ADDRESS_LIMIT);
|
||||
ASSERT_EQ(memblock.reserved.cnt, 1);
|
||||
ASSERT_EQ(memblock.reserved.total_size, size);
|
||||
|
||||
test_pass_pop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The last byte of the allocation is immediately below the low limit. */
|
||||
static int alloc_low_exact_limit_check(void)
|
||||
{
|
||||
phys_addr_t limit = ARCH_LOW_ADDRESS_LIMIT;
|
||||
phys_addr_t base = ALIGN_DOWN(limit - SZ_64, SMP_CACHE_BYTES);
|
||||
phys_addr_t size = limit - base;
|
||||
void *allocated_ptr;
|
||||
|
||||
PREFIX_PUSH();
|
||||
setup_memblock();
|
||||
ASSERT_EQ(memblock_remove(memblock_start_of_DRAM(),
|
||||
base - memblock_start_of_DRAM()), 0);
|
||||
|
||||
allocated_ptr = memblock_alloc_low(size, SMP_CACHE_BYTES);
|
||||
|
||||
ASSERT_NE(allocated_ptr, NULL);
|
||||
ASSERT_EQ((phys_addr_t)(uintptr_t)allocated_ptr, base);
|
||||
ASSERT_MEM_EQ(allocated_ptr, 0, size);
|
||||
ASSERT_EQ(memblock.reserved.regions[0].base, base);
|
||||
ASSERT_EQ(region_end(&memblock.reserved.regions[0]), limit);
|
||||
ASSERT_EQ(memblock.reserved.cnt, 1);
|
||||
ASSERT_EQ(memblock.reserved.total_size, size);
|
||||
|
||||
test_pass_pop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are size bytes below the limit, but aligning the start makes the
|
||||
* allocation cross it. Memory above the limit must not satisfy the request.
|
||||
*/
|
||||
static int alloc_low_alignment_crosses_limit_check(void)
|
||||
{
|
||||
phys_addr_t limit = ARCH_LOW_ADDRESS_LIMIT;
|
||||
phys_addr_t base = ALIGN_DOWN(limit, SMP_CACHE_BYTES) - 1;
|
||||
phys_addr_t size = limit - base;
|
||||
void *allocated_ptr;
|
||||
|
||||
PREFIX_PUSH();
|
||||
setup_memblock();
|
||||
ASSERT_EQ(memblock_remove(memblock_start_of_DRAM(),
|
||||
base - memblock_start_of_DRAM()), 0);
|
||||
|
||||
allocated_ptr = memblock_alloc_low(size, SMP_CACHE_BYTES);
|
||||
|
||||
ASSERT_EQ(allocated_ptr, NULL);
|
||||
ASSERT_EQ(memblock.reserved.cnt, 0);
|
||||
ASSERT_EQ(memblock.reserved.total_size, 0);
|
||||
ASSERT_MEM_EQ((void *)(uintptr_t)base, 1, memblock_end_of_DRAM() - base);
|
||||
|
||||
test_pass_pop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocation must fail after reserving all low memory, with high memory free. */
|
||||
static int alloc_low_reserved_check(void)
|
||||
{
|
||||
phys_addr_t limit = ARCH_LOW_ADDRESS_LIMIT;
|
||||
phys_addr_t base = dummy_physical_memory_base();
|
||||
phys_addr_t size = SZ_64;
|
||||
void *allocated_ptr;
|
||||
|
||||
PREFIX_PUSH();
|
||||
setup_memblock();
|
||||
ASSERT_EQ(memblock_reserve(base, limit - base), 0);
|
||||
|
||||
allocated_ptr = memblock_alloc_low(size, SMP_CACHE_BYTES);
|
||||
|
||||
ASSERT_EQ(allocated_ptr, NULL);
|
||||
ASSERT_EQ(memblock.reserved.cnt, 1);
|
||||
ASSERT_EQ(memblock.reserved.regions[0].base, base);
|
||||
ASSERT_EQ(memblock.reserved.regions[0].size, limit - base);
|
||||
ASSERT_EQ(memblock.reserved.total_size, limit - base);
|
||||
ASSERT_MEM_EQ((void *)(uintptr_t)base, 1, MEM_SIZE);
|
||||
|
||||
allocated_ptr = memblock_alloc(size, SMP_CACHE_BYTES);
|
||||
ASSERT_NE(allocated_ptr, NULL);
|
||||
ASSERT_LE(limit, (phys_addr_t)(uintptr_t)allocated_ptr);
|
||||
ASSERT_MEM_EQ(allocated_ptr, 0, size);
|
||||
|
||||
test_pass_pop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alloc_low_checks(void)
|
||||
{
|
||||
alloc_low_simple_check();
|
||||
alloc_low_exact_limit_check();
|
||||
alloc_low_alignment_crosses_limit_check();
|
||||
alloc_low_reserved_check();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int memblock_alloc_low_checks(void)
|
||||
{
|
||||
prefix_reset();
|
||||
prefix_push("memblock_alloc_low");
|
||||
test_print("Running memblock_alloc_low tests...\n");
|
||||
|
||||
reset_memblock_attributes();
|
||||
dummy_physical_memory_init();
|
||||
|
||||
run_top_down(alloc_low_checks);
|
||||
run_bottom_up(alloc_low_checks);
|
||||
|
||||
dummy_physical_memory_cleanup();
|
||||
prefix_pop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
9
tools/testing/memblock/tests/alloc_low_api.h
Normal file
9
tools/testing/memblock/tests/alloc_low_api.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#ifndef _MEMBLOCK_ALLOC_LOW_H
|
||||
#define _MEMBLOCK_ALLOC_LOW_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int memblock_alloc_low_checks(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -20,8 +20,6 @@ static const unsigned int node_fractions[] = {
|
|||
|
||||
static inline const char * const get_memblock_alloc_nid_name(int flags)
|
||||
{
|
||||
if (flags & TEST_F_EXACT)
|
||||
return "memblock_alloc_exact_nid_raw";
|
||||
if (flags & TEST_F_RAW)
|
||||
return "memblock_alloc_try_nid_raw";
|
||||
return "memblock_alloc_try_nid";
|
||||
|
|
@ -32,15 +30,6 @@ static inline void *run_memblock_alloc_nid(phys_addr_t size,
|
|||
phys_addr_t min_addr,
|
||||
phys_addr_t max_addr, int nid)
|
||||
{
|
||||
assert(!(alloc_nid_test_flags & TEST_F_EXACT) ||
|
||||
(alloc_nid_test_flags & TEST_F_RAW));
|
||||
/*
|
||||
* TEST_F_EXACT should be checked before TEST_F_RAW since
|
||||
* memblock_alloc_exact_nid_raw() performs raw allocations.
|
||||
*/
|
||||
if (alloc_nid_test_flags & TEST_F_EXACT)
|
||||
return memblock_alloc_exact_nid_raw(size, align, min_addr,
|
||||
max_addr, nid);
|
||||
if (alloc_nid_test_flags & TEST_F_RAW)
|
||||
return memblock_alloc_try_nid_raw(size, align, min_addr,
|
||||
max_addr, nid);
|
||||
|
|
@ -2722,12 +2711,3 @@ int memblock_alloc_nid_checks(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int memblock_alloc_exact_nid_range_checks(void)
|
||||
{
|
||||
alloc_nid_test_flags = (TEST_F_RAW | TEST_F_EXACT);
|
||||
|
||||
memblock_alloc_nid_range_checks();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
#include "common.h"
|
||||
|
||||
int memblock_alloc_nid_checks(void);
|
||||
int memblock_alloc_exact_nid_range_checks(void);
|
||||
int __memblock_alloc_nid_numa_checks(void);
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
|
|
|
|||
|
|
@ -1730,7 +1730,7 @@ static int memblock_free_simple_check(void)
|
|||
reset_memblock_regions();
|
||||
memblock_reserve(r1.base, r1.size);
|
||||
memblock_reserve(r2.base, r2.size);
|
||||
memblock_free((void *)r1.base, r1.size);
|
||||
memblock_phys_free(r1.base, r1.size);
|
||||
|
||||
ASSERT_EQ(rgn->base, r2.base);
|
||||
ASSERT_EQ(rgn->size, r2.size);
|
||||
|
|
@ -1778,7 +1778,7 @@ static int memblock_free_absent_check(void)
|
|||
|
||||
reset_memblock_regions();
|
||||
memblock_reserve(r1.base, r1.size);
|
||||
memblock_free((void *)r2.base, r2.size);
|
||||
memblock_phys_free(r2.base, r2.size);
|
||||
|
||||
ASSERT_EQ(rgn->base, r1.base);
|
||||
ASSERT_EQ(rgn->size, r1.size);
|
||||
|
|
@ -1832,7 +1832,7 @@ static int memblock_free_overlap_top_check(void)
|
|||
|
||||
reset_memblock_regions();
|
||||
memblock_reserve(r1.base, r1.size);
|
||||
memblock_free((void *)r2.base, r2.size);
|
||||
memblock_phys_free(r2.base, r2.size);
|
||||
|
||||
ASSERT_EQ(rgn->base, r2.base + r2.size);
|
||||
ASSERT_EQ(rgn->size, total_size);
|
||||
|
|
@ -1881,7 +1881,7 @@ static int memblock_free_overlap_bottom_check(void)
|
|||
|
||||
reset_memblock_regions();
|
||||
memblock_reserve(r1.base, r1.size);
|
||||
memblock_free((void *)r2.base, r2.size);
|
||||
memblock_phys_free(r2.base, r2.size);
|
||||
|
||||
ASSERT_EQ(rgn->base, r1.base);
|
||||
ASSERT_EQ(rgn->size, total_size);
|
||||
|
|
@ -1938,7 +1938,7 @@ static int memblock_free_within_check(void)
|
|||
|
||||
reset_memblock_regions();
|
||||
memblock_reserve(r1.base, r1.size);
|
||||
memblock_free((void *)r2.base, r2.size);
|
||||
memblock_phys_free(r2.base, r2.size);
|
||||
|
||||
ASSERT_EQ(rgn1->base, r1.base);
|
||||
ASSERT_EQ(rgn1->size, r1_size);
|
||||
|
|
@ -1976,7 +1976,7 @@ static int memblock_free_only_region_check(void)
|
|||
|
||||
reset_memblock_regions();
|
||||
memblock_reserve(r1.base, r1.size);
|
||||
memblock_free((void *)r1.base, r1.size);
|
||||
memblock_phys_free(r1.base, r1.size);
|
||||
|
||||
ASSERT_EQ(rgn->base, 0);
|
||||
ASSERT_EQ(rgn->size, 0);
|
||||
|
|
@ -2003,7 +2003,7 @@ static int memblock_free_only_region_check(void)
|
|||
* Expect the total size of reserved memory to be updated and the counter to
|
||||
* not be updated.
|
||||
*/
|
||||
static int memblock_free_near_max_check(void)
|
||||
static int memblock_phys_free_near_max_check(void)
|
||||
{
|
||||
struct memblock_region *rgn;
|
||||
phys_addr_t total_size;
|
||||
|
|
@ -2026,7 +2026,7 @@ static int memblock_free_near_max_check(void)
|
|||
|
||||
reset_memblock_regions();
|
||||
memblock_reserve(r1.base, r1.size);
|
||||
memblock_free((void *)r2.base, r2.size);
|
||||
memblock_phys_free(r2.base, r2.size);
|
||||
|
||||
ASSERT_EQ(rgn->base, r1.base);
|
||||
ASSERT_EQ(rgn->size, total_size);
|
||||
|
|
@ -2086,7 +2086,7 @@ static int memblock_free_overlap_two_check(void)
|
|||
reset_memblock_regions();
|
||||
memblock_reserve(r1.base, r1.size);
|
||||
memblock_reserve(r2.base, r2.size);
|
||||
memblock_free((void *)r3.base, r3.size);
|
||||
memblock_phys_free(r3.base, r3.size);
|
||||
|
||||
ASSERT_EQ(rgn1->base, r1.base);
|
||||
ASSERT_EQ(rgn1->size, new_r1_size);
|
||||
|
|
@ -2114,7 +2114,7 @@ static int memblock_free_checks(void)
|
|||
memblock_free_overlap_bottom_check();
|
||||
memblock_free_within_check();
|
||||
memblock_free_only_region_check();
|
||||
memblock_free_near_max_check();
|
||||
memblock_phys_free_near_max_check();
|
||||
memblock_free_overlap_two_check();
|
||||
|
||||
prefix_pop();
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ static inline void fill_memblock(void)
|
|||
void setup_memblock(void)
|
||||
{
|
||||
reset_memblock_regions();
|
||||
memblock_add((phys_addr_t)memory_block.base, MEM_SIZE);
|
||||
memblock_add((phys_addr_t)(uintptr_t)memory_block.base, MEM_SIZE);
|
||||
fill_memblock();
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ void setup_numa_memblock(const unsigned int node_fracs[])
|
|||
int flags;
|
||||
|
||||
reset_memblock_regions();
|
||||
base = (phys_addr_t)memory_block.base;
|
||||
base = (phys_addr_t)(uintptr_t)memory_block.base;
|
||||
flags = (movable_node_is_enabled()) ? MEMBLOCK_NONE : MEMBLOCK_HOTPLUG;
|
||||
|
||||
for (int i = 0; i < NUMA_NODES; i++) {
|
||||
|
|
@ -115,7 +115,13 @@ void dummy_physical_memory_cleanup(void)
|
|||
|
||||
phys_addr_t dummy_physical_memory_base(void)
|
||||
{
|
||||
return (phys_addr_t)memory_block.base;
|
||||
return (phys_addr_t)(uintptr_t)memory_block.base;
|
||||
}
|
||||
|
||||
phys_addr_t dummy_physical_memory_low_limit(void)
|
||||
{
|
||||
/* The low limit is halfway through memory registered by setup_memblock(). */
|
||||
return dummy_physical_memory_base() + MEM_SIZE / 2;
|
||||
}
|
||||
|
||||
static void usage(const char *prog)
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@ enum test_flags {
|
|||
TEST_F_NONE = 0x0,
|
||||
/* Perform raw allocations (no zeroing of memory). */
|
||||
TEST_F_RAW = 0x1,
|
||||
/* Perform allocations on the exact node specified. */
|
||||
TEST_F_EXACT = 0x2
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user