From 8a29e28040e4733b38169ea6902d87128942513c Mon Sep 17 00:00:00 2001 From: sluck <162204411+sluck-msft@users.noreply.github.com> Date: Fri, 24 Jan 2025 16:30:08 -0800 Subject: [PATCH] scope startvp handling to cvms --- openhcl/virt_mshv_vtl/src/lib.rs | 1 + .../src/processor/hardware_cvm/mod.rs | 67 +++++++++++++++++++ openhcl/virt_mshv_vtl/src/processor/mod.rs | 66 +++--------------- .../virt_mshv_vtl/src/processor/mshv/arm64.rs | 1 - .../virt_mshv_vtl/src/processor/mshv/x64.rs | 1 - .../virt_mshv_vtl/src/processor/snp/mod.rs | 7 ++ vm/hv1/hv1_emulator/src/cpuid.rs | 4 +- 7 files changed, 84 insertions(+), 63 deletions(-) diff --git a/openhcl/virt_mshv_vtl/src/lib.rs b/openhcl/virt_mshv_vtl/src/lib.rs index e412e3632b..3a6d4e93f4 100644 --- a/openhcl/virt_mshv_vtl/src/lib.rs +++ b/openhcl/virt_mshv_vtl/src/lib.rs @@ -653,6 +653,7 @@ impl WakeReason { // Convenient constants. const EXTINT: Self = Self::new().with_extint(true); const MESSAGE_QUEUES: Self = Self::new().with_message_queues(true); + #[cfg(guest_arch = "x86_64")] const HV_START_ENABLE_VP_VTL: Self = Self::new().with_hv_start_enable_vtl_vp(true); // StartVp/EnableVpVtl handling const INTCON: Self = Self::new().with_intcon(true); #[cfg(guest_arch = "x86_64")] 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 c391fa4453..28f2c17291 100644 --- a/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs +++ b/openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs @@ -942,6 +942,45 @@ impl hv1_hypercall::VtlReturn for UhHypercallHand } } +impl + hv1_hypercall::StartVirtualProcessor + for UhHypercallHandler<'_, '_, T, B> +{ + fn start_virtual_processor( + &mut self, + partition_id: u64, + target_vp: u32, + target_vtl: Vtl, + vp_context: &hvdef::hypercall::InitialVpContextX64, + ) -> HvResult<()> { + tracing::debug!( + vp_index = self.vp.vp_index().index(), + target_vp, + ?target_vtl, + "HvStartVirtualProcessor" + ); + + if partition_id != hvdef::HV_PARTITION_ID_SELF { + return Err(HvError::InvalidPartitionId); + } + + if target_vp == self.vp.vp_index().index() + || target_vp as usize >= self.vp.partition.vps.len() + { + return Err(HvError::InvalidVpIndex); + } + + let target_vtl = self.target_vtl_no_higher(target_vtl)?; + let target_vp = &self.vp.partition.vps[target_vp as usize]; + + // TODO CVM GUEST VSM: probably some validation on vtl1_enabled + *target_vp.hv_start_enable_vtl_vp[target_vtl].lock() = Some(Box::new(*vp_context)); + target_vp.wake(target_vtl, WakeReason::HV_START_ENABLE_VP_VTL); + + Ok(()) + } +} + impl hv1_hypercall::ModifyVtlProtectionMask for UhHypercallHandler<'_, '_, T, B> { @@ -1214,6 +1253,34 @@ impl UhProcessor<'_, B> { Ok(reprocessing_required) } + pub(crate) fn hcvm_handle_vp_start_enable_vtl( + &mut self, + vtl: GuestVtl, + ) -> Result<(), UhRunVpError> { + if let Some(context) = self.inner.hv_start_enable_vtl_vp[vtl].lock().take() { + tracing::debug!( + vp_index = self.inner.cpu_index, + ?vtl, + "starting vp with initial registers" + ); + hv1_emulator::hypercall::set_x86_vp_context( + &mut self.access_state(vtl.into()), + &context, + ) + .map_err(UhRunVpError::State)?; + + if vtl == GuestVtl::Vtl1 { + assert!(self.partition.isolation.is_hardware_isolated()); + // Should have already initialized the hv emulator for this vtl + assert!(self.backing.hv(vtl).is_some()); + + // TODO CVM GUEST VSM: Revisit during AP startup if we need to exit to VTL 1 here + } + } + + Ok(()) + } + fn get_vsm_vp_secure_config_vtl( &mut self, requesting_vtl: GuestVtl, diff --git a/openhcl/virt_mshv_vtl/src/processor/mod.rs b/openhcl/virt_mshv_vtl/src/processor/mod.rs index a0baa0d831..c5f6cdbde5 100644 --- a/openhcl/virt_mshv_vtl/src/processor/mod.rs +++ b/openhcl/virt_mshv_vtl/src/processor/mod.rs @@ -247,6 +247,13 @@ mod private { dev: &impl CpuIo, ) -> Result; + fn handle_vp_start_enable_vtl_wake( + _this: &mut UhProcessor<'_, Self>, + _vtl: GuestVtl, + ) -> Result<(), UhRunVpError> { + Ok(()) + } + fn inspect_extra(_this: &mut UhProcessor<'_, Self>, _resp: &mut inspect::Response<'_>) {} fn hv(&self, vtl: GuestVtl) -> Option<&ProcessorVtlHv>; @@ -915,26 +922,7 @@ impl<'a, T: Backing> UhProcessor<'a, T> { #[cfg(guest_arch = "x86_64")] if wake_reasons.hv_start_enable_vtl_vp() { - if let Some(context) = self.inner.hv_start_enable_vtl_vp[vtl].lock().take() { - tracing::debug!( - vp_index = self.inner.cpu_index, - ?vtl, - "starting vp with initial registers" - ); - hv1_emulator::hypercall::set_x86_vp_context( - &mut self.access_state(vtl.into()), - &context, - ) - .map_err(UhRunVpError::State)?; - - if vtl == GuestVtl::Vtl1 { - assert!(self.partition.isolation.is_hardware_isolated()); - // Should have already initialized the hv emulator for this vtl - assert!(self.backing.hv(vtl).is_some()); - - // TODO CVM GUEST VSM: Revisit during AP startup if we need to exit to VTL 1 here - } - } + T::handle_vp_start_enable_vtl_wake(self, vtl)?; } #[cfg(guest_arch = "x86_64")] @@ -1324,44 +1312,6 @@ impl Arm64RegisterState for UhHypercallHandler<'_, '_, T, } } -impl hv1_hypercall::StartVirtualProcessor - for UhHypercallHandler<'_, '_, T, B> -{ - fn start_virtual_processor( - &mut self, - partition_id: u64, - target_vp: u32, - target_vtl: Vtl, - vp_context: &hvdef::hypercall::InitialVpContextX64, - ) -> hvdef::HvResult<()> { - tracing::debug!( - vp_index = self.vp.vp_index().index(), - target_vp, - ?target_vtl, - "HvStartVirtualProcessor" - ); - - if partition_id != hvdef::HV_PARTITION_ID_SELF { - return Err(HvError::InvalidPartitionId); - } - - if target_vp == self.vp.vp_index().index() - || target_vp as usize >= self.vp.partition.vps.len() - { - return Err(HvError::InvalidVpIndex); - } - - let target_vtl = self.target_vtl_no_higher(target_vtl)?; - let target_vp = &self.vp.partition.vps[target_vp as usize]; - - // TODO CVM GUEST VSM: probably some validation on vtl1_enabled - *target_vp.hv_start_enable_vtl_vp[target_vtl].lock() = Some(Box::new(*vp_context)); - target_vp.wake(target_vtl, WakeReason::HV_START_ENABLE_VP_VTL); - - Ok(()) - } -} - impl hv1_hypercall::PostMessage for UhHypercallHandler<'_, '_, T, B> { fn post_message(&mut self, connection_id: u32, message: &[u8]) -> hvdef::HvResult<()> { tracing::trace!( diff --git a/openhcl/virt_mshv_vtl/src/processor/mshv/arm64.rs b/openhcl/virt_mshv_vtl/src/processor/mshv/arm64.rs index 460e9abeab..88c8af5580 100644 --- a/openhcl/virt_mshv_vtl/src/processor/mshv/arm64.rs +++ b/openhcl/virt_mshv_vtl/src/processor/mshv/arm64.rs @@ -705,7 +705,6 @@ impl UhHypercallHandler<'_, '_, T, HypervisorBackedArm64> { hv1_hypercall::HvPostMessage, hv1_hypercall::HvSignalEvent, hv1_hypercall::HvRetargetDeviceInterrupt, - hv1_hypercall::HvX64StartVirtualProcessor, hv1_hypercall::HvGetVpIndexFromApicId, ] ); diff --git a/openhcl/virt_mshv_vtl/src/processor/mshv/x64.rs b/openhcl/virt_mshv_vtl/src/processor/mshv/x64.rs index 8cb5b322e2..cdeb022035 100644 --- a/openhcl/virt_mshv_vtl/src/processor/mshv/x64.rs +++ b/openhcl/virt_mshv_vtl/src/processor/mshv/x64.rs @@ -1651,7 +1651,6 @@ impl UhHypercallHandler<'_, '_, T, HypervisorBackedX86> { hv1_hypercall::HvPostMessage, hv1_hypercall::HvSignalEvent, hv1_hypercall::HvRetargetDeviceInterrupt, - hv1_hypercall::HvX64StartVirtualProcessor, hv1_hypercall::HvGetVpIndexFromApicId, hv1_hypercall::HvSetVpRegisters, hv1_hypercall::HvModifyVtlProtectionMask diff --git a/openhcl/virt_mshv_vtl/src/processor/snp/mod.rs b/openhcl/virt_mshv_vtl/src/processor/snp/mod.rs index 8dc6612c64..4cf613db14 100644 --- a/openhcl/virt_mshv_vtl/src/processor/snp/mod.rs +++ b/openhcl/virt_mshv_vtl/src/processor/snp/mod.rs @@ -551,6 +551,13 @@ impl BackingPrivate for SnpBacked { fn untrusted_synic_mut(&mut self) -> Option<&mut ProcessorSynic> { None } + + fn handle_vp_start_enable_vtl_wake( + this: &mut UhProcessor<'_, Self>, + vtl: GuestVtl, + ) -> Result<(), UhRunVpError> { + this.hcvm_handle_vp_start_enable_vtl(vtl) + } } fn hv_seg_to_snp(val: &hvdef::HvX64SegmentRegister) -> SevSelector { diff --git a/vm/hv1/hv1_emulator/src/cpuid.rs b/vm/hv1/hv1_emulator/src/cpuid.rs index b744fe3ffd..cb27af5b84 100644 --- a/vm/hv1/hv1_emulator/src/cpuid.rs +++ b/vm/hv1/hv1_emulator/src/cpuid.rs @@ -42,10 +42,8 @@ pub fn hv_cpuid_leaves( .with_access_apic_msrs(true) .with_access_vp_runtime_msr(true) .with_access_partition_reference_tsc(true) - .with_start_virtual_processor(true) + .with_start_virtual_processor(hardware_isolated) .with_access_vsm(access_vsm) - // TODO GUEST_VSM: Not actually implemented yet, but this is - // needed for guest vsm bringup .with_enable_extended_gva_ranges_flush_va_list(access_vsm); if hardware_isolated {