From nobody Mon Feb 9 17:24:37 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=quarantine dis=none) header.from=antgroup.com ARC-Seal: i=1; a=rsa-sha256; t=1769434587; cv=none; d=zohomail.com; s=zohoarc; b=h1+8mv4yTrDruFjeSs3cd6bOtqWR3MkN0MJppAMn+s2DZa3uTmHcuOXullEgFQE7pwFjHgW2Kg75VqqrdWwWQOM/H1bx/A3km3x1vpaiUfAA5NeBZulINOHDeRHoNYcl+Z2mlCg4PM4UOmYgO3mm31F9x5Pll6I7wgprQWAuSp4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769434587; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=VyKxMTwvBHUzyW1uTW736L2GPVuIiSygzDpiTrPhWW8=; b=H1roWBvy5x5zgVS3ZG61zf8sLaePTbt9qtur/q/bHZBpSOCtbnhs09yEFPq7sR3XAwUG8gx6IfAGzs4nN3cmIabKy/uZS+xE07Uk3XOOFudKlFlcn55bi8owEvLSncYMxIpPIGqIm3LbmNxgTYCpg9InK3k81Y8EL9wspyhuwzM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1769434587509279.1738565953484; Mon, 26 Jan 2026 05:36:27 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1213720.1524193 (Exim 4.92) (envelope-from ) id 1vkMlK-0003iB-4C; Mon, 26 Jan 2026 13:36:14 +0000 Received: by outflank-mailman (output) from mailman id 1213720.1524193; Mon, 26 Jan 2026 13:36:14 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vkMlK-0003i4-1A; Mon, 26 Jan 2026 13:36:14 +0000 Received: by outflank-mailman (input) for mailman id 1213720; Mon, 26 Jan 2026 13:36:12 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vkMlI-0003VU-GW for xen-devel@lists.xenproject.org; Mon, 26 Jan 2026 13:36:12 +0000 Received: from out28-52.mail.aliyun.com (out28-52.mail.aliyun.com [115.124.28.52]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id f6e9401c-fabb-11f0-9ccf-f158ae23cfc8; Mon, 26 Jan 2026 14:36:08 +0100 (CET) Received: from localhost(mailfrom:houwenlong.hwl@antgroup.com fp:SMTPD_---.gGID1nH_1769434562 cluster:ay29) by smtp.aliyun-inc.com; Mon, 26 Jan 2026 21:36:03 +0800 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: f6e9401c-fabb-11f0-9ccf-f158ae23cfc8 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=antgroup.com; s=default; t=1769434565; h=From:To:Subject:Date:Message-Id:MIME-Version; bh=VyKxMTwvBHUzyW1uTW736L2GPVuIiSygzDpiTrPhWW8=; b=Iwk6WT3ax7dZYFr2LpsKXdh+MDYo1dBQLcy/P/FOeFykpsga67y6uySmOjRlnTDyxmC5lxmjJSk/2Od51rVv7fUPF2giChSQbtzJt+N+5JIjJ2zPy9rZ7s6aD0D94AWHj38LoqVTvtjXuabu+x5A7SK1gnAnPP6TJdlH2ci3P0c= From: Hou Wenlong To: linux-kernel@vger.kernel.org Cc: Lai Jiangshan , Hou Wenlong , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Juergen Gross , Boris Ostrovsky , Ard Biesheuvel , Josh Poimboeuf , Nathan Chancellor , Andrew Morton , Alexander Graf , Joel Granados , Thomas Huth , Uros Bizjak , Brian Gerst , Kiryl Shutsemau , "Xin Li (Intel)" , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , xen-devel@lists.xenproject.org Subject: [RFC PATCH 4/5] x86/boot: Perform virtual address relocation in kernel entry Date: Mon, 26 Jan 2026 21:33:54 +0800 Message-Id: X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @antgroup.com) X-ZM-MESSAGEID: 1769434589790158500 Content-Type: text/plain; charset="utf-8" Perform virtual address relocation for the uncompressed kernel during booting, which is similar to the relocation during decompression. Signed-off-by: Hou Wenlong --- arch/x86/boot/startup/Makefile | 1 + arch/x86/boot/startup/kaslr.c | 116 +++++++++++++++++++++++++++++++++ arch/x86/include/asm/setup.h | 1 + arch/x86/kernel/head_64.S | 7 ++ arch/x86/lib/cmdline.c | 6 ++ arch/x86/lib/kaslr.c | 5 ++ arch/x86/platform/pvh/head.S | 15 ++++- 7 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 arch/x86/boot/startup/kaslr.c diff --git a/arch/x86/boot/startup/Makefile b/arch/x86/boot/startup/Makefile index 5e499cfb29b5..eeaefa4e25fb 100644 --- a/arch/x86/boot/startup/Makefile +++ b/arch/x86/boot/startup/Makefile @@ -20,6 +20,7 @@ KCOV_INSTRUMENT :=3D n =20 obj-$(CONFIG_X86_64) +=3D gdt_idt.o map_kernel.o obj-$(CONFIG_AMD_MEM_ENCRYPT) +=3D sme.o sev-startup.o +obj-$(CONFIG_RELOCATABLE_UNCOMPRESSED_KERNEL) +=3D kaslr.o pi-objs :=3D $(patsubst %.o,$(obj)/%.o,$(obj-y)) =20 lib-$(CONFIG_X86_64) +=3D la57toggle.o diff --git a/arch/x86/boot/startup/kaslr.c b/arch/x86/boot/startup/kaslr.c new file mode 100644 index 000000000000..fb07c31e21b3 --- /dev/null +++ b/arch/x86/boot/startup/kaslr.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include + +/* A hack to avoid non-static declaration for kaslr_get_random_long(). */ +#define _ASM_KASLR_H_ +#include +#include +#include + +extern char __relocation_end[]; + +static struct boot_params *boot_params_ptr __initdata; + +static inline void debug_putstr(const char *str) +{ +} + +static inline bool has_cpuflag(int flag) +{ + u32 reg =3D 0; + u32 level =3D native_cpuid_eax(0x0); + + if (level >=3D 0x00000001) { + if (flag =3D=3D X86_FEATURE_RDRAND) + reg =3D native_cpuid_edx(0x1); + else if (flag =3D=3D X86_FEATURE_TSC) + reg =3D native_cpuid_ecx(0x1); + } + + return test_bit(flag & 31, (unsigned long *)®); +} + +static unsigned long __init rotate_xor(unsigned long hash, const void *are= a, + size_t size) +{ + size_t i; + unsigned long *ptr =3D (unsigned long *)area; + + for (i =3D 0; i < size / sizeof(hash); i++) { + /* Rotate by odd number of bits and XOR. */ + hash =3D (hash << ((sizeof(hash) * 8) - 7)) | (hash >> 7); + hash ^=3D ptr[i]; + } + + return hash; +} + +/* Attempt to create a simple but unpredictable starting entropy. */ +static unsigned long get_boot_seed(void) +{ + unsigned long hash =3D 0; + + hash =3D rotate_xor(hash, boot_params_ptr, sizeof(*boot_params_ptr)); + + return hash; +} + +#define KASLR_COMPRESSED_BOOT +#define KASLR_FUNC_PREFIX static __init +#include "../../lib/kaslr.c" + +/* A hack to avoid non-static declaration for cmdline_find_option_bool(). = */ +#define _ASM_X86_CMDLINE_H +#undef CONFIG_CMDLINE_BOOL +#define builtin_cmdline NULL +#define CMDLINE_FUNC_PREFIX static __maybe_unused __init +#include "../../lib/cmdline.c" + +static unsigned long __init find_random_virt_addr(unsigned long minimum, + unsigned long image_size) +{ + unsigned long slots, random_addr; + + /* + * There are how many CONFIG_PHYSICAL_ALIGN-sized slots + * that can hold image_size within the range of minimum to + * KERNEL_IMAGE_SIZE? + */ + slots =3D 1 + (KERNEL_IMAGE_SIZE - minimum - image_size) / CONFIG_PHYSICA= L_ALIGN; + + random_addr =3D kaslr_get_random_long("Virtual") % slots; + + return random_addr * CONFIG_PHYSICAL_ALIGN + minimum; +} + +void __init __relocate_kernel(unsigned long p2v_offset, struct boot_params= *bp) +{ + int *reloc =3D (int *)rip_rel_ptr(__relocation_end); + unsigned long image_size =3D rip_rel_ptr(_end) - rip_rel_ptr(_text); + unsigned long ptr, virt_addr, delta; + unsigned long cmd_line_ptr; + + /* If relocation has occurred during decompression, simply skip it. */ + if (bp->hdr.loadflags & KASLR_FLAG) + return; + + cmd_line_ptr =3D bp->hdr.cmd_line_ptr | ((u64)bp->ext_cmd_line_ptr << 32); + if (cmdline_find_option_bool((char *)cmd_line_ptr, "nokaslr")) + return; + + boot_params_ptr =3D bp; + virt_addr =3D find_random_virt_addr(LOAD_PHYSICAL_ADDR, image_size); + delta =3D virt_addr - LOAD_PHYSICAL_ADDR; + + for (reloc--; *reloc; reloc--) { + ptr =3D (unsigned long)(*reloc + p2v_offset); + *(uint32_t *)ptr +=3D delta; + } + + for (reloc--; *reloc; reloc--) { + ptr =3D (unsigned long)(*reloc + p2v_offset); + *(uint64_t *)ptr +=3D delta; + } +} diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index 914eb32581c7..86a715a255a5 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h @@ -56,6 +56,7 @@ extern void startup_64_load_idt(void *vc_handler); extern void __pi_startup_64_load_idt(void *vc_handler); extern void early_setup_idt(void); extern void __init do_early_exception(struct pt_regs *regs, int trapnr); +extern void __init __relocate_kernel(unsigned long p2v_offset, struct boot= _params *bp); =20 #ifdef CONFIG_X86_INTEL_MID extern void x86_intel_mid_early_setup(void); diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 21816b48537c..868d8fdd59df 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -97,6 +97,13 @@ SYM_CODE_START_NOALIGN(startup_64) /* Sanitize CPU configuration */ call verify_cpu =20 +#ifdef CONFIG_RELOCATABLE_UNCOMPRESSED_KERNEL + leaq common_startup_64(%rip), %rdi + subq .Lcommon_startup_64(%rip), %rdi + movq %r15, %rsi + call __pi___relocate_kernel +#endif + /* * Derive the kernel's physical-to-virtual offset from the physical and * virtual addresses of common_startup_64(). diff --git a/arch/x86/lib/cmdline.c b/arch/x86/lib/cmdline.c index c65cd5550454..07c4398b9e67 100644 --- a/arch/x86/lib/cmdline.c +++ b/arch/x86/lib/cmdline.c @@ -11,6 +11,10 @@ #include #include =20 +#ifndef CMDLINE_FUNC_PREFIX +#define CMDLINE_FUNC_PREFIX +#endif + static inline int myisspace(u8 c) { return c <=3D ' '; /* Close enough approximation */ @@ -205,6 +209,7 @@ __cmdline_find_option(const char *cmdline, int max_cmdl= ine_size, return len; } =20 +CMDLINE_FUNC_PREFIX int cmdline_find_option_bool(const char *cmdline, const char *option) { int ret; @@ -219,6 +224,7 @@ int cmdline_find_option_bool(const char *cmdline, const= char *option) return ret; } =20 +CMDLINE_FUNC_PREFIX int cmdline_find_option(const char *cmdline, const char *option, char *buf= fer, int bufsize) { diff --git a/arch/x86/lib/kaslr.c b/arch/x86/lib/kaslr.c index 8c7cd115b484..711a19729e20 100644 --- a/arch/x86/lib/kaslr.c +++ b/arch/x86/lib/kaslr.c @@ -13,6 +13,10 @@ #include #include =20 +#ifndef KASLR_FUNC_PREFIX +#define KASLR_FUNC_PREFIX +#endif + /* * When built for the regular kernel, several functions need to be stubbed= out * or changed to their regular kernel equivalent. @@ -46,6 +50,7 @@ static inline u16 i8254(void) return timer; } =20 +KASLR_FUNC_PREFIX unsigned long kaslr_get_random_long(const char *purpose) { #ifdef CONFIG_X86_64 diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S index 344030c1a81d..94832930b0a2 100644 --- a/arch/x86/platform/pvh/head.S +++ b/arch/x86/platform/pvh/head.S @@ -103,6 +103,17 @@ SYM_CODE_START(pvh_start_xen) btsl $_EFER_LME, %eax wrmsr =20 + /* + * Fill the identity mapping entries instead of preconstructing them, + * as later relocations in __relocation_kernel() would modify them and + * break the mapping if they are prefilled, due to the generation of + * relocation entries. + */ + leal rva(pvh_init_top_pgt)(%ebp), %edi + addl $(pvh_level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC), = (%edi) + leal rva(pvh_level3_ident_pgt)(%ebp), %edi + addl $(pvh_level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC), = (%edi) + /* * Reuse the non-relocatable symbol emitted for the ELF note to * subtract the build time physical address of pvh_start_xen() from @@ -254,7 +265,6 @@ SYM_DATA_END_LABEL(early_stack, SYM_L_LOCAL, early_stac= k_end) * startup_64 transitions to init_top_pgt. */ SYM_DATA_START_PAGE_ALIGNED(pvh_init_top_pgt) - .quad pvh_level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC .org pvh_init_top_pgt + L4_PAGE_OFFSET * 8, 0 .quad pvh_level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC .org pvh_init_top_pgt + L4_START_KERNEL * 8, 0 @@ -263,8 +273,7 @@ SYM_DATA_START_PAGE_ALIGNED(pvh_init_top_pgt) SYM_DATA_END(pvh_init_top_pgt) =20 SYM_DATA_START_PAGE_ALIGNED(pvh_level3_ident_pgt) - .quad pvh_level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC - .fill 511, 8, 0 + .fill 512, 8, 0 SYM_DATA_END(pvh_level3_ident_pgt) SYM_DATA_START_PAGE_ALIGNED(pvh_level2_ident_pgt) /* --=20 2.31.1