Skip to content

Commit

Permalink
provide TdxVcpu user API
Browse files Browse the repository at this point in the history
Signed-off-by: Jake Correnti <[email protected]>
  • Loading branch information
jakecorrenti committed May 30, 2024
1 parent 79ca0c8 commit 70dd780
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 7 deletions.
5 changes: 3 additions & 2 deletions src/launch/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ pub const NR_CPUID_CONFIGS: usize = 12;
/// Trust Domain eXtensions sub-ioctl() commands
#[repr(u32)]
pub enum CmdId {
GetCapabilities = 0,
InitVm = 1,
GetCapabilities,
InitVm,
InitVcpu,
}

/// Contains information for the sub-ioctl() command to be run. This is
Expand Down
57 changes: 55 additions & 2 deletions src/launch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ impl TdxVm {
/// Create a new TDX VM with KVM
pub fn new(kvm_fd: &Kvm, max_vcpus: u64) -> Result<Self, TdxError> {
let vm_fd = kvm_fd.create_vm_with_type(KVM_X86_TDX_VM)?;
let mut cap: kvm_enable_cap = Default::default();

// TDX requires that MAX_VCPUS and SPLIT_IRQCHIP be set
cap.cap = KVM_CAP_MAX_VCPUS;
let mut cap: kvm_enable_cap = kvm_enable_cap {
cap: KVM_CAP_MAX_VCPUS,
..Default::default()
};
cap.args[0] = max_vcpus;
vm_fd.enable_cap(&cap).unwrap();

Expand Down Expand Up @@ -261,3 +263,54 @@ pub struct TdxCapabilities {

pub cpuid_configs: Vec<CpuidConfig>,
}

/// Manually create the wrapper for KVM_MEMORY_ENCRYPT_OP since `kvm_ioctls` doesn't
/// support `.encrypt_op` for vcpu fds
use vmm_sys_util::*;
ioctl_iowr_nr!(
KVM_MEMORY_ENCRYPT_OP,
kvm_bindings::KVMIO,
0xba,
std::os::raw::c_ulong
);

pub struct TdxVcpu<'a> {
pub fd: &'a mut kvm_ioctls::VcpuFd,
}

impl<'a> TdxVcpu<'a> {
pub fn init(&self, hob_address: u64) -> Result<(), TdxError> {
let mut cmd = Cmd {
id: linux::CmdId::InitVcpu as u32,
flags: 0,
data: hob_address as *const u64 as _,
error: 0,
_unused: 0,
};
let ret = unsafe { ioctl::ioctl_with_mut_ptr(self.fd, KVM_MEMORY_ENCRYPT_OP(), &mut cmd) };
if ret < 0 {
// can't return `ret` because it will just return -1 and not give the error
// code. `cmd.error` will also just be 0.
return Err(TdxError::from(errno::Error::last()));
}
Ok(())
}
}

impl<'a> TryFrom<&'a mut kvm_ioctls::VcpuFd> for TdxVcpu<'a> {
type Error = TdxError;

fn try_from(fd: &'a mut kvm_ioctls::VcpuFd) -> Result<Self, Self::Error> {
// need to enable the X2APIC bit for CPUID[0x1] so that the kernel can call
// KVM_SET_MSRS(MSR_IA32_APIC_BASE) without failing
let kvm = Kvm::new()?;
let mut cpuid = kvm.get_supported_cpuid(kvm_bindings::KVM_MAX_CPUID_ENTRIES)?;
for entry in cpuid.as_mut_slice().iter_mut() {
if entry.index == 0x1 {
entry.ecx &= 1 << 21;
}
}
fd.set_cpuid2(&cpuid)?;
Ok(Self { fd })
}
}
8 changes: 5 additions & 3 deletions tests/launch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use kvm_ioctls::Kvm;

use tdx::launch::TdxVm;
use tdx::launch::{TdxVcpu, TdxVm};
use tdx::tdvf;

#[test]
Expand All @@ -15,8 +15,10 @@ fn launch() {
let _ = tdx_vm.init_vm(&kvm_fd, &caps).unwrap();

// create vcpu
let _vcpufd = tdx_vm.fd.create_vcpu(10).unwrap();
let mut vcpufd = tdx_vm.fd.create_vcpu(10).unwrap();
let tdx_vcpu = TdxVcpu::try_from(&mut vcpufd).unwrap();
let mut firmware = std::fs::File::open("./tests/data/OVMF.inteltdx.fd").unwrap();
let sections = tdvf::parse_sections(&mut firmware).unwrap();
let _hob_section = tdvf::get_hob_section(&sections).unwrap();
let hob_section = tdvf::get_hob_section(&sections).unwrap();
tdx_vcpu.init(hob_section.memory_address).unwrap();
}

0 comments on commit 70dd780

Please sign in to comment.