Skip to content

Commit

Permalink
Adds support for Azure 3
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon Davies committed Nov 11, 2024
1 parent 5de971c commit b826b9a
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 31 deletions.
2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ repository = "https://github.com/hyperlight-dev/hyperlight"
readme = "README.md"

[workspace.dependencies]
mshv-bindings = { version = "=0.2.1" }
mshv-ioctls = { version = "=0.2.1" }

hyperlight-common = { path = "src/hyperlight_common", version = "0.1.0", default-features = false }
hyperlight-host = { path = "src/hyperlight_host", version = "0.1.0", default-features = false }
Expand Down
11 changes: 7 additions & 4 deletions src/hyperlight_host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,12 @@ windows-result = "0.2"

[target.'cfg(unix)'.dependencies]
seccompiler = { version = "0.4.0", optional = true }
mshv-bindings = { workspace = true, optional = true }
mshv-ioctls = { workspace = true, optional = true }
kvm-bindings = { version = "0.10.0", features = ["fam-wrappers"], optional = true }
kvm-ioctls = { version = "0.19.0", optional = true }
mshv-bindings2 = { package="mshv-bindings", version = "=0.2.1", optional = true }
mshv-ioctls2 = { package="mshv-ioctls", version = "=0.2.1", optional = true}
mshv-bindings3 = { package="mshv-bindings", version = "0.3.1", optional = true }
mshv-ioctls3 = { package="mshv-ioctls", version = "0.3.1", optional = true}

[dev-dependencies]
signal-hook-registry = "1.4.1"
Expand Down Expand Up @@ -112,7 +114,7 @@ cfg_aliases = "0.2.1"
built = { version = "0.7.0", features = ["chrono","git2"] }

[features]
default = ["kvm", "mshv", "seccomp"]
default = ["kvm", "mshv2", "seccomp"]
seccomp = ["dep:seccompiler"]
function_call_metrics = []
executable_heap = []
Expand All @@ -122,7 +124,8 @@ print_debug = []
# the name of the file is output to stdout and logged.
dump_on_crash = ["dep:tempfile"]
kvm = ["dep:kvm-bindings", "dep:kvm-ioctls"]
mshv = ["dep:mshv-bindings", "dep:mshv-ioctls"]
mshv2 = ["mshv-bindings2", "mshv-ioctls2"]
mshv3 = ["mshv-bindings3", "mshv-ioctls3"]
inprocess = []

[[bench]]
Expand Down
8 changes: 6 additions & 2 deletions src/hyperlight_host/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ use anyhow::Result;
use built::write_built_file;

