1 // Copyright © 2019 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause 4 // 5 // Copyright © 2020, Microsoft Corporation 6 // 7 // Copyright 2018-2019 CrowdStrike, Inc. 8 // 9 // 10 11 #[cfg(target_arch = "aarch64")] 12 use crate::aarch64::VcpuInit; 13 use crate::cpu::Vcpu; 14 #[cfg(target_arch = "x86_64")] 15 use crate::ClockData; 16 use crate::{CreateDevice, DeviceFd, IoEventAddress, IrqRouting, MemoryRegion}; 17 use std::sync::Arc; 18 use thiserror::Error; 19 use vmm_sys_util::eventfd::EventFd; 20 21 /// 22 /// I/O events data matches (32 or 64 bits). 23 /// 24 pub enum DataMatch { 25 DataMatch32(u32), 26 DataMatch64(u64), 27 } 28 29 impl Into<u64> for DataMatch { 30 fn into(self) -> u64 { 31 match self { 32 DataMatch::DataMatch32(dm) => dm.into(), 33 DataMatch::DataMatch64(dm) => dm, 34 } 35 } 36 } 37 38 #[derive(Error, Debug)] 39 /// 40 /// Enum for VM error 41 pub enum HypervisorVmError { 42 /// 43 /// Create Vcpu error 44 /// 45 #[error("Failed to create Vcpu: {0}")] 46 CreateVcpu(#[source] anyhow::Error), 47 /// 48 /// TSS address error 49 /// 50 #[error("Failed to set TSS address: {0}")] 51 SetTssAddress(#[source] anyhow::Error), 52 /// 53 /// Create interrupt controller error 54 /// 55 #[error("Failed to create interrupt controller: {0}")] 56 CreateIrq(#[source] anyhow::Error), 57 /// 58 /// Register interrupt event error 59 /// 60 #[error("Failed to register interrupt event: {0}")] 61 RegisterIrqFd(#[source] anyhow::Error), 62 /// 63 /// Un register interrupt event error 64 /// 65 #[error("Failed to unregister interrupt event: {0}")] 66 UnregisterIrqFd(#[source] anyhow::Error), 67 /// 68 /// Register IO event error 69 /// 70 #[error("Failed to register IO event: {0}")] 71 RegisterIoEvent(#[source] anyhow::Error), 72 /// 73 /// Unregister IO event error 74 /// 75 #[error("Failed to unregister IO event: {0}")] 76 UnregisterIoEvent(#[source] anyhow::Error), 77 /// 78 /// Set GSI routing error 79 /// 80 #[error("Failed to set GSI routing: {0}")] 81 SetGsiRouting(#[source] anyhow::Error), 82 /// 83 /// Set user memory error 84 /// 85 #[error("Failed to set user memory: {0}")] 86 SetUserMemory(#[source] anyhow::Error), 87 /// 88 /// Create device error 89 /// 90 #[error("Failed to set GSI routing: {0}")] 91 CreateDevice(#[source] anyhow::Error), 92 /// 93 /// Get preferred target error 94 /// 95 #[error("Failed to get preferred target: {0}")] 96 GetPreferredTarget(#[source] anyhow::Error), 97 /// 98 /// Enable split Irq error 99 /// 100 #[error("Failed to enable split Irq: {0}")] 101 EnableSplitIrq(#[source] anyhow::Error), 102 /// 103 /// Get clock error 104 /// 105 #[error("Failed to get clock: {0}")] 106 GetClock(#[source] anyhow::Error), 107 /// 108 /// Set clock error 109 /// 110 #[error("Failed to set clock: {0}")] 111 SetClock(#[source] anyhow::Error), 112 } 113 /// 114 /// Result type for returning from a function 115 /// 116 pub type Result<T> = std::result::Result<T, HypervisorVmError>; 117 118 /// 119 /// Trait to represent a Vm 120 /// 121 /// This crate provides a hypervisor-agnostic interfaces for Vm 122 /// 123 pub trait Vm: Send + Sync { 124 #[cfg(target_arch = "x86_64")] 125 /// Sets the address of the three-page region in the VM's address space. 126 fn set_tss_address(&self, offset: usize) -> Result<()>; 127 /// Creates an in-kernel interrupt controller. 128 fn create_irq_chip(&self) -> Result<()>; 129 /// Registers an event that will, when signaled, trigger the `gsi` IRQ. 130 fn register_irqfd(&self, fd: &EventFd, gsi: u32) -> Result<()>; 131 /// Unregister an event that will, when signaled, trigger the `gsi` IRQ. 132 fn unregister_irqfd(&self, fd: &EventFd, gsi: u32) -> Result<()>; 133 /// Creates a new KVM vCPU file descriptor and maps the memory corresponding 134 fn create_vcpu(&self, id: u8) -> Result<Arc<dyn Vcpu>>; 135 /// Registers an event to be signaled whenever a certain address is written to. 136 fn register_ioevent( 137 &self, 138 fd: &EventFd, 139 addr: &IoEventAddress, 140 datamatch: Option<DataMatch>, 141 ) -> Result<()>; 142 /// Unregister an event from a certain address it has been previously registered to. 143 fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> Result<()>; 144 /// Sets the GSI routing table entries, overwriting any previously set 145 fn set_gsi_routing(&self, irq_routing: &IrqRouting) -> Result<()>; 146 /// Creates a memory region structure that can be used with set_user_memory_region 147 fn make_user_memory_region( 148 &self, 149 slot: u32, 150 guest_phys_addr: u64, 151 memory_size: u64, 152 userspace_addr: u64, 153 readonly: bool, 154 ) -> MemoryRegion; 155 /// Creates/modifies a guest physical memory slot. 156 fn set_user_memory_region(&self, user_memory_region: MemoryRegion) -> Result<()>; 157 /// Creates an emulated device in the kernel. 158 fn create_device(&self, device: &mut CreateDevice) -> Result<DeviceFd>; 159 /// Returns the preferred CPU target type which can be emulated by KVM on underlying host. 160 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 161 fn get_preferred_target(&self, kvi: &mut VcpuInit) -> Result<()>; 162 /// Enable split Irq capability 163 #[cfg(target_arch = "x86_64")] 164 fn enable_split_irq(&self) -> Result<()>; 165 /// Retrieve guest clock. 166 #[cfg(target_arch = "x86_64")] 167 fn get_clock(&self) -> Result<ClockData>; 168 /// Set guest clock. 169 #[cfg(target_arch = "x86_64")] 170 fn set_clock(&self, data: &ClockData) -> Result<()>; 171 } 172