LoongArch: Add KHO support and selftests
Subsystems (8)
v6 cover LoongArch: Add KHO support and selftests
From: George Guo <[email protected]>
This series enables Kexec HandOver (KHO) on 64-bit LoongArch and adds LoongArch to the KHO and liveupdate QEMU selftests.
KHO has to give the next kernel two addresses: the KHO FDT and the bootmem area list. arm64 and riscv put them under /chosen in the boot FDT, and x86 puts them in setup_data. LoongArch systems that boot with EFI and ACPI have no boot FDT, so this series passes the addresses in a Linux EFI configuration table:
- On a cold boot, the LoongArch EFI stub installs the table, zeroed. Kernels started by kexec are given the same EFI system table, so they find the same table.
- In early boot, the kernel reserves the table and calls kho_populate() if the table holds KHO state.
- Just before kexec, the kernel writes the KHO state of the image it is about to run, or zeroes the table if that image has none, for example a crash kernel.
A kernel started by kexec from a kernel that did not install the table has no table and cannot pass KHO state on, so LoongArch turns KHO off at boot in that case.
Patch 1 adds the table, and patch 2 writes it at kexec time. Patch 3 fixes a kho_block.c build failure with CONFIG_KFENCE=y on LoongArch. Patch 4 adds kho_disable(). Patch 5 lets the LoongArch memblock arrays grow, which restoring many preserved regions needs, and patch 6 enables KHO on LoongArch. Patches 7 and 8 add LoongArch to the KHO and liveupdate vmtests.
The series is based on liveupdate-7.4 and depends on "liveupdate: kho:
calculate per-node bootmem sizes before allocating any" [1]. Without it, the KHO vmtest fails on a 1 GiB LoongArch guest because KHO cannot reserve its bootmem areas.
Tested in QEMU: the KHO vmtest passes on LoongArch with both CONFIG_NUMA=n and CONFIG_NUMA=y, and run-vmtests.sh passes all four liveupdate tests on x86_64, aarch64 and loongarch64.
Changes since v5:
- Drop CONFIG_EFI_KHO. Only the LoongArch stub installs the table, from efi_boot_kernel(). The other code is built with CONFIG_EFI and does nothing when there is no table (Pratyush).
- efi_kho_update() returns 0 when there is no table, so kexec on other architectures is not affected.
- Warn if the table cannot be mapped in early boot (Pratyush).
- Document each member of struct linux_efi_kho_data and drop __packed
(Pratyush).
- Rename efi_kho_table_phys to efi_kho, mark it __initdata, and join
wrapped lines (Huacai).
- Rename kho_sync_channel() to kho_update_efi_table(), and stop
calling the table a "channel" or "transport" (Mike, Pratyush).
- New patch 4: turn KHO off at boot on LoongArch when the table is
missing.
- New patch 5: allow the memblock arrays to resize on LoongArch. The
liveupdate luo_stress_files test overflowed the reserved array in
the next kernel when CONFIG_SMP was not set.
- New patch 8: add LoongArch to the liveupdate vmtest.
- Rename scratch to bootmem, following Pratyush's rename series.
- Drop the luo_session history from patch 3's commit message
(Pratyush). - Capitalize the subjects and use the kho: prefix (Huacai).
- Rewrite the cover letter and commit messages (Mike, Pratyush).
- Rebase onto liveupdate-7.4.
- No Assisted-by tags, although my v5 reply said patches written with LLM help would carry one: the Assisted-by references have since been removed from the documentation in mainline.
[1] https://lore.kernel.org/all/[email protected]/
v5: https://lore.kernel.org/loongarch/[email protected]/
v4: https://lore.kernel.org/loongarch/[email protected]/
George Guo (8):
efi: Pass KHO state to the next kernel in a configuration table
kho: Write KHO state to the EFI table at kexec time
kho: Include linux/mm.h in kho_block.c
kho: Add kho_disable()
LoongArch: Allow memblock arrays to resize
LoongArch: Enable kexec handover (KHO)
selftests/kho: Add LoongArch vmtest support selftests/liveupdate: Add LoongArch vmtest support
arch/loongarch/Kconfig | 3 + arch/loongarch/kernel/setup.c | 19 ++++++ drivers/firmware/efi/efi.c | 68 +++++++++++++++++++ drivers/firmware/efi/libstub/efi-stub.c | 22 ++++++ drivers/firmware/efi/libstub/efistub.h | 2 + drivers/firmware/efi/libstub/loongarch.c | 2 + include/linux/efi.h | 40 +++++++++++ include/linux/kexec_handover.h | 3 + kernel/crash_core.c | 6 ++ kernel/kexec_core.c | 5 ++ kernel/kexec_internal.h | 8 +++ kernel/liveupdate/kexec_handover.c | 35 ++++++++++ kernel/liveupdate/kho_block.c | 1 + tools/testing/selftests/kho/loongarch.conf | 11 +++ tools/testing/selftests/kho/vmtest.sh | 3 +- .../selftests/liveupdate/config.loongarch64 | 5 ++ .../selftests/liveupdate/run-vmtests.sh | 4 +- tools/testing/selftests/liveupdate/vmtest.sh | 14 +++- 18 files changed, 247 insertions(+), 4 deletions(-) create mode 100644 tools/testing/selftests/kho/loongarch.conf create mode 100644 tools/testing/selftests/liveupdate/config.loongarch64
base-commit: 9a6a70aefe77f6fb9ff2b3037dcf87f6dff65c8c
prerequisite-patch-id: 433e6f8fdec5151f12221a0a34f8fb111b95bb46
Signature · 1 line
2.53.0
PATCH v6 1/8 efi: Pass KHO state to the next kernel in a configuration table
From: George Guo <[email protected]>
KHO has to give the next kernel two addresses: the KHO FDT and the bootmem area list. arm64 and riscv put them under /chosen in the boot FDT. LoongArch systems booting with EFI and ACPI do not require a boot FDT, so KHO needs another way to pass this information.
Add a Linux EFI configuration table for them, under LINUX_EFI_KEXEC_HANDOVER_GUID. It points to a struct linux_efi_kho_data.
- On a cold boot, the LoongArch EFI stub installs the table, zeroed. Each kexec'd kernel is given the same EFI system table, so it finds the same table.
- In early boot, efi_config_parse_tables() reserves the table so neither the page allocator nor kexec segments use it, and calls kho_populate() if the table holds KHO state.
- Provide efi_kho_update() to update the table before kexec. Map the table during boot so updates do not require allocation or mapping at panic time.
- efi_kho_table_found() tells architecture code whether the table was found at boot, so it can turn KHO off when the table is missing.
Only the LoongArch stub installs the table, and only with CONFIG_KEXEC_HANDOVER. Elsewhere there is no table and this code does nothing.
--- drivers/firmware/efi/efi.c | 68 ++++++++++++++++++++++++ drivers/firmware/efi/libstub/efi-stub.c | 22 ++++++++ drivers/firmware/efi/libstub/efistub.h | 2 + drivers/firmware/efi/libstub/loongarch.c | 2 + include/linux/efi.h | 40 ++++++++++++++ 5 files changed, 134 insertions(+)
drivers/firmware/efi/efi.c +68 -0
@@ -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,7 @@ 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 ; +static unsigned long efi_kho__initdata =EFI_INVALID_TABLE_ADDR ;extern unsigned long primary_display_table;
@@ -629,6 +631,7 @@ 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" }, + {LINUX_EFI_KEXEC_HANDOVER_GUID, &efi_kho, "KHO" }, {LINUX_EFI_INITRD_MEDIA_GUID, &initrd, "INITRD" }, {EFI_RT_PROPERTIES_TABLE_GUID, &rt_prop, "RTPROP" }, #ifdef CONFIG_OVMF_DEBUG_LOG
@@ -806,6 +809,23 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables, } } +if (efi_kho !=EFI_INVALID_TABLE_ADDR ) { +struct linux_efi_kho_data *kho; + +/* Keep the buddy allocator and kexec segments off the table. */ +memblock_reserve (efi_kho,sizeof (*kho)); + + kho =early_memremap (efi_kho,sizeof (*kho)); +if (kho) { +if (kho->fdt_addr) +kho_populate ((phys_addr_t )kho->fdt_addr, kho->fdt_size, + (phys_addr_t )kho->bootmem_addr, kho->bootmem_size); +early_memunmap (kho,sizeof (*kho)); + }else { +pr_warn ("Could not map UEFI KHO table!\n" ); + } + } +if (rt_prop !=EFI_INVALID_TABLE_ADDR ) {efi_rt_properties_table_t *tbl;
@@ -1171,6 +1191,54 @@ static int __init efi_memreserve_root_init(void) }early_initcall (efi_memreserve_root_init); +static struct linux_efi_kho_data *efi_kho_table__ro_after_init ; + +/* Did the previous kernel or the EFI stub pass a KHO table? */ +bool __init efi_kho_table_found (void ) +{ +return efi_kho !=EFI_INVALID_TABLE_ADDR ; +} + +static int __init efi_kho_table_init (void ) +{ +if (efi_kho ==EFI_INVALID_TABLE_ADDR ) +return 0 ; + +/* Map it now: the table is also written at panic time. */ + efi_kho_table =memremap (efi_kho,sizeof (*efi_kho_table),MEMREMAP_WB ); +if (WARN_ON_ONCE (!efi_kho_table)) + efi_kho_table =ERR_PTR (-ENOMEM ); + +return 0 ; +} +early_initcall (efi_kho_table_init); + +/* +* Write the KHO addresses the next kernel should use, or zeroes +* if it should boot without KHO. +*/ +int efi_kho_update (phys_addr_t fdt_addr,u64 fdt_size, +phys_addr_t bootmem_addr,u64 bootmem_size) +{ +struct linux_efi_kho_data *kho = efi_kho_table; + +/* +* No table: either the architecture passes the KHO state some other +* way, or it turned KHO off at boot because the table was missing. +*/ +if (!kho) +return 0 ; +if (IS_ERR (kho)) +return PTR_ERR (kho); + + kho->fdt_addr = fdt_addr; + kho->fdt_size = fdt_size; + kho->bootmem_addr = bootmem_addr; + kho->bootmem_size = bootmem_size; + +return 0 ; +} +#ifdef CONFIG_KEXEC static int update_efi_random_seed (struct notifier_block *nb,unsigned long code,void *unused)
drivers/firmware/efi/libstub/efi-stub.c +22 -0
@@ -100,6 +100,28 @@ static void install_memreserve_table(void)efi_err ("Failed to install memreserve config table!\n" ); } +void install_kho_table (void ) +{ +struct linux_efi_kho_data *kho; +efi_guid_t kho_table_guid =LINUX_EFI_KEXEC_HANDOVER_GUID ; +efi_status_t status; + +if (!IS_ENABLED (CONFIG_KEXEC_HANDOVER )) +return ; + + 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" ); +} +static u32 get_supported_rt_services (void ) {const efi_rt_properties_table_t *rt_prop_table;
drivers/firmware/efi/libstub/efistub.h +2 -0
@@ -1057,6 +1057,8 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv,efi_status_t efi_boot_kernel (void *handle,efi_loaded_image_t *image,unsigned long kernel_addr,char *cmdline_ptr); +void install_kho_table (void ); +void *get_fdt (unsigned long *fdt_size); efi_status_t efi_alloc_virtmap(efi_memory_desc_t **virtmap,
drivers/firmware/efi/libstub/loongarch.c +2 -0
@@ -74,6 +74,8 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,efi_status_t status;u32 desc_ver; +install_kho_table (); + status =efi_alloc_virtmap (&priv.runtime_map, &desc_size, &desc_ver);if (status !=EFI_SUCCESS ) {efi_err ("Unable to retrieve UEFI memory map.\n" );
include/linux/efi.h +40 -0
@@ -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,45 @@ struct linux_efi_memreserve {void __init efi_arch_mem_reserve (phys_addr_t addr,u64 size); +/** +* struct linux_efi_kho_data - KHO state passed to the next kernel +* @fdt_addr: physical address of the KHO FDT, 0 if there is none +* @fdt_size: size of the KHO FDT +* @bootmem_addr: physical address of the bootmem area list +* @bootmem_size: size of the bootmem area list +* +* Pointed to by the LINUX_EFI_KEXEC_HANDOVER_GUID configuration table. +* +* The EFI stub installs this table zeroed on a cold boot. It stays +* in place across kexec; the running kernel rewrites it just before +* each kexec, and the next kernel reads it during early boot. +* +* The layout is fixed. Changing it requires a new GUID. +*/ +struct linux_efi_kho_data { +u64 fdt_addr; +u64 fdt_size; +u64 bootmem_addr; +u64 bootmem_size; +}; + +#ifdef CONFIG_EFI +bool efi_kho_table_found (void ); +int efi_kho_update (phys_addr_t fdt_addr,u64 fdt_size, +phys_addr_t bootmem_addr,u64 bootmem_size); +#else +static inline bool efi_kho_table_found (void ) +{ +return false; +} + +static inline int efi_kho_update (phys_addr_t fdt_addr,u64 fdt_size, +phys_addr_t bootmem_addr,u64 bootmem_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
Signature · 1 line
2.53.0
[email protected]
AI reviewRe: [PATCH v6 1/8] efi: Pass KHO state to the next kernel in a configuration table
Sashiko has reviewed this patch and found no issues.
Quoted 22 lines
From: George Guo <[email protected]>
KHO has to give the next kernel two addresses: the KHO FDT and the bootmem area list. arm64 and riscv put them under /chosen in the boot FDT. LoongArch systems booting with EFI and ACPI do not require a boot FDT, so KHO needs another way to pass this information.
Add a Linux EFI configuration table for them, under
LINUX_EFI_KEXEC_HANDOVER_GUID. It points to a structlinux_efi_kho_data.- On a cold boot, the LoongArch EFI stub installs the table, zeroed. Each kexec'd kernel is given the same EFI system table, so it finds the same table.
- In early boot,
efi_config_parse_tables()reserves the table so neither the page allocator nor kexec segments use it, and callskho_populate()if the table holds KHO state.- Provide
efi_kho_update()to update the table before kexec. Map the table during boot so updates do not require allocation or mapping at panic time.
Quoted 8 lines
-
efi_kho_table_found()tells architecture code whether the table was found at boot, so it can turn KHO off when the table is missing.Only the LoongArch stub installs the table, and only with
CONFIG_KEXEC_HANDOVER. Elsewhere there is no table and this code does nothing.Signed-off-by George Guo <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Ard Biesheuvel
maintainerRe: [PATCH v6 1/8] efi: Pass KHO state to the next kernel in a configuration table
In reply to George GuoQuoted 22 lines · George Guo
From: George Guo <[email protected]>
KHO has to give the next kernel two addresses: the KHO FDT and the bootmem area list. arm64 and riscv put them under /chosen in the boot FDT. LoongArch systems booting with EFI and ACPI do not require a boot FDT, so KHO needs another way to pass this information.
Add a Linux EFI configuration table for them, under
LINUX_EFI_KEXEC_HANDOVER_GUID. It points to a structlinux_efi_kho_data.- On a cold boot, the LoongArch EFI stub installs the table, zeroed. Each kexec'd kernel is given the same EFI system table, so it finds the same table.
- In early boot,
efi_config_parse_tables()reserves the table so neither the page allocator nor kexec segments use it, and callskho_populate()if the table holds KHO state.- Provide
efi_kho_update()to update the table before kexec. Map the table during boot so updates do not require allocation or mapping at panic time.
Quoted 7 lines
-
efi_kho_table_found()tells architecture code whether the table was found at boot, so it can turn KHO off when the table is missing.Only the LoongArch stub installs the table, and only with
CONFIG_KEXEC_HANDOVER. Elsewhere there is no table and this code does nothing.
Can we handle this as an arch table then, and handle everything in the LoongArch arch code?
Pratyush Yadav
maintainerRe: [PATCH v6 1/8] efi: Pass KHO state to the next kernel in a configuration table
Hi Ard,
Quoted 26 lines · Ard Biesheuvel
Quoted 25 lines · George Guo
From: George Guo <[email protected]>
KHO has to give the next kernel two addresses: the KHO FDT and the bootmem area list. arm64 and riscv put them under /chosen in the boot FDT. LoongArch systems booting with EFI and ACPI do not require a boot FDT, so KHO needs another way to pass this information.
Add a Linux EFI configuration table for them, under
LINUX_EFI_KEXEC_HANDOVER_GUID. It points to a structlinux_efi_kho_data.- On a cold boot, the LoongArch EFI stub installs the table, zeroed. Each kexec'd kernel is given the same EFI system table, so it finds the same table.
- In early boot,
efi_config_parse_tables()reserves the table so neither the page allocator nor kexec segments use it, and callskho_populate()if the table holds KHO state.- Provide
efi_kho_update()to update the table before kexec. Map the table during boot so updates do not require allocation or mapping at panic time.-
efi_kho_table_found()tells architecture code whether the table was found at boot, so it can turn KHO off when the table is missing.
Quoted 7 lines
Quoted 4 lines
Only the LoongArch stub installs the table, and only with
CONFIG_KEXEC_HANDOVER. Elsewhere there is no table and this code does nothing.Can we handle this as an arch table then, and handle everything in the LoongArch arch code?
I think this is useful for all architectures that use EFI, not only Loongarch. Today Loongarch is the only user, but this can very easily be used by other architectures.
For example, I have been considering moving x86 over to this too. Today we use setup_data. Once we get EFI support, I would like to get rid of that and unify everything under EFI. It is much simpler to have a universal way to pass KHO payload over.
Signature · 2 lines
Regards, Pratyush Yadav
Re: [PATCH v6 1/8] efi: Pass KHO state to the next kernel in a configuration table
In reply to Ard BiesheuvelHi Ard, Pratyush,
Quoted 2 lines · Ard Biesheuvel
Can we handle this as an arch table then, and handle everything in the LoongArch arch code?
Ard, LoongArch is currently the only user, so I understand the suggestion to keep the handling in the architecture code.
My preference is to keep the table definition and handling common, given the potential for x86 to use it as Pratyush described in his reply, to replace setup_data once x86 gains EFI support. The table contains no LoongArch-specific fields, and only the LoongArch stub installs it. On systems without the table, the common code does nothing.
Would that be acceptable, or would you prefer to keep the handling in LoongArch until a second architecture adopts it?
Thanks,
George
Huacai Chen
maintainerRe: [PATCH v6 1/8] efi: Pass KHO state to the next kernel in a configuration table
Quoted 10 lines · George Guo
Hi Ard, Pratyush,
Quoted 2 lines · Ard Biesheuvel
Can we handle this as an arch table then, and handle everything in the LoongArch arch code?
Ard, LoongArch is currently the only user, so I understand the suggestion to keep the handling in the architecture code.
Quoted 8 lines
My preference is to keep the table definition and handling common, given the potential for x86 to use it as Pratyush described in his reply, to replace
setup_dataonce x86 gains EFI support. The table contains no LoongArch-specific fields, and only the LoongArch stub installs it. On systems without the table, the common code does nothing.Would that be acceptable, or would you prefer to keep the handling in LoongArch until a second architecture adopts it?
I prefer to keep it in LoongArch until a second architecture, and I think Ard is the same. But this is not a strong objection to Pratyush.
Huacai
Quoted 3 lines
Thanks,
George
Re: [PATCH v6 1/8] efi: Pass KHO state to the next kernel in a configuration table
In reply to George GuoHi George,
Quoted 74 lines · George Guo
From: George Guo <[email protected]>
KHO has to give the next kernel two addresses: the KHO FDT and the bootmem area list. arm64 and riscv put them under /chosen in the boot FDT. LoongArch systems booting with EFI and ACPI do not require a boot FDT, so KHO needs another way to pass this information.
Add a Linux EFI configuration table for them, under
LINUX_EFI_KEXEC_HANDOVER_GUID. It points to a structlinux_efi_kho_data.- On a cold boot, the LoongArch EFI stub installs the table, zeroed. Each kexec'd kernel is given the same EFI system table, so it finds the same table.
- In early boot,
efi_config_parse_tables()reserves the table so neither the page allocator nor kexec segments use it, and callskho_populate()if the table holds KHO state.- Provide
efi_kho_update()to update the table before kexec. Map the table during boot so updates do not require allocation or mapping at panic time.-
efi_kho_table_found()tells architecture code whether the table was found at boot, so it can turn KHO off when the table is missing.Only the LoongArch stub installs the table, and only with
CONFIG_KEXEC_HANDOVER. Elsewhere there is no table and this code does nothing.Signed-off-by George Guo <[email protected]>--- drivers/firmware/efi/efi.c | 68 ++++++++++++++++++++++++ drivers/firmware/efi/libstub/efi-stub.c | 22 ++++++++ drivers/firmware/efi/libstub/efistub.h | 2 + drivers/firmware/efi/libstub/loongarch.c | 2 + include/linux/efi.h | 40 ++++++++++++++ 5 files changed, 134 insertions(+)drivers/firmware/efi/efi.c +7
-0@@ -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,7 @@ 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 ; +static unsigned long efi_kho__initdata =EFI_INVALID_TABLE_ADDR ;extern unsigned long primary_display_table;@@ -629,6 +631,7 @@ 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" }, + {LINUX_EFI_KEXEC_HANDOVER_GUID, &efi_kho, "KHO" }, {LINUX_EFI_INITRD_MEDIA_GUID, &initrd, "INITRD" }, {EFI_RT_PROPERTIES_TABLE_GUID, &rt_prop, "RTPROP" }, #ifdef CONFIG_OVMF_DEBUG_LOG@@ -806,6 +809,23 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables, } } +if (efi_kho !=EFI_INVALID_TABLE_ADDR ) { +struct linux_efi_kho_data *kho; + +/* Keep the buddy allocator and kexec segments off the table. */
drivers/firmware/efi/efi.c int __init efi_config_parse_tables(const efi_config_table_t *config_tables, · line 825
Quoted 10 lines
drivers/firmware/efi/efi.c +10
-0+memblock_reserve (efi_kho,sizeof (*kho)); + + kho =early_memremap (efi_kho,sizeof (*kho)); +if (kho) { +if (kho->fdt_addr) +kho_populate ((phys_addr_t )kho->fdt_addr, kho->fdt_size, + (phys_addr_t )kho->bootmem_addr, kho->bootmem_size); +early_memunmap (kho,sizeof (*kho)); + }else { +pr_warn ("Could not map UEFI KHO table!\n" );
This is a Linux EFI configuration table, not a __UEFI KHO table__, so IMHO; UEFI wording is wrong here.
Quoted 80 lines
drivers/firmware/efi/efi.c +51
-0+ } + } +if (rt_prop !=EFI_INVALID_TABLE_ADDR ) {efi_rt_properties_table_t *tbl;@@ -1171,6 +1191,54 @@ static int __init efi_memreserve_root_init(void) }early_initcall (efi_memreserve_root_init); +static struct linux_efi_kho_data *efi_kho_table__ro_after_init ; + +/* Did the previous kernel or the EFI stub pass a KHO table? */ +bool __init efi_kho_table_found (void ) +{ +return efi_kho !=EFI_INVALID_TABLE_ADDR ; +} + +static int __init efi_kho_table_init (void ) +{ +if (efi_kho ==EFI_INVALID_TABLE_ADDR ) +return 0 ; + +/* Map it now: the table is also written at panic time. */ + efi_kho_table =memremap (efi_kho,sizeof (*efi_kho_table),MEMREMAP_WB ); +if (WARN_ON_ONCE (!efi_kho_table)) + efi_kho_table =ERR_PTR (-ENOMEM ); + +return 0 ; +} +early_initcall (efi_kho_table_init); + +/* +* Write the KHO addresses the next kernel should use, or zeroes +* if it should boot without KHO. +*/ +int efi_kho_update (phys_addr_t fdt_addr,u64 fdt_size, +phys_addr_t bootmem_addr,u64 bootmem_size) +{ +struct linux_efi_kho_data *kho = efi_kho_table; + +/* +* No table: either the architecture passes the KHO state some other +* way, or it turned KHO off at boot because the table was missing. +*/ +if (!kho) +return 0 ; +if (IS_ERR (kho)) +return PTR_ERR (kho); + + kho->fdt_addr = fdt_addr; + kho->fdt_size = fdt_size; + kho->bootmem_addr = bootmem_addr; + kho->bootmem_size = bootmem_size; + +return 0 ; +} +#ifdef CONFIG_KEXEC static int update_efi_random_seed (struct notifier_block *nb,unsigned long code,void *unused)drivers/firmware/efi/libstub/efi-stub.c +11
-0@@ -100,6 +100,28 @@ static void install_memreserve_table(void)efi_err ("Failed to install memreserve config table!\n" ); } +void install_kho_table (void ) +{ +struct linux_efi_kho_data *kho; +efi_guid_t kho_table_guid =LINUX_EFI_KEXEC_HANDOVER_GUID ; +efi_status_t status; + +if (!IS_ENABLED (CONFIG_KEXEC_HANDOVER )) +return ; + + status =efi_bs_call (allocate_pool,EFI_LOADER_DATA ,sizeof (*kho), (void **)&kho); +if (status !=EFI_SUCCESS ) {
drivers/firmware/efi/libstub/efi-stub.c static void install_memreserve_table(void) · line 123
Quoted 10 lines
drivers/firmware/efi/libstub/efi-stub.c +9
-0+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" );
When install_configuration_table fails, the pool allocation made just above using efi_bs_callis never freed, so a page of EFI_LOADER_DATA is leaked until ExitBootServices, This is a minor leak so mentioned here for review completeness.
Quoted 49 lines
drivers/firmware/efi/libstub/efi-stub.c +2
-0+} +static u32 get_supported_rt_services (void ) {drivers/firmware/efi/libstub/efi-stub.c +0
-0const efi_rt_properties_table_t *rt_prop_table;drivers/firmware/efi/libstub/efistub.h +2
-0@@ -1057,6 +1057,8 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv,efi_status_t efi_boot_kernel (void *handle,efi_loaded_image_t *image,unsigned long kernel_addr,char *cmdline_ptr); +void install_kho_table (void ); +void *get_fdt (unsigned long *fdt_size); efi_status_t efi_alloc_virtmap(efi_memory_desc_t **virtmap,drivers/firmware/efi/libstub/loongarch.c +2
-0@@ -74,6 +74,8 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,efi_status_t status;u32 desc_ver; +install_kho_table (); + status =efi_alloc_virtmap (&priv.runtime_map, &desc_size, &desc_ver);if (status !=EFI_SUCCESS ) {efi_err ("Unable to retrieve UEFI memory map.\n" );include/linux/efi.h +3
-0@@ -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,45 @@ struct linux_efi_memreserve {void __init efi_arch_mem_reserve (phys_addr_t addr,u64 size); +/** +* struct linux_efi_kho_data - KHO state passed to the next kernel
include/linux/efi.h struct linux_efi_memreserve { · line 1288
Quoted 10 lines
include/linux/efi.h +10
-0+* @fdt_addr: physical address of the KHO FDT, 0 if there is none +* @fdt_size: size of the KHO FDT +* @bootmem_addr: physical address of the bootmem area list +* @bootmem_size: size of the bootmem area list +* +* Pointed to by the LINUX_EFI_KEXEC_HANDOVER_GUID configuration table. +* +* The EFI stub installs this table zeroed on a cold boot. It stays +* in place across kexec; the running kernel rewrites it just before +* each kexec, and the next kernel reads it during early boot.
This statement is only true for the LoongArch and on arm64/riscv/x86 no table exists, so the comment describes a kernel-wide invariant that does not hold.
Quoted 30 lines
include/linux/efi.h +27
-0+* +* The layout is fixed. Changing it requires a new GUID. +*/ +struct linux_efi_kho_data { +u64 fdt_addr; +u64 fdt_size; +u64 bootmem_addr; +u64 bootmem_size; +}; + +#ifdef CONFIG_EFI +bool efi_kho_table_found (void ); +int efi_kho_update (phys_addr_t fdt_addr,u64 fdt_size, +phys_addr_t bootmem_addr,u64 bootmem_size); +#else +static inline bool efi_kho_table_found (void ) +{ +return false; +} + +static inline int efi_kho_update (phys_addr_t fdt_addr,u64 fdt_size, +phys_addr_t bootmem_addr,u64 bootmem_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
Signature · 2 lines
Regards, Mukesh Pilaniya
PATCH v6 2/8 kho: Write KHO state to the EFI table at kexec time
In reply to George GuoFrom: George Guo <[email protected]>
On arm64 and riscv, KHO addresses and sizes are passed through /chosen properties in the boot FDT prepared for each kexec image. On x86, they are passed through a SETUP_KEXEC_KHO record linked from the image's boot parameters. These records are per-image, unlike the shared EFI table.
The EFI table is shared. A KHO-enabled normal image and a crash image can both be loaded, but need different contents: the normal image needs the KHO addresses, while the crash image needs an empty table. Updating the table at load time cannot satisfy both.
Write the table in kernel_kexec() and __crash_kexec(), once the image that will run is known. kho_update_efi_table() fills the table from that image, or zeroes it if the image has no KHO state, including images loaded with kexec_load().
Clear the table even with CONFIG_KEXEC_HANDOVER disabled, since the kernel may have inherited a populated table. This prevents a later kernel from trying to revive obsolete KHO state.
The table stores the size of the bootmem area list (bufsz), not of its page-aligned segment, as the FDT and x86 code do. If updating or clearing the table fails, kernel_kexec() returns before liveupdate_reboot(), so LUO does not save state that the next kernel would not find. __crash_kexec() ignores the error so the crash boot can still proceed.
--- kernel/crash_core.c | 6 ++++++ kernel/kexec_core.c | 5 +++++ kernel/kexec_internal.h | 8 ++++++++ kernel/liveupdate/kexec_handover.c | 26 ++++++++++++++++++++++++++ 4 files changed, 45 insertions(+)
kernel/crash_core.c +6 -0
@@ -138,6 +138,12 @@ void __noclone __crash_kexec(struct pt_regs *regs)if (kexec_crash_image) {struct pt_regs fixed_regs; +/* +* A crash image has no KHO state. Zero the EFI +* table so the crash kernel has no inherited KHO state. +*/ + (void )kho_update_efi_table (kexec_crash_image); +crash_setup_regs (&fixed_regs, regs);crash_save_vmcoreinfo ();machine_crash_shutdown (&fixed_regs);
kernel/kexec_core.c +5 -0
@@ -1146,6 +1146,11 @@ int kernel_kexec(void) goto Unlock; } +/* Write this image's KHO state into the EFI table. */ + error =kho_update_efi_table (kexec_image); +if (error) + goto Unlock; +if (!kexec_image->preserve_context) { error =liveupdate_reboot ();if (error)
kernel/kexec_internal.h +8 -0
@@ -2,6 +2,7 @@#ifndef LINUX_KEXEC_INTERNAL_H #define LINUX_KEXEC_INTERNAL_H +#include <linux/efi.h> #include <linux/kexec.h> struct kexec_segment ;
@@ -46,6 +47,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_update_efi_table (struct kimage *image);#else static inline int kho_locate_mem_hole (struct kexec_buf *kbuf,int (*func)(struct resource *,void *))
@@ -54,5 +56,11 @@ 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_update_efi_table (struct kimage *image) +{ +/* The previous kernel may have left KHO state in the EFI table. */ +return efi_kho_update (0 ,0 ,0 ,0 ); +}#endif /* CONFIG_KEXEC_HANDOVER */ #endif /* LINUX_KEXEC_INTERNAL_H */
kernel/liveupdate/kexec_handover.c +26 -0
@@ -15,6 +15,7 @@#include <linux/crash_dump.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>
@@ -2094,6 +2095,31 @@ int kho_fill_kimage(struct kimage *image)return 0 ; } +/* +* Write the KHO state of @image into the EFI table, or zero the table if +* @image has none. +* +* There is one table, but the normal and the crash image can both be loaded, +* so the table is written just before @image runs rather than at load time. +* Crash images, images loaded with kexec_load() and images loaded with KHO +* disabled have no KHO state. Zeroing the table for them makes the next +* kernel boot without inherited KHO state instead of reading stale addresses. +*/ +int kho_update_efi_table (struct kimage *image) +{ +int err; + +if (!image->kho.fdt || !image->kho.bootmem) +return efi_kho_update (0 ,0 ,0 ,0 ); + + err =efi_kho_update (image->kho.fdt,PAGE_SIZE , + image->kho.bootmem->mem, image->kho.bootmem->bufsz); +if (err) +pr_warn ("failed to update EFI config table: %pe\n" ,ERR_PTR (err)); + +return err; +} +static int kho_walk_bootmem (struct kexec_buf *kbuf,int (*func)(struct resource *,void *)) {
Signature · 1 line
2.53.0
[email protected]
AI reviewRe: [PATCH v6 2/8] kho: Write KHO state to the EFI table at kexec time
Sashiko has reviewed this patch and found no issues.
Quoted 21 lines
From: George Guo <[email protected]>
On arm64 and riscv, KHO addresses and sizes are passed through /chosen properties in the boot FDT prepared for each kexec image. On x86, they are passed through a
SETUP_KEXEC_KHOrecord linked from the image's boot parameters. These records are per-image, unlike the shared EFI table.The EFI table is shared. A KHO-enabled normal image and a crash image can both be loaded, but need different contents: the normal image needs the KHO addresses, while the crash image needs an empty table. Updating the table at load time cannot satisfy both.
Write the table in
kernel_kexec()and__crash_kexec(), once the image that will run is known.kho_update_efi_table()fills the table from that image, or zeroes it if the image has no KHO state, including images loaded withkexec_load().Clear the table even with
CONFIG_KEXEC_HANDOVERdisabled, since the kernel may have inherited a populated table. This prevents a later kernel from trying to revive obsolete KHO state.
Quoted 7 lines
The table stores the size of the bootmem area list (bufsz), not of its page-aligned segment, as the FDT and x86 code do. If updating or clearing the table fails,
kernel_kexec()returns beforeliveupdate_reboot(), so LUO does not save state that the next kernel would not find.__crash_kexec()ignores the error so the crash boot can still proceed.Signed-off-by George Guo <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
PATCH v6 3/8 kho: Include linux/mm.h in kho_block.c
In reply to George GuoFrom: George Guo <[email protected]>
kho_block.c calls virt_to_phys() and phys_to_virt(). With CONFIG_KFENCE=y, the LoongArch implementations use offset_in_page() and page_address(), which are provided by <linux/mm.h>.
Include <linux/mm.h> explicitly to avoid implicit-declaration build errors for these helpers.
--- kernel/liveupdate/kho_block.c | 1 + 1 file changed, 1 insertion(+)
kernel/liveupdate/kho_block.c +1 -0
@@ -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
Signature · 1 line
2.53.0
[email protected]
AI reviewRe: [PATCH v6 3/8] kho: Include linux/mm.h in kho_block.c
Sashiko has reviewed this patch and found no issues.
Quoted 6 lines
From: George Guo <[email protected]>
kho_block.ccallsvirt_to_phys()andphys_to_virt(). WithCONFIG_KFENCE=y, the LoongArch implementations useoffset_in_page()andpage_address(), which are provided by <linux/mm.h>.
Quoted 6 lines
Include <
linux/mm.h> explicitly to avoid implicit-declaration build errors for these helpers.Co-developed-by Kexin Liu <[email protected]>Signed-off-by Kexin Liu <[email protected]>Signed-off-by George Guo <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
PATCH v6 4/8 kho: Add kho_disable()
In reply to George GuoFrom: George Guo <[email protected]>
On LoongArch, KHO state is passed to the next kernel only through an EFI configuration table. Only the EFI stub installs this table, during a cold boot.
A kernel entered through kexec does not run the EFI stub, so it cannot create the table if the previous kernel did not provide one. Without the table, it cannot pass KHO state to the next kernel on a subsequent kexec.
Add kho_disable() so architecture code can turn KHO off when the EFI configuration table is missing.
--- include/linux/kexec_handover.h | 3 +++ kernel/liveupdate/kexec_handover.c | 9 +++++++++ 2 files changed, 12 insertions(+)
include/linux/kexec_handover.h +3 -0
@@ -15,6 +15,7 @@ struct page;#ifdef CONFIG_KEXEC_HANDOVER bool kho_is_enabled (void ); +void kho_disable (void );bool is_kho_boot (void );int kho_preserve_folio (struct folio *folio);
@@ -54,6 +55,8 @@ static inline bool kho_is_enabled(void)return false; } +static inline void kho_disable (void ) { } +static inline bool is_kho_boot (void ) {return false;
kernel/liveupdate/kexec_handover.c +9 -0
@@ -82,6 +82,15 @@ static int __init kho_parse_enable(char *p) }early_param ("kho" , kho_parse_enable); +/* +* For architecture code that finds, after the early parameters are parsed, +* that it cannot pass the KHO state to the next kernel. +*/ +void __init kho_disable (void ) +{ + kho_enable = false; +} +struct kho_out {void *fdt;struct mutex lock;/* protects KHO FDT */
Signature · 1 line
2.53.0
[email protected]
AI reviewRe: [PATCH v6 4/8] kho: Add kho_disable()
Sashiko has reviewed this patch and found no issues.
Quoted 11 lines
From: George Guo <[email protected]>
On LoongArch, KHO state is passed to the next kernel only through an EFI configuration table. Only the EFI stub installs this table, during a cold boot.
A kernel entered through kexec does not run the EFI stub, so it cannot create the table if the previous kernel did not provide one. Without the table, it cannot pass KHO state to the next kernel on a subsequent kexec.
Quoted 4 lines
Add
kho_disable()so architecture code can turn KHO off when the EFI configuration table is missing.Signed-off-by George Guo <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
Mike Rapoport
maintainerRe: [PATCH v6 4/8] kho: Add kho_disable()
In reply to George GuoHi George,
Quoted 10 lines · George Guo
From: George Guo <[email protected]>
On LoongArch, KHO state is passed to the next kernel only through an EFI configuration table. Only the EFI stub installs this table, during a cold boot.
A kernel entered through kexec does not run the EFI stub, so it cannot create the table if the previous kernel did not provide one. Without the table, it cannot pass KHO state to the next kernel on a subsequent kexec.
The idea behind KHO and liveupdate is that the system uses kexec + KHO for reboots after the cold boot unless a new cold reboot is a must.
Doing one yes, one no, breaks that assumption.
Quoted 2 lines
Add
kho_disable()so architecture code can turn KHO off when the EFI configuration table is missing.
I don't like a global kho_disable() API. It's ambiguous and fragile.
Quoted 5 lines
Signed-off-by George Guo <[email protected]>--- include/linux/kexec_handover.h | 3 +++ kernel/liveupdate/kexec_handover.c | 9 +++++++++ 2 files changed, 12 insertions(+)
Signature · 2 lines
Sincerely yours, Mike.
PATCH v6 5/8 LoongArch: Allow memblock arrays to resize
In reply to George GuoFrom: George Guo <[email protected]>
LoongArch never calls memblock_allow_resize(), so the reserved region array cannot grow beyond INIT_MEMBLOCK_RESERVED_REGIONS entries (INIT_MEMBLOCK_REGIONS + NR_CPUS).
After kexec, kho_memory_init() reserves every range preserved by KHO. Each range that is not adjacent to another one needs its own entry, so with enough scattered preserved pages the array overflows and the incoming kernel panics:
Kernel panic - not syncing: memblock: cannot resize reserved array Call Trace: memblock_double_array+0x2d4/0x2f8 memblock_isolate_range+0x54/0x1a8 memblock_setclr_flag+0x44/0xe0 kho_preserved_memory_reserve+0x78/0xb8 ... kho_memory_init+0xbc/0x394 mm_core_init+0x124/0x154 start_kernel+0x568/0x6dc
The liveupdate luo_stress_files test with 500 files triggers it on a kernel without CONFIG_SMP, where NR_CPUS is 1. With CONFIG_SMP the array is larger and the test passes, but more preserved memory still overflows it.
When the reserved array is full, memblock allocates a bigger array from free memory. This is only safe once all memory in use has been reserved, so enable resizing in arch_mem_init() after the firmware, kernel and initrd reservations are made.
The memory preserved by KHO is reserved later, in kho_memory_init(). A new array cannot land on it either, because kho_populate() already limits memblock allocations to the KHO bootmem areas, which hold no preserved data.
--- arch/loongarch/kernel/setup.c | 3 +++ 1 file changed, 3 insertions(+)
arch/loongarch/kernel/setup.c +3 -0
@@ -402,6 +402,9 @@ static void __init arch_mem_init(char **cmdline_p)check_kernel_sections_mem (); +/* KHO may restore more reserved regions than the initial array holds. */ +memblock_allow_resize (); +memblock_set_bottom_up (true);swiotlb_init (true,SWIOTLB_VERBOSE );
Signature · 1 line
2.53.0
[email protected]
AI reviewRe: [PATCH v6 5/8] LoongArch: Allow memblock arrays to resize
Sashiko has reviewed this patch and found no issues.
Quoted 15 lines
From: George Guo <[email protected]>
LoongArch never calls
memblock_allow_resize(), so the reserved region array cannot grow beyondINIT_MEMBLOCK_RESERVED_REGIONSentries (INIT_MEMBLOCK_REGIONS+NR_CPUS).After kexec,
kho_memory_init()reserves every range preserved by KHO. Each range that is not adjacent to another one needs its own entry, so with enough scattered preserved pages the array overflows and the incoming kernel panics:Kernel panic - not syncing: memblock: cannot resize reserved array Call Trace: memblock_double_array+0x2d4/0x2f8 memblock_isolate_range+0x54/0x1a8
Quoted 6 lines
[ ... ]
preserved data.Co-developed-by Kexin Liu <[email protected]>Signed-off-by Kexin Liu <[email protected]>Signed-off-by George Guo <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
Mike Rapoport
maintainerRe: [PATCH v6 5/8] LoongArch: Allow memblock arrays to resize
In reply to George GuoQuoted 5 lines · George Guo
From: George Guo <[email protected]>
LoongArch never calls
memblock_allow_resize(), so the reserved region array cannot grow beyondINIT_MEMBLOCK_RESERVED_REGIONSentries (INIT_MEMBLOCK_REGIONS+NR_CPUS).
This might be something to fix independent of KHO.
Huacai,
What's the reason LoongArch never enables memblock resizing and why it defines INIT_MEMBLOCK_RESERVED_REGIONS to include NR_CPUS?
Signature · 2 lines
Sincerely yours, Mike.
Huacai Chen
maintainerRe: [PATCH v6 5/8] LoongArch: Allow memblock arrays to resize
Hi, Mike,
Quoted 8 lines · Mike Rapoport
Quoted 5 lines · George Guo
From: George Guo <[email protected]>
LoongArch never calls
memblock_allow_resize(), so the reserved region array cannot grow beyondINIT_MEMBLOCK_RESERVED_REGIONSentries (INIT_MEMBLOCK_REGIONS+NR_CPUS).
Quoted 6 lines
This might be something to fix independent of KHO.
Huacai,
What's the reason LoongArch never enables memblock resizing and why it defines
INIT_MEMBLOCK_RESERVED_REGIONSto includeNR_CPUS?
At first we didn't define INIT_MEMBLOCK_RESERVED_REGIONS, then we got boot failures on a 128-cores machine, so define it, and the value is similar to arm64.
The reason LoongArch never enables memblock resizing is because the mm code is derived from MIPS, and MIPS never enables it.
Huacai
Quoted 4 lines
--
Sincerely yours,
Mike.
Mike Rapoport
maintainerRe: [PATCH v6 5/8] LoongArch: Allow memblock arrays to resize
Quoted 13 lines · Huacai Chen
Hi, Mike,
Quoted 10 lines · Mike Rapoport
Quoted 5 lines · George Guo
From: George Guo <[email protected]>
LoongArch never calls
memblock_allow_resize(), so the reserved region array cannot grow beyondINIT_MEMBLOCK_RESERVED_REGIONSentries (INIT_MEMBLOCK_REGIONS+NR_CPUS).This might be something to fix independent of KHO.
Quoted 7 lines
Quoted 4 lines
Huacai,
What's the reason LoongArch never enables memblock resizing and why it defines
INIT_MEMBLOCK_RESERVED_REGIONSto includeNR_CPUS?At first we didn't define
INIT_MEMBLOCK_RESERVED_REGIONS, then we got boot failures on a 128-cores machine, so define it, and the value is similar to arm64.
AFAIR, arm64 had to reserve some per cpu data before they could enable memblock resizing, so they had to make it static.
Quoted 2 lines
The reason LoongArch never enables memblock resizing is because the mm code is derived from MIPS, and MIPS never enables it.
If that's the only reason, you might want to revisit that :)
Quoted 6 lines
Huacai
Quoted 4 lines
--
Sincerely yours,
Mike.
Signature · 2 lines
Sincerely yours, Mike.
Huacai Chen
maintainerRe: [PATCH v6 5/8] LoongArch: Allow memblock arrays to resize
Quoted 17 lines · Mike Rapoport
Quoted 15 lines · Huacai Chen
Hi, Mike,
Quoted 12 lines · Mike Rapoport
Quoted 5 lines · George Guo
From: George Guo <[email protected]>
LoongArch never calls
memblock_allow_resize(), so the reserved region array cannot grow beyondINIT_MEMBLOCK_RESERVED_REGIONSentries (INIT_MEMBLOCK_REGIONS+NR_CPUS).This might be something to fix independent of KHO.
Huacai,
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
What's the reason LoongArch never enables memblock resizing and why it defines
INIT_MEMBLOCK_RESERVED_REGIONSto includeNR_CPUS?At first we didn't define
INIT_MEMBLOCK_RESERVED_REGIONS, then we got boot failures on a 128-cores machine, so define it, and the value is similar to arm64.AFAIR, arm64 had to reserve some per cpu data before they could enable memblock resizing, so they had to make it static.
LoongArch is similar, so below 64-cores machine has no problem.
Quoted 5 lines
Quoted 3 lines
The reason LoongArch never enables memblock resizing is because the mm code is derived from MIPS, and MIPS never enables it.
If that's the only reason, you might want to revisit that :)
Yes, it seems we need memblock_allow_resize(), but maybe it is better to bring back paging_init()? Most other archs call memblock_allow_resize() in paging_init().
Huacai
Quoted 11 lines
Quoted 7 lines
Huacai
Quoted 4 lines
--
Sincerely yours,
Mike.--
Sincerely yours,
Mike.
Mike Rapoport
maintainerRe: [PATCH v6 5/8] LoongArch: Allow memblock arrays to resize
Quoted 29 lines · Huacai Chen
Quoted 17 lines · Mike Rapoport
Quoted 15 lines · Huacai Chen
Hi, Mike,
Quoted 12 lines · Mike Rapoport
Quoted 5 lines · George Guo
From: George Guo <[email protected]>
LoongArch never calls
memblock_allow_resize(), so the reserved region array cannot grow beyondINIT_MEMBLOCK_RESERVED_REGIONSentries (INIT_MEMBLOCK_REGIONS+NR_CPUS).This might be something to fix independent of KHO.
Huacai,
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
What's the reason LoongArch never enables memblock resizing and why it defines
INIT_MEMBLOCK_RESERVED_REGIONSto includeNR_CPUS?At first we didn't define
INIT_MEMBLOCK_RESERVED_REGIONS, then we got boot failures on a 128-cores machine, so define it, and the value is similar to arm64.AFAIR, arm64 had to reserve some per cpu data before they could enable memblock resizing, so they had to make it static.
LoongArch is similar, so below 64-cores machine has no problem.
Quoted 1 line
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
The reason LoongArch never enables memblock resizing is because the mm code is derived from MIPS, and MIPS never enables it.
If that's the only reason, you might want to revisit that :)
Yes, it seems we need
memblock_allow_resize(), but maybe it is better to bring backpaging_init()? Most other archs callmemblock_allow_resize()inpaging_init().
paging_init() is a historical relict that hugely misnamed everywhere :)
I think platform_init() should be fine.
As far as I can tell, by the time platform_init() calls init_numa_memory(), all memory reservations that must happen before any memblock allocations are done.
Quoted 1 line
Huacai
Signature · 2 lines
Sincerely yours, Mike.
Huacai Chen
maintainerRe: [PATCH v6 5/8] LoongArch: Allow memblock arrays to resize
Quoted 34 lines · Mike Rapoport
Quoted 32 lines · Huacai Chen
Quoted 17 lines · Mike Rapoport
Quoted 15 lines · Huacai Chen
Hi, Mike,
Quoted 12 lines · Mike Rapoport
Quoted 5 lines · George Guo
From: George Guo <[email protected]>
LoongArch never calls
memblock_allow_resize(), so the reserved region array cannot grow beyondINIT_MEMBLOCK_RESERVED_REGIONSentries (INIT_MEMBLOCK_REGIONS+NR_CPUS).This might be something to fix independent of KHO.
Huacai,
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
What's the reason LoongArch never enables memblock resizing and why it defines
INIT_MEMBLOCK_RESERVED_REGIONSto includeNR_CPUS?At first we didn't define
INIT_MEMBLOCK_RESERVED_REGIONS, then we got boot failures on a 128-cores machine, so define it, and the value is similar to arm64.AFAIR, arm64 had to reserve some per cpu data before they could enable memblock resizing, so they had to make it static.
LoongArch is similar, so below 64-cores machine has no problem.
Quoted 4 lines
Quoted 3 lines
The reason LoongArch never enables memblock resizing is because the mm code is derived from MIPS, and MIPS never enables it.
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
If that's the only reason, you might want to revisit that :)
Yes, it seems we need
memblock_allow_resize(), but maybe it is better to bring backpaging_init()? Most other archs callmemblock_allow_resize()inpaging_init().
paging_init()is a historical relict that hugely misnamed everywhere :)I think
platform_init()should be fine.
If paging_init() is unnecessary, then arch_mem_init() is better than platform_init(), at least the name is better.
Huacai
Quoted 10 lines
As far as I can tell, by the time
platform_init()callsinit_numa_memory(), all memory reservations that must happen before any memblock allocations are done.Quoted 1 line
Huacai
--
Sincerely yours,
Mike.
PATCH v6 6/8 LoongArch: Enable kexec handover (KHO)
In reply to George GuoFrom: George Guo <[email protected]>
Enable ARCH_SUPPORTS_KEXEC_HANDOVER on 64-bit LoongArch with EFI_STUB. KHO state is passed through an EFI configuration table installed by the stub.
Disable KHO at boot if the table is missing, since the kernel cannot pass KHO state to the next kernel without it.
--- arch/loongarch/Kconfig | 3 +++ arch/loongarch/kernel/setup.c | 16 ++++++++++++++++ 2 files changed, 19 insertions(+)
arch/loongarch/Kconfig +3 -0
@@ -685,6 +685,9 @@ config ARCH_SUPPORTS_KEXEC config ARCH_SUPPORTS_KEXEC_FILE def_bool 64BIT +config ARCH_SUPPORTS_KEXEC_HANDOVER + def_bool 64BIT && EFI_STUB + config ARCH_SELECTS_KEXEC_FILE def_bool 64BIT depends on KEXEC_FILE
arch/loongarch/kernel/setup.c +16 -0
@@ -20,6 +20,7 @@#include <linux/initrd.h> #include <linux/ioport.h> #include <linux/kexec.h> +#include <linux/kexec_handover.h> #include <linux/crash_dump.h> #include <linux/root_dev.h> #include <linux/console.h>
@@ -594,6 +595,20 @@ static void __init prefill_possible_map(void) }#endif +/* +* Only the EFI stub installs the KHO table, on a cold boot. A kernel +* started by kexec from a kernel that did not install it has no table, +* and the next kernel would not find what this kernel preserves, so +* turn KHO off. +*/ +static void __init kho_check_efi_table (void ) +{ +if (kho_is_enabled () && !efi_kho_table_found ()) { +pr_warn ("No EFI KHO table, disabling kexec handover\n" ); +kho_disable (); + } +} +void __init setup_arch (char **cmdline_p) {cpu_probe ();
@@ -608,6 +623,7 @@ void __init setup_arch(char **cmdline_p)bootcmdline_init (cmdline_p);jump_label_init ();/* Initialise the static keys for early params */ parse_early_param (); +kho_check_efi_table ();reserve_initrd_mem ();platform_init ();
Signature · 1 line
2.53.0
[email protected]
AI reviewRe: [PATCH v6 6/8] LoongArch: Enable kexec handover (KHO)
Sashiko has reviewed this patch and found no issues.
Quoted 6 lines
From: George Guo <[email protected]>
Enable
ARCH_SUPPORTS_KEXEC_HANDOVERon 64-bit LoongArch withEFI_STUB. KHO state is passed through an EFI configuration table installed by the stub.
Quoted 6 lines
Disable KHO at boot if the table is missing, since the kernel cannot pass KHO state to the next kernel without it.
Co-developed-by Kexin Liu <[email protected]>Signed-off-by Kexin Liu <[email protected]>Signed-off-by George Guo <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=6
PATCH v6 7/8 selftests/kho: Add LoongArch vmtest support
In reply to George GuoFrom: George Guo <[email protected]>
Add loongarch.conf to run the test on QEMU's LoongArch virtual machine with a la464 CPU and an 8250 serial console, and let vmtest.sh accept the loongarch64 target.
Boot vmlinux.efi through EFI firmware. The EFI stub installs the KHO EFI table, and QEMU's direct kernel boot would skip the stub. QEMU_EFI defaults to /usr/share/edk2/loongarch64/QEMU_EFI.fd and can be set for distributions that install the firmware elsewhere, such as Debian's qemu-efi-loongarch64 package.
QEMU's LoongArch virtual machine has no i8042 controller. Enable the generic PCI host so its I/O space is mapped before the i8042 fallback probe touches the legacy ports. This keeps i8042 enabled, so the same kernel configuration still works on real hardware.
Enable ACPI_SPCR_TABLE so the bare earlycon parameter gets the UART from the SPCR table installed by EDK2. Unlike x86, LoongArch does not enable it by default, and without it there is no early console and vmtest sees no early boot output.
The KHO vmtest needs CONFIG_DEFERRED_STRUCT_PAGE_INIT=y, which depends on SPARSEMEM, so select CONFIG_SPARSEMEM_MANUAL=y.
--- tools/testing/selftests/kho/loongarch.conf | 11 +++++++++++ tools/testing/selftests/kho/vmtest.sh | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/kho/loongarch.conf
tools/testing/selftests/kho/loongarch.conf new file +11 -0
@@ -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"
tools/testing/selftests/kho/vmtest.sh +2 -1
@@ -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
Signature · 1 line
2.53.0
[email protected]
AI reviewRe: [PATCH v6 7/8] selftests/kho: Add LoongArch vmtest support
Sashiko has reviewed this patch and found no issues.
Quoted 22 lines
From: George Guo <[email protected]>
Add loongarch.conf to run the test on QEMU's LoongArch virtual machine with a la464 CPU and an 8250 serial console, and let
vmtest.shaccept the loongarch64 target.Boot vmlinux.efi through EFI firmware. The EFI stub installs the KHO EFI table, and QEMU's direct kernel boot would skip the stub.
QEMU_EFIdefaults to/usr/share/edk2/loongarch64/QEMU_EFI.fdand can be set for distributions that install the firmware elsewhere, such as Debian's qemu-efi-loongarch64 package.QEMU's LoongArch virtual machine has no i8042 controller. Enable the generic PCI host so its I/O space is mapped before the i8042 fallback probe touches the legacy ports. This keeps i8042 enabled, so the same kernel configuration still works on real hardware.
Enable
ACPI_SPCR_TABLEso the bare earlycon parameter gets the UART from the SPCR table installed by EDK2. Unlike x86, LoongArch does not enable it by default, and without it there is no early console and vmtest sees no early boot output.
Quoted 6 lines
The KHO vmtest needs
CONFIG_DEFERRED_STRUCT_PAGE_INIT=y, which depends on SPARSEMEM, so selectCONFIG_SPARSEMEM_MANUAL=y.Co-developed-by Kexin Liu <[email protected]>Signed-off-by Kexin Liu <[email protected]>Signed-off-by George Guo <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=7
PATCH v6 8/8 selftests/liveupdate: Add LoongArch vmtest support
In reply to George GuoFrom: George Guo <[email protected]>
Add the LoongArch kernel configuration, target and cross-compiler detection, and include loongarch64 in the VM test suite.
Boot vmlinux.efi through EFI firmware so the EFI stub installs the KHO table. Allow the firmware path to be set with QEMU_EFI and skip the test if it is unavailable.
--- .../selftests/liveupdate/config.loongarch64 | 5 +++++ tools/testing/selftests/liveupdate/run-vmtests.sh | 4 ++-- tools/testing/selftests/liveupdate/vmtest.sh | 14 +++++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 tools/testing/selftests/liveupdate/config.loongarch64
tools/testing/selftests/liveupdate/config.loongarch64 new file +5 -0
@@ -0,0 +1,5 @@ +CONFIG_ACPI_SPCR_TABLE=y +CONFIG_PCI_HOST_GENERIC=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SMP=y
tools/testing/selftests/liveupdate/run-vmtests.sh +2 -2
@@ -4,7 +4,7 @@ SCRIPT_DIR=$(dirname "$(realpath "$0")") TEST_RUNNER="$SCRIPT_DIR/vmtest.sh" -TARGETS=("x86_64" "aarch64") +TARGETS=("x86_64" "aarch64" "loongarch64") GREEN='\033[0;32m' RED='\033[0;31m'
@@ -72,7 +72,7 @@ function main() { for test_name in "${TEST_NAMES[@]}"; do log="$output_dir/${arch}_${test_name}.log" - printf " -> %-8s %-24s ... " "$arch" "$test_name" + printf " -> %-11s %-24s ... " "$arch" "$test_name" "$TEST_RUNNER" -t "$arch" -T "$test_name" &> "$log" exit_code=$?
tools/testing/selftests/liveupdate/vmtest.sh +13 -1
@@ -21,6 +21,12 @@ function get_arch_conf() { QEMU_CMD="qemu-system-aarch64 -M virt -cpu max" KERNEL_IMAGE="Image" KERNEL_CMDLINE="console=ttyAMA0" + elif [[ "$arch" == "loongarch" ]]; then + local qemu_efi="${QEMU_EFI:-/usr/share/edk2/loongarch64/QEMU_EFI.fd}" + [ -r "$qemu_efi" ] || skip "EFI firmware '$qemu_efi' not found, set QEMU_EFI" + QEMU_CMD="qemu-system-loongarch64 -M virt -cpu la464 -bios $qemu_efi" + KERNEL_IMAGE="vmlinux.efi" + KERNEL_CMDLINE="console=ttyS0 earlycon" elif [[ "$arch" == "x86" ]]; then QEMU_CMD="qemu-system-x86_64" KERNEL_IMAGE="bzImage"
@@ -37,11 +43,15 @@ $0 [-d build_dir] [-j jobs] [-t target_arch] [-T test_name] [-w workspace_dir] [ Options: -d) path to the kernel build directory (default: .luo_test_build.<arch>) -j) number of jobs for compilation - -t) run test for target_arch (aarch64, x86_64) + -t) run test for target_arch (aarch64, loongarch64, x86_64) -T) test name to run (default: luo_kexec_simple) -w) custom workspace directory (default: creates temp dir) -k) keep workspace directory after successful test -h) display this help + +Environment: + QEMU_EFI LoongArch EFI firmware path + (default: /usr/share/edk2/loongarch64/QEMU_EFI.fd) EOF }
@@ -86,6 +96,7 @@ function detect_cross_compile() { local candidate="" case "$target" in aarch64) candidate="aarch64-linux-gnu-" ;; + loongarch64) candidate="loongarch64-linux-gnu-" ;; x86_64) candidate="x86_64-linux-gnu-" ;; *) skip "Auto-detection for target '$target' not supported. Please set CROSS_COMPILE manually." ;; esac
@@ -193,6 +204,7 @@ function target_to_arch() { local target=$1 case $target in aarch64) echo "arm64" ;; + loongarch64) echo "loongarch" ;; x86_64) echo "x86" ;; *) skip "architecture $target is not supported" esac
Signature · 1 line
2.53.0
[email protected]
AI reviewRe: [PATCH v6 8/8] selftests/liveupdate: Add LoongArch vmtest support
Sashiko has reviewed this patch and found no issues.
Quoted 5 lines
From: George Guo <[email protected]>
Add the LoongArch kernel configuration, target and cross-compiler detection, and include loongarch64 in the VM test suite.
Quoted 7 lines
Boot vmlinux.efi through EFI firmware so the EFI stub installs the KHO table. Allow the firmware path to be set with
QEMU_EFIand skip the test if it is unavailable.Co-developed-by Kexin Liu <[email protected]>Signed-off-by Kexin Liu <[email protected]>Signed-off-by George Guo <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=8