Skip to content

Add preliminary Intel TDX support [v2] #355

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 35 additions & 7 deletions Cargo.lock

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

16 changes: 16 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ SNP_INIT_SRC = init/tee/snp_attest.c \
init/tee/snp_attest.h \
$(KBS_INIT_SRC) \

TDX_INIT_SRC = $(KBS_INIT_SRC)

KBS_LD_FLAGS = -lcurl -lidn2 -lssl -lcrypto -lzstd -lz -lbrotlidec-static \
-lbrotlicommon-static

Expand All @@ -27,6 +29,14 @@ ifeq ($(SEV),1)
INIT_SRC += $(SNP_INIT_SRC)
BUILD_INIT = 0
endif
ifeq ($(TDX),1)
VARIANT = -tdx
FEATURE_FLAGS := --features tdx,tee,blk,kbs-types,serde,serde_json,curl
INIT_DEFS += -DTDX=1
INIT_DEFS += $(KBS_LD_FLAGS)
INIT_SRC += $(KBS_INIT_SRC)
BUILD_INIT = 0
endif
ifeq ($(VIRGL_RESOURCE_MAP2),1)
FEATURE_FLAGS += --features virgl_resource_map2
endif
Expand Down Expand Up @@ -99,6 +109,9 @@ endif
ifeq ($(NITRO),1)
mv target/release/libkrun.so target/release/$(KRUN_BASE_$(OS))
endif
ifeq ($(TDX),1)
mv target/release/libkrun.so target/release/$(KRUN_BASE_$(OS))
endif
ifeq ($(OS),Darwin)
ifeq ($(EFI),1)
install_name_tool -id $(PREFIX)/$(LIBDIR_$(OS))/$(KRUN_SONAME_$(OS)) target/release/libkrun.dylib
Expand All @@ -111,6 +124,9 @@ $(LIBRARY_DEBUG_$(OS)): $(INIT_BINARY)
cargo build $(FEATURE_FLAGS)
ifeq ($(SEV),1)
mv target/debug/libkrun.so target/debug/$(KRUN_BASE_$(OS))
endif
ifeq ($(TDX),1)
mv target/debug/libkrun.so target/debug/$(KRUN_BASE_$(OS))
endif
cp target/debug/$(KRUN_BASE_$(OS)) $(LIBRARY_DEBUG_$(OS))

Expand Down
9 changes: 9 additions & 0 deletions examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ LDFLAGS_x86_64_Linux = -lkrun
LDFLAGS_aarch64_Linux = -lkrun
LDFLAGS_arm64_Darwin = -L/opt/homebrew/lib -lkrun
LDFLAGS_sev = -lkrun-sev
LDFLAGS_tdx = -lkrun-tdx
LDFLAGS_efi = -L/opt/homebrew/lib -lkrun-efi
LDFLAGS_nitro = -lkrun-nitro
CFLAGS = -O2 -g -I../include
Expand All @@ -16,6 +17,9 @@ EXAMPLES := chroot_vm external_kernel
ifeq ($(SEV),1)
EXAMPLES := launch-tee
endif
ifeq ($(TDX),1)
EXAMPLES := launch-tee
endif
ifeq ($(EFI),1)
EXAMPLES := boot_efi
endif
Expand All @@ -29,7 +33,12 @@ ifeq ($(OS),Darwin)
endif

launch-tee: launch-tee.c
ifeq ($(SEV),1)
gcc -o $@ $< $(CFLAGS) $(LDFLAGS_sev)
endif
ifeq ($(TDX),1)
gcc -o $@ $< $(CFLAGS) $(LDFLAGS_tdx)
endif

boot_efi: boot_efi.c
gcc -o $@ $< $(CFLAGS) $(LDFLAGS_efi)
Expand Down
6 changes: 6 additions & 0 deletions examples/launch-tee.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ int main(int argc, char *const argv[])
return -1;
}

if (err = krun_split_irqchip(ctx_id, true)) {
errno = -err;
perror("Error setting split IRQCHIP property");
return -1;
}

