diff --git a/.github/workflows/Benchmarks.yml b/.github/workflows/Benchmarks.yml index 02206406..245fbf62 100644 --- a/.github/workflows/Benchmarks.yml +++ b/.github/workflows/Benchmarks.yml @@ -17,11 +17,11 @@ jobs: strategy: fail-fast: true matrix: - hypervisor: [hyperv, mshv, kvm] # hyperv is windows, mshv and kvm are linux + hypervisor: [hyperv, mshv, mshv3, kvm] # hyperv is windows, mshv and kvm are linux cpu: [amd, intel] config: [release] # don't want to benchmark debug-builds - runs-on: ${{ fromJson(format('["self-hosted", "{0}", "X64", "1ES.Pool=hld-{1}-{2}"]', matrix.hypervisor == 'hyperv' && 'Windows' || 'Linux', matrix.hypervisor == 'hyperv' && 'win2022' || matrix.hypervisor, matrix.cpu)) }} + runs-on: ${{ fromJson(format('["self-hosted", "{0}", "X64", "1ES.Pool=hld-{1}-{2}"]', matrix.hypervisor == 'hyperv' && 'Windows' || 'Linux', matrix.hypervisor == 'hyperv' && 'win2022' || matrix.hypervisor == 'mshv3' && 'azlinux3-mshv' || matrix.hypervisor, matrix.cpu)) }} steps: ### Setup ### @@ -67,7 +67,7 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Run Benchmarks - run: just bench-ci main release + run: just bench-ci main release ${{ matrix.hypervisor == 'mshv3' && 'mshv3' || ''}} - uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/dep_rust.yml b/.github/workflows/dep_rust.yml index d55d7003..b725210d 100644 --- a/.github/workflows/dep_rust.yml +++ b/.github/workflows/dep_rust.yml @@ -26,11 +26,15 @@ jobs: strategy: fail-fast: true matrix: - hypervisor: [hyperv, mshv, kvm] # hyperv is windows, mshv and kvm are linux + hypervisor: [hyperv, mshv, mshv3, kvm] # hyperv is windows, mshv and kvm are linux cpu: [amd, intel] config: [debug, release] - runs-on: ${{ fromJson(format('["self-hosted", "{0}", "X64", "1ES.Pool=hld-{1}-{2}"]', matrix.hypervisor == 'hyperv' && 'Windows' || 'Linux', matrix.hypervisor == 'hyperv' && 'win2022' || matrix.hypervisor, matrix.cpu)) }} + runs-on: ${{ fromJson( + format('["self-hosted", "{0}", "X64", "1ES.Pool=hld-{1}-{2}"]', + matrix.hypervisor == 'hyperv' && 'Windows' || 'Linux', + matrix.hypervisor == 'hyperv' && 'win2022' || matrix.hypervisor == 'mshv3' && 'azlinux3-mshv' || matrix.hypervisor, + matrix.cpu)) }} steps: - uses: actions/checkout@v4 @@ -75,10 +79,10 @@ jobs: CARGO_TERM_COLOR: always run: | # with default features - just test-rust ${{ matrix.config }} + just test-rust ${{ matrix.config }} ${{ matrix.hypervisor == 'mshv3' && 'mshv3' || ''}} # with only one driver enabled (driver mshv/kvm feature is ignored on windows) + seccomp + inprocess - just test-rust ${{ matrix.config }} inprocess,seccomp,${{ matrix.hypervisor == 'mshv' && 'mshv' || 'kvm' }} + just test-rust ${{ matrix.config }} inprocess,seccomp,${{ matrix.hypervisor == 'mshv' && 'mshv2' || matrix.hypervisor == 'mshv3' && 'mshv3' || 'kvm' }} # make sure certain cargo features compile cargo check -p hyperlight-host --features crashdump @@ -100,7 +104,7 @@ jobs: env: CARGO_TERM_COLOR: always RUST_LOG: debug - run: just run-rust-examples-linux ${{ matrix.config }} + run: just run-rust-examples-linux ${{ matrix.config }} ${{ matrix.hypervisor == 'mshv3' && 'mshv3' || ''}} ### Benchmarks ### - name: Install github-cli (Linux mariner) @@ -120,5 +124,5 @@ jobs: - name: Run benchmarks run: | - just bench-ci main ${{ matrix.config }} + just bench-ci main ${{ matrix.config }} ${{ matrix.hypervisor == 'mshv3' && 'mshv3' || ''}} if: ${{ matrix.config == 'release' }} diff --git a/Cargo.lock b/Cargo.lock index 97e1700c..b44d8801 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1102,8 +1102,10 @@ dependencies = [ "lazy_static", "libc", "log", - "mshv-bindings", - "mshv-ioctls", + "mshv-bindings 0.2.1", + "mshv-bindings 0.3.2", + "mshv-ioctls 0.2.1", + "mshv-ioctls 0.3.2", "once_cell", "opentelemetry", "opentelemetry-otlp", @@ -1617,7 +1619,19 @@ dependencies = [ "libc", "num_enum", "vmm-sys-util", - "zerocopy", + "zerocopy 0.7.35", +] + +[[package]] +name = "mshv-bindings" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0cb5031f3243a7459b7c13d960d25420980874eebda816db24ce6077e21d43" +dependencies = [ + "libc", + "num_enum", + "vmm-sys-util", + "zerocopy 0.8.14", ] [[package]] @@ -1627,11 +1641,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d57586da719aacc905042eea71ff2efb52d16c7228a94af155c9ea45fe09c1c7" dependencies = [ "libc", - "mshv-bindings", + "mshv-bindings 0.2.1", "thiserror 1.0.69", "vmm-sys-util", ] +[[package]] +name = "mshv-ioctls" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89abe853221fa6f14ad4066affb9abda241a03d65622887d5794e1422d0bd75a" +dependencies = [ + "libc", + "mshv-bindings 0.3.2", + "thiserror 2.0.10", + "vmm-sys-util", +] + [[package]] name = "nom" version = "7.1.3" @@ -1910,7 +1936,7 @@ version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -3499,7 +3525,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a367f292d93d4eab890745e75a778da40909cab4d6ff8173693812f79c4a2468" +dependencies = [ + "zerocopy-derive 0.8.14", ] [[package]] @@ -3513,6 +3548,17 @@ dependencies = [ "syn", ] +[[package]] +name = "zerocopy-derive" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3931cb58c62c13adec22e38686b559c86a30565e16ad6e8510a337cedc611e1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zerofrom" version = "0.1.4" diff --git a/Cargo.toml b/Cargo.toml index 9e3d0b3c..52359d14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 } diff --git a/Justfile b/Justfile index 60411361..56045d0b 100644 --- a/Justfile +++ b/Justfile @@ -76,7 +76,7 @@ clean-rust: # Some tests cannot run with other tests, they are marked as ignored so that cargo test works # there may be tests that we really want to ignore so we can't just use --ignored and we have to # Specify the test name of the ignored tests that we want to run -test-rust target=default-target features="": (test-rust-int "rust" target features) (test-rust-int "c" target features) (test-seccomp target) +test-rust target=default-target features="": (test-rust-int "rust" target features) (test-rust-int "c" target features) (test-seccomp target features) # unit tests cargo test {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" { "dev" } else { target } }} --lib @@ -91,23 +91,23 @@ test-rust target=default-target features="": (test-rust-int "rust" target featur cargo test {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" { "dev" } else { target } }} hypervisor::hypervisor_handler::tests::create_1000_sandboxes -p hyperlight-host --lib -- --ignored {{ set-trace-env-vars }} cargo test {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" { "dev" } else { target } }} --lib sandbox::outb::tests::test_log_outb_log -- --ignored -test-seccomp target=default-target: +test-seccomp target=default-target features="": # run seccomp test with feature "seccomp" on and off - cargo test --profile={{ if target == "debug" { "dev" } else { target } }} -p hyperlight-host test_violate_seccomp_filters --lib -- --ignored - cargo test --profile={{ if target == "debug" { "dev" } else { target } }} -p hyperlight-host test_violate_seccomp_filters --no-default-features --features mshv,kvm --lib -- --ignored + cargo test --profile={{ if target == "debug" { "dev" } else { target } }} -p hyperlight-host test_violate_seccomp_filters --lib {{ if features =="" {''} else { "--features " + features } }} -- --ignored + cargo test --profile={{ if target == "debug" { "dev" } else { target } }} -p hyperlight-host test_violate_seccomp_filters --no-default-features {{ if features =~"mshv3" {"--features mshv3"} else {"--features mshv2,kvm" } }} --lib -- --ignored # rust integration tests. guest can either be "rust" or "c" test-rust-int guest target=default-target features="": # integration tests # run execute_on_heap test with feature "executable_heap" on and off - {{if os() == "windows" { "$env:" } else { "" } }}GUEST="{{guest}}"{{if os() == "windows" { ";" } else { "" } }} cargo test --profile={{ if target == "debug" { "dev" } else { target } }} --test integration_test execute_on_heap --features executable_heap -- --ignored - {{if os() == "windows" { "$env:" } else { "" } }}GUEST="{{guest}}"{{if os() == "windows" { ";" } else { "" } }} cargo test --profile={{ if target == "debug" { "dev" } else { target } }} --test integration_test execute_on_heap -- --ignored + {{if os() == "windows" { "$env:" } else { "" } }}GUEST="{{guest}}"{{if os() == "windows" { ";" } else { "" } }} cargo test --profile={{ if target == "debug" { "dev" } else { target } }} --test integration_test execute_on_heap {{ if features =="" {" --features executable_heap"} else {"--features executable_heap," + features} }} -- --ignored + {{if os() == "windows" { "$env:" } else { "" } }}GUEST="{{guest}}"{{if os() == "windows" { ";" } else { "" } }} cargo test --profile={{ if target == "debug" { "dev" } else { target } }} --test integration_test execute_on_heap {{ if features =="" {""} else {"--features " + features} }} -- --ignored # run the rest of the integration tests {{if os() == "windows" { "$env:" } else { "" } }}GUEST="{{guest}}"{{if os() == "windows" { ";" } else { "" } }} cargo test -p hyperlight-host {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" { "dev" } else { target } }} --test '*' test-rust-feature-compilation-fail target=default-target: - @# the following should fail on linux because either kvm or msh feature must be specified, which is why the exit code is inverted with an !. + @# the following should fail on linux because one of kvm, mshv, or mshv3 feature must be specified, which is why the exit code is inverted with an !. {{ if os() == "linux" { "! cargo check -p hyperlight-host --no-default-features 2> /dev/null"} else { "" } }} test target=default-target: (test-rust target) @@ -149,15 +149,15 @@ gen-all-fbs-rust-code: just fmt-apply # RUST EXAMPLES -run-rust-examples target=default-target: (build-rust target) - cargo run --profile={{ if target == "debug" { "dev" } else { target } }} --example metrics - cargo run --profile={{ if target == "debug" { "dev" } else { target } }} --example metrics --features "function_call_metrics" - {{ set-trace-env-vars }} cargo run --profile={{ if target == "debug" { "dev" } else { target } }} --example logging +run-rust-examples target=default-target features="": (build-rust target) + cargo run --profile={{ if target == "debug" { "dev" } else { target } }} --example metrics {{ if features =="" {''} else { "--features " + features } }} + cargo run --profile={{ if target == "debug" { "dev" } else { target } }} --example metrics {{ if features =="" {"--features function_call_metrics"} else {"--features function_call_metrics," + features} }} + {{ set-trace-env-vars }} cargo run --profile={{ if target == "debug" { "dev" } else { target } }} --example logging {{ if features =="" {''} else { "--features " + features } }} # The two tracing examples are flaky on windows so we run them on linux only for now, need to figure out why as they run fine locally on windows -run-rust-examples-linux target=default-target: (build-rust target) (run-rust-examples target) - {{ set-trace-env-vars }} cargo run --profile={{ if target == "debug" { "dev" } else { target } }} --example tracing - {{ set-trace-env-vars }} cargo run --profile={{ if target == "debug" { "dev" } else { target } }} --example tracing --features "function_call_metrics" +run-rust-examples-linux target=default-target features="": (build-rust target) (run-rust-examples target features) + {{ set-trace-env-vars }} cargo run --profile={{ if target == "debug" { "dev" } else { target } }} --example tracing {{ if features =="" {''} else { "--features " + features } }} + {{ set-trace-env-vars }} cargo run --profile={{ if target == "debug" { "dev" } else { target } }} --example tracing {{ if features =="" {"--features function_call_metrics" } else {"--features function_call_metrics," + features} }} # BENCHMARKING @@ -174,15 +174,15 @@ bench-download os hypervisor cpu tag="": tar -zxvf target/benchmarks_{{ os }}_{{ hypervisor }}_{{ cpu }}.tar.gz -C target/criterion/ --strip-components=1 # Warning: compares to and then OVERWRITES the given baseline -bench-ci baseline target=default-target: - cargo bench --profile={{ if target == "debug" { "dev" } else { target } }} -- --verbose --save-baseline {{ baseline }} +bench-ci baseline target=default-target features="": + cargo bench --profile={{ if target == "debug" { "dev" } else { target } }} {{ if features =="" {''} else { "--features " + features } }} -- --verbose --save-baseline {{ baseline }} -bench target=default-target: - cargo bench --profile={{ if target == "debug" { "dev" } else { target } }} -- --verbose +bench target=default-target features="": + cargo bench --profile={{ if target == "debug" { "dev" } else { target } }} {{ if features =="" {''} else { "--features " + features } }} -- --verbose # FUZZING fuzz: cd src/hyperlight_host && cargo +nightly fuzz run fuzz_target_1 fuzz-timed: - cd src/hyperlight_host && cargo +nightly fuzz run fuzz_target_1 -- -max_total_time=300 \ No newline at end of file + cd src/hyperlight_host && cargo +nightly fuzz run fuzz_target_1 -- -max_total_time=300 diff --git a/src/hyperlight_host/Cargo.toml b/src/hyperlight_host/Cargo.toml index fc18566a..b1f02b03 100644 --- a/src/hyperlight_host/Cargo.toml +++ b/src/hyperlight_host/Cargo.toml @@ -71,10 +71,12 @@ windows-version = "0.1" [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.1", 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.2", optional = true } +mshv-ioctls3 = { package="mshv-ioctls", version = "0.3.2", optional = true} [dev-dependencies] uuid = { version = "1.12.1", features = ["v4"] } @@ -114,7 +116,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 = [] @@ -122,7 +124,8 @@ executable_heap = [] print_debug = [] crashdump = ["dep:tempfile"] # Dumps the VM state to a file on unexpected errors or crashes. The path of the file will be printed on stdout and logged. This feature can only be used in debug builds. kvm = ["dep:kvm-bindings", "dep:kvm-ioctls"] -mshv = ["dep:mshv-bindings", "dep:mshv-ioctls"] +mshv2 = ["dep:mshv-bindings2", "dep:mshv-ioctls2"] +mshv3 = ["dep:mshv-bindings3", "dep:mshv-ioctls3"] inprocess = [] [[bench]] diff --git a/src/hyperlight_host/build.rs b/src/hyperlight_host/build.rs index 2aa321e7..7600f647 100644 --- a/src/hyperlight_host/build.rs +++ b/src/hyperlight_host/build.rs @@ -85,12 +85,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) }, @@ -98,6 +98,11 @@ fn main() -> Result<()> { crashdump: { all(feature = "crashdump", debug_assertions) }, // print_debug feature is aliased with debug_assertions to make it only available in debug-builds. print_debug: { all(feature = "print_debug", debug_assertions) }, + // the following features are mutually exclusive but rather than enforcing that here we are enabling mshv3 to override mshv2 when both are enabled + // because mshv2 is in the default feature set we want to allow users to enable mshv3 without having to set --no-default-features and the re-enable + // the other features they want. + mshv2: { all(feature = "mshv2", not(feature="mshv3"), target_os = "linux") }, + mshv3: { all(feature = "mshv3", target_os = "linux") }, } write_built_file()?; diff --git a/src/hyperlight_host/src/error.rs b/src/hyperlight_host/src/error.rs index f6bed4f9..e846ee12 100644 --- a/src/hyperlight_host/src/error.rs +++ b/src/hyperlight_host/src/error.rs @@ -14,6 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ +#[cfg(mshv2)] +extern crate mshv_ioctls2 as mshv_ioctls; + +#[cfg(mshv3)] +extern crate mshv_ioctls3 as mshv_ioctls; + use std::array::TryFromSliceError; use std::cell::{BorrowError, BorrowMutError}; use std::convert::Infallible; diff --git a/src/hyperlight_host/src/hypervisor/hyperv_linux.rs b/src/hyperlight_host/src/hypervisor/hyperv_linux.rs index db00a2c8..33798d88 100644 --- a/src/hyperlight_host/src/hypervisor/hyperv_linux.rs +++ b/src/hyperlight_host/src/hypervisor/hyperv_linux.rs @@ -14,16 +14,32 @@ See the License for the specific language governing permissions and limitations under the License. */ +#[cfg(mshv2)] +extern crate mshv_bindings2 as mshv_bindings; +#[cfg(mshv2)] +extern crate mshv_ioctls2 as mshv_ioctls; + +#[cfg(mshv3)] +extern crate mshv_bindings3 as mshv_bindings; +#[cfg(mshv3)] +extern crate mshv_ioctls3 as mshv_ioctls; + use std::fmt::{Debug, Formatter}; use log::error; +#[cfg(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(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}; @@ -86,7 +102,24 @@ impl HypervLinuxDriver { ) -> Result { let mshv = Mshv::new()?; let pr = Default::default(); + #[cfg(mshv2)] let vm_fd = mshv.create_vm_with_config(&pr)?; + #[cfg(mshv3)] + let vm_fd = { + // It's important to avoid create_vm() and explicitly use + // create_vm_with_args() with an empty arguments structure + // here, because otherwise the partition is set up with a SynIC. + + 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.initialize()?; + vm_fd + }; + let mut vcpu_fd = vm_fd.create_vcpu(0)?; mem_regions.iter().try_for_each(|region| { @@ -280,8 +313,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(mshv2)] + let run_result = { + let hv_message: hv_message = Default::default(); + &self.vcpu_fd.run(hv_message) + }; + #[cfg(mshv3)] + let run_result = &self.vcpu_fd.run(); + + let result = match run_result { Ok(m) => match m.header.message_type { HALT_MESSAGE => { crate::debug!("mshv - Halt Details : {:#?}", &self); diff --git a/src/hyperlight_host/src/mem/memory_region.rs b/src/hyperlight_host/src/mem/memory_region.rs index f8911ff6..6956d963 100644 --- a/src/hyperlight_host/src/mem/memory_region.rs +++ b/src/hyperlight_host/src/mem/memory_region.rs @@ -14,6 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ +#[cfg(mshv2)] +extern crate mshv_bindings2 as mshv_bindings; +#[cfg(mshv2)] +extern crate mshv_ioctls2 as mshv_ioctls; + +#[cfg(mshv3)] +extern crate mshv_bindings3 as mshv_bindings; +#[cfg(mshv3)] +extern crate mshv_ioctls3 as mshv_ioctls; + use std::ops::Range; use bitflags::bitflags; @@ -21,9 +31,14 @@ use bitflags::bitflags; 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(mshv2)] +use mshv_bindings::{ + HV_MAP_GPA_EXECUTABLE, HV_MAP_GPA_PERMISSIONS_NONE, HV_MAP_GPA_READABLE, HV_MAP_GPA_WRITABLE, +}; +#[cfg(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}; @@ -227,22 +242,45 @@ impl From 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(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(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() + } } } }