Skip to content

Commit 1146fb7

Browse files
committed
Move hypervisor-related functions out of sandbox module
Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent 9cf7847 commit 1146fb7

File tree

5 files changed

+100
-119
lines changed

5 files changed

+100
-119
lines changed

src/hyperlight_host/src/hypervisor/hyperlight_vm.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ use crate::hypervisor::LinuxInterruptHandle;
4141
#[cfg(crashdump)]
4242
use crate::hypervisor::crashdump;
4343
use crate::hypervisor::regs::CommonSpecialRegisters;
44+
use crate::hypervisor::vm::HypervisorType;
4445
#[cfg(not(gdb))]
4546
use crate::hypervisor::vm::Vm;
47+
use crate::hypervisor::vm::get_available_hypervisor;
4648
#[cfg(kvm)]
4749
use crate::hypervisor::vm::kvm::KvmVm;
4850
#[cfg(mshv3)]
@@ -59,7 +61,6 @@ use crate::mem::shared_mem::HostSharedMemory;
5961
use crate::metrics::{METRIC_ERRONEOUS_VCPU_KICKS, METRIC_GUEST_CANCELLATION};
6062
use crate::sandbox::SandboxConfiguration;
6163
use crate::sandbox::host_funcs::FunctionRegistry;
62-
use crate::sandbox::hypervisor::{HypervisorType, get_available_hypervisor};
6364
use crate::sandbox::outb::handle_outb;
6465
#[cfg(feature = "mem_profile")]
6566
use crate::sandbox::trace::MemTraceInfo;

src/hyperlight_host/src/hypervisor/vm/mod.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use tracing::{Span, instrument};
2+
13
use crate::Result;
24
use crate::hypervisor::regs::{CommonFpu, CommonRegisters, CommonSpecialRegisters};
35
use crate::mem::memory_region::MemoryRegion;
@@ -12,6 +14,77 @@ pub(crate) mod mshv;
1214
#[cfg(target_os = "windows")]
1315
pub(crate) mod whp;
1416

17+
use std::sync::OnceLock;
18+
19+
static AVAILABLE_HYPERVISOR: OnceLock<Option<HypervisorType>> = OnceLock::new();
20+
21+
/// Returns which type of hypervisor is available, if any
22+
pub fn get_available_hypervisor() -> &'static Option<HypervisorType> {
23+
AVAILABLE_HYPERVISOR.get_or_init(|| {
24+
cfg_if::cfg_if! {
25+
if #[cfg(all(kvm, mshv3))] {
26+
// If both features are enabled, we need to determine hypervisor at runtime.
27+
// Currently /dev/kvm and /dev/mshv cannot exist on the same machine, so the first one
28+
// that works is guaranteed to be correct.
29+
if mshv::is_hypervisor_present() {
30+
Some(HypervisorType::Mshv)
31+
} else if kvm::is_hypervisor_present() {
32+
Some(HypervisorType::Kvm)
33+
} else {
34+
None
35+
}
36+
} else if #[cfg(kvm)] {
37+
if kvm::is_hypervisor_present() {
38+
Some(HypervisorType::Kvm)
39+
} else {
40+
None
41+
}
42+
} else if #[cfg(mshv3)] {
43+
if mshv::is_hypervisor_present() {
44+
Some(HypervisorType::Mshv)
45+
} else {
46+
None
47+
}
48+
} else if #[cfg(target_os = "windows")] {
49+
if whp::is_hypervisor_present() {
50+
Some(HypervisorType::Whp)
51+
} else {
52+
None
53+
}
54+
} else {
55+
None
56+
}
57+
}
58+
})
59+
}
60+
61+
/// Returns `true` if a suitable hypervisor is available.
62+
/// If this returns `false`, no hypervisor-backed sandboxes can be created.
63+
#[instrument(skip_all, parent = Span::current())]
64+
pub fn is_hypervisor_present() -> bool {
65+
get_available_hypervisor().is_some()
66+
}
67+
68+
/// The hypervisor types available for the current platform
69+
#[derive(PartialEq, Eq, Debug)]
70+
pub(crate) enum HypervisorType {
71+
#[cfg(kvm)]
72+
Kvm,
73+
74+
#[cfg(mshv3)]
75+
Mshv,
76+
77+
#[cfg(target_os = "windows")]
78+
Whp,
79+
}
80+
81+
// Compiler error if no hypervisor type is available
82+
#[cfg(not(any(kvm, mshv3, target_os = "windows")))]
83+
compile_error!(
84+
"No hypervisor type is available for the current platform. Please enable either the `kvm` or `mshv3` cargo feature."
85+
);
86+
87+
/// The various reasons a VM's vCPU can exit
1588
pub(crate) enum VmExit {
1689
/// The vCPU has exited due to a debug event (usually breakpoint)
1790
#[cfg(gdb)]
@@ -88,3 +161,26 @@ pub(crate) trait Vm: Debug + Send {
88161
#[cfg(target_os = "windows")]
89162
fn complete_initial_memory_setup(&mut self);
90163
}
164+
165+
#[cfg(test)]
166+
mod tests {
167+
168+
#[test]
169+
// TODO: add support for testing on WHP
170+
#[cfg(target_os = "linux")]
171+
fn is_hypervisor_present() {
172+
use std::path::Path;
173+
174+
cfg_if::cfg_if! {
175+
if #[cfg(all(kvm, mshv3))] {
176+
assert_eq!(Path::new("/dev/kvm").exists() || Path::new("/dev/mshv").exists(), super::is_hypervisor_present());
177+
} else if #[cfg(kvm)] {
178+
assert_eq!(Path::new("/dev/kvm").exists(), super::is_hypervisor_present());
179+
} else if #[cfg(mshv3)] {
180+
assert_eq!(Path::new("/dev/mshv").exists(), super::is_hypervisor_present());
181+
} else {
182+
assert!(!super::is_hypervisor_present());
183+
}
184+
}
185+
}
186+
}

