xref: /cloud-hypervisor/hypervisor/src/lib.rs (revision e5211a6e1d840e76a6cec0fba386977687e08603)
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