Skip to content

Commit

Permalink
stage0_bin_tdx jumps to 64-bit long mode
Browse files Browse the repository at this point in the history
This CR adds the page tables to linker script. TD loads the pml4
address into cr3 and long jumps to 64-bit long mode entry point.
Also it uses a TEMP_MEM section for the low 640KiB memory area,
zeros out the .bss section, and set up the stack.

The Rust entrypoint prints a hello world message, checks if .data
section is in good shape, prints TdInfo and loops infinitely.

Temporarily park AP in a dead loop.

Also it fixes a bug in oak_tdx_guest, where the Attributes should
contain a bit for SEPT_VE_DISABLE. Without it, guest would crash on
get_td_info(). I used ver 1.5.05.44 of the TDX module ABI spec for
reference.

Example log:

ttyS0: Hello from stage0_bin_tdx!
ttyS0: TEST_DATA: deadbeaf
ttyS0: td_info.gpa_width: 0000000000000034
ttyS0: td_info.attributes: 0000000010000000
ttyS0: td_info.max_vcpus: 00000004
ttyS0: td_info.num_vcpus: 00000004

Bug: 352784756

Change-Id: I83aec1a8ca704409cbb074480d94d1bc3c5b8443
  • Loading branch information
dingelish committed Aug 5, 2024
1 parent 25949f5 commit aa3d5af
Show file tree
Hide file tree
Showing 8 changed files with 282 additions and 116 deletions.
43 changes: 35 additions & 8 deletions oak_tdx_guest/src/tdcall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,53 @@ const SUCCESS: u64 = 0;
bitflags! {
/// Attributes of a TD.
///
/// See section 18.2.1 of [Architecture Specification: Intel® Trust Domain Extensions(Intel® TDX)
/// Module](https://www.intel.com/content/dam/develop/external/us/en/documents/intel-tdx-module-1eas.pdf)
/// for more information.
/// See section 3.4.1 of [Intel® Trust Domain Extensions (Intel® TDX) Module
/// Architecture Application Binary Interface (ABI) Reference Specification]
/// (https://cdrdv2.intel.com/v1/dl/getContent/733579) Draft 1.5.05.44 for
/// more information.
#[derive(Default)]
pub struct Attributes: u64 {
/// The guest TD runs in off-TD debug mode.
///
/// If this is enabled the TD should be considered untrusted.
const DEBUG = 1 << 0;
/// Whether system profiling is enabled on the TD.
///
/// If this is enabled the TD should be considered untrusted.
const SYSPROF = 1 << 1;
/// The TD participates in HGS+ operation. HGS+ monitors the TD
/// operation as part of the whole system.
/// This bit may be set, if supported by the TDX module, regardless
/// on CPU support.
const HGS_PLUS_PROF = 1 << 4;
/// The TD participates in system profiling using performance monitoring
/// counters. Those counters are not context-switched on TD entry and
/// exit; they monitor the TD operation as part of the whole system.
/// This bit may be set, if supported by the TDX module, regardless on
/// CPU support.
const PERF_PROF = 1 << 5;
/// The TD participates in system profiling using core out-of-band
/// telemetry. Core telemetry monitors the TD operation as part of the
/// whole system.
/// This bit may be set, if supported by the TDX module, regardless of
/// CPU support.
const PMT_PROF = 1 << 6;
/// TD is allowed to use Linear Address Space Separation.
/// This bit may only be set if both the TDX module and the CPU support
/// LASS.
const LASS = 1 << 27;
/// Disable EPT violation conversion to #VE on guest TD access of
/// PENDING pages
const SEPT_VE_DISABLE = 1 << 28;
/// Whether the TD is migratable
const MIGRATABLE = 1 << 29;
/// Whether the TD is allowed to use Supervisor Protection Keys.
const PKS = 1 << 30;
/// Whether the TD is allowed to use Key Locker.
///
/// Must be 0 for the current version.
const KL = 1 << 31;
/// Wehther the TD is allowed to use Perfmon and PERF_METRICS.
/// The TD is a TDX Connect Provisioning Agent.
/// This bit may only be set if both the TDX module and the CPU support
/// TDX Connect.
const TPA = 1 << 62;
/// Whether the TD is allowed to use Perfmon and PERF_METRICS.
const PERFMON = 1 << 63;
}
}
Expand Down
10 changes: 10 additions & 0 deletions stage0_bin_tdx/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions stage0_bin_tdx/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ members = ["."]