fn main() -> Result<()> {
// mshv2 and mshv3 features are mutually exclusive.
#[cfg(all(feature = "mshv2", feature = "mshv3"))]
panic!("mshv2 and mshv3 features are mutually exclusive");

// re-run the build if this script is changed (or deleted!),
// even if the rust code is completely unchanged.
println!("cargo:rerun-if-changed=build.rs");
Expand Down Expand Up @@ -85,12 +89,12 @@ fn main() -> Result<()> {
}

// Makes #[cfg(kvm)] == #[cfg(all(feature = "kvm", target_os = "linux"))]
// and #[cfg(mshv)] == #[cfg(all(feature = "mshv", target_os = "linux"))].
// and #[cfg(mshv)] == #[cfg(all(any(feature = "mshv2", feature = "mshv3"), target_os = "linux"))].
// Essentially the kvm and mshv features are ignored on windows as long as you use #[cfg(kvm)] and not #[cfg(feature = "kvm")].
// You should never use #[cfg(feature = "kvm")] or #[cfg(feature = "mshv")] in the codebase.
cfg_aliases::cfg_aliases! {
kvm: { all(feature = "kvm", target_os = "linux") },
mshv: { all(feature = "mshv", target_os = "linux") },
mshv: { all(any(feature = "mshv2", feature = "mshv3"), target_os = "linux") },
// inprocess feature is aliased with debug_assertions to make it only available in debug-builds.
// You should never use #[cfg(feature = "inprocess")] in the codebase. Use #[cfg(inprocess)] instead.
inprocess: { all(feature = "inprocess", debug_assertions) },
Expand Down
6 changes: 6 additions & 0 deletions src/hyperlight_host/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

#[cfg(feature = "mshv2")]
extern crate mshv_ioctls2 as mshv_ioctls;

#[cfg(feature = "mshv3")]
extern crate mshv_ioctls3 as mshv_ioctls;

use std::array::TryFromSliceError;
use std::cell::{BorrowError, BorrowMutError};
use std::convert::Infallible;
Expand Down
45 changes: 40 additions & 5 deletions src/hyperlight_host/src/hypervisor/hyperv_linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,32 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

#[cfg(feature = "mshv2")]
extern crate mshv_bindings2 as mshv_bindings;
#[cfg(feature = "mshv2")]
extern crate mshv_ioctls2 as mshv_ioctls;

#[cfg(feature = "mshv3")]
extern crate mshv_bindings3 as mshv_bindings;
#[cfg(feature = "mshv3")]
extern crate mshv_ioctls3 as mshv_ioctls;

use std::fmt::{Debug, Formatter};

use log::error;
#[cfg(feature = "mshv2")]
use mshv_bindings::hv_message;
use mshv_bindings::{
hv_message, hv_message_type, hv_message_type_HVMSG_GPA_INTERCEPT,
hv_message_type_HVMSG_UNMAPPED_GPA, hv_message_type_HVMSG_X64_HALT,
hv_message_type_HVMSG_X64_IO_PORT_INTERCEPT, hv_register_assoc,
hv_message_type, hv_message_type_HVMSG_GPA_INTERCEPT, hv_message_type_HVMSG_UNMAPPED_GPA,
hv_message_type_HVMSG_X64_HALT, hv_message_type_HVMSG_X64_IO_PORT_INTERCEPT, hv_register_assoc,
hv_register_name_HV_X64_REGISTER_RIP, hv_register_value, mshv_user_mem_region,
FloatingPointUnit, SegmentRegister, SpecialRegisters, StandardRegisters,
};
#[cfg(feature = "mshv3")]
use mshv_bindings::{
hv_partition_property_code_HV_PARTITION_PROPERTY_SYNTHETIC_PROC_FEATURES,
hv_partition_synthetic_processor_features,
};
use mshv_ioctls::{Mshv, VcpuFd, VmFd};
use tracing::{instrument, Span};

Expand Down Expand Up @@ -89,7 +105,19 @@ impl HypervLinuxDriver {
}
let mshv = Mshv::new()?;
let pr = Default::default();
#[cfg(feature = "mshv2")]
let vm_fd = mshv.create_vm_with_config(&pr)?;
#[cfg(feature = "mshv3")]
let vm_fd = {
let vm_fd = mshv.create_vm_with_args(&pr)?;
let features: hv_partition_synthetic_processor_features = Default::default();
vm_fd.hvcall_set_partition_property(
hv_partition_property_code_HV_PARTITION_PROPERTY_SYNTHETIC_PROC_FEATURES,
unsafe { features.as_uint64[0] },
)?;
vm_fd
};

let mut vcpu_fd = vm_fd.create_vcpu(0)?;

mem_regions.iter().try_for_each(|region| {
Expand Down Expand Up @@ -283,8 +311,15 @@ impl Hypervisor for HypervLinuxDriver {
const UNMAPPED_GPA_MESSAGE: hv_message_type = hv_message_type_HVMSG_UNMAPPED_GPA;
const INVALID_GPA_ACCESS_MESSAGE: hv_message_type = hv_message_type_HVMSG_GPA_INTERCEPT;

let hv_message: hv_message = Default::default();
let result = match &self.vcpu_fd.run(hv_message) {
#[cfg(feature = "mshv2")]
let run_result = {
let hv_message: hv_message = Default::default();
&self.vcpu_fd.run(hv_message)
};
#[cfg(feature = "mshv3")]
let run_result = &self.vcpu_fd.run();

let result = match run_result {
Ok(m) => match m.header.message_type {
HALT_MESSAGE => {
debug!("mshv - Halt Details : {:#?}", &self);
Expand Down
74 changes: 56 additions & 18 deletions src/hyperlight_host/src/mem/memory_region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,31 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

#[cfg(feature = "mshv2")]
extern crate mshv_bindings2 as mshv_bindings;
#[cfg(feature = "mshv2")]
extern crate mshv_ioctls2 as mshv_ioctls;

#[cfg(feature = "mshv3")]
extern crate mshv_bindings3 as mshv_bindings;
#[cfg(feature = "mshv3")]
extern crate mshv_ioctls3 as mshv_ioctls;

use std::ops::Range;

use bitflags::bitflags;
#[cfg(mshv)]
use hyperlight_common::mem::PAGE_SHIFT;
use hyperlight_common::mem::PAGE_SIZE_USIZE;
#[cfg(mshv)]
use mshv_bindings::{hv_x64_memory_intercept_message, mshv_user_mem_region};
#[cfg(feature = "mshv2")]
use mshv_bindings::{
HV_MAP_GPA_EXECUTABLE, HV_MAP_GPA_PERMISSIONS_NONE, HV_MAP_GPA_READABLE, HV_MAP_GPA_WRITABLE,
};
#[cfg(feature = "mshv3")]
use mshv_bindings::{
hv_x64_memory_intercept_message, mshv_user_mem_region, HV_MAP_GPA_EXECUTABLE,
HV_MAP_GPA_PERMISSIONS_NONE, HV_MAP_GPA_READABLE, HV_MAP_GPA_WRITABLE,
MSHV_SET_MEM_BIT_EXECUTABLE, MSHV_SET_MEM_BIT_UNMAP, MSHV_SET_MEM_BIT_WRITABLE,
};
#[cfg(target_os = "windows")]
use windows::Win32::System::Hypervisor::{self, WHV_MEMORY_ACCESS_TYPE};
Expand Down Expand Up @@ -227,22 +242,45 @@ impl From<MemoryRegion> for mshv_user_mem_region {
let guest_pfn = region.guest_region.start as u64 >> PAGE_SHIFT;
let userspace_addr = region.host_region.start as u64;

let flags = region.flags.iter().fold(0, |acc, flag| {
let flag_value = match flag {
MemoryRegionFlags::NONE => HV_MAP_GPA_PERMISSIONS_NONE,
MemoryRegionFlags::READ => HV_MAP_GPA_READABLE,
MemoryRegionFlags::WRITE => HV_MAP_GPA_WRITABLE,
MemoryRegionFlags::EXECUTE => HV_MAP_GPA_EXECUTABLE,
_ => 0, // ignore any unknown flags
};
acc | flag_value
});

mshv_user_mem_region {
guest_pfn,
size,
userspace_addr,
flags,
#[cfg(feature = "mshv2")]
{
let flags = region.flags.iter().fold(0, |acc, flag| {
let flag_value = match flag {
MemoryRegionFlags::NONE => HV_MAP_GPA_PERMISSIONS_NONE,
MemoryRegionFlags::READ => HV_MAP_GPA_READABLE,
MemoryRegionFlags::WRITE => HV_MAP_GPA_WRITABLE,
MemoryRegionFlags::EXECUTE => HV_MAP_GPA_EXECUTABLE,
_ => 0, // ignore any unknown flags
};
acc | flag_value
});
mshv_user_mem_region {
guest_pfn,
size,
userspace_addr,
flags,
}
}
#[cfg(feature = "mshv3")]
{
let flags: u8 = region.flags.iter().fold(0, |acc, flag| {
let flag_value = match flag {
MemoryRegionFlags::NONE => 1 << MSHV_SET_MEM_BIT_UNMAP,
MemoryRegionFlags::READ => 0,
MemoryRegionFlags::WRITE => 1 << MSHV_SET_MEM_BIT_WRITABLE,
MemoryRegionFlags::EXECUTE => 1 << MSHV_SET_MEM_BIT_EXECUTABLE,
_ => 0, // ignore any unknown flags
};
acc | flag_value
});

mshv_user_mem_region {
guest_pfn,
size,
userspace_addr,
flags,
..Default::default()
}
}
}
}

0 comments on commit b826b9a

Please sign in to comment.