From 41672c2acb86c7f570fe353a2d7738d626d22865 Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Fri, 21 Nov 2025 11:53:09 -0500 Subject: [PATCH 1/2] tdvf: use `#[repr(C)]` on packed structs Fixes: #19 Signed-off-by: Jake Correnti --- src/tdvf/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tdvf/mod.rs b/src/tdvf/mod.rs index 62c53e9..5c9783d 100644 --- a/src/tdvf/mod.rs +++ b/src/tdvf/mod.rs @@ -8,7 +8,7 @@ use uuid::Uuid; const EXPECTED_TABLE_FOOTER_GUID: &str = "96b582de-1fb2-45f7-baea-a366c55a082d"; const EXPECTED_METADATA_GUID: &str = "e47a6535-984a-4798-865e-4685a7bf8ec2"; -#[repr(packed)] +#[repr(C, packed)] #[derive(Default, Debug)] struct TdvfDescriptor { /// Signature should equal "TDVF" in bytes @@ -24,7 +24,7 @@ struct TdvfDescriptor { number_of_section_entry: u32, } -#[repr(packed)] +#[repr(C, packed)] #[derive(Clone, Copy, Default, Debug)] pub struct TdvfSection { /// The offset to the raw section in the binary image From 5e8d3e6e65973315751548d57f1347256a44ad13 Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Fri, 21 Nov 2025 12:08:18 -0500 Subject: [PATCH 2/2] launch: support dynamically determining nr_cpuid Different generations of TDX may report a different number of cpuid configs. Support determining this number on the fly rather than hardcoding a value. Fixes: #18 Signed-off-by: Jake Correnti --- src/launch/linux.rs | 2 -- src/launch/mod.rs | 66 ++++++++++++++++++++++++++++----------------- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/src/launch/linux.rs b/src/launch/linux.rs index 29994ac..8cfc771 100644 --- a/src/launch/linux.rs +++ b/src/launch/linux.rs @@ -2,8 +2,6 @@ use std::marker::PhantomData; -pub const NR_CPUID_CONFIGS: usize = 24; - /// Trust Domain eXtensions sub-ioctl() commands #[repr(u32)] pub enum CmdId { diff --git a/src/launch/mod.rs b/src/launch/mod.rs index 267bea0..7d563d5 100644 --- a/src/launch/mod.rs +++ b/src/launch/mod.rs @@ -4,7 +4,7 @@ mod bindings; mod linux; use bindings::{kvm_tdx_capabilities, kvm_tdx_init_mem_region, kvm_tdx_init_vm}; -use linux::{Cmd, CmdId, NR_CPUID_CONFIGS}; +use linux::{Cmd, CmdId}; use bitflags::bitflags; use iocuddle::*; @@ -128,31 +128,47 @@ impl Launcher { /// in the system. pub fn get_capabilities(&mut self) -> Result { let mut caps = kvm_tdx_capabilities::default(); - - let mut defaults = Vec::with_capacity(NR_CPUID_CONFIGS); - (0..NR_CPUID_CONFIGS) - .for_each(|_| defaults.push(kvm_bindings::kvm_cpuid_entry2::default())); - let mut cpuid_entries = vec_with_array_field::< - kvm_tdx_capabilities, - kvm_bindings::kvm_cpuid_entry2, - >(NR_CPUID_CONFIGS); - cpuid_entries[0].cpuid.nent = NR_CPUID_CONFIGS as u32; - cpuid_entries[0].cpuid.padding = 0; - unsafe { - let cpuid_entries_slice: &mut [kvm_bindings::kvm_cpuid_entry2] = cpuid_entries[0] - .cpuid - .entries - .as_mut_slice(NR_CPUID_CONFIGS); - cpuid_entries_slice.copy_from_slice(defaults.as_slice()); + let mut defaults: Vec; + let mut cpuid_entries: Vec; + + let mut nr_cpuid_configs = 6; + + loop { + // configure the vec of the defaults with a nr_cpuid_configs capacity + defaults = Vec::with_capacity(nr_cpuid_configs); + (0..nr_cpuid_configs) + .for_each(|_| defaults.push(kvm_bindings::kvm_cpuid_entry2::default())); + + // allocate the memory for the dynamic number of entries to be eventually copied into + cpuid_entries = vec_with_array_field::< + kvm_tdx_capabilities, + kvm_bindings::kvm_cpuid_entry2, + >(nr_cpuid_configs); + cpuid_entries[0].cpuid.nent = nr_cpuid_configs as u32; + cpuid_entries[0].cpuid.padding = 0; + unsafe { + let cpuid_entries_slice: &mut [kvm_bindings::kvm_cpuid_entry2] = cpuid_entries[0] + .cpuid + .entries + .as_mut_slice(nr_cpuid_configs); + cpuid_entries_slice.copy_from_slice(defaults.as_slice()); + } + caps.cpuid.nent = nr_cpuid_configs as u32; + caps.cpuid.padding = 0; + let mut cmd: Cmd = + Cmd::from(CmdId::GetCapabilities, &cpuid_entries[0]); + + match GET_CAPABILITIES.ioctl(&mut self.vm_fd, &mut cmd) { + Err(e) if e.raw_os_error().is_some_and(|x| x == 7) => { + drop(defaults); + drop(cpuid_entries); + nr_cpuid_configs *= 2; + continue; + } + Err(e) => return Err(Error::GetCapabilities(e)), + Ok(_) => break, + }; } - caps.cpuid.nent = NR_CPUID_CONFIGS as u32; - caps.cpuid.padding = 0; - let mut cmd: Cmd = - Cmd::from(CmdId::GetCapabilities, &cpuid_entries[0]); - - GET_CAPABILITIES - .ioctl(&mut self.vm_fd, &mut cmd) - .map_err(Error::GetCapabilities)?; Ok(TdxCapabilities { attributes: AttributesFlags::from_bits_truncate(cpuid_entries[0].supported_attrs),