Re: [PATCH v8 12/17] x86/e820: temporarily enable KHO scratch for memory below 1M

Pratyush Yadav
2025-11-25T14:39:41Z

On Tue, Nov 25 2025, Usama Arif wrote:

> On 25/11/2025 13:15, Pratyush Yadav wrote:
>> On Mon, Nov 24 2025, Usama Arif wrote:
>>
>>> On 09/05/2025 08:46, Changyuan Lyu wrote:
>>>> From: Alexander Graf <graf@amazon.com>
>>>>
>>>> KHO kernels are special and use only scratch memory for memblock
>>>> allocations, but memory below 1M is ignored by kernel after early boot
>>>> and cannot be naturally marked as scratch.
>>>>
>>>> To allow allocation of the real-mode trampoline and a few (if any) other
>>>> very early allocations from below 1M forcibly mark the memory below 1M
>>>> as scratch.
>>>>
>>>> After real mode trampoline is allocated, clear that scratch marking.
>>>>
>>>> Signed-off-by: Alexander Graf <graf@amazon.com>
[...]
>> Anyway, you do indeed point at a bug. memblock_mark_kho_scratch() should
>> only be called on a KHO boot, not unconditionally. So even with
>> CONFIG_MEMBLOCK_KHO_SCRATCH enabled, this should only be called on a KHO
>> boot, not every time.
>>
>> I think the below diff should fix the warning for you by making sure the
>> scratch areas are not present on non-KHO boot. I still don't know why
>> you hit the warning in the first place though. If you'd be willing to
>> dig deeper into that, it would be great.
>>
>> Can you give the below a try and if it fixes the problem for you I can
>> send it on the list.
>
> Is there a reason for compiling this code with is_kho_boot, when we have disabled
> KEXEC_HANDOVER and dont want this in? i.e. why not just ifdef it with MEMBLOCK_KHO_SCRATCH
> when that defconfig is designed for it?

is_kho_boot() will always be false when CONFIG_KEXEC_HANDOVER is not
enabled. So the compiler should optimize this out.

Only using the ifdef is not enough. Just because the config is enabled
doesn't mean every boot will be a KHO boot. You can do regular reboots
or even regular kexec, without ever having KHO involved. We only want to
call this for a KHO boot. So a runtime check is needed anyway.

>
>>
>> diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
>> index c3acbd26408ba..0a34dc011bf91 100644
>> --- a/arch/x86/kernel/e820.c
>> +++ b/arch/x86/kernel/e820.c
>> @@ -16,6 +16,7 @@
>> #include <linux/firmware-map.h>
>> #include <linux/sort.h>
>> #include <linux/memory_hotplug.h>
>> +#include <linux/kexec_handover.h>
>>
>> #include <asm/e820/api.h>
>> #include <asm/setup.h>
>> @@ -1315,7 +1316,8 @@ void __init e820__memblock_setup(void)
>> * After real mode trampoline is allocated, we clear that scratch
>> * marking.
>> */
>> - memblock_mark_kho_scratch(0, SZ_1M);
>> + if (is_kho_boot())
>> + memblock_mark_kho_scratch(0, SZ_1M);
>>
>> /*
>> * 32-bit systems are limited to 4BG of memory even with HIGHMEM and
>> diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
>> index 88be32026768c..4e9b4dff17216 100644
>> --- a/arch/x86/realmode/init.c
>> +++ b/arch/x86/realmode/init.c
>> @@ -4,6 +4,7 @@
>> #include <linux/memblock.h>
>> #include <linux/cc_platform.h>
>> #include <linux/pgtable.h>
>> +#include <linux/kexec_handover.h>
>>
>> #include <asm/set_memory.h>
>> #include <asm/realmode.h>
>> @@ -67,7 +68,8 @@ void __init reserve_real_mode(void)
>> */
>> memblock_reserve(0, SZ_1M);
>>
>> - memblock_clear_kho_scratch(0, SZ_1M);
>> + if (is_kho_boot())
>> + memblock_clear_kho_scratch(0, SZ_1M);
>> }
>>
>> static void __init sme_sev_setup_real_mode(struct trampoline_header *th)
>>
>>
>

--
Regards,
Pratyush Yadav