FAILED: patch "[PATCH] mm: Always release pages to the buddy allocator in" failed to apply to 5.15-stable tree
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
Possible dependencies:
115d9d77bb0f ("mm: Always release pages to the buddy allocator in memblock_free_late().") 16802e55dea9 ("memblock tests: Add skeleton of the memblock simulator")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 115d9d77bb0f9152c60b6e8646369fa7f6167593 Mon Sep 17 00:00:00 2001
From: Aaron Thompson <[email protected]>
Date: Fri, 6 Jan 2023 22:22:44 +0000
Subject: [PATCH] mm: Always release pages to the buddy allocator in
memblock_free_late().
If CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled, memblock_free_pages() only releases pages to the buddy allocator if they are not in the deferred range. This is correct for free pages (as defined by for_each_free_mem_pfn_range_in_zone()) because free pages in the deferred range will be initialized and released as part of the deferred init process. memblock_free_pages() is called by memblock_free_late(), which is used to free reserved ranges after memblock_free_all() has run. All pages in reserved ranges have been initialized at that point, and accordingly, those pages are not touched by the deferred init process. This means that currently, if the pages that memblock_free_late() intends to release are in the deferred range, they will never be released to the buddy allocator. They will forever be reserved.
In addition, memblock_free_pages() calls kmsan_memblock_free_pages(), which is also correct for free pages but is not correct for reserved pages. KMSAN metadata for reserved pages is initialized by kmsan_init_shadow(), which runs shortly before memblock_free_all().
For both of these reasons, memblock_free_pages() should only be called for free pages, and memblock_free_late() should call __free_pages_core() directly instead.
One case where this issue can occur in the wild is EFI boot on x86_64. The x86 EFI code reserves all EFI boot services memory ranges via memblock_reserve() and frees them later via memblock_free_late() (efi_reserve_boot_services() and efi_free_boot_services(), respectively). If any of those ranges happens to fall within the deferred init range, the pages will not be released and that memory will be unavailable.
For example, on an Amazon EC2 t3.micro VM (1 GB) booting via EFI:
v6.2-rc2:
# grep -E 'Node|spanned|present|managed' /proc/zoneinfo
Node 0, zone DMA
spanned 4095
present 3999
managed 3840
Node 0, zone DMA32
spanned 246652
present 245868
managed 178867v6.2-rc2 + patch:
# grep -E 'Node|spanned|present|managed' /proc/zoneinfo
Node 0, zone DMA
spanned 4095
present 3999
managed 3840
Node 0, zone DMA32
spanned 246652
present 245868
managed 222816 # +43,949 pagesmm/memblock.c +7 -1
@@ -1640,7 +1640,13 @@ void __init memblock_free_late(phys_addr_t base, phys_addr_t size) end =PFN_DOWN (base + size);for (; cursor < end; cursor++) { -memblock_free_pages (pfn_to_page (cursor), cursor,0 ); +/* +* Reserved pages are always initialized by the end of +* memblock_free_all() (by memmap_init() and, if deferred +* initialization is enabled, memmap_init_reserved_pages()), so +* these pages can be released directly to the buddy allocator. +*/ +__free_pages_core (pfn_to_page (cursor),0 );totalram_pages_inc (); } }
tools/testing/memblock/internal.h +4 -0
@@ -15,6 +15,10 @@ bool mirrored_kernelcore = false;struct page {}; +void __free_pages_core (struct page *page,unsigned int order) +{ +} +void memblock_free_pages (struct page *page,unsigned long pfn,unsigned int order) {
Mike Rapoport
maintainerQuoted 5 lines · On Sat, Jan 14, 2023 at 05:45:53PM +0100, [email protected] wrote:
The patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
The patch below applies to 5.15, 5.10 and 5.4.
As for 4.19 and 4.14, they still have bootmem/nobootmem so I'd rather wouldn't touch them.
From c292bd7e64214fcc78b7c72a9ccd3973dd19b7fb Mon Sep 17 00:00:00 2001
From: Aaron Thompson <[email protected]>
Date: Fri, 6 Jan 2023 22:22:44 +0000
Subject: [PATCH] mm: Always release pages to the buddy allocator in
memblock_free_late().
If CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled, memblock_free_pages() only releases pages to the buddy allocator if they are not in the deferred range. This is correct for free pages (as defined by for_each_free_mem_pfn_range_in_zone()) because free pages in the deferred range will be initialized and released as part of the deferred init process. memblock_free_pages() is called by memblock_free_late(), which is used to free reserved ranges after memblock_free_all() has run. All pages in reserved ranges have been initialized at that point, and accordingly, those pages are not touched by the deferred init process. This means that currently, if the pages that memblock_free_late() intends to release are in the deferred range, they will never be released to the buddy allocator. They will forever be reserved.
In addition, memblock_free_pages() calls kmsan_memblock_free_pages(), which is also correct for free pages but is not correct for reserved pages. KMSAN metadata for reserved pages is initialized by kmsan_init_shadow(), which runs shortly before memblock_free_all().
For both of these reasons, memblock_free_pages() should only be called for free pages, and memblock_free_late() should call __free_pages_core() directly instead.
One case where this issue can occur in the wild is EFI boot on x86_64. The x86 EFI code reserves all EFI boot services memory ranges via memblock_reserve() and frees them later via memblock_free_late() (efi_reserve_boot_services() and efi_free_boot_services(), respectively). If any of those ranges happens to fall within the deferred init range, the pages will not be released and that memory will be unavailable.
For example, on an Amazon EC2 t3.micro VM (1 GB) booting via EFI:
v6.2-rc2:
# grep -E 'Node|spanned|present|managed' /proc/zoneinfo
Node 0, zone DMA
spanned 4095
present 3999
managed 3840
Node 0, zone DMA32
spanned 246652
present 245868
managed 178867v6.2-rc2 + patch:
# grep -E 'Node|spanned|present|managed' /proc/zoneinfo
Node 0, zone DMA
spanned 4095
present 3999
managed 3840
Node 0, zone DMA32
spanned 246652
present 245868
managed 222816 # +43,949 pages--- mm/memblock.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
mm/memblock.c +7 -1
@@ -1615,7 +1615,13 @@ void __init __memblock_free_late(phys_addr_t base, phys_addr_t size) end =PFN_DOWN (base + size);for (; cursor < end; cursor++) { -memblock_free_pages (pfn_to_page (cursor), cursor,0 ); +/* +* Reserved pages are always initialized by the end of +* memblock_free_all() (by memmap_init() and, if deferred +* initialization is enabled, memmap_init_reserved_pages()), so +* these pages can be released directly to the buddy allocator. +*/ +__free_pages_core (pfn_to_page (cursor),0 );totalram_pages_inc (); } }
Signature · 1 line
2.35.1
Quoted 4 lines
thanks,
greg k-h
Signature · 2 lines
Sincerely yours, Mike.
Quoted 8 lines · Mike Rapoport
Quoted 5 lines · On Sat, Jan 14, 2023 at 05:45:53PM +0100, [email protected] wrote:
The patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.The patch below applies to 5.15, 5.10 and 5.4.
Thanks Mike. The code works as intended, but the commit message and the comments have some inaccuracies (changed function names, no KMSAN). Does that matter? I can send updated patches if so, just let me know.
Quoted 93 lines
As for 4.19 and 4.14, they still have bootmem/nobootmem so I'd rather wouldn't touch them.
From
c292bd7e64214fcc78b7c72a9ccd3973dd19b7fbMon Sep 17 00:00:00 2001
From: Aaron Thompson <[email protected]>
Date: Fri, 6 Jan 2023 22:22:44 +0000
Subject: [PATCH] mm: Always release pages to the buddy allocator in
memblock_free_late().If
CONFIG_DEFERRED_STRUCT_PAGE_INITis enabled,memblock_free_pages()only releases pages to the buddy allocator if they are not in the deferred range. This is correct for free pages (as defined byfor_each_free_mem_pfn_range_in_zone()) because free pages in the deferred range will be initialized and released as part of the deferred init process.memblock_free_pages()is called bymemblock_free_late(), which is used to free reserved ranges aftermemblock_free_all()has run. All pages in reserved ranges have been initialized at that point, and accordingly, those pages are not touched by the deferred init process. This means that currently, if the pages thatmemblock_free_late()intends to release are in the deferred range, they will never be released to the buddy allocator. They will forever be reserved.In addition,
memblock_free_pages()callskmsan_memblock_free_pages(), which is also correct for free pages but is not correct for reserved pages. KMSAN metadata for reserved pages is initialized bykmsan_init_shadow(), which runs shortly beforememblock_free_all().For both of these reasons,
memblock_free_pages()should only be called for free pages, andmemblock_free_late()should call__free_pages_core()directly instead.One case where this issue can occur in the wild is EFI boot on
x86_64. The x86 EFI code reserves all EFI boot services memory ranges viamemblock_reserve()and frees them later viamemblock_free_late()(efi_reserve_boot_services()andefi_free_boot_services(), respectively). If any of those ranges happens to fall within the deferred init range, the pages will not be released and that memory will be unavailable.For example, on an Amazon EC2 t3.micro VM (1 GB) booting via EFI:
v6.2-rc2:
# grep -E 'Node|spanned|present|managed' /proc/zoneinfo Node 0, zone DMA spanned 4095 present 3999 managed 3840 Node 0, zone DMA32 spanned 246652 present 245868 managed 178867v6.2-rc2 + patch:
# grep -E 'Node|spanned|present|managed' /proc/zoneinfo Node 0, zone DMA spanned 4095 present 3999 managed 3840 Node 0, zone DMA32 spanned 246652 present 245868 managed 222816 # +43,949 pagesFixes 3a80a7fa7989 ("mm: meminit: initialise a subset of struct pagesif
CONFIG_DEFERRED_STRUCT_PAGE_INITis set")Signed-off-by Aaron Thompson <[email protected]>Signed-off-by Mike Rapoport (IBM) <[email protected]>--- mm/memblock.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)mm/memblock.c +7
-1@@ -1615,7 +1615,13 @@ void __init __memblock_free_late(phys_addr_t base, phys_addr_t size) end =PFN_DOWN (base + size);for (; cursor < end; cursor++) { -memblock_free_pages (pfn_to_page (cursor), cursor,0 ); +/* +* Reserved pages are always initialized by the end of +* memblock_free_all() (by memmap_init() and, if deferred +* initialization is enabled, memmap_init_reserved_pages()), so +* these pages can be released directly to the buddy allocator. +*/ +__free_pages_core (pfn_to_page (cursor),0 );totalram_pages_inc (); }
Quoted 9 lines
}
--
2.35.1Quoted 4 lines
thanks,
greg k-h
Thanks,
-- Aaron
Mike Rapoport
maintainerQuoted 11 lines · Aaron Thompson
Quoted 9 lines · Mike Rapoport
Quoted 6 lines · On Sat, Jan 14, 2023 at 05:45:53PM +0100, [email protected] wrote:
The patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit
id to <[email protected]>.
Quoted 5 lines
Quoted 1 line
The patch below applies to 5.15, 5.10 and 5.4.
Thanks Mike. The code works as intended, but the commit message and the comments have some inaccuracies (changed function names, no KMSAN). Does that matter? I can send updated patches if so, just let me know.
It's up to stable folks, I think.
Greg?
Quoted 105 lines
Quoted 93 lines
As for 4.19 and 4.14, they still have bootmem/nobootmem so I'd rather wouldn't touch them.
From
c292bd7e64214fcc78b7c72a9ccd3973dd19b7fbMon Sep 17 00:00:00 2001
From: Aaron Thompson <[email protected]>
Date: Fri, 6 Jan 2023 22:22:44 +0000
Subject: [PATCH] mm: Always release pages to the buddy allocator in
memblock_free_late().If
CONFIG_DEFERRED_STRUCT_PAGE_INITis enabled,memblock_free_pages()only releases pages to the buddy allocator if they are not in the deferred range. This is correct for free pages (as defined byfor_each_free_mem_pfn_range_in_zone()) because free pages in the deferred range will be initialized and released as part of the deferred init process.memblock_free_pages()is called bymemblock_free_late(), which is used to free reserved ranges aftermemblock_free_all()has run. All pages in reserved ranges have been initialized at that point, and accordingly, those pages are not touched by the deferred init process. This means that currently, if the pages thatmemblock_free_late()intends to release are in the deferred range, they will never be released to the buddy allocator. They will forever be reserved.In addition,
memblock_free_pages()callskmsan_memblock_free_pages(), which is also correct for free pages but is not correct for reserved pages. KMSAN metadata for reserved pages is initialized bykmsan_init_shadow(), which runs shortly beforememblock_free_all().For both of these reasons,
memblock_free_pages()should only be called for free pages, andmemblock_free_late()should call__free_pages_core()directly instead.One case where this issue can occur in the wild is EFI boot on
x86_64. The x86 EFI code reserves all EFI boot services memory ranges viamemblock_reserve()and frees them later viamemblock_free_late()(efi_reserve_boot_services()andefi_free_boot_services(), respectively). If any of those ranges happens to fall within the deferred init range, the pages will not be released and that memory will be unavailable.For example, on an Amazon EC2 t3.micro VM (1 GB) booting via EFI:
v6.2-rc2:
# grep -E 'Node|spanned|present|managed' /proc/zoneinfo Node 0, zone DMA spanned 4095 present 3999 managed 3840 Node 0, zone DMA32 spanned 246652 present 245868 managed 178867v6.2-rc2 + patch:
# grep -E 'Node|spanned|present|managed' /proc/zoneinfo Node 0, zone DMA spanned 4095 present 3999 managed 3840 Node 0, zone DMA32 spanned 246652 present 245868 managed 222816 # +43,949 pagesFixes 3a80a7fa7989 ("mm: meminit: initialise a subset of struct pagesif
CONFIG_DEFERRED_STRUCT_PAGE_INITis set")Signed-off-by Aaron Thompson <[email protected]>Signed-off-by Mike Rapoport (IBM) <[email protected]>--- mm/memblock.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)mm/memblock.c +7
-1@@ -1615,7 +1615,13 @@ void __init __memblock_free_late(phys_addr_t base, phys_addr_t size) end =PFN_DOWN (base + size);for (; cursor < end; cursor++) { -memblock_free_pages (pfn_to_page (cursor), cursor,0 ); +/* +* Reserved pages are always initialized by the end of +* memblock_free_all() (by memmap_init() and, if deferred +* initialization is enabled, memmap_init_reserved_pages()), so +* these pages can be released directly to the buddy allocator. +*/ +__free_pages_core (pfn_to_page (cursor),0 );totalram_pages_inc (); }Quoted 9 lines
}
--
2.35.1Quoted 4 lines
thanks,
greg k-h
Thanks,
-- Aaron
Signature · 2 lines
Sincerely yours, Mike.