mm/mm_init: don't overlap zones with kernelcore=mirror
Mike Rapoport
maintainerv2 cover mm/mm_init: don't overlap zones with kernelcore=mirror
From: "Mike Rapoport (Microsoft)" <[email protected]>
Hi,
These patches make the behaviour of kernelcore= parameter uniform and treat mirror just as another way to size the zones and cleanup a weird part of the memory map initialization.
For example, for the memory layout below with the first two memory ranges being mirrored (flags=0x2)
memory[0x0] [0x0000000000001000-0x000000000009efff], 0x000000000009e000 bytes on node 0 flags: 0x2 memory[0x1] [0x0000000000100000-0x00000000bffdefff], 0x00000000bfedf000 bytes on node 0 flags: 0x2 memory[0x2] [0x0000000100000000-0x000000013fffffff], 0x0000000040000000 bytes on node 0 flags: 0x2 memory[0x3] [0x0000000140000000-0x00000001bfffffff], 0x0000000080000000 bytes on node 0 flags: 0x0
with kernelcore=mirror set zone ranges would be
Normal [100000, 1c0000]
Movable [140000, 1c0000]
and range [140000, 1c0000] is spanned by both NORMAL and MOVABLE zones.
This range will be passed twice to memmap_init_range() - once for each zone that spans it.
The memory map for this range will be initialized as ZONE_NORMAL during the first pass and skipped because of overlap_memmap_init() during the second pass (ZONE_MOVABLE initialization), although the pages in this range actually belong to ZONE_MOVABLE.
Aligning kernelcore=mirror behaviour with other variants of kernelcore=/movablecore= resolves this issue and makes the code less obfuscated.
I intend to carry this via memblock tree.
Mike Rapoport (Microsoft) (2):
mm/mm_init: don't overlap NORMAL and MOVABLE zones with kernelcore=mirror mm/mm_init: drop overlap_memmap_init()
mm/mm_init.c | 60 +++------------------------------------------------- 1 file changed, 3 insertions(+), 57 deletions(-)
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
Signature · 1 line
2.53.0
Mike Rapoport
maintainerPATCH v2 1/2 mm/mm_init: don't overlap NORMAL and MOVABLE zones with kernelcore=mirror
From: "Mike Rapoport (Microsoft)" <[email protected]>
When kernelcore or movablecore kernel parameters define size of the NORMAL and MOVABLE zones as percents of the total memory or by absolute value, ZONE_NORMAL is clamped at the beginning of ZONE_MOVABLE.
However, when kernelcore=mirror the ZONE_NORMAL span is not changed but rather pages from ZONE_MOVABLE counted as absent in ZONE_NORMAL.
Make the behaviour of kernelcore= parameter uniform and treat mirror just as another way to size the zones.
--- mm/mm_init.c | 36 +++--------------------------------- 1 file changed, 3 insertions(+), 33 deletions(-)
mm/mm_init.c +3 -33
@@ -1174,9 +1174,8 @@ static void __init adjust_zone_range_for_zone_movable(int nid, arch_zone_highest_possible_pfn[movable_zone]);/* Adjust for ZONE_MOVABLE starting within this range */ - }else if (!mirrored_kernelcore && - *zone_start_pfn < zone_movable_pfn[nid] && - *zone_end_pfn > zone_movable_pfn[nid]) { + }else if (*zone_start_pfn < zone_movable_pfn[nid] && + *zone_end_pfn > zone_movable_pfn[nid]) { *zone_end_pfn = zone_movable_pfn[nid];/* Check if this whole range is within ZONE_MOVABLE */
@@ -1224,40 +1223,11 @@ static unsigned long __init zone_absent_pages_in_node(int nid, unsigned long zone_start_pfn, unsigned long zone_end_pfn) { - unsigned long nr_absent; -/* zone is empty, we don't have any absent pages */ if (zone_start_pfn == zone_end_pfn)return 0 ; - nr_absent =__absent_pages_in_range (nid, zone_start_pfn, zone_end_pfn); - -/* -* ZONE_MOVABLE handling. -* Treat pages to be ZONE_MOVABLE in ZONE_NORMAL as absent pages -* and vice versa. -*/ -if (mirrored_kernelcore && zone_movable_pfn[nid]) { -unsigned long start_pfn, end_pfn; -struct memblock_region *r; - -for_each_mem_region (r) { - start_pfn =clamp (memblock_region_memory_base_pfn (r), - zone_start_pfn, zone_end_pfn); - end_pfn =clamp (memblock_region_memory_end_pfn (r), - zone_start_pfn, zone_end_pfn); - -if (zone_type ==ZONE_MOVABLE && -memblock_is_mirror (r)) - nr_absent += end_pfn - start_pfn; - -if (zone_type ==ZONE_NORMAL && - !memblock_is_mirror (r)) - nr_absent += end_pfn - start_pfn; - } - } - -return nr_absent; +return __absent_pages_in_range (nid, zone_start_pfn, zone_end_pfn); }/*
Signature · 1 line
2.53.0
Re: [PATCH v2 1/2] mm/mm_init: don't overlap NORMAL and MOVABLE zones with kernelcore=mirror
Quoted 9 lines · Mike Rapoport
From: "Mike Rapoport (Microsoft)" <[email protected]>
When kernelcore or movablecore kernel parameters define size of the NORMAL and MOVABLE zones as percents of the total memory or by absolute value,
ZONE_NORMALis clamped at the beginning ofZONE_MOVABLE.However, when kernelcore=mirror the
ZONE_NORMALspan is not changed but rather pages fromZONE_MOVABLEcounted as absent inZONE_NORMAL.
Quoted 7 lines
Make the behaviour of kernelcore= parameter uniform and treat mirror just as another way to size the zones.
Co-developed-by Wei Yang <[email protected]>Signed-off-by Wei Yang <[email protected]>Signed-off-by Mike Rapoport (Microsoft) <[email protected]>---
Signature · 3 lines
Cheers, David
Mike Rapoport
maintainerPATCH v2 2/2 mm/mm_init: drop overlap_memmap_init()
In reply to Mike RapoportFrom: "Mike Rapoport (Microsoft)" <[email protected]>
When ZONE_NORMAL and ZONE_MOVABLE could overlap because kernelcore=mirror didn't reduce the span of ZONE_NORMAL, initialization of the memory map had to skip overlapping pages during initialization of ZONE_MOVABLE to avoid double initialization of the same struct pages.
Since kernelcore=mirror works now the same way as other variants of kernelcore=/movablecore=, and adjusts the span of ZONE_NORMAL, there can't be an overlap between ZONE_NORMAL and ZONE_MOVABLE.
Remove overlap_memmap_init().
--- mm/mm_init.c | 24 ------------------------ 1 file changed, 24 deletions(-)
mm/mm_init.c +0 -24
@@ -799,28 +799,6 @@ void __meminit init_deferred_page(unsigned long pfn, int nid)__init_deferred_page (pfn, nid); } -/* If zone is ZONE_MOVABLE but memory is mirrored, it is an overlapped init */ -static bool __meminit -overlap_memmap_init (unsigned long zone,unsigned long *pfn) -{ -static struct memblock_region *r__meminitdata ; - -if (mirrored_kernelcore && zone ==ZONE_MOVABLE ) { -if (!r || *pfn >=memblock_region_memory_end_pfn (r)) { -for_each_mem_region (r) { -if (*pfn <memblock_region_memory_end_pfn (r)) -break ; - } - } -if (*pfn >=memblock_region_memory_base_pfn (r) && -memblock_is_mirror (r)) { - *pfn =memblock_region_memory_end_pfn (r); -return true; - } - } -return false; -} -/* * Only struct pages that correspond to ranges defined by memblock.memory * are zeroed and initialized by going through __init_single_page() during
@@ -907,8 +885,6 @@ void __meminit memmap_init_range(unsigned long size, int nid, unsigned long zone* function. They do not exist on hotplugged memory. */ if (context ==MEMINIT_EARLY ) { -if (overlap_memmap_init (zone, &pfn)) -continue ;if (defer_init (nid, pfn, zone_end_pfn)) { deferred_struct_pages = true;break ;
Signature · 1 line
2.53.0
Re: [PATCH v2 2/2] mm/mm_init: drop overlap_memmap_init()
Quoted 11 lines · Mike Rapoport
From: "Mike Rapoport (Microsoft)" <[email protected]>
When
ZONE_NORMALandZONE_MOVABLEcould overlap because kernelcore=mirror didn't reduce the span ofZONE_NORMAL, initialization of the memory map had to skip overlapping pages during initialization ofZONE_MOVABLEto avoid double initialization of the same struct pages.Since kernelcore=mirror works now the same way as other variants of kernelcore=/movablecore=, and adjusts the span of
ZONE_NORMAL, there can't be an overlap betweenZONE_NORMALandZONE_MOVABLE.
Quoted 6 lines
Remove
overlap_memmap_init().Co-developed-by Wei Yang <[email protected]>Signed-off-by Wei Yang <[email protected]>Signed-off-by Mike Rapoport (Microsoft) <[email protected]>---
Signature · 3 lines
Cheers, David