Skip to content

Commit a4e1e67

Browse files
SergiiDmytrukkrystian-hebel
authored andcommitted
x86/boot: find MBI and SLRT on AMD
secure-kernel-loader on AMD with SKINIT passes MBI as a parameter for Multiboot kernel. Another thing of interest is the location of SLRT which is bootloader's data after SKL. Signed-off-by: Sergii Dmytruk <[email protected]>
1 parent a2f8392 commit a4e1e67

File tree

2 files changed

+78
-5
lines changed

2 files changed

+78
-5
lines changed

xen/arch/x86/boot/head.S

+29-4
Original file line numberDiff line numberDiff line change
@@ -351,10 +351,12 @@ cs32_switch:
351351
jmp *%edi
352352

353353
/*
354-
* Entry point for TrenchBoot Secure Launch on Intel TXT platforms.
354+
* Entry point for TrenchBoot Secure Launch, common for Intel TXT and
355+
* AMD Secure Startup, but state is slightly different.
355356
*
357+
* On Intel:
356358
* CPU is in 32b protected mode with paging disabled. On entry:
357-
* - %ebx = %eip = MLE entry point,
359+
* - %ebx = %eip = this entry point,
358360
* - stack pointer is undefined,
359361
* - CS is flat 4GB code segment,
360362
* - DS, ES, SS, FS and GS are undefined.
@@ -368,13 +370,34 @@ cs32_switch:
368370
* - trying to enter real mode results in reset
369371
* - APs must be brought up by MONITOR or GETSEC[WAKEUP], depending on
370372
* which is supported by a given SINIT ACM
373+
*
374+
* On AMD (as implemented by TrenchBoot's SKL):
375+
* CPU is in 32b protected mode with paging disabled. On entry:
376+
* - %ebx = %eip = this entry point,
377+
* - %ebp holds base address of SKL
378+
* - stack pointer is treated as undefined for parity with TXT,
379+
* - CS is flat 4GB code segment,
380+
* - DS, ES, SS are flat 4GB data segments, but treated as undefined for
381+
* parity with TXT.
382+
*
383+
* Additional restrictions:
384+
* - interrupts (including NMIs and SMIs) are disabled and must be
385+
* enabled later
386+
* - APs must be brought up by SIPI without an INIT
371387
*/
372388
slaunch_stub_entry:
373389
/* Calculate the load base address. */
374390
mov %ebx, %esi
375391
sub $sym_offs(slaunch_stub_entry), %esi
376392

377-
/* Mark Secure Launch boot protocol and jump to common entry. */
393+
/* On AMD, %ebp holds the base address of SLB, save it for later. */
394+
mov %ebp, %ebx
395+
396+
/*
397+
* Mark Secure Launch boot protocol and jump to common entry. Note that
398+
* all general purpose registers except %ebx and %esi are clobbered
399+
* between here and .Lslaunch_proto.
400+
*/
378401
mov $SLAUNCH_BOOTLOADER_MAGIC, %eax
379402
jmp .Lset_stack
380403

@@ -497,10 +520,12 @@ __start:
497520
sub $8, %esp
498521

499522
push %esp /* pointer to output structure */
523+
push %ebx /* Slaunch parameter on AMD */
500524
lea sym_offs(__2M_rwdata_end), %ecx /* end of target image */
501525
lea sym_offs(_start), %edx /* target base address */
502526
mov %esi, %eax /* load base address */
503-
/* slaunch_early_tests(load/eax, tgt/edx, tgt_end/ecx, ret/stk) using fastcall. */
527+
/* slaunch_early_tests(load/eax, tgt/edx, tgt_end/ecx,
528+
slaunch/stk, ret/stk) using fastcall. */
504529
call slaunch_early_tests
505530

506531
/* Move outputs of slaunch_early_tests() from stack into registers. */

xen/arch/x86/boot/slaunch_early.c

+49-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
* - %eax = load_base_addr,
2121
* - %edx = tgt_base_addr,
2222
* - %ecx = tgt_end_addr,
23-
* - 0x04(%esp) = &result.
23+
* - 0x04(%esp) = slaunch_param,
24+
* - 0x08(%esp) = &result.
2425
*/
2526
asm (
2627
" .text \n"
@@ -32,13 +33,30 @@ asm (
3233
#include <xen/macros.h>
3334
#include <xen/types.h>
3435
#include <asm/intel_txt.h>
36+
#include <xen/slr_table.h>
37+
#include <asm/x86-vendors.h>
3538

3639
struct early_tests_results
3740
{
3841
uint32_t mbi_pa;
3942
uint32_t slrt_pa;
4043
} __packed;
4144

45+
static bool is_intel_cpu(void)
46+
{
47+
/*
48+
* asm/processor.h can't be included in early code, which means neither
49+
* cpuid() function nor boot_cpu_data can be used here.
50+
*/
51+
uint32_t eax, ebx, ecx, edx;
52+
asm volatile ( "cpuid"
53+
: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
54+
: "0" (0), "c" (0) );
55+
return ebx == X86_VENDOR_INTEL_EBX
56+
&& ecx == X86_VENDOR_INTEL_ECX
57+
&& edx == X86_VENDOR_INTEL_EDX;
58+
}
59+
4260
static void verify_pmr_ranges(struct txt_os_mle_data *os_mle,
4361
struct txt_os_sinit_data *os_sinit,
4462
uint32_t load_base_addr, uint32_t tgt_base_addr,
@@ -118,13 +136,43 @@ static void verify_pmr_ranges(struct txt_os_mle_data *os_mle,
118136
void slaunch_early_tests(uint32_t load_base_addr,
119137
uint32_t tgt_base_addr,
120138
uint32_t tgt_end_addr,
139+
uint32_t slaunch_param,
121140
struct early_tests_results *result)
122141
{
123142
void *txt_heap;
124143
struct txt_os_mle_data *os_mle;
125144
struct txt_os_sinit_data *os_sinit;
126145
uint32_t size = tgt_end_addr - tgt_base_addr;
127146

147+
if ( !is_intel_cpu() )
148+
{
149+
/*
150+
* Not an Intel CPU. Currently the only other option is AMD with SKINIT
151+
* and secure-kernel-loader.
152+
*/
153+
struct slr_table *slrt;
154+
struct slr_entry_dl_info *dl_info;
155+
156+
const uint16_t *sl_header = (void *)slaunch_param;
157+
/*
158+
* The fourth 16-bit integer of SKL's header is an offset to
159+
* bootloader's data, which is SLRT.
160+
*/
161+
result->slrt_pa = slaunch_param + sl_header[3];
162+
slrt = (struct slr_table *)result->slrt_pa;
163+
164+
result->mbi_pa = 0;
165+
dl_info = (struct slr_entry_dl_info *)
166+
slr_next_entry_by_tag (slrt, NULL, SLR_ENTRY_DL_INFO);
167+
/* Basic checks only, SKL checked and consumed the rest. */
168+
if ( dl_info == NULL
169+
|| dl_info->hdr.size != sizeof(*dl_info)
170+
|| dl_info->bl_context.bootloader != SLR_BOOTLOADER_GRUB )
171+
result->mbi_pa = dl_info->bl_context.context;
172+
173+
return;
174+
}
175+
128176
/* Clear the TXT error registers for a clean start of day */
129177
write_txt_reg(TXTCR_ERRORCODE, 0);
130178

0 commit comments

Comments
 (0)