Skip to content

Commit 4b5256f

Browse files
committed
Merge tag 'fixes-2025-04-29' of git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock
Pull memblock fixes from Mike Rapoport: "Fixes for nid setting in memmap_init_reserved_pages(): - pass 'size' rather than 'end' to memblock_set_node() as that function expects - fix a corner case when memblock.reserved is doubled at memmap_init_reserved_pages() and the newly reserved block won't have nid assigned" * tag 'fixes-2025-04-29' of git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock: memblock tests: add test for memblock_set_node mm/memblock: repeat setting reserved region nid if array is doubled mm/memblock: pass size instead of end to memblock_set_node()
2 parents ca91b95 + 3b394df commit 4b5256f

File tree

2 files changed

+113
-1
lines changed

2 files changed

+113
-1
lines changed

mm/memblock.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2183,11 +2183,14 @@ static void __init memmap_init_reserved_pages(void)
21832183
struct memblock_region *region;
21842184
phys_addr_t start, end;
21852185
int nid;
2186+
unsigned long max_reserved;
21862187

21872188
/*
21882189
* set nid on all reserved pages and also treat struct
21892190
* pages for the NOMAP regions as PageReserved
21902191
*/
2192+
repeat:
2193+
max_reserved = memblock.reserved.max;
21912194
for_each_mem_region(region) {
21922195
nid = memblock_get_region_node(region);
21932196
start = region->base;
@@ -2196,8 +2199,15 @@ static void __init memmap_init_reserved_pages(void)
21962199
if (memblock_is_nomap(region))
21972200
reserve_bootmem_region(start, end, nid);
21982201

2199-
memblock_set_node(start, end, &memblock.reserved, nid);
2202+
memblock_set_node(start, region->size, &memblock.reserved, nid);
22002203
}
2204+
/*
2205+
* 'max' is changed means memblock.reserved has been doubled its
2206+
* array, which may result a new reserved region before current
2207+
* 'start'. Now we should repeat the procedure to set its node id.
2208+
*/
2209+
if (max_reserved != memblock.reserved.max)
2210+
goto repeat;
22012211

22022212
/*
22032213
* initialize struct pages for reserved regions that don't have

tools/testing/memblock/tests/basic_api.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2434,6 +2434,107 @@ static int memblock_overlaps_region_checks(void)
24342434
return 0;
24352435
}
24362436

2437+
#ifdef CONFIG_NUMA
2438+
static int memblock_set_node_check(void)
2439+
{
2440+
unsigned long i, max_reserved;
2441+
struct memblock_region *rgn;
2442+
void *orig_region;
2443+
2444+
PREFIX_PUSH();
2445+
2446+
reset_memblock_regions();
2447+
memblock_allow_resize();
2448+
2449+
dummy_physical_memory_init();
2450+
memblock_add(dummy_physical_memory_base(), MEM_SIZE);
2451+
orig_region = memblock.reserved.regions;
2452+
2453+
/* Equally Split range to node 0 and 1*/
2454+
memblock_set_node(memblock_start_of_DRAM(),
2455+
memblock_phys_mem_size() / 2, &memblock.memory, 0);
2456+
memblock_set_node(memblock_start_of_DRAM() + memblock_phys_mem_size() / 2,
2457+
memblock_phys_mem_size() / 2, &memblock.memory, 1);
2458+
2459+
ASSERT_EQ(memblock.memory.cnt, 2);
2460+
rgn = &memblock.memory.regions[0];
2461+
ASSERT_EQ(rgn->base, memblock_start_of_DRAM());
2462+
ASSERT_EQ(rgn->size, memblock_phys_mem_size() / 2);
2463+
ASSERT_EQ(memblock_get_region_node(rgn), 0);
2464+
rgn = &memblock.memory.regions[1];
2465+
ASSERT_EQ(rgn->base, memblock_start_of_DRAM() + memblock_phys_mem_size() / 2);
2466+
ASSERT_EQ(rgn->size, memblock_phys_mem_size() / 2);
2467+
ASSERT_EQ(memblock_get_region_node(rgn), 1);
2468+
2469+
/* Reserve 126 regions with the last one across node boundary */
2470+
for (i = 0; i < 125; i++)
2471+
memblock_reserve(memblock_start_of_DRAM() + SZ_16 * i, SZ_8);
2472+
2473+
memblock_reserve(memblock_start_of_DRAM() + memblock_phys_mem_size() / 2 - SZ_8,
2474+
SZ_16);
2475+
2476+
/*
2477+
* Commit 61167ad5fecd ("mm: pass nid to reserve_bootmem_region()")
2478+
* do following process to set nid to each memblock.reserved region.
2479+
* But it may miss some region if memblock_set_node() double the
2480+
* array.
2481+
*
2482+
* By checking 'max', we make sure all region nid is set properly.
2483+
*/
2484+
repeat:
2485+
max_reserved = memblock.reserved.max;
2486+
for_each_mem_region(rgn) {
2487+
int nid = memblock_get_region_node(rgn);
2488+
2489+
memblock_set_node(rgn->base, rgn->size, &memblock.reserved, nid);
2490+
}
2491+
if (max_reserved != memblock.reserved.max)
2492+
goto repeat;
2493+
2494+
/* Confirm each region has valid node set */
2495+
for_each_reserved_mem_region(rgn) {
2496+
ASSERT_TRUE(numa_valid_node(memblock_get_region_node(rgn)));
2497+
if (rgn == (memblock.reserved.regions + memblock.reserved.cnt - 1))
2498+
ASSERT_EQ(1, memblock_get_region_node(rgn));
2499+
else
2500+
ASSERT_EQ(0, memblock_get_region_node(rgn));
2501+
}
2502+
2503+
dummy_physical_memory_cleanup();
2504+
2505+
/*
2506+
* The current reserved.regions is occupying a range of memory that
2507+
* allocated from dummy_physical_memory_init(). After free the memory,
2508+
* we must not use it. So restore the origin memory region to make sure
2509+
* the tests can run as normal and not affected by the double array.
2510+
*/
2511+
memblock.reserved.regions = orig_region;
2512+
memblock.reserved.cnt = INIT_MEMBLOCK_RESERVED_REGIONS;
2513+
2514+
test_pass_pop();
2515+
2516+
return 0;
2517+
}
2518+
2519+
static int memblock_set_node_checks(void)
2520+
{
2521+
prefix_reset();
2522+
prefix_push("memblock_set_node");
2523+
test_print("Running memblock_set_node tests...\n");
2524+
2525+
memblock_set_node_check();
2526+
2527+
prefix_pop();
2528+
2529+
return 0;
2530+
}
2531+
#else
2532+
static int memblock_set_node_checks(void)
2533+
{
2534+
return 0;
2535+
}
2536+
#endif
2537+
24372538
int memblock_basic_checks(void)
24382539
{
24392540
memblock_initialization_check();
@@ -2444,6 +2545,7 @@ int memblock_basic_checks(void)
24442545
memblock_bottom_up_checks();
24452546
memblock_trim_memory_checks();
24462547
memblock_overlaps_region_checks();
2548+
memblock_set_node_checks();
24472549

24482550
return 0;
24492551
}

0 commit comments

Comments
 (0)