* [PATCH] memblock: fix page count when preserving reserve_mem regions
@ 2026-09-01 16:52 Sang-Heon Jeon
2026-09-01 18:49 ` Mike Rapoport
0 siblings, 1 reply; 3+ messages in thread
From: Sang-Heon Jeon @ 2026-09-01 16:52 UTC (permalink / raw)
To: Andrew Morton, Mike Rapoport; +Cc: Jason Gunthorpe, linux-mm, Pratyush Yadav
When map->start or map->size is not page aligned,
reserved_mem_preserve() does not preserve the last pages of the region
from map->start to map->start + map->size.
After kexec the new kernel reserves only the preserved pages, so the
last pages are released to the buddy allocator. But
reserve_mem_find_by_name() still returns the whole region including the
last pages, so they can be allocated while the subsystem is still using
them.
Preserve every page the region spans so the new kernel reserves all of
it.
Fixes: 8375b76517cb ("kho: replace kho_preserve_phys() with kho_preserve_pages()")
Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com>
---
QEMU-based test results
- Booted with "memblock=debug kho=on reserve_mem=5000:64:oops"
# kexec -s -l /bzImage --initrd=/initramfs.gz --reuse-cmdline
# kexec -e
# dmesg | grep kho_preserved_memory_reserve
1) AS-IS (before fix)
[ 0.188536] __memblock_reserve: [0x000000013ffee000-0x000000013ffeefff] nid=-1 flags=0 kho_preserved_memory_reserve+0x3d/0x70
2) TO-BE (after fix)
[ 0.076935] __memblock_reserve: [0x000000013ffee000-0x000000013ffeffff] nid=-1 flags=0 kho_preserved_memory_reserve+0x3d/0x70
mm/memblock.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/mm/memblock.c b/mm/memblock.c
index 777c69f05400..a17b1cccaf3d 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -2534,7 +2534,8 @@ static int __init reserved_mem_preserve(void)
for (unsigned int i = 0; i < reserved_mem_count; i++, nr_preserved++) {
struct reserve_mem_table *map = &reserved_mem_table[i];
struct page *page = phys_to_page(map->start);
- unsigned int nr_pages = map->size >> PAGE_SHIFT;
+ unsigned int nr_pages = PFN_UP(map->start + map->size) -
+ PFN_DOWN(map->start);
err = kho_preserve_pages(page, nr_pages);
if (err)
@@ -2547,7 +2548,8 @@ static int __init reserved_mem_preserve(void)
for (unsigned int i = 0; i < nr_preserved; i++) {
struct reserve_mem_table *map = &reserved_mem_table[i];
struct page *page = phys_to_page(map->start);
- unsigned int nr_pages = map->size >> PAGE_SHIFT;
+ unsigned int nr_pages = PFN_UP(map->start + map->size) -
+ PFN_DOWN(map->start);
kho_unpreserve_pages(page, nr_pages);
}
base-commit: dde94c26af59f5020adafafa08ece21ccd32590b
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] memblock: fix page count when preserving reserve_mem regions 2026-09-01 16:52 [PATCH] memblock: fix page count when preserving reserve_mem regions Sang-Heon Jeon @ 2026-09-01 18:49 ` Mike Rapoport 2026-09-02 15:19 ` Sang-Heon Jeon 0 siblings, 1 reply; 3+ messages in thread From: Mike Rapoport @ 2026-09-01 18:49 UTC (permalink / raw) To: Sang-Heon Jeon; +Cc: Andrew Morton, Jason Gunthorpe, linux-mm, Pratyush Yadav Hi, On Wed, Sep 02, 2026 at 01:52:35AM +0900, Sang-Heon Jeon wrote: > When map->start or map->size is not page aligned, > reserved_mem_preserve() does not preserve the last pages of the region I believe it's the last page, not pages. > from map->start to map->start + map->size. > > After kexec the new kernel reserves only the preserved pages, so the > last pages are released to the buddy allocator. But > reserve_mem_find_by_name() still returns the whole region including the > last pages, so they can be allocated while the subsystem is still using > them. > > Preserve every page the region spans so the new kernel reserves all of > it. If there are two adjacent not page aligned reserve_mem regions, we'll preserve them twice, or worse unintentionally unpreserve one of them on error handling of another. I think it's better to restrict the reserve_mem alignment to PAGE_SIZE. > Fixes: 8375b76517cb ("kho: replace kho_preserve_phys() with kho_preserve_pages()") > Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com> > --- > > QEMU-based test results > > - Booted with "memblock=debug kho=on reserve_mem=5000:64:oops" > > # kexec -s -l /bzImage --initrd=/initramfs.gz --reuse-cmdline > # kexec -e > # dmesg | grep kho_preserved_memory_reserve > > 1) AS-IS (before fix) > [ 0.188536] __memblock_reserve: [0x000000013ffee000-0x000000013ffeefff] nid=-1 flags=0 kho_preserved_memory_reserve+0x3d/0x70 > > 2) TO-BE (after fix) > [ 0.076935] __memblock_reserve: [0x000000013ffee000-0x000000013ffeffff] nid=-1 flags=0 kho_preserved_memory_reserve+0x3d/0x70 > > mm/memblock.c | 6 ++++-- > 1 file changed, 4 insertions(+), 2 deletions(-) > > diff --git a/mm/memblock.c b/mm/memblock.c > index 777c69f05400..a17b1cccaf3d 100644 > --- a/mm/memblock.c > +++ b/mm/memblock.c > @@ -2534,7 +2534,8 @@ static int __init reserved_mem_preserve(void) > for (unsigned int i = 0; i < reserved_mem_count; i++, nr_preserved++) { > struct reserve_mem_table *map = &reserved_mem_table[i]; > struct page *page = phys_to_page(map->start); > - unsigned int nr_pages = map->size >> PAGE_SHIFT; > + unsigned int nr_pages = PFN_UP(map->start + map->size) - > + PFN_DOWN(map->start); > > err = kho_preserve_pages(page, nr_pages); > if (err) > @@ -2547,7 +2548,8 @@ static int __init reserved_mem_preserve(void) > for (unsigned int i = 0; i < nr_preserved; i++) { > struct reserve_mem_table *map = &reserved_mem_table[i]; > struct page *page = phys_to_page(map->start); > - unsigned int nr_pages = map->size >> PAGE_SHIFT; > + unsigned int nr_pages = PFN_UP(map->start + map->size) - > + PFN_DOWN(map->start); > > kho_unpreserve_pages(page, nr_pages); > } > > base-commit: dde94c26af59f5020adafafa08ece21ccd32590b > -- > 2.43.0 > -- Sincerely yours, Mike. ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] memblock: fix page count when preserving reserve_mem regions 2026-09-01 18:49 ` Mike Rapoport @ 2026-09-02 15:19 ` Sang-Heon Jeon 0 siblings, 0 replies; 3+ messages in thread From: Sang-Heon Jeon @ 2026-09-02 15:19 UTC (permalink / raw) To: Mike Rapoport; +Cc: Andrew Morton, Jason Gunthorpe, linux-mm, Pratyush Yadav Hi, On Wed, Sep 2, 2026 at 3:49 AM Mike Rapoport <rppt@kernel.org> wrote: > > Hi, > > On Wed, Sep 02, 2026 at 01:52:35AM +0900, Sang-Heon Jeon wrote: > > When map->start or map->size is not page aligned, > > reserved_mem_preserve() does not preserve the last pages of the region > > I believe it's the last page, not pages. If the reserve_mem region is [6KB..13KB] and PAGE_SIZE is 4KB, it spans three pages, but map->size >> PAGE_SHIFT is 1. Yeah, To be exact, the last one or two. > > from map->start to map->start + map->size. > > > > After kexec the new kernel reserves only the preserved pages, so the > > last pages are released to the buddy allocator. But > > reserve_mem_find_by_name() still returns the whole region including the > > last pages, so they can be allocated while the subsystem is still using > > them. > > > > Preserve every page the region spans so the new kernel reserves all of > > it. > > If there are two adjacent not page aligned reserve_mem regions, we'll > preserve them twice, or worse unintentionally unpreserve one of them on > error handling of another. Right, unexpected overlap could occur with this patch. Luckily, overlap doesn't seem to break the system in the existing code.. > I think it's better to restrict the reserve_mem alignment to PAGE_SIZE. I considered that direction as well. If it doesn't break existing users, I'm all for it. I'll send a v2 soon. Thanks for your review. > > Fixes: 8375b76517cb ("kho: replace kho_preserve_phys() with kho_preserve_pages()") > > Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com> > > --- > > > > QEMU-based test results > > > > - Booted with "memblock=debug kho=on reserve_mem=5000:64:oops" > > > > # kexec -s -l /bzImage --initrd=/initramfs.gz --reuse-cmdline > > # kexec -e > > # dmesg | grep kho_preserved_memory_reserve > > > > 1) AS-IS (before fix) > > [ 0.188536] __memblock_reserve: [0x000000013ffee000-0x000000013ffeefff] nid=-1 flags=0 kho_preserved_memory_reserve+0x3d/0x70 > > > > 2) TO-BE (after fix) > > [ 0.076935] __memblock_reserve: [0x000000013ffee000-0x000000013ffeffff] nid=-1 flags=0 kho_preserved_memory_reserve+0x3d/0x70 > > > > mm/memblock.c | 6 ++++-- > > 1 file changed, 4 insertions(+), 2 deletions(-) > > > > diff --git a/mm/memblock.c b/mm/memblock.c > > index 777c69f05400..a17b1cccaf3d 100644 > > --- a/mm/memblock.c > > +++ b/mm/memblock.c > > @@ -2534,7 +2534,8 @@ static int __init reserved_mem_preserve(void) > > for (unsigned int i = 0; i < reserved_mem_count; i++, nr_preserved++) { > > struct reserve_mem_table *map = &reserved_mem_table[i]; > > struct page *page = phys_to_page(map->start); > > - unsigned int nr_pages = map->size >> PAGE_SHIFT; > > + unsigned int nr_pages = PFN_UP(map->start + map->size) - > > + PFN_DOWN(map->start); > > > > err = kho_preserve_pages(page, nr_pages); > > if (err) > > @@ -2547,7 +2548,8 @@ static int __init reserved_mem_preserve(void) > > for (unsigned int i = 0; i < nr_preserved; i++) { > > struct reserve_mem_table *map = &reserved_mem_table[i]; > > struct page *page = phys_to_page(map->start); > > - unsigned int nr_pages = map->size >> PAGE_SHIFT; > > + unsigned int nr_pages = PFN_UP(map->start + map->size) - > > + PFN_DOWN(map->start); > > > > kho_unpreserve_pages(page, nr_pages); > > } > > > > base-commit: dde94c26af59f5020adafafa08ece21ccd32590b > > -- > > 2.43.0 > > > > -- > Sincerely yours, > Mike. Best regards, Sang-Heon Jeon ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-02 15:19 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-09-01 16:52 [PATCH] memblock: fix page count when preserving reserve_mem regions Sang-Heon Jeon 2026-09-01 18:49 ` Mike Rapoport 2026-09-02 15:19 ` Sang-Heon Jeon
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox