From 156fd90bc7ab540abd5f309ea09247c56b538f79 Mon Sep 17 00:00:00 2001 From: Chakradhar Kotamraju Date: Wed, 18 Dec 2024 16:51:52 -0700 Subject: [PATCH 1/6] TODO TDX comments were removed and corresponding issue items have been created --- openhcl/hcl/src/ioctl.rs | 2 - openhcl/openhcl_boot/src/arch/x86_64/tdx.rs | 2 - openhcl/openhcl_boot/src/main.rs | 8 --- openhcl/underhill_mem/src/lib.rs | 6 -- openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs | 2 - openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs | 13 +--- openhcl/virt_mshv_vtl/src/lib.rs | 9 +-- .../src/processor/hardware_cvm/mod.rs | 1 - .../virt_mshv_vtl/src/processor/tdx/mod.rs | 69 ++----------------- vm/hv1/hv1_emulator/src/cpuid.rs | 1 - vm/x86/tdcall/src/lib.rs | 5 -- vm/x86/x86defs/src/tdx.rs | 2 +- 12 files changed, 10 insertions(+), 110 deletions(-) diff --git a/openhcl/hcl/src/ioctl.rs b/openhcl/hcl/src/ioctl.rs index 967619e89..9663134c6 100644 --- a/openhcl/hcl/src/ioctl.rs +++ b/openhcl/hcl/src/ioctl.rs @@ -2783,7 +2783,6 @@ impl Hcl { IsolationType::Snp => hvdef::HvRegisterVsmCapabilities::new() .with_deny_lower_vtl_startup(caps.deny_lower_vtl_startup()) .with_intercept_page_available(caps.intercept_page_available()), - // TODO TDX: Figure out what these values should be. IsolationType::Tdx => hvdef::HvRegisterVsmCapabilities::new() .with_deny_lower_vtl_startup(caps.deny_lower_vtl_startup()) .with_intercept_page_available(caps.intercept_page_available()), @@ -2884,7 +2883,6 @@ impl Hcl { target_vtl: HvInputVtl, ) -> Result<(), ApplyVtlProtectionsError> { if self.isolation.is_hardware_isolated() { - // TODO SNP TODO TDX - required for vmbus relay monitor page support todo!(); } diff --git a/openhcl/openhcl_boot/src/arch/x86_64/tdx.rs b/openhcl/openhcl_boot/src/arch/x86_64/tdx.rs index 47858bd3c..33427c554 100644 --- a/openhcl/openhcl_boot/src/arch/x86_64/tdx.rs +++ b/openhcl/openhcl_boot/src/arch/x86_64/tdx.rs @@ -113,8 +113,6 @@ pub fn get_tdx_tsc_reftime() -> Option { // This is first called by the BSP from openhcl_boot and the frequency // is saved in this gloabal variable. Subsequent calls use the global variable. if TSC_FREQUENCY.get() == 0 { - // TODO TDX: Getting tsc frequency from HV currently. Explore the option - // of getting it from more reliable source such as CPUID. TSC_FREQUENCY.set(read_msr_tdcall(hvdef::HV_X64_MSR_TSC_FREQUENCY)); } diff --git a/openhcl/openhcl_boot/src/main.rs b/openhcl/openhcl_boot/src/main.rs index a1a8a306f..45b2aa53b 100644 --- a/openhcl/openhcl_boot/src/main.rs +++ b/openhcl/openhcl_boot/src/main.rs @@ -790,14 +790,6 @@ fn validate_vp_hw_ids(partition_info: &PartitionInfo) { use hypercall::HwId; if partition_info.isolation.is_hardware_isolated() { - // TODO TDX SNP: we don't have a GHCB/GHCI page set up to communicate - // with the hypervisor here, so we can't easily perform the check. Since - // there is no security impact to this check, we can skip it for now; if - // the VM fails to boot, then this is due to a host contract violation. - // - // For TDX, we could use ENUM TOPOLOGY to validate that the TD VCPU - // indexes correspond to the APIC IDs in the right order. I am not - // certain if there are places where we depend on this mapping today. return; } diff --git a/openhcl/underhill_mem/src/lib.rs b/openhcl/underhill_mem/src/lib.rs index 173bc4355..4e1971573 100644 --- a/openhcl/underhill_mem/src/lib.rs +++ b/openhcl/underhill_mem/src/lib.rs @@ -1139,12 +1139,6 @@ mod mapping { } } IsolationType::Tdx => { - // TODO TDX GUEST VSM: implement acceptor.vtl_permissions - // For now, since guest vsm isn't enabled (therefore no VTL - // 1), and VTL 0 can't change its own permissions, the - // permissions should be the same as when VTL 2 initialized - // guest memory. - GpaVtlPermissions::new(IsolationType::Tdx, vtl, HV_MAP_GPA_PERMISSIONS_ALL) } }; diff --git a/openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs b/openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs index 9da1bbdbd..7ab64b8e7 100644 --- a/openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs +++ b/openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs @@ -59,8 +59,6 @@ trait CpuidArchInitializer { /// Processes extended state enumeration subleaves 2+. result is a helper /// for retrieving the result of a given subleaf. // - // (TODO TDX: This will be to populate them, will need to update the - // signature to pass CpuidResults as a mutable reference) fn process_extended_state_subleaves( &self, results: &mut CpuidSubtable, diff --git a/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs b/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs index c95088bb1..864be264d 100644 --- a/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs +++ b/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs @@ -22,8 +22,6 @@ pub const TDX_REQUIRED_LEAVES: &[(CpuidFunction, Option)] = &[ (CpuidFunction::TileInformation, Some(0)), (CpuidFunction::TileInformation, Some(1)), (CpuidFunction::TmulInformation, Some(0)), - // TODO TDX: The following aren't required from AMD. Need to double-check if - // they're required for TDX (CpuidFunction::CacheAndTlbInformation, None), (CpuidFunction::ExtendedFeatures, Some(1)), (CpuidFunction::CacheParameters, Some(0)), @@ -51,7 +49,6 @@ impl CpuidArchInitializer for TdxCpuidInitializer { } fn extended_max_function(&self) -> u32 { - // TODO TDX: Check if this is the same value in the OS repo CpuidFunction::ExtendedIntelMaximum.0 } @@ -111,7 +108,6 @@ impl CpuidArchInitializer for TdxCpuidInitializer { } CpuidFunction::TmulInformation => { if subleaf == 0 { - // TODO TDX: does this actually have subleaves? the spec says 1+ are reserved Some(CpuidResultMask::new( 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, true, )) @@ -164,7 +160,6 @@ impl CpuidArchInitializer for TdxCpuidInitializer { results: &mut CpuidSubtable, extended_state_mask: u64, ) -> Result<(), CpuidResultsError> { - // TODO TDX: See HvlpPopulateExtendedStateCpuid let xfd_supported = if let Some(support) = results.get(&1).map( |CpuidResult { eax, @@ -187,9 +182,7 @@ impl CpuidArchInitializer for TdxCpuidInitializer { if (1 << i) & summary_mask != 0 { let result = Self::cpuid(CpuidFunction::ExtendedStateEnumeration.0, i); let result_xfd = cpuid::ExtendedStateEnumerationSubleafNEcx::from(result.ecx).xfd(); - if xfd_supported && result_xfd { - // TODO TDX: update some maximum xfd value; see HvlpMaximumXfd - } + if xfd_supported && result_xfd {} results.insert(i, result); } @@ -205,8 +198,6 @@ impl CpuidArchInitializer for TdxCpuidInitializer { _address_space_sizes_ecx: cpuid::ExtendedAddressSpaceSizesEcx, _processor_topology_ebx: Option, // Will be None for Intel ) -> Result { - // TODO TDX: see HvlpInitializeCpuidTopologyIntel - // TODO TDX: fix returned errors let vps_per_socket; if !version_and_features_edx.mt_per_socket() { if version_and_features_ebx.lps_per_package() > 1 { @@ -220,8 +211,6 @@ impl CpuidArchInitializer for TdxCpuidInitializer { vps_per_socket = version_and_features_ebx.lps_per_package(); } - // TODO TDX: validation of leaf 0xB - Ok(super::ExtendedTopologyResult { subleaf0: None, subleaf1: None, diff --git a/openhcl/virt_mshv_vtl/src/lib.rs b/openhcl/virt_mshv_vtl/src/lib.rs index d0258d7c6..d1dede3f2 100644 --- a/openhcl/virt_mshv_vtl/src/lib.rs +++ b/openhcl/virt_mshv_vtl/src/lib.rs @@ -819,9 +819,6 @@ impl virt::Synic for UhPartition { } fn monitor_support(&self) -> Option<&dyn virt::SynicMonitor> { - // TODO TDX TODO SNP: Disable monitor support for TDX and SNP as support - // for VTL2 protections is needed to emulate this page, which is not - // implemented yet. if self.inner.isolation.is_hardware_isolated() { None } else { @@ -1343,10 +1340,6 @@ impl<'a> UhProtoPartition<'a> { let is_hardware_isolated = isolation.is_hardware_isolated(); // Intercept Debug Exceptions - // TODO TDX: This currently works on TDX because all Underhill TDs today - // have the debug policy bit set, allowing the hypervisor to install the - // intercept on behalf of the guest. In the future, Underhill should - // register for these intercepts itself. if params.intercept_debug_exceptions { if !cfg!(feature = "gdb") { return Err(Error::InvalidDebugConfiguration); @@ -1698,7 +1691,7 @@ impl UhProtoPartition<'_> { match params.isolation { IsolationType::None | IsolationType::Vbs => {} #[cfg(guest_arch = "x86_64")] - IsolationType::Tdx => return false, // TODO TDX GUEST_VSM + IsolationType::Tdx => return false, #[cfg(guest_arch = "x86_64")] IsolationType::Snp => { if !params.env_cvm_guest_vsm { diff --git a/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs b/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs index 31aebec67..97c813077 100644 --- a/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs +++ b/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs @@ -709,7 +709,6 @@ impl UhHypercallHandler<'_, '_, T, B> { } // TODO GUEST VSM: interrupt rewinding - // TODO TDX GUEST VSM: update execution mode } } diff --git a/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs b/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs index af78b5970..69b1fe855 100644 --- a/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs +++ b/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs @@ -483,7 +483,6 @@ impl HardwareIsolatedBacking for TdxBacked { this: &UhProcessor<'_, Self>, vtl: GuestVtl, ) -> TranslationRegisters { - // TODO TDX GUEST VSM: use vtl for all registers let cr0 = this.backing.cr0.read(&this.runner); let cr4 = this.backing.cr4.read(&this.runner); let efer = this.backing.efer; @@ -538,9 +537,6 @@ impl BackingPrivate for TdxBacked { params: super::private::BackingParams<'_, '_, Self>, _shared: &TdxBackedShared, ) -> Result { - // TODO TDX: TDX shares the vp context page for xmm registers only. It - // should probably move to its own page. - // // FX regs and XMM registers are zero-initialized by the kernel. Set // them to the arch default. *params.runner.fx_state_mut() = @@ -565,14 +561,6 @@ impl BackingPrivate for TdxBacked { *rflags = regs.rflags; *rip = regs.rip; - // TODO TDX: ssp is for shadow stack - - // TODO TDX: direct overlay like snp? - // TODO TDX: lapic / APIC setup? - - // TODO TDX: see ValInitializeVplc - // TODO TDX: XCR_XFMEM setup? - // Configure L2 controls to permit shared memory. // // Ideally we would disable this when `hide_isolation` is set, but @@ -621,8 +609,6 @@ impl BackingPrivate for TdxBacked { // Allowed cr4 bits depend on the values allowed by the SEAM. // - // TODO TDX: Consider just using MSR kernel module instead of explicit - // ioctl. let read_cr4 = hcl.read_vmx_cr4_fixed1(); let allowed_cr4_bits = (ShadowedRegister::Cr4.guest_owned_mask() | X64_CR4_MCE) & read_cr4; @@ -677,7 +663,6 @@ impl BackingPrivate for TdxBacked { ) .into(); - // TODO TDX: This needs to come from a private pool let flush_page = params .partition .shared_vis_pages_pool @@ -787,7 +772,6 @@ impl BackingPrivate for TdxBacked { this.run_vp_tdx(dev).await } - // TODO TDX GUEST VSM fn poll_apic( this: &mut UhProcessor<'_, Self>, _vtl: GuestVtl, @@ -828,7 +812,6 @@ impl BackingPrivate for TdxBacked { this: &mut UhProcessor<'_, Self>, _dev: &impl CpuIo, ) -> Result { - // TODO TDX GUEST VSM this.hcvm_handle_cross_vtl_interrupts(|_this, _vtl, _check_rflags| false) } @@ -856,7 +839,6 @@ impl UhProcessor<'_, TdxBacked> { // Check for interrupt requests from the host. let mut update_rvi = false; if let Some(irr) = self.runner.proxy_irr() { - // TODO TDX: filter proxy IRRs. if self.backing.cvm.lapics[GuestVtl::Vtl0] .lapic .can_offload_irr() @@ -1332,11 +1314,6 @@ impl UhProcessor<'_, TdxBacked> { // otherwise the interrupt will be lost and the guest left in a bad // state. // - // TODO TDX: Unclear what kind of exits these would be, but they - // should be spurious EPT exits. Can we validate or assert that - // somehow? If we were to somehow call some other path which would - // set interruption_information before we inject this one, we would - // lose this interrupt. if next_interruption.valid() { tracing::debug!( ?next_interruption, @@ -1498,7 +1475,6 @@ impl UhProcessor<'_, TdxBacked> { let subleaf = enter_state.rcx() as u32; let xfem = self .runner - // TODO TDX GUEST VSM .get_vp_register(GuestVtl::Vtl0, HvX64RegisterName::Xfem) .map_err(|err| VpHaltReason::Hypervisor(UhRunVpError::EmulationState(err)))? .as_u64(); @@ -1610,7 +1586,6 @@ impl UhProcessor<'_, TdxBacked> { }) { self.runner - // TODO TDX GUEST VSM .set_vp_register(GuestVtl::Vtl0, HvX64RegisterName::Xfem, value.into()) .map_err(|err| { VpHaltReason::Hypervisor(UhRunVpError::EmulationState(err)) @@ -1634,20 +1609,6 @@ impl UhProcessor<'_, TdxBacked> { &mut self.backing.exit_stats.wbinvd } VmxExit::EPT_VIOLATION => { - // TODO TDX: If this is an access to a shared gpa, we need to - // check the intercept page to see if this is a real exit or - // spurious. This exit is only real if the hypervisor has - // delivered an intercept message for this GPA. - // - // However, at this point the kernel has cleared that - // information so some kind of redesign is required to figure - // this out. - // - // For now, we instead treat EPTs on readable RAM as spurious - // and log appropriately. This check is also not entirely - // sufficient, as it may be a write access where the page is - // protected, but we don't yet support MNF/guest VSM so this is - // okay enough. let is_readable_ram = self.partition.gm[intercepted_vtl].check_gpa_readable(exit_info.gpa()); if is_readable_ram { @@ -1880,7 +1841,6 @@ impl UhProcessor<'_, TdxBacked> { // so that the hypervisor can directly inject events. if matches!(msr, hvdef::HV_X64_MSR_SINT0..=hvdef::HV_X64_MSR_SINT15) { if let Err(err) = self.runner.set_vp_register( - // TODO TDX GUEST VSM GuestVtl::Vtl0, HvX64RegisterName( HvX64RegisterName::Sint0.0 + (msr - hvdef::HV_X64_MSR_SINT0), @@ -1900,14 +1860,7 @@ impl UhProcessor<'_, TdxBacked> { } fn read_msr_cvm(&self, msr: u32, vtl: GuestVtl) -> Result { - // TODO TDX: port remaining tdx and common values - // - // TODO TDX: consider if this can be shared with SnpBacked's - // implementation. For the most part other than Intel/TDX specific - // registers, MSR handling should be the same. - match msr { - // TODO TDX: LIFTED FROM WHP x86defs::X86X_IA32_MSR_PLATFORM_ID => { // Windows requires accessing this to boot. WHP // used to pass this through to the hardware, @@ -2064,8 +2017,6 @@ impl UhProcessor<'_, TdxBacked> { self.runner .write_vmcs32(vtl, seg.attributes(), !0, attributes.into()); - // TODO TDX: cache CS into last exit because last exit contains CS optionally? - Ok(()) } @@ -2101,7 +2052,6 @@ impl EmulatorSupport for UhEmulationState<'_, '_, T, TdxBacked> { let cs = TdxExit(self.vp.runner.tdx_vp_enter_exit_info()).cs(); let enter_state = self.vp.runner.tdx_enter_guest_state(); - // TODO TDX: Only supports VTL0 Ok(x86emu::CpuState { gps: enter_state.gps, segs: [ @@ -2205,7 +2155,6 @@ impl EmulatorSupport for UhEmulationState<'_, '_, T, TdxBacked> { _gpa: u64, _mode: TranslateMode, ) -> Result<(), virt_support_x86emu::emulate::EmuCheckVtlAccessError> { - // TODO TDX: VTL1 not supported // Lock Vtl TLB Ok(()) } @@ -2590,9 +2539,6 @@ impl UhHypercallHandler<'_, '_, T, TdxBacked> { hv1_hypercall::HvPostMessage, hv1_hypercall::HvSignalEvent, hv1_hypercall::HvExtQueryCapabilities, - // TODO TDX: copied from SNP, enable individually as needed. - // hv1_hypercall::HvGetVpRegisters, - // hv1_hypercall::HvEnablePartitionVtl, ] ); @@ -2806,8 +2752,8 @@ impl AccessVpState for UhVpStateAccess<'_, '_, TdxBacked> { nmi_masked: interruptibility.blocked_by_nmi(), interrupt_shadow: interruptibility.blocked_by_sti() || interruptibility.blocked_by_movss(), - pending_event: None, // TODO TDX - pending_interruption: None, // TODO TDX + pending_event: None, + pending_interruption: None, }) } @@ -2817,8 +2763,8 @@ impl AccessVpState for UhVpStateAccess<'_, '_, TdxBacked> { nmi_pending, nmi_masked, interrupt_shadow, - pending_event: _, // TODO TDX - pending_interruption: _, // TODO TDX + pending_event: _, + pending_interruption: _, } = value; self.vp.backing.cvm.lapics[self.vtl].activity = mp_state; self.vp.backing.cvm.lapics[self.vtl].nmi_pending = nmi_pending; @@ -2887,14 +2833,13 @@ impl AccessVpState for UhVpStateAccess<'_, '_, TdxBacked> { fn mtrrs(&mut self) -> Result { Ok(vp::Mtrrs { - msr_mtrr_def_type: 0, // TODO TDX: MTRRs - fixed: [0; 11], // TODO TDX: MTRRs - variable: [0; 16], // TODO TDX: MTRRs + msr_mtrr_def_type: 0, + fixed: [0; 11], + variable: [0; 16], }) } fn set_mtrrs(&mut self, _value: &vp::Mtrrs) -> Result<(), Self::Error> { - // TODO TDX: MTRRs Ok(()) } diff --git a/vm/hv1/hv1_emulator/src/cpuid.rs b/vm/hv1/hv1_emulator/src/cpuid.rs index 29d1dfb7b..5c2ef8382 100644 --- a/vm/hv1/hv1_emulator/src/cpuid.rs +++ b/vm/hv1/hv1_emulator/src/cpuid.rs @@ -129,7 +129,6 @@ pub fn hv_cpuid_leaves( .with_use_apic_msrs(use_apic_msrs); if hardware_isolated { - // TODO TDX too when it's ready if isolation == IsolationType::Snp { enlightenments = enlightenments .with_use_hypercall_for_remote_flush_and_local_flush_entire(true); diff --git a/vm/x86/tdcall/src/lib.rs b/vm/x86/tdcall/src/lib.rs index c3a3ac1af..e109a9d77 100644 --- a/vm/x86/tdcall/src/lib.rs +++ b/vm/x86/tdcall/src/lib.rs @@ -357,8 +357,6 @@ pub fn tdcall_page_attr_wr( let output = call.tdcall(input); - // TODO TDX: RCX and RDX also contain info that could be returned - match output.rax.code() { TdCallResultCode::SUCCESS => Ok(()), val => Err(val), @@ -392,7 +390,6 @@ fn set_page_attr( /// The error returned by [`accept_pages`]. #[derive(Debug)] pub enum AcceptPagesError { - // TODO TDX: better error types /// Unknown error type. Unknown(TdCallResultCode), /// Setting page attributes failed after accepting, @@ -574,8 +571,6 @@ pub fn tdcall_map_gpa( let output = call.tdcall(input); - // TODO TDX: check rax return code - let result = TdVmCallR10Result(output.r10); match result { diff --git a/vm/x86/x86defs/src/tdx.rs b/vm/x86/x86defs/src/tdx.rs index 2e047cafd..cfab14119 100644 --- a/vm/x86/x86defs/src/tdx.rs +++ b/vm/x86/x86defs/src/tdx.rs @@ -502,7 +502,7 @@ pub struct TdxExtendedFieldCode { /// Instruction info returned in r11 for a TDG.VP.ENTER call. #[bitfield(u64)] pub struct TdxInstructionInfo { - pub info: u32, // TODO TDX: what is this + pub info: u32, pub length: u32, } From b0a21f6b6d96dfbbfb9bed07b802a0b317ffdea4 Mon Sep 17 00:00:00 2001 From: Chakradhar Kotamraju Date: Thu, 16 Jan 2025 18:01:46 -0700 Subject: [PATCH 2/6] Merged from OpenVMM --- openhcl/virt_mshv_vtl/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openhcl/virt_mshv_vtl/src/lib.rs b/openhcl/virt_mshv_vtl/src/lib.rs index 7cdcb642b..d1dede3f2 100644 --- a/openhcl/virt_mshv_vtl/src/lib.rs +++ b/openhcl/virt_mshv_vtl/src/lib.rs @@ -113,7 +113,7 @@ use zerocopy::FromZeroes; /// General error returned by operations. #[derive(Error, Debug)] -#[expect(missing_docs)] +#[allow(missing_docs)] pub enum Error { #[error("hcl error")] Hcl(#[source] hcl::ioctl::Error), @@ -158,7 +158,7 @@ pub enum Error { /// Error revoking guest VSM. #[derive(Error, Debug)] -#[expect(missing_docs)] +#[allow(missing_docs)] pub enum RevokeGuestVsmError { #[error("failed to set vsm config")] SetGuestVsmConfig(#[source] hcl::ioctl::SetGuestVsmConfigError), From 45807ffe41479f55242f57748f9fc6532fa8406e Mon Sep 17 00:00:00 2001 From: Chakradhar Kotamraju Date: Thu, 16 Jan 2025 18:29:19 -0700 Subject: [PATCH 3/6] Merged changed from OpenVMM tip --- openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs | 4 +- openhcl/virt_mshv_vtl/src/lib.rs | 6 +- .../src/processor/hardware_cvm/mod.rs | 1 + .../virt_mshv_vtl/src/processor/tdx/mod.rs | 126 +++++++++++------- 4 files changed, 86 insertions(+), 51 deletions(-) diff --git a/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs b/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs index 864be264d..c4d645607 100644 --- a/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs +++ b/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs @@ -182,7 +182,9 @@ impl CpuidArchInitializer for TdxCpuidInitializer { if (1 << i) & summary_mask != 0 { let result = Self::cpuid(CpuidFunction::ExtendedStateEnumeration.0, i); let result_xfd = cpuid::ExtendedStateEnumerationSubleafNEcx::from(result.ecx).xfd(); - if xfd_supported && result_xfd {} + if xfd_supported && result_xfd { + // TODO TDX: update some maximum xfd value; see HvlpMaximumXfd + } results.insert(i, result); } diff --git a/openhcl/virt_mshv_vtl/src/lib.rs b/openhcl/virt_mshv_vtl/src/lib.rs index d1dede3f2..b2eaa204a 100644 --- a/openhcl/virt_mshv_vtl/src/lib.rs +++ b/openhcl/virt_mshv_vtl/src/lib.rs @@ -113,7 +113,7 @@ use zerocopy::FromZeroes; /// General error returned by operations. #[derive(Error, Debug)] -#[allow(missing_docs)] +#[expect(missing_docs)] pub enum Error { #[error("hcl error")] Hcl(#[source] hcl::ioctl::Error), @@ -158,7 +158,7 @@ pub enum Error { /// Error revoking guest VSM. #[derive(Error, Debug)] -#[allow(missing_docs)] +#[expect(missing_docs)] pub enum RevokeGuestVsmError { #[error("failed to set vsm config")] SetGuestVsmConfig(#[source] hcl::ioctl::SetGuestVsmConfigError), @@ -1691,7 +1691,7 @@ impl UhProtoPartition<'_> { match params.isolation { IsolationType::None | IsolationType::Vbs => {} #[cfg(guest_arch = "x86_64")] - IsolationType::Tdx => return false, + IsolationType::Tdx => return false, // TODO TDX GUEST_VSM #[cfg(guest_arch = "x86_64")] IsolationType::Snp => { if !params.env_cvm_guest_vsm { diff --git a/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs b/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs index 97c813077..31aebec67 100644 --- a/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs +++ b/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs @@ -709,6 +709,7 @@ impl UhHypercallHandler<'_, '_, T, B> { } // TODO GUEST VSM: interrupt rewinding + // TODO TDX GUEST VSM: update execution mode } } diff --git a/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs b/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs index e6f78875f..d03bd890a 100644 --- a/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs +++ b/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs @@ -64,7 +64,7 @@ use virt_support_apic::ApicWork; use virt_support_apic::OffloadNotSupported; use virt_support_x86emu::emulate::emulate_io; use virt_support_x86emu::emulate::emulate_translate_gva; -use virt_support_x86emu::emulate::EmulatorSupport; +use virt_support_x86emu::emulate::EmulatorSupport as X86EmulatorSupport; use virt_support_x86emu::emulate::TranslateMode; use virt_support_x86emu::translate::TranslationRegisters; use vmcore::vmtime::VmTimeAccess; @@ -112,6 +112,8 @@ use x86defs::X64_EFER_LME; use x86defs::X64_EFER_NXE; use x86defs::X64_EFER_SVME; use x86defs::X86X_MSR_EFER; +use x86emu::Gp; +use x86emu::Segment; #[derive(Debug)] struct TdxExit<'a>(&'a tdx_tdg_vp_enter_exit_info); @@ -436,6 +438,12 @@ struct TdxVtl { exit_stats: ExitStats, } +#[derive(Default)] +pub struct TdxEmulationCache { + pub segs: [Option; 6], + pub cr0: Option, +} + #[derive(Inspect, Default)] pub struct EnterStats { pub success: Counter, @@ -542,7 +550,7 @@ impl TdxBackedShared { impl BackingPrivate for TdxBacked { type HclBacking = Tdx; type Shared = TdxBackedShared; - type EmulationCache = (); + type EmulationCache = TdxEmulationCache; fn shared(shared: &BackingShared) -> &Self::Shared { let BackingShared::Tdx(shared) = shared else { @@ -594,10 +602,9 @@ impl BackingPrivate for TdxBacked { // when VTL 1 is enabled. // Configure L2 controls to permit shared memory. - // - // Ideally we would disable this when `hide_isolation` is set, but - // currently this is failing with `METADATA_FIELD_NOT_WRITABLE`. - let mut controls = TdxL2Ctls::new().with_enable_shared_ept(true); + + let mut controls = + TdxL2Ctls::new().with_enable_shared_ept(!params.partition.hide_isolation); // If the synic is to be managed by the hypervisor, then enable TDVMCALLs. controls.set_enable_tdvmcall( @@ -1504,6 +1511,7 @@ impl UhProcessor<'_, TdxBacked> { .interruption_information .valid(), intercepted_vtl, + TdxEmulationCache::default(), ) .await?; } else { @@ -1766,7 +1774,6 @@ impl UhProcessor<'_, TdxBacked> { // spurious. This exit is only real if the hypervisor has // delivered an intercept message for this GPA. // - // However, at this point the kernel has cleared that // information so some kind of redesign is required to figure // this out. @@ -1811,6 +1818,7 @@ impl UhProcessor<'_, TdxBacked> { .interruption_information .valid(), intercepted_vtl, + TdxEmulationCache::default(), ) .await?; } @@ -2219,65 +2227,89 @@ impl UhProcessor<'_, TdxBacked> { } } -impl EmulatorSupport for UhEmulationState<'_, '_, T, TdxBacked> { +impl X86EmulatorSupport for UhEmulationState<'_, '_, T, TdxBacked> { type Error = UhRunVpError; fn vp_index(&self) -> VpIndex { self.vp.vp_index() } + fn flush(&mut self) -> Result<(), Self::Error> { + // no cached registers are modifiable by the emulator for TDX + Ok(()) + } + fn vendor(&self) -> x86defs::cpuid::Vendor { self.vp.partition.caps.vendor } - fn state(&mut self) -> Result { - let cr0 = self.vp.backing.vtls[self.vtl].cr0.read(&self.vp.runner); - let efer = self.vp.backing.vtls[self.vtl].efer; - let cs = TdxExit(self.vp.runner.tdx_vp_enter_exit_info()).cs(); + fn gp(&mut self, reg: Gp) -> u64 { let enter_state = self.vp.runner.tdx_enter_guest_state(); - - Ok(x86emu::CpuState { - gps: enter_state.gps, - segs: [ - self.vp.read_segment(self.vtl, TdxSegmentReg::Es).into(), - cs.into(), - self.vp.read_segment(self.vtl, TdxSegmentReg::Ss).into(), - self.vp.read_segment(self.vtl, TdxSegmentReg::Ds).into(), - self.vp.read_segment(self.vtl, TdxSegmentReg::Fs).into(), - self.vp.read_segment(self.vtl, TdxSegmentReg::Gs).into(), - ], - rip: enter_state.rip, - rflags: enter_state.rflags.into(), - cr0, - efer, - }) + enter_state.gps[reg as usize] } - fn set_state(&mut self, state: x86emu::CpuState) -> Result<(), Self::Error> { - // TODO: immutable true? copied from snp - let x86emu::CpuState { - gps, - segs: _, // immutable - rip, - rflags, - cr0: _, // immutable - efer: _, // immutable - } = state; + fn set_gp(&mut self, reg: Gp, v: u64) { let enter_state = self.vp.runner.tdx_enter_guest_state_mut(); + enter_state.gps[reg as usize] = v; + } + + fn xmm(&mut self, index: usize) -> u128 { + u128::from_ne_bytes(self.vp.runner.fx_state().xmm[index]) + } - enter_state.gps = gps; - enter_state.rip = rip; - enter_state.rflags = rflags.into(); // TODO: rflags means interrupt state changed?? + fn set_xmm(&mut self, index: usize, v: u128) -> Result<(), Self::Error> { + self.vp.runner.fx_state_mut().xmm[index] = v.to_ne_bytes(); Ok(()) } - fn get_xmm(&mut self, reg: usize) -> Result { - Ok(u128::from_ne_bytes(self.vp.runner.fx_state().xmm[reg])) + fn rip(&mut self) -> u64 { + let enter_state = self.vp.runner.tdx_enter_guest_state(); + enter_state.rip } - fn set_xmm(&mut self, reg: usize, value: u128) -> Result<(), Self::Error> { - self.vp.runner.fx_state_mut().xmm[reg] = value.to_ne_bytes(); - Ok(()) + fn set_rip(&mut self, v: u64) { + let enter_state = self.vp.runner.tdx_enter_guest_state_mut(); + enter_state.rip = v; + } + + fn segment(&mut self, index: Segment) -> x86defs::SegmentRegister { + let tdx_segment_index = match index { + Segment::CS => TdxSegmentReg::Cs, + Segment::ES => TdxSegmentReg::Es, + Segment::SS => TdxSegmentReg::Ss, + Segment::DS => TdxSegmentReg::Ds, + Segment::FS => TdxSegmentReg::Fs, + Segment::GS => TdxSegmentReg::Gs, + }; + let reg = match tdx_segment_index { + TdxSegmentReg::Cs => self.cache.segs[index as usize] + .get_or_insert_with(|| TdxExit(self.vp.runner.tdx_vp_enter_exit_info()).cs()), + _ => self.cache.segs[index as usize] + .get_or_insert_with(|| self.vp.read_segment(self.vtl, tdx_segment_index)), + }; + (*reg).into() + } + + fn efer(&mut self) -> u64 { + self.vp.backing.vtls[self.vtl].efer + } + + fn cr0(&mut self) -> u64 { + let reg = self + .cache + .cr0 + .get_or_insert_with(|| self.vp.backing.vtls[self.vtl].cr0.read(&self.vp.runner)); + *reg + } + + fn rflags(&mut self) -> RFlags { + let enter_state = self.vp.runner.tdx_enter_guest_state(); + enter_state.rflags.into() + } + + fn set_rflags(&mut self, v: RFlags) { + let enter_state = self.vp.runner.tdx_enter_guest_state_mut(); + enter_state.rflags = v.into(); } fn instruction_bytes(&self) -> &[u8] { @@ -2329,8 +2361,8 @@ impl EmulatorSupport for UhEmulationState<'_, '_, T, TdxBacked> { _gpa: u64, _mode: TranslateMode, ) -> Result<(), virt_support_x86emu::emulate::EmuCheckVtlAccessError> { - // TODO TDX GUEST VSM: VTL1 not supported // Lock Vtl TLB + // TODO TDX GUEST VSM: VTL1 not yet supported Ok(()) } From 2060465eef29ccfa857524f6bb7d26054638b544 Mon Sep 17 00:00:00 2001 From: Chakradhar Kotamraju Date: Fri, 17 Jan 2025 10:00:58 -0700 Subject: [PATCH 4/6] Replaced TODO TDX comments with the respective issue items. --- openhcl/hcl/src/ioctl.rs | 2 + openhcl/openhcl_boot/src/arch/x86_64/tdx.rs | 1 + openhcl/openhcl_boot/src/main.rs | 9 +++ openhcl/underhill_mem/src/lib.rs | 6 ++ openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs | 2 + openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs | 9 ++- openhcl/virt_mshv_vtl/src/lib.rs | 9 ++- .../src/processor/hardware_cvm/mod.rs | 2 +- .../virt_mshv_vtl/src/processor/tdx/mod.rs | 62 +++++++++---------- vm/hv1/hv1_emulator/src/cpuid.rs | 1 + vm/x86/tdcall/src/lib.rs | 5 ++ 11 files changed, 74 insertions(+), 34 deletions(-) diff --git a/openhcl/hcl/src/ioctl.rs b/openhcl/hcl/src/ioctl.rs index db0a85dc7..d9b1cbaa9 100644 --- a/openhcl/hcl/src/ioctl.rs +++ b/openhcl/hcl/src/ioctl.rs @@ -2797,6 +2797,7 @@ impl Hcl { IsolationType::Snp => hvdef::HvRegisterVsmCapabilities::new() .with_deny_lower_vtl_startup(caps.deny_lower_vtl_startup()) .with_intercept_page_available(caps.intercept_page_available()), + // Issue #560. Figure out what these values should be. IsolationType::Tdx => hvdef::HvRegisterVsmCapabilities::new() .with_deny_lower_vtl_startup(caps.deny_lower_vtl_startup()) .with_intercept_page_available(caps.intercept_page_available()), @@ -2897,6 +2898,7 @@ impl Hcl { target_vtl: HvInputVtl, ) -> Result<(), ApplyVtlProtectionsError> { if self.isolation.is_hardware_isolated() { + // Issue # 559 - required for vmbus relay monitor page support todo!(); } diff --git a/openhcl/openhcl_boot/src/arch/x86_64/tdx.rs b/openhcl/openhcl_boot/src/arch/x86_64/tdx.rs index 33427c554..a9890def6 100644 --- a/openhcl/openhcl_boot/src/arch/x86_64/tdx.rs +++ b/openhcl/openhcl_boot/src/arch/x86_64/tdx.rs @@ -113,6 +113,7 @@ pub fn get_tdx_tsc_reftime() -> Option { // This is first called by the BSP from openhcl_boot and the frequency // is saved in this gloabal variable. Subsequent calls use the global variable. if TSC_FREQUENCY.get() == 0 { + // Issue #432. Explore the option of getting frequency from CPUID. TSC_FREQUENCY.set(read_msr_tdcall(hvdef::HV_X64_MSR_TSC_FREQUENCY)); } diff --git a/openhcl/openhcl_boot/src/main.rs b/openhcl/openhcl_boot/src/main.rs index df8d4874a..d09508110 100644 --- a/openhcl/openhcl_boot/src/main.rs +++ b/openhcl/openhcl_boot/src/main.rs @@ -796,6 +796,15 @@ fn validate_vp_hw_ids(partition_info: &PartitionInfo) { use hypercall::HwId; if partition_info.isolation.is_hardware_isolated() { + // Issue #572: check and make sure the vp index ordering is in agreement with + // the host and hypervisor. We don't have a GHCB/GHCI page set up to communicate + // with the hypervisor here, so we can't easily perform the check. Since + // there is no security impact to this check, we can skip it for now; if + // the VM fails to boot, then this is due to a host contract violation. + // + // For TDX, we could use ENUM TOPOLOGY to validate that the TD VCPU + // indexes correspond to the APIC IDs in the right order. I am not + // certain if there are places where we depend on this mapping today. return; } diff --git a/openhcl/underhill_mem/src/lib.rs b/openhcl/underhill_mem/src/lib.rs index 2d398e4d3..798b8457a 100644 --- a/openhcl/underhill_mem/src/lib.rs +++ b/openhcl/underhill_mem/src/lib.rs @@ -1137,6 +1137,12 @@ mod mapping { } } IsolationType::Tdx => { + // Issue #573: implement acceptor.vtl_permissions + // For now, since guest vsm isn't enabled (therefore no VTL + // 1), and VTL 0 can't change its own permissions, the + // permissions should be the same as when VTL 2 initialized + // guest memory. + GpaVtlPermissions::new(IsolationType::Tdx, vtl, HV_MAP_GPA_PERMISSIONS_ALL) } }; diff --git a/openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs b/openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs index 7ab64b8e7..4c85cd599 100644 --- a/openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs +++ b/openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs @@ -59,6 +59,8 @@ trait CpuidArchInitializer { /// Processes extended state enumeration subleaves 2+. result is a helper /// for retrieving the result of a given subleaf. // + // (Issue #556: This will be to populate them, will need to update the + // signature to pass CpuidResults as a mutable reference) fn process_extended_state_subleaves( &self, results: &mut CpuidSubtable, diff --git a/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs b/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs index c4d645607..825247683 100644 --- a/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs +++ b/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs @@ -22,6 +22,8 @@ pub const TDX_REQUIRED_LEAVES: &[(CpuidFunction, Option)] = &[ (CpuidFunction::TileInformation, Some(0)), (CpuidFunction::TileInformation, Some(1)), (CpuidFunction::TmulInformation, Some(0)), + // Issue #562: The following aren't required from AMD. Need to double-check if + // they're required for TDX (CpuidFunction::CacheAndTlbInformation, None), (CpuidFunction::ExtendedFeatures, Some(1)), (CpuidFunction::CacheParameters, Some(0)), @@ -49,6 +51,7 @@ impl CpuidArchInitializer for TdxCpuidInitializer { } fn extended_max_function(&self) -> u32 { + // Issue #556: Check if this is the same value in the OS repo CpuidFunction::ExtendedIntelMaximum.0 } @@ -108,6 +111,7 @@ impl CpuidArchInitializer for TdxCpuidInitializer { } CpuidFunction::TmulInformation => { if subleaf == 0 { + // Issue #556: does this actually have subleaves? the spec says 1+ are reserved Some(CpuidResultMask::new( 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, true, )) @@ -160,6 +164,7 @@ impl CpuidArchInitializer for TdxCpuidInitializer { results: &mut CpuidSubtable, extended_state_mask: u64, ) -> Result<(), CpuidResultsError> { + // Issue #556: See HvlpPopulateExtendedStateCpuid let xfd_supported = if let Some(support) = results.get(&1).map( |CpuidResult { eax, @@ -183,7 +188,7 @@ impl CpuidArchInitializer for TdxCpuidInitializer { let result = Self::cpuid(CpuidFunction::ExtendedStateEnumeration.0, i); let result_xfd = cpuid::ExtendedStateEnumerationSubleafNEcx::from(result.ecx).xfd(); if xfd_supported && result_xfd { - // TODO TDX: update some maximum xfd value; see HvlpMaximumXfd + // Issue #556: update some maximum xfd value; see HvlpMaximumXfd } results.insert(i, result); @@ -200,6 +205,7 @@ impl CpuidArchInitializer for TdxCpuidInitializer { _address_space_sizes_ecx: cpuid::ExtendedAddressSpaceSizesEcx, _processor_topology_ebx: Option, // Will be None for Intel ) -> Result { + // Issue #556: see HvlpInitializeCpuidTopologyIntel and fix returned errors let vps_per_socket; if !version_and_features_edx.mt_per_socket() { if version_and_features_ebx.lps_per_package() > 1 { @@ -213,6 +219,7 @@ impl CpuidArchInitializer for TdxCpuidInitializer { vps_per_socket = version_and_features_ebx.lps_per_package(); } + // Issue #556: validation of leaf 0xB Ok(super::ExtendedTopologyResult { subleaf0: None, subleaf1: None, diff --git a/openhcl/virt_mshv_vtl/src/lib.rs b/openhcl/virt_mshv_vtl/src/lib.rs index b2eaa204a..60843b006 100644 --- a/openhcl/virt_mshv_vtl/src/lib.rs +++ b/openhcl/virt_mshv_vtl/src/lib.rs @@ -819,6 +819,9 @@ impl virt::Synic for UhPartition { } fn monitor_support(&self) -> Option<&dyn virt::SynicMonitor> { + // Issue #575: Disable monitor support for TDX and SNP as support + // for VTL2 protections is needed to emulate this page, which is not + // implemented yet. if self.inner.isolation.is_hardware_isolated() { None } else { @@ -1340,6 +1343,10 @@ impl<'a> UhProtoPartition<'a> { let is_hardware_isolated = isolation.is_hardware_isolated(); // Intercept Debug Exceptions + // Issue #558: This currently works on TDX because all Underhill TDs today + // have the debug policy bit set, allowing the hypervisor to install the + // intercept on behalf of the guest. In the future, Underhill should + // register for these intercepts itself. if params.intercept_debug_exceptions { if !cfg!(feature = "gdb") { return Err(Error::InvalidDebugConfiguration); @@ -1691,7 +1698,7 @@ impl UhProtoPartition<'_> { match params.isolation { IsolationType::None | IsolationType::Vbs => {} #[cfg(guest_arch = "x86_64")] - IsolationType::Tdx => return false, // TODO TDX GUEST_VSM + IsolationType::Tdx => return false, // Issue #557. GUEST_VSM #[cfg(guest_arch = "x86_64")] IsolationType::Snp => { if !params.env_cvm_guest_vsm { diff --git a/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs b/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs index 31aebec67..e53982dab 100644 --- a/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs +++ b/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs @@ -709,7 +709,7 @@ impl UhHypercallHandler<'_, '_, T, B> { } // TODO GUEST VSM: interrupt rewinding - // TODO TDX GUEST VSM: update execution mode + // Issue #687 GUEST VSM: update execution mode } } diff --git a/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs b/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs index d03bd890a..6270b621d 100644 --- a/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs +++ b/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs @@ -500,7 +500,7 @@ impl HardwareIsolatedBacking for TdxBacked { _source_vtl: GuestVtl, _target_vtl: GuestVtl, ) { - // TODO TDX GUEST VSM + // Issue #685: GUEST VSM todo!() } @@ -563,7 +563,7 @@ impl BackingPrivate for TdxBacked { params: super::private::BackingParams<'_, '_, Self>, _shared: &TdxBackedShared, ) -> Result { - // TODO TDX: TDX shares the vp context page for xmm registers only. It + // Issue #555: TDX shares the vp context page for xmm registers only. It // should probably move to its own page. // // FX regs and XMM registers are zero-initialized by the kernel. Set @@ -590,15 +590,15 @@ impl BackingPrivate for TdxBacked { *rflags = regs.rflags; *rip = regs.rip; - // TODO TDX: ssp is for shadow stack + // Issue #555: ssp is for shadow stack - // TODO TDX: direct overlay like snp? - // TODO TDX: lapic / APIC setup? + // direct overlay like snp? + // lapic / APIC setup? - // TODO TDX: see ValInitializeVplc - // TODO TDX: XCR_XFMEM setup? + // see ValInitializeVplc + // XCR_XFMEM setup? - // TODO TDX GUEST VSM: Presumably we need to duplicate much of this work + // GUEST VSM: Presumably we need to duplicate much of this work // when VTL 1 is enabled. // Configure L2 controls to permit shared memory. @@ -648,7 +648,7 @@ impl BackingPrivate for TdxBacked { // Allowed cr4 bits depend on the values allowed by the SEAM. // - // TODO TDX: Consider just using MSR kernel module instead of explicit + // Isse #555: Consider just using MSR kernel module instead of explicit // ioctl. let read_cr4 = hcl.read_vmx_cr4_fixed1(); let allowed_cr4_bits = (ShadowedRegister::Cr4.guest_owned_mask() | X64_CR4_MCE) & read_cr4; @@ -689,7 +689,7 @@ impl BackingPrivate for TdxBacked { let pfns = pfns_handle.base_pfn()..pfns_handle.base_pfn() + pfns_handle.size_pages(); let overlays: Vec<_> = pfns.collect(); - // TODO TDX: This needs to come from a private pool + // Issue #555: This needs to come from a private pool let flush_page = params .partition .shared_vis_pages_pool @@ -764,7 +764,7 @@ impl BackingPrivate for TdxBacked { } fn init(this: &mut UhProcessor<'_, Self>) { - // TODO TDX GUEST VSM: Presumably we need to duplicate much of this work + // Issue #555 GUEST VSM: Presumably we need to duplicate much of this work // when VTL 1 is enabled. // Configure the synic overlays. @@ -862,7 +862,7 @@ impl BackingPrivate for TdxBacked { this: &mut UhProcessor<'_, Self>, _dev: &impl CpuIo, ) -> Result { - // TODO TDX GUEST VSM + // Issue # 686: GUEST VSM this.hcvm_handle_cross_vtl_interrupts(|_this, _vtl, _check_rflags| false) } @@ -888,9 +888,9 @@ impl UhProcessor<'_, TdxBacked> { /// poll retried. fn try_poll_apic(&mut self, vtl: GuestVtl, scan_irr: bool) -> Result { // Check for interrupt requests from the host and kernel IPI offload. - // TODO TDX GUEST VSM supporting VTL 1 proxy irrs requires kernel changes + // Issue #554: GUEST VSM supporting VTL 1 proxy irrs requires kernel changes if vtl == GuestVtl::Vtl0 { - // TODO TDX: filter proxy IRRs by setting the `proxy_irr_blocked` field of the run page + // Issue #554: filter proxy IRRs by setting the `proxy_irr_blocked` field of the run page if let Some(irr) = self.runner.proxy_irr() { // We can't put the interrupts directly on the APIC page because we might need // to clear the tmr state. This can happen if a vector was previously used for a level @@ -1460,7 +1460,7 @@ impl UhProcessor<'_, TdxBacked> { // otherwise the interrupt will be lost and the guest left in a bad // state. // - // TODO TDX: Unclear what kind of exits these would be, but they + // Issue #553: Unclear what kind of exits these would be, but they // should be spurious EPT exits. Can we validate or assert that // somehow? If we were to somehow call some other path which would // set interruption_information before we inject this one, we would @@ -1691,7 +1691,7 @@ impl UhProcessor<'_, TdxBacked> { VmxExit::HLT_INSTRUCTION => { self.backing.cvm.lapics[intercepted_vtl].activity = MpState::Halted; - // TODO TDX: see lots of these exits while waiting at frontpage. + // Issue #688: see lots of these exits while waiting at frontpage. // Probably expected, given we will still get L1 timer // interrupts? self.clear_interrupt_shadow(intercepted_vtl); @@ -1769,7 +1769,7 @@ impl UhProcessor<'_, TdxBacked> { &mut self.backing.vtls[intercepted_vtl].exit_stats.wbinvd } VmxExit::EPT_VIOLATION => { - // TODO TDX: If this is an access to a shared gpa, we need to + // Issue #689: If this is an access to a shared gpa, we need to // check the intercept page to see if this is a real exit or // spurious. This exit is only real if the hypervisor has // delivered an intercept message for this GPA. @@ -2043,14 +2043,14 @@ impl UhProcessor<'_, TdxBacked> { } fn read_msr_cvm(&self, msr: u32, vtl: GuestVtl) -> Result { - // TODO TDX: port remaining tdx and common values + // Issue #551: port remaining tdx and common values // - // TODO TDX: consider if this can be shared with SnpBacked's + // Consider if this can be shared with SnpBacked's // implementation. For the most part other than Intel/TDX specific // registers, MSR handling should be the same. match msr { - // TODO TDX: LIFTED FROM WHP + // Issue #551: LIFTED FROM WHP x86defs::X86X_IA32_MSR_PLATFORM_ID => { // Windows requires accessing this to boot. WHP // used to pass this through to the hardware, @@ -2207,7 +2207,7 @@ impl UhProcessor<'_, TdxBacked> { self.runner .write_vmcs32(vtl, seg.attributes(), !0, attributes.into()); - // TODO TDX: cache CS into last exit because last exit contains CS optionally? + // Issue #550: cache CS into last exit because last exit contains CS optionally? Ok(()) } @@ -2362,7 +2362,7 @@ impl X86EmulatorSupport for UhEmulationState<'_, '_, T, TdxBacked> { _mode: TranslateMode, ) -> Result<(), virt_support_x86emu::emulate::EmuCheckVtlAccessError> { // Lock Vtl TLB - // TODO TDX GUEST VSM: VTL1 not yet supported + // Issue #549 GUEST VSM: VTL1 not yet supported Ok(()) } @@ -2745,7 +2745,7 @@ impl UhHypercallHandler<'_, '_, T, TdxBacked> { hv1_hypercall::HvPostMessage, hv1_hypercall::HvSignalEvent, hv1_hypercall::HvExtQueryCapabilities, - // TODO TDX: copied from SNP, enable individually as needed. + // Issue #548: copied from SNP, enable individually as needed. // hv1_hypercall::HvGetVpRegisters, // hv1_hypercall::HvEnablePartitionVtl, ] @@ -2950,8 +2950,8 @@ impl AccessVpState for UhVpStateAccess<'_, '_, TdxBacked> { nmi_masked: interruptibility.blocked_by_nmi(), interrupt_shadow: interruptibility.blocked_by_sti() || interruptibility.blocked_by_movss(), - pending_event: None, // TODO TDX - pending_interruption: None, // TODO TDX + pending_event: None, // Issue #547 + pending_interruption: None, // Issue #547 }) } @@ -2961,8 +2961,8 @@ impl AccessVpState for UhVpStateAccess<'_, '_, TdxBacked> { nmi_pending, nmi_masked, interrupt_shadow, - pending_event: _, // TODO TDX - pending_interruption: _, // TODO TDX + pending_event: _, // Issue #547 + pending_interruption: _, // Issue #547 } = value; self.vp.backing.cvm.lapics[self.vtl].activity = mp_state; self.vp.backing.cvm.lapics[self.vtl].nmi_pending = nmi_pending; @@ -3032,14 +3032,14 @@ impl AccessVpState for UhVpStateAccess<'_, '_, TdxBacked> { fn mtrrs(&mut self) -> Result { Ok(vp::Mtrrs { - msr_mtrr_def_type: 0, // TODO TDX: MTRRs - fixed: [0; 11], // TODO TDX: MTRRs - variable: [0; 16], // TODO TDX: MTRRs + msr_mtrr_def_type: 0, // Issue #547: MTRRs + fixed: [0; 11], // Issue #547: MTRRs + variable: [0; 16], // Issue #547: MTRRs }) } fn set_mtrrs(&mut self, _value: &vp::Mtrrs) -> Result<(), Self::Error> { - // TODO TDX: MTRRs + // Issue #547: MTRRs Ok(()) } diff --git a/vm/hv1/hv1_emulator/src/cpuid.rs b/vm/hv1/hv1_emulator/src/cpuid.rs index 5c2ef8382..0e9b471c3 100644 --- a/vm/hv1/hv1_emulator/src/cpuid.rs +++ b/vm/hv1/hv1_emulator/src/cpuid.rs @@ -129,6 +129,7 @@ pub fn hv_cpuid_leaves( .with_use_apic_msrs(use_apic_msrs); if hardware_isolated { + // Issue #546: Process TDX isolation type when it's ready if isolation == IsolationType::Snp { enlightenments = enlightenments .with_use_hypercall_for_remote_flush_and_local_flush_entire(true); diff --git a/vm/x86/tdcall/src/lib.rs b/vm/x86/tdcall/src/lib.rs index e109a9d77..e504edf5e 100644 --- a/vm/x86/tdcall/src/lib.rs +++ b/vm/x86/tdcall/src/lib.rs @@ -357,6 +357,8 @@ pub fn tdcall_page_attr_wr( let output = call.tdcall(input); + // Issue #545: RCX and RDX also contain info that could be returned + match output.rax.code() { TdCallResultCode::SUCCESS => Ok(()), val => Err(val), @@ -390,6 +392,7 @@ fn set_page_attr( /// The error returned by [`accept_pages`]. #[derive(Debug)] pub enum AcceptPagesError { + // Issue #545: Add better error types /// Unknown error type. Unknown(TdCallResultCode), /// Setting page attributes failed after accepting, @@ -571,6 +574,8 @@ pub fn tdcall_map_gpa( let output = call.tdcall(input); + // Issue #545: check rax return code + let result = TdVmCallR10Result(output.r10); match result { From 938fe9337c4191dd775d989fbeb6b161cfeed726 Mon Sep 17 00:00:00 2001 From: Chakradhar Kotamraju Date: Fri, 17 Jan 2025 13:24:29 -0700 Subject: [PATCH 5/6] Added TODO comments back along with their issue numbers --- openhcl/hcl/src/ioctl.rs | 4 +- openhcl/openhcl_boot/src/arch/x86_64/tdx.rs | 2 +- openhcl/openhcl_boot/src/main.rs | 4 +- openhcl/underhill_mem/src/lib.rs | 4 +- openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs | 4 +- openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs | 16 ++--- openhcl/virt_mshv_vtl/src/lib.rs | 10 +-- .../src/processor/hardware_cvm/mod.rs | 2 +- .../virt_mshv_vtl/src/processor/tdx/mod.rs | 64 +++++++++---------- vm/hv1/hv1_emulator/src/cpuid.rs | 2 +- vm/x86/tdcall/src/lib.rs | 6 +- vm/x86/x86defs/src/tdx.rs | 4 +- 12 files changed, 59 insertions(+), 63 deletions(-) diff --git a/openhcl/hcl/src/ioctl.rs b/openhcl/hcl/src/ioctl.rs index d9b1cbaa9..d98819869 100644 --- a/openhcl/hcl/src/ioctl.rs +++ b/openhcl/hcl/src/ioctl.rs @@ -2797,7 +2797,7 @@ impl Hcl { IsolationType::Snp => hvdef::HvRegisterVsmCapabilities::new() .with_deny_lower_vtl_startup(caps.deny_lower_vtl_startup()) .with_intercept_page_available(caps.intercept_page_available()), - // Issue #560. Figure out what these values should be. + // TODO TDX: Figure out what these values should be. (Issue #560) IsolationType::Tdx => hvdef::HvRegisterVsmCapabilities::new() .with_deny_lower_vtl_startup(caps.deny_lower_vtl_startup()) .with_intercept_page_available(caps.intercept_page_available()), @@ -2898,7 +2898,7 @@ impl Hcl { target_vtl: HvInputVtl, ) -> Result<(), ApplyVtlProtectionsError> { if self.isolation.is_hardware_isolated() { - // Issue # 559 - required for vmbus relay monitor page support + // TODO SNP TODO TDX - required for vmbus relay monitor page support (Issue #559) todo!(); } diff --git a/openhcl/openhcl_boot/src/arch/x86_64/tdx.rs b/openhcl/openhcl_boot/src/arch/x86_64/tdx.rs index a9890def6..28bda1248 100644 --- a/openhcl/openhcl_boot/src/arch/x86_64/tdx.rs +++ b/openhcl/openhcl_boot/src/arch/x86_64/tdx.rs @@ -113,7 +113,7 @@ pub fn get_tdx_tsc_reftime() -> Option { // This is first called by the BSP from openhcl_boot and the frequency // is saved in this gloabal variable. Subsequent calls use the global variable. if TSC_FREQUENCY.get() == 0 { - // Issue #432. Explore the option of getting frequency from CPUID. + // TODO TDX: Explore the option of getting frequency from CPUID. (Issue #432) TSC_FREQUENCY.set(read_msr_tdcall(hvdef::HV_X64_MSR_TSC_FREQUENCY)); } diff --git a/openhcl/openhcl_boot/src/main.rs b/openhcl/openhcl_boot/src/main.rs index d09508110..b92490b2c 100644 --- a/openhcl/openhcl_boot/src/main.rs +++ b/openhcl/openhcl_boot/src/main.rs @@ -796,7 +796,7 @@ fn validate_vp_hw_ids(partition_info: &PartitionInfo) { use hypercall::HwId; if partition_info.isolation.is_hardware_isolated() { - // Issue #572: check and make sure the vp index ordering is in agreement with + // TODO TDX SNP: check and make sure the vp index ordering is in agreement with // the host and hypervisor. We don't have a GHCB/GHCI page set up to communicate // with the hypervisor here, so we can't easily perform the check. Since // there is no security impact to this check, we can skip it for now; if @@ -804,7 +804,7 @@ fn validate_vp_hw_ids(partition_info: &PartitionInfo) { // // For TDX, we could use ENUM TOPOLOGY to validate that the TD VCPU // indexes correspond to the APIC IDs in the right order. I am not - // certain if there are places where we depend on this mapping today. + // certain if there are places where we depend on this mapping today. (Issue #572) return; } diff --git a/openhcl/underhill_mem/src/lib.rs b/openhcl/underhill_mem/src/lib.rs index 798b8457a..9d19a7faa 100644 --- a/openhcl/underhill_mem/src/lib.rs +++ b/openhcl/underhill_mem/src/lib.rs @@ -1137,11 +1137,11 @@ mod mapping { } } IsolationType::Tdx => { - // Issue #573: implement acceptor.vtl_permissions + // TODO TDX: implement acceptor.vtl_permissions // For now, since guest vsm isn't enabled (therefore no VTL // 1), and VTL 0 can't change its own permissions, the // permissions should be the same as when VTL 2 initialized - // guest memory. + // guest memory. (Issue #573) GpaVtlPermissions::new(IsolationType::Tdx, vtl, HV_MAP_GPA_PERMISSIONS_ALL) } diff --git a/openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs b/openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs index 4c85cd599..b6c48cc7a 100644 --- a/openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs +++ b/openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs @@ -59,8 +59,8 @@ trait CpuidArchInitializer { /// Processes extended state enumeration subleaves 2+. result is a helper /// for retrieving the result of a given subleaf. // - // (Issue #556: This will be to populate them, will need to update the - // signature to pass CpuidResults as a mutable reference) + // (TODO TDX: This will be to populate them, will need to update the + // signature to pass CpuidResults as a mutable reference. Issue #556) fn process_extended_state_subleaves( &self, results: &mut CpuidSubtable, diff --git a/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs b/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs index 825247683..d2ca0edc4 100644 --- a/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs +++ b/openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs @@ -22,8 +22,8 @@ pub const TDX_REQUIRED_LEAVES: &[(CpuidFunction, Option)] = &[ (CpuidFunction::TileInformation, Some(0)), (CpuidFunction::TileInformation, Some(1)), (CpuidFunction::TmulInformation, Some(0)), - // Issue #562: The following aren't required from AMD. Need to double-check if - // they're required for TDX + // TODO TDX: The following aren't required from AMD. Need to double-check if + // they're required for TDX (Issue #562) (CpuidFunction::CacheAndTlbInformation, None), (CpuidFunction::ExtendedFeatures, Some(1)), (CpuidFunction::CacheParameters, Some(0)), @@ -51,7 +51,7 @@ impl CpuidArchInitializer for TdxCpuidInitializer { } fn extended_max_function(&self) -> u32 { - // Issue #556: Check if this is the same value in the OS repo + // TODO TDX: Check if this is the same value in the OS repo (Issue #556) CpuidFunction::ExtendedIntelMaximum.0 } @@ -111,7 +111,7 @@ impl CpuidArchInitializer for TdxCpuidInitializer { } CpuidFunction::TmulInformation => { if subleaf == 0 { - // Issue #556: does this actually have subleaves? the spec says 1+ are reserved + // TODO TDX: does this actually have subleaves? the spec says 1+ are reserved (Issue #556) Some(CpuidResultMask::new( 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, true, )) @@ -164,7 +164,7 @@ impl CpuidArchInitializer for TdxCpuidInitializer { results: &mut CpuidSubtable, extended_state_mask: u64, ) -> Result<(), CpuidResultsError> { - // Issue #556: See HvlpPopulateExtendedStateCpuid + // TODO TDX: See HvlpPopulateExtendedStateCpuid (Issue #556) let xfd_supported = if let Some(support) = results.get(&1).map( |CpuidResult { eax, @@ -188,7 +188,7 @@ impl CpuidArchInitializer for TdxCpuidInitializer { let result = Self::cpuid(CpuidFunction::ExtendedStateEnumeration.0, i); let result_xfd = cpuid::ExtendedStateEnumerationSubleafNEcx::from(result.ecx).xfd(); if xfd_supported && result_xfd { - // Issue #556: update some maximum xfd value; see HvlpMaximumXfd + // TODO TDX: update some maximum xfd value; see HvlpMaximumXfd (Issue #556) } results.insert(i, result); @@ -205,7 +205,7 @@ impl CpuidArchInitializer for TdxCpuidInitializer { _address_space_sizes_ecx: cpuid::ExtendedAddressSpaceSizesEcx, _processor_topology_ebx: Option, // Will be None for Intel ) -> Result { - // Issue #556: see HvlpInitializeCpuidTopologyIntel and fix returned errors + // TODO TDX: see HvlpInitializeCpuidTopologyIntel and fix returned errors (Issue #556) let vps_per_socket; if !version_and_features_edx.mt_per_socket() { if version_and_features_ebx.lps_per_package() > 1 { @@ -219,7 +219,7 @@ impl CpuidArchInitializer for TdxCpuidInitializer { vps_per_socket = version_and_features_ebx.lps_per_package(); } - // Issue #556: validation of leaf 0xB + // TODO TDX: validation of leaf 0xB (Issue #556) Ok(super::ExtendedTopologyResult { subleaf0: None, subleaf1: None, diff --git a/openhcl/virt_mshv_vtl/src/lib.rs b/openhcl/virt_mshv_vtl/src/lib.rs index 60843b006..e7dbe435a 100644 --- a/openhcl/virt_mshv_vtl/src/lib.rs +++ b/openhcl/virt_mshv_vtl/src/lib.rs @@ -819,9 +819,9 @@ impl virt::Synic for UhPartition { } fn monitor_support(&self) -> Option<&dyn virt::SynicMonitor> { - // Issue #575: Disable monitor support for TDX and SNP as support + // TODO TDX TODO SNP: Disable monitor support for TDX and SNP as support // for VTL2 protections is needed to emulate this page, which is not - // implemented yet. + // implemented yet. (Issue #575) if self.inner.isolation.is_hardware_isolated() { None } else { @@ -1343,10 +1343,10 @@ impl<'a> UhProtoPartition<'a> { let is_hardware_isolated = isolation.is_hardware_isolated(); // Intercept Debug Exceptions - // Issue #558: This currently works on TDX because all Underhill TDs today + // TODO TDX: This currently works on TDX because all Underhill TDs today // have the debug policy bit set, allowing the hypervisor to install the // intercept on behalf of the guest. In the future, Underhill should - // register for these intercepts itself. + // register for these intercepts itself. (Issue #558) if params.intercept_debug_exceptions { if !cfg!(feature = "gdb") { return Err(Error::InvalidDebugConfiguration); @@ -1698,7 +1698,7 @@ impl UhProtoPartition<'_> { match params.isolation { IsolationType::None | IsolationType::Vbs => {} #[cfg(guest_arch = "x86_64")] - IsolationType::Tdx => return false, // Issue #557. GUEST_VSM + IsolationType::Tdx => return false, // TODO TDX GUEST_VSM (Issue #557) #[cfg(guest_arch = "x86_64")] IsolationType::Snp => { if !params.env_cvm_guest_vsm { diff --git a/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs b/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs index e53982dab..6958fe263 100644 --- a/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs +++ b/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs @@ -709,7 +709,7 @@ impl UhHypercallHandler<'_, '_, T, B> { } // TODO GUEST VSM: interrupt rewinding - // Issue #687 GUEST VSM: update execution mode + // TODO TDX GUEST VSM: update execution mode (Issue #687) } } diff --git a/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs b/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs index 6270b621d..7d31b0b6f 100644 --- a/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs +++ b/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs @@ -500,7 +500,7 @@ impl HardwareIsolatedBacking for TdxBacked { _source_vtl: GuestVtl, _target_vtl: GuestVtl, ) { - // Issue #685: GUEST VSM + // TODO TDX GUEST VSM (Issue #685) todo!() } @@ -563,8 +563,8 @@ impl BackingPrivate for TdxBacked { params: super::private::BackingParams<'_, '_, Self>, _shared: &TdxBackedShared, ) -> Result { - // Issue #555: TDX shares the vp context page for xmm registers only. It - // should probably move to its own page. + // TODO TDX: TDX shares the vp context page for xmm registers only. It + // should probably move to its own page. (Issue #555) // // FX regs and XMM registers are zero-initialized by the kernel. Set // them to the arch default. @@ -590,14 +590,12 @@ impl BackingPrivate for TdxBacked { *rflags = regs.rflags; *rip = regs.rip; - // Issue #555: ssp is for shadow stack - + // TODO TDX: Implement the following for vp context (Issue #555) + // ssp is for shadow stack // direct overlay like snp? // lapic / APIC setup? - // see ValInitializeVplc // XCR_XFMEM setup? - // GUEST VSM: Presumably we need to duplicate much of this work // when VTL 1 is enabled. @@ -689,7 +687,7 @@ impl BackingPrivate for TdxBacked { let pfns = pfns_handle.base_pfn()..pfns_handle.base_pfn() + pfns_handle.size_pages(); let overlays: Vec<_> = pfns.collect(); - // Issue #555: This needs to come from a private pool + // TODO TDX: This needs to come from a private pool (Issue #555) let flush_page = params .partition .shared_vis_pages_pool @@ -764,8 +762,8 @@ impl BackingPrivate for TdxBacked { } fn init(this: &mut UhProcessor<'_, Self>) { - // Issue #555 GUEST VSM: Presumably we need to duplicate much of this work - // when VTL 1 is enabled. + // TODO TDX GUEST VSM: Presumably we need to duplicate much of this work + // when VTL 1 is enabled. (Issue #555) // Configure the synic overlays. let pfns = &this.backing.direct_overlays_pfns; @@ -862,7 +860,7 @@ impl BackingPrivate for TdxBacked { this: &mut UhProcessor<'_, Self>, _dev: &impl CpuIo, ) -> Result { - // Issue # 686: GUEST VSM + // TODO TDX GUEST VSM (Issue #686) this.hcvm_handle_cross_vtl_interrupts(|_this, _vtl, _check_rflags| false) } @@ -888,9 +886,8 @@ impl UhProcessor<'_, TdxBacked> { /// poll retried. fn try_poll_apic(&mut self, vtl: GuestVtl, scan_irr: bool) -> Result { // Check for interrupt requests from the host and kernel IPI offload. - // Issue #554: GUEST VSM supporting VTL 1 proxy irrs requires kernel changes + // TODO TDX GUEST VSM supporting VTL 1 proxy irrs requires kernel changes (Issue #691) if vtl == GuestVtl::Vtl0 { - // Issue #554: filter proxy IRRs by setting the `proxy_irr_blocked` field of the run page if let Some(irr) = self.runner.proxy_irr() { // We can't put the interrupts directly on the APIC page because we might need // to clear the tmr state. This can happen if a vector was previously used for a level @@ -1460,11 +1457,11 @@ impl UhProcessor<'_, TdxBacked> { // otherwise the interrupt will be lost and the guest left in a bad // state. // - // Issue #553: Unclear what kind of exits these would be, but they + // TODO TDX: Unclear what kind of exits these would be, but they // should be spurious EPT exits. Can we validate or assert that // somehow? If we were to somehow call some other path which would // set interruption_information before we inject this one, we would - // lose this interrupt. + // lose this interrupt. (Issue #553) if next_interruption.valid() { tracing::debug!( ?next_interruption, @@ -1691,9 +1688,9 @@ impl UhProcessor<'_, TdxBacked> { VmxExit::HLT_INSTRUCTION => { self.backing.cvm.lapics[intercepted_vtl].activity = MpState::Halted; - // Issue #688: see lots of these exits while waiting at frontpage. + // TODO TDX: see lots of these exits while waiting at frontpage. // Probably expected, given we will still get L1 timer - // interrupts? + // interrupts? (Issue #688) self.clear_interrupt_shadow(intercepted_vtl); self.advance_to_next_instruction(); &mut self.backing.vtls[intercepted_vtl].exit_stats.hlt @@ -1769,10 +1766,9 @@ impl UhProcessor<'_, TdxBacked> { &mut self.backing.vtls[intercepted_vtl].exit_stats.wbinvd } VmxExit::EPT_VIOLATION => { - // Issue #689: If this is an access to a shared gpa, we need to - // check the intercept page to see if this is a real exit or - // spurious. This exit is only real if the hypervisor has - // delivered an intercept message for this GPA. + // TODO TDX: If this is an access to a shared gpa, then this + // is the result of hypervisor unable to handle it and + // delivered an intercept message for this GPA. (Issue #689) // // However, at this point the kernel has cleared that // information so some kind of redesign is required to figure @@ -2043,14 +2039,14 @@ impl UhProcessor<'_, TdxBacked> { } fn read_msr_cvm(&self, msr: u32, vtl: GuestVtl) -> Result { - // Issue #551: port remaining tdx and common values + // TODO TDX: port remaining tdx and common values (Issue #551) // // Consider if this can be shared with SnpBacked's // implementation. For the most part other than Intel/TDX specific // registers, MSR handling should be the same. match msr { - // Issue #551: LIFTED FROM WHP + // TODO TDX: LIFTED FROM WHP (Issue #551) x86defs::X86X_IA32_MSR_PLATFORM_ID => { // Windows requires accessing this to boot. WHP // used to pass this through to the hardware, @@ -2207,7 +2203,7 @@ impl UhProcessor<'_, TdxBacked> { self.runner .write_vmcs32(vtl, seg.attributes(), !0, attributes.into()); - // Issue #550: cache CS into last exit because last exit contains CS optionally? + // TODO TDX: cache CS into last exit because last exit contains CS optionally? (Issue #550) Ok(()) } @@ -2362,7 +2358,7 @@ impl X86EmulatorSupport for UhEmulationState<'_, '_, T, TdxBacked> { _mode: TranslateMode, ) -> Result<(), virt_support_x86emu::emulate::EmuCheckVtlAccessError> { // Lock Vtl TLB - // Issue #549 GUEST VSM: VTL1 not yet supported + // TODO TDX GUEST VSM: VTL1 not yet supported (Issue #549) Ok(()) } @@ -2745,7 +2741,7 @@ impl UhHypercallHandler<'_, '_, T, TdxBacked> { hv1_hypercall::HvPostMessage, hv1_hypercall::HvSignalEvent, hv1_hypercall::HvExtQueryCapabilities, - // Issue #548: copied from SNP, enable individually as needed. + // TODO TDX: copied from SNP, enable individually as needed. (Issue #548) // hv1_hypercall::HvGetVpRegisters, // hv1_hypercall::HvEnablePartitionVtl, ] @@ -2950,8 +2946,8 @@ impl AccessVpState for UhVpStateAccess<'_, '_, TdxBacked> { nmi_masked: interruptibility.blocked_by_nmi(), interrupt_shadow: interruptibility.blocked_by_sti() || interruptibility.blocked_by_movss(), - pending_event: None, // Issue #547 - pending_interruption: None, // Issue #547 + pending_event: None, // TODO TDX (Issue #547) + pending_interruption: None, // TODO TDX (Issue #547) }) } @@ -2961,8 +2957,8 @@ impl AccessVpState for UhVpStateAccess<'_, '_, TdxBacked> { nmi_pending, nmi_masked, interrupt_shadow, - pending_event: _, // Issue #547 - pending_interruption: _, // Issue #547 + pending_event: _, // TODO TDX (Issue #547) + pending_interruption: _, // TODO TDX (Issue #547) } = value; self.vp.backing.cvm.lapics[self.vtl].activity = mp_state; self.vp.backing.cvm.lapics[self.vtl].nmi_pending = nmi_pending; @@ -3032,14 +3028,14 @@ impl AccessVpState for UhVpStateAccess<'_, '_, TdxBacked> { fn mtrrs(&mut self) -> Result { Ok(vp::Mtrrs { - msr_mtrr_def_type: 0, // Issue #547: MTRRs - fixed: [0; 11], // Issue #547: MTRRs - variable: [0; 16], // Issue #547: MTRRs + msr_mtrr_def_type: 0, // TODO TDX: MTRRs (Issue #547) + fixed: [0; 11], // TODO TDX: MTRRs (Issue #547) + variable: [0; 16], // TODO TDX: MTRRs (Issue #547) }) } fn set_mtrrs(&mut self, _value: &vp::Mtrrs) -> Result<(), Self::Error> { - // Issue #547: MTRRs + // TODO TDX: MTRRs (Issue #547) Ok(()) } diff --git a/vm/hv1/hv1_emulator/src/cpuid.rs b/vm/hv1/hv1_emulator/src/cpuid.rs index 0e9b471c3..6e0459f3b 100644 --- a/vm/hv1/hv1_emulator/src/cpuid.rs +++ b/vm/hv1/hv1_emulator/src/cpuid.rs @@ -129,7 +129,7 @@ pub fn hv_cpuid_leaves( .with_use_apic_msrs(use_apic_msrs); if hardware_isolated { - // Issue #546: Process TDX isolation type when it's ready + // TODO TDX: Process TDX isolation type when it's ready (Issue #546) if isolation == IsolationType::Snp { enlightenments = enlightenments .with_use_hypercall_for_remote_flush_and_local_flush_entire(true); diff --git a/vm/x86/tdcall/src/lib.rs b/vm/x86/tdcall/src/lib.rs index e504edf5e..91a2b8a5b 100644 --- a/vm/x86/tdcall/src/lib.rs +++ b/vm/x86/tdcall/src/lib.rs @@ -357,7 +357,7 @@ pub fn tdcall_page_attr_wr( let output = call.tdcall(input); - // Issue #545: RCX and RDX also contain info that could be returned + // TODO TDX: RCX and RDX also contain info that could be returned (Issue #545) match output.rax.code() { TdCallResultCode::SUCCESS => Ok(()), @@ -392,7 +392,7 @@ fn set_page_attr( /// The error returned by [`accept_pages`]. #[derive(Debug)] pub enum AcceptPagesError { - // Issue #545: Add better error types + // TODO TDX: Add better error types (Issue #545) /// Unknown error type. Unknown(TdCallResultCode), /// Setting page attributes failed after accepting, @@ -574,7 +574,7 @@ pub fn tdcall_map_gpa( let output = call.tdcall(input); - // Issue #545: check rax return code + // TODO TDX: check rax return code (Issue #545) let result = TdVmCallR10Result(output.r10); diff --git a/vm/x86/x86defs/src/tdx.rs b/vm/x86/x86defs/src/tdx.rs index cfab14119..904e819a5 100644 --- a/vm/x86/x86defs/src/tdx.rs +++ b/vm/x86/x86defs/src/tdx.rs @@ -502,8 +502,8 @@ pub struct TdxExtendedFieldCode { /// Instruction info returned in r11 for a TDG.VP.ENTER call. #[bitfield(u64)] pub struct TdxInstructionInfo { - pub info: u32, - pub length: u32, + pub info: u32, // Information about the instruction that caused VM exit. Refer Intel SDM 28.2 + pub length: u32, // Length of the instruction that caused VM exit. } #[bitfield(u64)] From 21d789cbf0b91ef81cd08e2d1a59ef4dfee84128 Mon Sep 17 00:00:00 2001 From: Chakradhar Kotamraju Date: Fri, 17 Jan 2025 13:37:47 -0700 Subject: [PATCH 6/6] Corrected spelling in the comment --- openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs b/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs index 7d31b0b6f..1318020d7 100644 --- a/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs +++ b/openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs @@ -646,8 +646,8 @@ impl BackingPrivate for TdxBacked { // Allowed cr4 bits depend on the values allowed by the SEAM. // - // Isse #555: Consider just using MSR kernel module instead of explicit - // ioctl. + // TODO TDX: Consider just using MSR kernel module instead of explicit + // ioctl. (Issue #555) let read_cr4 = hcl.read_vmx_cr4_fixed1(); let allowed_cr4_bits = (ShadowedRegister::Cr4.guest_owned_mask() | X64_CR4_MCE) & read_cr4;