LoongArch: add KHO support and selftests
Subsystems (5)
v3 cover LoongArch: add KHO support and selftests
From: George Guo <[email protected]>
This series adds Kexec Handover (KHO) support for LoongArch and extends the KHO selftest infrastructure to run on LoongArch under QEMU.
KHO passes metadata (the KHO state FDT and scratch area addresses) to the second kernel via the FDT /chosen node, using the linux,kho-fdt and linux,kho-scratch properties that drivers/of/kexec.c:kho_add_chosen() writes and drivers/of/fdt.c:early_init_dt_check_kho() reads.
KHO support (patches 1-2):
Patch 1 adds KHO support for FDT-based systems (initial_boot_params != NULL, e.g. QEMU virt without OVMF). kho_load_fdt() copies the running kernel's FDT, appends linux,kho-fdt and linux,kho-scratch to /chosen, and loads the result as a kexec segment. machine_kexec() updates the DEVICE_TREE_GUID entry in the EFI config table to point to this segment so the second kernel's fdt_setup() can find and parse it.
Patch 2 adds KHO support for ACPI-only systems (initial_boot_params == NULL, e.g. LoongArch servers with UEFI or QEMU with OVMF). Because no system FDT is available, kho_load_fdt() builds a minimal FDT from scratch containing only /chosen with the two KHO properties. Since DEVICE_TREE_GUID is absent from the EFI config table on ACPI-only systems, a new extended config table is built with the entry appended and loaded as a kexec segment; machine_kexec() switches st->tables to point to it before jumping. The second kernel's fdt_setup() calls efi_fdt_pointer() to detect the KHO FDT and passes it to early_init_dt_check_kho().
Selftest support (patch 3):
Patch 3 adds loongarch.conf and extends vmtest.sh to recognise loongarch64 as a build target. The LoongArch virt machine is FDT-only (no ACPI), so 'earlycon' must appear on the kernel cmdline or the console UART is never discovered. PS/2 input devices are disabled since QEMU's LoongArch virt machine has no i8042 controller; the fallback port probe hits a page fault and panics before reaching userspace. QEMU provides no EFI runtime services on LoongArch, so machine_restart() falls through to an infinite idle loop after kexec; QEMU_TIMEOUT=120 in loongarch.conf lets timeout(1) terminate QEMU once the time limit is reached.
Changes in v3:
- Merge selftest patches 3 and 4 from v2 into a single patch
- Replace QEMU_NEEDS_KILL/background kill loop with QEMU_TIMEOUT/timeout(1); the timeout value is set per-arch in the conf file.
George Guo (3):
LoongArch: kexec: add KHO support for FDT-based systems
LoongArch: kexec: add KHO support for ACPI-only systems selftests/kho: add LoongArch vmtest support
arch/loongarch/Kconfig | 3 + arch/loongarch/include/asm/kexec.h | 7 + arch/loongarch/kernel/machine_kexec.c | 38 +++ arch/loongarch/kernel/machine_kexec_file.c | 256 +++++++++++++++++++++ arch/loongarch/kernel/setup.c | 21 +- tools/testing/selftests/kho/loongarch.conf | 13 ++ tools/testing/selftests/kho/vmtest.sh | 23 +- 7 files changed, 353 insertions(+), 8 deletions(-) create mode 100644 tools/testing/selftests/kho/loongarch.conf
--
2.25.1
PATCH v3 1/3 LoongArch: kexec: add KHO support for FDT-based
From: George Guo <[email protected]>
Enable Kexec Handover (KHO) on LoongArch64 for FDT-based systems.
- Kconfig: select ARCH_SUPPORTS_KEXEC_HANDOVER for CONFIG_64BIT
- kexec.h: add fdt/fdt_mem fields to kimage_arch to hold the KHO FDT kexec segment virtual and physical addresses
- machine_kexec_file.c: add kho_load_fdt() which copies the running kernel's FDT (initial_boot_params), appends linux,kho-fdt and linux,kho-scratch properties to /chosen, and loads the result as a kexec segment; called from load_other_segments(). Returns -EINVAL when initial_boot_params is NULL (ACPI-only boot) since that path requires separate handling.
- machine_kexec.c: before jumping to the new kernel, update the DEVICE_TREE_GUID entry in the EFI config table to point to the KHO FDT segment so the second kernel finds it via efi_fdt_pointer() and early_init_dt_check_kho() calls kho_populate()
--- arch/loongarch/Kconfig | 3 + arch/loongarch/include/asm/kexec.h | 4 + arch/loongarch/kernel/machine_kexec.c | 27 +++++ arch/loongarch/kernel/machine_kexec_file.c | 118 +++++++++++++++++++++ 4 files changed, 152 insertions(+)
arch/loongarch/Kconfig +3 -0
@@ -684,6 +684,9 @@ config ARCH_SUPPORTS_KEXEC config ARCH_SUPPORTS_KEXEC_FILE def_bool 64BIT +config ARCH_SUPPORTS_KEXEC_HANDOVER + def_bool 64BIT + config ARCH_SELECTS_KEXEC_FILE def_bool 64BIT depends on KEXEC_FILE
arch/loongarch/include/asm/kexec.h +4 -0
@@ -39,6 +39,10 @@ struct kimage_arch {unsigned long efi_boot;unsigned long cmdline_ptr;unsigned long systable_ptr; +#ifdef CONFIG_KEXEC_HANDOVER +void *fdt;/* virtual address of KHO FDT segment buffer */ +unsigned long fdt_mem;/* physical address of KHO FDT segment */ +#endif };#ifdef CONFIG_KEXEC_FILE
arch/loongarch/kernel/machine_kexec.c +27 -0
@@ -6,6 +6,7 @@*/ #include <linux/compiler.h> #include <linux/cpu.h> +#include <linux/efi.h> #include <linux/kexec.h> #include <linux/crash_dump.h> #include <linux/delay.h>
@@ -289,6 +290,32 @@ void machine_kexec(struct kimage *image)pr_notice ("We will call new kernel at 0x%lx\n" , start_addr);pr_notice ("Bye ...\n" ); +#ifdef CONFIG_KEXEC_HANDOVER +/* +* Point the EFI FDTPTR config table entry at the modified FDT so the +* second kernel picks up the linux,kho-fdt and linux,kho-scratch +* properties via early_init_dt_check_kho(). +*/ +if (internal->fdt_mem) { +/* +* FDT-based system: DEVICE_TREE_GUID already exists in the EFI +* config table; just update its pointer to our KHO FDT. +*/ +efi_system_table_t *st = + (efi_system_table_t *)TO_CACHE (systable_ptr); +efi_config_table_t *ct = + (efi_config_table_t *)TO_CACHE ((unsigned long )st->tables); +unsigned long i; + +for (i =0 ; i < st->nr_tables; i++) { +if (!efi_guidcmp (ct[i].guid,DEVICE_TREE_GUID )) { + ct[i].table = (void *)internal->fdt_mem; +break ; + } + } + } +#endif +/* Make reboot code buffer available to the boot CPU. */ flush_cache_all ();
arch/loongarch/kernel/machine_kexec_file.c +118 -0
143 lines not on this page · raw message
Signature · 1 line
2.25.1
PATCH v3 2/3 LoongArch: kexec: add KHO support for ACPI-only
From: George Guo <[email protected]>
On ACPI-only systems fdt_setup() returns early when it detects ACPI, so initial_boot_params remains NULL and the FDT-based kho_load_fdt() path cannot be used.
machine_kexec_file.c:
- kho_load_fdt(): add an else branch that builds a minimal FDT from scratch (SZ_1K) containing only a /chosen node with linux,kho-fdt and linux,kho-scratch properties, using the libfdt creation API.
- Since DEVICE_TREE_GUID is absent from the EFI config table on ACPI-only systems, build a new config table with DEVICE_TREE_GUID appended and load it as a kexec segment. Store the result in kimage_arch so machine_kexec() can switch st->tables before jumping.
- arch_kimage_file_post_load_cleanup(): free the efi_tables kvmalloc buffer once the kexec image has been loaded.
machine_kexec.c:
- Before jumping, update the EFI system table pointer: for FDT-based systems update the existing DEVICE_TREE_GUID entry; for ACPI-only systems switch st->tables / st->nr_tables to the new extended table.
setup.c:
- fdt_setup(): when ACPI is detected, use efi_fdt_pointer() to detect whether this is a KHO kexec boot. The first kernel switches the EFI config table to a new one that includes a DEVICE_TREE_GUID entry pointing to the minimal KHO FDT. If found, call early_init_dt_scan() so early_init_dt_check_kho() can consume linux,kho-fdt and linux,kho-scratch, then reset initial_boot_params to NULL so the rest of the ACPI boot path is unaffected.
kexec.h:
- Add efi_tables, efi_tables_mem, efi_tables_cnt to kimage_arch.
--- arch/loongarch/include/asm/kexec.h | 3 + arch/loongarch/kernel/machine_kexec.c | 11 ++ arch/loongarch/kernel/machine_kexec_file.c | 162 +++++++++++++++++++-- arch/loongarch/kernel/setup.c | 21 ++- 4 files changed, 184 insertions(+), 13 deletions(-)
arch/loongarch/include/asm/kexec.h +3 -0
@@ -42,6 +42,9 @@ struct kimage_arch {#ifdef CONFIG_KEXEC_HANDOVER void *fdt;/* virtual address of KHO FDT segment buffer */ unsigned long fdt_mem;/* physical address of KHO FDT segment */ +void *efi_tables;/* new EFI config table buffer (virtual) */ +unsigned long efi_tables_mem;/* physical address of new EFI config table */ +unsigned long efi_tables_cnt;/* number of entries in new EFI config table */ #endif };
arch/loongarch/kernel/machine_kexec.c +11 -0
@@ -313,6 +313,17 @@ void machine_kexec(struct kimage *image) break; } } + }else if (internal->efi_tables_mem) { +/* +* ACPI-only system: DEVICE_TREE_GUID was not in the original +* EFI config table. Switch to the new table that was built in +* kho_load_fdt() with DEVICE_TREE_GUID appended. +*/ +efi_system_table_t *st = + (efi_system_table_t *)TO_CACHE (systable_ptr); + + st->tables = internal->efi_tables_mem; + st->nr_tables = internal->efi_tables_cnt; }#endif
arch/loongarch/kernel/machine_kexec_file.c +150 -12
198 lines not on this page · raw message
arch/loongarch/kernel/setup.c +20 -1
@@ -286,8 +286,27 @@ static void __init fdt_setup(void)void *fdt_pointer;/* ACPI-based systems do not require parsing fdt */ -if (acpi_os_get_root_pointer ()) +if (acpi_os_get_root_pointer ()) { +#ifdef CONFIG_KEXEC_HANDOVER +/* +* On a KHO kexec boot the first kernel builds a minimal FDT +* containing only /chosen with linux,kho-fdt and +* linux,kho-scratch, and switches the EFI config table to a +* new one that includes a DEVICE_TREE_GUID entry pointing to +* it. Use efi_fdt_pointer() to detect this case. +* +* Call early_init_dt_scan() to let early_init_dt_check_kho() +* consume the KHO data, then reset initial_boot_params so the +* rest of the ACPI boot path is not confused by this FDT. +*/ + fdt_pointer =efi_fdt_pointer (); +if (fdt_pointer && !fdt_check_header (fdt_pointer)) { +early_init_dt_scan (fdt_pointer,__pa (fdt_pointer)); + initial_boot_params =NULL ; + } +#endif return ; + }/* Prefer to use built-in dtb, checking its legality first. */ if (IS_ENABLED (CONFIG_BUILTIN_DTB ) && !fdt_check_header (__dtb_start))
Signature · 1 line
2.25.1
PATCH v3 3/3 selftests/kho: add LoongArch vmtest support
In reply to George GuoFrom: George Guo <[email protected]>
Add loongarch.conf to configure QEMU's LoongArch virt machine with a la464 CPU, enable the 8250 serial console, and set the kernel image to vmlinux.efi. Extend vmtest.sh to recognise loongarch64 as a supported target and map it to the 'loongarch' kernel arch name.
QEMU's LoongArch virt machine provides no ACPI tables and relies on FDT to describe hardware. Without 'earlycon' on the kernel command line, the FDT is not scanned for a console UART, no output reaches the console, and vmtest.sh's console log stays empty causing the test to always fail. Add 'earlycon' to KERNEL_CMDLINE in loongarch.conf.
QEMU's LoongArch virt machine has no i8042 PS/2 controller. When PNP detection finds nothing, i8042_init() falls back to probing the ports directly. On LoongArch the I/O ports are memory-mapped, and the i8042 port addresses are not backed by any device on the virt machine, so i8042_flush() takes a page fault and the kernel panics:
i8042: PNP: No PS/2 controller found.
i8042: Probing ports directly.
CPU 0 Unable to handle kernel paging request at virtual address ffff800000008064
ERA: i8042_flush+0x50/0x198
RA: i8042_init+0x2a8/0x35c
Kernel panic - not syncing: Attempted to kill init!
Disable SERIO_I8042 and its dependents (KEYBOARD_ATKBD, MOUSE_PS2) in the QEMU_KCONFIG fragment to prevent the driver from being built. All three options are scoped to loongarch.conf; no other architecture is affected.
QEMU provides no EFI runtime services on LoongArch, so machine_restart() falls through to an infinite idle loop after kexec. Set QEMU_TIMEOUT=120 in loongarch.conf so vmtest.sh wraps the QEMU invocation with timeout(1), which terminates QEMU after 120 seconds if it does not exit on its own. Architectures that do not set QEMU_TIMEOUT are unaffected.
--- tools/testing/selftests/kho/loongarch.conf | 13 ++++++++++++ tools/testing/selftests/kho/vmtest.sh | 23 +++++++++++++++------- 2 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 tools/testing/selftests/kho/loongarch.conf
tools/testing/selftests/kho/loongarch.conf new file +13 -0
@@ -0,0 +1,13 @@ +QEMU_CMD="qemu-system-loongarch64 -M virt -cpu la464" +QEMU_KCONFIG=" +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_MOUSE_PS2 is not set +# CONFIG_SERIO_I8042 is not set +" +KERNEL_IMAGE="vmlinux.efi" +KERNEL_CMDLINE="console=ttyS0 earlycon" +# QEMU never exits after kexec on LoongArch (no EFI runtime services); +# give the test a fixed time limit and let timeout(1) terminate QEMU. +QEMU_TIMEOUT=120
tools/testing/selftests/kho/vmtest.sh +16 -7
@@ -21,7 +21,7 @@ Options: -d) path to the kernel build directory -j) number of jobs for compilation, similar to -j in make -t) run test for target_arch, requires CROSS_COMPILE set - supported targets: aarch64, x86_64 + supported targets: aarch64, x86_64, loongarch64 -h) display this help EOF }
@@ -107,12 +107,20 @@ function run_qemu() { cmdline="$cmdline kho=on panic=-1" - $qemu_cmd -m 1G -smp 2 -no-reboot -nographic -nodefaults \ - -accel kvm -accel hvf -accel tcg \ - -serial file:"$serial" \ - -append "$cmdline" \ - -kernel "$kernel" \ - -initrd "$initrd" + local qemu_args=( + -m 1G -smp 2 -no-reboot -nographic -nodefaults + -accel kvm -accel hvf -accel tcg + -serial file:"$serial" + -append "$cmdline" + -kernel "$kernel" + -initrd "$initrd" + ) + + if [[ -n "${QEMU_TIMEOUT:-}" ]]; then + timeout "$QEMU_TIMEOUT" $qemu_cmd "${qemu_args[@]}" || true + else + $qemu_cmd "${qemu_args[@]}" + fi grep "KHO restore succeeded" "$serial" &> /dev/null || fail "KHO failed" }
@@ -123,6 +131,7 @@ function target_to_arch() { case $target in aarch64) echo "arm64" ;; x86_64) echo "x86" ;; + loongarch64) echo "loongarch" ;; *) skip "architecture $target is not supported" esac }
Signature · 1 line
2.25.1
Mike Rapoport
maintainerRe: [PATCH v3 3/3] selftests/kho: add LoongArch vmtest support
On Mon, 01 Jun 2026 17:39:30 +0800, George Guo <[email protected]> wrote:
Hi,
Quoted 1 line
Add loongarch.conf to configure QEMU's LoongArch virt machine with a
Please spell out "virtual machine" here and below or use VM abbrevation.
Quoted 8 lines
tools/testing/selftests/kho/vmtest.sh +0
-0@@ -107,12 +107,20 @@ function run_qemu() {[ ... skip 14 lines ... ]
tools/testing/selftests/kho/vmtest.sh function run_qemu() { · line 120
Quoted 6 lines
tools/testing/selftests/kho/vmtest.sh +6
-0+ -kernel "$kernel" + -initrd "$initrd" + ) + + if [[ -n "${QEMU_TIMEOUT:-}" ]]; then + timeout "$QEMU_TIMEOUT" $qemu_cmd "${qemu_args[@]}" || true
Runnig with timeout can be actually useful for other architecures. Let's make a local variable for timeout of 120 seconds and always run qemu with timeout.
Signature · 2 lines
Sincerely yours, Mike.
Pratyush Yadav
maintainerRe: [PATCH v3 1/3] LoongArch: kexec: add KHO support for FDT-based
In reply to George GuoQuoted 88 lines · George Guo
From: George Guo <[email protected]>
Enable Kexec Handover (KHO) on LoongArch64 for FDT-based systems.
-
Kconfig: selectARCH_SUPPORTS_KEXEC_HANDOVERforCONFIG_64BIT
-kexec.h: add fdt/fdt_mem fields tokimage_archto hold the KHO FDT kexec segment virtual and physical addresses
-machine_kexec_file.c: addkho_load_fdt()which copies the running kernel's FDT (initial_boot_params), appends linux,kho-fdt and linux,kho-scratch properties to /chosen, and loads the result as a kexec segment; called fromload_other_segments(). Returns-EINVALwheninitial_boot_paramsis NULL (ACPI-only boot) since that path requires separate handling.
-machine_kexec.c: before jumping to the new kernel, update theDEVICE_TREE_GUIDentry in the EFI config table to point to the KHO FDT segment so the second kernel finds it viaefi_fdt_pointer()andearly_init_dt_check_kho()callskho_populate()Co-developed-by Kexin Liu <[email protected]>Signed-off-by Kexin Liu <[email protected]>Signed-off-by George Guo <[email protected]>--- arch/loongarch/Kconfig | 3 + arch/loongarch/include/asm/kexec.h | 4 + arch/loongarch/kernel/machine_kexec.c | 27 +++++ arch/loongarch/kernel/machine_kexec_file.c | 118 +++++++++++++++++++++ 4 files changed, 152 insertions(+)arch/loongarch/Kconfig +3
-0@@ -684,6 +684,9 @@ config ARCH_SUPPORTS_KEXEC config ARCH_SUPPORTS_KEXEC_FILE def_bool 64BIT +config ARCH_SUPPORTS_KEXEC_HANDOVER + def_bool 64BIT + config ARCH_SELECTS_KEXEC_FILE def_bool 64BIT depends on KEXEC_FILEarch/loongarch/include/asm/kexec.h +4
-0@@ -39,6 +39,10 @@ struct kimage_arch {unsigned long efi_boot;unsigned long cmdline_ptr;unsigned long systable_ptr; +#ifdef CONFIG_KEXEC_HANDOVER +void *fdt;/* virtual address of KHO FDT segment buffer */ +unsigned long fdt_mem;/* physical address of KHO FDT segment */ +#endif };#ifdef CONFIG_KEXEC_FILE arch/loongarch/kernel/machine_kexec.c +16
-0@@ -6,6 +6,7 @@*/ #include <linux/compiler.h> #include <linux/cpu.h> +#include <linux/efi.h> #include <linux/kexec.h> #include <linux/crash_dump.h> #include <linux/delay.h> @@ -289,6 +290,32 @@ void machine_kexec(struct kimage *image)pr_notice ("We will call new kernel at 0x%lx\n" , start_addr);pr_notice ("Bye ...\n" ); +#ifdef CONFIG_KEXEC_HANDOVER +/* +* Point the EFI FDTPTR config table entry at the modified FDT so the +* second kernel picks up the linux,kho-fdt and linux,kho-scratch +* properties via early_init_dt_check_kho(). +*/ +if (internal->fdt_mem) { +/* +* FDT-based system: DEVICE_TREE_GUID already exists in the EFI +* config table; just update its pointer to our KHO FDT. +*/ +efi_system_table_t *st = + (efi_system_table_t *)TO_CACHE (systable_ptr); +efi_config_table_t *ct = + (efi_config_table_t *)TO_CACHE ((unsigned long )st->tables);
arch/loongarch/kernel/machine_kexec.c void machine_kexec(struct kimage *image) · line 317
Quoted 10 lines
arch/loongarch/kernel/machine_kexec.c +10
-0+unsigned long i; + +for (i =0 ; i < st->nr_tables; i++) { +if (!efi_guidcmp (ct[i].guid,DEVICE_TREE_GUID )) { + ct[i].table = (void *)internal->fdt_mem; +break ; + } + } + } +#endif
Honestly this and the ACPI stuff looks worse to me than what your previous version did. Now I am not an expert on EFI and architecture stuff, and know nothing about Loongarch, but to me this looks hacky and I am not sure if it is doing the right thing.
I think you should get some alignment with Loongarch maintainers on what the kexec boot protocol looks like. It looked odd to me, but if the Loongarch maintainers are fine with using the kernel cmdline for bootloader to pass data to the kernel, then I think we should go back to that.
Huacai, do you have any thoughts? For KHO we essentially need a way for the pre-kexec kernel to tell the post-kexec kernel about a blob of memory that has some information it can use. For x86, we do that via setup data. See arch/x86/include/uapi/asm/setup_data.h and struct kho_data for example. On arm64, we use the boot FDT's /chosen node. See kho_add_chosen() in drivers/of/kexec.c.
Ideally, all device tree platforms should use the FDT path. But Loongarch also has ACPI only and I don't know what a good idea for that is.
So, do you have any suggestions on where to best place a pointer to this blob of data on Loongarch? v1 of this series put it in the kernel commandline, but I found that odd and asked if it can be done via DT instead. But to me, this code looks even more hacky.
Quoted 4 lines
arch/loongarch/kernel/machine_kexec.c +1
-0+/* Make reboot code buffer available to the boot CPU. */ flush_cache_all ();
[...]
Signature · 2 lines
Regards, Pratyush Yadav
Huacai Chen
maintainerRe: [PATCH v3 1/3] LoongArch: kexec: add KHO support for FDT-based
Hi, Pratyush,
Quoted 120 lines · Pratyush Yadav
Quoted 88 lines · George Guo
From: George Guo <[email protected]>
Enable Kexec Handover (KHO) on LoongArch64 for FDT-based systems.
-
Kconfig: selectARCH_SUPPORTS_KEXEC_HANDOVERforCONFIG_64BIT
-kexec.h: add fdt/fdt_mem fields tokimage_archto hold the KHO FDT kexec segment virtual and physical addresses
-machine_kexec_file.c: addkho_load_fdt()which copies the running kernel's FDT (initial_boot_params), appends linux,kho-fdt and linux,kho-scratch properties to /chosen, and loads the result as a kexec segment; called fromload_other_segments(). Returns-EINVALwheninitial_boot_paramsis NULL (ACPI-only boot) since that path requires separate handling.
-machine_kexec.c: before jumping to the new kernel, update theDEVICE_TREE_GUIDentry in the EFI config table to point to the KHO FDT segment so the second kernel finds it viaefi_fdt_pointer()andearly_init_dt_check_kho()callskho_populate()Co-developed-by Kexin Liu <[email protected]>Signed-off-by Kexin Liu <[email protected]>Signed-off-by George Guo <[email protected]>--- arch/loongarch/Kconfig | 3 + arch/loongarch/include/asm/kexec.h | 4 + arch/loongarch/kernel/machine_kexec.c | 27 +++++ arch/loongarch/kernel/machine_kexec_file.c | 118 +++++++++++++++++++++ 4 files changed, 152 insertions(+)arch/loongarch/Kconfig +3
-0@@ -684,6 +684,9 @@ config ARCH_SUPPORTS_KEXEC config ARCH_SUPPORTS_KEXEC_FILE def_bool 64BIT +config ARCH_SUPPORTS_KEXEC_HANDOVER + def_bool 64BIT + config ARCH_SELECTS_KEXEC_FILE def_bool 64BIT depends on KEXEC_FILEarch/loongarch/include/asm/kexec.h +4
-0@@ -39,6 +39,10 @@ struct kimage_arch {unsigned long efi_boot;unsigned long cmdline_ptr;unsigned long systable_ptr; +#ifdef CONFIG_KEXEC_HANDOVER +void *fdt;/* virtual address of KHO FDT segment buffer */ +unsigned long fdt_mem;/* physical address of KHO FDT segment */ +#endif };#ifdef CONFIG_KEXEC_FILE arch/loongarch/kernel/machine_kexec.c +16
-0@@ -6,6 +6,7 @@*/ #include <linux/compiler.h> #include <linux/cpu.h> +#include <linux/efi.h> #include <linux/kexec.h> #include <linux/crash_dump.h> #include <linux/delay.h> @@ -289,6 +290,32 @@ void machine_kexec(struct kimage *image)pr_notice ("We will call new kernel at 0x%lx\n" , start_addr);pr_notice ("Bye ...\n" ); +#ifdef CONFIG_KEXEC_HANDOVER +/* +* Point the EFI FDTPTR config table entry at the modified FDT so the +* second kernel picks up the linux,kho-fdt and linux,kho-scratch +* properties via early_init_dt_check_kho(). +*/ +if (internal->fdt_mem) { +/* +* FDT-based system: DEVICE_TREE_GUID already exists in the EFI +* config table; just update its pointer to our KHO FDT. +*/ +efi_system_table_t *st = + (efi_system_table_t *)TO_CACHE (systable_ptr); +efi_config_table_t *ct = + (efi_config_table_t *)TO_CACHE ((unsigned long )st->tables);arch/loongarch/kernel/machine_kexec.c void machine_kexec(struct kimage *image) · line 317
Quoted 10 lines
arch/loongarch/kernel/machine_kexec.c +10
-0+unsigned long i; + +for (i =0 ; i < st->nr_tables; i++) { +if (!efi_guidcmp (ct[i].guid,DEVICE_TREE_GUID )) { + ct[i].table = (void *)internal->fdt_mem; +break ; + } + } + } +#endif Honestly this and the ACPI stuff looks worse to me than what your previous version did. Now I am not an expert on EFI and architecture stuff, and know nothing about Loongarch, but to me this looks hacky and I am not sure if it is doing the right thing.
I think you should get some alignment with Loongarch maintainers on what the kexec boot protocol looks like. It looked odd to me, but if the Loongarch maintainers are fine with using the kernel cmdline for bootloader to pass data to the kernel, then I think we should go back to that.
Huacai, do you have any thoughts? For KHO we essentially need a way for the pre-kexec kernel to tell the post-kexec kernel about a blob of memory that has some information it can use. For x86, we do that via setup data. See
arch/x86/include/uapi/asm/setup_data.hand structkho_datafor example. On arm64, we use the boot FDT's /chosen node. Seekho_add_chosen()indrivers/of/kexec.c.
Quoted 8 lines
Ideally, all device tree platforms should use the FDT path. But Loongarch also has ACPI only and I don't know what a good idea for that is.
So, do you have any suggestions on where to best place a pointer to this blob of data on Loongarch? v1 of this series put it in the kernel commandline, but I found that odd and asked if it can be done via DT instead. But to me, this code looks even more hacky.
I don't know which is the best way, but I can give some information.
ARM64 and RISC-V create a FDT to contain all needed boot information (EFI system table, command line, etc.) in efistub. In other words, both ACPI booting and FDT booting have an existing FDT to pass the blob.
But LoongArch is different, the efistub doesn't create a FDT, instead it passes the EFI system table and command line to the core kernel directly.
Huacai
Quoted 10 lines
arch/loongarch/kernel/machine_kexec.c void machine_kexec(struct kimage *image) · line 321
Quoted 5 lines
arch/loongarch/kernel/machine_kexec.c +1
-0+/* Make reboot code buffer available to the boot CPU. */ flush_cache_all ();[...]
--
Regards,
Pratyush Yadav
Re: [PATCH v3 1/3] LoongArch: kexec: add KHO support for FDT-based
Hi Huacai, Pratyush,
Thanks for the direction. You were both right that the v3 approach was the wrong shape, and I have dropped it.
Let me restate the constraint and report what I did.
Quoted 3 lines
But LoongArch is different, the efistub doesn't create a FDT, instead it passes the EFI system table and command line to the core kernel directly.
So LoongArch has no boot FDT, and the arm64 /chosen path does not apply. My v3 synthesized an FDT and rewrote the DEVICE_TREE_GUID entry only to reuse the generic reader. That was the hacky part, and it is gone.
I followed the x86 model instead. x86 has no boot FDT either; it carries the KHO pointer in setup_data (struct kho_data) and calls kho_populate() directly. LoongArch has no setup_data, but it does pass the EFI system table. So I use the EFI configuration table as the channel:
- The first kernel builds a small handover struct (the KHO FDT and scratch addresses), adds a dedicated GUID entry pointing to it, and loads both as kexec segments. machine_kexec() switches the system table to the extended table before jumping.
- The next kernel scans the configuration table for that GUID, reads the struct, and calls kho_populate() directly.
There is no synthesized FDT, no DEVICE_TREE_GUID rewrite, and nothing on the command line. I did not go back to the v1 command line because that exposes the addresses to unprivileged userspace through /proc/cmdline.
I tested this on real LoongArch hardware (ACPI/UEFI) with the live update two-stage kexec test and the test passes:
$ sudo ./luo_kexec_simple --stage 1 # [STAGE 1] Starting pre-kexec setup... # [STAGE 1] Creating state file for next stage (2)... # [STAGE 1] Creating session 'test-session' and preserving memfd... # [STAGE 1] Forking persistent child to hold sessions... # [STAGE 1] Child PID: 1242. Resources are pinned. # [STAGE 1] You may now perform kexec reboot. $ sudo kexec -l /boot/vmlinuz-7.1.0-rc6 --initrd=/boot/initramfs-7.1.0-rc6.img --reuse-cmdline $ sudo kexec -e
$ sudo ./luo_kexec_simple --stage 2 # [STAGE 2] Starting post-kexec verification... # [STAGE 2] Retrieving session 'test-session'... # [STAGE 2] Restoring and verifying memfd (token 0x1a)... # [STAGE 2] Test data verified successfully. # [STAGE 2] Finalizing test session... # [STAGE 2] Finalizing state session... # --- SIMPLE KEXEC TEST PASSED --- $ sudo dmesg | grep kexec [ 0.000000] [ T0] KHO: found kexec handover data.
I will send this as v4, folding in Mike's two selftest comments. If you see a problem with the EFI configuration table approach, please tell me before I post.
Thanks,
George
Hi Mike, Huacai,
Gentle ping on this v3. In the v2 review you mentioned you'd wait for v3 for a more detailed look -- v3 addresses both points (folded the two selftest patches into one, and replaced the LoongArch-specific kill loop with timeout(1), with the timeout value set per-arch in the conf).
No rush, just making sure it didn't slip through the cracks. Happy to spin a rebase if it's gone stale.
Thanks!
--
George
Pratyush Yadav
maintainerQuoted 9 lines · George Guo
Hi Mike, Huacai,
Gentle ping on this v3. In the v2 review you mentioned you'd wait for v3 for a more detailed look -- v3 addresses both points (folded the two selftest patches into one, and replaced the LoongArch-specific kill loop with timeout(1), with the timeout value set per-arch in the conf).
No rush, just making sure it didn't slip through the cracks. Happy to spin a rebase if it's gone stale.
It is on my review list, and I hope to get to it soon. But no promises unfortunately.
Signature · 2 lines
Regards, Pratyush Yadav