diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index cda2c3f02..e3ec3e0c8 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -18,7 +18,10 @@ pub use x86_64::{CpuId, ExtendedControlRegisters, LapicState, MsrEntries, Xsave} /// Export generically-named wrappers of kvm-bindings for Unix-based platforms /// pub use { - kvm_bindings::kvm_fpu as FpuState, kvm_bindings::kvm_mp_state as MpState, + kvm_bindings::kvm_create_device as CreateDevice, kvm_bindings::kvm_fpu as FpuState, + kvm_bindings::kvm_irq_routing as IrqRouting, kvm_bindings::kvm_mp_state as MpState, kvm_bindings::kvm_regs as StandardRegisters, kvm_bindings::kvm_sregs as SpecialRegisters, - kvm_bindings::kvm_vcpu_events as VcpuEvents, kvm_ioctls::VcpuExit, + kvm_bindings::kvm_userspace_memory_region as MemoryRegion, + kvm_bindings::kvm_vcpu_events as VcpuEvents, kvm_ioctls::DeviceFd, kvm_ioctls::IoEventAddress, + kvm_ioctls::VcpuExit, }; diff --git a/hypervisor/src/lib.rs b/hypervisor/src/lib.rs index ccb84d6dc..78ba0e178 100644 --- a/hypervisor/src/lib.rs +++ b/hypervisor/src/lib.rs @@ -21,6 +21,9 @@ /// KVM implementation module pub mod kvm; +/// Vm related module +pub mod vm; + /// CPU related module mod cpu; diff --git a/hypervisor/src/vm.rs b/hypervisor/src/vm.rs new file mode 100644 index 000000000..2350f3173 --- /dev/null +++ b/hypervisor/src/vm.rs @@ -0,0 +1,144 @@ +// Copyright © 2019 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// +// Copyright © 2020, Microsoft Corporation +// +// Copyright 2018-2019 CrowdStrike, Inc. +// +// + +#[cfg(target_arch = "aarch64")] +use crate::aarch64::VcpuInit; +use crate::cpu::Vcpu; +use crate::{CreateDevice, DeviceFd, IoEventAddress, IrqRouting, MemoryRegion}; +use std::sync::Arc; +use thiserror::Error; +use vmm_sys_util::eventfd::EventFd; + +/// +/// I/O events data matches (32 or 64 bits). +/// +pub enum DataMatch { + DataMatch32(u32), + DataMatch64(u64), +} + +impl Into for DataMatch { + fn into(self) -> u64 { + match self { + DataMatch::DataMatch32(dm) => dm.into(), + DataMatch::DataMatch64(dm) => dm, + } + } +} + +#[derive(Error, Debug)] +/// +/// Enum for VM error +pub enum HypervisorVmError { + /// + /// Create Vcpu error + /// + #[error("Failed to create Vcpu: {0}")] + CreateVcpu(#[source] anyhow::Error), + /// + /// TSS address error + /// + #[error("Failed to set TSS address: {0}")] + SetTssAddress(#[source] anyhow::Error), + /// + /// Create interrupt controller error + /// + #[error("Failed to create interrupt controller: {0}")] + CreateIrq(#[source] anyhow::Error), + /// + /// Register interrupt event error + /// + #[error("Failed to register interrupt event: {0}")] + RegisterIrqFd(#[source] anyhow::Error), + /// + /// Un register interrupt event error + /// + #[error("Failed to unregister interrupt event: {0}")] + UnregisterIrqFd(#[source] anyhow::Error), + /// + /// Register IO event error + /// + #[error("Failed to register IO event: {0}")] + RegisterIoEvent(#[source] anyhow::Error), + /// + /// Unregister IO event error + /// + #[error("Failed to unregister IO event: {0}")] + UnregisterIoEvent(#[source] anyhow::Error), + /// + /// Set GSI routing error + /// + #[error("Failed to set GSI routing: {0}")] + SetGsiRouting(#[source] anyhow::Error), + /// + /// Set user memory error + /// + #[error("Failed to set user memory: {0}")] + SetUserMemory(#[source] anyhow::Error), + /// + /// Create device error + /// + #[error("Failed to set GSI routing: {0}")] + CreateDevice(#[source] anyhow::Error), + /// + /// Get preferred target error + /// + #[error("Failed to get preferred target: {0}")] + GetPreferredTarget(#[source] anyhow::Error), + /// + /// Enable split Irq error + /// + #[error("Failed to enable split Irq: {0}")] + EnableSplitIrq(#[source] anyhow::Error), +} +/// +/// Result type for returning from a function +/// +pub type Result = std::result::Result; + +/// +/// Trait to represent a Vm +/// +/// This crate provides a hypervisor-agnostic interfaces for Vm +/// +pub trait Vm: Send + Sync { + #[cfg(target_arch = "x86_64")] + /// Sets the address of the three-page region in the VM's address space. + fn set_tss_address(&self, offset: usize) -> Result<()>; + /// Creates an in-kernel interrupt controller. + fn create_irq_chip(&self) -> Result<()>; + /// Registers an event that will, when signaled, trigger the `gsi` IRQ. + fn register_irqfd(&self, fd: &EventFd, gsi: u32) -> Result<()>; + /// Unregister an event that will, when signaled, trigger the `gsi` IRQ. + fn unregister_irqfd(&self, fd: &EventFd, gsi: u32) -> Result<()>; + /// Creates a new KVM vCPU file descriptor and maps the memory corresponding + fn create_vcpu(&self, id: u8) -> Result>; + /// Registers an event to be signaled whenever a certain address is written to. + fn register_ioevent( + &self, + fd: &EventFd, + addr: &IoEventAddress, + datamatch: Option, + ) -> Result<()>; + /// Unregister an event from a certain address it has been previously registered to. + fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> Result<()>; + /// Sets the GSI routing table entries, overwriting any previously set + fn set_gsi_routing(&self, irq_routing: &IrqRouting) -> Result<()>; + /// Creates/modifies a guest physical memory slot. + fn set_user_memory_region(&self, user_memory_region: MemoryRegion) -> Result<()>; + /// Creates an emulated device in the kernel. + fn create_device(&self, device: &mut CreateDevice) -> Result; + /// Returns the preferred CPU target type which can be emulated by KVM on underlying host. + #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] + fn get_preferred_target(&self, kvi: &mut VcpuInit) -> Result<()>; + /// Enable split Irq capability + #[cfg(target_arch = "x86_64")] + fn enable_split_irq(&self) -> Result<()>; +}