public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ardb@kernel.org>
To: linux-kernel@vger.kernel.org
Cc: x86@kernel.org, Ard Biesheuvel <ardb@kernel.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Josh Poimboeuf <jpoimboe@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Kees Cook <kees@kernel.org>, Uros Bizjak <ubizjak@gmail.com>,
	Brian Gerst <brgerst@gmail.com>,
	linux-hardening@vger.kernel.org
Subject: [RFC/RFT PATCH 04/19] x86: Make the 64-bit bzImage always physically relocatable
Date: Thu,  8 Jan 2026 09:25:31 +0000	[thread overview]
Message-ID: <20260108092526.28586-25-ardb@kernel.org> (raw)
In-Reply-To: <20260108092526.28586-21-ardb@kernel.org>

On x86_64, the physical placement of the kernel is independent from its
mapping in the 'High Kernel Mapping' range. This means that even a
position dependent kernel built without boot-time relocation support can
run from any suitably aligned physical address, and there is no need to
make this behavior dependent on whether or not the kernel is virtually
relocatable.

On i386, the situation is different, given that the physical and virtual
load offsets must be equal, and so only a relocatable kernel can be
loaded at a physical address that deviates from its build-time default.

Clarify this in Kconfig and in the code, and advertise the 64-bit
bzImage as loadable at any physical offset regardless of whether
CONFIG_RELOCATABLE is set. In practice, this makes little difference,
given that it defaults to 'y' and is a prerequisite for EFI_STUB and
RANDOMIZE_BASE, but it will help with some future refactoring of the
relocation code.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/Kconfig                   | 40 ++++++++++++--------
 arch/x86/boot/compressed/head_64.S |  4 --
 arch/x86/boot/compressed/misc.c    |  8 ++--
 arch/x86/boot/header.S             |  8 +---
 4 files changed, 29 insertions(+), 31 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 80527299f859..bf51e17d5813 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1931,7 +1931,7 @@ config EFI
 config EFI_STUB
 	bool "EFI stub support"
 	depends on EFI
-	select RELOCATABLE
+	select RELOCATABLE if X86_32
 	help
 	  This kernel feature allows a bzImage to be loaded directly
 	  by EFI firmware without the use of a bootloader.
@@ -2028,8 +2028,9 @@ config PHYSICAL_START
 	help
 	  This gives the physical address where the kernel is loaded.
 
-	  If the kernel is not relocatable (CONFIG_RELOCATABLE=n) then bzImage
-	  will decompress itself to above physical address and run from there.
+	  If the kernel is not relocatable (CONFIG_RELOCATABLE=n) and built for
+	  i386, then the bzImage will decompress itself to the above physical
+	  address and run from there.
 	  Otherwise, bzImage will run from the address where it has been loaded
 	  by the boot loader. The only exception is if it is loaded below the
 	  above physical address, in which case it will relocate itself there.
@@ -2064,16 +2065,22 @@ config PHYSICAL_START
 	  Don't change this unless you know what you are doing.
 
 config RELOCATABLE
-	bool "Build a relocatable kernel"
-	default y
+	bool "Build a relocatable kernel" if X86_32
+	default X86_32
 	help
-	  This builds a kernel image that retains relocation information
-	  so it can be loaded someplace besides the default 1MB.
+	  This builds a kernel image that retains relocation information so it
+	  can be placed someplace besides the default PAGE_OFFSET + 1MB. This
+	  is a prerequisite for KASLR.
 	  The relocations tend to make the kernel binary about 10% larger,
 	  but are discarded at runtime.
 
-	  One use is for the kexec on panic case where the recovery kernel
-	  must live at a different physical address than the primary
+	  On i386, where the virtual and physical load offset of the kernel
+	  must be equal, this also allows the kernel image to be placed at a
+	  physical load address that differs from the compile time default. On
+	  x86_64, this is always permitted.
+
+	  One use is for the kexec on panic case on i386, where the recovery
+	  kernel must live at a different physical address than the primary
 	  kernel.
 
 	  Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address
@@ -2082,7 +2089,7 @@ config RELOCATABLE
 
 config RANDOMIZE_BASE
 	bool "Randomize the address of the kernel image (KASLR)"
-	depends on RELOCATABLE
+	select RELOCATABLE
 	default y
 	help
 	  In support of Kernel Address Space Layout Randomization (KASLR),
@@ -2118,7 +2125,7 @@ config RANDOMIZE_BASE
 # Relocation on x86 needs some additional build support
 config X86_NEED_RELOCS
 	def_bool y
