[PATCH v4 09/23] x86/boot/slaunch-early: implement early initialization
Sergii Dmytruk <[email protected]> Sun, 2 Aug 2026 16:09:25 +0300
| Newsgroups | org.xenproject.lists.xen-devel |
|---|---|
| Message-ID | <d454fcaf31f09b36610b8d5e60ff04c1ca60c4fc.1785668458.git.sergii.dmytruk@3mdeb.com> |
Make head.S invoke a C function to retrieve MBI and SLRT addresses in a platform-specific way. This is also the place to perform sanity checks of DRTM. Signed-off-by: Krystian Hebel <[email protected]> Signed-off-by: Sergii Dmytruk <[email protected]> --- Notes: v4: use CONFIG_SLAUNCH v4: expose slaunch_early_init_results via asm-offsets.c to not hard-code its size v4: use `mov` instead of `lea` in head.S v4: put SPDX license comment on its own line v4: check that SLRT address is below 4 GiB v4: perform a TXT reset with specific error codes if data doesn't meet expectations v4: replace SLAUNCH_ERROR_GENERIC with specific error codes v4: removed declaration and a reference to otherwise unused slaunch_get_slrt() v4: mark `slaunch_active` variable with `__ro_after_init` v4: updates to the handling of TXT heap sections due to different API xen/arch/x86/Makefile | 1 + xen/arch/x86/boot/Makefile | 12 +++++++- xen/arch/x86/boot/head.S | 35 +++++++++++++++++++-- xen/arch/x86/boot/slaunch-early.c | 46 ++++++++++++++++++++++++++++ xen/arch/x86/include/asm/intel-txt.h | 20 ++++++++++++ xen/arch/x86/include/asm/slaunch.h | 30 ++++++++++++++++++ xen/arch/x86/slaunch.c | 32 +++++++++++++++++++ xen/arch/x86/x86_64/asm-offsets.c | 10 ++++++ 8 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 xen/arch/x86/boot/slaunch-early.c create mode 100644 xen/arch/x86/include/asm/slaunch.h create mode 100644 xen/arch/x86/slaunch.c diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 293f3bee35..a03f5a91ef 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_COMPAT) += x86_64/physdev.o obj-$(CONFIG_X86_PSR) += psr.o obj-y += setup.o obj-y += shutdown.o +obj-$(CONFIG_SLAUNCH) += slaunch.o obj-y += smp.o obj-y += smpboot.o obj-y += spec_ctrl.o diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile index feae17c14a..02f690d34a 100644 --- a/xen/arch/x86/boot/Makefile +++ b/xen/arch/x86/boot/Makefile @@ -5,10 +5,18 @@ obj-bin-y += $(obj64) obj32 := cmdline.32.o obj32 += reloc.32.o obj32 += reloc-trampoline.32.o +ifeq ($(CONFIG_SLAUNCH),y) +obj32 += slaunch-early.32.o +endif obj32 += tpm-early.32.o obj64 := reloc-trampoline.o +exports := cmdline_parse_early,reloc,reloc_trampoline32 +ifeq ($(CONFIG_SLAUNCH),y) +exports := $(exports),slaunch_early_init +endif + nocov-y += $(obj32) $(obj64) noubsan-y += $(obj32) $(obj64) targets += $(obj32) @@ -29,6 +37,8 @@ $(obj32): XEN_CFLAGS := $(CFLAGS_x86_32) -fpic $(obj)/%.32.o: $(src)/%.c FORCE $(call if_changed_rule,cc_o_c) +$(obj)/slaunch-early.32.o: XEN_CFLAGS += -D__EARLY_SLAUNCH__ + $(obj)/tpm-early.32.o: XEN_CFLAGS += -D__EARLY_TPM__ $(obj)/tpm-early.32.o: $(src)/../tpm.c FORCE $(call if_changed_rule,cc_o_c) @@ -86,7 +96,7 @@ cmd_combine = \ --bin1 $(obj)/built-in-32.base.bin \ --bin2 $(obj)/built-in-32.offset.bin \ --map $(obj)/built-in-32.base.map \ - --exports cmdline_parse_early,reloc,reloc_trampoline32 \ + --exports $(exports) \ --output $@ targets += built-in-32.S diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index cbf91b23c9..700d1d850e 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -508,8 +508,39 @@ __start: * bootloader with ESP, ESI and EDX being clobbered above. */ - /* Hang as this boot path is yet to be implemented. */ - jmp .Lslaunch_proto + /* Save information that TrenchBoot slaunch was used. */ + movb $1, sym_esi(slaunch_active) + + /* + * Prepare space for output parameter of slaunch_early_init(), which is + * the following structure: + * struct slaunch_early_init_results + * { + * uint32_t mbi_pa; + * uint32_t slrt_pa; + * } __packed; + */ + sub $SL_EIR_size, %esp + + push %esp /* pointer to output structure */ + mov $sym_offs(__2M_rwdata_end), %ecx /* end of target image */ + mov $sym_offs(_start), %edx /* target base address */ + mov %esi, %eax /* load base address */ + /* + * slaunch_early_init(load/eax, tgt/edx, tgt_end/ecx, ret/stk) using + * fastcall calling convention. + */ + call slaunch_early_init + add $4, %esp /* pop the fourth parameter */ + + /* Move outputs of slaunch_early_init() from the stack. */ + pop %ebx /* store physical MBI address in EBX where + MB2 code expects it */ + pop sym_esi(slaunch_slrt) /* save physical address of SLRT for C + code */ + + /* Move magic number expected by Multiboot 2 to EAX and fall through. */ + movl $MULTIBOOT2_BOOTLOADER_MAGIC, %eax #endif .Lmultiboot2_proto: diff --git a/xen/arch/x86/boot/slaunch-early.c b/xen/arch/x86/boot/slaunch-early.c new file mode 100644 index 0000000000..35992cb9b3 --- /dev/null +++ b/xen/arch/x86/boot/slaunch-early.c @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Early Slaunch initialization code responsible for determining location of + * MBI and SLRT and enforcing basic conditions. + * + * Copyright (c) 2022-2026 3mdeb Sp. z o.o. All rights reserved. + */ + +#include <xen/kernel.h> +#include <xen/slr-table.h> +#include <xen/types.h> + +#include <asm/intel-txt.h> +#include <asm/slaunch.h> + +void asmlinkage slaunch_early_init(uint32_t load_base_addr, + uint32_t tgt_base_addr, + uint32_t tgt_end_addr, + struct slaunch_early_init_results *result) +{ + void *txt_heap; + const struct txt_os_mle_data *os_mle; + const struct slr_table *slrt; + const struct slr_entry_hdr *entry; + const struct slr_entry_intel_info *intel_info; + + txt_heap = txt_init(); + os_mle = txt_start(txt_heap, TXT_OS2MLE); + + if ( os_mle->slrt & ~0xffffffffULL ) + txt_reset(SLAUNCH_ERROR_BAD_SLRT_ADDRESS); + + result->slrt_pa = os_mle->slrt; + + slrt = (const struct slr_table *)result->slrt_pa; + + entry = slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_INFO); + if ( entry == NULL ) + txt_reset(SLAUNCH_ERROR_NO_VENDOR_INFO); + + intel_info = container_of(entry, const struct slr_entry_intel_info, hdr); + if ( intel_info->hdr.size != sizeof(*intel_info) ) + txt_reset(SLAUNCH_ERROR_BAD_VENDOR_INFO); + + result->mbi_pa = intel_info->boot_params_base; +} diff --git a/xen/arch/x86/include/asm/intel-txt.h b/xen/arch/x86/include/asm/intel-txt.h index 15d474f002..dc6c689f1a 100644 --- a/xen/arch/x86/include/asm/intel-txt.h +++ b/xen/arch/x86/include/asm/intel-txt.h @@ -62,6 +62,9 @@ #define SLAUNCH_ERROR_BUFFER_BEYOND_PMR 0xc0008006U #define SLAUNCH_ERROR_HEAP_BAD_OS2MLE 0xc0008007U #define SLAUNCH_ERROR_HEAP_BAD_OS2SINIT 0xc0008008U +#define SLAUNCH_ERROR_NO_VENDOR_INFO 0xc0008009U +#define SLAUNCH_ERROR_BAD_VENDOR_INFO 0xc000800AU +#define SLAUNCH_ERROR_BAD_SLRT_ADDRESS 0xc000800BU #ifndef __ASSEMBLER__ @@ -245,6 +248,23 @@ static inline void *txt_start(void *heap, int table_index) return heap + sizeof(uint64_t); } +static inline void *txt_init(void) +{ + void *txt_heap; + + /* Clear the TXT error register for a clean start of the day. */ + txt_write(TXTCR_ERRORCODE, 0); + + txt_heap = _p(txt_read(TXTCR_HEAP_BASE)); + + if ( txt_size(txt_heap, TXT_OS2MLE) < sizeof(struct txt_os_mle_data) ) + txt_reset(SLAUNCH_ERROR_HEAP_BAD_OS2MLE); + if ( txt_size(txt_heap, TXT_OS2SINIT) < sizeof(struct txt_os_sinit_data) ) + txt_reset(SLAUNCH_ERROR_HEAP_BAD_OS2SINIT); + + return txt_heap; +} + #endif /* !__ASSEMBLER__ */ #endif /* X86_INTEL_TXT_H */ diff --git a/xen/arch/x86/include/asm/slaunch.h b/xen/arch/x86/include/asm/slaunch.h new file mode 100644 index 0000000000..24ba164c0a --- /dev/null +++ b/xen/arch/x86/include/asm/slaunch.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Declarations related to Slaunch (an implementation of a DRTM launch). This + * header is consumed by both normal and early boot code and has to take the + * two environments into account. + * + * More details about Slaunch are available at: + * https://trenchboot.org/specifications/Secure_Launch/ + * + * Copyright (c) 2022-2026 3mdeb Sp. z o.o. All rights reserved. + */ + +#ifndef X86_SLAUNCH_H +#define X86_SLAUNCH_H + +#include <xen/types.h> + +struct slaunch_early_init_results +{ + uint32_t mbi_pa; + uint32_t slrt_pa; +} __packed; + +/* Indicates an active Secure Launch boot. */ +extern bool slaunch_active; + +/* Holds physical address of SLRT. */ +extern uint32_t slaunch_slrt; + +#endif /* X86_SLAUNCH_H */ diff --git a/xen/arch/x86/slaunch.c b/xen/arch/x86/slaunch.c new file mode 100644 index 0000000000..acf751804f --- /dev/null +++ b/xen/arch/x86/slaunch.c @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Main Slaunch code used during boot process. + * + * Copyright (c) 2022-2026 3mdeb Sp. z o.o. All rights reserved. + */ + +#include <xen/compiler.h> +#include <xen/init.h> +#include <xen/inttypes.h> +#include <xen/macros.h> +#include <xen/sections.h> + +#include <asm/slaunch.h> + +/* + * These variables are assigned to by the code near Xen's entry point. + * + * slaunch_active is not __initdata to allow checking for an active Secure + * Launch boot at any point. + */ +bool __ro_after_init slaunch_active; +uint32_t __initdata slaunch_slrt; /* physical address */ + +/* + * Using slaunch_active in head.S assumes it's a single byte in size, so enforce + * this assumption. + */ +static void __maybe_unused compile_time_checks(void) +{ + BUILD_BUG_ON(sizeof(slaunch_active) != 1); +} diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c index baf266ab80..f0aaf0f4ba 100644 --- a/xen/arch/x86/x86_64/asm-offsets.c +++ b/xen/arch/x86/x86_64/asm-offsets.c @@ -16,6 +16,9 @@ #include <xen/multiboot.h> #include <xen/multiboot2.h> #include <asm/guest-msr.h> +#ifdef CONFIG_SLAUNCH +#include <asm/slaunch.h> +#endif #ifdef CONFIG_VIDEO # include "../boot/video.h" @@ -236,4 +239,11 @@ void __dummy__(void) DEFINE(BVI_size, sizeof(struct boot_video_info)); BLANK(); #endif /* CONFIG_VIDEO */ + +#ifdef CONFIG_SLAUNCH + OFFSET(SL_EIR_mbi_pa, struct slaunch_early_init_results, mbi_pa); + OFFSET(SL_EIR_slrt_pa, struct slaunch_early_init_results, slrt_pa); + DEFINE(SL_EIR_size, sizeof(struct slaunch_early_init_results)); + BLANK(); +#endif } -- 2.55.0