[dependencies]
oak_stage0 = { path = "../stage0" }
oak_tdx_guest = { path = "../oak_tdx_guest" }

[profile.dev]
opt-level = "z"
Expand Down
77 changes: 56 additions & 21 deletions stage0_bin_tdx/layout.ld
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 The Project Oak Authors
* Copyright 2024 The Project Oak Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -67,20 +67,6 @@ SECTIONS {
. = ALIGN(4K);
} > ram_low

.ap_text : AT(TOP - 4K) {
ap_text_start = .;
*(.ap_text .ap_text.*)
ap_text_size = . - ap_text_start;
} > ram_low

.ap_bss (NOLOAD) : AT (ADDR(.ap_text) + SIZEOF(.ap_text)) {
ap_bss_start = .;
*(.ap_bss .ap_bss.*)
ap_bss_size = . - ap_bss_start;
} > ram_low

ASSERT(. <= 0x10000, "AP bootstrap code needs to be in the first 64K")

.bss (NOLOAD) : {
bss_start = .;
/* Include large section (.lbss) to support large code model.
Expand Down Expand Up @@ -260,6 +246,48 @@ SECTIONS {

ASSERT(. == TOP - BFV_SIZE + 120 + 24 + 4, "wrong BFV header size")

/* The ROM area is read only. We need to hard code the page table here
* and use it to switch to 64-bit long mode. After entering the 64-bit
* long mode, we are able to make tdcall to accept memory for ram_low
* section and create another set of page tables there.
* offset is : 0x00001000
* memory address: 0xffe01000 */
.page_tables ALIGN(4K): AT (TOP - BFV_SIZE + 0x1000) {
bios_pml4 = .; /* CR3 */
QUAD(ADDR(.page_tables) + 0x1000 + 0x23) /* 0..512GiB */
FILL(0)
. = bios_pml4 + 0x1000;

/* offset is : 0x00002000 */
/* memory address: 0xffe02000 */
bios_pdpt = .;
QUAD(ADDR(.page_tables) + 0x2000 + 0x23) /* 0..1GiB */
QUAD(0)
QUAD(0)
QUAD(ADDR(.page_tables) + 0x3000 + 0x23) /* 3..4GiB */
FILL(0)
. = bios_pdpt + 0x1000;

/* offset is : 0x00003000 */
/* memory address: 0xffe03000 */
bios_pd_0 = .;
QUAD(0x0 + 0xA3) /* 0..2MiB, HUGE_PAGE | PAGE_ACCESSED | PAGE_READ_WRITE | PAGE_PRESENT */
FILL(0)
. = bios_pd_0 + 0x1000;

/* offset is : 0x00004000 */
/* memory address: 0xffe04000 */
bios_pd_3 = .;
FILL(0)
. = bios_pd_3 + 0xFF8;
QUAD(0xFFE000A1) /* 4GiB-2MiB..4GiB, HUGE_PAGE | PAGE_ACCESSED | PAGE_PRESENT */
} > bios
ASSERT((bios_pml4 == ADDR(.page_tables)), "wrong pml4 address")
ASSERT((bios_pdpt == ADDR(.page_tables) + 0x1000), "wrong pdpt address")
ASSERT((bios_pd_0 == ADDR(.page_tables) + 0x2000), "wrong pd_0 address")
ASSERT((bios_pd_3 == ADDR(.page_tables) + 0x3000), "wrong pd_3 address")
ASSERT((. == ADDR(.page_tables) + 0x4000), "wrong page table size")

.rodata : {
/* Include large section (.lrodata) to support large code model.
* See <https://lld.llvm.org/ELF/large_sections.html>.
Expand All @@ -273,11 +301,13 @@ SECTIONS {
*/
*(.text .text.* .ltext.*)
*(.tdx.bootstrap)
text_end = .;
} > bios

/* Everything below this line interacts with 16-bit code, so should be kept as close to the end of the file as
* possible; max TOP - 32k. */

/* TODO: remove this section */
.text16 ALIGN(TOP - 4K + SIZEOF(.ap_text), 16) : {
*(.text16 .text16.*)
} > bios
Expand All @@ -295,12 +325,10 @@ SECTIONS {
* - C=0
*/
cs = . - ADDR(.rodata.gdt);
QUAD(SEGMENT_4K |
SEGMENT_LONG |
QUAD(SEGMENT_LONG |
SEGMENT_PRESENT |
SEGMENT_USER |
SEGMENT_CODE |
SEGMENT_WRITABLE |
SEGMENT_ACCESSED)
/* 64-bit data segment (see Section 4.8.2):
* - P=1 (present)
Expand Down Expand Up @@ -337,7 +365,6 @@ SECTIONS {
SEGMENT_PRESENT |
SEGMENT_USER |
SEGMENT_CODE |
SEGMENT_WRITABLE |
SEGMENT_ACCESSED |
(0xF << (32 + 16)) | /* Segment Limit [19:16] */
0xFFFF) /* Segment Limit [15:0] */
Expand All @@ -359,7 +386,7 @@ SECTIONS {
*/
.guid_tables TOP - 0x20 - (16 /* Intel TDX metadata GUID */
+ 16 /* TDVF decriptor <-----------| */
+ 2*32 /* TDVF sections | */
+ 3*32 /* TDVF sections | */
+ 22 /* Intel TDX metadata offset block | */
+ 18 /* footer */) : {

Expand Down Expand Up @@ -410,12 +437,20 @@ SECTIONS {
* header to describe a chunk. Since it is smaller than 16MB we can
* just use EFI_FFS_FILE_HEADER.
*/
LONG(0x0) /* TDX_BFV_RAW_DATA_OFFSET */
LONG(0x0) /* TDX_BFV_RAW_DATA_OFFSET */
LONG(BFV_SIZE) /* TDX_BFV_RAW_DATA_SIZE */
QUAD(TOP - BFV_SIZE) /* TDX_BFV_MEMORY_BASE */
QUAD(BFV_SIZE) /* TDX_BFV_MEMORY_SIZE */
LONG(0) /* TDX_METADATA_SECTION_TYPE_BFV */
LONG(0x00000001) /* TDX_METADATA_ATTRIBUTES_EXTENDMR */

/* The ram_low (TEMP_MEM). UEFI Section type 3 */
LONG(0) /* RAM_LOW firmware offset */
LONG(0) /* RAM_LOW binary size */
QUAD(0x0) /* RAM_LOW BASE */
QUAD(0xA0000) /* RAM_LOW SIZE 640KiB */
LONG(3) /* TDX_METADATA_SECTION_TYPE_TEMP_MEM */
LONG(0)
HIDDEN(tdx_metadata_structure_end = .);

/*
Expand Down
8 changes: 4 additions & 4 deletions stage0_bin_tdx/src/asm/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2022 The Project Oak Authors
// Copyright 2024 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -16,12 +16,12 @@

use core::arch::global_asm;

global_asm!(include_str!("reset_vector_tdx.s"), options(att_syntax, raw));
global_asm!(
include_str!("tdx.s"),
pml4 = sym crate::paging::PML4,
pdpt = sym crate::paging::PDPT,
pd_0 = sym crate::paging::PD_0,
pd_3 = sym crate::paging::PD_3,
options(att_syntax)
);
options(att_syntax));

global_asm!(include_str!("reset_vector_tdx.s"), options(att_syntax, raw));
2 changes: 1 addition & 1 deletion stage0_bin_tdx/src/asm/reset_vector_tdx.s
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 The Project Oak Authors
* Copyright 2024 The Project Oak Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
Loading

0 comments on commit aa3d5af

Please sign in to comment.