-	depends on RANDOMIZE_BASE || (X86_32 && RELOCATABLE)
+	depends on RELOCATABLE
 	select ARCH_VMLINUX_NEEDS_RELOCS
 
 config PHYSICAL_ALIGN
@@ -2131,12 +2138,13 @@ config PHYSICAL_ALIGN
 	  where kernel is loaded and run from. Kernel is compiled for an
 	  address which meets above alignment restriction.
 
-	  If bootloader loads the kernel at a non-aligned address and
-	  CONFIG_RELOCATABLE is set, kernel will move itself to nearest
-	  address aligned to above value and run from there.
+	  If the bootloader loads the kernel at a non-aligned address and it
+	  is built for x86_64 or CONFIG_RELOCATABLE is set, the kernel will
+	  move itself to the nearest address aligned to above value and run
+	  from there.
 
-	  If bootloader loads the kernel at a non-aligned address and
-	  CONFIG_RELOCATABLE is not set, kernel will ignore the run time
+	  If the bootloader loads the i386 kernel at a non-aligned address and
+	  CONFIG_RELOCATABLE is not set, the kernel will ignore the run time
 	  load address and decompress itself to the address it has been
 	  compiled for and run from there. The address for which kernel is
 	  compiled already meets above alignment restrictions. Hence the
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index d9dab940ff62..8a964a4d45c2 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -143,7 +143,6 @@ SYM_FUNC_START(startup_32)
  * for safe in-place decompression.
  */
 
-#ifdef CONFIG_RELOCATABLE
 	movl	%ebp, %ebx
 	movl	BP_kernel_alignment(%esi), %eax
 	decl	%eax
@@ -152,7 +151,6 @@ SYM_FUNC_START(startup_32)
 	andl	%eax, %ebx
 	cmpl	$LOAD_PHYSICAL_ADDR, %ebx
 	jae	1f
-#endif
 	movl	$LOAD_PHYSICAL_ADDR, %ebx
 1:
 
@@ -312,7 +310,6 @@ SYM_CODE_START(startup_64)
 	 */
 
 	/* Start with the delta to where the kernel will run at. */
-#ifdef CONFIG_RELOCATABLE
 	leaq	startup_32(%rip) /* - $startup_32 */, %rbp
 	movl	BP_kernel_alignment(%rsi), %eax
 	decl	%eax
@@ -321,7 +318,6 @@ SYM_CODE_START(startup_64)
 	andq	%rax, %rbp
 	cmpq	$LOAD_PHYSICAL_ADDR, %rbp
 	jae	1f
-#endif
 	movq	$LOAD_PHYSICAL_ADDR, %rbp
 1:
 
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 0f41ca0e52c0..d37569e7ee10 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -314,12 +314,10 @@ static size_t parse_elf(void *output)
 			if ((phdr->p_align % 0x200000) != 0)
 				error("Alignment of LOAD segment isn't multiple of 2MB");
 #endif
-#ifdef CONFIG_RELOCATABLE
-			dest = output;
-			dest += (phdr->p_paddr - LOAD_PHYSICAL_ADDR);
-#else
 			dest = (void *)(phdr->p_paddr);
-#endif
+			if (IS_ENABLED(CONFIG_X86_64) ||
+			    IS_ENABLED(CONFIG_RELOCATABLE))
+				dest += (unsigned long)output - LOAD_PHYSICAL_ADDR;
 			memmove(dest, output + phdr->p_offset, phdr->p_filesz);
 			break;
 		default: /* Ignore other PT_* */ break;
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 9bea5a1e2c52..b72e6055e103 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -332,7 +332,7 @@ initrd_addr_max: .long 0x7fffffff
 kernel_alignment:  .long CONFIG_PHYSICAL_ALIGN	#physical addr alignment
 						#required for protected mode
 						#kernel
-#ifdef CONFIG_RELOCATABLE
+#if defined(CONFIG_RELOCATABLE) || defined(CONFIG_X86_64)
 relocatable_kernel:    .byte 1
 #else
 relocatable_kernel:    .byte 0
@@ -342,14 +342,10 @@ min_alignment:		.byte MIN_KERNEL_ALIGN_LG2	# minimum alignment
 xloadflags:
 #ifdef CONFIG_X86_64
 # define XLF0 XLF_KERNEL_64			/* 64-bit kernel */
-#else
-# define XLF0 0
-#endif
-
-#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_X86_64)
    /* kernel/boot_param/ramdisk could be loaded above 4g */
 # define XLF1 XLF_CAN_BE_LOADED_ABOVE_4G
 #else
