[PATCH v3] LoongArch: kexec: use core control page for relocation trampoline to avoid QEMU FDT conflict

Huacai Chen chenhuacai at kernel.org
Mon Jun 29 07:06:17 PDT 2026


Hi, George,

On Thu, Jun 4, 2026 at 7:41 PM George Guo <dongtai.guo at linux.dev> wrote:
>
> From: George Guo <guodongtai at kylinos.cn>
>
> KEXEC_CONTROL_CODE was hardcoded to TO_CACHE(0x100000).  QEMU places its
> machine FDT at physical 0x100000 when booting with '-kernel', so
> machine_kexec_prepare() overwrote the FDT with the relocation trampoline.
> The kexec'd kernel's fdt_setup() then read trampoline code instead of a
> valid FDT, earlycon auto-detection failed, and the second kernel booted
> silently with no console output.
>
> The trampoline does not need a fixed address.  It is executed by the
> current kernel to relocate and enter the new kernel, and is dead once the
> new kernel starts.  Drop KEXEC_CONTROL_CODE and reuse the
> control_code_page that the kexec core already allocates (as arm64 and
> riscv do).  That page is excluded from the relocation copy and lives
> nowhere near 0x100000, so the QEMU FDT is left intact.
>
> Signed-off-by: George Guo <guodongtai at kylinos.cn>
> ---
> Changes in v3:
> - Only the relocation trampoline is moved off the hardcoded address onto
>   the core-allocated control_code_page.  v2 also moved the kernel command
>   line to a kexec control page, but as Huacai pointed out a control page
>   only avoids being clobbered by the relocation copy in the current
>   kernel; it is not reserved in the new kernel, which reads the command
>   line early in boot.  The command line therefore stays at the existing
>   fixed KEXEC_CMDLINE_ADDR in the reserved first 2MB (unchanged).
Then how to avoid the cmdline overlapping FDT, and how to avoid the
control page being corrupted by the new kernel?

Huacai

>
> Changes in v2:
> - Instead of moving KEXEC_CONTROL_CODE to a different fixed address, reuse
>   the kexec core's control_code_page for the trampoline.
>
> v2: https://lore.kernel.org/all/20260601033820.38805-1-dongtai.guo@linux.dev/
> v1: https://lore.kernel.org/all/20260528135828.196953-1-dongtai.guo@linux.dev/
>
>  arch/loongarch/kernel/machine_kexec.c | 21 ++++++++++++++++-----
>  1 file changed, 16 insertions(+), 5 deletions(-)
>
> diff --git a/arch/loongarch/kernel/machine_kexec.c b/arch/loongarch/kernel/machine_kexec.c
> index d7fafda1d541..3527da57234d 100644
> --- a/arch/loongarch/kernel/machine_kexec.c
> +++ b/arch/loongarch/kernel/machine_kexec.c
> @@ -21,8 +21,14 @@
>  #include <asm/cacheflush.h>
>  #include <asm/page.h>
>
> -/* 0x100000 ~ 0x200000 is safe */
> -#define KEXEC_CONTROL_CODE     TO_CACHE(0x100000UL)
> +/*
> + * The kexec'd kernel reads its command line from this pointer early in
> + * boot, so the command line must live in memory the new kernel will not
> + * reuse.  Keep it at a fixed address in the first 2MB, which both the
> + * current and the kexec'd kernel always keep reserved (see
> + * memblock_reserve(PHYS_OFFSET, 0x200000) in arch/loongarch/kernel/mem.c).
> + * 0x108000 does not overlap QEMU's machine FDT at 0x100000.
> + */
>  #define KEXEC_CMDLINE_ADDR     TO_CACHE(0x108000UL)
>
>  static unsigned long reboot_code_buffer;
> @@ -72,9 +78,14 @@ int machine_kexec_prepare(struct kimage *kimage)
>                 }
>         }
>
> -       /* kexec/kdump need a safe page to save reboot_code_buffer */
> -       kimage->control_code_page = virt_to_page((void *)KEXEC_CONTROL_CODE);
> -
> +       /*
> +        * kexec/kdump need a safe page to save reboot_code_buffer.  Reuse the
> +        * control_code_page allocated by the kexec core (as arm64 and riscv
> +        * do) instead of a fixed address: the trampoline is only executed by
> +        * the current kernel before entering the new kernel, so it needs no
> +        * fixed or reserved location.  This also stops machine_kexec_prepare()
> +        * from overwriting QEMU's machine FDT at 0x100000.
> +        */
>         reboot_code_buffer = (unsigned long)page_address(kimage->control_code_page);
>         memcpy((void *)reboot_code_buffer, relocate_new_kernel, relocate_new_kernel_size);
>
> --
> 2.25.1
>



More information about the kexec mailing list