mm/memblock.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
The scratch memory for kexec handover is used to bootstrap the
kexec'ed kernel. It is only needed when CONFIG_MEMBLOCK_KHO_SCRATCH
is enabled (selected by KHO) and if it is a KHO boot. Add checks
to prevent marking a KHO scratch region unless needed.
kexec_handover.h is now unconditionally included for is_kho_boot.
Fixes: a2daf83e10378 ("x86/e820: temporarily enable KHO scratch for memory below 1M")
Reported-by: Vlad Poenaru <thevlad@meta.com>
Signed-off-by: Usama Arif <usamaarif642@gmail.com>
---
mm/memblock.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/mm/memblock.c b/mm/memblock.c
index e23e16618e9b3..5c85d575bb61c 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -20,8 +20,8 @@
#ifdef CONFIG_KEXEC_HANDOVER
#include <linux/libfdt.h>
-#include <linux/kexec_handover.h>
#endif /* CONFIG_KEXEC_HANDOVER */
+#include <linux/kexec_handover.h>
#include <asm/sections.h>
#include <linux/io.h>
@@ -1126,8 +1126,11 @@ int __init_memblock memblock_reserved_mark_noinit(phys_addr_t base, phys_addr_t
*/
__init int memblock_mark_kho_scratch(phys_addr_t base, phys_addr_t size)
{
- return memblock_setclr_flag(&memblock.memory, base, size, 1,
- MEMBLOCK_KHO_SCRATCH);
+ if (IS_ENABLED(CONFIG_MEMBLOCK_KHO_SCRATCH) && is_kho_boot())
+ return memblock_setclr_flag(&memblock.memory, base, size, 1,
+ MEMBLOCK_KHO_SCRATCH);
+ else
+ return 0;
}
/**
@@ -1140,8 +1143,11 @@ __init int memblock_mark_kho_scratch(phys_addr_t base, phys_addr_t size)
*/
__init int memblock_clear_kho_scratch(phys_addr_t base, phys_addr_t size)
{
- return memblock_setclr_flag(&memblock.memory, base, size, 0,
- MEMBLOCK_KHO_SCRATCH);
+ if (IS_ENABLED(CONFIG_MEMBLOCK_KHO_SCRATCH) && is_kho_boot())
+ return memblock_setclr_flag(&memblock.memory, base, size, 0,
+ MEMBLOCK_KHO_SCRATCH);
+ else
+ return 0;
}
static bool should_skip_region(struct memblock_type *type,
--
2.47.3
On Wed, Nov 26, 2025 at 07:20:51AM +0000, Usama Arif wrote:
> The scratch memory for kexec handover is used to bootstrap the
> kexec'ed kernel. It is only needed when CONFIG_MEMBLOCK_KHO_SCRATCH
> is enabled (selected by KHO) and if it is a KHO boot. Add checks
> to prevent marking a KHO scratch region unless needed.
>
> kexec_handover.h is now unconditionally included for is_kho_boot.
>
> Fixes: a2daf83e10378 ("x86/e820: temporarily enable KHO scratch for memory below 1M")
> Reported-by: Vlad Poenaru <thevlad@meta.com>
> Signed-off-by: Usama Arif <usamaarif642@gmail.com>
> ---
> mm/memblock.c | 16 +++++++++++-----
> 1 file changed, 11 insertions(+), 5 deletions(-)
>
> diff --git a/mm/memblock.c b/mm/memblock.c
> index e23e16618e9b3..5c85d575bb61c 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -20,8 +20,8 @@
>
> #ifdef CONFIG_KEXEC_HANDOVER
> #include <linux/libfdt.h>
> -#include <linux/kexec_handover.h>
> #endif /* CONFIG_KEXEC_HANDOVER */
> +#include <linux/kexec_handover.h>
>
> #include <asm/sections.h>
> #include <linux/io.h>
> @@ -1126,8 +1126,11 @@ int __init_memblock memblock_reserved_mark_noinit(phys_addr_t base, phys_addr_t
> */
> __init int memblock_mark_kho_scratch(phys_addr_t base, phys_addr_t size)
> {
> - return memblock_setclr_flag(&memblock.memory, base, size, 1,
> - MEMBLOCK_KHO_SCRATCH);
> + if (IS_ENABLED(CONFIG_MEMBLOCK_KHO_SCRATCH) && is_kho_boot())
> + return memblock_setclr_flag(&memblock.memory, base, size, 1,
> + MEMBLOCK_KHO_SCRATCH);
> + else
else is not needed.
> + return 0;
> }
>
> /**
> @@ -1140,8 +1143,11 @@ __init int memblock_mark_kho_scratch(phys_addr_t base, phys_addr_t size)
> */
> __init int memblock_clear_kho_scratch(phys_addr_t base, phys_addr_t size)
> {
> - return memblock_setclr_flag(&memblock.memory, base, size, 0,
> - MEMBLOCK_KHO_SCRATCH);
> + if (IS_ENABLED(CONFIG_MEMBLOCK_KHO_SCRATCH) && is_kho_boot())
> + return memblock_setclr_flag(&memblock.memory, base, size, 0,
> + MEMBLOCK_KHO_SCRATCH);
> + else
Ditto.
> + return 0;
> }
>
> static bool should_skip_region(struct memblock_type *type,
> --
> 2.47.3
>
--
Sincerely yours,
Mike.
On Wed, Nov 26, 2025 at 07:20:51AM +0000, Usama Arif wrote:
> @@ -1126,8 +1126,11 @@ int __init_memblock memblock_reserved_mark_noinit(phys_addr_t base, phys_addr_t
> */
> __init int memblock_mark_kho_scratch(phys_addr_t base, phys_addr_t size)
> {
> - return memblock_setclr_flag(&memblock.memory, base, size, 1,
> - MEMBLOCK_KHO_SCRATCH);
> + if (IS_ENABLED(CONFIG_MEMBLOCK_KHO_SCRATCH) && is_kho_boot())
It makes me wounder why CONFIG_MEMBLOCK_KHO_SCRATCH exists? It seems to
be a proxy for CONFIG_KEXEC_HANDOVER which is the only option that
selects it and does it always.
Can we make s/CONFIG_MEMBLOCK_KHO_SCRATCH/CONFIG_KEXEC_HANDOVER/ and
remove IS_ENABLED() from this check? Just is_kho_boot() is enough.
--
Kiryl Shutsemau / Kirill A. Shutemov
On 26/11/2025 10:40, Kiryl Shutsemau wrote:
> On Wed, Nov 26, 2025 at 07:20:51AM +0000, Usama Arif wrote:
>> @@ -1126,8 +1126,11 @@ int __init_memblock memblock_reserved_mark_noinit(phys_addr_t base, phys_addr_t
>> */
>> __init int memblock_mark_kho_scratch(phys_addr_t base, phys_addr_t size)
>> {
>> - return memblock_setclr_flag(&memblock.memory, base, size, 1,
>> - MEMBLOCK_KHO_SCRATCH);
>> + if (IS_ENABLED(CONFIG_MEMBLOCK_KHO_SCRATCH) && is_kho_boot())
>
> It makes me wounder why CONFIG_MEMBLOCK_KHO_SCRATCH exists? It seems to
> be a proxy for CONFIG_KEXEC_HANDOVER which is the only option that
> selects it and does it always.
>
> Can we make s/CONFIG_MEMBLOCK_KHO_SCRATCH/CONFIG_KEXEC_HANDOVER/ and
> remove IS_ENABLED() from this check? Just is_kho_boot() is enough.
>
>
Thats a very good point! I imagine it might have been for maybe debug purposes?
Looking at the code, CONFIG_MEMBLOCK_KHO_SCRATCH shouldnt be needed. I guess
this might be a good time to clean it up. If Mike is happy for it to be replaced
with CONFIG_KEXEC_HANDOVER (and removed where needed), happy to send that
for review instead of this.
Thanks
Usama
On Wed, Nov 26, 2025 at 11:43:21AM +0000, Usama Arif wrote:
>
> On 26/11/2025 10:40, Kiryl Shutsemau wrote:
> > On Wed, Nov 26, 2025 at 07:20:51AM +0000, Usama Arif wrote:
> >> @@ -1126,8 +1126,11 @@ int __init_memblock memblock_reserved_mark_noinit(phys_addr_t base, phys_addr_t
> >> */
> >> __init int memblock_mark_kho_scratch(phys_addr_t base, phys_addr_t size)
> >> {
> >> - return memblock_setclr_flag(&memblock.memory, base, size, 1,
> >> - MEMBLOCK_KHO_SCRATCH);
> >> + if (IS_ENABLED(CONFIG_MEMBLOCK_KHO_SCRATCH) && is_kho_boot())
> >
> > It makes me wounder why CONFIG_MEMBLOCK_KHO_SCRATCH exists? It seems to
> > be a proxy for CONFIG_KEXEC_HANDOVER which is the only option that
> > selects it and does it always.
> >
> > Can we make s/CONFIG_MEMBLOCK_KHO_SCRATCH/CONFIG_KEXEC_HANDOVER/ and
> > remove IS_ENABLED() from this check? Just is_kho_boot() is enough.
> >
> >
>
> Thats a very good point! I imagine it might have been for maybe debug purposes?
>
> Looking at the code, CONFIG_MEMBLOCK_KHO_SCRATCH shouldnt be needed. I guess
> this might be a good time to clean it up. If Mike is happy for it to be replaced
> with CONFIG_KEXEC_HANDOVER (and removed where needed), happy to send that
> for review instead of this.
Yeah, let's kill CONFIG_MEMBLOCK_KHO_SCRATCH and use CONFIG_KEXEC_HANDOVER
where needed.
IS_ENABLED() is not needed in the check because with
CONFIG_MEMBLOCK_KHO_SCRATCH=n both mark_kho_scratch() and
clear_kho_scratch() are empty stubs, so it's enough to check is_kho_boot().
> Thanks
> Usama
--
Sincerely yours,
Mike.
© 2016 - 2025 Red Hat, Inc.