Linux Kernel Selftest development
 help / color / mirror / Atom feed
From: Pratyush Yadav <pratyush@kernel.org>
To: George Guo <dongtai.guo@linux.dev>
Cc: chenhuacai@kernel.org,  rppt@kernel.org,
	 pasha.tatashin@soleen.com, pratyush@kernel.org,
	 shuah@kernel.org,  ardb@kernel.org, guodongtai@kylinos.cn,
	 kernel@xen0n.name,  graf@amazon.com, loongarch@lists.linux.dev,
	 linux-kernel@vger.kernel.org, kexec@lists.infradead.org,
	 linux-mm@kvack.org, linux-kselftest@vger.kernel.org,
	 linux-efi@vger.kernel.org,  Kexin Liu <liukexin@kylinos.cn>
Subject: Re: [PATCH v4 2/4] LoongArch: kexec: add KHO support
Date: Mon, 10 Aug 2026 19:37:36 +0200	[thread overview]
Message-ID: <2vxzo6f96fmn.fsf@kernel.org> (raw)
In-Reply-To: <20260807103714.33074-3-dongtai.guo@linux.dev> (George Guo's message of "Fri, 7 Aug 2026 18:37:12 +0800")

On Fri, Aug 07 2026, George Guo wrote:

> From: George Guo <guodongtai@kylinos.cn>
>
> Enable Kexec Handover (KHO) on LoongArch64.
>
> LoongArch has no boot FDT: the efistub passes the EFI system table and
> the command line to the core kernel directly, so the arm64 /chosen path
> (append linux,kho-fdt / linux,kho-scratch and let
> early_init_dt_check_kho() read them) does not apply.  Follow the x86
> model instead, which has no boot FDT either: carry the KHO pointer out of
> band and call kho_populate() directly.  The channel is the EFI
> configuration table entry added by the previous patch.
>
> - Kconfig: ARCH_SUPPORTS_KEXEC_HANDOVER is def_bool 64BIT.
> - machine_kexec_file.c: kho_load_data() builds a small handover blob
>   (struct linux_efi_kho_data) holding the KHO state FDT and scratch
>   addresses, and a new EFI configuration table with a
>   LINUX_EFI_KHO_TABLE_GUID entry pointing to it; both are loaded as kexec
>   segments.
> - machine_kexec.c: before jumping to the next kernel, switch the EFI
>   system table to the extended configuration table.
> - setup.c: kho_populate_from_efi() scans the configuration table for
>   LINUX_EFI_KHO_TABLE_GUID and calls kho_populate() from setup_arch(),
>   after efi_init() and before memblock_init().
>
> Handover is set up by the kexec_file_load() syscall only.  kho_load_data()
> runs from load_other_segments(), which the older kexec_load() syscall does
> not reach.  This matches x86, where KHO lives in the bzImage64 loader.
>
> Tested on a LoongArch machine booting through ACPI/UEFI.  After the kexec,
> the second kernel reports
>
>   KHO: found kexec handover data.
>
> and the two-stage test passes: luo_kexec_simple --stage 1, kexec into the
> second kernel, then luo_kexec_simple --stage 2.
>
> Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
> Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
> Signed-off-by: George Guo <guodongtai@kylinos.cn>
[...]
> @@ -55,6 +64,121 @@ static void cmdline_add_initrd(struct kimage *image, unsigned long *cmdline_tmpl
>  	*cmdline_tmplen += initrd_strlen;
>  }
>  
> +#ifdef CONFIG_KEXEC_HANDOVER
> +/*
> + * Hand the KHO state to the next kernel through a dedicated EFI configuration
> + * table entry.
> + *
> + * LoongArch has no boot FDT: the efistub passes the EFI system table and the
> + * command line to the core kernel directly.  So instead of the arm64 /chosen
> + * FDT path, build a small handover blob (struct linux_efi_kho_data) holding the
> + * KHO state FDT and scratch addresses, register it in the EFI configuration
> + * table under LINUX_EFI_KHO_TABLE_GUID, and let the next kernel read it and
> + * call kho_populate() directly.
> + *
> + * Both the blob and the extended configuration table are loaded as kexec
> + * segments; machine_kexec() switches st->tables to the new table before jumping.
> + *
> + * image->kho.fdt and image->kho.scratch are filled in by kho_fill_kimage()
> + * before the arch loader runs, so they are valid here.
> + */
> +static int kho_load_data(struct kimage *image)
> +{
> +	struct linux_efi_kho_data *kho;
> +	efi_system_table_t *st;
> +	efi_config_table_t *ct, *new_ct;
> +	size_t old_sz, new_sz;
> +	struct kexec_buf kbuf = {
> +		.image		= image,
> +		.buf_min	= 0,
> +		.buf_max	= ULONG_MAX,
> +		.top_down	= true,
> +	};
> +	int ret;
> +
> +	if (!image->kho.fdt || !image->kho.scratch)
> +		return 0;
> +
> +	if (!fw_arg2) {
> +		pr_err("KHO requires an EFI boot, no EFI system table found\n");
> +		return -EINVAL;
> +	}
> +
> +	/* Build the handover blob and load it as a kexec segment. */
> +	kho = kzalloc(sizeof(*kho), GFP_KERNEL);
> +	if (!kho)
> +		return -ENOMEM;
> +
> +	kho->fdt_addr     = image->kho.fdt;
> +	kho->fdt_size     = PAGE_SIZE;
> +	kho->scratch_addr = image->kho.scratch->mem;
> +	kho->scratch_size = image->kho.scratch->memsz;
> +
> +	kbuf.buffer	= kho;
> +	kbuf.bufsz	= sizeof(*kho);
> +	kbuf.memsz	= sizeof(*kho);
> +	kbuf.buf_align	= sizeof(u64);
> +	kbuf.mem	= KEXEC_BUF_MEM_UNKNOWN;
> +
> +	ret = kexec_add_buffer(&kbuf);
> +	if (ret) {
> +		kfree(kho);
> +		return ret;
> +	}
> +	image->arch.kho_data	 = kho;
> +	image->arch.kho_data_mem = kbuf.mem;
> +
> +	kexec_dprintk("Loaded KHO handover blob at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
> +		      image->arch.kho_data_mem, kbuf.bufsz, kbuf.memsz);
> +	kexec_dprintk("KHO fdt at 0x%llx, scratch at 0x%llx size 0x%llx\n",
> +		      kho->fdt_addr, kho->scratch_addr, kho->scratch_size);
> +
> +	/*
> +	 * Build a new EFI configuration table with a LINUX_EFI_KHO_TABLE_GUID
> +	 * entry appended, pointing at the handover blob, and load it as a kexec
> +	 * segment.  machine_kexec() updates st->tables / st->nr_tables to point
> +	 * to it before jumping.
> +	 *
> +	 * fw_arg2 is the EFI system table physical address passed by the
> +	 * firmware/bootloader.  Use it directly because image->arch.systable_ptr
> +	 * is set later in machine_kexec_prepare(), which runs after this.
> +	 */

This looks wrong. I don't think you should be modifying the EFI
configuration table in this way. You also should have this in
architecture-agnostic code.

I'm not an EFI expert, but I took a look at how the other Linux-specific
tables work. I picked LINUX_EFI_MEMRESERVE_TABLE_GUID as my example. The
table is allocated and installed from the EFI stub (see
install_memreserve_table()). Then efi_memreserve_map_root() maps the
table and it is used by efi_mem_reserve_persistent().

You should do something similar. Allocate and install the table from the
stub, and then just update it on kexec. This would also let other
architectures use this GUID without having to reinvent this again.

> +	st = (efi_system_table_t *)TO_CACHE(fw_arg2);
> +	ct = (efi_config_table_t *)TO_CACHE((unsigned long)st->tables);
> +	old_sz = st->nr_tables * sizeof(efi_config_table_t);
> +	new_sz = old_sz + sizeof(efi_config_table_t);
> +
> +	new_ct = kvmalloc(new_sz, GFP_KERNEL);
> +	if (!new_ct)
> +		return -ENOMEM;
> +
> +	memcpy(new_ct, ct, old_sz);
> +	new_ct[st->nr_tables].guid  = LINUX_EFI_KHO_TABLE_GUID;
> +	new_ct[st->nr_tables].table = (void *)image->arch.kho_data_mem;
> +
> +	kbuf.buffer	= new_ct;
> +	kbuf.bufsz	= new_sz;
> +	kbuf.memsz	= new_sz;
> +	kbuf.buf_align	= sizeof(void *);
> +	kbuf.mem	= KEXEC_BUF_MEM_UNKNOWN;
> +
> +	ret = kexec_add_buffer(&kbuf);
> +	if (ret) {
> +		kvfree(new_ct);
> +		return ret;
> +	}
> +	image->arch.efi_tables	   = new_ct;
> +	image->arch.efi_tables_mem = kbuf.mem;
> +	image->arch.efi_tables_cnt = st->nr_tables + 1;
> +
> +	kexec_dprintk("Loaded EFI config table at 0x%lx bufsz=0x%lx memsz=0x%lx nr_tables=%lu\n",
> +		      image->arch.efi_tables_mem, kbuf.bufsz, kbuf.memsz,
> +		      image->arch.efi_tables_cnt);
> +
> +	return 0;
> +}
> +#endif
> +
>  #ifdef CONFIG_CRASH_DUMP
>  
>  static int prepare_elf_headers(void **addr, unsigned long *sz)
> @@ -220,6 +344,13 @@ int load_other_segments(struct kimage *image,
>  		cmdline_add_initrd(image, &cmdline_tmplen, modified_cmdline, initrd_load_addr);
>  	}
>  
> +#ifdef CONFIG_KEXEC_HANDOVER
> +	/* Load the KHO handover blob and the extended EFI configuration table */
> +	ret = kho_load_data(image);
> +	if (ret)
> +		goto out_err;
> +#endif
> +
>  	if (cmdline_len + cmdline_tmplen > COMMAND_LINE_SIZE) {
>  		pr_err("Appending command line exceeds COMMAND_LINE_SIZE\n");
>  		ret = -EINVAL;
[...]

-- 
Regards,
Pratyush Yadav

  parent reply	other threads:[~2026-08-10 17:37 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-07 10:37 [PATCH v4 0/4] LoongArch: add KHO support and selftests George Guo
2026-08-07 10:37 ` [PATCH v4 1/4] efi: add a KHO configuration table GUID George Guo
2026-08-09  4:18   ` Huacai Chen
2026-08-10 13:13     ` Ard Biesheuvel
2026-08-10 14:35       ` Huacai Chen
2026-08-10 16:19         ` Pratyush Yadav
2026-08-07 10:37 ` [PATCH v4 2/4] LoongArch: kexec: add KHO support George Guo
2026-08-10 14:42   ` Huacai Chen
2026-08-10 17:37   ` Pratyush Yadav [this message]
2026-08-07 10:37 ` [PATCH v4 3/4] liveupdate: luo_session: include linux/mm.h for virt/phys translation George Guo
2026-08-10 14:37   ` Huacai Chen
2026-08-10 17:39     ` Pratyush Yadav
2026-08-10 17:44       ` Pratyush Yadav
2026-08-07 10:37 ` [PATCH v4 4/4] selftests/kho: add LoongArch vmtest support George Guo
2026-08-09  4:16   ` Huacai Chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2vxzo6f96fmn.fsf@kernel.org \
    --to=pratyush@kernel.org \
    --cc=ardb@kernel.org \
    --cc=chenhuacai@kernel.org \
    --cc=dongtai.guo@linux.dev \
    --cc=graf@amazon.com \
    --cc=guodongtai@kylinos.cn \
    --cc=kernel@xen0n.name \
    --cc=kexec@lists.infradead.org \
    --cc=linux-efi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=liukexin@kylinos.cn \
    --cc=loongarch@lists.linux.dev \
    --cc=pasha.tatashin@soleen.com \
    --cc=rppt@kernel.org \
    --cc=shuah@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox