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:
Linus Torvalds 2026-10-25 17:27:19 -10:00
commit 394023fbe3
21 changed files with 294 additions and 582 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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 */

View File

@ -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)

View File

@ -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

View File

@ -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
==========

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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();

View 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;
}

View 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

View File

@ -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;
}

View File

@ -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

View File

@ -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();

View File

@ -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)

View File

@ -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
};
/**