+# define XLF0 0
 # define XLF1 0
 #endif
 
-- 
2.47.3


  parent reply	other threads:[~2026-01-08  9:28 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-08  9:25 [RFC/RFT PATCH 00/19] Link the relocatable x86 kernel as PIE Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 01/19] x86/idt: Move idt_table to __ro_after_init section Ard Biesheuvel
2026-01-22 13:08   ` Borislav Petkov
2026-01-22 13:48     ` Ard Biesheuvel
2026-01-22 13:58       ` Borislav Petkov
2026-01-22 14:09         ` Ard Biesheuvel
2026-01-22 14:16           ` Borislav Petkov
2026-01-22 14:20             ` Ard Biesheuvel
2026-01-22 14:25               ` Borislav Petkov
2026-01-08  9:25 ` [RFC/RFT PATCH 02/19] x86/sev: Don't emit BSS_DECRYPT section unless it is in use Ard Biesheuvel
2026-01-31 14:09   ` [tip: x86/sev] x86/sev: Don't emit BSS_DECRYPTED " tip-bot2 for Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 03/19] x86: Combine .data with .bss in kernel mapping Ard Biesheuvel
2026-03-06 19:07   ` Borislav Petkov
2026-03-09 14:11     ` Ard Biesheuvel
2026-01-08  9:25 ` Ard Biesheuvel [this message]
2026-01-12  4:01   ` [RFC/RFT PATCH 04/19] x86: Make the 64-bit bzImage always physically relocatable H. Peter Anvin
2026-01-12 10:47     ` David Laight
2026-01-12 12:06       ` H. Peter Anvin
2026-01-08  9:25 ` [RFC/RFT PATCH 05/19] x86/efistub: Simplify early remapping of kernel text Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 06/19] alloc_tag: Use __ prefixed ELF section names Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 07/19] tools/objtool: Treat indirect ftrace calls as direct calls Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 08/19] x86: Use PIE codegen for the relocatable 64-bit kernel Ard Biesheuvel
2026-01-09 21:34   ` Jan Engelhardt
2026-01-09 22:07     ` Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 09/19] x86/pm-trace: Use RIP-relative accesses for .tracedata Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 10/19] x86/kvm: Use RIP-relative addressing Ard Biesheuvel
2026-01-20 17:04   ` Sean Christopherson
2026-01-20 19:43     ` David Laight
2026-01-20 20:54       ` Ard Biesheuvel
2026-01-20 22:00         ` David Laight
2026-01-08  9:25 ` [RFC/RFT PATCH 11/19] x86/rethook: Use RIP-relative reference for fake return address Ard Biesheuvel
2026-01-08 12:08   ` David Laight
2026-01-08 12:10     ` Ard Biesheuvel
2026-01-08 12:19       ` Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 12/19] x86/sync_core: Use RIP-relative addressing Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 13/19] x86/entry_64: " Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 14/19] x86/hibernate: Prefer RIP-relative accesses Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 15/19] x64/acpi: Use PIC-compatible references in wakeup_64.S Ard Biesheuvel
2026-01-09  5:01   ` Brian Gerst
2026-01-09  7:59     ` Ard Biesheuvel
2026-01-09 11:46       ` Brian Gerst
2026-01-09 12:09         ` Ard Biesheuvel
2026-01-09 12:10           ` Ard Biesheuvel
2026-01-09 12:51             ` Brian Gerst
2026-01-08  9:25 ` [RFC/RFT PATCH 16/19] x86/kexec: Use 64-bit wide absolute reference from relocated code Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 17/19] x86/head64: Avoid absolute references in startup asm Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 18/19] x86/boot: Implement support for RELA/RELR/REL runtime relocations Ard Biesheuvel
2026-01-08  9:25 ` [RFC/RFT PATCH 19/19] x86/kernel: Switch to PIE linking for the relocatable kernel Ard Biesheuvel
2026-01-08 16:35 ` [RFC/RFT PATCH 00/19] Link the relocatable x86 kernel as PIE Alexander Lobakin
2026-01-09  0:36 ` H. Peter Anvin
2026-01-09  9:21   ` Ard Biesheuvel
2026-01-14 18:16     ` Kees Cook
2026-01-20 20:45       ` H. Peter Anvin
2026-01-21  8:56         ` Ard Biesheuvel

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=20260108092526.28586-25-ardb@kernel.org \
    --to=ardb@kernel.org \
    --cc=bp@alien8.de \
    --cc=brgerst@gmail.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=jpoimboe@kernel.org \
    --cc=kees@kernel.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=ubizjak@gmail.com \
    --cc=x86@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