hypervisor: provide a generic ClockData structure

Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
Wei Liu 2022-07-14 14:16:49 +00:00 committed by Liu Wei
parent beb4f86b82
commit 4201bf4011
5 changed files with 68 additions and 15 deletions

View File

@ -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<CpuState> for VcpuKvmState {
}
}
#[cfg(target_arch = "x86_64")]
impl From<kvm_clock_data> for ClockData {
fn from(d: kvm_clock_data) -> Self {
ClockData::Kvm(d)
}
}
#[cfg(target_arch = "x86_64")]
impl From<ClockData> 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<ClockData> {
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.

View File

@ -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)]
_ => {}
}
}
}

View File

@ -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<ClockData> {
Ok(ClockData::Mshv)
}
/// Set guest clock.
#[cfg(target_arch = "x86_64")]
fn set_clock(&self, _data: &ClockData) -> vm::Result<()> {
Ok(())
}
}

View File

@ -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<ClockData>;
/// 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.

View File

@ -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);
}