| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/09/05 19:21 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"KMSANReasoning": "",
"NeedsKMSAN": false,
"Reasoning": "The patch introduces EFI configuration table transport for kexec handover (KHO), targeted at architectures that boot through EFI without device tree (such as LoongArch). The new config CONFIG_EFI_KHO is only selected by arch/loongarch/Kconfig and cannot be enabled on the target architecture (amd64). On amd64, all EFI KHO logic in the EFI drivers and libstub is compiled out, efi_kho_update() is an inline no-op returning 0, and the remaining changes are selftest scripts and a header inclusion. Therefore, no reachable executable code is modified for amd64.",
"WorthFuzzing": false
} |
| 1/1 | 2026/09/05 19:21 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 1d1354e17143c5874863dc5a7a88f3ce23789967\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Sat Sep 5 19:21:22 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig\nindex a21f51e5815e9..5eaa65578d58e 100644\n--- a/arch/loongarch/Kconfig\n+++ b/arch/loongarch/Kconfig\n@@ -685,6 +685,10 @@ config ARCH_SUPPORTS_KEXEC\n config ARCH_SUPPORTS_KEXEC_FILE\n \tdef_bool 64BIT\n \n+config ARCH_SUPPORTS_KEXEC_HANDOVER\n+\tdef_bool 64BIT \u0026\u0026 EFI_STUB\n+\tselect EFI_KHO if KEXEC_HANDOVER\n+\n config ARCH_SELECTS_KEXEC_FILE\n \tdef_bool 64BIT\n \tdepends on KEXEC_FILE\ndiff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig\nindex 29e0729299f5b..d6c1372484b4b 100644\n--- a/drivers/firmware/efi/Kconfig\n+++ b/drivers/firmware/efi/Kconfig\n@@ -314,6 +314,18 @@ config EFI_SBAT_FILE\n \n \t If unsure, leave blank.\n \n+config EFI_KHO\n+\tbool\n+\tdepends on EFI_STUB \u0026\u0026 EFI_GENERIC_STUB \u0026\u0026 KEXEC_HANDOVER\n+\thelp\n+\t Carry the KHO state (the KHO state FDT and the scratch area) from\n+\t one kernel to the next across kexec via an EFI configuration table\n+\t entry under LINUX_EFI_KEXEC_HANDOVER_GUID, for architectures that\n+\t boot through EFI without a device tree (e.g. LoongArch).\n+\n+\t Architectures with a boot FDT (arm64, riscv) use the /chosen FDT\n+\t path instead and do not select this.\n+\n endmenu\n \n config UEFI_CPER\ndiff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c\nindex 0327a39d31fa5..6380cfab1493e 100644\n--- a/drivers/firmware/efi/efi.c\n+++ b/drivers/firmware/efi/efi.c\n@@ -24,6 +24,7 @@\n #include \u003clinux/initrd.h\u003e\n #include \u003clinux/io.h\u003e\n #include \u003clinux/kexec.h\u003e\n+#include \u003clinux/kexec_handover.h\u003e\n #include \u003clinux/platform_device.h\u003e\n #include \u003clinux/random.h\u003e\n #include \u003clinux/reboot.h\u003e\n@@ -62,6 +63,9 @@ unsigned long __ro_after_init efi_rng_seed = EFI_INVALID_TABLE_ADDR;\n static unsigned long __initdata mem_reserve = EFI_INVALID_TABLE_ADDR;\n static unsigned long __initdata rt_prop = EFI_INVALID_TABLE_ADDR;\n static unsigned long __initdata initrd = EFI_INVALID_TABLE_ADDR;\n+#ifdef CONFIG_EFI_KHO\n+static unsigned long __ro_after_init efi_kho_table_phys = EFI_INVALID_TABLE_ADDR;\n+#endif\n \n extern unsigned long primary_display_table;\n \n@@ -629,6 +633,9 @@ static const efi_config_table_type_t common_tables[] __initconst = {\n \t{EFI_TCG2_FINAL_EVENTS_TABLE_GUID,\t\u0026efi.tpm_final_log,\t\"TPMFinalLog\"\t},\n \t{EFI_CC_FINAL_EVENTS_TABLE_GUID,\t\u0026efi.tpm_final_log,\t\"CCFinalLog\"\t},\n \t{LINUX_EFI_MEMRESERVE_TABLE_GUID,\t\u0026mem_reserve,\t\t\"MEMRESERVE\"\t},\n+#ifdef CONFIG_EFI_KHO\n+\t{LINUX_EFI_KEXEC_HANDOVER_GUID,\t\t\u0026efi_kho_table_phys,\t\"KHO\"\t\t},\n+#endif\n \t{LINUX_EFI_INITRD_MEDIA_GUID,\t\t\u0026initrd,\t\t\"INITRD\"\t},\n \t{EFI_RT_PROPERTIES_TABLE_GUID,\t\t\u0026rt_prop,\t\t\"RTPROP\"\t},\n #ifdef CONFIG_OVMF_DEBUG_LOG\n@@ -806,6 +813,31 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,\n \t\t}\n \t}\n \n+#ifdef CONFIG_EFI_KHO\n+\tif (efi_kho_table_phys != EFI_INVALID_TABLE_ADDR) {\n+\t\tstruct linux_efi_kho_data *kho;\n+\n+\t\t/*\n+\t\t * Reserve the stub-allocated table so it is neither handed\n+\t\t * out by the buddy allocator nor placed on by kexec\n+\t\t * segments, mirroring the memreserve handling above. This\n+\t\t * runs on every boot, so it also protects the table in the\n+\t\t * next kernel until it reads it.\n+\t\t */\n+\t\tmemblock_reserve(efi_kho_table_phys, sizeof(*kho));\n+\n+\t\tkho = early_memremap(efi_kho_table_phys, sizeof(*kho));\n+\t\tif (kho) {\n+\t\t\tif (kho-\u003efdt_addr)\n+\t\t\t\tkho_populate((phys_addr_t)kho-\u003efdt_addr,\n+\t\t\t\t\t kho-\u003efdt_size,\n+\t\t\t\t\t (phys_addr_t)kho-\u003escratch_addr,\n+\t\t\t\t\t kho-\u003escratch_size);\n+\t\t\tearly_memunmap(kho, sizeof(*kho));\n+\t\t}\n+\t}\n+#endif\n+\n \tif (rt_prop != EFI_INVALID_TABLE_ADDR) {\n \t\tefi_rt_properties_table_t *tbl;\n \n@@ -1171,6 +1203,52 @@ static int __init efi_memreserve_root_init(void)\n }\n early_initcall(efi_memreserve_root_init);\n \n+#ifdef CONFIG_EFI_KHO\n+static struct linux_efi_kho_data *efi_kho_table __ro_after_init;\n+\n+static int __init efi_kho_table_init(void)\n+{\n+\tif (efi_kho_table_phys == EFI_INVALID_TABLE_ADDR)\n+\t\treturn 0;\n+\n+\t/*\n+\t * Keep a persistent mapping of the table, the same way\n+\t * efi_memreserve_root_init() keeps the memreserve root mapped:\n+\t * efi_kho_update() is also called on the crash kexec path, where\n+\t * memremap() is no longer an option.\n+\t */\n+\tefi_kho_table = memremap(efi_kho_table_phys, sizeof(*efi_kho_table),\n+\t\t\t\t MEMREMAP_WB);\n+\tWARN_ON_ONCE(!efi_kho_table);\n+\n+\treturn 0;\n+}\n+early_initcall(efi_kho_table_init);\n+\n+/*\n+ * Update the KHO config table in place before a kexec, so the next kernel\n+ * finds the current handover state. Mirrors efi_mem_reserve_persistent():\n+ * the config table entry was installed once by the EFI stub and is inherited\n+ * across kexec, so only the table contents are rewritten here -- the config\n+ * table array is never rebuilt and st-\u003etables is never switched.\n+ */\n+int efi_kho_update(phys_addr_t fdt_addr, u64 fdt_size,\n+\t\t phys_addr_t scratch_addr, u64 scratch_size)\n+{\n+\tstruct linux_efi_kho_data *kho = efi_kho_table;\n+\n+\tif (!kho)\n+\t\treturn -ENODEV;\n+\n+\tkho-\u003efdt_addr\t\t= fdt_addr;\n+\tkho-\u003efdt_size\t\t= fdt_size;\n+\tkho-\u003escratch_addr\t= scratch_addr;\n+\tkho-\u003escratch_size\t= scratch_size;\n+\n+\treturn 0;\n+}\n+#endif\n+\n #ifdef CONFIG_KEXEC\n static int update_efi_random_seed(struct notifier_block *nb,\n \t\t\t\t unsigned long code, void *unused)\ndiff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c\nindex 42d6073bcd062..751f46280433b 100644\n--- a/drivers/firmware/efi/libstub/efi-stub.c\n+++ b/drivers/firmware/efi/libstub/efi-stub.c\n@@ -100,6 +100,29 @@ static void install_memreserve_table(void)\n \t\tefi_err(\"Failed to install memreserve config table!\\n\");\n }\n \n+static void install_kho_table(void)\n+{\n+#ifdef CONFIG_EFI_KHO\n+\tstruct linux_efi_kho_data *kho;\n+\tefi_guid_t kho_table_guid = LINUX_EFI_KEXEC_HANDOVER_GUID;\n+\tefi_status_t status;\n+\n+\tstatus = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(*kho),\n+\t\t\t (void **)\u0026kho);\n+\tif (status != EFI_SUCCESS) {\n+\t\tefi_err(\"Failed to allocate KHO config table!\\n\");\n+\t\treturn;\n+\t}\n+\n+\t*kho = (struct linux_efi_kho_data){};\n+\n+\tstatus = efi_bs_call(install_configuration_table, \u0026kho_table_guid,\n+\t\t\t kho);\n+\tif (status != EFI_SUCCESS)\n+\t\tefi_err(\"Failed to install KHO config table!\\n\");\n+#endif\n+}\n+\n static u32 get_supported_rt_services(void)\n {\n \tconst efi_rt_properties_table_t *rt_prop_table;\n@@ -180,6 +203,8 @@ efi_status_t efi_stub_common(efi_handle_t handle,\n \n \tinstall_memreserve_table();\n \n+\tinstall_kho_table();\n+\n \tstatus = efi_boot_kernel(handle, image, image_addr, cmdline_ptr);\n \n \tfree_primary_display(dpy);\ndiff --git a/include/linux/efi.h b/include/linux/efi.h\nindex aa15ff88539bd..564b3cbd5ccb8 100644\n--- a/include/linux/efi.h\n+++ b/include/linux/efi.h\n@@ -422,6 +422,7 @@ void efi_native_runtime_setup(void);\n #define LINUX_EFI_COCO_SECRET_AREA_GUID\t\tEFI_GUID(0xadf956ad, 0xe98c, 0x484c, 0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47)\n #define LINUX_EFI_BOOT_MEMMAP_GUID\t\tEFI_GUID(0x800f683f, 0xd08b, 0x423a, 0xa2, 0x93, 0x96, 0x5c, 0x3c, 0x6f, 0xe2, 0xb4)\n #define LINUX_EFI_UNACCEPTED_MEM_TABLE_GUID\tEFI_GUID(0xd5d1de3c, 0x105c, 0x44f9, 0x9e, 0xa9, 0xbc, 0xef, 0x98, 0x12, 0x00, 0x31)\n+#define LINUX_EFI_KEXEC_HANDOVER_GUID\t\tEFI_GUID(0xc941b6c7, 0x7b3f, 0x4af6, 0x9e, 0x50, 0xfc, 0xb3, 0xa8, 0x86, 0x8a, 0x17)\n \n #define RISCV_EFI_BOOT_PROTOCOL_GUID\t\tEFI_GUID(0xccd15fec, 0x6f73, 0x4eec, 0x83, 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf)\n \n@@ -1273,6 +1274,41 @@ struct linux_efi_memreserve {\n \n void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size);\n \n+#ifdef CONFIG_EFI_KHO\n+/*\n+ * The LINUX_EFI_KEXEC_HANDOVER_GUID config table points to this structure.\n+ * It carries the kexec handover (KHO) state from the current kernel to the\n+ * next one: the addresses of the KHO state FDT and of the scratch area.\n+ *\n+ * This is the handover channel for architectures that boot through EFI\n+ * without a device tree (e.g. LoongArch), where the /chosen linux,kho-fdt\n+ * and linux,kho-scratch properties read by early_init_dt_check_kho() are not\n+ * available. The EFI stub allocates and installs the table once at boot;\n+ * the current kernel updates its contents before a kexec, and the next\n+ * kernel reads it back and calls kho_populate().\n+ *\n+ * The layout is an ABI between the two kernels and carries no version\n+ * field: an incompatible change must use a new GUID. The handover payload\n+ * itself is versioned separately by the compatible string of the KHO state\n+ * FDT, which kho_populate() checks.\n+ */\n+struct linux_efi_kho_data {\n+\tu64 fdt_addr;\n+\tu64 fdt_size;\n+\tu64 scratch_addr;\n+\tu64 scratch_size;\n+} __packed;\n+\n+int efi_kho_update(phys_addr_t fdt_addr, u64 fdt_size,\n+\t\t phys_addr_t scratch_addr, u64 scratch_size);\n+#else\n+static inline int efi_kho_update(phys_addr_t fdt_addr, u64 fdt_size,\n+\t\t\t\t phys_addr_t scratch_addr, u64 scratch_size)\n+{\n+\treturn 0;\n+}\n+#endif\n+\n /*\n * The LINUX_EFI_MOK_VARIABLE_TABLE_GUID config table can be provided\n * to the kernel by an EFI boot loader. The table contains a packed\ndiff --git a/kernel/crash_core.c b/kernel/crash_core.c\nindex 2b36aa9fade06..6166ce4203d3b 100644\n--- a/kernel/crash_core.c\n+++ b/kernel/crash_core.c\n@@ -138,6 +138,13 @@ void __noclone __crash_kexec(struct pt_regs *regs)\n \t\tif (kexec_crash_image) {\n \t\t\tstruct pt_regs fixed_regs;\n \n+\t\t\t/*\n+\t\t\t * A crash image carries no KHO state: clear the\n+\t\t\t * transport so the crash kernel boots cold instead\n+\t\t\t * of reviving from stale state.\n+\t\t\t */\n+\t\t\t(void)kho_sync_channel(kexec_crash_image);\n+\n \t\t\tcrash_setup_regs(\u0026fixed_regs, regs);\n \t\t\tcrash_save_vmcoreinfo();\n \t\t\tmachine_crash_shutdown(\u0026fixed_regs);\ndiff --git a/kernel/kexec_core.c b/kernel/kexec_core.c\nindex dc770b9a6d053..147f5b5b23d40 100644\n--- a/kernel/kexec_core.c\n+++ b/kernel/kexec_core.c\n@@ -1146,6 +1146,11 @@ int kernel_kexec(void)\n \t\tgoto Unlock;\n \t}\n \n+\t/* Synchronize the handover transport with the image being executed. */\n+\terror = kho_sync_channel(kexec_image);\n+\tif (error)\n+\t\tgoto Unlock;\n+\n \tif (!kexec_image-\u003epreserve_context) {\n \t\terror = liveupdate_reboot();\n \t\tif (error)\ndiff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h\nindex 228bb88c018bc..4d4c2290e85c7 100644\n--- a/kernel/kexec_internal.h\n+++ b/kernel/kexec_internal.h\n@@ -46,6 +46,7 @@ struct kexec_buf;\n int kho_locate_mem_hole(struct kexec_buf *kbuf,\n \t\t\tint (*func)(struct resource *, void *));\n int kho_fill_kimage(struct kimage *image);\n+int kho_sync_channel(struct kimage *image);\n #else\n static inline int kho_locate_mem_hole(struct kexec_buf *kbuf,\n \t\t\t\t int (*func)(struct resource *, void *))\n@@ -54,5 +55,7 @@ static inline int kho_locate_mem_hole(struct kexec_buf *kbuf,\n }\n \n static inline int kho_fill_kimage(struct kimage *image) { return 0; }\n+\n+static inline int kho_sync_channel(struct kimage *image) { return 0; }\n #endif /* CONFIG_KEXEC_HANDOVER */\n #endif /* LINUX_KEXEC_INTERNAL_H */\ndiff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c\nindex 7c4d86daf86d5..b6008c01525d9 100644\n--- a/kernel/liveupdate/kexec_handover.c\n+++ b/kernel/liveupdate/kexec_handover.c\n@@ -14,6 +14,7 @@\n #include \u003clinux/cma.h\u003e\n #include \u003clinux/kmemleak.h\u003e\n #include \u003clinux/count_zeros.h\u003e\n+#include \u003clinux/efi.h\u003e\n #include \u003clinux/kasan.h\u003e\n #include \u003clinux/kexec.h\u003e\n #include \u003clinux/kexec_handover.h\u003e\n@@ -2063,6 +2064,38 @@ int kho_fill_kimage(struct kimage *image)\n \treturn 0;\n }\n \n+/*\n+ * Synchronize the handover transport with the image that is about to be\n+ * executed. The EFI config table channel is global, while kexec keeps\n+ * separate images for a normal reboot and for crash. Write the state of the\n+ * selected image immediately before it is executed, rather than while a\n+ * candidate image is being loaded, so a failed replacement cannot leave the\n+ * channel pointing at that failed image.\n+ *\n+ * An image loaded through the legacy kexec_load() syscall, a crash image, or\n+ * an image loaded while KHO is disabled carries no handover state. Clear the\n+ * channel for those images so the next kernel boots cold instead of reviving\n+ * from stale state. Clearing is best-effort because an absent channel cannot\n+ * affect a cold boot.\n+ */\n+int kho_sync_channel(struct kimage *image)\n+{\n+\tint err;\n+\n+\tif (!image-\u003ekho.fdt || !image-\u003ekho.scratch) {\n+\t\tefi_kho_update(0, 0, 0, 0);\n+\t\treturn 0;\n+\t}\n+\n+\terr = efi_kho_update(image-\u003ekho.fdt, PAGE_SIZE,\n+\t\t\t image-\u003ekho.scratch-\u003emem,\n+\t\t\t image-\u003ekho.scratch-\u003ebufsz);\n+\tif (err)\n+\t\tpr_warn(\"failed to update EFI config table: %d\\n\", err);\n+\n+\treturn err;\n+}\n+\n static int kho_walk_scratch(struct kexec_buf *kbuf,\n \t\t\t int (*func)(struct resource *, void *))\n {\ndiff --git a/kernel/liveupdate/kho_block.c b/kernel/liveupdate/kho_block.c\nindex 0d2a342ef4228..0d56891b2f4c8 100644\n--- a/kernel/liveupdate/kho_block.c\n+++ b/kernel/liveupdate/kho_block.c\n@@ -25,6 +25,7 @@\n #include \u003clinux/kho/abi/block.h\u003e\n #include \u003clinux/kho_block.h\u003e\n #include \u003clinux/slab.h\u003e\n+#include \u003clinux/mm.h\u003e\n \n /*\n * Safeguard limit for the number of serialization blocks. This is used to\ndiff --git a/tools/testing/selftests/kho/loongarch.conf b/tools/testing/selftests/kho/loongarch.conf\nnew file mode 100644\nindex 0000000000000..36153b03c4efb\n--- /dev/null\n+++ b/tools/testing/selftests/kho/loongarch.conf\n@@ -0,0 +1,11 @@\n+QEMU_EFI=\"${QEMU_EFI:-/usr/share/edk2/loongarch64/QEMU_EFI.fd}\"\n+QEMU_CMD=\"qemu-system-loongarch64 -M virt -cpu la464 -bios $QEMU_EFI\"\n+QEMU_KCONFIG=\"\n+CONFIG_ACPI_SPCR_TABLE=y\n+CONFIG_PCI_HOST_GENERIC=y\n+CONFIG_SERIAL_8250=y\n+CONFIG_SERIAL_8250_CONSOLE=y\n+CONFIG_SPARSEMEM_MANUAL=y\n+\"\n+KERNEL_IMAGE=\"vmlinux.efi\"\n+KERNEL_CMDLINE=\"console=ttyS0 earlycon\"\ndiff --git a/tools/testing/selftests/kho/vmtest.sh b/tools/testing/selftests/kho/vmtest.sh\nindex 0014bd76e88de..d05ba0734b259 100755\n--- a/tools/testing/selftests/kho/vmtest.sh\n+++ b/tools/testing/selftests/kho/vmtest.sh\n@@ -21,7 +21,7 @@ Options:\n \t-d)\tpath to the kernel build directory\n \t-j)\tnumber of jobs for compilation, similar to -j in make\n \t-t)\trun test for target_arch, requires CROSS_COMPILE set\n-\t\tsupported targets: aarch64, x86_64\n+\t\tsupported targets: aarch64, loongarch64, x86_64\n \t-h)\tdisplay this help\n EOF\n }\n@@ -126,6 +126,7 @@ function target_to_arch() {\n \n \tcase $target in\n \t aarch64) echo \"arm64\" ;;\n+\t loongarch64) echo \"loongarch\" ;;\n \t x86_64) echo \"x86\" ;;\n \t *) skip \"architecture $target is not supported\"\n \tesac\n"
} |
| 2/1 | 2026/09/05 19:21 | agent | patch-evaluator |
0mModel:core Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch introduces EFI configuration table transport for kexec handover (KHO), targeted at architectures that boot through EFI without device tree (such as LoongArch). The new config CONFIG_EFI_KHO is only selected by arch/loongarch/Kconfig and cannot be enabled on the target architecture (amd64). On amd64, all EFI KHO logic in the EFI drivers and libstub is compiled out, efi_kho_update() is an inline no-op returning 0, and the remaining changes are selftest scripts and a header inclusion. Therefore, no reachable executable code is modified for amd64.",
"WorthFuzzing": false
}Instruction: You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.
IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.
================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.
- REACHABILITY IS THE PRIMARY GATE:
Fuzzing can only discover bugs in code that can actually execute in standard virtualized
environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
regardless of whether it adds assertions or complex logic.
- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
Patch authors routinely label changes as "cleanups", "refactorings", or state
"No functional change intended". Do NOT take these claims at face value.
Code refactorings that rearrange logic, introduce helper functions, or alter state management
in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
If reachable executable code is modified or refactored, it MUST be fuzzed.
- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
Even if the author believes the invariant always holds, fuzzing is essential to verify whether
an unusual sequence of operations can violate it.
================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:
- Non-kernel and non-executable changes:
* Modifications to Documentation/, comments, or spelling fixes.
* User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
that do not affect the compiled kernel image (vmlinux) or kernel modules.
* Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
that do not alter control flow or data structures.
* Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
* Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
* Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
physical PCI hot-unplug or manual sysfs driver unbinding.
* Code paths exclusive to architectures other than the target architecture.
================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
* Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
* Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
* Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
* Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).
================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:
- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
Do NOT list generic, ubiquitous functions called by almost every program in the corpus
(including, but not limited to: general memory allocators and deallocators, page fault
and trap handlers, or core synchronization primitives; this is not an exhaustive list).
Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
which severely dilutes fuzzing effort away from the actual changes.
- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
List functions that specifically implement the logic being added or altered, or direct API entrypoints
for the subsystem feature under review.
- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).
================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit 1d1354e17143c5874863dc5a7a88f3ce23789967
Author: syz-cluster <triage@syzkaller.com>
Date: Sat Sep 5 19:21:22 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index a21f51e5815e9..5eaa65578d58e 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -685,6 +685,10 @@ config ARCH_SUPPORTS_KEXEC
config ARCH_SUPPORTS_KEXEC_FILE
def_bool 64BIT
+config ARCH_SUPPORTS_KEXEC_HANDOVER
+ def_bool 64BIT && EFI_STUB
+ select EFI_KHO if KEXEC_HANDOVER
+
config ARCH_SELECTS_KEXEC_FILE
def_bool 64BIT
depends on KEXEC_FILE
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 29e0729299f5b..d6c1372484b4b 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -314,6 +314,18 @@ config EFI_SBAT_FILE
If unsure, leave blank.
+config EFI_KHO
+ bool
+ depends on EFI_STUB && EFI_GENERIC_STUB && KEXEC_HANDOVER
+ help
+ Carry the KHO state (the KHO state FDT and the scratch area) from
+ one kernel to the next across kexec via an EFI configuration table
+ entry under LINUX_EFI_KEXEC_HANDOVER_GUID, for architectures that
+ boot through EFI without a device tree (e.g. LoongArch).
+
+ Architectures with a boot FDT (arm64, riscv) use the /chosen FDT
+ path instead and do not select this.
+
endmenu
config UEFI_CPER
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 0327a39d31fa5..6380cfab1493e 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -24,6 +24,7 @@
#include <linux/initrd.h>
#include <linux/io.h>
#include <linux/kexec.h>
+#include <linux/kexec_handover.h>
#include <linux/platform_device.h>
#include <linux/random.h>
#include <linux/reboot.h>
@@ -62,6 +63,9 @@ unsigned long __ro_after_init efi_rng_seed = EFI_INVALID_TABLE_ADDR;
static unsigned long __initdata mem_reserve = EFI_INVALID_TABLE_ADDR;
static unsigned long __initdata rt_prop = EFI_INVALID_TABLE_ADDR;
static unsigned long __initdata initrd = EFI_INVALID_TABLE_ADDR;
+#ifdef CONFIG_EFI_KHO
+static unsigned long __ro_after_init efi_kho_table_phys = EFI_INVALID_TABLE_ADDR;
+#endif
extern unsigned long primary_display_table;
@@ -629,6 +633,9 @@ static const efi_config_table_type_t common_tables[] __initconst = {
{EFI_TCG2_FINAL_EVENTS_TABLE_GUID, &efi.tpm_final_log, "TPMFinalLog" },
{EFI_CC_FINAL_EVENTS_TABLE_GUID, &efi.tpm_final_log, "CCFinalLog" },
{LINUX_EFI_MEMRESERVE_TABLE_GUID, &mem_reserve, "MEMRESERVE" },
+#ifdef CONFIG_EFI_KHO
+ {LINUX_EFI_KEXEC_HANDOVER_GUID, &efi_kho_table_phys, "KHO" },
+#endif
{LINUX_EFI_INITRD_MEDIA_GUID, &initrd, "INITRD" },
{EFI_RT_PROPERTIES_TABLE_GUID, &rt_prop, "RTPROP" },
#ifdef CONFIG_OVMF_DEBUG_LOG
@@ -806,6 +813,31 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
}
}
+#ifdef CONFIG_EFI_KHO
+ if (efi_kho_table_phys != EFI_INVALID_TABLE_ADDR) {
+ struct linux_efi_kho_data *kho;
+
+ /*
+ * Reserve the stub-allocated table so it is neither handed
+ * out by the buddy allocator nor placed on by kexec
+ * segments, mirroring the memreserve handling above. This
+ * runs on every boot, so it also protects the table in the
+ * next kernel until it reads it.
+ */
+ memblock_reserve(efi_kho_table_phys, sizeof(*kho));
+
+ kho = early_memremap(efi_kho_table_phys, sizeof(*kho));
+ if (kho) {
+ if (kho->fdt_addr)
+ kho_populate((phys_addr_t)kho->fdt_addr,
+ kho->fdt_size,
+ (phys_addr_t)kho->scratch_addr,
+ kho->scratch_size);
+ early_memunmap(kho, sizeof(*kho));
+ }
+ }
+#endif
+
if (rt_prop != EFI_INVALID_TABLE_ADDR) {
efi_rt_properties_table_t *tbl;
@@ -1171,6 +1203,52 @@ static int __init efi_memreserve_root_init(void)
}
early_initcall(efi_memreserve_root_init);
+#ifdef CONFIG_EFI_KHO
+static struct linux_efi_kho_data *efi_kho_table __ro_after_init;
+
+static int __init efi_kho_table_init(void)
+{
+ if (efi_kho_table_phys == EFI_INVALID_TABLE_ADDR)
+ return 0;
+
+ /*
+ * Keep a persistent mapping of the table, the same way
+ * efi_memreserve_root_init() keeps the memreserve root mapped:
+ * efi_kho_update() is also called on the crash kexec path, where
+ * memremap() is no longer an option.
+ */
+ efi_kho_table = memremap(efi_kho_table_phys, sizeof(*efi_kho_table),
+ MEMREMAP_WB);
+ WARN_ON_ONCE(!efi_kho_table);
+
+ return 0;
+}
+early_initcall(efi_kho_table_init);
+
+/*
+ * Update the KHO config table in place before a kexec, so the next kernel
+ * finds the current handover state. Mirrors efi_mem_reserve_persistent():
+ * the config table entry was installed once by the EFI stub and is inherited
+ * across kexec, so only the table contents are rewritten here -- the config
+ * table array is never rebuilt and st->tables is never switched.
+ */
+int efi_kho_update(phys_addr_t fdt_addr, u64 fdt_size,
+ phys_addr_t scratch_addr, u64 scratch_size)
+{
+ struct linux_efi_kho_data *kho = efi_kho_table;
+
+ if (!kho)
+ return -ENODEV;
+
+ kho->fdt_addr = fdt_addr;
+ kho->fdt_size = fdt_size;
+ kho->scratch_addr = scratch_addr;
+ kho->scratch_size = scratch_size;
+
+ return 0;
+}
+#endif
+
#ifdef CONFIG_KEXEC
static int update_efi_random_seed(struct notifier_block *nb,
unsigned long code, void *unused)
diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
index 42d6073bcd062..751f46280433b 100644
--- a/drivers/firmware/efi/libstub/efi-stub.c
+++ b/drivers/firmware/efi/libstub/efi-stub.c
@@ -100,6 +100,29 @@ static void install_memreserve_table(void)
efi_err("Failed to install memreserve config table!\n");
}
+static void install_kho_table(void)
+{
+#ifdef CONFIG_EFI_KHO
+ struct linux_efi_kho_data *kho;
+ efi_guid_t kho_table_guid = LINUX_EFI_KEXEC_HANDOVER_GUID;
+ efi_status_t status;
+
+ status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(*kho),
+ (void **)&kho);
+ if (status != EFI_SUCCESS) {
+ efi_err("Failed to allocate KHO config table!\n");
+ return;
+ }
+
+ *kho = (struct linux_efi_kho_data){};
+
+ status = efi_bs_call(install_configuration_table, &kho_table_guid,
+ kho);
+ if (status != EFI_SUCCESS)
+ efi_err("Failed to install KHO config table!\n");
+#endif
+}
+
static u32 get_supported_rt_services(void)
{
const efi_rt_properties_table_t *rt_prop_table;
@@ -180,6 +203,8 @@ efi_status_t efi_stub_common(efi_handle_t handle,
install_memreserve_table();
+ install_kho_table();
+
status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr);
free_primary_display(dpy);
diff --git a/include/linux/efi.h b/include/linux/efi.h
index aa15ff88539bd..564b3cbd5ccb8 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -422,6 +422,7 @@ void efi_native_runtime_setup(void);
#define LINUX_EFI_COCO_SECRET_AREA_GUID EFI_GUID(0xadf956ad, 0xe98c, 0x484c, 0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47)
#define LINUX_EFI_BOOT_MEMMAP_GUID EFI_GUID(0x800f683f, 0xd08b, 0x423a, 0xa2, 0x93, 0x96, 0x5c, 0x3c, 0x6f, 0xe2, 0xb4)
#define LINUX_EFI_UNACCEPTED_MEM_TABLE_GUID EFI_GUID(0xd5d1de3c, 0x105c, 0x44f9, 0x9e, 0xa9, 0xbc, 0xef, 0x98, 0x12, 0x00, 0x31)
+#define LINUX_EFI_KEXEC_HANDOVER_GUID EFI_GUID(0xc941b6c7, 0x7b3f, 0x4af6, 0x9e, 0x50, 0xfc, 0xb3, 0xa8, 0x86, 0x8a, 0x17)
#define RISCV_EFI_BOOT_PROTOCOL_GUID EFI_GUID(0xccd15fec, 0x6f73, 0x4eec, 0x83, 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf)
@@ -1273,6 +1274,41 @@ struct linux_efi_memreserve {
void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size);
+#ifdef CONFIG_EFI_KHO
+/*
+ * The LINUX_EFI_KEXEC_HANDOVER_GUID config table points to this structure.
+ * It carries the kexec handover (KHO) state from the current kernel to the
+ * next one: the addresses of the KHO state FDT and of the scratch area.
+ *
+ * This is the handover channel for architectures that boot through EFI
+ * without a device tree (e.g. LoongArch), where the /chosen linux,kho-fdt
+ * and linux,kho-scratch properties read by early_init_dt_check_kho() are not
+ * available. The EFI stub allocates and installs the table once at boot;
+ * the current kernel updates its contents before a kexec, and the next
+ * kernel reads it back and calls kho_populate().
+ *
+ * The layout is an ABI between the two kernels and carries no version
+ * field: an incompatible change must use a new GUID. The handover payload
+ * itself is versioned separately by the compatible string of the KHO state
+ * FDT, which kho_populate() checks.
+ */
+struct linux_efi_kho_data {
+ u64 fdt_addr;
+ u64 fdt_size;
+ u64 scratch_addr;
+ u64 scratch_size;
+} __packed;
+
+int efi_kho_update(phys_addr_t fdt_addr, u64 fdt_size,
+ phys_addr_t scratch_addr, u64 scratch_size);
+#else
+static inline int efi_kho_update(phys_addr_t fdt_addr, u64 fdt_size,
+ phys_addr_t scratch_addr, u64 scratch_size)
+{
+ return 0;
+}
+#endif
+
/*
* The LINUX_EFI_MOK_VARIABLE_TABLE_GUID config table can be provided
* to the kernel by an EFI boot loader. The table contains a packed
diff --git a/kernel/crash_core.c b/kernel/crash_core.c
index 2b36aa9fade06..6166ce4203d3b 100644
--- a/kernel/crash_core.c
+++ b/kernel/crash_core.c
@@ -138,6 +138,13 @@ void __noclone __crash_kexec(struct pt_regs *regs)
if (kexec_crash_image) {
struct pt_regs fixed_regs;
+ /*
+ * A crash image carries no KHO state: clear the
+ * transport so the crash kernel boots cold instead
+ * of reviving from stale state.
+ */
+ (void)kho_sync_channel(kexec_crash_image);
+
crash_setup_regs(&fixed_regs, regs);
crash_save_vmcoreinfo();
machine_crash_shutdown(&fixed_regs);
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index dc770b9a6d053..147f5b5b23d40 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -1146,6 +1146,11 @@ int kernel_kexec(void)
goto Unlock;
}
+ /* Synchronize the handover transport with the image being executed. */
+ error = kho_sync_channel(kexec_image);
+ if (error)
+ goto Unlock;
+
if (!kexec_image->preserve_context) {
error = liveupdate_reboot();
if (error)
diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h
index 228bb88c018bc..4d4c2290e85c7 100644
--- a/kernel/kexec_internal.h
+++ b/kernel/kexec_internal.h
@@ -46,6 +46,7 @@ struct kexec_buf;
int kho_locate_mem_hole(struct kexec_buf *kbuf,
int (*func)(struct resource *, void *));
int kho_fill_kimage(struct kimage *image);
+int kho_sync_channel(struct kimage *image);
#else
static inline int kho_locate_mem_hole(struct kexec_buf *kbuf,
int (*func)(struct resource *, void *))
@@ -54,5 +55,7 @@ static inline int kho_locate_mem_hole(struct kexec_buf *kbuf,
}
static inline int kho_fill_kimage(struct kimage *image) { return 0; }
+
+static inline int kho_sync_channel(struct kimage *image) { return 0; }
#endif /* CONFIG_KEXEC_HANDOVER */
#endif /* LINUX_KEXEC_INTERNAL_H */
diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index 7c4d86daf86d5..b6008c01525d9 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -14,6 +14,7 @@
#include <linux/cma.h>
#include <linux/kmemleak.h>
#include <linux/count_zeros.h>
+#include <linux/efi.h>
#include <linux/kasan.h>
#include <linux/kexec.h>
#include <linux/kexec_handover.h>
@@ -2063,6 +2064,38 @@ int kho_fill_kimage(struct kimage *image)
return 0;
}
+/*
+ * Synchronize the handover transport with the image that is about to be
+ * executed. The EFI config table channel is global, while kexec keeps
+ * separate images for a normal reboot and for crash. Write the state of the
+ * selected image immediately before it is executed, rather than while a
+ * candidate image is being loaded, so a failed replacement cannot leave the
+ * channel pointing at that failed image.
+ *
+ * An image loaded through the legacy kexec_load() syscall, a crash image, or
+ * an image loaded while KHO is disabled carries no handover state. Clear the
+ * channel for those images so the next kernel boots cold instead of reviving
+ * from stale state. Clearing is best-effort because an absent channel cannot
+ * affect a cold boot.
+ */
+int kho_sync_channel(struct kimage *image)
+{
+ int err;
+
+ if (!image->kho.fdt || !image->kho.scratch) {
+ efi_kho_update(0, 0, 0, 0);
+ return 0;
+ }
+
+ err = efi_kho_update(image->kho.fdt, PAGE_SIZE,
+ image->kho.scratch->mem,
+ image->kho.scratch->bufsz);
+ if (err)
+ pr_warn("failed to update EFI config table: %d\n", err);
+
+ return err;
+}
+
static int kho_walk_scratch(struct kexec_buf *kbuf,
int (*func)(struct resource *, void *))
{
diff --git a/kernel/liveupdate/kho_block.c b/kernel/liveupdate/kho_block.c
index 0d2a342ef4228..0d56891b2f4c8 100644
--- a/kernel/liveupdate/kho_block.c
+++ b/kernel/liveupdate/kho_block.c
@@ -25,6 +25,7 @@
#include <linux/kho/abi/block.h>
#include <linux/kho_block.h>
#include <linux/slab.h>
+#include <linux/mm.h>
/*
* Safeguard limit for the number of serialization blocks. This is used to
diff --git a/tools/testing/selftests/kho/loongarch.conf b/tools/testing/selftests/kho/loongarch.conf
new file mode 100644
index 0000000000000..36153b03c4efb
--- /dev/null
+++ b/tools/testing/selftests/kho/loongarch.conf
@@ -0,0 +1,11 @@
+QEMU_EFI="${QEMU_EFI:-/usr/share/edk2/loongarch64/QEMU_EFI.fd}"
+QEMU_CMD="qemu-system-loongarch64 -M virt -cpu la464 -bios $QEMU_EFI"
+QEMU_KCONFIG="
+CONFIG_ACPI_SPCR_TABLE=y
+CONFIG_PCI_HOST_GENERIC=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SPARSEMEM_MANUAL=y
+"
+KERNEL_IMAGE="vmlinux.efi"
+KERNEL_CMDLINE="console=ttyS0 earlycon"
diff --git a/tools/testing/selftests/kho/vmtest.sh b/tools/testing/selftests/kho/vmtest.sh
index 0014bd76e88de..d05ba0734b259 100755
--- a/tools/testing/selftests/kho/vmtest.sh
+++ b/tools/testing/selftests/kho/vmtest.sh
@@ -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, loongarch64, x86_64
-h) display this help
EOF
}
@@ -126,6 +126,7 @@ function target_to_arch() {
case $target in
aarch64) echo "arm64" ;;
+ loongarch64) echo "loongarch" ;;
x86_64) echo "x86" ;;
*) skip "architecture $target is not supported"
esac
|
| 3/2 | 2026/09/05 19:21 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 8497 output: 38 thoughts: 295 Thoughts: **Analyzing this Patch for AMD64 Compatibility** Okay, so the architecture in play is amd64, which is my bread and butter. I need to understand this patch and how it'll affect the system. First, I'm going to take a really close look at the commit message and the diff itself – that's crucial. I see changes across a few areas: `arch/loongarch/Kconfig`, `drivers/firmware/efi/*`, `include/linux/efi.h`, `kernel/crash_core.c`, `kernel/kexec_*` files, and some test-related files in `tools/testing/selftests/kho/`. That's a pretty broad scope, which usually means it's pretty important. My main focus right now is to understand the Kconfig options, particularly how `KEXEC_HANDOVER`, `EFI_KHO`, and related settings behave. Are they general, or are there any architecture-specific quirks? Are there any dependencies here that are going to bite me later? I'll pay close attention to the x86_64 aspects, since that's where I need to make sure things are working correctly. To dig into that, I'm going to use `grepper` and search for instances of `KEXEC_HANDOVER` in the codebase to understand its usage and dependencies. This should reveal how it's used across the architecture. |
| 4/2 | 2026/09/05 19:21 | tool | grepper |
0mArgs:{
"Expression": "config (KEXEC_HANDOVER|ARCH_SUPPORTS_KEXEC_HANDOVER|EFI_KHO)"
}Results: {
"Output": "arch/arm64/Kconfig=1708=config ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG\n--\narch/arm64/Kconfig-1710-\narch/arm64/Kconfig:1711:config ARCH_SUPPORTS_KEXEC_HANDOVER\narch/arm64/Kconfig-1712-\tdef_bool y\n--\narch/loongarch/Kconfig=685=config ARCH_SUPPORTS_KEXEC_FILE\n--\narch/loongarch/Kconfig-687-\narch/loongarch/Kconfig:688:config ARCH_SUPPORTS_KEXEC_HANDOVER\narch/loongarch/Kconfig-689-\tdef_bool 64BIT \u0026\u0026 EFI_STUB\n--\narch/x86/Kconfig=1978=config ARCH_SUPPORTS_KEXEC_JUMP\n--\narch/x86/Kconfig-1980-\narch/x86/Kconfig:1981:config ARCH_SUPPORTS_KEXEC_HANDOVER\narch/x86/Kconfig-1982-\tdef_bool X86_64\n--\ndrivers/firmware/efi/Kconfig=296=config EFI_SBAT_FILE\n--\ndrivers/firmware/efi/Kconfig-316-\ndrivers/firmware/efi/Kconfig:317:config EFI_KHO\ndrivers/firmware/efi/Kconfig-318-\tbool\n--\nkernel/liveupdate/Kconfig=3=menu \"Live Update and Kexec HandOver\"\nkernel/liveupdate/Kconfig-4-\nkernel/liveupdate/Kconfig:5:config KEXEC_HANDOVER\nkernel/liveupdate/Kconfig-6-\tbool \"kexec handover\"\n--\nkernel/liveupdate/Kconfig-17-\nkernel/liveupdate/Kconfig:18:config KEXEC_HANDOVER_DEBUG\nkernel/liveupdate/Kconfig-19-\tbool \"Enable Kexec Handover debug checks\"\n--\nkernel/liveupdate/Kconfig-26-\nkernel/liveupdate/Kconfig:27:config KEXEC_HANDOVER_DEBUGFS\nkernel/liveupdate/Kconfig-28-\tbool \"kexec handover debugfs interface\"\n--\nkernel/liveupdate/Kconfig-37-\nkernel/liveupdate/Kconfig:38:config KEXEC_HANDOVER_ENABLE_DEFAULT\nkernel/liveupdate/Kconfig-39-\tbool \"Enable kexec handover by default\"\n"
} |
| 5/2 | 2026/09/05 19:21 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 9744 output: 35 thoughts: 47 Thoughts: Okay, let's dive into this. Here's how I'd approach this task, as if these were my internal thoughts: **Analyzing KEXEC Handover and EFI_KHO on x86_64** Right, so I need to understand the interaction between `KEXEC_HANDOVER` and `EFI_KHO` specifically within the x86_64 architecture. That means I should start by looking at the configuration files. My immediate focus will be on `arch/x86/Kconfig` to grasp the x86_64-specific implications. Then, I need to see how the live update component interacts with those options, so I should cross-reference this with `kernel/liveupdate/Kconfig`. I'm hoping this will illuminate how these features are managed and what conditions enable them on x86_64. Hopefully, the Kconfig files will clearly outline the dependencies, defaults, and any architectural quirks involved in either handover mechanisms when enabled on an x86\_64 system. |
| 6/2 | 2026/09/05 19:21 | tool | grepper |
0mArgs:{
"Expression": "EFI_KHO|KEXEC_HANDOVER",
"PathPrefix": "arch/x86"
}Results: {
"Output": "arch/x86/Kconfig=1978=config ARCH_SUPPORTS_KEXEC_JUMP\n--\narch/x86/Kconfig-1980-\narch/x86/Kconfig:1981:config ARCH_SUPPORTS_KEXEC_HANDOVER\narch/x86/Kconfig-1982-\tdef_bool X86_64\n--\narch/x86/boot/compressed/kaslr.c=770=static bool process_kho_entries(unsigned long minimum, unsigned long image_size)\n--\narch/x86/boot/compressed/kaslr.c-776-\narch/x86/boot/compressed/kaslr.c:777:\tif (!IS_ENABLED(CONFIG_KEXEC_HANDOVER))\narch/x86/boot/compressed/kaslr.c-778-\t\treturn false;\n--\narch/x86/kernel/kexec-bzimage64.c=274=static void setup_kho(const struct kimage *image, struct boot_params *params,\n--\narch/x86/kernel/kexec-bzimage64.c-280-\narch/x86/kernel/kexec-bzimage64.c:281:\tif (!IS_ENABLED(CONFIG_KEXEC_HANDOVER))\narch/x86/kernel/kexec-bzimage64.c-282-\t\treturn;\n--\narch/x86/kernel/kexec-bzimage64.c=301=setup_boot_parameters(struct kimage *image, struct boot_params *params,\n--\narch/x86/kernel/kexec-bzimage64.c-390-\narch/x86/kernel/kexec-bzimage64.c:391:\tif (IS_ENABLED(CONFIG_KEXEC_HANDOVER)) {\narch/x86/kernel/kexec-bzimage64.c-392-\t\t/* Setup space to store preservation metadata */\n--\narch/x86/kernel/kexec-bzimage64.c=475=static void *bzImage64_load(struct kimage *image, char *kernel,\n--\narch/x86/kernel/kexec-bzimage64.c-581-\narch/x86/kernel/kexec-bzimage64.c:582:\tif (IS_ENABLED(CONFIG_KEXEC_HANDOVER))\narch/x86/kernel/kexec-bzimage64.c-583-\t\tkbuf.bufsz += sizeof(struct setup_data) +\n--\narch/x86/kernel/setup.c=457=static void __init add_kho(u64 phys_addr, u32 data_len)\n--\narch/x86/kernel/setup.c-462-\narch/x86/kernel/setup.c:463:\tif (!IS_ENABLED(CONFIG_KEXEC_HANDOVER)) {\narch/x86/kernel/setup.c:464:\t\tpr_warn(\"Passed KHO data, but CONFIG_KEXEC_HANDOVER not set. Ignoring.\\n\");\narch/x86/kernel/setup.c-465-\t\treturn;\n"
} |
| 7/2 | 2026/09/05 19:21 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 10847 output: 25 thoughts: 44 Thoughts: Okay, let's break this down. **Investigating the EFI_KHO Configuration Option** Right, so I'm looking at the `arch/x86/Kconfig` file. Specifically, I'm checking to see if `EFI_KHO` is directly enabled there. Nope, doesn't seem to be. Interesting. That tells me it's not a straightforward, default-on kind of thing within the x86 architecture itself. This means it's likely selected by something else. This means I need to broaden my search. So, I need to figure out *what* is selecting `EFI_KHO` from *anywhere* in the codebase. I need to track down its dependencies. Where's it being pulled in from? Time to dig deeper and figure out the chain of dependencies. |
| 8/2 | 2026/09/05 19:21 | tool | grepper |
0mArgs:{
"Expression": "select.*EFI_KHO|EFI_KHO"
}Results: {
"Output": "arch/loongarch/Kconfig=688=config ARCH_SUPPORTS_KEXEC_HANDOVER\narch/loongarch/Kconfig-689-\tdef_bool 64BIT \u0026\u0026 EFI_STUB\narch/loongarch/Kconfig:690:\tselect EFI_KHO if KEXEC_HANDOVER\narch/loongarch/Kconfig-691-\n--\ndrivers/firmware/efi/Kconfig=296=config EFI_SBAT_FILE\n--\ndrivers/firmware/efi/Kconfig-316-\ndrivers/firmware/efi/Kconfig:317:config EFI_KHO\ndrivers/firmware/efi/Kconfig-318-\tbool\n--\ndrivers/firmware/efi/efi.c=65=static unsigned long __initdata initrd = EFI_INVALID_TABLE_ADDR;\ndrivers/firmware/efi/efi.c:66:#ifdef CONFIG_EFI_KHO\ndrivers/firmware/efi/efi.c-67-static unsigned long __ro_after_init efi_kho_table_phys = EFI_INVALID_TABLE_ADDR;\n--\ndrivers/firmware/efi/efi.c=624=static const efi_config_table_type_t common_tables[] __initconst = {\n--\ndrivers/firmware/efi/efi.c-635-\t{LINUX_EFI_MEMRESERVE_TABLE_GUID,\t\u0026mem_reserve,\t\t\"MEMRESERVE\"\t},\ndrivers/firmware/efi/efi.c:636:#ifdef CONFIG_EFI_KHO\ndrivers/firmware/efi/efi.c-637-\t{LINUX_EFI_KEXEC_HANDOVER_GUID,\t\t\u0026efi_kho_table_phys,\t\"KHO\"\t\t},\n--\ndrivers/firmware/efi/efi.c=716=int __init efi_config_parse_tables(const efi_config_table_t *config_tables,\n--\ndrivers/firmware/efi/efi.c-815-\ndrivers/firmware/efi/efi.c:816:#ifdef CONFIG_EFI_KHO\ndrivers/firmware/efi/efi.c-817-\tif (efi_kho_table_phys != EFI_INVALID_TABLE_ADDR) {\n--\ndrivers/firmware/efi/efi.c=1204=early_initcall(efi_memreserve_root_init);\ndrivers/firmware/efi/efi.c-1205-\ndrivers/firmware/efi/efi.c:1206:#ifdef CONFIG_EFI_KHO\ndrivers/firmware/efi/efi.c-1207-static struct linux_efi_kho_data *efi_kho_table __ro_after_init;\n--\ndrivers/firmware/efi/libstub/efi-stub.c=103=static void install_kho_table(void)\ndrivers/firmware/efi/libstub/efi-stub.c-104-{\ndrivers/firmware/efi/libstub/efi-stub.c:105:#ifdef CONFIG_EFI_KHO\ndrivers/firmware/efi/libstub/efi-stub.c-106-\tstruct linux_efi_kho_data *kho;\n--\ninclude/linux/efi.h=1275=void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size);\ninclude/linux/efi.h-1276-\ninclude/linux/efi.h:1277:#ifdef CONFIG_EFI_KHO\ninclude/linux/efi.h-1278-/*\n"
} |
| 9/2 | 2026/09/05 19:21 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 11968 output: 41 thoughts: 3709 Thoughts: **Analysis of Kexec Handover Patch for amd64 Architecture** Alright, let's break this down. My initial thought was to dig into the Kconfig options, specifically `EFI_KHO`, and see what the dependencies are. It's immediately clear that `EFI_KHO` is a very specific option, selected only if `EFI_STUB`, `EFI_GENERIC_STUB`, and `KEXEC_HANDOVER` are enabled, with further constraints from the architecture-specific Kconfig file. The key here is its lack of a direct prompt. It's *only* selectable by other options. My investigation led me to `arch/loongarch/Kconfig`, which defines `ARCH_SUPPORTS_KEXEC_HANDOVER` and *selects* `EFI_KHO` *if* `KEXEC_HANDOVER` is also selected. Bingo! This strongly suggests a very targeted use case for architectures booting via EFI *without* a device tree (FDT), as explicitly stated in the help text. I proceeded to meticulously examine all the changes introduced by this patch series: 1. Modified `arch/loongarch/Kconfig` 2. Added `drivers/firmware/efi/Kconfig` and `config EFI_KHO` 3. Changes to `drivers/firmware/efi/efi.c`, including the introduction of `efi_kho_table_phys`, table entries, and related functions within a `#ifdef CONFIG_EFI_KHO` block. 4. Updates to `drivers/firmware/efi/libstub/efi-stub.c`, specifically `install_kho_table`, also protected by `#ifdef CONFIG_EFI_KHO`. 5. Modifications to `include/linux/efi.h` with the introduction of `struct linux_efi_kho_data` and a declaration/stub for `efi_kho_update` 6. Updates in `kernel/crash_core.c` and `kernel/kexec_core.c` including calls to `kho_sync_channel`, which is a key function for handover. 7. The addition of `kho_sync_channel` within `kernel/liveupdate/kexec_handover.c`, which calls `efi_kho_update`. 8. Declaration of `kho_sync_channel()` / stub when `!CONFIG_KEXEC_HANDOVER` in `kernel/kexec_internal.h` 9. Addition of `#include <linux/mm.h>` in `kernel/liveupdate/kho_block.c` 10. Selftest/script changes in `tools/testing/selftests/kho/...` I needed to determine if *any* of this change affects amd64. I confirmed that `CONFIG_EFI_KHO` can **never** be enabled on amd64, because LoongArch's Kconfig is the only place it can be selected. I then checked `grepper` and confirmed nothing else in the kernel tree selected or mentioned `CONFIG_EFI_KHO`. This is critical. On amd64, these changes are not activated. I drilled down further, examining the behavior of `kho_sync_channel` on amd64. I see that even if `CONFIG_KEXEC_HANDOVER` *is* enabled on amd64, `kho_sync_channel` calls `efi_kho_update()`. However, since `CONFIG_EFI_KHO` is *not* defined on amd64, `efi_kho_update()` is just an *inline* function that returns 0. So the function call becomes a no-op. The same is true for `kho_sync_channel`. In summary, even with `CONFIG_KEXEC_HANDOVER` enabled, KHO on amd64 boils down to a trivial no-op. Then I considered other ways kexec handover works, e.g. on x86, which, as I suspected, uses `setup_data` (specifically `SETUP_KHO_MEM`), and not EFI configuration tables. Now, let's connect all the dots and see if the changes are worth fuzzing: * The fundamental logic for EFI-based KHO table handling is entirely gated by `#ifdef CONFIG_EFI_KHO`. This guard is *only* enabled for LoongArch. * The functions added in `drivers/firmware/efi/` are *not* compiled for amd64. * The inclusion of `#include <linux/mm.h>` is a non-executable change and, thus, irrelevant to fuzzing. * The tests in `tools/testing/selftests/` are user-space tests. * `kho_sync_channel` |
| 10/2 | 2026/09/05 19:21 | tool | read-file |
0mArgs:{
"File": "kernel/liveupdate/kexec_handover.c",
"FirstLine": 2060,
"LineCount": 45
}Results: {
"Contents": "2060:\t\tif (err)\n2061:\t\t\treturn err;\n2062:\t\timage-\u003ekho.scratch = \u0026image-\u003esegment[image-\u003enr_segments - 1];\n2063:\t\n2064:\t\treturn 0;\n2065:\t}\n2066:\t\n2067:\t/*\n2068:\t * Synchronize the handover transport with the image that is about to be\n2069:\t * executed. The EFI config table channel is global, while kexec keeps\n2070:\t * separate images for a normal reboot and for crash. Write the state of the\n2071:\t * selected image immediately before it is executed, rather than while a\n2072:\t * candidate image is being loaded, so a failed replacement cannot leave the\n2073:\t * channel pointing at that failed image.\n2074:\t *\n2075:\t * An image loaded through the legacy kexec_load() syscall, a crash image, or\n2076:\t * an image loaded while KHO is disabled carries no handover state. Clear the\n2077:\t * channel for those images so the next kernel boots cold instead of reviving\n2078:\t * from stale state. Clearing is best-effort because an absent channel cannot\n2079:\t * affect a cold boot.\n2080:\t */\n2081:\tint kho_sync_channel(struct kimage *image)\n2082:\t{\n2083:\t\tint err;\n2084:\t\n2085:\t\tif (!image-\u003ekho.fdt || !image-\u003ekho.scratch) {\n2086:\t\t\tefi_kho_update(0, 0, 0, 0);\n2087:\t\t\treturn 0;\n2088:\t\t}\n2089:\t\n2090:\t\terr = efi_kho_update(image-\u003ekho.fdt, PAGE_SIZE,\n2091:\t\t\t\t image-\u003ekho.scratch-\u003emem,\n2092:\t\t\t\t image-\u003ekho.scratch-\u003ebufsz);\n2093:\t\tif (err)\n2094:\t\t\tpr_warn(\"failed to update EFI config table: %d\\n\", err);\n2095:\t\n2096:\t\treturn err;\n2097:\t}\n2098:\t\n2099:\tstatic int kho_walk_scratch(struct kexec_buf *kbuf,\n2100:\t\t\t\t int (*func)(struct resource *, void *))\n2101:\t{\n2102:\t\tint ret = 0;\n2103:\t\tint i;\n2104:\t\n"
} |
| 11/2 | 2026/09/05 19:21 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 17420 output: 161 thoughts: 338 Thoughts: **My Assessment of the KHO Patch on amd64** Okay, I've got this. This patch is adding EFI configuration table support for kexec handover, or KHO, specifically for LoongArch. The important bit here is `CONFIG_EFI_KHO`, and I see that it's tightly bound to `arch/loongarch/Kconfig`. This immediately tells me that it's designed for architectures that boot through EFI *without* a device tree, so it's not relevant to my typical amd64 setup. Looking closer at the amd64 side, as I suspected, everything related to EFI KHO is dead code. The implementation in `drivers/firmware/efi/` is completely `#ifdef CONFIG_EFI_KHO`d out. `efi_kho_update` is just a no-op stub, just returning zero, and `kho_sync_channel()` doesn't actually *do* anything on amd64. Even the test scripts are user-space stuff, so I don't see any exposed kernel entry points. Therefore, `WorthFuzzing` has to be `false`. I can't find anything useful here. So, let's build the argument for `set-results`. I need: * `WorthFuzzing`: `false` * `Reasoning`: "The patch introduces EFI configuration table transport for kexec handover (KHO), specifically for architectures that boot through EFI without a device tree (LoongArch). CONFIG_EFI_KHO is only selected by arch/loongarch/Kconfig and cannot be enabled on the target architecture (amd64). On amd64, all substantive EFI KHO logic is compiled out, efi_kho_update() is a no-op inline returning 0, and the remaining changes consist of selftest scripts and a header include." * `EnableConfigs`: `[]` (nothing to enable) * `FocusSymbols`: `[]` (nothing relevant to focus on) Alright, that's everything. Time to call `set-results`. |
| 12/2 | 2026/09/05 19:21 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch introduces EFI configuration table transport for kexec handover (KHO), targeted at architectures that boot through EFI without device tree (such as LoongArch). The new config CONFIG_EFI_KHO is only selected by arch/loongarch/Kconfig and cannot be enabled on the target architecture (amd64). On amd64, all EFI KHO logic in the EFI drivers and libstub is compiled out, efi_kho_update() is an inline no-op returning 0, and the remaining changes are selftest scripts and a header inclusion. Therefore, no reachable executable code is modified for amd64.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch introduces EFI configuration table transport for kexec handover (KHO), targeted at architectures that boot through EFI without device tree (such as LoongArch). The new config CONFIG_EFI_KHO is only selected by arch/loongarch/Kconfig and cannot be enabled on the target architecture (amd64). On amd64, all EFI KHO logic in the EFI drivers and libstub is compiled out, efi_kho_update() is an inline no-op returning 0, and the remaining changes are selftest scripts and a header inclusion. Therefore, no reachable executable code is modified for amd64.",
"WorthFuzzing": false
} |
| 13/1 | 2026/09/05 19:21 | action | If |
0mArgs:{
"WorthFuzzing": false
}Results: null |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|