hypervisor, vmm: Feature guard KVM specific code

There are some code base and function which are purely KVM specific for
now and we don't have those supports in mshv at the moment but we have plan
for the future. We are doing a feature guard with KVM. For example, KVM has
mp_state, cpu clock support,  which we don't have for mshv. In order to build
those code we are making the code base for KVM specific compilation.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
This commit is contained in:
Muminul Islam 2020-12-04 15:35:29 -08:00 committed by Samuel Ortiz
parent 47f59409db
commit 9ce6c3b75c
8 changed files with 36 additions and 24 deletions

View File

@ -272,10 +272,12 @@ pub trait Vcpu: Send + Sync {
/// Setup the model-specific registers (MSR) for this vCPU. /// Setup the model-specific registers (MSR) for this vCPU.
/// ///
fn set_msrs(&self, msrs: &MsrEntries) -> Result<usize>; fn set_msrs(&self, msrs: &MsrEntries) -> Result<usize>;
#[cfg(feature = "kvm")]
/// ///
/// Returns the vcpu's current "multiprocessing state". /// Returns the vcpu's current "multiprocessing state".
/// ///
fn get_mp_state(&self) -> Result<MpState>; fn get_mp_state(&self) -> Result<MpState>;
#[cfg(feature = "kvm")]
/// ///
/// Sets the vcpu's current "multiprocessing state". /// Sets the vcpu's current "multiprocessing state".
/// ///
@ -312,7 +314,7 @@ pub trait Vcpu: Send + Sync {
/// of the vcpu. /// of the vcpu.
/// ///
fn set_vcpu_events(&self, events: &VcpuEvents) -> Result<()>; fn set_vcpu_events(&self, events: &VcpuEvents) -> Result<()>;
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
/// ///
/// Let the guest know that it has been paused, which prevents from /// Let the guest know that it has been paused, which prevents from
/// potential soft lockups when being resumed. /// potential soft lockups when being resumed.

View File

@ -10,7 +10,7 @@
use crate::vm::Vm; use crate::vm::Vm;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use crate::x86_64::{CpuId, MsrList}; use crate::x86_64::{CpuId, MsrList};
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
use kvm_ioctls::Cap; use kvm_ioctls::Cap;
use std::sync::Arc; use std::sync::Arc;
@ -78,19 +78,22 @@ pub trait Hypervisor: Send + Sync {
/// Return a hypervisor-agnostic Vm trait object /// Return a hypervisor-agnostic Vm trait object
/// ///
fn create_vm(&self) -> Result<Arc<dyn Vm>>; fn create_vm(&self) -> Result<Arc<dyn Vm>>;
#[cfg(feature = "kvm")]
/// ///
/// Returns the size of the memory mapping required to use the vcpu's structures /// Returns the size of the memory mapping required to use the vcpu's structures
/// ///
fn get_vcpu_mmap_size(&self) -> Result<usize>; fn get_vcpu_mmap_size(&self) -> Result<usize>;
#[cfg(feature = "kvm")]
/// ///
/// Gets the recommended maximum number of VCPUs per VM. /// Gets the recommended maximum number of VCPUs per VM.
/// ///
fn get_max_vcpus(&self) -> Result<usize>; fn get_max_vcpus(&self) -> Result<usize>;
#[cfg(feature = "kvm")]
/// ///
/// Gets the recommended number of VCPUs per VM. /// Gets the recommended number of VCPUs per VM.
/// ///
fn get_nr_vcpus(&self) -> Result<usize>; fn get_nr_vcpus(&self) -> Result<usize>;
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
/// ///
/// Checks if a particular `Cap` is available. /// Checks if a particular `Cap` is available.
/// ///

View File

@ -28,6 +28,7 @@ extern crate serde_derive;
extern crate serde_json; extern crate serde_json;
extern crate thiserror; extern crate thiserror;
#[cfg(feature = "kvm")]
/// KVM implementation module /// KVM implementation module
pub mod kvm; pub mod kvm;
@ -49,6 +50,7 @@ mod device;
pub use crate::hypervisor::{Hypervisor, HypervisorError}; pub use crate::hypervisor::{Hypervisor, HypervisorError};
pub use cpu::{HypervisorCpuError, Vcpu, VmExit}; pub use cpu::{HypervisorCpuError, Vcpu, VmExit};
pub use device::{Device, HypervisorDeviceError}; pub use device::{Device, HypervisorDeviceError};
#[cfg(feature = "kvm")]
pub use kvm::*; pub use kvm::*;
pub use vm::{DataMatch, HypervisorVmError, Vm}; pub use vm::{DataMatch, HypervisorVmError, Vm};

View File

@ -12,10 +12,12 @@
use crate::aarch64::VcpuInit; use crate::aarch64::VcpuInit;
use crate::cpu::Vcpu; use crate::cpu::Vcpu;
use crate::device::Device; use crate::device::Device;
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
use crate::ClockData; use crate::ClockData;
#[cfg(feature = "kvm")]
use crate::KvmVmState as VmState; use crate::KvmVmState as VmState;
use crate::{CreateDevice, IoEventAddress, IrqRoutingEntry, MemoryRegion}; use crate::{CreateDevice, IoEventAddress, IrqRoutingEntry, MemoryRegion};
#[cfg(feature = "kvm")]
use kvm_ioctls::Cap; use kvm_ioctls::Cap;
use std::sync::Arc; use std::sync::Arc;
use thiserror::Error; use thiserror::Error;
@ -198,6 +200,7 @@ pub trait Vm: Send + Sync {
) -> MemoryRegion; ) -> MemoryRegion;
/// Creates/modifies a guest physical memory slot. /// Creates/modifies a guest physical memory slot.
fn set_user_memory_region(&self, user_memory_region: MemoryRegion) -> Result<()>; fn set_user_memory_region(&self, user_memory_region: MemoryRegion) -> Result<()>;
#[cfg(feature = "kvm")]
/// Creates an emulated device in the kernel. /// Creates an emulated device in the kernel.
fn create_device(&self, device: &mut CreateDevice) -> Result<Arc<dyn Device>>; fn create_device(&self, device: &mut CreateDevice) -> Result<Arc<dyn Device>>;
/// Returns the preferred CPU target type which can be emulated by KVM on underlying host. /// Returns the preferred CPU target type which can be emulated by KVM on underlying host.
@ -207,11 +210,12 @@ pub trait Vm: Send + Sync {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn enable_split_irq(&self) -> Result<()>; fn enable_split_irq(&self) -> Result<()>;
/// Retrieve guest clock. /// Retrieve guest clock.
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
fn get_clock(&self) -> Result<ClockData>; fn get_clock(&self) -> Result<ClockData>;
/// Set guest clock. /// Set guest clock.
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
fn set_clock(&self, data: &ClockData) -> Result<()>; fn set_clock(&self, data: &ClockData) -> Result<()>;
#[cfg(feature = "kvm")]
/// Checks if a particular `Cap` is available. /// Checks if a particular `Cap` is available.
fn check_extension(&self, c: Cap) -> bool; fn check_extension(&self, c: Cap) -> bool;
/// Create a device that is used for passthrough /// Create a device that is used for passthrough

View File

@ -1360,7 +1360,7 @@ impl Pausable for CpuManager {
for vcpu in self.vcpus.iter() { for vcpu in self.vcpus.iter() {
let mut vcpu = vcpu.lock().unwrap(); let mut vcpu = vcpu.lock().unwrap();
vcpu.pause()?; vcpu.pause()?;
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
if !self.config.kvm_hyperv { if !self.config.kvm_hyperv {
vcpu.vcpu.notify_guest_clock_paused().map_err(|e| { vcpu.vcpu.notify_guest_clock_paused().map_err(|e| {
MigratableError::Pause(anyhow!( MigratableError::Pause(anyhow!(
@ -1424,7 +1424,7 @@ impl Snapshottable for CpuManager {
impl Transportable for CpuManager {} impl Transportable for CpuManager {}
impl Migratable for CpuManager {} impl Migratable for CpuManager {}
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View File

@ -43,7 +43,7 @@ use devices::{
interrupt_controller, interrupt_controller::InterruptController, legacy::Serial, interrupt_controller, interrupt_controller::InterruptController, legacy::Serial,
HotPlugNotificationFlags, HotPlugNotificationFlags,
}; };
use hypervisor::kvm_ioctls; #[cfg(feature = "kvm")]
use hypervisor::kvm_ioctls::*; use hypervisor::kvm_ioctls::*;
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
use hypervisor::CpuState; use hypervisor::CpuState;
@ -181,7 +181,7 @@ pub enum DeviceManagerError {
AllocateIrq, AllocateIrq,
/// Cannot configure the IRQ. /// Cannot configure the IRQ.
Irq(kvm_ioctls::Error), Irq(vmm_sys_util::errno::Error),
/// Cannot allocate PCI BARs /// Cannot allocate PCI BARs
AllocateBars(pci::PciDeviceError), AllocateBars(pci::PciDeviceError),

View File

@ -325,6 +325,7 @@ where
} }
} }
#[cfg(feature = "kvm")]
pub mod kvm { pub mod kvm {
use super::*; use super::*;
use hypervisor::kvm::KVM_MSI_VALID_DEVID; use hypervisor::kvm::KVM_MSI_VALID_DEVID;

View File

@ -453,7 +453,7 @@ pub struct Vm {
#[cfg_attr(not(feature = "kvm"), allow(dead_code))] #[cfg_attr(not(feature = "kvm"), allow(dead_code))]
// The hypervisor abstracted virtual machine. // The hypervisor abstracted virtual machine.
vm: Arc<dyn hypervisor::Vm>, vm: Arc<dyn hypervisor::Vm>,
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
saved_clock: Option<hypervisor::ClockData>, saved_clock: Option<hypervisor::ClockData>,
#[cfg(feature = "acpi")] #[cfg(feature = "acpi")]
numa_nodes: NumaNodes, numa_nodes: NumaNodes,
@ -471,7 +471,7 @@ impl Vm {
reset_evt: EventFd, reset_evt: EventFd,
seccomp_action: &SeccompAction, seccomp_action: &SeccompAction,
hypervisor: Arc<dyn hypervisor::Hypervisor>, hypervisor: Arc<dyn hypervisor::Hypervisor>,
_saved_clock: Option<hypervisor::ClockData>, #[cfg(feature = "kvm")] _saved_clock: Option<hypervisor::ClockData>,
) -> Result<Self> { ) -> Result<Self> {
config config
.lock() .lock()
@ -550,7 +550,7 @@ impl Vm {
cpu_manager, cpu_manager,
memory_manager, memory_manager,
vm, vm,
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
saved_clock: _saved_clock, saved_clock: _saved_clock,
#[cfg(feature = "acpi")] #[cfg(feature = "acpi")]
numa_nodes, numa_nodes,
@ -631,7 +631,7 @@ impl Vm {
seccomp_action: &SeccompAction, seccomp_action: &SeccompAction,
hypervisor: Arc<dyn hypervisor::Hypervisor>, hypervisor: Arc<dyn hypervisor::Hypervisor>,
) -> Result<Self> { ) -> Result<Self> {
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
hypervisor.check_required_extensions().unwrap(); hypervisor.check_required_extensions().unwrap();
let vm = hypervisor.create_vm().unwrap(); let vm = hypervisor.create_vm().unwrap();
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
@ -664,6 +664,7 @@ impl Vm {
reset_evt, reset_evt,
seccomp_action, seccomp_action,
hypervisor, hypervisor,
#[cfg(feature = "kvm")]
None, None,
)?; )?;
@ -688,7 +689,7 @@ impl Vm {
seccomp_action: &SeccompAction, seccomp_action: &SeccompAction,
hypervisor: Arc<dyn hypervisor::Hypervisor>, hypervisor: Arc<dyn hypervisor::Hypervisor>,
) -> Result<Self> { ) -> Result<Self> {
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
hypervisor.check_required_extensions().unwrap(); hypervisor.check_required_extensions().unwrap();
let vm = hypervisor.create_vm().unwrap(); let vm = hypervisor.create_vm().unwrap();
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
@ -727,9 +728,7 @@ impl Vm {
reset_evt, reset_evt,
seccomp_action, seccomp_action,
hypervisor, hypervisor,
#[cfg(target_arch = "x86_64")] #[cfg(feature = "kvm")]
vm_snapshot.clock,
#[cfg(target_arch = "aarch64")]
None, None,
) )
} }
@ -741,7 +740,7 @@ impl Vm {
seccomp_action: &SeccompAction, seccomp_action: &SeccompAction,
hypervisor: Arc<dyn hypervisor::Hypervisor>, hypervisor: Arc<dyn hypervisor::Hypervisor>,
) -> Result<Self> { ) -> Result<Self> {
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
hypervisor.check_required_extensions().unwrap(); hypervisor.check_required_extensions().unwrap();
let vm = hypervisor.create_vm().unwrap(); let vm = hypervisor.create_vm().unwrap();
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
@ -764,6 +763,7 @@ impl Vm {
reset_evt, reset_evt,
seccomp_action, seccomp_action,
hypervisor, hypervisor,
#[cfg(feature = "kvm")]
None, None,
) )
} }
@ -1737,7 +1737,7 @@ impl Pausable for Vm {
.valid_transition(new_state) .valid_transition(new_state)
.map_err(|e| MigratableError::Pause(anyhow!("Invalid transition: {:?}", e)))?; .map_err(|e| MigratableError::Pause(anyhow!("Invalid transition: {:?}", e)))?;
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
{ {
let mut clock = self let mut clock = self
.vm .vm
@ -1767,7 +1767,7 @@ impl Pausable for Vm {
.map_err(|e| MigratableError::Resume(anyhow!("Invalid transition: {:?}", e)))?; .map_err(|e| MigratableError::Resume(anyhow!("Invalid transition: {:?}", e)))?;
self.cpu_manager.lock().unwrap().resume()?; self.cpu_manager.lock().unwrap().resume()?;
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
{ {
if let Some(clock) = &self.saved_clock { if let Some(clock) = &self.saved_clock {
self.vm.set_clock(clock).map_err(|e| { self.vm.set_clock(clock).map_err(|e| {
@ -1787,7 +1787,7 @@ impl Pausable for Vm {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct VmSnapshot { pub struct VmSnapshot {
pub config: Arc<Mutex<VmConfig>>, pub config: Arc<Mutex<VmConfig>>,
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
pub clock: Option<hypervisor::ClockData>, pub clock: Option<hypervisor::ClockData>,
pub state: Option<hypervisor::VmState>, pub state: Option<hypervisor::VmState>,
} }
@ -1813,7 +1813,7 @@ impl Snapshottable for Vm {
.map_err(|e| MigratableError::Snapshot(e.into()))?; .map_err(|e| MigratableError::Snapshot(e.into()))?;
let vm_snapshot_data = serde_json::to_vec(&VmSnapshot { let vm_snapshot_data = serde_json::to_vec(&VmSnapshot {
config: self.get_config(), config: self.get_config(),
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
clock: self.saved_clock, clock: self.saved_clock,
state: Some(vm_state), state: Some(vm_state),
}) })
@ -2016,7 +2016,7 @@ impl Transportable for Vm {
} }
impl Migratable for Vm {} impl Migratable for Vm {}
#[cfg(target_arch = "x86_64")] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;