// Start and enter the microVM. Unless there is some error while creating the microVM
// this function never returns.
if (err = krun_start_enter(ctx_id)) {
Expand Down
8 changes: 8 additions & 0 deletions examples/tdx-config-noattest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"workload_id": "tdxtest",
"cpus": 1,
"ram_mib": 2048,
"tee": "tdx",
"tee_data": "{\"vendor_chain\": \"\", \"attestation_server_pubkey\": \"\"}",
"attestation_url": ""
}
2 changes: 2 additions & 0 deletions src/arch/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2021"
[features]
tee = []
amd-sev = [ "tee" ]
tdx = [ "tee", "dep:tdx" ]
efi = []

[dependencies]
Expand All @@ -21,6 +22,7 @@ utils = { path = "../utils" }
[target.'cfg(target_os = "linux")'.dependencies]
kvm-bindings = { version = ">=0.11", features = ["fam-wrappers"] }
kvm-ioctls = ">=0.21"
tdx = { version = "0.1.0", optional = true }

[dev-dependencies]
utils = { path = "../utils" }
15 changes: 13 additions & 2 deletions src/arch/src/x86_64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ pub enum Error {

// Where BIOS/VGA magic would live on a real PC.
const EBDA_START: u64 = 0x9fc00;
#[cfg(not(feature = "tdx"))]
pub const RESET_VECTOR: u64 = 0xfff0;
#[cfg(feature = "tdx")]
pub const RESET_VECTOR: u64 = 0xffff_fff0;
pub const RESET_VECTOR_SEV_AP: u64 = 0xfff3;
pub const BIOS_START: u64 = 0xffff_0000;
pub const BIOS_SIZE: usize = 65536;
Expand Down Expand Up @@ -269,12 +272,20 @@ pub fn configure_system(
params.0.hdr.ramdisk_size = initrd_config.size as u32;
}

#[cfg(feature = "tee")]
#[cfg(all(feature = "tee", not(feature = "tdx")))]
{
params.0.hdr.syssize = num_cpus as u32;
}

add_e820_entry(&mut params.0, 0, EBDA_START, E820_RAM)?;
#[cfg(feature = "tdx")]
{
// number of 4k pages
params.0.hdr.syssize = (arch_memory_info.ram_last_addr / 4096) as u32;
// nuymber of vCPUs
params.0.hdr.root_flags = num_cpus as u16;
}

add_e820_entry(&mut params.0, 0, EBDA_START - 0x10000, E820_RAM)?;

let last_addr = GuestAddress(arch_memory_info.ram_last_addr);
if last_addr < end_32bit_gap_start {
Expand Down
3 changes: 3 additions & 0 deletions src/cpuid/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ version = "0.1.0"
authors = ["Amazon Firecracker team <firecracker-devel@amazon.com>"]
edition = "2021"

[features]
tdx = []

[dependencies]
vmm-sys-util = ">= 0.14"

Expand Down
54 changes: 54 additions & 0 deletions src/cpuid/src/transformer/intel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,61 @@ pub fn update_feature_info_entry(

common::update_feature_info_entry(entry, vm_spec)?;

// enable X2APIC bit
#[cfg(feature = "tdx")]
if entry.index == 0x1 {
println!("adjusting 0x1 index feature");
entry.ecx &= 1 << 21;
}

entry.ecx.write_bit(ecx::TSC_DEADLINE_TIMER_BITINDEX, true);

Ok(())
}

#[cfg(feature = "tdx")]
pub fn update_kvm_features(entry: &mut kvm_cpuid_entry2, _vm_spec: &VmSpec) -> Result<(), Error> {
// KVM feature bits
const NOP_IO_RELAY: u32 = 1;
const PV_UNHALT: u32 = 1;
const PV_TLB_FLUSH: u32 = 9;
const PV_SEND_IPI: u32 = 11;
const POLL_CONTROL: u32 = 12;
const PV_SCHED_YIELD: u32 = 13;
const MSI_EXT_DEST_ID: u32 = 15;

// These features are not supported by TDX
entry.eax &= (1 << NOP_IO_RELAY)
| (1 << PV_UNHALT)
| (1 << PV_TLB_FLUSH)
| (1 << PV_SEND_IPI)
| (1 << POLL_CONTROL)
| (1 << PV_SCHED_YIELD)
| (1 << MSI_EXT_DEST_ID);
Ok(())
}

#[cfg(feature = "tdx")]
pub fn update_0xd_for_tdx(entry: &mut kvm_cpuid_entry2, _vm_spec: &VmSpec) -> Result<(), Error> {
// set XSAVE features
if entry.function == 0xD && entry.index == 0 {
const XFEATURE_MASK_XTILE: u32 = (1 << 17) | (1 << 18);
if (entry.eax & XFEATURE_MASK_XTILE) != XFEATURE_MASK_XTILE {
entry.eax &= !XFEATURE_MASK_XTILE;
}
}

if entry.function == 0xD && entry.index == 1 {
entry.ecx &= !(1 << 15);
const XFEATURE_MASK_CET: u32 = (1 << 11) | (1 << 12);
if entry.ecx & XFEATURE_MASK_CET > 0 {
entry.ecx |= XFEATURE_MASK_CET;
}
}

Ok(())
}

fn update_deterministic_cache_entry(
entry: &mut kvm_cpuid_entry2,
vm_spec: &VmSpec,
Expand Down Expand Up @@ -146,6 +196,10 @@ impl CpuidTransformer for IntelCpuidTransformer {
leaf_0x6::LEAF_NUM => Some(intel::update_power_management_entry),
leaf_0xa::LEAF_NUM => Some(intel::update_perf_mon_entry),
leaf_0xb::LEAF_NUM => Some(intel::update_extended_cache_topology_entry),
#[cfg(feature = "tdx")]
leaf_0xd::LEAF_NUM => Some(intel::update_0xd_for_tdx),
#[cfg(feature = "tdx")]
0x4000_0001 => Some(intel::update_kvm_features),
0x8000_0002..=0x8000_0004 => Some(common::update_brand_string_entry),
_ => None,
}
Expand Down
1 change: 1 addition & 0 deletions src/devices/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2021"
[features]
tee = []
amd-sev = ["blk", "tee"]
tdx = ["tee"]
net = []
blk = []
efi = ["blk", "net"]
Expand Down
22 changes: 14 additions & 8 deletions src/devices/src/legacy/ioapic.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use crossbeam_channel::unbounded;
#[cfg(not(feature = "tdx"))]
use kvm_bindings::{kvm_enable_cap, KVM_CAP_SPLIT_IRQCHIP};
use kvm_bindings::{
kvm_enable_cap, kvm_irq_routing_entry, kvm_irq_routing_entry__bindgen_ty_1,
kvm_irq_routing_msi, KvmIrqRouting, KVM_CAP_SPLIT_IRQCHIP, KVM_IRQ_ROUTING_MSI,
kvm_irq_routing_entry, kvm_irq_routing_entry__bindgen_ty_1, kvm_irq_routing_msi, KvmIrqRouting,
KVM_IRQ_ROUTING_MSI,
};

use kvm_ioctls::{Error, VmFd};

use utils::eventfd::EventFd;
Expand Down Expand Up @@ -105,12 +108,15 @@ impl IoApic {
vm: &VmFd,
_irq_sender: crossbeam_channel::Sender<WorkerMessage>,
) -> Result<Self, Error> {
let mut cap = kvm_enable_cap {
cap: KVM_CAP_SPLIT_IRQCHIP,
..Default::default()
};
cap.args[0] = 24;
vm.enable_cap(&cap)?;
#[cfg(not(feature = "tdx"))]
{
let mut cap = kvm_enable_cap {
cap: KVM_CAP_SPLIT_IRQCHIP,
..Default::default()
};
cap.args[0] = 24;
vm.enable_cap(&cap)?;
}

let mut ioapic = Self {
id: 0,
Expand Down
Loading
Loading