From: Ard Biesheuvel <ardb@kernel.org>
To: linux-efi@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel <ardb@kernel.org>,
Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
Ingo Molnar <mingo@redhat.com>,
Thomas Gleixner <tglx@linutronix.de>
Subject: [PATCH v9 01/23] x86/decompressor: Don't rely on upper 32 bits of GPRs being preserved
Date: Mon, 7 Aug 2023 18:26:58 +0200 [thread overview]
Message-ID: <20230807162720.545787-2-ardb@kernel.org> (raw)
In-Reply-To: <20230807162720.545787-1-ardb@kernel.org>
The 4-to-5 level mode switch trampoline disables long mode and paging in
order to be able to flick the LA57 bit. According to section 3.4.1.1 of
the x86 architecture manual [0], 64-bit GPRs might not retain the upper
32 bits of their contents across such a mode switch.
Given that RBP, RBX and RSI are live at this point, preserve them on the
stack, along with the return address that might be above 4G as well.
[0] Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1: Basic Architecture
"Because the upper 32 bits of 64-bit general-purpose registers are
undefined in 32-bit modes, the upper 32 bits of any general-purpose
register are not preserved when switching from 64-bit mode to a 32-bit
mode (to protected mode or compatibility mode). Software must not
depend on these bits to maintain a value after a 64-bit to 32-bit
mode switch."
Fixes: 194a9749c73d650c ("x86/boot/compressed/64: Handle 5-level paging boot if kernel is above 4G")
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/x86/boot/compressed/head_64.S | 30 +++++++++++++++-----
1 file changed, 23 insertions(+), 7 deletions(-)
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 03c4328a88cbd5d0..f732426d3b483139 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -459,11 +459,25 @@ SYM_CODE_START(startup_64)
/* Save the trampoline address in RCX */
movq %rax, %rcx
+ /* Set up 32-bit addressable stack */
+ leaq TRAMPOLINE_32BIT_STACK_END(%rcx), %rsp
+
/*
- * Load the address of trampoline_return() into RDI.
- * It will be used by the trampoline to return to the main code.
+ * Preserve live 64-bit registers on the stack: this is necessary
+ * because the architecture does not guarantee that GPRs will retain
+ * their full 64-bit values across a 32-bit mode switch.
+ */
+ pushq %rbp
+ pushq %rbx
+ pushq %rsi
+
+ /*
+ * Push the 64-bit address of trampoline_return() onto the new stack.
+ * It will be used by the trampoline to return to the main code. Due to
+ * the 32-bit mode switch, it cannot be kept it in a register either.
*/
leaq trampoline_return(%rip), %rdi
+ pushq %rdi
/* Switch to compatibility mode (CS.L = 0 CS.D = 1) via far return */
pushq $__KERNEL32_CS
@@ -471,6 +485,11 @@ SYM_CODE_START(startup_64)
pushq %rax
lretq
trampoline_return:
+ /* Restore live 64-bit registers */
+ popq %rsi
+ popq %rbx
+ popq %rbp
+
/* Restore the stack, the 32-bit trampoline uses its own stack */
leaq rva(boot_stack_end)(%rbx), %rsp
@@ -582,7 +601,7 @@ SYM_FUNC_END(.Lrelocated)
/*
* This is the 32-bit trampoline that will be copied over to low memory.
*
- * RDI contains the return address (might be above 4G).
+ * Return address is at the top of the stack (might be above 4G).
* ECX contains the base address of the trampoline memory.
* Non zero RDX means trampoline needs to enable 5-level paging.
*/
@@ -592,9 +611,6 @@ SYM_CODE_START(trampoline_32bit_src)
movl %eax, %ds
movl %eax, %ss
- /* Set up new stack */
- leal TRAMPOLINE_32BIT_STACK_END(%ecx), %esp
-
/* Disable paging */
movl %cr0, %eax
btrl $X86_CR0_PG_BIT, %eax
@@ -671,7 +687,7 @@ SYM_CODE_END(trampoline_32bit_src)
.code64
SYM_FUNC_START_LOCAL_NOALIGN(.Lpaging_enabled)
/* Return from the trampoline */
- jmp *%rdi
+ retq
SYM_FUNC_END(.Lpaging_enabled)
/*
--
2.39.2
next prev parent reply other threads:[~2023-08-07 16:27 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-07 16:26 [PATCH v9 00/23] efi/x86: Avoid bare metal decompressor during EFI boot Ard Biesheuvel
2023-08-07 16:26 ` Ard Biesheuvel [this message]
2023-08-08 8:44 ` [tip: x86/boot] x86/decompressor: Don't rely on upper 32 bits of GPRs being preserved tip-bot2 for Ard Biesheuvel
2023-08-07 16:26 ` [PATCH v9 02/23] x86/head_64: Store boot_params pointer in callee save register Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 03/23] x86/efistub: Branch straight to kernel entry point from C code Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 04/23] x86/efistub: Simplify and clean up handover entry code Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 05/23] x86/decompressor: Avoid magic offsets for EFI handover entrypoint Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 06/23] x86/efistub: Clear BSS in EFI handover protocol entrypoint Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 07/23] x86/decompressor: Store boot_params pointer in callee save register Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 08/23] x86/decompressor: Assign paging related global variables earlier Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 09/23] x86/decompressor: Call trampoline as a normal function Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 10/23] x86/decompressor: Use standard calling convention for trampoline Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 11/23] x86/decompressor: Avoid the need for a stack in the 32-bit trampoline Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 12/23] x86/decompressor: Call trampoline directly from C code Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 13/23] x86/decompressor: Only call the trampoline when changing paging levels Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 14/23] x86/decompressor: Pass pgtable address to trampoline directly Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 15/23] x86/decompressor: Merge trampoline cleanup with switching code Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 16/23] x86/efistub: Perform 4/5 level paging switch from the stub Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 17/23] x86/efistub: Prefer EFI memory attributes protocol over DXE services Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 18/23] decompress: Use 8 byte alignment Ard Biesheuvel
2023-08-08 8:44 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 19/23] x86/decompressor: Move global symbol references to C code Ard Biesheuvel
2023-08-08 8:43 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 20/23] x86/decompressor: Factor out kernel decompression and relocation Ard Biesheuvel
2023-08-08 8:43 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 21/23] efi/libstub: Add limit argument to efi_random_alloc() Ard Biesheuvel
2023-08-08 8:43 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 22/23] x86/efistub: Perform SNP feature test while running in the firmware Ard Biesheuvel
2023-08-08 8:43 ` [tip: x86/boot] " tip-bot2 for Ard Biesheuvel
2023-08-07 16:27 ` [PATCH v9 23/23] x86/efistub: Avoid legacy decompressor when doing EFI boot Ard Biesheuvel
2023-08-08 8:43 ` [tip: x86/boot] " tip-bot2 for 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=20230807162720.545787-2-ardb@kernel.org \
--to=ardb@kernel.org \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=linux-efi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=tglx@linutronix.de \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.