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 #[macro_use] 22 extern crate anyhow; 23 #[cfg(target_arch = "x86_64")] 24 #[macro_use] 25 extern crate log; 26 27 /// Architecture specific definitions 28 #[macro_use] 29 pub mod arch; 30 31 #[cfg(feature = "kvm")] 32 /// KVM implementation module 33 pub mod kvm; 34 35 /// Microsoft Hypervisor implementation module 36 #[cfg(all(feature = "mshv", target_arch = "x86_64"))] 37 pub mod mshv; 38 39 /// Hypevisor related module 40 pub mod hypervisor; 41 42 /// Vm related module 43 pub mod vm; 44 45 /// CPU related module 46 mod cpu; 47 48 /// Device related module 49 mod device; 50 51 pub use crate::hypervisor::{Hypervisor, HypervisorError}; 52 pub use cpu::{HypervisorCpuError, Vcpu, VmExit}; 53 pub use device::{Device, HypervisorDeviceError}; 54 #[cfg(feature = "tdx")] 55 pub use kvm::TdxCapabilities; 56 #[cfg(feature = "kvm")] 57 pub use kvm::*; 58 #[cfg(all(feature = "mshv", target_arch = "x86_64"))] 59 pub use mshv::*; 60 pub use vm::{DataMatch, HypervisorVmError, Vm}; 61 62 use std::sync::Arc; 63 64 pub fn new() -> std::result::Result<Arc<dyn Hypervisor>, HypervisorError> { 65 #[cfg(feature = "kvm")] 66 let hv = kvm::KvmHypervisor::new()?; 67 68 #[cfg(feature = "mshv")] 69 let hv = mshv::MshvHypervisor::new()?; 70 71 Ok(Arc::new(hv)) 72 } 73 74 // Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`. 75 fn vec_with_size_in_bytes<T: Default>(size_in_bytes: usize) -> Vec<T> { 76 let rounded_size = (size_in_bytes + size_of::<T>() - 1) / size_of::<T>(); 77 let mut v = Vec::with_capacity(rounded_size); 78 v.resize_with(rounded_size, T::default); 79 v 80 } 81 82 // The kvm API has many structs that resemble the following `Foo` structure: 83 // 84 // ``` 85 // #[repr(C)] 86 // struct Foo { 87 // some_data: u32 88 // entries: __IncompleteArrayField<__u32>, 89 // } 90 // ``` 91 // 92 // In order to allocate such a structure, `size_of::<Foo>()` would be too small because it would not 93 // include any space for `entries`. To make the allocation large enough while still being aligned 94 // for `Foo`, a `Vec<Foo>` is created. Only the first element of `Vec<Foo>` would actually be used 95 // as a `Foo`. The remaining memory in the `Vec<Foo>` is for `entries`, which must be contiguous 96 // with `Foo`. This function is used to make the `Vec<Foo>` with enough space for `count` entries. 97 use std::mem::size_of; 98 pub fn vec_with_array_field<T: Default, F>(count: usize) -> Vec<T> { 99 let element_space = count * size_of::<F>(); 100 let vec_size_bytes = size_of::<T>() + element_space; 101 vec_with_size_in_bytes(vec_size_bytes) 102 } 103