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 //! A generic abstraction around hypervisor functionality 12 //! 13 //! This crate offers a trait abstraction for underlying hypervisors 14 //! 15 //! # Platform support 16 //! 17 //! - x86_64 18 //! - arm64 19 //! 20 21 #![allow(clippy::significant_drop_in_scrutinee)] 22 23 #[macro_use] 24 extern crate anyhow; 25 #[cfg(target_arch = "x86_64")] 26 #[macro_use] 27 extern crate log; 28 29 /// Architecture specific definitions 30 #[macro_use] 31 pub mod arch; 32 33 #[cfg(feature = "kvm")] 34 /// KVM implementation module 35 pub mod kvm; 36 37 /// Microsoft Hypervisor implementation module 38 #[cfg(all(feature = "mshv", target_arch = "x86_64"))] 39 pub mod mshv; 40 41 /// Hypevisor related module 42 mod hypervisor; 43 44 /// Vm related module 45 mod vm; 46 47 /// CPU related module 48 mod cpu; 49 50 /// Device related module 51 mod device; 52 53 pub use cpu::{HypervisorCpuError, Vcpu, VmExit}; 54 pub use device::{Device, HypervisorDeviceError}; 55 pub use hypervisor::{Hypervisor, HypervisorError}; 56 #[cfg(all(feature = "kvm", target_arch = "x86_64"))] 57 pub use kvm::x86_64; 58 #[cfg(all(feature = "kvm", target_arch = "aarch64"))] 59 pub use kvm::{aarch64, GicState}; 60 // Aliased types exposed from both hypervisors 61 #[cfg(feature = "kvm")] 62 pub use kvm::{CreateDevice, DeviceAttr, DeviceFd}; 63 #[cfg(all(feature = "mshv", target_arch = "x86_64"))] 64 pub use mshv::x86_64; 65 // Aliased types exposed from both hypervisors 66 #[cfg(all(feature = "mshv", target_arch = "x86_64"))] 67 pub use mshv::{CreateDevice, DeviceAttr, DeviceFd}; 68 use std::sync::Arc; 69 pub use vm::{ 70 DataMatch, HypervisorVmError, InterruptSourceConfig, LegacyIrqSourceConfig, MsiIrqSourceConfig, 71 Vm, VmOps, 72 }; 73 74 pub fn new() -> std::result::Result<Arc<dyn Hypervisor>, HypervisorError> { 75 #[cfg(feature = "kvm")] 76 let hv = kvm::KvmHypervisor::new()?; 77 78 #[cfg(feature = "mshv")] 79 let hv = mshv::MshvHypervisor::new()?; 80 81 Ok(Arc::new(hv)) 82 } 83 84 // Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`. 85 fn vec_with_size_in_bytes<T: Default>(size_in_bytes: usize) -> Vec<T> { 86 let rounded_size = (size_in_bytes + size_of::<T>() - 1) / size_of::<T>(); 87 let mut v = Vec::with_capacity(rounded_size); 88 v.resize_with(rounded_size, T::default); 89 v 90 } 91 92 // The kvm API has many structs that resemble the following `Foo` structure: 93 // 94 // ``` 95 // #[repr(C)] 96 // struct Foo { 97 // some_data: u32 98 // entries: __IncompleteArrayField<__u32>, 99 // } 100 // ``` 101 // 102 // In order to allocate such a structure, `size_of::<Foo>()` would be too small because it would not 103 // include any space for `entries`. To make the allocation large enough while still being aligned 104 // for `Foo`, a `Vec<Foo>` is created. Only the first element of `Vec<Foo>` would actually be used 105 // as a `Foo`. The remaining memory in the `Vec<Foo>` is for `entries`, which must be contiguous 106 // with `Foo`. This function is used to make the `Vec<Foo>` with enough space for `count` entries. 107 use std::mem::size_of; 108 pub fn vec_with_array_field<T: Default, F>(count: usize) -> Vec<T> { 109 let element_space = count * size_of::<F>(); 110 let vec_size_bytes = size_of::<T>() + element_space; 111 vec_with_size_in_bytes(vec_size_bytes) 112 } 113 114 /// 115 /// User memory region structure 116 /// 117 #[derive(Debug, Default, Eq, PartialEq)] 118 pub struct UserMemoryRegion { 119 pub slot: u32, 120 pub guest_phys_addr: u64, 121 pub memory_size: u64, 122 pub userspace_addr: u64, 123 pub flags: u32, 124 } 125 126 /// 127 /// Flags for user memory region 128 /// 129 pub const USER_MEMORY_REGION_READ: u32 = 1; 130 pub const USER_MEMORY_REGION_WRITE: u32 = 1 << 1; 131 pub const USER_MEMORY_REGION_EXECUTE: u32 = 1 << 2; 132 pub const USER_MEMORY_REGION_LOG_DIRTY: u32 = 1 << 3; 133 134 #[derive(Debug)] 135 pub enum MpState { 136 #[cfg(feature = "kvm")] 137 Kvm(kvm_bindings::kvm_mp_state), 138 #[cfg(all(feature = "mshv", target_arch = "x86_64"))] 139 Mshv, /* MSHV does not supprt MpState yet */ 140 } 141 142 #[derive(Debug, Clone, Copy)] 143 pub enum IoEventAddress { 144 Pio(u64), 145 Mmio(u64), 146 } 147 148 #[derive(Clone, serde::Serialize, serde::Deserialize)] 149 pub enum CpuState { 150 #[cfg(feature = "kvm")] 151 Kvm(kvm::VcpuKvmState), 152 #[cfg(all(feature = "mshv", target_arch = "x86_64"))] 153 Mshv(mshv::VcpuMshvState), 154 } 155 156 #[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)] 157 #[cfg(target_arch = "x86_64")] 158 pub enum ClockData { 159 #[cfg(feature = "kvm")] 160 Kvm(kvm_bindings::kvm_clock_data), 161 #[cfg(feature = "mshv")] 162 Mshv, /* MSHV does not supprt ClockData yet */ 163 } 164 165 #[cfg(target_arch = "x86_64")] 166 impl ClockData { 167 pub fn reset_flags(&mut self) { 168 match self { 169 #[cfg(feature = "kvm")] 170 ClockData::Kvm(s) => s.flags = 0, 171 #[allow(unreachable_patterns)] 172 _ => {} 173 } 174 } 175 } 176 177 #[derive(Copy, Clone)] 178 pub enum IrqRoutingEntry { 179 #[cfg(feature = "kvm")] 180 Kvm(kvm_bindings::kvm_irq_routing_entry), 181 #[cfg(feature = "mshv")] 182 Mshv(mshv_bindings::mshv_msi_routing_entry), 183 } 184