// Copyright © 2019 Intel Corporation // // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause // // Copyright © 2020, Microsoft Corporation // // Copyright 2018-2019 CrowdStrike, Inc. // // //! A generic abstraction around hypervisor functionality //! //! This crate offers a trait abstraction for underlying hypervisors //! //! # Platform support //! //! - x86_64 //! - arm64 //! #![allow(clippy::significant_drop_in_scrutinee)] #[macro_use] extern crate anyhow; #[cfg(target_arch = "x86_64")] #[macro_use] extern crate log; /// Architecture specific definitions #[macro_use] pub mod arch; #[cfg(feature = "kvm")] /// KVM implementation module pub mod kvm; /// Microsoft Hypervisor implementation module #[cfg(all(feature = "mshv", target_arch = "x86_64"))] pub mod mshv; /// Hypevisor related module mod hypervisor; /// Vm related module mod vm; /// CPU related module mod cpu; /// Device related module mod device; pub use cpu::{HypervisorCpuError, Vcpu, VmExit}; pub use device::{Device, HypervisorDeviceError}; pub use hypervisor::{Hypervisor, HypervisorError}; #[cfg(all(feature = "kvm", target_arch = "x86_64"))] pub use kvm::x86_64; #[cfg(all(feature = "kvm", target_arch = "aarch64"))] pub use kvm::{aarch64, GicState}; // Aliased types exposed from both hypervisors #[cfg(feature = "kvm")] pub use kvm::{ ClockData, CpuState, CreateDevice, DeviceAttr, DeviceFd, IoEventAddress, IrqRoutingEntry, VcpuEvents, VmState, }; #[cfg(all(feature = "mshv", target_arch = "x86_64"))] pub use mshv::x86_64; // Aliased types exposed from both hypervisors #[cfg(all(feature = "mshv", target_arch = "x86_64"))] pub use mshv::{ CpuState, CreateDevice, DeviceAttr, DeviceFd, IoEventAddress, IrqRoutingEntry, VcpuEvents, VmState, }; use std::sync::Arc; pub use vm::{ DataMatch, HypervisorVmError, InterruptSourceConfig, LegacyIrqSourceConfig, MsiIrqSourceConfig, Vm, VmOps, }; pub fn new() -> std::result::Result, HypervisorError> { #[cfg(feature = "kvm")] let hv = kvm::KvmHypervisor::new()?; #[cfg(feature = "mshv")] let hv = mshv::MshvHypervisor::new()?; Ok(Arc::new(hv)) } // Returns a `Vec` with a size in bytes at least as large as `size_in_bytes`. fn vec_with_size_in_bytes(size_in_bytes: usize) -> Vec { let rounded_size = (size_in_bytes + size_of::() - 1) / size_of::(); let mut v = Vec::with_capacity(rounded_size); v.resize_with(rounded_size, T::default); v } // The kvm API has many structs that resemble the following `Foo` structure: // // ``` // #[repr(C)] // struct Foo { // some_data: u32 // entries: __IncompleteArrayField<__u32>, // } // ``` // // In order to allocate such a structure, `size_of::()` would be too small because it would not // include any space for `entries`. To make the allocation large enough while still being aligned // for `Foo`, a `Vec` is created. Only the first element of `Vec` would actually be used // as a `Foo`. The remaining memory in the `Vec` is for `entries`, which must be contiguous // with `Foo`. This function is used to make the `Vec` with enough space for `count` entries. use std::mem::size_of; pub fn vec_with_array_field(count: usize) -> Vec { let element_space = count * size_of::(); let vec_size_bytes = size_of::() + element_space; vec_with_size_in_bytes(vec_size_bytes) } /// /// User memory region structure /// #[derive(Debug, Default, Eq, PartialEq)] pub struct UserMemoryRegion { pub slot: u32, pub guest_phys_addr: u64, pub memory_size: u64, pub userspace_addr: u64, pub flags: u32, } /// /// Flags for user memory region /// pub const USER_MEMORY_REGION_READ: u32 = 1; pub const USER_MEMORY_REGION_WRITE: u32 = 1 << 1; pub const USER_MEMORY_REGION_EXECUTE: u32 = 1 << 2; pub const USER_MEMORY_REGION_LOG_DIRTY: u32 = 1 << 3; #[derive(Debug)] pub enum MpState { #[cfg(feature = "kvm")] Kvm(kvm_bindings::kvm_mp_state), #[cfg(all(feature = "mshv", target_arch = "x86_64"))] Mshv, /* MSHV does not supprt MpState yet */ }