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