From: George Guo <dongtai.guo@linux.dev>
To: maobibo@loongson.cn
Cc: chenhuacai@kernel.org, dongtai.guo@linux.dev,
guodongtai@kylinos.cn, kernel@xen0n.name,
linux-kernel@vger.kernel.org, loongarch@lists.linux.dev
Subject: [PATCH v2] LoongArch: kexec: drop hardcoded addresses to avoid QEMU FDT conflict
Date: Mon, 1 Jun 2026 11:38:20 +0800 [thread overview]
Message-ID: <20260601033820.38805-1-dongtai.guo@linux.dev> (raw)
In-Reply-To: <dbcb280c-9929-b084-0f2b-4f712a85d17b@loongson.cn>
From: George Guo <guodongtai@kylinos.cn>
KEXEC_CONTROL_CODE and KEXEC_CMDLINE_ADDR were hardcoded to fixed
physical addresses (0x100000 and 0x108000) in the first 2MB. QEMU
places its machine FDT at 0x100000 when booting with '-kernel', so
machine_kexec_prepare() was overwriting the FDT with the relocation
trampoline. The kexec'd kernel's fdt_setup() then found trampoline
code instead of a valid FDT, causing earlycon to fail silently.
Fix this by dropping the hardcoded addresses entirely. Use the
control_code_page already allocated by the kexec core for the
relocation trampoline, and allocate a separate page via
kimage_alloc_control_pages() for the kernel command line copy.
kimage_alloc_control_pages() registers pages with the kexec core so
the page-copy loop skips them, providing the same safety guarantee
without depending on any specific physical location.
This follows the approach used by arm64 and riscv, which also rely on
the core-allocated control_code_page rather than fixed addresses.
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
Changes in v2:
- Instead of moving KEXEC_CONTROL_CODE to a different fixed address,
drop hardcoded addresses entirely. Use the kexec core's already-
allocated control_code_page for the trampoline and allocate a
separate page via kimage_alloc_control_pages() for the command line,
following the approach used by arm64 and riscv.
arch/loongarch/kernel/machine_kexec.c | 31 ++++++++++++++++-----------
1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/arch/loongarch/kernel/machine_kexec.c b/arch/loongarch/kernel/machine_kexec.c
index d7fafda1d541..ad27fef098f1 100644
--- a/arch/loongarch/kernel/machine_kexec.c
+++ b/arch/loongarch/kernel/machine_kexec.c
@@ -21,10 +21,6 @@
#include <asm/cacheflush.h>
#include <asm/page.h>
-/* 0x100000 ~ 0x200000 is safe */
-#define KEXEC_CONTROL_CODE TO_CACHE(0x100000UL)
-#define KEXEC_CMDLINE_ADDR TO_CACHE(0x108000UL)
-
static unsigned long reboot_code_buffer;
static cpumask_t cpus_in_crash = CPU_MASK_NONE;
@@ -43,19 +39,30 @@ int machine_kexec_prepare(struct kimage *kimage)
{
int i;
char *bootloader = "kexec";
- void *cmdline_ptr = (void *)KEXEC_CMDLINE_ADDR;
+ struct page *cmdline_page;
+ void *cmdline_ptr;
kimage->arch.efi_boot = fw_arg0;
kimage->arch.systable_ptr = fw_arg2;
+ /*
+ * Allocate a separate control page for the kernel command line.
+ * kimage_alloc_control_pages() ensures the page is not overwritten
+ * by the kexec page-copy loop.
+ */
+ cmdline_page = kimage_alloc_control_pages(kimage, 0);
+ if (!cmdline_page)
+ return -ENOMEM;
+ cmdline_ptr = page_to_virt(cmdline_page);
+
if (kimage->file_mode == 1) {
/*
- * kimage->cmdline_buf will be released in kexec_file_load, so copy
- * to the KEXEC_CMDLINE_ADDR safe area.
+ * kimage->cmdline_buf will be released in kexec_file_load, so
+ * copy it to the control page before it is freed.
*/
- memcpy((void *)KEXEC_CMDLINE_ADDR, (void *)kimage->arch.cmdline_ptr,
- strlen((char *)kimage->arch.cmdline_ptr) + 1);
- kimage->arch.cmdline_ptr = (unsigned long)KEXEC_CMDLINE_ADDR;
+ memcpy(cmdline_ptr, (void *)kimage->arch.cmdline_ptr,
+ strlen((char *)kimage->arch.cmdline_ptr) + 1);
+ kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
} else {
/* Find the command line */
for (i = 0; i < kimage->nr_segments; i++) {
@@ -73,9 +80,7 @@ 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);
-
- reboot_code_buffer = (unsigned long)page_address(kimage->control_code_page);
+ reboot_code_buffer = (unsigned long)page_to_virt(kimage->control_code_page);
memcpy((void *)reboot_code_buffer, relocate_new_kernel, relocate_new_kernel_size);
#ifdef CONFIG_SMP
--
2.25.1
prev parent reply other threads:[~2026-06-01 3:38 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-28 13:58 [PATCH 1/1] LoongArch: kexec: avoid overwriting QEMU's machine FDT at 0x100000 George Guo
2026-05-29 4:25 ` Huacai Chen
2026-05-29 6:19 ` Bibo Mao
2026-05-29 6:40 ` Bibo Mao
2026-06-01 3:38 ` George Guo [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260601033820.38805-1-dongtai.guo@linux.dev \
--to=dongtai.guo@linux.dev \
--cc=chenhuacai@kernel.org \
--cc=guodongtai@kylinos.cn \
--cc=kernel@xen0n.name \
--cc=linux-kernel@vger.kernel.org \
--cc=loongarch@lists.linux.dev \
--cc=maobibo@loongson.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome