diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index f7663dfe0..481a5bf33 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -47,6 +47,8 @@ use vmm_sys_util::eventfd::EventFd; pub mod x86_64; #[cfg(target_arch = "x86_64")] use crate::arch::x86::NUM_IOAPIC_PINS; +#[cfg(target_arch = "x86_64")] +use crate::ClockData; use crate::{ CpuState, IoEventAddress, MpState, UserMemoryRegion, USER_MEMORY_REGION_LOG_DIRTY, USER_MEMORY_REGION_READ, USER_MEMORY_REGION_WRITE, @@ -72,9 +74,9 @@ pub use kvm_bindings; #[cfg(feature = "tdx")] use kvm_bindings::KVMIO; pub use kvm_bindings::{ - kvm_create_device, kvm_device_type_KVM_DEV_TYPE_VFIO, kvm_irq_routing, kvm_irq_routing_entry, - kvm_mp_state, kvm_userspace_memory_region, KVM_IRQ_ROUTING_IRQCHIP, KVM_IRQ_ROUTING_MSI, - KVM_MEM_LOG_DIRTY_PAGES, KVM_MEM_READONLY, KVM_MSI_VALID_DEVID, + kvm_clock_data, kvm_create_device, kvm_device_type_KVM_DEV_TYPE_VFIO, kvm_irq_routing, + kvm_irq_routing_entry, kvm_mp_state, kvm_userspace_memory_region, KVM_IRQ_ROUTING_IRQCHIP, + KVM_IRQ_ROUTING_MSI, KVM_MEM_LOG_DIRTY_PAGES, KVM_MEM_READONLY, KVM_MSI_VALID_DEVID, }; #[cfg(target_arch = "aarch64")] use kvm_bindings::{ @@ -92,8 +94,7 @@ use vmm_sys_util::{ioctl::ioctl_with_val, ioctl_expr, ioctl_ioc_nr, ioctl_iowr_n /// Export generically-named wrappers of kvm-bindings for Unix-based platforms /// pub use { - kvm_bindings::kvm_clock_data as ClockData, kvm_bindings::kvm_create_device as CreateDevice, - kvm_bindings::kvm_device_attr as DeviceAttr, + kvm_bindings::kvm_create_device as CreateDevice, kvm_bindings::kvm_device_attr as DeviceAttr, kvm_bindings::kvm_irq_routing_entry as IrqRoutingEntry, kvm_bindings::kvm_run, kvm_bindings::kvm_vcpu_events as VcpuEvents, kvm_ioctls::DeviceFd, kvm_ioctls::VcpuExit, }; @@ -262,6 +263,25 @@ impl From for VcpuKvmState { } } +#[cfg(target_arch = "x86_64")] +impl From for ClockData { + fn from(d: kvm_clock_data) -> Self { + ClockData::Kvm(d) + } +} + +#[cfg(target_arch = "x86_64")] +impl From for kvm_clock_data { + fn from(ms: ClockData) -> Self { + match ms { + ClockData::Kvm(s) => s, + /* Needed in case other hypervisors are enabled */ + #[allow(unreachable_patterns)] + _ => panic!("CpuState is not valid"), + } + } +} + struct KvmDirtyLogSlot { slot: u32, guest_phys_addr: u64, @@ -624,15 +644,18 @@ impl vm::Vm for KvmVm { /// Retrieve guest clock. #[cfg(target_arch = "x86_64")] fn get_clock(&self) -> vm::Result { - self.fd + Ok(self + .fd .get_clock() - .map_err(|e| vm::HypervisorVmError::GetClock(e.into())) + .map_err(|e| vm::HypervisorVmError::GetClock(e.into()))? + .into()) } /// Set guest clock. #[cfg(target_arch = "x86_64")] fn set_clock(&self, data: &ClockData) -> vm::Result<()> { + let data = (*data).into(); self.fd - .set_clock(data) + .set_clock(&data) .map_err(|e| vm::HypervisorVmError::SetClock(e.into())) } /// Checks if a particular `Cap` is available. diff --git a/hypervisor/src/lib.rs b/hypervisor/src/lib.rs index fc27237e5..cec0990fc 100644 --- a/hypervisor/src/lib.rs +++ b/hypervisor/src/lib.rs @@ -59,7 +59,7 @@ pub use kvm::x86_64; pub use kvm::{aarch64, GicState}; // Aliased types exposed from both hypervisors #[cfg(feature = "kvm")] -pub use kvm::{ClockData, CreateDevice, DeviceAttr, DeviceFd, IrqRoutingEntry}; +pub use kvm::{CreateDevice, DeviceAttr, DeviceFd, IrqRoutingEntry}; #[cfg(all(feature = "mshv", target_arch = "x86_64"))] pub use mshv::x86_64; // Aliased types exposed from both hypervisors @@ -152,3 +152,24 @@ pub enum CpuState { #[cfg(all(feature = "mshv", target_arch = "x86_64"))] Mshv(mshv::VcpuMshvState), } + +#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)] +#[cfg(target_arch = "x86_64")] +pub enum ClockData { + #[cfg(feature = "kvm")] + Kvm(kvm_bindings::kvm_clock_data), + #[cfg(feature = "mshv")] + Mshv, /* MSHV does not supprt ClockData yet */ +} + +#[cfg(target_arch = "x86_64")] +impl ClockData { + pub fn reset_flags(&mut self) { + match self { + #[cfg(feature = "kvm")] + ClockData::Kvm(s) => s.flags = 0, + #[allow(unreachable_patterns)] + _ => {} + } + } +} diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index 93c5e2bb9..178e1bca6 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -23,7 +23,7 @@ use vm::DataMatch; pub mod x86_64; use crate::device; use crate::{ - CpuState, IoEventAddress, MpState, UserMemoryRegion, USER_MEMORY_REGION_EXECUTE, + ClockData, CpuState, IoEventAddress, MpState, UserMemoryRegion, USER_MEMORY_REGION_EXECUTE, USER_MEMORY_REGION_READ, USER_MEMORY_REGION_WRITE, }; use vmm_sys_util::eventfd::EventFd; @@ -1148,4 +1148,14 @@ impl vm::Vm for MshvVm { ) .map_err(|e| vm::HypervisorVmError::GetDirtyLog(e.into())) } + /// Retrieve guest clock. + #[cfg(target_arch = "x86_64")] + fn get_clock(&self) -> vm::Result { + Ok(ClockData::Mshv) + } + /// Set guest clock. + #[cfg(target_arch = "x86_64")] + fn set_clock(&self, _data: &ClockData) -> vm::Result<()> { + Ok(()) + } } diff --git a/hypervisor/src/vm.rs b/hypervisor/src/vm.rs index 783344415..ead0b0620 100644 --- a/hypervisor/src/vm.rs +++ b/hypervisor/src/vm.rs @@ -16,7 +16,7 @@ use crate::cpu::Vcpu; use crate::device::Device; #[cfg(feature = "tdx")] use crate::x86_64::CpuId; -#[cfg(all(feature = "kvm", target_arch = "x86_64"))] +#[cfg(target_arch = "x86_64")] use crate::ClockData; use crate::CreateDevice; use crate::UserMemoryRegion; @@ -324,10 +324,10 @@ pub trait Vm: Send + Sync { #[cfg(target_arch = "x86_64")] fn enable_sgx_attribute(&self, file: File) -> Result<()>; /// Retrieve guest clock. - #[cfg(all(feature = "kvm", target_arch = "x86_64"))] + #[cfg(target_arch = "x86_64")] fn get_clock(&self) -> Result; /// Set guest clock. - #[cfg(all(feature = "kvm", target_arch = "x86_64"))] + #[cfg(target_arch = "x86_64")] fn set_clock(&self, data: &ClockData) -> Result<()>; #[cfg(feature = "kvm")] /// Checks if a particular `Cap` is available. diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index a28323d55..facb5e00a 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -2564,8 +2564,7 @@ impl Pausable for Vm { .vm .get_clock() .map_err(|e| MigratableError::Pause(anyhow!("Could not get VM clock: {}", e)))?; - // Reset clock flags. - clock.flags = 0; + clock.reset_flags(); self.saved_clock = Some(clock); }