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