src/hyperlight_host/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,13 @@ pub(crate) mod testing;
8585

8686
/// The re-export for the `HyperlightError` type
8787
pub use error::HyperlightError;
88+
/// The re-export for the `is_hypervisor_present` type
89+
pub use hypervisor::vm::is_hypervisor_present;
8890
/// A sandbox that can call be used to make multiple calls to guest functions,
8991
/// and otherwise reused multiple times
9092
pub use sandbox::MultiUseSandbox;
9193
/// The re-export for the `UninitializedSandbox` type
9294
pub use sandbox::UninitializedSandbox;
93-
/// The re-export for the `is_hypervisor_present` type
94-
pub use sandbox::is_hypervisor_present;
9595
/// The re-export for the `GuestBinary` type
9696
pub use sandbox::uninitialized::GuestBinary;
9797

src/hyperlight_host/src/sandbox/hypervisor.rs

Lines changed: 0 additions & 85 deletions
This file was deleted.

src/hyperlight_host/src/sandbox/mod.rs

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ limitations under the License.
1818
pub mod config;
1919
/// Functionality for reading, but not modifying host functions
2020
pub(crate) mod host_funcs;
21-
/// Functionality for dealing with `Sandbox`es that contain Hypervisors
22-
pub(crate) mod hypervisor;
2321
/// Functionality for dealing with initialized sandboxes that can
2422
/// call 0 or more guest functions
2523
pub mod initialized_multi_use;
@@ -47,21 +45,11 @@ pub use callable::Callable;
4745
pub use config::SandboxConfiguration;
4846
/// Re-export for the `MultiUseSandbox` type
4947
pub use initialized_multi_use::MultiUseSandbox;
50-
use tracing::{Span, instrument};
5148
/// Re-export for `GuestBinary` type
5249
pub use uninitialized::GuestBinary;
5350
/// Re-export for `UninitializedSandbox` type
5451
pub use uninitialized::UninitializedSandbox;
5552

56-
/// Determine whether a suitable hypervisor is available to run
57-
/// this sandbox.
58-
///
59-
/// Returns a boolean indicating whether a suitable hypervisor is present.
60-
#[instrument(skip_all, parent = Span::current())]
61-
pub fn is_hypervisor_present() -> bool {
62-
hypervisor::get_available_hypervisor().is_some()
63-
}
64-
6553
#[cfg(test)]
6654
mod tests {
6755
use std::sync::Arc;
@@ -73,25 +61,6 @@ mod tests {
7361
use crate::sandbox::uninitialized::GuestBinary;
7462
use crate::{MultiUseSandbox, UninitializedSandbox, new_error};
7563

76-
#[test]
77-
// TODO: add support for testing on WHP
78-
#[cfg(target_os = "linux")]
79-
fn is_hypervisor_present() {
80-
use std::path::Path;
81-
82-
cfg_if::cfg_if! {
83-
if #[cfg(all(kvm, mshv3))] {
84-
assert_eq!(Path::new("/dev/kvm").exists() || Path::new("/dev/mshv").exists(), super::is_hypervisor_present());
85-
} else if #[cfg(kvm)] {
86-
assert_eq!(Path::new("/dev/kvm").exists(), super::is_hypervisor_present());
87-
} else if #[cfg(mshv3)] {
88-
assert_eq!(Path::new("/dev/mshv").exists(), super::is_hypervisor_present());
89-
} else {
90-
assert!(!super::is_hypervisor_present());
91-
}
92-
}
93-
}
94-
9564
#[test]
9665
fn check_create_and_use_sandbox_on_different_threads() {
9766
let unintializedsandbox_queue = Arc::new(ArrayQueue::<UninitializedSandbox>::new(10));

0 commit comments

Comments
 (0)