Skip to content

Commit cff8931

Browse files
committed
x86/boot: find MBI and SLRT on AMD
Use slr_entry_amd_info::boot_params_base on AMD with SKINIT to get MBI location. Another thing of interest is the location of SLRT which is bootloader's data after SKL. Signed-off-by: Krystian Hebel <[email protected]> Signed-off-by: Sergii Dmytruk <[email protected]>
1 parent cf90ad6 commit cff8931

File tree

2 files changed

+91
-6
lines changed

2 files changed

+91
-6
lines changed

xen/arch/x86/boot/head.S

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -354,10 +354,12 @@ cs32_switch:
354354
jmp *%edi
355355

356356
/*
357-
* Entry point for TrenchBoot Secure Launch on Intel TXT platforms.
357+
* Entry point for TrenchBoot Secure Launch, common for Intel TXT and
358+
* AMD Secure Startup, but state is slightly different.
358359
*
360+
* On Intel:
359361
* CPU is in 32b protected mode with paging disabled. On entry:
360-
* - %ebx = %eip = MLE entry point,
362+
* - %ebx = %eip = this entry point,
361363
* - stack pointer is undefined,
362364
* - CS is flat 4GB code segment,
363365
* - DS, ES, SS, FS and GS are undefined according to TXT SDG, but this
@@ -375,13 +377,34 @@ cs32_switch:
375377
* - trying to enter real mode results in reset
376378
* - APs must be brought up by MONITOR or GETSEC[WAKEUP], depending on
377379
* which is supported by a given SINIT ACM
380+
*
381+
* On AMD (as implemented by TrenchBoot's SKL):
382+
* CPU is in 32b protected mode with paging disabled. On entry:
383+
* - %ebx = %eip = this entry point,
384+
* - %ebp holds base address of SKL
385+
* - stack pointer is treated as undefined for parity with TXT,
386+
* - CS is flat 4GB code segment,
387+
* - DS, ES, SS are flat 4GB data segments, but treated as undefined for
388+
* parity with TXT.
389+
*
390+
* Additional restrictions:
391+
* - interrupts (including NMIs and SMIs) are disabled and must be
392+
* enabled later
393+
* - APs must be brought up by SIPI without an INIT
378394
*/
379395
slaunch_stub_entry:
380396
/* Calculate the load base address. */
381397
mov %ebx, %esi
382398
sub $sym_offs(slaunch_stub_entry), %esi
383399

384-
/* Mark Secure Launch boot protocol and jump to common entry. */
400+
/* On AMD, %ebp holds the base address of SLB, save it for later. */
401+
mov %ebp, %ebx
402+
403+
/*
404+
* Mark Secure Launch boot protocol and jump to common entry. Note that
405+
* all general purpose registers except %ebx and %esi are clobbered
406+
* between here and .Lslaunch_proto.
407+
*/
385408
mov $SLAUNCH_BOOTLOADER_MAGIC, %eax
386409
jmp .Lset_stack
387410

@@ -508,15 +531,18 @@ __start:
508531
sub $8, %esp
509532

510533
push %esp /* pointer to output structure */
534+
push %ebx /* Slaunch parameter on AMD */
511535
lea sym_offs(__2M_rwdata_end), %ecx /* end of target image */
512536
lea sym_offs(_start), %edx /* target base address */
513537
mov %esi, %eax /* load base address */
514538
/*
515-
* slaunch_early_tests(load/eax, tgt/edx, tgt_end/ecx, ret/stk) using
516-
* fastcall calling convention.
539+
* slaunch_early_tests(load/eax, tgt/edx, tgt_end/ecx,
540+
* slaunch/stk, ret/stk)
541+
*
542+
* Uses fastcall calling convention.
517543
*/
518544
call slaunch_early_tests
519-
add $4, %esp /* pop the fourth parameter */
545+
add $8, %esp /* pop last two parameters */
520546

521547
/* Move outputs of slaunch_early_tests() from stack into registers. */
522548
pop %eax /* physical MBI address */

xen/arch/x86/boot/slaunch_early.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,47 @@
77
#include <xen/macros.h>
88
#include <xen/types.h>
99
#include <asm/intel_txt.h>
10+
#include <xen/slr_table.h>
11+
#include <asm/x86-vendors.h>
12+
13+
/*
14+
* The AMD-defined structure layout for the SLB. The last two fields are
15+
* SL-specific.
16+
*/
17+
struct skinit_sl_header
18+
{
19+
uint16_t skl_entry_point;
20+
uint16_t length;
21+
uint8_t reserved[62];
22+
uint16_t skl_info_offset;
23+
uint16_t bootloader_data_offset;
24+
} __packed;
1025

1126
struct early_tests_results
1227
{
1328
uint32_t mbi_pa;
1429
uint32_t slrt_pa;
1530
} __packed;
1631

32+
static bool is_intel_cpu(void)
33+
{
34+
/*
35+
* asm/processor.h can't be included in early code, which means neither
36+
* cpuid() function nor boot_cpu_data can be used here.
37+
*/
38+
uint32_t eax, ebx, ecx, edx;
39+
asm volatile ( "cpuid"
40+
: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
41+
: "0" (0), "c" (0) );
42+
return ebx == X86_VENDOR_INTEL_EBX
43+
&& ecx == X86_VENDOR_INTEL_ECX
44+
&& edx == X86_VENDOR_INTEL_EDX;
45+
}
46+
1747
void slaunch_early_tests(uint32_t load_base_addr,
1848
uint32_t tgt_base_addr,
1949
uint32_t tgt_end_addr,
50+
uint32_t slaunch_param,
2051
struct early_tests_results *result)
2152
{
2253
void *txt_heap;
@@ -26,6 +57,34 @@ void slaunch_early_tests(uint32_t load_base_addr,
2657
struct slr_entry_intel_info *intel_info;
2758
uint32_t size = tgt_end_addr - tgt_base_addr;
2859

60+
if ( !is_intel_cpu() )
61+
{
62+
/*
63+
* Not an Intel CPU. Currently the only other option is AMD with SKINIT
64+
* and secure-kernel-loader (SKL).
65+
*/
66+
struct slr_entry_amd_info *amd_info;
67+
const struct skinit_sl_header *sl_header = (void *)slaunch_param;
68+
69+
/*
70+
* slaunch_param holds a physical address of SLB.
71+
* Bootloader's data is SLRT.
72+
*/
73+
result->slrt_pa = slaunch_param + sl_header->bootloader_data_offset;
74+
result->mbi_pa = 0;
75+
76+
slrt = (struct slr_table *)(uintptr_t)result->slrt_pa;
77+
78+
amd_info = (struct slr_entry_amd_info *)
79+
slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_AMD_INFO);
80+
/* Basic checks only, SKL checked and consumed the rest. */
81+
if ( amd_info == NULL || amd_info->hdr.size != sizeof(*amd_info) )
82+
return;
83+
84+
result->mbi_pa = amd_info->boot_params_base;
85+
return;
86+
}
87+
2988
txt_heap = txt_init();
3089
os_mle = txt_os_mle_data_start(txt_heap);
3190
os_sinit = txt_os_sinit_data_start(txt_heap);

0 commit comments

Comments
 (0)