xref: /cloud-hypervisor/hypervisor/src/lib.rs (revision b440cb7d2330770cd415b63544a371d4caa2db3a)
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 #![allow(clippy::significant_drop_in_scrutinee)]
22 
23 #[macro_use]
24 extern crate anyhow;
25 #[cfg(target_arch = "x86_64")]
26 #[macro_use]
27 extern crate log;
28 
29 /// Architecture specific definitions
30 #[macro_use]
31 pub mod arch;
32 
33 #[cfg(feature = "kvm")]
34 /// KVM implementation module
35 pub mod kvm;
36 
37 /// Microsoft Hypervisor implementation module
38 #[cfg(all(feature = "mshv", target_arch = "x86_64"))]
39 pub mod mshv;
40 
41 /// Hypevisor related module
42 mod hypervisor;
43 
44 /// Vm related module
45 mod vm;
46 
47 /// CPU related module
48 mod cpu;
49 
50 /// Device related module
51 mod device;
52 
53 pub use cpu::{HypervisorCpuError, Vcpu, VmExit};
54 pub use device::{Device, HypervisorDeviceError};
55 pub use hypervisor::{Hypervisor, HypervisorError};
56 #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
57 pub use kvm::x86_64;
58 #[cfg(all(feature = "kvm", target_arch = "aarch64"))]
59 pub use kvm::{aarch64, GicState};
60 // Aliased types exposed from both hypervisors
61 #[cfg(feature = "kvm")]
62 pub use kvm::{CreateDevice, DeviceAttr, DeviceFd};
63 #[cfg(all(feature = "mshv", target_arch = "x86_64"))]
64 pub use mshv::x86_64;
65 // Aliased types exposed from both hypervisors
66 #[cfg(all(feature = "mshv", target_arch = "x86_64"))]
67 pub use mshv::{CreateDevice, DeviceAttr, DeviceFd};
68 use std::sync::Arc;
69 pub use vm::{
70     DataMatch, HypervisorVmError, InterruptSourceConfig, LegacyIrqSourceConfig, MsiIrqSourceConfig,
71     Vm, VmOps,
72 };
73 
74 pub fn new() -> std::result::Result<Arc<dyn Hypervisor>, HypervisorError> {
75     #[cfg(feature = "kvm")]
76     let hv = kvm::KvmHypervisor::new()?;
77 
78     #[cfg(feature = "mshv")]
79     let hv = mshv::MshvHypervisor::new()?;
80 
81     Ok(Arc::new(hv))
82 }
83 
84 // Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`.
85 fn vec_with_size_in_bytes<T: Default>(size_in_bytes: usize) -> Vec<T> {
86     let rounded_size = (size_in_bytes + size_of::<T>() - 1) / size_of::<T>();
87     let mut v = Vec::with_capacity(rounded_size);
88     v.resize_with(rounded_size, T::default);
89     v
90 }
91 
92 // The kvm API has many structs that resemble the following `Foo` structure:
93 //
94 // ```
95 // #[repr(C)]
96 // struct Foo {
97 //    some_data: u32
98 //    entries: __IncompleteArrayField<__u32>,
99 // }
100 // ```
101 //
102 // In order to allocate such a structure, `size_of::<Foo>()` would be too small because it would not
103 // include any space for `entries`. To make the allocation large enough while still being aligned
104 // for `Foo`, a `Vec<Foo>` is created. Only the first element of `Vec<Foo>` would actually be used
105 // as a `Foo`. The remaining memory in the `Vec<Foo>` is for `entries`, which must be contiguous
106 // with `Foo`. This function is used to make the `Vec<Foo>` with enough space for `count` entries.
107 use std::mem::size_of;
108 pub fn vec_with_array_field<T: Default, F>(count: usize) -> Vec<T> {
109     let element_space = count * size_of::<F>();
110     let vec_size_bytes = size_of::<T>() + element_space;
111     vec_with_size_in_bytes(vec_size_bytes)
112 }
113 
114 ///
115 /// User memory region structure
116 ///
117 #[derive(Debug, Default, Eq, PartialEq)]
118 pub struct UserMemoryRegion {
119     pub slot: u32,
120     pub guest_phys_addr: u64,
121     pub memory_size: u64,
122     pub userspace_addr: u64,
123     pub flags: u32,
124 }
125 
126 ///
127 /// Flags for user memory region
128 ///
129 pub const USER_MEMORY_REGION_READ: u32 = 1;
130 pub const USER_MEMORY_REGION_WRITE: u32 = 1 << 1;
131 pub const USER_MEMORY_REGION_EXECUTE: u32 = 1 << 2;
132 pub const USER_MEMORY_REGION_LOG_DIRTY: u32 = 1 << 3;
133 
134 #[derive(Debug)]
135 pub enum MpState {
136     #[cfg(feature = "kvm")]
137     Kvm(kvm_bindings::kvm_mp_state),
138     #[cfg(all(feature = "mshv", target_arch = "x86_64"))]
139     Mshv, /* MSHV does not supprt MpState yet */
140 }
141 
142 #[derive(Debug, Clone, Copy)]
143 pub enum IoEventAddress {
144     Pio(u64),
145     Mmio(u64),
146 }
147 
148 #[derive(Clone, serde::Serialize, serde::Deserialize)]
149 pub enum CpuState {
150     #[cfg(feature = "kvm")]
151     Kvm(kvm::VcpuKvmState),
152     #[cfg(all(feature = "mshv", target_arch = "x86_64"))]
153     Mshv(mshv::VcpuMshvState),
154 }
155 
156 #[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
157 #[cfg(target_arch = "x86_64")]
158 pub enum ClockData {
159     #[cfg(feature = "kvm")]
160     Kvm(kvm_bindings::kvm_clock_data),
161     #[cfg(feature = "mshv")]
162     Mshv, /* MSHV does not supprt ClockData yet */
163 }
164 
165 #[cfg(target_arch = "x86_64")]
166 impl ClockData {
167     pub fn reset_flags(&mut self) {
168         match self {
169             #[cfg(feature = "kvm")]
170             ClockData::Kvm(s) => s.flags = 0,
171             #[allow(unreachable_patterns)]
172             _ => {}
173         }
174     }
175 }
176 
177 #[derive(Copy, Clone)]
178 pub enum IrqRoutingEntry {
179     #[cfg(feature = "kvm")]
180     Kvm(kvm_bindings::kvm_irq_routing_entry),
181     #[cfg(feature = "mshv")]
182     Mshv(mshv_bindings::mshv_msi_routing_entry),
183 }
184