xref: /cloud-hypervisor/hypervisor/src/lib.rs (revision 9af2968a7dc47b89bf07ea9dc5e735084efcfa3a)
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 = "kvm")]
55 pub use kvm::*;
56 #[cfg(all(feature = "mshv", target_arch = "x86_64"))]
57 pub use mshv::*;
58 pub use vm::{DataMatch, HypervisorVmError, Vm};
59 
60 use std::sync::Arc;
61 
62 pub fn new() -> std::result::Result<Arc<dyn Hypervisor>, HypervisorError> {
63     #[cfg(feature = "kvm")]
64     let hv = kvm::KvmHypervisor::new()?;
65 
66     #[cfg(feature = "mshv")]
67     let hv = mshv::MshvHypervisor::new()?;
68 
69     Ok(Arc::new(hv))
70 }
71 
72 // Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`.
73 fn vec_with_size_in_bytes<T: Default>(size_in_bytes: usize) -> Vec<T> {
74     let rounded_size = (size_in_bytes + size_of::<T>() - 1) / size_of::<T>();
75     let mut v = Vec::with_capacity(rounded_size);
76     v.resize_with(rounded_size, T::default);
77     v
78 }
79 
80 // The kvm API has many structs that resemble the following `Foo` structure:
81 //
82 // ```
83 // #[repr(C)]
84 // struct Foo {
85 //    some_data: u32
86 //    entries: __IncompleteArrayField<__u32>,
87 // }
88 // ```
89 //
90 // In order to allocate such a structure, `size_of::<Foo>()` would be too small because it would not
91 // include any space for `entries`. To make the allocation large enough while still being aligned
92 // for `Foo`, a `Vec<Foo>` is created. Only the first element of `Vec<Foo>` would actually be used
93 // as a `Foo`. The remaining memory in the `Vec<Foo>` is for `entries`, which must be contiguous
94 // with `Foo`. This function is used to make the `Vec<Foo>` with enough space for `count` entries.
95 use std::mem::size_of;
96 pub fn vec_with_array_field<T: Default, F>(count: usize) -> Vec<T> {
97     let element_space = count * size_of::<F>();
98     let vec_size_bytes = size_of::<T>() + element_space;
99     vec_with_size_in_bytes(vec_size_bytes)
100 }
101