From nobody Fri Oct 3 08:48:20 2025 Received: from out-182.mta0.migadu.com (out-182.mta0.migadu.com [91.218.175.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4D9CE22172E for ; Wed, 3 Sep 2025 03:02:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756868539; cv=none; b=E2iFql6i5FqNIl6bGRNvFUOBzWGPFrAcwlrmvcvPhH4ELuju6tNbaRYaDEmCPwHyGfTAyw9VBAhV/niLj7IMKtT6NDRYvniGU6DI405II8JgMdRclWmAoet6nPwh6ZwSr257WJMMHrHq2t/+hB5SI3+YPLoGH9aDfmUvU4waUas= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756868539; c=relaxed/simple; bh=WjhsrADC0GwnfBXxhFnWnNnYaAC+LU2wLei9uwujpOA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=CpIi31THROrvMmSsQX/4280++wkMffxRY/tbphQtDO9DlJN+GwXJMc33hOCl6+mXyD3/wBpRaL6kXnyCspltdEudVoUc+/2WBX2d1omdjrJNOAGgqaZC5I92IlcyYScaCc4lxflkr376aAocniIxiDd3YeiFxwL1bq9fDzUljJU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=G7jOzflN; arc=none smtp.client-ip=91.218.175.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="G7jOzflN" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1756868535; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9B6OfEVdBH7wSZaIebpK16txAhX6ctZF4LG8My4lKI0=; b=G7jOzflNI/vNR76mNjnQLgVxECxcx7TMgYOD0x3Tw8+UYC/6d0kHe2p0kLEJMe5tQd0wv6 klmRVAZm5+zdcvBSJO9B5TVMqtsF95dpyCvCHBvz7NvnCfTO+FJ2QaG8ai7Jph2EIVg5cm GNadLNnoX5YawEMWVjJIHqEEF+pfDPU= From: Youling Tang To: Huacai Chen Cc: WANG Xuerui , Baoquan He , Yao Zi , kexec@lists.infradead.org, loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, youling.tang@linux.dev, Youling Tang Subject: [PATCH v4 1/7] LoongArch: Add struct loongarch_image_header for kernel image Date: Wed, 3 Sep 2025 11:00:54 +0800 Message-Id: <20250903030100.196744-2-youling.tang@linux.dev> In-Reply-To: <20250903030100.196744-1-youling.tang@linux.dev> References: <20250903030100.196744-1-youling.tang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Youling Tang Define a dedicated image header structure for LoongArch architecture to standardize kernel loading in bootloaders (primarily for kexec_file). This header includes critical metadata such as PE signature, entry points, image size and load address offset, etc. Signed-off-by: Youling Tang --- arch/loongarch/include/asm/image.h | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 arch/loongarch/include/asm/image.h diff --git a/arch/loongarch/include/asm/image.h b/arch/loongarch/include/as= m/image.h new file mode 100644 index 000000000000..ff539711c9ea --- /dev/null +++ b/arch/loongarch/include/asm/image.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * LoongArch binary image header for EFI(PE/COFF) format. + * + * Author: Youling Tang + * Copyright (C) 2025 KylinSoft Corporation. + */ + +#ifndef __ASM_IMAGE_H +#define __ASM_IMAGE_H +#ifndef __ASSEMBLER__ + +/** + * struct loongarch_image_header + * + * @dos_sig: Optional PE format 'MZ' signature. + * @padding_1: Reserved. + * @kernel_entry: Kernel image entry pointer. + * @kernel_asize: An estimated size of the memory image size in LSB byte o= rder. + * @text_offset: The image load offset in LSB byte order. + * @padding_2: Reserved. + * @pe_header: Optional offset to a PE format header. + **/ + +struct loongarch_image_header { + uint8_t dos_sig[2]; + uint16_t padding_1[3]; + uint64_t kernel_entry; + uint64_t kernel_asize; + uint64_t text_offset; + uint32_t padding_2[7]; + uint32_t pe_header; +}; + +#endif /* __ASSEMBLER__ */ +#endif /* __ASM_IMAGE_H */ --=20 2.43.0 From nobody Fri Oct 3 08:48:20 2025 Received: from out-174.mta0.migadu.com (out-174.mta0.migadu.com [91.218.175.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 448072C17B6 for ; Wed, 3 Sep 2025 03:02:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756868544; cv=none; b=G+dPgQ5Okv+w021/VwF4HwyOWhDBt2VH/EwWaz/wmc1pZVF95jBpFA17Ylz8L5Gdv7tGoEMM+GTpLPbZYp+p9d5LoggUtQSlxyDMMR0iQeb2zME+mr8H8u86o2HG+oDlIVMTNYRNcoHbOBCpcT7ZqYG5OC4mwWl+Hi0hFjL0aQA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756868544; c=relaxed/simple; bh=NfejkKV2ScDWNYVETG4saIiKhnSkyp5Z9x8Lt1ggI3Y=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=bGIACBmIVuCAu/meU54rImPu/v5d+iJJfRqhJ73t/h+udc8fuLzVpNen5j5n0n7wR7/l8QyeWClylIVuKn89zwOLPaN9QZg0Mx2VfHp5AUFike7kM15r8Fy0I/rZh8M7L71OVD4gBPinpHiSG38KTmXWGQEpJyBqRXwbLxQ30nk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=E+yTcW3p; arc=none smtp.client-ip=91.218.175.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="E+yTcW3p" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1756868538; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1i1DxNMFGAJrj4Ygws+WaPRM7lDIcdG5pw9Nz5YA+4c=; b=E+yTcW3pnCeDoCwluiewrsVE6U4tNnSYml18Acv1I4cVIWnSr/B3Aqj6Ol7AYF/oQhjqyS mKE8sjTOFQqnciju62Ad8pOQ1OBpQOPvfdGyHlM2+k/nrEy0kW3hgtVOa1Xb97hIRAxzml I+ZPjW/Gi9C/S72m5ebxHLojO/+MydI= From: Youling Tang To: Huacai Chen Cc: WANG Xuerui , Baoquan He , Yao Zi , kexec@lists.infradead.org, loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, youling.tang@linux.dev, Youling Tang Subject: [PATCH v4 2/7] LoongArch: Add preparatory infrastructure for kexec_file Date: Wed, 3 Sep 2025 11:00:55 +0800 Message-Id: <20250903030100.196744-3-youling.tang@linux.dev> In-Reply-To: <20250903030100.196744-1-youling.tang@linux.dev> References: <20250903030100.196744-1-youling.tang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Youling Tang Add some preparatory infrastructure: - Add support for loading other segments. - Add command line processing. - Other minor modifications. This initrd will be passed to the second kernel via the command line 'initrd=3Dstart,size'. The 'kexec_file' command line parameter indicates that the kernel is loaded via kexec_file. Signed-off-by: Youling Tang --- arch/loongarch/Kconfig | 9 ++ arch/loongarch/include/asm/kexec.h | 11 ++ arch/loongarch/kernel/Makefile | 1 + arch/loongarch/kernel/machine_kexec.c | 37 +++--- arch/loongarch/kernel/machine_kexec_file.c | 126 +++++++++++++++++++++ 5 files changed, 171 insertions(+), 13 deletions(-) create mode 100644 arch/loongarch/kernel/machine_kexec_file.c diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index f0abc38c40ac..490dc6eed749 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -625,6 +625,15 @@ config CPU_HAS_PREFETCH config ARCH_SUPPORTS_KEXEC def_bool y =20 +config ARCH_SUPPORTS_KEXEC_FILE + def_bool 64BIT + +config ARCH_SELECTS_KEXEC_FILE + def_bool y + depends on KEXEC_FILE + select HAVE_IMA_KEXEC if IMA + select RELOCATABLE + config ARCH_SUPPORTS_CRASH_DUMP def_bool y =20 diff --git a/arch/loongarch/include/asm/kexec.h b/arch/loongarch/include/as= m/kexec.h index cf95cd3eb2de..ed7e3fc8571e 100644 --- a/arch/loongarch/include/asm/kexec.h +++ b/arch/loongarch/include/asm/kexec.h @@ -41,6 +41,17 @@ struct kimage_arch { unsigned long systable_ptr; }; =20 +#ifdef CONFIG_KEXEC_FILE + +int arch_kimage_file_post_load_cleanup(struct kimage *image); +#define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_clea= nup + +extern int load_other_segments(struct kimage *image, + unsigned long kernel_load_addr, unsigned long kernel_size, + char *initrd, unsigned long initrd_len, + char *cmdline, unsigned long cmdline_len); +#endif + typedef void (*do_kexec_t)(unsigned long efi_boot, unsigned long cmdline_ptr, unsigned long systable_ptr, diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile index 6f5a4574a911..67b9b214d212 100644 --- a/arch/loongarch/kernel/Makefile +++ b/arch/loongarch/kernel/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_MAGIC_SYSRQ) +=3D sysrq.o obj-$(CONFIG_RELOCATABLE) +=3D relocate.o =20 obj-$(CONFIG_KEXEC_CORE) +=3D machine_kexec.o relocate_kernel.o +obj-$(CONFIG_KEXEC_FILE) +=3D machine_kexec_file.o obj-$(CONFIG_CRASH_DUMP) +=3D crash_dump.o =20 obj-$(CONFIG_UNWINDER_GUESS) +=3D unwind_guess.o diff --git a/arch/loongarch/kernel/machine_kexec.c b/arch/loongarch/kernel/= machine_kexec.c index f9381800e291..d5accdc4576d 100644 --- a/arch/loongarch/kernel/machine_kexec.c +++ b/arch/loongarch/kernel/machine_kexec.c @@ -70,18 +70,28 @@ int machine_kexec_prepare(struct kimage *kimage) kimage->arch.efi_boot =3D fw_arg0; kimage->arch.systable_ptr =3D fw_arg2; =20 - /* Find the command line */ - for (i =3D 0; i < kimage->nr_segments; i++) { - if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(b= ootloader))) { - if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_S= IZE)) - kimage->arch.cmdline_ptr =3D (unsigned long)cmdline_ptr; - break; + if (kimage->file_mode =3D=3D 1) { + /* + * kimage->cmdline_buf will be released in kexec_file_load, so copy to + * the KEXEC_CMDLINE_ADDR safe area. + */ + memcpy((void *)KEXEC_CMDLINE_ADDR, (void *)kimage->arch.cmdline_ptr, + strlen((char *)kimage->arch.cmdline_ptr) + 1); + kimage->arch.cmdline_ptr =3D (unsigned long)KEXEC_CMDLINE_ADDR; + } else { + /* Find the command line */ + for (i =3D 0; i < kimage->nr_segments; i++) { + if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(= bootloader))) { + if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_= SIZE)) + kimage->arch.cmdline_ptr =3D (unsigned long)cmdline_ptr; + break; + } } - } =20 - if (!kimage->arch.cmdline_ptr) { - pr_err("Command line not included in the provided image\n"); - return -EINVAL; + if (!kimage->arch.cmdline_ptr) { + pr_err("Command line not included in the provided image\n"); + return -EINVAL; + } } =20 /* kexec/kdump need a safe page to save reboot_code_buffer */ @@ -287,9 +297,10 @@ void machine_kexec(struct kimage *image) /* We do not want to be bothered. */ local_irq_disable(); =20 - pr_notice("EFI boot flag 0x%lx\n", efi_boot); - pr_notice("Command line at 0x%lx\n", cmdline_ptr); - pr_notice("System table at 0x%lx\n", systable_ptr); + pr_notice("EFI boot flag: 0x%lx\n", efi_boot); + pr_notice("Command line addr: 0x%lx\n", cmdline_ptr); + pr_notice("Command line string: %s\n", (char *)cmdline_ptr); + pr_notice("System table addr: 0x%lx\n", systable_ptr); pr_notice("We will call new kernel at 0x%lx\n", start_addr); pr_notice("Bye ...\n"); =20 diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/ke= rnel/machine_kexec_file.c new file mode 100644 index 000000000000..584ce9471e93 --- /dev/null +++ b/arch/loongarch/kernel/machine_kexec_file.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * kexec_file for LoongArch + * + * Author: Youling Tang + * Copyright (C) 2025 KylinSoft Corporation. + * + * Most code is derived from LoongArch port of kexec-tools + */ + +#define pr_fmt(fmt) "kexec_file: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const struct kexec_file_ops * const kexec_file_loaders[] =3D { + NULL +}; + +int arch_kimage_file_post_load_cleanup(struct kimage *image) +{ + vfree(image->elf_headers); + image->elf_headers =3D NULL; + image->elf_headers_sz =3D 0; + + return kexec_image_post_load_cleanup_default(image); +} + +/* Adds the "initrd=3Dstart,size" command line parameter to command line. = */ +static void cmdline_add_initrd(struct kimage *image, unsigned long *cmdlin= e_tmplen, + char *modified_cmdline, unsigned long initrd) +{ + int initrd_strlen; + + initrd_strlen =3D sprintf(modified_cmdline + (*cmdline_tmplen), "initrd= =3D0x%lx,0x%lx ", + initrd, image->initrd_buf_len); + *cmdline_tmplen +=3D initrd_strlen; +} + +/* Adds the "kexec_file" command line parameter to command line. */ +static void cmdline_add_prefix(unsigned long *cmdline_tmplen, char *modifi= ed_cmdline) +{ + int prefix_strlen; + + prefix_strlen =3D sprintf(modified_cmdline + (*cmdline_tmplen), "kexec_fi= le "); + *cmdline_tmplen +=3D prefix_strlen; +} + +/* + * Tries to add the initrd to the image. If it is not possible to find + * valid locations, this function will undo changes to the image and retur= n non + * zero. + */ +int load_other_segments(struct kimage *image, + unsigned long kernel_load_addr, + unsigned long kernel_size, + char *initrd, unsigned long initrd_len, + char *cmdline, unsigned long cmdline_len) +{ + struct kexec_buf kbuf; + unsigned long orig_segments =3D image->nr_segments; + char *modified_cmdline =3D NULL; + unsigned long cmdline_tmplen =3D 0; + unsigned long initrd_load_addr =3D 0; + int ret =3D 0; + + + kbuf.image =3D image; + /* not allocate anything below the kernel */ + kbuf.buf_min =3D kernel_load_addr + kernel_size; + + modified_cmdline =3D kzalloc(COMMAND_LINE_SIZE, GFP_KERNEL); + if (!modified_cmdline) + return -EINVAL; + + cmdline_add_prefix(&cmdline_tmplen, modified_cmdline); + /* Ensure it's null terminated */ + modified_cmdline[COMMAND_LINE_SIZE - 1] =3D '\0'; + + /* load initrd */ + if (initrd) { + kbuf.buffer =3D initrd; + kbuf.bufsz =3D initrd_len; + kbuf.mem =3D KEXEC_BUF_MEM_UNKNOWN; + kbuf.memsz =3D initrd_len; + kbuf.buf_align =3D 0; + /* within 1GB-aligned window of up to 32GB in size */ + kbuf.buf_max =3D round_down(kernel_load_addr, SZ_1G) + + (unsigned long)SZ_1G * 32; + kbuf.top_down =3D false; + + ret =3D kexec_add_buffer(&kbuf); + if (ret) + goto out_err; + initrd_load_addr =3D kbuf.mem; + + kexec_dprintk("Loaded initrd at 0x%lx bufsz=3D0x%lx memsz=3D0x%lx\n", + initrd_load_addr, kbuf.bufsz, kbuf.memsz); + + /* Add the initrd=3Dstart,size parameter to the command line */ + cmdline_add_initrd(image, &cmdline_tmplen, modified_cmdline, initrd_load= _addr); + } + + if (cmdline_len + cmdline_tmplen > COMMAND_LINE_SIZE) { + pr_err("Appending command line exceeds COMMAND_LINE_SIZE\n"); + ret =3D -EINVAL; + goto out_err; + } + memcpy(modified_cmdline + cmdline_tmplen, cmdline, cmdline_len); + cmdline =3D modified_cmdline; + image->arch.cmdline_ptr =3D (unsigned long)cmdline; + + return 0; + +out_err: + image->nr_segments =3D orig_segments; + kfree(modified_cmdline); + return ret; +} --=20 2.43.0 From nobody Fri Oct 3 08:48:20 2025 Received: from out-188.mta0.migadu.com (out-188.mta0.migadu.com [91.218.175.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 72DE122172E for ; Wed, 3 Sep 2025 03:02:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756868545; cv=none; b=k+G/Jgx5FJmnzCBzkrsQLIQorYtszRQjwEB772yrbKUPa8sodM95rQkFwCd4BfD30DmDt3WRklwomc4HSp0+qdV2NUgrMETre8cq46uem7U5LJBL2j4jOsE2B+AyeBojXIjZ8mLXLW9rArNfbzphuxLXoH0ZkUz3q5X3X6MocUY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756868545; c=relaxed/simple; bh=mqb600+pneecQKzsZoignJ/8aykXWDyXNzFUolsqzrw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Y4jKomXZqf9K3tQnRQTqk3LGXdOjCLUVnLucqpBu2W+2CTFZPAt9kP3rLRnL/jkYSm27H54+Ibj0pqMI4p8WTgiwnrmcY+ZZ49movuv+w/aHzmxX9A5K8CUaBen35/PTrQzZ+soDTtdbA5wTfOca8DaLjR+ToXomHvBU+U1ZBeg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=VthOXtS9; arc=none smtp.client-ip=91.218.175.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="VthOXtS9" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1756868541; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3Y/9kZHekM+gIBRRUe68eDicKpPDtNyELOaDeeOu0CE=; b=VthOXtS91xS1dwsI7nuJzwzt7lhGfFY3j33cNwgTp64x7gCkivNXJwTi4G8iB9N8gEoMBE ffVKs54+iChzx6YS1RvXAeYHuszCM7hNfRvXHdnZjky6dpzMZKCPw47NVlKro57ZNGe/Kh NknhUZ1S70FseA816Wy9fc8gIVpkAtg= From: Youling Tang To: Huacai Chen Cc: WANG Xuerui , Baoquan He , Yao Zi , kexec@lists.infradead.org, loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, youling.tang@linux.dev, Youling Tang Subject: [PATCH v4 3/7] LoongArch/kexec_file: Support loading EFI binary file Date: Wed, 3 Sep 2025 11:00:56 +0800 Message-Id: <20250903030100.196744-4-youling.tang@linux.dev> In-Reply-To: <20250903030100.196744-1-youling.tang@linux.dev> References: <20250903030100.196744-1-youling.tang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Youling Tang This patch creates kexec_efi_ops to load EFI binary file for kexec_file_load() syscall. The efi_kexec_load() as two parts: - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi) - the second part loads other segments (eg: initrd, cmdline) Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images are supported. The basic usage (vmlinuz.efi or vmlinux.efi): 1) Load second kernel image: # kexec -s -l vmlinuz.efi --initrd=3Dinitrd.img --reuse-cmdline 2) Startup second kernel: # kexec -e Signed-off-by: Youling Tang --- arch/loongarch/include/asm/image.h | 17 +++ arch/loongarch/include/asm/kexec.h | 1 + arch/loongarch/kernel/Makefile | 2 +- arch/loongarch/kernel/kexec_efi.c | 114 +++++++++++++++++++++ arch/loongarch/kernel/machine_kexec_file.c | 1 + 5 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 arch/loongarch/kernel/kexec_efi.c diff --git a/arch/loongarch/include/asm/image.h b/arch/loongarch/include/as= m/image.h index ff539711c9ea..982cebd31cac 100644 --- a/arch/loongarch/include/asm/image.h +++ b/arch/loongarch/include/asm/image.h @@ -32,5 +32,22 @@ struct loongarch_image_header { uint32_t pe_header; }; =20 +static const uint8_t loongarch_image_dos_sig[2] =3D {'M', 'Z'}; + +/** + * loongarch_header_check_dos_sig - Helper to check the loongarch image he= ader. + * + * Returns non-zero if 'MZ' signature is found. + */ + +static inline int loongarch_header_check_dos_sig(const struct loongarch_im= age_header *h) +{ + if (!h) + return 0; + + return (h->dos_sig[0] =3D=3D loongarch_image_dos_sig[0] + && h->dos_sig[1] =3D=3D loongarch_image_dos_sig[1]); +} + #endif /* __ASSEMBLER__ */ #endif /* __ASM_IMAGE_H */ diff --git a/arch/loongarch/include/asm/kexec.h b/arch/loongarch/include/as= m/kexec.h index ed7e3fc8571e..34799db933fb 100644 --- a/arch/loongarch/include/asm/kexec.h +++ b/arch/loongarch/include/asm/kexec.h @@ -42,6 +42,7 @@ struct kimage_arch { }; =20 #ifdef CONFIG_KEXEC_FILE +extern const struct kexec_file_ops kexec_efi_ops; =20 int arch_kimage_file_post_load_cleanup(struct kimage *image); #define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_clea= nup diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile index 67b9b214d212..dd6183f353e6 100644 --- a/arch/loongarch/kernel/Makefile +++ b/arch/loongarch/kernel/Makefile @@ -62,7 +62,7 @@ obj-$(CONFIG_MAGIC_SYSRQ) +=3D sysrq.o obj-$(CONFIG_RELOCATABLE) +=3D relocate.o =20 obj-$(CONFIG_KEXEC_CORE) +=3D machine_kexec.o relocate_kernel.o -obj-$(CONFIG_KEXEC_FILE) +=3D machine_kexec_file.o +obj-$(CONFIG_KEXEC_FILE) +=3D machine_kexec_file.o kexec_efi.o obj-$(CONFIG_CRASH_DUMP) +=3D crash_dump.o =20 obj-$(CONFIG_UNWINDER_GUESS) +=3D unwind_guess.o diff --git a/arch/loongarch/kernel/kexec_efi.c b/arch/loongarch/kernel/kexe= c_efi.c new file mode 100644 index 000000000000..e02fd88cf5d0 --- /dev/null +++ b/arch/loongarch/kernel/kexec_efi.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Load EFI vmlinux file for the kexec_file_load syscall. + * + * Author: Youling Tang + * Copyright (C) 2025 KylinSoft Corporation. + */ + +#define pr_fmt(fmt) "kexec_file(EFI): " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int efi_kexec_probe(const char *kernel_buf, unsigned long kernel_le= n) +{ + const struct loongarch_image_header *h =3D (const struct loongarch_image_= header *)kernel_buf; + + if (!h || (kernel_len < sizeof(*h))) { + pr_err("No loongarch image header.\n"); + return -EINVAL; + } + + if (!loongarch_header_check_dos_sig(h)) { + pr_warn("No loongarch PE image header.\n"); + return -EINVAL; + } + + return 0; +} + +static void *efi_kexec_load(struct kimage *image, + char *kernel, unsigned long kernel_len, + char *initrd, unsigned long initrd_len, + char *cmdline, unsigned long cmdline_len) +{ + struct loongarch_image_header *h; + struct kexec_buf kbuf; + unsigned long text_offset, kernel_segment_number; + struct kexec_segment *kernel_segment; + int ret; + + h =3D (struct loongarch_image_header *)kernel; + if (!h->kernel_asize) + return ERR_PTR(-EINVAL); + + /* + * Load the kernel + * FIXME: Non-relocatable kernel rejected for kexec_file (require CONFIG_= RELOCATABLE) + */ + kbuf.image =3D image; + kbuf.buf_max =3D ULONG_MAX; + kbuf.top_down =3D false; + + kbuf.buffer =3D kernel; + kbuf.bufsz =3D kernel_len; + kbuf.mem =3D KEXEC_BUF_MEM_UNKNOWN; + kbuf.memsz =3D le64_to_cpu(h->kernel_asize); + text_offset =3D le64_to_cpu(h->text_offset); + kbuf.buf_min =3D text_offset; + kbuf.buf_align =3D SZ_2M; + + kernel_segment_number =3D image->nr_segments; + + /* + * The location of the kernel segment may make it impossible to satisfy + * the other segment requirements, so we try repeatedly to find a + * location that will work. + */ + while ((ret =3D kexec_add_buffer(&kbuf)) =3D=3D 0) { + /* Try to load additional data */ + kernel_segment =3D &image->segment[kernel_segment_number]; + ret =3D load_other_segments(image, kernel_segment->mem, + kernel_segment->memsz, initrd, + initrd_len, cmdline, cmdline_len); + if (!ret) + break; + + /* + * We couldn't find space for the other segments; erase the + * kernel segment and try the next available hole. + */ + image->nr_segments -=3D 1; + kbuf.buf_min =3D kernel_segment->mem + kernel_segment->memsz; + kbuf.mem =3D KEXEC_BUF_MEM_UNKNOWN; + } + + if (ret) { + pr_err("Could not find any suitable kernel location!"); + return ERR_PTR(ret); + } + + kernel_segment =3D &image->segment[kernel_segment_number]; + + /* Make sure the second kernel jumps to the correct "kernel_entry". */ + image->start =3D kernel_segment->mem + h->kernel_entry - text_offset; + + kexec_dprintk("Loaded kernel at 0x%lx bufsz=3D0x%lx memsz=3D0x%lx\n", + kernel_segment->mem, kbuf.bufsz, + kernel_segment->memsz); + + return NULL; +} + +const struct kexec_file_ops kexec_efi_ops =3D { + .probe =3D efi_kexec_probe, + .load =3D efi_kexec_load, +}; diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/ke= rnel/machine_kexec_file.c index 584ce9471e93..a454e9dfc339 100644 --- a/arch/loongarch/kernel/machine_kexec_file.c +++ b/arch/loongarch/kernel/machine_kexec_file.c @@ -21,6 +21,7 @@ #include =20 const struct kexec_file_ops * const kexec_file_loaders[] =3D { + &kexec_efi_ops, NULL }; =20 --=20 2.43.0 From nobody Fri Oct 3 08:48:20 2025 Received: from out-186.mta0.migadu.com (out-186.mta0.migadu.com [91.218.175.186]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 92AEC2C21DF for ; Wed, 3 Sep 2025 03:02:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.186 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756868549; cv=none; b=SRSknT03crc9AZqbxqbjhaiNIF98EuIXUsqNWwaMiyuzD1wpmzjYaiJJkUgekQWOqNKxoUWCKkXCiDEk9I+ohadXdE7gjExxrn/1Snup3toLN8sfOioS9EpVQ0vbvhIzCObJZtNnQ6eVe55UcHgOqD0x+0MY6iOn8xZ8VJRky7s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756868549; c=relaxed/simple; bh=OmcHN8DTdWzNc+Nw36q0A/0SOtjkrcHRKZb80MwQQ7U=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=I8GeU5bbFzGPNXeH7/I76D1E0eu/+mu2ZihsCFu7Uv6HUJUXZUBRYSUjp1/7bhMAaBdSSMdBf8HanyPjJoWH4k/DmdxyTdYHRx/rnJahfQJbdzbucFS11xwE1z1z7EpMS+z9FOkFrnXT6E2+2QcWkArBuIHEDaTUF01lui2by+4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=d68UxUnI; arc=none smtp.client-ip=91.218.175.186 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="d68UxUnI" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1756868544; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=83PuVuFgr80Y4Y/zYHwpjQEYSpCD6sDbiyfLT6lkmLg=; b=d68UxUnIXjvuVa5rxu2nU6DO7egzUULtp+BtNzj3zbtN9KhkF3t8AtWpp+Gviys0zLUzdq kLxhIXbepBg3bh44dg7whRy6yqKN3B6aRu7Y0yK4R6Fka0QjhMV+jZAM1lyK1WkoI7+CvR RbfNyyD7gxlJID4K5akBEgfIkqNCdyc= From: Youling Tang To: Huacai Chen Cc: WANG Xuerui , Baoquan He , Yao Zi , kexec@lists.infradead.org, loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, youling.tang@linux.dev, Youling Tang Subject: [PATCH v4 4/7] LoongArch/kexec_file: Support loading ELF binary file Date: Wed, 3 Sep 2025 11:00:57 +0800 Message-Id: <20250903030100.196744-5-youling.tang@linux.dev> In-Reply-To: <20250903030100.196744-1-youling.tang@linux.dev> References: <20250903030100.196744-1-youling.tang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Youling Tang This patch creates kexec_elf_ops to load ELF binary file for kexec_file_load() syscall. However, for `kbuf->memsz` and `kbuf->buf_min`, special handling is require= d, and the generic `kexec_elf_load()` cannot be used directly. $ readelf -l vmlinux ... Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000010000 0x9000000000200000 0x9000000000200000 0x0000000002747a00 0x000000000287a0d8 RWE 0x10000 NOTE 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 R 0x8 phdr->p_paddr should have been a physical address, but it is a virtual address on the current LoongArch. This will cause kexec_file to fail when loading the kernel and need to be converted to a physical address. From the above MemSiz, it can be seen that 0x287a0d8 has not been aligned. Although kexec_add_buffer() will perform PAGE_SIZE alignment on kbuf->memsz, there is still a stampeding in the loaded kernel space and initrd space. The initrd resolution failed when starting the second kernel. It can be known from the link script vmlinux.lds.S that, BSS_SECTION(0, SZ_64K, 8) . =3D ALIGN(PECOFF_SEGMENT_ALIGN); It needs to be aligned according to the SZ_64K size, so that after alignment, its size is consistent with _kernel_asize. The basic usage (vmlinux): 1) Load second kernel image: # kexec -s -l vmlinux --initrd=3Dinitrd.img --reuse-cmdline 2) Startup second kernel: # kexec -e Signed-off-by: Youling Tang --- arch/loongarch/Kconfig | 1 + arch/loongarch/include/asm/kexec.h | 1 + arch/loongarch/kernel/Makefile | 2 +- arch/loongarch/kernel/kexec_elf.c | 105 +++++++++++++++++++++ arch/loongarch/kernel/machine_kexec_file.c | 1 + 5 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 arch/loongarch/kernel/kexec_elf.c diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index 490dc6eed749..bf2664ed7ce3 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -632,6 +632,7 @@ config ARCH_SELECTS_KEXEC_FILE def_bool y depends on KEXEC_FILE select HAVE_IMA_KEXEC if IMA + select KEXEC_ELF select RELOCATABLE =20 config ARCH_SUPPORTS_CRASH_DUMP diff --git a/arch/loongarch/include/asm/kexec.h b/arch/loongarch/include/as= m/kexec.h index 34799db933fb..fecfb3015abc 100644 --- a/arch/loongarch/include/asm/kexec.h +++ b/arch/loongarch/include/asm/kexec.h @@ -43,6 +43,7 @@ struct kimage_arch { =20 #ifdef CONFIG_KEXEC_FILE extern const struct kexec_file_ops kexec_efi_ops; +extern const struct kexec_file_ops kexec_elf_ops; =20 int arch_kimage_file_post_load_cleanup(struct kimage *image); #define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_clea= nup diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile index dd6183f353e6..001924877772 100644 --- a/arch/loongarch/kernel/Makefile +++ b/arch/loongarch/kernel/Makefile @@ -62,7 +62,7 @@ obj-$(CONFIG_MAGIC_SYSRQ) +=3D sysrq.o obj-$(CONFIG_RELOCATABLE) +=3D relocate.o =20 obj-$(CONFIG_KEXEC_CORE) +=3D machine_kexec.o relocate_kernel.o -obj-$(CONFIG_KEXEC_FILE) +=3D machine_kexec_file.o kexec_efi.o +obj-$(CONFIG_KEXEC_FILE) +=3D machine_kexec_file.o kexec_efi.o kexec_elf.o obj-$(CONFIG_CRASH_DUMP) +=3D crash_dump.o =20 obj-$(CONFIG_UNWINDER_GUESS) +=3D unwind_guess.o diff --git a/arch/loongarch/kernel/kexec_elf.c b/arch/loongarch/kernel/kexe= c_elf.c new file mode 100644 index 000000000000..175d8d935e11 --- /dev/null +++ b/arch/loongarch/kernel/kexec_elf.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Load ELF vmlinux file for the kexec_file_load syscall. + * + * Author: Youling Tang + * Copyright (C) 2025 KylinSoft Corporation. + */ + +#define pr_fmt(fmt) "kexec_file(ELF): " fmt + +#include +#include +#include +#include +#include +#include + +static int loongarch_kexec_elf_load(struct kimage *image, struct elfhdr *e= hdr, + struct kexec_elf_info *elf_info, + struct kexec_buf *kbuf, + unsigned long *text_offset) +{ + int ret =3D -1; + size_t i; + + /* Read in the PT_LOAD segments. */ + for (i =3D 0; i < ehdr->e_phnum; i++) { + size_t size; + const struct elf_phdr *phdr; + + phdr =3D &elf_info->proghdrs[i]; + if (phdr->p_type !=3D PT_LOAD) + continue; + + size =3D phdr->p_filesz; + if (size > phdr->p_memsz) + size =3D phdr->p_memsz; + + kbuf->buffer =3D (void *)elf_info->buffer + phdr->p_offset; + kbuf->bufsz =3D size; + kbuf->buf_align =3D phdr->p_align; + *text_offset =3D __pa(phdr->p_paddr); + kbuf->buf_min =3D *text_offset; + kbuf->memsz =3D ALIGN(phdr->p_memsz, SZ_64K); + kbuf->mem =3D KEXEC_BUF_MEM_UNKNOWN; + ret =3D kexec_add_buffer(kbuf); + if (ret) + break; + } + + return ret; +} + +static void *elf_kexec_load(struct kimage *image, char *kernel_buf, + unsigned long kernel_len, char *initrd, + unsigned long initrd_len, char *cmdline, + unsigned long cmdline_len) +{ + int ret; + unsigned long text_offset =3D 0, kernel_segment_number; + struct elfhdr ehdr; + struct kexec_elf_info elf_info; + struct kexec_segment *kernel_segment; + struct kexec_buf kbuf; + + ret =3D kexec_build_elf_info(kernel_buf, kernel_len, &ehdr, &elf_info); + if (ret) + return ERR_PTR(ret); + + /* + * Load the kernel + * FIXME: Non-relocatable kernel rejected for kexec_file (require CONFIG_= RELOCATABLE) + */ + kbuf.image =3D image; + kbuf.buf_max =3D ULONG_MAX; + kbuf.top_down =3D false; + + kernel_segment_number =3D image->nr_segments; + + ret =3D loongarch_kexec_elf_load(image, &ehdr, &elf_info, &kbuf, &text_of= fset); + if (ret) + goto out; + + /* Load additional data */ + kernel_segment =3D &image->segment[kernel_segment_number]; + ret =3D load_other_segments(image, kernel_segment->mem, kernel_segment->m= emsz, + initrd, initrd_len, cmdline, cmdline_len); + if (ret) + goto out; + + /* Make sure the second kernel jumps to the correct "kernel_entry". */ + image->start =3D kernel_segment->mem + __pa(ehdr.e_entry) - text_offset; + + kexec_dprintk("Loaded kernel at 0x%lx bufsz=3D0x%lx memsz=3D0x%lx\n", + kernel_segment->mem, kbuf.bufsz, kernel_segment->memsz); + +out: + kexec_free_elf_info(&elf_info); + return ret ? ERR_PTR(ret) : NULL; +} + +const struct kexec_file_ops kexec_elf_ops =3D { + .probe =3D kexec_elf_probe, + .load =3D elf_kexec_load, +}; diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/ke= rnel/machine_kexec_file.c index a454e9dfc339..81913359b7a1 100644 --- a/arch/loongarch/kernel/machine_kexec_file.c +++ b/arch/loongarch/kernel/machine_kexec_file.c @@ -22,6 +22,7 @@ =20 const struct kexec_file_ops * const kexec_file_loaders[] =3D { &kexec_efi_ops, + &kexec_elf_ops, NULL }; =20 --=20 2.43.0 From nobody Fri Oct 3 08:48:20 2025 Received: from out-179.mta0.migadu.com (out-179.mta0.migadu.com [91.218.175.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B8C2F2C17B2 for ; Wed, 3 Sep 2025 03:02:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756868551; cv=none; b=Kh67sKilX615SXSMZ9PL7ocVQGXDzjM/80YDHQHpr7LQm46TOmJk3+8e2bBIpNSx1DFdcY41CZyGxdPFyjFUSIjNZ3as4Q+nTGCtX9I5nRDBxvti/GDyAJmkS3g/5KVNWJyCvn9lw/anv+btK7KlgbnyRbepk3lD+s6OFaHgWRk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756868551; c=relaxed/simple; bh=w9hUK+dRlUOgZ73nZQFMw0tDODSshINp6P9j9jqXgPI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=PSG2l58U7FOlZq+X9LHC6QRFspBU8iVyKASxQBy8gqUt7NujGhzWNZt3bXUvhRE2C0nXxaYcR2yfLCkBToepfKJoE3RlB/Q0iR/Fkl1GY3EANoKXFu2woVJ1UfPjMg9Zj1jkeSuB2rYhKX/XKmQy32M7XNjGEj2xw3fm1Vu90Xk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=Rg9FFLbI; arc=none smtp.client-ip=91.218.175.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="Rg9FFLbI" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1756868547; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=T4b0Kpf/tl9a1URo/4A0Vd1S2ONlllDvpb/j2reoa1Y=; b=Rg9FFLbISnAC0DPDnwOyxhM3/tWaI9dO48YHk+2Zx+Px4b26FA/g59xDqdb8kU0ifLAzbZ QUuy+e7ju/GJb7rMqHwaRLzi4t9JApYlARrogxSm0/0ctvnD8mcKnDlAZyRzhuJU3Kl6kx 902Zc7obQiMhI82H91bln5hrImWAc0E= From: Youling Tang To: Huacai Chen Cc: WANG Xuerui , Baoquan He , Yao Zi , kexec@lists.infradead.org, loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, youling.tang@linux.dev, Youling Tang Subject: [PATCH v4 5/7] LoongArch/kexec_file: Add crash dump support Date: Wed, 3 Sep 2025 11:00:58 +0800 Message-Id: <20250903030100.196744-6-youling.tang@linux.dev> In-Reply-To: <20250903030100.196744-1-youling.tang@linux.dev> References: <20250903030100.196744-1-youling.tang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Youling Tang Enabling crash dump (kdump) includes: - Prepare contents of ELF header of a core dump file, /proc/vmcore, using crash_prepare_elf64_headers(). - Add "elfcorehdr=3Dsize@start" to cmdline. - Add the "mem=3Dsize@start" parameter to the command line and pass it to the capture kernel. Limit the runtime memory area of the captured kernel to avoid disrupting the production kernel's runtime state. The basic usage for kdump(add the cmdline parameter crashkernel=3D512M to grub.cfg): 1) Load capture kernel image(vmlinux.efi or vmlinux can also be used): # kexec -s -p vmlinuz.efi --initrd=3Dinitrd.img --reuse-cmdline 2) Do something to crash, like: # echo c > /proc/sysrq-trigger Signed-off-by: Youling Tang --- arch/loongarch/kernel/machine_kexec_file.c | 116 +++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/ke= rnel/machine_kexec_file.c index 81913359b7a1..907a3286fa0d 100644 --- a/arch/loongarch/kernel/machine_kexec_file.c +++ b/arch/loongarch/kernel/machine_kexec_file.c @@ -35,6 +35,82 @@ int arch_kimage_file_post_load_cleanup(struct kimage *im= age) return kexec_image_post_load_cleanup_default(image); } =20 +#ifdef CONFIG_CRASH_DUMP + +static int prepare_elf_headers(void **addr, unsigned long *sz) +{ + struct crash_mem *cmem; + unsigned int nr_ranges; + int ret; + u64 i; + phys_addr_t start, end; + + nr_ranges =3D 2; /* for exclusion of crashkernel region */ + for_each_mem_range(i, &start, &end) + nr_ranges++; + + cmem =3D kmalloc(struct_size(cmem, ranges, nr_ranges), GFP_KERNEL); + if (!cmem) + return -ENOMEM; + + cmem->max_nr_ranges =3D nr_ranges; + cmem->nr_ranges =3D 0; + for_each_mem_range(i, &start, &end) { + cmem->ranges[cmem->nr_ranges].start =3D start; + cmem->ranges[cmem->nr_ranges].end =3D end - 1; + cmem->nr_ranges++; + } + + /* Exclude crashkernel region */ + ret =3D crash_exclude_mem_range(cmem, crashk_res.start, crashk_res.end); + if (ret) + goto out; + + if (crashk_low_res.end) { + ret =3D crash_exclude_mem_range(cmem, crashk_low_res.start, crashk_low_r= es.end); + if (ret) + goto out; + } + + ret =3D crash_prepare_elf64_headers(cmem, true, addr, sz); + +out: + kfree(cmem); + return ret; +} + +/* Adds the "elfcorehdr=3Dsize@start" command line parameter to command li= ne. */ +static void cmdline_add_elfcorehdr(struct kimage *image, unsigned long *cm= dline_tmplen, + char *modified_cmdline, unsigned long elfcorehdr_sz) +{ + int elfcorehdr_strlen =3D 0; + + elfcorehdr_strlen =3D sprintf(modified_cmdline + (*cmdline_tmplen), "elfc= orehdr=3D0x%lx@0x%lx ", + elfcorehdr_sz, image->elf_load_addr); + *cmdline_tmplen +=3D elfcorehdr_strlen; +} + +/* + * Adds the "mem=3Dsize@start" command line parameter to command line, ind= icating the + * memory region the new kernel can use to boot into. + */ +static void cmdline_add_mem(unsigned long *cmdline_tmplen, char *modified_= cmdline) +{ + int mem_strlen =3D 0; + + mem_strlen =3D sprintf(modified_cmdline + (*cmdline_tmplen), "mem=3D0x%ll= x@0x%llx ", + crashk_res.end - crashk_res.start + 1, crashk_res.start); + *cmdline_tmplen +=3D mem_strlen; + + if (crashk_low_res.end) { + mem_strlen =3D sprintf(modified_cmdline + (*cmdline_tmplen), "mem=3D0x%l= lx@0x%llx ", + crashk_low_res.end - crashk_low_res.start + 1, crashk_low_res.start); + *cmdline_tmplen +=3D mem_strlen; + } +} + +#endif + /* Adds the "initrd=3Dstart,size" command line parameter to command line. = */ static void cmdline_add_initrd(struct kimage *image, unsigned long *cmdlin= e_tmplen, char *modified_cmdline, unsigned long initrd) @@ -86,6 +162,46 @@ int load_other_segments(struct kimage *image, /* Ensure it's null terminated */ modified_cmdline[COMMAND_LINE_SIZE - 1] =3D '\0'; =20 +#ifdef CONFIG_CRASH_DUMP + /* load elf core header */ + void *headers; + unsigned long headers_sz; + + if (image->type =3D=3D KEXEC_TYPE_CRASH) { + ret =3D prepare_elf_headers(&headers, &headers_sz); + if (ret) { + pr_err("Preparing elf core header failed\n"); + goto out_err; + } + + kbuf.buffer =3D headers; + kbuf.bufsz =3D headers_sz; + kbuf.mem =3D KEXEC_BUF_MEM_UNKNOWN; + kbuf.memsz =3D headers_sz; + kbuf.buf_align =3D SZ_64K; /* largest supported page size */ + kbuf.buf_max =3D ULONG_MAX; + kbuf.top_down =3D true; + + ret =3D kexec_add_buffer(&kbuf); + if (ret) { + vfree(headers); + goto out_err; + } + image->elf_headers =3D headers; + image->elf_load_addr =3D kbuf.mem; + image->elf_headers_sz =3D headers_sz; + + kexec_dprintk("Loaded elf core header at 0x%lx bufsz=3D0x%lx memsz=3D0x%= lx\n", + image->elf_load_addr, kbuf.bufsz, kbuf.memsz); + + /* Add the elfcorehdr=3Dsize@start parameter to the command line */ + cmdline_add_elfcorehdr(image, &cmdline_tmplen, modified_cmdline, headers= _sz); + + /* Add the mem=3Dsize@start parameter to the command line */ + cmdline_add_mem(&cmdline_tmplen, modified_cmdline); + } +#endif + /* load initrd */ if (initrd) { kbuf.buffer =3D initrd; --=20 2.43.0 From nobody Fri Oct 3 08:48:20 2025 Received: from out-182.mta0.migadu.com (out-182.mta0.migadu.com [91.218.175.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 540B12D0615 for ; Wed, 3 Sep 2025 03:02:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756868555; cv=none; b=Km+2s4q7FlJ9w9reQ/1Hca2aTS8tqAyh9V1NTTrn+zSmYYNbu3D3b/lAtGj5x6jhG9ebZ0FSl+n0QaKDwHxZuQgkpL75SZGwHjaNhsGhRL7JZ81G9evE7y8md/kOb+25aeIXkYahmaaYCo5RYf1K0puGb3+kk7TEeCZQex6ljJc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756868555; c=relaxed/simple; bh=kZD+S95HMcR2nglnxtv9Ct+84C8o9d//zBGkBPOOi/c=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=MSw21vv6rR25LTC89tlOvZFd/YJZ5S2fS/nYxOOG+oK0r9r3pNPGUliwmLsCspGQWKycEEJbtqcLRCd7jwW0uQ+UXJVgKptme2LiSO7X9sXKM95VwtezIvNqo9BEtt94KbFvaPDTm5fVTx2RrPNSjX9H/CDr2bJrPh1AtRFc40o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=f9v3HJRt; arc=none smtp.client-ip=91.218.175.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="f9v3HJRt" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1756868551; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/Tx2jEMYoq+JZmLfU1X2XC0TcFq4rDCnPfS8rv1Co/4=; b=f9v3HJRtEPoHVtsb36i9AJ/EENH+XT+9tVrfyaZTy3JbfQuhVfbkgVbbAzrPkV3wXlyk9v BC8vBd2c9cNKyItzFfSAiyg8WmUd5l2HssYD4wv/w5Hw9J0dO4uWAeSDg18akW9pPSvx6X DkBPHzNd+MHZif29SmTlWwaKDS2k8lo= From: Youling Tang To: Huacai Chen Cc: WANG Xuerui , Baoquan He , Yao Zi , kexec@lists.infradead.org, loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, youling.tang@linux.dev, Youling Tang , stable@vger.kernel.org Subject: [PATCH v4 6/7] LoongArch: Automatically disable kaslr when the kernel loads from kexec_file Date: Wed, 3 Sep 2025 11:00:59 +0800 Message-Id: <20250903030100.196744-7-youling.tang@linux.dev> In-Reply-To: <20250903030100.196744-1-youling.tang@linux.dev> References: <20250903030100.196744-1-youling.tang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Youling Tang Automatically disable kaslr when the kernel loads from kexec_file. kexec_file loads the secondary kernel image to a non-linked address, inherently providing KASLR-like randomization. However, on LoongArch where System RAM may be non-contiguous, enabling KASLR for the second kernel could relocate it to an invalid memory region and cause boot failure. Thus, we disable KASLR when "kexec_file" is detected in the command line. To ensure compatibility with older kernels loaded via kexec_file, this patch need be backported to stable branches. Cc: stable@vger.kernel.org Signed-off-by: Youling Tang --- arch/loongarch/kernel/relocate.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/loongarch/kernel/relocate.c b/arch/loongarch/kernel/reloc= ate.c index 50c469067f3a..4c097532cb88 100644 --- a/arch/loongarch/kernel/relocate.c +++ b/arch/loongarch/kernel/relocate.c @@ -140,6 +140,10 @@ static inline __init bool kaslr_disabled(void) if (str =3D=3D boot_command_line || (str > boot_command_line && *(str - 1= ) =3D=3D ' ')) return true; =20 + str =3D strstr(boot_command_line, "kexec_file"); + if (str =3D=3D boot_command_line || (str > boot_command_line && *(str - 1= ) =3D=3D ' ')) + return true; + #ifdef CONFIG_HIBERNATION str =3D strstr(builtin_cmdline, "nohibernate"); if (str =3D=3D builtin_cmdline || (str > builtin_cmdline && *(str - 1) = =3D=3D ' ')) --=20 2.43.0 From nobody Fri Oct 3 08:48:20 2025 Received: from out-189.mta0.migadu.com (out-189.mta0.migadu.com [91.218.175.189]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3F7342D0638 for ; Wed, 3 Sep 2025 03:02:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.189 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756868557; cv=none; b=JqmurCs2hpODmKomS99YYAQWOwzp20C/tQA7m0Bxc/lbA3FQ2PmN3r9ik45Sv2dwJfEqRhh75622FXL2HpqYZsXfCNxWJoHCDPTpK6Kg+p7Ry0v0niNFkqaLjVcWxRv7agxjRKIbRmW4LUprr55YGmP+4W39KfEQ8wHhf+onZhI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756868557; c=relaxed/simple; bh=QUKo6e58SSJFQgr+/h0Hwp0bH0rAwKhcQAAdxn7j7xs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=AvVaqzsyq+SrZO734KHG9KjH0H4sEDIwsSRid+qJBTwp+jEuwVUHC2eQ60OwhLmlkehEhA4Zo8H6TvKqXkdEMNlvoIPvhA9WvrWWCOOG5V6ysHJQ7aCYdie9MCdiAvOudmcY9YjW9jS/q/m7VJmsGoLI2gOvxC5z82jI7Fqi7Pk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=mF4aqh+1; arc=none smtp.client-ip=91.218.175.189 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="mF4aqh+1" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1756868554; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cRynx6jaHBNziqdWwYMx6lpx2wd+0zdA8DgB67CZ52I=; b=mF4aqh+1V/7wCkaLaALq3wIS5h4V21NQrY/AN44J2nbOiurpql+JHY/6ILtCAnCC4aZxNi wwtqekrTRGXl1XrPjM8A1pQoESrS4M7YiC0YcXnvvoAMAefcCR/iUDDqd2atZR6mgfpGKk R6w0RZRIzYjiS4fpFUg6seR/coxRNmU= From: Youling Tang To: Huacai Chen Cc: WANG Xuerui , Baoquan He , Yao Zi , kexec@lists.infradead.org, loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, youling.tang@linux.dev, Youling Tang Subject: [PATCH v4 7/7] LoongArch: Enable CONFIG_KEXEC_FILE Date: Wed, 3 Sep 2025 11:01:00 +0800 Message-Id: <20250903030100.196744-8-youling.tang@linux.dev> In-Reply-To: <20250903030100.196744-1-youling.tang@linux.dev> References: <20250903030100.196744-1-youling.tang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Youling Tang This patch enables config KEXEC_FILE by default in the loongson3_defconfig, so that user-space tools like kexec-tools can use the same as the default interface for kexec/kdump on LoongArch. Signed-off-by: Youling Tang --- arch/loongarch/configs/loongson3_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/loongarch/configs/loongson3_defconfig b/arch/loongarch/co= nfigs/loongson3_defconfig index 34eaee0384c9..6cfea2f37cc0 100644 --- a/arch/loongarch/configs/loongson3_defconfig +++ b/arch/loongarch/configs/loongson3_defconfig @@ -45,6 +45,7 @@ CONFIG_EXPERT=3Dy CONFIG_KALLSYMS_ALL=3Dy CONFIG_PERF_EVENTS=3Dy CONFIG_KEXEC=3Dy +CONFIG_KEXEC_FILE=3Dy CONFIG_CRASH_DUMP=3Dy CONFIG_LOONGARCH=3Dy CONFIG_64BIT=3Dy --=20 2.43.0