RE: [PATCH v5 1/5] mm: move mirrored memory overlap checking to the outer loop

From: Liu, Yuan1

Date: Tue Jun 02 2026 - 04:01:22 EST


> -----Original Message-----
> From: Wei Yang <richard.weiyang@xxxxxxxxx>
> Sent: Monday, May 25, 2026 4:36 PM
> To: Liu, Yuan1 <yuan1.liu@xxxxxxxxx>
> Cc: Wei Yang <richard.weiyang@xxxxxxxxx>; David Hildenbrand
> <david@xxxxxxxxxx>; Oscar Salvador <osalvador@xxxxxxx>; Mike Rapoport
> <rppt@xxxxxxxxxx>; linux-mm@xxxxxxxxx; Hu, Yong <yong.hu@xxxxxxxxx>; Zou,
> Nanhai <nanhai.zou@xxxxxxxxx>; Tim Chen <tim.c.chen@xxxxxxxxxxxxxxx>;
> Zhuo, Qiuxu <qiuxu.zhuo@xxxxxxxxx>; Chen, Yu C <yu.c.chen@xxxxxxxxx>;
> Deng, Pan <pan.deng@xxxxxxxxx>; Li, Tianyou <tianyou.li@xxxxxxxxx>; Chen
> Zhang <zhangchen.kidd@xxxxxx>; Zeng, Jason <jason.zeng@xxxxxxxxx>; linux-
> kernel@xxxxxxxxxxxxxxx
> Subject: Re: [PATCH v5 1/5] mm: move mirrored memory overlap checking to
> the outer loop
>
> On Fri, May 22, 2026 at 07:43:38AM +0000, Liu, Yuan1 wrote:
> >> Subject: Re: [PATCH v5 1/5] mm: move mirrored memory overlap checking
> to
> >> the outer loop
> >>
> >> On Wed, May 20, 2026 at 05:34:53AM -0400, Yuan Liu wrote:
> >> >Move the overlap memmap initialization check from memmap_init_range()
> >> >to memmap_init(), and replace the per-PFN check with a memblock-based
> >> >check.
> >>
> >> The description is a little simple.
> >>
> >> Even I know the purpose, I feel confused at the first glance.
> >
> >Thanks for the review.
> >I will try to rephrase it and provide a clearer description in the next
> version.
> >
> >> >
> >> >Reviewed-by: Wei Yang <richard.weiyang@xxxxxxxxx>
> >> >Reviewed-by: Jason Zeng <jason.zeng@xxxxxxxxx>
> >> >Signed-off-by: Yuan Liu <yuan1.liu@xxxxxxxxx>
> >> >---
> >> > mm/mm_init.c | 29 +++++------------------------
> >> > 1 file changed, 5 insertions(+), 24 deletions(-)
> >> >
> >> >diff --git a/mm/mm_init.c b/mm/mm_init.c
> >> >index f9f8e1af921c..24e103a402b0 100644
> >> >--- a/mm/mm_init.c
> >> >+++ b/mm/mm_init.c
> >> >@@ -783,28 +783,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
> >> >@@ -891,8 +869,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;
> >> >@@ -956,6 +932,7 @@ static void __init memmap_init(void)
> >> > int i, j, zone_id = 0, nid;
> >> >
> >> > for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid)
> >> {
> >> >+ struct memblock_region *r = &memblock.memory.regions[i];
> >> > struct pglist_data *node = NODE_DATA(nid);
> >> >
> >> > for (j = 0; j < MAX_NR_ZONES; j++) {
> >> >@@ -964,6 +941,10 @@ static void __init memmap_init(void)
> >> > if (!populated_zone(zone))
> >> > continue;
> >> >
> >> >+ if (mirrored_kernelcore && j == ZONE_MOVABLE &&
> >> >+ memblock_is_mirror(r))
> >> >+ continue;
> >> >+
> >>
> >> So you have figured out the memory layout of mirror memory?
> >>
> >> Would you mind elaborate?
> >
> >I have a Xeon server, collected mirror memory layout information as below
> by using follow changes:
> >
> >int __init_memblock memblock_mark_mirror(phys_addr_t base, phys_addr_t
> size)
> > {
> >- if (!mirrored_kernelcore)
> >+ int ret;
> >+ phys_addr_t end = base + size - 1;
> >+
> >+ pr_info("memblock_mark_mirror: base=%pa, size=%pa,
> mirrored_kernelcore=%d\n",
> >+ &base, &size, mirrored_kernelcore);
> >+
> >+ if (!mirrored_kernelcore) {
> >+ pr_info("memblock_mark_mirror: mirrored_kernelcore not
> enabled, skipping\n");
> > return 0;
> >+ }
> >
> > system_has_some_mirror = true;
> >
> >- return memblock_setclr_flag(&memblock.memory, base, size, 1,
> MEMBLOCK_MIRROR);
> >+ ret = memblock_setclr_flag(&memblock.memory, base, size, 1,
> MEMBLOCK_MIRROR);
> >+ pr_info("memblock_mark_mirror: marked [%pa-%pa] as MIRROR,
> ret=%d\n",
> >+ &base, &end, ret);
> >+ return ret;
> > }
> >
> >Here is the detailed layout information:
> >
>
> Thanks for the detailed output.
>
> After some investigation, I got two things to discuss here:
>
> * current mirror memory would disable memmap defer init
> * confirm the mirror memory layout and may simplify handling
>
> Before discussion, let me mark the key point in the output below.
>
> >Case 1: efibootmgr -m t -M 0
> >Enable mirror memory below 4GB, and no mirror memory above 4G
> >
> >=== zoneinfo summary ===
> >node zone start_pfn end_pfn start_addr end_addr
> >------ ---------- ------------ ------------ ------------------ ----------
> ---
> >0 DMA 0x1 0xfff 0x1000 0xffffff
> >0 DMA32 0x1000 0xfffff 0x1000000 0xffffffff
> >0 Normal 0x100000 0x7fbffff 0x100000000
> 0x7fbfffffff
> >0 Movable 0x140000 0x7fbffff 0x140000000
> 0x7fbfffffff
>
> (1) Normal and Movable zone end with the same address, so overlapped.
>
> >1 Normal 0x7fc0000 0xff7ffff 0x7fc0000000
> 0xff7fffffff
> >1 Movable 0x8000000 0xff7ffff 0x8000000000
> 0xff7fffffff
>
> The same as (1).
>
> >
> >node start end size flags
> mirror pfn_range
> >---- -------------------- -------------------- ------------ ------------
> --- -------- ------------------
> >0 0x0000000000001000 0x000000000009dfff 0x000000000009d000 0x2
> yes 0x1-0x9e
> >0 0x000000000009f000 0x000000000009ffff 0x0000000000001000 0x2
> yes 0x9f-0xa0
> >0 0x0000000000100000 0x0000000066416fff 0x0000000066317000 0x2
> yes 0x100-0x66417
> >0 0x00000000777ff000 0x00000000777fffff 0x0000000000001000 0x2
> yes 0x777ff-0x77800
> >0 0x0000000100000000 0x000000013fffffff 0x0000000040000000 0x2
> yes 0x100000-0x140000
>
> (2) You mentioned no mirror memory above 4G. If my understanding is
> correct, 4G's
> address is 0x100000000. So why this range is marked mirror? Is there some
> limitation for this?

Hi Wei

efibootmgr enables mirror memory below 4 GB through the -m (--mirror-below-4G)
option, and configures the percentage of memory to be mirrored above 4 GB through
the -M (--mirror-above-4G) option.

My understanding is that the layout of mirrored memory is determined by the BIOS.