Move memory acceptance x86 arch code into EFI stub
Subsystems (3)
Ard Biesheuvel
maintainerv2 cover Move memory acceptance x86 arch code into EFI stub
This is a follow-up to [0].
Move arch_accept_memory(), which is only called by the EFI stub and never by the decompressor on a non-EFI boot, into the EFI stub, and avoid relying directly on decompressor APIs such as error().
Instead, call tdx_panic() on a failure to accept memory in a TDX guest.
This makes the decompressor's implementation of panic() obsolete, and allows it to be removed. This is a prerequisite for dropping the implementation of snprintf() from the EFI stub entirely, which is what the series containing [0] implements.
Changes since v1 [1]:
- Add missing stub for early_is_sevsnp_guest() when SEV support is compiled out but TDX support is built in.
- Use native_cpuid() in EFI stub code so it does not get paravirtualized
- Set __NO_FORTIFY when including tdx-shared.c so the decompressor/stub version does not get instrumented. Needed for the memcpy() in tdx_panic().
[0] http://lore.kernel.org/r/[email protected]
[1] https://lore.kernel.org/all/[email protected]/
Ard Biesheuvel (3):
x86/tdx: Share tdx_panic() with the EFI stub
x86/boot: Move unaccepted memory handling out of the decompressor x86/boot: Drop unused implementation of panic()
arch/x86/boot/compressed/error.c | 19 --------- arch/x86/boot/compressed/error.h | 1 - arch/x86/boot/compressed/mem.c | 42 -------------------- arch/x86/boot/compressed/sev.h | 2 - arch/x86/boot/compressed/tdx-shared.c | 2 + arch/x86/coco/tdx/tdx-shared.c | 31 +++++++++++++++ arch/x86/coco/tdx/tdx.c | 35 ---------------- arch/x86/include/asm/sev.h | 2 + arch/x86/include/asm/shared/tdx.h | 1 + drivers/firmware/efi/libstub/x86-stub.c | 39 ++++++++++++++++++ 10 files changed, 75 insertions(+), 99 deletions(-)
Signature · 1 line
2.53.0
Ard Biesheuvel
maintainerPATCH v2 1/3 x86/tdx: Share tdx_panic() with the EFI stub
Move the implementation of tdx_panic() into the source file that is shared with the decompressor and the EFI stub.
Use memcpy() and strnlen() instead of strtomem_pad(), as the latter does not exist in the early boot code. Avoid fortify instrumentation in the decompressor/EFI stub by #define'ing __NO_FORTIFY before including tdx-shared.c
Note that __tdx_hypercall() may call __tdx_hypercall_failed() if the hypercall returns with an error (while it should never return to begin with). __tdx_hypercall_failed() calls the decompressor's error() routine, which prints a message and then loops forever.
When called from the EFI stub, this error() call may attempt to use port I/O to the default serial port rather than the TDX hypercalls which the decompressor uses normally to print diagnostics to the console, but this is fine: given that this situation only occurs after a catastrophic error, and a subsequent spurious return from tdx_panic(), whether error() uses port I/O or not is rather moot at that point, as long as it never returns.
--- arch/x86/boot/compressed/tdx-shared.c | 2 ++ arch/x86/coco/tdx/tdx-shared.c | 31 +++++++++++++++++ arch/x86/coco/tdx/tdx.c | 35 -------------------- arch/x86/include/asm/shared/tdx.h | 1 + 4 files changed, 34 insertions(+), 35 deletions(-)
arch/x86/boot/compressed/tdx-shared.c +2 -0
@@ -1,2 +1,4 @@ +#define __NO_FORTIFY +#include "error.h" #include "../../coco/tdx/tdx-shared.c"
arch/x86/coco/tdx/tdx-shared.c +31 -0
@@ -89,3 +89,34 @@ noinstr u64 __tdx_hypercall(struct tdx_module_args *args)/* TDVMCALL leaf return code is in R10 */ return args->r10; } + +void __noreturn tdx_panic (const char *msg) +{ +struct tdx_module_args args = { + .r10 =TDX_HYPERCALL_STANDARD , + .r11 =TDVMCALL_REPORT_FATAL_ERROR , + .r12 =0 ,/* Error code: 0 is Panic */ + }; +/* Define register order according to the GHCI */ +struct {u64 r14, r15, rbx, rdi, rsi, r8, r9, rdx; } message = {}; + +/* VMM assumes '\0' in byte 65, if the message took all 64 bytes */ +memcpy (&message, msg,strnlen (msg,sizeof (message))); + + args.r8 = message.r8; + args.r9 = message.r9; + args.r14 = message.r14; + args.r15 = message.r15; + args.rdi = message.rdi; + args.rsi = message.rsi; + args.rbx = message.rbx; + args.rdx = message.rdx; + +/* +* This hypercall should never return and it is not safe +* to keep the guest running. Call it forever if it +* happens to return. +*/ +while (1 ) +__tdx_hypercall (&args); +}
arch/x86/coco/tdx/tdx.c +0 -35
@@ -198,41 +198,6 @@ u64 tdx_hcall_get_quote(u8 *buf, size_t size) }EXPORT_SYMBOL_GPL (tdx_hcall_get_quote); -static void __noreturn tdx_panic (const char *msg) -{ -struct tdx_module_args args = { - .r10 =TDX_HYPERCALL_STANDARD , - .r11 =TDVMCALL_REPORT_FATAL_ERROR , - .r12 =0 ,/* Error code: 0 is Panic */ - }; -union { -/* Define register order according to the GHCI */ -struct {u64 r14, r15, rbx, rdi, rsi, r8, r9, rdx; }; - - char bytes[64] __nonstring; - } message; - -/* VMM assumes '\0' in byte 65, if the message took all 64 bytes */ -strtomem_pad (message.bytes, msg,'\0' ); - - args.r8 = message.r8; - args.r9 = message.r9; - args.r14 = message.r14; - args.r15 = message.r15; - args.rdi = message.rdi; - args.rsi = message.rsi; - args.rbx = message.rbx; - args.rdx = message.rdx; - -/* -* This hypercall should never return and it is not safe -* to keep the guest running. Call it forever if it -* happens to return. -*/ -while (1 ) -__tdx_hypercall (&args); -} -/* * The kernel cannot handle #VEs when accessing normal kernel memory. Ensure * that no #VE will be delivered for accesses to TD-private memory.
arch/x86/include/asm/shared/tdx.h +1 -0
@@ -171,6 +171,7 @@ static inline u64 _tdx_hypercall(u64 fn, u64 r12, u64 r13, u64 r14, u64 r15)return __tdx_hypercall (&args); } +void __noreturn tdx_panic (const char *msg);/* Called from __tdx_hypercall() for unrecoverable failure */ void __noreturn __tdx_hypercall_failed (void );
Signature · 1 line
2.53.0
Re: [PATCH v2 1/3] x86/tdx: Share tdx_panic() with the EFI stub
Quoted 21 lines · Ard Biesheuvel
Move the implementation of
tdx_panic()into the source file that is shared with the decompressor and the EFI stub.Use
memcpy()andstrnlen()instead ofstrtomem_pad(), as the latter does not exist in the early boot code. Avoid fortify instrumentation in the decompressor/EFI stub by #define'ing__NO_FORTIFYbefore includingtdx-shared.cNote that
__tdx_hypercall()may call__tdx_hypercall_failed()if the hypercall returns with an error (while it should never return to begin with).__tdx_hypercall_failed()calls the decompressor'serror()routine, which prints a message and then loops forever.When called from the EFI stub, this
error()call may attempt to use port I/O to the default serial port rather than the TDX hypercalls which the decompressor uses normally to print diagnostics to the console, but this is fine: given that this situation only occurs after a catastrophic error, and a subsequent spurious return fromtdx_panic(), whethererror()uses port I/O or not is rather moot at that point, as long as it never returns.
Quoted 1 line
Signed-off-by Ard Biesheuvel <[email protected]>
Signature · 1 line
Kiryl Shutsemau / Kirill A. Shutemov
[tip: x86/boot] x86/tdx: Share tdx_panic() with the EFI stub
In reply to Ard BiesheuvelThe following commit has been merged into the x86/boot branch of tip:
The following commit has been merged into the x86/boot branch of tip:
Commit-ID: 0ffdb6c1ea44ddb40794b9c20a39b8fb30551875 Gitweb: https://git.kernel.org/tip/0ffdb6c1ea44ddb40794b9c20a39b8fb30551875 Author: Ard Biesheuvel <[email protected]> AuthorDate: Fri, 25 Sep 2026 09:51:39 +02:00 Committer: Borislav Petkov (AMD) <[email protected]> CommitterDate: Mon, 28 Sep 2026 15:07:42 -07:00
x86/tdx: Share tdx_panic() with the EFI stub
Move the implementation of tdx_panic() into the source file that is shared with the decompressor and the EFI stub.
Use memcpy() and strnlen() instead of strtomem_pad(), as the latter does not exist in the early boot code. Avoid fortify instrumentation in the decompressor/EFI stub by defining __NO_FORTIFY before including tdx-shared.c
Note that __tdx_hypercall() may call __tdx_hypercall_failed() if the hypercall returns with an error (while it should never return to begin with). __tdx_hypercall_failed() calls the decompressor's error() routine, which prints a message and then loops forever.
When called from the EFI stub, this error() call may attempt to use port I/O to the default serial port rather than the TDX hypercalls which the decompressor uses normally to print diagnostics to the console, but this is fine: given that this situation only occurs after a catastrophic error, and a subsequent spurious return from tdx_panic(), whether error() uses port I/O or not is rather moot at that point, as long as it never returns.
--- arch/x86/boot/compressed/tdx-shared.c | 2 +- arch/x86/coco/tdx/tdx-shared.c | 31 +++++++++++++++++++++++- arch/x86/coco/tdx/tdx.c | 35 +-------------------------- arch/x86/include/asm/shared/tdx.h | 1 +- 4 files changed, 34 insertions(+), 35 deletions(-)
arch/x86/boot/compressed/tdx-shared.c +2 -0
@@ -1,2 +1,4 @@ +#define __NO_FORTIFY +#include "error.h" #include "../../coco/tdx/tdx-shared.c"
arch/x86/coco/tdx/tdx-shared.c +31 -0
@@ -89,3 +89,34 @@ noinstr u64 __tdx_hypercall(struct tdx_module_args *args)/* TDVMCALL leaf return code is in R10 */ return args->r10; } + +void __noreturn tdx_panic (const char *msg) +{ +struct tdx_module_args args = { + .r10 =TDX_HYPERCALL_STANDARD , + .r11 =TDVMCALL_REPORT_FATAL_ERROR , + .r12 =0 ,/* Error code: 0 is Panic */ + }; +/* Define register order according to the GHCI */ +struct {u64 r14, r15, rbx, rdi, rsi, r8, r9, rdx; } message = {}; + +/* VMM assumes '\0' in byte 65, if the message took all 64 bytes */ +memcpy (&message, msg,strnlen (msg,sizeof (message))); + + args.r8 = message.r8; + args.r9 = message.r9; + args.r14 = message.r14; + args.r15 = message.r15; + args.rdi = message.rdi; + args.rsi = message.rsi; + args.rbx = message.rbx; + args.rdx = message.rdx; + +/* +* This hypercall should never return and it is not safe +* to keep the guest running. Call it forever if it +* happens to return. +*/ +while (1 ) +__tdx_hypercall (&args); +}
arch/x86/coco/tdx/tdx.c +0 -35
@@ -198,41 +198,6 @@ u64 tdx_hcall_get_quote(u8 *buf, size_t size) }EXPORT_SYMBOL_GPL (tdx_hcall_get_quote); -static void __noreturn tdx_panic (const char *msg) -{ -struct tdx_module_args args = { - .r10 =TDX_HYPERCALL_STANDARD , - .r11 =TDVMCALL_REPORT_FATAL_ERROR , - .r12 =0 ,/* Error code: 0 is Panic */ - }; -union { -/* Define register order according to the GHCI */ -struct {u64 r14, r15, rbx, rdi, rsi, r8, r9, rdx; }; - - char bytes[64] __nonstring; - } message; - -/* VMM assumes '\0' in byte 65, if the message took all 64 bytes */ -strtomem_pad (message.bytes, msg,'\0' ); - - args.r8 = message.r8; - args.r9 = message.r9; - args.r14 = message.r14; - args.r15 = message.r15; - args.rdi = message.rdi; - args.rsi = message.rsi; - args.rbx = message.rbx; - args.rdx = message.rdx; - -/* -* This hypercall should never return and it is not safe -* to keep the guest running. Call it forever if it -* happens to return. -*/ -while (1 ) -__tdx_hypercall (&args); -} -/* * The kernel cannot handle #VEs when accessing normal kernel memory. Ensure * that no #VE will be delivered for accesses to TD-private memory.
arch/x86/include/asm/shared/tdx.h +1 -0
@@ -171,6 +171,7 @@ static inline u64 _tdx_hypercall(u64 fn, u64 r12, u64 r13, u64 r14, u64 r15)return __tdx_hypercall (&args); } +void __noreturn tdx_panic (const char *msg);/* Called from __tdx_hypercall() for unrecoverable failure */ void __noreturn __tdx_hypercall_failed (void );
Ard Biesheuvel
maintainerPATCH v2 2/3 x86/boot: Move unaccepted memory handling out of the decompressor
In reply to Ard Biesheuvelarch_accept_memory() is an arch-specific hook that is required by the EFI stub when processing memory that the firmware reports to the OS as EFI_UNACCEPTED_MEMORY.
This hook is called after ExitBootServices() has been called, as before that point, the EFI memory map may get updated behind the back of the running EFI stub, making it difficult to get a stable view on it while iterating over the entries.
Currently, the x86 version of this hook is implemented in its decompressor rather than in the EFI stub itself, in a manner that is
problematic: when an error occurs, it calls the decompressor's error() routine, but without having gone through the decompressor initialization code. This means it will resort to direct port I/O rather than the hypercall based interface that TDX guests would use otherwise.
Conceptually, code that is only called from the EFI stub, and never by the decompressor when doing legacy boot, belongs in the EFI stub and not in the decompressor.
So move it into the x86-specific EFI stub code, replacing the error() on the TDX path with tdx_panic(), and dropping the error() when no CC support is detected - the kernel can decide what to do in this case after it has booted.
--- arch/x86/boot/compressed/mem.c | 42 -------------------- arch/x86/boot/compressed/sev.h | 2 - arch/x86/include/asm/sev.h | 2 + drivers/firmware/efi/libstub/x86-stub.c | 39 ++++++++++++++++++ 4 files changed, 41 insertions(+), 44 deletions(-)
arch/x86/boot/compressed/mem.c +0 -42
@@ -2,48 +2,6 @@#include "error.h" #include "misc.h" -#include "tdx.h" -#include "sev.h" -#include <asm/shared/tdx.h> - -/* -* accept_memory() and process_unaccepted_memory() called from EFI stub which -* runs before decompressor and its early_tdx_detect(). -* -* Enumerate TDX directly from the early users. -*/ -static bool early_is_tdx_guest (void ) -{ -static bool once; -static bool is_tdx; - -if (!IS_ENABLED (CONFIG_INTEL_TDX_GUEST )) -return false; - -if (!once) { -u32 eax, sig[3 ]; - -cpuid_count (TDX_CPUID_LEAF_ID ,0 , &eax, - &sig[0 ], &sig[2 ], &sig[1 ]); - is_tdx = !memcmp (TDX_IDENT , sig,sizeof (sig)); - once = true; - } - -return is_tdx; -} - -void arch_accept_memory (phys_addr_t start,phys_addr_t end) -{ -/* Platform-specific memory-acceptance call goes here */ -if (early_is_tdx_guest ()) { -if (!tdx_accept_memory (start, end)) -panic ("TDX: Failed to accept memory\n" ); - }else if (early_is_sevsnp_guest ()) { -snp_accept_memory (start, end); - }else { -error ("Cannot accept memory: unknown platform\n" ); - } -}bool init_unaccepted_memory (void ) {
arch/x86/boot/compressed/sev.h +0 -2
@@ -14,7 +14,6 @@void snp_accept_memory (phys_addr_t start,phys_addr_t end);u64 sev_get_status (void ); -bool early_is_sevsnp_guest (void );static inline u64 sev_es_rd_ghcb_msr (void ) {
@@ -37,7 +36,6 @@ static inline void sev_es_wr_ghcb_msr(u64 val)static inline void snp_accept_memory (phys_addr_t start,phys_addr_t end) { }static inline u64 sev_get_status (void ) {return 0 ; } -static inline bool early_is_sevsnp_guest (void ) {return false; }#endif
arch/x86/include/asm/sev.h +2 -0
@@ -517,6 +517,7 @@ void snp_accept_memory(phys_addr_t start, phys_addr_t end);u64 snp_get_unsupported_features (u64 status);u64 sev_get_status (void );void sev_show_status (void ); +bool early_is_sevsnp_guest (void );int prepare_pte_enc (struct pte_enc_desc *d);void set_pte_enc_mask (pte_t *kpte,unsigned long pfn,pgprot_t new_prot);void snp_kexec_finish (void );
@@ -626,6 +627,7 @@ static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { }static inline u64 snp_get_unsupported_features (u64 status) {return 0 ; }static inline u64 sev_get_status (void ) {return 0 ; }static inline void sev_show_status (void ) { } +static inline bool early_is_sevsnp_guest (void ) {return false; }static inline int prepare_pte_enc (struct pte_enc_desc *d) {return 0 ; }static inline void set_pte_enc_mask (pte_t *kpte,unsigned long pfn,pgprot_t new_prot) { }static inline void snp_kexec_finish (void ) { }
drivers/firmware/efi/libstub/x86-stub.c +39 -0
@@ -10,6 +10,7 @@#include <linux/pci.h> #include <linux/stddef.h> +#include <asm/cpuid/api.h> #include <asm/efi.h> #include <asm/e820/types.h> #include <asm/setup.h>
@@ -17,6 +18,7 @@#include <asm/boot.h> #include <asm/kaslr.h> #include <asm/sev.h> +#include <asm/shared/tdx.h> #include "efistub.h" #include "x86-stub.h"
@@ -1068,3 +1070,40 @@ void efi64_stub_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg, struct boot_params *boot_params);#endif #endif + +#ifdef CONFIG_UNACCEPTED_MEMORY +/* +* process_unaccepted_memory() is called after ExitBootServices(), and so these +* memory acceptance routines cannot rely on EFI protocols for detecting the +* presence of TDX or SEV-SNP, or emit any kind of output if any error +* conditions are detected. +*/ +static bool early_is_tdx_guest (void ) +{ +static bool once; +static bool is_tdx; + +if (!IS_ENABLED (CONFIG_INTEL_TDX_GUEST )) +return false; + +if (!once) { +u32 eax =TDX_CPUID_LEAF_ID , sig[3 ] = {}; + +native_cpuid (&eax, &sig[0 ], &sig[2 ], &sig[1 ]); + is_tdx = !memcmp (TDX_IDENT , sig,sizeof (sig)); + once = true; + } + +return is_tdx; +} + +void arch_accept_memory (phys_addr_t start,phys_addr_t end) +{ +if (early_is_tdx_guest ()) { +if (!tdx_accept_memory (start, end)) +tdx_panic ("Failed to accept memory" ); + }else if (early_is_sevsnp_guest ()) { +snp_accept_memory (start, end); + } +} +#endif
Signature · 1 line
2.53.0
Re: [PATCH v2 2/3] x86/boot: Move unaccepted memory handling out of the decompressor
Quoted 20 lines · Ard Biesheuvel
arch_accept_memory()is an arch-specific hook that is required by the EFI stub when processing memory that the firmware reports to the OS asEFI_UNACCEPTED_MEMORY.This hook is called after
ExitBootServices()has been called, as before that point, the EFI memory map may get updated behind the back of the running EFI stub, making it difficult to get a stable view on it while iterating over the entries.Currently, the x86 version of this hook is implemented in its decompressor rather than in the EFI stub itself, in a manner that is
problematic: when an error occurs, it calls the decompressor'serror()routine, but without having gone through the decompressor initialization code. This means it will resort to direct port I/O rather than the hypercall based interface that TDX guests would use otherwise.Conceptually, code that is only called from the EFI stub, and never by the decompressor when doing legacy boot, belongs in the EFI stub and not in the decompressor.
Quoted 6 lines
So move it into the x86-specific EFI stub code, replacing the
error()on the TDX path withtdx_panic(), and dropping theerror()when no CC support is detected - the kernel can decide what to do in this case after it has booted.Signed-off-by Ard Biesheuvel <[email protected]>
Signature · 1 line
Kiryl Shutsemau / Kirill A. Shutemov
[tip: x86/boot] x86/boot: Move unaccepted memory handling out of the decompressor
In reply to Ard BiesheuvelThe following commit has been merged into the x86/boot branch of tip:
The following commit has been merged into the x86/boot branch of tip:
Commit-ID: a9bc562daaf2596e6eab5f1a5e3a5880c4b2a1ee Gitweb: https://git.kernel.org/tip/a9bc562daaf2596e6eab5f1a5e3a5880c4b2a1ee Author: Ard Biesheuvel <[email protected]> AuthorDate: Fri, 25 Sep 2026 09:51:40 +02:00 Committer: Borislav Petkov (AMD) <[email protected]> CommitterDate: Mon, 28 Sep 2026 17:41:46 -07:00
x86/boot: Move unaccepted memory handling out of the decompressor
arch_accept_memory() is an arch-specific hook that is required by the EFI stub when processing memory that the firmware reports to the OS as EFI_UNACCEPTED_MEMORY.
This hook is called after ExitBootServices() has been called, as before that point, the EFI memory map may get updated behind the back of the running EFI stub, making it difficult to get a stable view on it while iterating over the entries.
Currently, the x86 version of this hook is implemented in its decompressor rather than in the EFI stub itself, in a manner that is
problematic: when an error occurs, it calls the decompressor's error() routine, but without having gone through the decompressor initialization code. This means it will resort to direct port I/O rather than the hypercall based interface that TDX guests would use otherwise.
Conceptually, code that is only called from the EFI stub, and never by the decompressor when doing legacy boot, belongs in the EFI stub and not in the decompressor.
So move it into the x86-specific EFI stub code, replacing the error() on the TDX path with tdx_panic(), and dropping the error() when no CC support is detected - the kernel can decide what to do in this case after it has booted.
--- arch/x86/boot/compressed/mem.c | 42 +------------------------ arch/x86/boot/compressed/sev.h | 2 +- arch/x86/include/asm/sev.h | 2 +- drivers/firmware/efi/libstub/x86-stub.c | 39 ++++++++++++++++++++++- 4 files changed, 41 insertions(+), 44 deletions(-)
arch/x86/boot/compressed/mem.c +0 -42
@@ -2,48 +2,6 @@#include "error.h" #include "misc.h" -#include "tdx.h" -#include "sev.h" -#include <asm/shared/tdx.h> - -/* -* accept_memory() and process_unaccepted_memory() called from EFI stub which -* runs before decompressor and its early_tdx_detect(). -* -* Enumerate TDX directly from the early users. -*/ -static bool early_is_tdx_guest (void ) -{ -static bool once; -static bool is_tdx; - -if (!IS_ENABLED (CONFIG_INTEL_TDX_GUEST )) -return false; - -if (!once) { -u32 eax, sig[3 ]; - -cpuid_count (TDX_CPUID_LEAF_ID ,0 , &eax, - &sig[0 ], &sig[2 ], &sig[1 ]); - is_tdx = !memcmp (TDX_IDENT , sig,sizeof (sig)); - once = true; - } - -return is_tdx; -} - -void arch_accept_memory (phys_addr_t start,phys_addr_t end) -{ -/* Platform-specific memory-acceptance call goes here */ -if (early_is_tdx_guest ()) { -if (!tdx_accept_memory (start, end)) -panic ("TDX: Failed to accept memory\n" ); - }else if (early_is_sevsnp_guest ()) { -snp_accept_memory (start, end); - }else { -error ("Cannot accept memory: unknown platform\n" ); - } -}bool init_unaccepted_memory (void ) {
arch/x86/boot/compressed/sev.h +0 -2
@@ -14,7 +14,6 @@void snp_accept_memory (phys_addr_t start,phys_addr_t end);u64 sev_get_status (void ); -bool early_is_sevsnp_guest (void );static inline u64 sev_es_rd_ghcb_msr (void ) {
@@ -37,7 +36,6 @@ static inline void sev_es_wr_ghcb_msr(u64 val)static inline void snp_accept_memory (phys_addr_t start,phys_addr_t end) { }static inline u64 sev_get_status (void ) {return 0 ; } -static inline bool early_is_sevsnp_guest (void ) {return false; }#endif
arch/x86/include/asm/sev.h +2 -0
@@ -517,6 +517,7 @@ void snp_accept_memory(phys_addr_t start, phys_addr_t end);u64 snp_get_unsupported_features (u64 status);u64 sev_get_status (void );void sev_show_status (void ); +bool early_is_sevsnp_guest (void );int prepare_pte_enc (struct pte_enc_desc *d);void set_pte_enc_mask (pte_t *kpte,unsigned long pfn,pgprot_t new_prot);void snp_kexec_finish (void );
@@ -626,6 +627,7 @@ static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { }static inline u64 snp_get_unsupported_features (u64 status) {return 0 ; }static inline u64 sev_get_status (void ) {return 0 ; }static inline void sev_show_status (void ) { } +static inline bool early_is_sevsnp_guest (void ) {return false; }static inline int prepare_pte_enc (struct pte_enc_desc *d) {return 0 ; }static inline void set_pte_enc_mask (pte_t *kpte,unsigned long pfn,pgprot_t new_prot) { }static inline void snp_kexec_finish (void ) { }
drivers/firmware/efi/libstub/x86-stub.c +39 -0
@@ -10,6 +10,7 @@#include <linux/pci.h> #include <linux/stddef.h> +#include <asm/cpuid/api.h> #include <asm/efi.h> #include <asm/e820/types.h> #include <asm/setup.h>
@@ -17,6 +18,7 @@#include <asm/boot.h> #include <asm/kaslr.h> #include <asm/sev.h> +#include <asm/shared/tdx.h> #include "efistub.h" #include "x86-stub.h"
@@ -1068,3 +1070,40 @@ void efi64_stub_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg, struct boot_params *boot_params);#endif #endif + +#ifdef CONFIG_UNACCEPTED_MEMORY +/* +* process_unaccepted_memory() is called after ExitBootServices(), and so these +* memory acceptance routines cannot rely on EFI protocols for detecting the +* presence of TDX or SEV-SNP, or emit any kind of output if any error +* conditions are detected. +*/ +static bool early_is_tdx_guest (void ) +{ +static bool once; +static bool is_tdx; + +if (!IS_ENABLED (CONFIG_INTEL_TDX_GUEST )) +return false; + +if (!once) { +u32 eax =TDX_CPUID_LEAF_ID , sig[3 ] = {}; + +native_cpuid (&eax, &sig[0 ], &sig[2 ], &sig[1 ]); + is_tdx = !memcmp (TDX_IDENT , sig,sizeof (sig)); + once = true; + } + +return is_tdx; +} + +void arch_accept_memory (phys_addr_t start,phys_addr_t end) +{ +if (early_is_tdx_guest ()) { +if (!tdx_accept_memory (start, end)) +tdx_panic ("Failed to accept memory" ); + }else if (early_is_sevsnp_guest ()) { +snp_accept_memory (start, end); + } +} +#endif
Ard Biesheuvel
maintainerPATCH v2 3/3 x86/boot: Drop unused implementation of panic()
In reply to Ard BiesheuvelThe decompressor has its own implementation of panic(), which is based on the vsnprintf() routine provided by the EFI stub.
The decompressor's panic() has no remaining users, and is implemented in terms of the EFI stub's snprintf() implementation, which is going away (and relying on the EFI stub from code that does not execute in the context of the EFI boot services is a bad idea in general).
So drop it.
--- arch/x86/boot/compressed/error.c | 19 ------------------- arch/x86/boot/compressed/error.h | 1 - 2 files changed, 20 deletions(-)
arch/x86/boot/compressed/error.c +0 -19
@@ -22,22 +22,3 @@ void error(char *m)while (1 ) asm("hlt" ); } - -/* EFI libstub provides vsnprintf() */ -#ifdef CONFIG_EFI_STUB -void panic (const char *fmt, ...) -{ -static char buf[1024 ]; -va_list args; -int len; - -va_start (args, fmt); - len =vsnprintf (buf,sizeof (buf), fmt, args); -va_end (args); - -if (len && buf[len -1 ] =='\n' ) - buf[len -1 ] ='\0' ; - -error (buf); -} -#endif
arch/x86/boot/compressed/error.h +0 -1
@@ -6,6 +6,5 @@void warn (const char *m);void error (char *m)__noreturn ; -void panic (const char *fmt, ...)__noreturn __cold ;#endif /* BOOT_COMPRESSED_ERROR_H */
Signature · 1 line
2.53.0
[tip: x86/boot] x86/boot: Drop unused implementation of panic()
The following commit has been merged into the x86/boot branch of tip:
The following commit has been merged into the x86/boot branch of tip:
Commit-ID: dc2a1671d983d26b8ea5a4c5de9c5a028707f40b Gitweb: https://git.kernel.org/tip/dc2a1671d983d26b8ea5a4c5de9c5a028707f40b Author: Ard Biesheuvel <[email protected]> AuthorDate: Fri, 25 Sep 2026 09:51:41 +02:00 Committer: Borislav Petkov (AMD) <[email protected]> CommitterDate: Mon, 28 Sep 2026 18:07:34 -07:00
x86/boot: Drop unused implementation of panic()
The decompressor has its own implementation of panic(), which is based on the vsnprintf() routine provided by the EFI stub.
The decompressor's panic() has no remaining users, and is implemented in terms of the EFI stub's snprintf() implementation, which is going away (and relying on the EFI stub from code that does not execute in the context of the EFI boot services is a bad idea in general).
So drop it.
--- arch/x86/boot/compressed/error.c | 19 ------------------- arch/x86/boot/compressed/error.h | 1 - 2 files changed, 20 deletions(-)
arch/x86/boot/compressed/error.c +0 -19
@@ -22,22 +22,3 @@ void error(char *m)while (1 ) asm("hlt" ); } - -/* EFI libstub provides vsnprintf() */ -#ifdef CONFIG_EFI_STUB -void panic (const char *fmt, ...) -{ -static char buf[1024 ]; -va_list args; -int len; - -va_start (args, fmt); - len =vsnprintf (buf,sizeof (buf), fmt, args); -va_end (args); - -if (len && buf[len -1 ] =='\n' ) - buf[len -1 ] ='\0' ; - -error (buf); -} -#endif
arch/x86/boot/compressed/error.h +0 -1
@@ -6,6 +6,5 @@void warn (const char *m);void error (char *m)__noreturn ; -void panic (const char *fmt, ...)__noreturn __cold ;#endif /* BOOT_COMPRESSED_ERROR_H */
Borislav Petkov
maintainerQuoted 5 lines · Ard Biesheuvel
This is a follow-up to [0].
Move
arch_accept_memory(), which is only called by the EFI stub and never by the decompressor on a non-EFI boot, into the EFI stub, and avoid relying directly on decompressor APIs such aserror().
Ok, pushed out.
I've also pushed a tag for you to use:
https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/tag/?h=tip_x86_boot_immutable_for_Ard
HTH.
Signature · 4 lines
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette