diff --git a/.github/workflows/Benchmarks.yml b/.github/workflows/Benchmarks.yml index 5a6838b..9d4795b 100644 --- a/.github/workflows/Benchmarks.yml +++ b/.github/workflows/Benchmarks.yml @@ -71,7 +71,7 @@ jobs: # the component model benchmark depends on the wasm wit component just ensure-tools just compile-wit - just bench-ci dev release ${{ matrix.hypervisor == 'mshv3' && 'mshv3' || ''}} + just bench-ci dev release ${{ matrix.hypervisor == 'mshv' && 'mshv2' || ''}} working-directory: ./src/hyperlight_wasm - name: Upload Benchmarks diff --git a/.github/workflows/dep_rust.yml b/.github/workflows/dep_rust.yml index 85e435a..da29e9f 100644 --- a/.github/workflows/dep_rust.yml +++ b/.github/workflows/dep_rust.yml @@ -92,7 +92,7 @@ jobs: run: just clippy ${{ matrix.config }} - name: Build - run: just build ${{ matrix.config }} ${{ matrix.hypervisor == 'mshv3' && 'mshv3' || ''}} + run: just build ${{ matrix.config }} ${{ matrix.hypervisor == 'mshv' && 'mshv2' || ''}} working-directory: ./src/hyperlight_wasm - name: Build Rust Wasm examples @@ -100,7 +100,7 @@ jobs: working-directory: ./src/hyperlight_wasm - name: Test - run: just test ${{ matrix.config }} ${{ matrix.hypervisor == 'mshv3' && 'mshv3' || ''}} + run: just test ${{ matrix.config }} ${{ matrix.hypervisor == 'mshv' && 'mshv2' || ''}} working-directory: ./src/hyperlight_wasm - name: Install github-cli (Windows) @@ -118,14 +118,14 @@ jobs: shell: pwsh - name: Test Examples - run: just examples-ci ${{ matrix.config }} ${{ matrix.hypervisor == 'mshv3' && 'mshv3' || ''}} + run: just examples-ci ${{ matrix.config }} ${{ matrix.hypervisor == 'mshv' && 'mshv2' || ''}} working-directory: ./src/hyperlight_wasm env: # required for gh cli when downloading GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Test Component Model Examples - run: just examples-components ${{ matrix.config }} ${{ matrix.hypervisor == 'mshv3' && 'mshv3' || ''}} + run: just examples-components ${{ matrix.config }} ${{ matrix.hypervisor == 'mshv' && 'mshv2' || ''}} working-directory: ./src/hyperlight_wasm ### Benchmarks ### @@ -141,6 +141,6 @@ jobs: - name: Run benchmarks run: | - just bench-ci dev ${{ matrix.config }} ${{ matrix.hypervisor == 'mshv3' && 'mshv3' || ''}} + just bench-ci dev ${{ matrix.config }} ${{ matrix.hypervisor == 'mshv' && 'mshv2' || ''}} working-directory: ./src/hyperlight_wasm if: ${{ matrix.config == 'release' }} diff --git a/Cargo.lock b/Cargo.lock index 331ce36..8a81f91 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -445,18 +445,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.43" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50fd97c9dc2399518aa331917ac6f274280ec5eb34e555dd291899745c48ec6f" +checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.43" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c35b5830294e1fa0462034af85cc95225a4cb07092c088c55bda3147cfcd8f65" +checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" dependencies = [ "anstream", "anstyle", @@ -1262,8 +1262,9 @@ dependencies = [ [[package]] name = "hyperlight-common" -version = "0.7.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=ea6fa8f#ea6fa8f16dae2325d94af39eb6ac3b441b24dcac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52423b32cefb31363194a332da0ed440c550407a8c2f2acf1c837e77b09cc06c" dependencies = [ "anyhow", "flatbuffers", @@ -1274,8 +1275,9 @@ dependencies = [ [[package]] name = "hyperlight-component-macro" -version = "0.7.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=b61265e4aa9e2ecf8d648b994022caeea0205352#b61265e4aa9e2ecf8d648b994022caeea0205352" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4551a2dc306210f2aebac2f8f1158452c201ede7247568ea484235dce3611639" dependencies = [ "env_logger", "hyperlight-component-util", @@ -1284,13 +1286,14 @@ dependencies = [ "proc-macro2", "quote", "syn", - "wasmparser", + "wasmparser 0.236.0", ] [[package]] name = "hyperlight-component-util" -version = "0.7.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=b61265e4aa9e2ecf8d648b994022caeea0205352#b61265e4aa9e2ecf8d648b994022caeea0205352" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34b2db33623c8d0e97e9be913064843621a1260cce140a15dc3b0da9378d45" dependencies = [ "itertools 0.14.0", "log", @@ -1298,16 +1301,18 @@ dependencies = [ "proc-macro2", "quote", "syn", - "wasmparser", + "wasmparser 0.236.0", ] [[package]] name = "hyperlight-host" -version = "0.7.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=ea6fa8f#ea6fa8f16dae2325d94af39eb6ac3b441b24dcac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b140cd8287fd04c23de72c251f13d97b6b4f95e6ffdc79638f1df556f58666cc" dependencies = [ "anyhow", "bitflags 2.9.1", + "blake3", "cfg-if", "cfg_aliases", "chrono", @@ -1337,7 +1342,8 @@ dependencies = [ "tracing", "tracing-core", "tracing-log", - "vmm-sys-util", + "uuid", + "vmm-sys-util 0.15.0", "windows", "windows-result", "windows-sys 0.60.2", @@ -1346,7 +1352,7 @@ dependencies = [ [[package]] name = "hyperlight-wasm" -version = "0.7.0" +version = "0.8.0" dependencies = [ "anyhow", "blake3", @@ -1374,7 +1380,7 @@ dependencies = [ [[package]] name = "hyperlight-wasm-aot" -version = "0.7.0" +version = "0.8.0" dependencies = [ "cargo-util-schemas", "cargo_metadata", @@ -1625,7 +1631,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf3432d9f609fbede9f624d1dbefcce77985a9322de1d0e6d460ec05502b7fd0" dependencies = [ - "vmm-sys-util", + "vmm-sys-util 0.14.0", ] [[package]] @@ -1637,7 +1643,7 @@ dependencies = [ "bitflags 2.9.1", "kvm-bindings", "libc", - "vmm-sys-util", + "vmm-sys-util 0.14.0", ] [[package]] @@ -1858,7 +1864,7 @@ checksum = "f416b4432174e5a3f956a7887f4c1a4acea9511d81def67fcb8473293630ab9e" dependencies = [ "libc", "num_enum", - "vmm-sys-util", + "vmm-sys-util 0.15.0", "zerocopy 0.7.35", ] @@ -1870,7 +1876,7 @@ checksum = "1e0cb5031f3243a7459b7c13d960d25420980874eebda816db24ce6077e21d43" dependencies = [ "libc", "num_enum", - "vmm-sys-util", + "vmm-sys-util 0.15.0", "zerocopy 0.8.25", ] @@ -1883,7 +1889,7 @@ dependencies = [ "libc", "mshv-bindings 0.2.1", "thiserror 1.0.69", - "vmm-sys-util", + "vmm-sys-util 0.15.0", ] [[package]] @@ -1895,7 +1901,7 @@ dependencies = [ "libc", "mshv-bindings 0.3.2", "thiserror 2.0.12", - "vmm-sys-util", + "vmm-sys-util 0.15.0", ] [[package]] @@ -2132,9 +2138,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.35" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" +checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" dependencies = [ "proc-macro2", "syn", @@ -3095,6 +3101,17 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" +dependencies = [ + "getrandom 0.3.3", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "valuable" version = "0.1.1" @@ -3123,6 +3140,16 @@ dependencies = [ "libc", ] +[[package]] +name = "vmm-sys-util" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "506c62fdf617a5176827c2f9afbcf1be155b03a9b4bf9617a60dbc07e3a1642f" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -3222,7 +3249,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3bc393c395cb621367ff02d854179882b9a351b4e0c93d1397e6090b53a5c2a" dependencies = [ "leb128fmt", - "wasmparser", + "wasmparser 0.235.0", ] [[package]] @@ -3238,6 +3265,19 @@ dependencies = [ "serde", ] +[[package]] +name = "wasmparser" +version = "0.236.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d1eee846a705f6f3cb9d7b9f79b54583810f1fb57a1e3aea76d1742db2e3d2" +dependencies = [ + "bitflags 2.9.1", + "hashbrown", + "indexmap", + "semver", + "serde", +] + [[package]] name = "wasmprinter" version = "0.235.0" @@ -3246,7 +3286,7 @@ checksum = "75aa8e9076de6b9544e6dab4badada518cca0bf4966d35b131bbd057aed8fa0a" dependencies = [ "anyhow", "termcolor", - "wasmparser", + "wasmparser 0.235.0", ] [[package]] @@ -3278,7 +3318,7 @@ dependencies = [ "serde_derive", "smallvec", "target-lexicon", - "wasmparser", + "wasmparser 0.235.0", "wasmtime-environ", "wasmtime-internal-asm-macros", "wasmtime-internal-component-macro", @@ -3314,7 +3354,7 @@ dependencies = [ "smallvec", "target-lexicon", "wasm-encoder", - "wasmparser", + "wasmparser 0.235.0", "wasmprinter", "wasmtime-internal-component-util", ] @@ -3370,7 +3410,7 @@ dependencies = [ "smallvec", "target-lexicon", "thiserror 2.0.12", - "wasmparser", + "wasmparser 0.235.0", "wasmtime-environ", "wasmtime-internal-math", "wasmtime-internal-versioned-export-macros", @@ -3454,7 +3494,7 @@ dependencies = [ "gimli", "object", "target-lexicon", - "wasmparser", + "wasmparser 0.235.0", "wasmtime-environ", "wasmtime-internal-cranelift", "winch-codegen", @@ -3539,7 +3579,7 @@ dependencies = [ "smallvec", "target-lexicon", "thiserror 2.0.12", - "wasmparser", + "wasmparser 0.235.0", "wasmtime-environ", "wasmtime-internal-cranelift", "wasmtime-internal-math", @@ -3853,7 +3893,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser", + "wasmparser 0.235.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 5db9026..75491ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ exclude = [ "src/wasm_runtime", "src/rust_wasm_samples", "src/hyperlight_wasm_m resolver = "2" [workspace.package] -version = "0.7.0" +version = "0.8.0" edition = "2024" rust-version = "1.86" license = "Apache-2.0" @@ -13,4 +13,4 @@ repository = "https://github.com/hyperlight-dev/hyperlight-wasm" readme = "README.md" [workspace.dependencies] -hyperlight-host = { version = "0.7.0", git = "https://github.com/hyperlight-dev/hyperlight", rev = "ea6fa8f", default-features = false, features = ["executable_heap", "init-paging"] } +hyperlight-host = { version = "0.8.0", default-features = false, features = ["executable_heap", "init-paging"] } diff --git a/Justfile b/Justfile index 5cc4e74..9d3adf8 100644 --- a/Justfile +++ b/Justfile @@ -19,9 +19,9 @@ ensure-tools: cargo install cargo-component --locked --version 0.21.1 cargo install wit-bindgen-cli --locked --version 0.43.0 -build-all target=default-target: (build target) (build-wasm-examples target) (build-rust-wasm-examples target) (build-wasm-runtime target) (build-rust-component-examples target) +build-all target=default-target: (build target) (build-wasm-examples target) (build-rust-wasm-examples target) (build-rust-component-examples target) (build-wasm-runtime target) -build target=default-target features="": (build-wasm-runtime target) (fmt-check) +build target=default-target features="": (fmt-check) cargo build {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--no-default-features -F " + features } }} --verbose --profile={{ if target == "debug" {"dev"} else { target } }} mkdir-redist target=default-target: @@ -89,16 +89,16 @@ test target=default-target features="": (test-seccomp target features) cargo test test_metrics {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} -- --ignored test-seccomp target=default-target features="": - cargo test {{ if features =="" {'--no-default-features -F "kvm,mshv2,seccomp"'} else {"--no-default-features -F seccomp," + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} -- --test-threads=1 - cargo test {{ if features =="" {'--no-default-features -F "kvm,mshv2,seccomp"'} else {"--no-default-features -F seccomp," + features } }} test_metrics --profile={{ if target == "debug" {"dev"} else { target } }} -- --ignored --test-threads=1 - cargo test {{ if features =="" {'--no-default-features -F "kvm,mshv2,seccomp"'} else {"--no-default-features -F seccomp," + features } }} test_gather_metrics --profile={{ if target == "debug" {"dev"} else { target } }} -- --ignored --test-threads=1 + cargo test {{ if features =="" {'--no-default-features -F "kvm,mshv3,seccomp"'} else {"--no-default-features -F seccomp," + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} -- --test-threads=1 + cargo test {{ if features =="" {'--no-default-features -F "kvm,mshv3,seccomp"'} else {"--no-default-features -F seccomp," + features } }} test_metrics --profile={{ if target == "debug" {"dev"} else { target } }} -- --ignored --test-threads=1 + cargo test {{ if features =="" {'--no-default-features -F "kvm,mshv3,seccomp"'} else {"--no-default-features -F seccomp," + features } }} test_gather_metrics --profile={{ if target == "debug" {"dev"} else { target } }} -- --ignored --test-threads=1 examples-ci target=default-target features="": (build-rust-wasm-examples target) cargo run {{ if features =="" {''} else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example helloworld cargo run {{ if features =="" {''} else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example hostfuncs cargo run {{ if features =="" {''} else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example rust_wasm_examples cargo run {{ if features =="" {''} else {"--no-default-features -F function_call_metrics," + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example metrics - cargo run {{ if features =="" {"--no-default-features --features kvm,mshv2"} else {"--no-default-features -F function_call_metrics," + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example metrics + cargo run {{ if features =="" {"--no-default-features --features kvm,mshv3"} else {"--no-default-features -F function_call_metrics," + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example metrics examples-components target=default-target features="": (build-rust-component-examples target) {{ wit-world }} cargo run {{ if features =="" {''} else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example component_example diff --git a/src/hyperlight_wasm/Cargo.toml b/src/hyperlight_wasm/Cargo.toml index 2570b62..78f215c 100644 --- a/src/hyperlight_wasm/Cargo.toml +++ b/src/hyperlight_wasm/Cargo.toml @@ -58,7 +58,7 @@ windows = { version = "0.61", features = ["Win32_System_Threading"] } page_size = "0.6.0" [dev-dependencies] -hyperlight-component-macro = { version = "0.7.0", git = "https://github.com/hyperlight-dev/hyperlight", rev = "b61265e4aa9e2ecf8d648b994022caeea0205352" } +hyperlight-component-macro = { version = "0.8.0" } examples_common = { path = "../examples_common" } criterion = { version = "0.7.0", features = ["html_reports"] } crossbeam-queue = "0.3" @@ -76,7 +76,7 @@ goblin = "0.10.0" tar = "0.4.44" [features] -default = ["function_call_metrics", "kvm", "mshv2"] +default = ["function_call_metrics", "kvm", "mshv3"] function_call_metrics = ["hyperlight-host/function_call_metrics"] seccomp = ["hyperlight-host/seccomp"] print_debug = ["hyperlight-host/print_debug"] diff --git a/src/hyperlight_wasm/src/lib.rs b/src/hyperlight_wasm/src/lib.rs index f974da6..4a022e6 100644 --- a/src/hyperlight_wasm/src/lib.rs +++ b/src/hyperlight_wasm/src/lib.rs @@ -39,6 +39,8 @@ pub type Result = hyperlight_host::Result; pub use hyperlight_host::is_hypervisor_present; /// Create a generic HyperlightError pub use hyperlight_host::new_error; +// A snapshot of the memory of a sandbox at a given point in time. +pub use hyperlight_host::sandbox::snapshot::Snapshot; /// Get the build information for this version of hyperlight-wasm pub fn get_build_info() -> BuildInfo { diff --git a/src/hyperlight_wasm/src/sandbox/loaded_wasm_sandbox.rs b/src/hyperlight_wasm/src/sandbox/loaded_wasm_sandbox.rs index b90c62c..e20371f 100644 --- a/src/hyperlight_wasm/src/sandbox/loaded_wasm_sandbox.rs +++ b/src/hyperlight_wasm/src/sandbox/loaded_wasm_sandbox.rs @@ -14,14 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ +use std::fmt::Debug; use std::sync::Arc; use hyperlight_host::func::{ParameterTuple, SupportedReturnType}; // re-export the InterruptHandle trait as it's part of the public API pub use hyperlight_host::hypervisor::InterruptHandle; use hyperlight_host::sandbox::Callable; -use hyperlight_host::sandbox_state::sandbox::{DevolvableSandbox, Sandbox}; -use hyperlight_host::sandbox_state::transition::Noop; +use hyperlight_host::sandbox::snapshot::Snapshot; use hyperlight_host::{MultiUseSandbox, Result, log_then_return, new_error}; use super::metrics::METRIC_TOTAL_LOADED_WASM_SANDBOXES; @@ -37,16 +37,15 @@ use crate::sandbox::metrics::{METRIC_ACTIVE_LOADED_WASM_SANDBOXES, METRIC_SANDBO /// memory context. If you want to "reset" the memory context, create /// a new `LoadedWasmSandbox` -- either from another `WasmSandbox` or by /// calling `my_loaded_wasm_sandbox.devolve()?.evolve()?` -#[derive(Debug)] pub struct LoadedWasmSandbox { // inner is an Option as we need to take ownership of it // We implement drop on the LoadedWasmSandbox to decrement the count of Sandboxes when it is dropped // because of this we cannot implement drop without making inner an Option (alternatively we could make MultiUseSandbox Copy but that would introduce other issues) inner: Option, + // The state the sandbox was in before loading a wasm module. Used for transitioning back to a `WasmSandbox` (unloading the wasm module). + runtime_snapshot: Option, } -impl Sandbox for LoadedWasmSandbox {} - impl LoadedWasmSandbox { /// Call the function in the guest with the name `fn_name`, passing /// parameters `params`. @@ -60,21 +59,54 @@ impl LoadedWasmSandbox { params: impl ParameterTuple, ) -> Result { match &mut self.inner { - Some(inner) => inner.call_guest_function_by_name(fn_name, params), - None => log_then_return!("No inner MultiUseSandbox to call_guest_function"), + Some(inner) => inner.call(fn_name, params), + None => log_then_return!("No inner MultiUseSandbox to call"), + } + } + + /// Take a snapshot of the current state of the sandbox. + pub fn snapshot(&mut self) -> Result { + match &mut self.inner { + Some(inner) => inner.snapshot(), + None => log_then_return!("No inner MultiUseSandbox to snapshot"), } } + + /// Restore the state of the sandbox to the state captured in the given snapshot. + pub fn restore(&mut self, snapshot: &Snapshot) -> Result<()> { + match &mut self.inner { + Some(inner) => inner.restore(snapshot), + None => log_then_return!("No inner MultiUseSandbox to restore"), + } + } + /// unload the wasm module and return a `WasmSandbox` that can be used to load another module - pub fn unload_module(self) -> Result { - self.devolve(Noop::default()).inspect(|_| { + pub fn unload_module(mut self) -> Result { + let sandbox = self + .inner + .take() + .ok_or_else(|| new_error!("No inner MultiUseSandbox to unload"))?; + + let snapshot = self + .runtime_snapshot + .take() + .ok_or_else(|| new_error!("No snapshot of the WasmSandbox to unload"))?; + + WasmSandbox::new_from_loaded(sandbox, snapshot).inspect(|_| { metrics::counter!(METRIC_SANDBOX_UNLOADS).increment(1); }) } - pub(super) fn new(inner: MultiUseSandbox) -> Result { + pub(super) fn new( + inner: MultiUseSandbox, + runtime_snapshot: Snapshot, + ) -> Result { metrics::gauge!(METRIC_ACTIVE_LOADED_WASM_SANDBOXES).increment(1); metrics::counter!(METRIC_TOTAL_LOADED_WASM_SANDBOXES).increment(1); - Ok(LoadedWasmSandbox { inner: Some(inner) }) + Ok(LoadedWasmSandbox { + inner: Some(inner), + runtime_snapshot: Some(runtime_snapshot), + }) } /// Get a handle to the interrupt handler for this sandbox, @@ -100,26 +132,20 @@ impl Callable for LoadedWasmSandbox { } } -/// Capability to transform a `LoadedWasmSandbox` back down to a -/// `WasmSandbox` -impl DevolvableSandbox> - for LoadedWasmSandbox -{ - fn devolve(mut self, _: Noop) -> Result { - let new_inner: MultiUseSandbox = match self.inner.take() { - Some(inner) => inner.devolve(Noop::default())?, - None => log_then_return!("No inner MultiUseSandbox to devolve"), - }; - Ok(WasmSandbox::new(new_inner)) - } -} - impl Drop for LoadedWasmSandbox { fn drop(&mut self) { metrics::gauge!(METRIC_ACTIVE_LOADED_WASM_SANDBOXES).decrement(1); } } +impl Debug for LoadedWasmSandbox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("LoadedWasmSandbox") + .field("inner", &self.inner) + .finish() + } +} + #[cfg(test)] mod tests { use std::sync::Arc; @@ -161,7 +187,7 @@ mod tests { } .unwrap(); - call_funcs(loaded_wasm_sandbox, 1000); + call_funcs(loaded_wasm_sandbox, 500); } #[test] diff --git a/src/hyperlight_wasm/src/sandbox/metrics.rs b/src/hyperlight_wasm/src/sandbox/metrics.rs index 834a5a1..e19c658 100644 --- a/src/hyperlight_wasm/src/sandbox/metrics.rs +++ b/src/hyperlight_wasm/src/sandbox/metrics.rs @@ -35,8 +35,16 @@ pub(crate) static METRIC_SANDBOX_UNLOADS: &str = "sandbox_unloads_total"; #[cfg(test)] mod tests { use examples_common::get_wasm_module_path; + use hyperlight_host::HyperlightError; - use crate::{LoadedWasmSandbox, ProtoWasmSandbox}; + use crate::{LoadedWasmSandbox, ProtoWasmSandbox, Result}; + + fn get_time_since_boot_microsecond() -> Result { + let res = std::time::SystemTime::now() + .duration_since(std::time::SystemTime::UNIX_EPOCH)? + .as_micros(); + i64::try_from(res).map_err(HyperlightError::IntConversionFailure) + } #[test] #[ignore = "Needs to run separately to not get influenced by other tests"] @@ -46,7 +54,13 @@ mod tests { recorder.install().unwrap(); let snapshot = { - let sandbox = ProtoWasmSandbox::default(); + let mut sandbox = ProtoWasmSandbox::default(); + sandbox + .register( + "GetTimeSinceBootMicrosecond", + get_time_since_boot_microsecond, + ) + .unwrap(); let wasm_sandbox = sandbox.load_runtime().unwrap(); let loaded_wasm_sandbox: LoadedWasmSandbox = { @@ -57,6 +71,10 @@ mod tests { snapshotter.snapshot() }; let snapshot = snapshot.into_vec(); - assert_eq!(snapshot.len(), 8); + if cfg!(feature = "function_call_metrics") { + assert_eq!(snapshot.len(), 10); + } else { + assert_eq!(snapshot.len(), 8); + } } } diff --git a/src/hyperlight_wasm/src/sandbox/proto_wasm_sandbox.rs b/src/hyperlight_wasm/src/sandbox/proto_wasm_sandbox.rs index 551096c..2aa93f4 100644 --- a/src/hyperlight_wasm/src/sandbox/proto_wasm_sandbox.rs +++ b/src/hyperlight_wasm/src/sandbox/proto_wasm_sandbox.rs @@ -14,15 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -use hyperlight_host::func::call_ctx::MultiUseGuestCallContext; use hyperlight_host::func::{HostFunction, ParameterTuple, Registerable, SupportedReturnType}; -use hyperlight_host::sandbox::Callable; #[cfg(all(feature = "seccomp", target_os = "linux"))] use hyperlight_host::sandbox::ExtraAllowedSyscall; use hyperlight_host::sandbox::config::SandboxConfiguration; -use hyperlight_host::sandbox_state::sandbox::{EvolvableSandbox, Sandbox}; -use hyperlight_host::sandbox_state::transition::{MultiUseContextCallback, Noop}; -use hyperlight_host::{GuestBinary, MultiUseSandbox, Result, UninitializedSandbox, new_error}; +use hyperlight_host::{GuestBinary, Result, UninitializedSandbox, new_error}; use super::metrics::{METRIC_ACTIVE_PROTO_WASM_SANDBOXES, METRIC_TOTAL_PROTO_WASM_SANDBOXES}; use super::sandbox_builder::SandboxBuilder; @@ -39,8 +35,6 @@ pub struct ProtoWasmSandbox { pub(super) inner: Option, } -impl Sandbox for ProtoWasmSandbox {} - impl Registerable for ProtoWasmSandbox { fn register_host_function( &mut self, @@ -95,27 +89,20 @@ impl ProtoWasmSandbox { /// The returned `WasmSandbox` can be then be cached and used to load a different Wasm module. /// pub fn load_runtime(mut self) -> Result { - let multi_use_sandbox: MultiUseSandbox = match self.inner.take() { - Some(s) => s.evolve(Noop::default())?, + let mut sandbox = match self.inner.take() { + Some(s) => s.evolve()?, None => return Err(new_error!("No inner sandbox found.")), }; - let func = Box::new(move |call_ctx: &mut MultiUseGuestCallContext| { - let res: i32 = call_ctx.call("InitWasmRuntime", ())?; - if res != 0 { - return Err(new_error!( - "InitWasmRuntime Failed with error code {:?}", - res - )); - } - Ok(()) - }); - - let transition_func = MultiUseContextCallback::from(func); - - let new_sbox: MultiUseSandbox = multi_use_sandbox.evolve(transition_func)?; + let res: i32 = sandbox.call("InitWasmRuntime", ())?; + if res != 0 { + return Err(new_error!( + "InitWasmRuntime Failed with error code {:?}", + res + )); + } - Ok(WasmSandbox::new(new_sbox)) + WasmSandbox::new(sandbox) } /// Register the given host function `host_func` with `self` under diff --git a/src/hyperlight_wasm/src/sandbox/wasm_sandbox.rs b/src/hyperlight_wasm/src/sandbox/wasm_sandbox.rs index ad382da..2629e34 100644 --- a/src/hyperlight_wasm/src/sandbox/wasm_sandbox.rs +++ b/src/hyperlight_wasm/src/sandbox/wasm_sandbox.rs @@ -16,11 +16,8 @@ limitations under the License. use std::path::Path; -use hyperlight_host::func::call_ctx::MultiUseGuestCallContext; use hyperlight_host::mem::memory_region::{MemoryRegion, MemoryRegionFlags, MemoryRegionType}; -use hyperlight_host::sandbox::Callable; -use hyperlight_host::sandbox_state::sandbox::{EvolvableSandbox, Sandbox}; -use hyperlight_host::sandbox_state::transition::MultiUseContextCallback; +use hyperlight_host::sandbox::snapshot::Snapshot; use hyperlight_host::{MultiUseSandbox, Result, new_error}; use super::loaded_wasm_sandbox::LoadedWasmSandbox; @@ -39,20 +36,39 @@ pub struct WasmSandbox { // We implement drop on the WasmSandbox to decrement the count of Sandboxes when it is dropped // because of this we cannot implement drop without making inner an Option (alternatively we could make MultiUseSandbox Copy but that would introduce other issues) inner: Option, + // Snapshot of state of an initial WasmSandbox (runtime loaded, but no guest module code loaded). + // Used for LoadedWasmSandbox to be able restore state back to WasmSandbox + snapshot: Option, } -impl Sandbox for WasmSandbox {} - const MAPPED_BINARY_VA: u64 = 0x1_0000_0000u64; impl WasmSandbox { /// Create a new WasmSandBox from a `MultiUseSandbox`. /// This function should be used to create a new `WasmSandbox` from a ProtoWasmSandbox. /// The difference between this function and creating a `WasmSandbox` directly is that /// this function will increment the metrics for the number of `WasmSandbox`es in the system. - pub(super) fn new(inner: MultiUseSandbox) -> Self { + pub(super) fn new(mut inner: MultiUseSandbox) -> Result { + let snapshot = inner.snapshot()?; + metrics::gauge!(METRIC_ACTIVE_WASM_SANDBOXES).increment(1); + metrics::counter!(METRIC_TOTAL_WASM_SANDBOXES).increment(1); + Ok(WasmSandbox { + inner: Some(inner), + snapshot: Some(snapshot), + }) + } + + /// Same as new, but doesn't take a new snapshot. Useful if `new` has already been called, + /// for example when creating a `WasmSandbox` from a `LoadedWasmSandbox`, since + /// the snapshot has already been created in that case. + /// Expects a snapshot of the state where wasm runtime is loaded, but no guest module code is loaded. + pub(super) fn new_from_loaded(mut loaded: MultiUseSandbox, snapshot: Snapshot) -> Result { + loaded.restore(&snapshot)?; metrics::gauge!(METRIC_ACTIVE_WASM_SANDBOXES).increment(1); metrics::counter!(METRIC_TOTAL_WASM_SANDBOXES).increment(1); - WasmSandbox { inner: Some(inner) } + Ok(WasmSandbox { + inner: Some(loaded), + snapshot: Some(snapshot), + }) } /// Load a Wasm module at the given path into the sandbox and return a `LoadedWasmSandbox` @@ -60,16 +76,20 @@ impl WasmSandbox { /// /// Before you can call guest functions in the sandbox, you must call /// this function and use the returned value to call guest functions. - pub fn load_module(self, file: impl AsRef) -> Result { - let func = Box::new(move |call_ctx: &mut MultiUseGuestCallContext| { - if let Ok(len) = call_ctx.map_file_cow(file.as_ref(), MAPPED_BINARY_VA) { - call_ctx.call("LoadWasmModulePhys", (MAPPED_BINARY_VA, len)) - } else { - let wasm_bytes = std::fs::read(file)?; - Self::load_module_from_buffer_transition_func(wasm_bytes)(call_ctx) - } - }); - self.load_module_inner(func) + pub fn load_module(mut self, file: impl AsRef) -> Result { + let inner = self + .inner + .as_mut() + .ok_or_else(|| new_error!("WasmSandbox is None"))?; + + if let Ok(len) = inner.map_file_cow(file.as_ref(), MAPPED_BINARY_VA) { + inner.call::<()>("LoadWasmModulePhys", (MAPPED_BINARY_VA, len))?; + } else { + let wasm_bytes = std::fs::read(file)?; + load_wasm_module_from_bytes(inner, wasm_bytes)?; + } + + self.finalize_module_load() } /// Load a Wasm module that is currently present in a buffer in @@ -84,45 +104,30 @@ impl WasmSandbox { /// of the region remains intact and is not written to until the /// produced LoadedWasmSandbox is discarded or devolved. pub unsafe fn load_module_by_mapping( - self, + mut self, base: *mut libc::c_void, len: usize, ) -> Result { - let func = Box::new(move |call_ctx: &mut MultiUseGuestCallContext| { - let guest_base: usize = MAPPED_BINARY_VA as usize; - let rgn = MemoryRegion { - host_region: base as usize..base.wrapping_add(len) as usize, - guest_region: guest_base..guest_base + len, - flags: MemoryRegionFlags::READ | MemoryRegionFlags::EXECUTE, - region_type: MemoryRegionType::Heap, - }; - if let Ok(()) = unsafe { call_ctx.map_region(&rgn) } { - call_ctx.call("LoadWasmModulePhys", (MAPPED_BINARY_VA, len as u64)) - } else { - let wasm_bytes = - unsafe { std::slice::from_raw_parts(base as *const u8, len).to_vec() }; - Self::load_module_from_buffer_transition_func(wasm_bytes)(call_ctx) - } - }); - self.load_module_inner(func) - } - - // todo: take a slice rather than a vec (requires somewhat - // refactoring the flatbuffers stuff maybe) - fn load_module_from_buffer_transition_func( - buffer: Vec, - ) -> impl FnOnce(&mut MultiUseGuestCallContext) -> Result<()> { - move |call_ctx: &mut MultiUseGuestCallContext| { - let len = buffer.len() as i32; - let res: i32 = call_ctx.call("LoadWasmModule", (buffer, len))?; - if res != 0 { - return Err(new_error!( - "LoadWasmModule Failed with error code {:?}", - res - )); - } - Ok(()) + let inner = self + .inner + .as_mut() + .ok_or_else(|| new_error!("WasmSandbox is None"))?; + + let guest_base: usize = MAPPED_BINARY_VA as usize; + let rgn = MemoryRegion { + host_region: base as usize..base.wrapping_add(len) as usize, + guest_region: guest_base..guest_base + len, + flags: MemoryRegionFlags::READ | MemoryRegionFlags::EXECUTE, + region_type: MemoryRegionType::Heap, + }; + if let Ok(()) = unsafe { inner.map_region(&rgn) } { + inner.call::<()>("LoadWasmModulePhys", (MAPPED_BINARY_VA, len as u64))?; + } else { + let wasm_bytes = unsafe { std::slice::from_raw_parts(base as *const u8, len).to_vec() }; + load_wasm_module_from_bytes(inner, wasm_bytes)?; } + + self.finalize_module_load() } /// Load a Wasm module from a buffer of bytes into the sandbox and return a `LoadedWasmSandbox` @@ -130,29 +135,44 @@ impl WasmSandbox { /// /// Before you can call guest functions in the sandbox, you must call /// this function and use the returned value to call guest functions. - pub fn load_module_from_buffer(self, buffer: &[u8]) -> Result { + pub fn load_module_from_buffer(mut self, buffer: &[u8]) -> Result { + let inner = self + .inner + .as_mut() + .ok_or_else(|| new_error!("WasmSandbox is None"))?; + // TODO: get rid of this clone - let func = Self::load_module_from_buffer_transition_func(buffer.to_vec()); + load_wasm_module_from_bytes(inner, buffer.to_vec())?; - self.load_module_inner(func) + self.finalize_module_load() } - fn load_module_inner Result<()>>( - mut self, - func: F, - ) -> Result { - let transition_func = MultiUseContextCallback::from(func); - match self.inner.take() { - Some(sbox) => { - let new_sbox: MultiUseSandbox = sbox.evolve(transition_func)?; - metrics::counter!(METRIC_SANDBOX_LOADS).increment(1); - LoadedWasmSandbox::new(new_sbox) - } - None => Err(new_error!("WasmSandbox is None, cannot load module")), + /// Helper function to finalize module loading and create LoadedWasmSandbox + fn finalize_module_load(mut self) -> Result { + metrics::counter!(METRIC_SANDBOX_LOADS).increment(1); + match (self.inner.take(), self.snapshot.take()) { + (Some(sandbox), Some(snapshot)) => LoadedWasmSandbox::new(sandbox, snapshot), + _ => Err(new_error!( + "WasmSandbox/snapshot is None, cannot load module" + )), } } } +fn load_wasm_module_from_bytes(inner: &mut MultiUseSandbox, wasm_bytes: Vec) -> Result<()> { + let res: i32 = inner.call( + "LoadWasmModule", + (wasm_bytes.clone(), wasm_bytes.len() as i32), + )?; + if res != 0 { + return Err(new_error!( + "LoadWasmModule Failed with error code {:?}", + res + )); + } + Ok(()) +} + impl std::fmt::Debug for WasmSandbox { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("WasmSandbox").finish() diff --git a/src/hyperlight_wasm_macro/Cargo.lock b/src/hyperlight_wasm_macro/Cargo.lock index 3b01b24..03e9b44 100644 --- a/src/hyperlight_wasm_macro/Cargo.lock +++ b/src/hyperlight_wasm_macro/Cargo.lock @@ -39,7 +39,7 @@ dependencies = [ [[package]] name = "hyperlight-component-util" version = "0.7.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=b61265e4aa9e2ecf8d648b994022caeea0205352#b61265e4aa9e2ecf8d648b994022caeea0205352" +source = "git+https://github.com/hyperlight-dev/hyperlight?rev=172fcfa69b0f9064c7a0e48e512f8a86ae1fdbe1#172fcfa69b0f9064c7a0e48e512f8a86ae1fdbe1" dependencies = [ "itertools", "log", diff --git a/src/hyperlight_wasm_macro/Cargo.toml b/src/hyperlight_wasm_macro/Cargo.toml index 3c2a2fc..38de5b0 100644 --- a/src/hyperlight_wasm_macro/Cargo.toml +++ b/src/hyperlight_wasm_macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hyperlight-wasm-macro" -version = "0.7.0" +version = "0.8.0" edition = "2024" description = """ Procedural macros to generate Hyperlight Wasm host and guest bindings from component types @@ -16,4 +16,4 @@ proc-macro2 = { version = "1.0.93" } syn = { version = "2.0.96" } itertools = { version = "0.14.0" } prettyplease = { version = "0.2.31" } -hyperlight-component-util = { version = "0.7.0", git = "https://github.com/hyperlight-dev/hyperlight", rev = "b61265e4aa9e2ecf8d648b994022caeea0205352" } +hyperlight-component-util = { version = "0.8.0" } diff --git a/src/hyperlight_wasm_macro/src/wasmguest.rs b/src/hyperlight_wasm_macro/src/wasmguest.rs index 02c2dce..01fd499 100644 --- a/src/hyperlight_wasm_macro/src/wasmguest.rs +++ b/src/hyperlight_wasm_macro/src/wasmguest.rs @@ -212,15 +212,17 @@ fn emit_wasm_function_call( let rwt = match result { None => { quote! { - instance.get_typed_func::<(#(#pwts,)*), ()>(&mut *store, func_idx)? - .call(&mut *store, (#(#pus,)*))?; + let func = instance.get_typed_func::<(#(#pwts,)*), ()>(&mut *store, func_idx)?; + func.call(&mut *store, (#(#pus,)*))?; + func.post_return(&mut *store)?; } } _ => { let r = rtypes::emit_func_result(s, result); quote! { - let #ret = instance.get_typed_func::<(#(#pwts,)*), ((#r,))>(&mut *store, func_idx)? - .call(&mut *store, (#(#pus,)*))?.0; + let func = instance.get_typed_func::<(#(#pwts,)*), ((#r,))>(&mut *store, func_idx)?; + let #ret = func.call(&mut *store, (#(#pus,)*))?.0; + func.post_return(&mut *store)?; } } }; diff --git a/src/wasm_runtime/Cargo.lock b/src/wasm_runtime/Cargo.lock index 4e9d307..f37d3b1 100644 --- a/src/wasm_runtime/Cargo.lock +++ b/src/wasm_runtime/Cargo.lock @@ -37,9 +37,9 @@ checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" @@ -53,7 +53,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -79,9 +79,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.18.1" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" dependencies = [ "allocator-api2", ] @@ -94,9 +94,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "camino" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da45bc31171d8d6960122e222a67740df867c1dd53b4d51caa297084c185cab" +checksum = "5d07aa9a93b00c76f71bc35d598bed923f6d4f3a9ca5c24b7737ae1a292841c0" dependencies = [ "serde", ] @@ -126,9 +126,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.26" +version = "1.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" +checksum = "2352e5597e9c544d5e6d9c95190d5d27738ade584fa8db0a16e130e5c2b5296e" dependencies = [ "shlex", ] @@ -147,9 +147,12 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "cobs" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror", +] [[package]] name = "cranelift-assembler-x64" @@ -290,9 +293,9 @@ checksum = "b530783809a55cb68d070e0de60cfbb3db0dc94c8850dd5725411422bedcf6bb" [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] @@ -343,12 +346,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -478,15 +481,15 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "foldhash", "serde", @@ -576,9 +579,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" dependencies = [ "base64", "bytes", @@ -592,7 +595,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.0", "tokio", "tower-service", "tracing", @@ -600,8 +603,9 @@ dependencies = [ [[package]] name = "hyperlight-common" -version = "0.7.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=ea6fa8f#ea6fa8f16dae2325d94af39eb6ac3b441b24dcac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52423b32cefb31363194a332da0ed440c550407a8c2f2acf1c837e77b09cc06c" dependencies = [ "anyhow", "flatbuffers", @@ -611,8 +615,9 @@ dependencies = [ [[package]] name = "hyperlight-component-util" -version = "0.7.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=b61265e4aa9e2ecf8d648b994022caeea0205352#b61265e4aa9e2ecf8d648b994022caeea0205352" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34b2db33623c8d0e97e9be913064843621a1260cce140a15dc3b0da9378d45" dependencies = [ "itertools", "log", @@ -620,23 +625,26 @@ dependencies = [ "proc-macro2", "quote", "syn", - "wasmparser", + "wasmparser 0.236.0", ] [[package]] name = "hyperlight-guest" -version = "0.7.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=ea6fa8f#ea6fa8f16dae2325d94af39eb6ac3b441b24dcac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa8cf088e745392262a57e344a1b08dabf79d72bfd90508e5f6e60290228141" dependencies = [ "anyhow", "hyperlight-common", + "hyperlight-guest-tracing", "serde_json", ] [[package]] name = "hyperlight-guest-bin" -version = "0.7.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=ea6fa8f#ea6fa8f16dae2325d94af39eb6ac3b441b24dcac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fd6cd25eaa0cbc22c67adae0c25d402409480eca9a184708b7de20e88c09e0a" dependencies = [ "buddy_system_allocator", "cc", @@ -644,13 +652,36 @@ dependencies = [ "glob", "hyperlight-common", "hyperlight-guest", + "hyperlight-guest-tracing", "log", "spin 0.10.0", ] +[[package]] +name = "hyperlight-guest-tracing" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79aea31011bf30126cbb1af667d53b344e8f39a0a0bd6d5e4d8f692ecd5151ab" +dependencies = [ + "hyperlight-common", + "hyperlight-guest-tracing-macro", + "spin 0.10.0", +] + +[[package]] +name = "hyperlight-guest-tracing-macro" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c57ab09dcec3021c972eefa4046c5ae4b06cfc777c673bbc6af773a066a28f4f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "hyperlight-wasm-macro" -version = "0.7.0" +version = "0.8.0" dependencies = [ "hyperlight-component-util", "itertools", @@ -775,15 +806,26 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown", "serde", ] +[[package]] +name = "io-uring" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" +dependencies = [ + "bitflags", + "cfg-if", + "libc", +] + [[package]] name = "ipnet" version = "2.11.0" @@ -833,9 +875,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.172" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "libm" @@ -879,18 +921,18 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" [[package]] name = "mach2" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" dependencies = [ "libc", ] [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memfd" @@ -959,9 +1001,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "postcard" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" dependencies = [ "cobs", "embedded-io 0.4.0", @@ -989,9 +1031,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.35" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" +checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" dependencies = [ "proc-macro2", "syn", @@ -999,9 +1041,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "d61789d7719defeb74ea5fe81f2fdfdbd28a803847077cecce2ff14e1472f6f1" dependencies = [ "unicode-ident", ] @@ -1042,7 +1084,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2", + "socket2 0.5.10", "thiserror", "tokio", "tracing", @@ -1072,14 +1114,14 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842" +checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2", + "socket2 0.5.10", "tracing", "windows-sys 0.59.0", ] @@ -1095,15 +1137,15 @@ dependencies = [ [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha", "rand_core", @@ -1144,9 +1186,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.20" +version = "0.12.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabf4c97d9130e2bf606614eb937e86edac8292eaa6f422f995d7e8de1eb1813" +checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" dependencies = [ "base64", "bytes", @@ -1198,9 +1240,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" @@ -1232,9 +1274,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.27" +version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ "once_cell", "ring", @@ -1256,9 +1298,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.3" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ "ring", "rustls-pki-types", @@ -1267,9 +1309,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -1314,9 +1356,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" dependencies = [ "itoa", "memchr", @@ -1344,12 +1386,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" @@ -1370,6 +1409,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "spin" version = "0.9.8" @@ -1448,18 +1497,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "c0b43c71ffa7199f8a00fe309ac01551e3c35105b50ceacd7f67ce080ec18fdf" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "c65da2500f2800e48970ef01d47aeb80e328e38adf723def51b5ad1d0a8ca03e" dependencies = [ "proc-macro2", "quote", @@ -1493,17 +1542,19 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.45.1" +version = "1.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", "bytes", + "io-uring", "libc", "mio", "pin-project-lite", - "socket2", - "windows-sys 0.52.0", + "slab", + "socket2 0.6.0", + "windows-sys 0.59.0", ] [[package]] @@ -1723,12 +1774,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3bc393c395cb621367ff02d854179882b9a351b4e0c93d1397e6090b53a5c2a" dependencies = [ "leb128fmt", - "wasmparser", + "wasmparser 0.235.0", ] [[package]] name = "wasm-runtime" -version = "0.7.0" +version = "0.8.0" dependencies = [ "cargo_metadata", "cc", @@ -1755,6 +1806,19 @@ dependencies = [ "serde", ] +[[package]] +name = "wasmparser" +version = "0.236.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d1eee846a705f6f3cb9d7b9f79b54583810f1fb57a1e3aea76d1742db2e3d2" +dependencies = [ + "bitflags", + "hashbrown", + "indexmap", + "semver", + "serde", +] + [[package]] name = "wasmprinter" version = "0.235.0" @@ -1763,7 +1827,7 @@ checksum = "75aa8e9076de6b9544e6dab4badada518cca0bf4966d35b131bbd057aed8fa0a" dependencies = [ "anyhow", "termcolor", - "wasmparser", + "wasmparser 0.235.0", ] [[package]] @@ -1792,7 +1856,7 @@ dependencies = [ "serde_derive", "smallvec", "target-lexicon", - "wasmparser", + "wasmparser 0.235.0", "wasmtime-environ", "wasmtime-internal-asm-macros", "wasmtime-internal-component-macro", @@ -1826,7 +1890,7 @@ dependencies = [ "smallvec", "target-lexicon", "wasm-encoder", - "wasmparser", + "wasmparser 0.235.0", "wasmprinter", "wasmtime-internal-component-util", ] @@ -1882,7 +1946,7 @@ dependencies = [ "smallvec", "target-lexicon", "thiserror", - "wasmparser", + "wasmparser 0.235.0", "wasmtime-environ", "wasmtime-internal-math", "wasmtime-internal-versioned-export-macros", @@ -1937,7 +2001,7 @@ dependencies = [ "gimli", "object", "target-lexicon", - "wasmparser", + "wasmparser 0.235.0", "wasmtime-environ", "wasmtime-internal-cranelift", "winch-codegen", @@ -1977,9 +2041,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" dependencies = [ "rustls-pki-types", ] @@ -2007,19 +2071,25 @@ dependencies = [ "smallvec", "target-lexicon", "thiserror", - "wasmparser", + "wasmparser 0.235.0", "wasmtime-environ", "wasmtime-internal-cranelift", "wasmtime-internal-math", ] +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -2028,7 +2098,16 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", ] [[package]] @@ -2037,14 +2116,31 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -2053,48 +2149,96 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "wit-bindgen-rt" version = "0.39.0" @@ -2119,7 +2263,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser", + "wasmparser 0.235.0", ] [[package]] @@ -2154,18 +2298,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", @@ -2212,9 +2356,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" dependencies = [ "yoke", "zerofrom", diff --git a/src/wasm_runtime/Cargo.toml b/src/wasm_runtime/Cargo.toml index 3c2fda6..5903113 100644 --- a/src/wasm_runtime/Cargo.toml +++ b/src/wasm_runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasm-runtime" -version = "0.7.0" +version = "0.8.0" edition = "2021" [[bin]] @@ -11,9 +11,9 @@ doctest = false bench = false [dependencies] -hyperlight-common = { version = "0.7.0", git = "https://github.com/hyperlight-dev/hyperlight", rev = "ea6fa8f", default-features = false } -hyperlight-guest-bin = { version = "0.7.0", git = "https://github.com/hyperlight-dev/hyperlight", rev = "ea6fa8f", features = [ "printf" ] } -hyperlight-guest = { version = "0.7.0", git = "https://github.com/hyperlight-dev/hyperlight", rev = "ea6fa8f" } +hyperlight-common = { version = "0.8.0", default-features = false } +hyperlight-guest-bin = { version = "0.8.0", features = [ "printf" ] } +hyperlight-guest = { version = "0.8.0" } wasmtime = { version = "35.0.0", default-features = false, features = [ "runtime", "custom-virtual-memory", "custom-native-signals", "component-model" ] } hyperlight-wasm-macro = { path = "../hyperlight_wasm_macro" } spin = "0.9.8" diff --git a/src/wasm_runtime/src/hostfuncs.rs b/src/wasm_runtime/src/hostfuncs.rs index 943d411..e468c55 100644 --- a/src/wasm_runtime/src/hostfuncs.rs +++ b/src/wasm_runtime/src/hostfuncs.rs @@ -79,9 +79,9 @@ pub(crate) fn hostfunc_type(d: &HostFunctionDefinition, e: &Engine) -> Result( d: &HostFunctionDefinition, - mut c: Caller<'_, ()>, + mut c: Caller<'_, T>, ps: &[Val], rs: &mut [Val], ) -> Result<()> { diff --git a/src/wasm_runtime/src/marshal.rs b/src/wasm_runtime/src/marshal.rs index 3ce22c0..a449046 100644 --- a/src/wasm_runtime/src/marshal.rs +++ b/src/wasm_runtime/src/marshal.rs @@ -14,6 +14,35 @@ See the License for the specific language governing permissions and limitations under the License. */ +//! Parameter and return value marshalling for WASM guest function calls. +//! +//! # Memory Management Contract +//! +//! This module implements a clear memory ownership model for both guest function calls and host function calls: +//! +//! ## Guest Function Parameters (Host → Guest) +//! - When calling guest functions with String or VecBytes parameters, the host allocates memory +//! in the guest's memory space and passes pointers to the guest. +//! - **The guest owns these allocations and must free them** when no longer needed using the +//! `free` function exported from the guest module. +//! +//! ## Guest Function Return Values (Guest → Host) +//! - When guest functions return String or VecBytes values, the guest allocates memory in its +//! own memory space and returns pointers to the host using the malloc corresponding to its +//! exported free. +//! - **The host takes ownership of these allocations and will free them** on the next VM entry +//! to prevent memory leaks. +//! +//! ## Host Function Parameters (Guest → Host) +//! - When guest code calls host functions with String or VecBytes parameters, the guest passes +//! pointers to data in its own memory space. +//! - **The guest retains ownership** of these allocations and remains responsible for freeing them. +//! +//! ## Host Function Return Values (Host → Guest) +//! - When host functions return String or VecBytes values to the guest, the host allocates memory +//! in the guest's memory space and returns pointers. +//! - **The guest owns these allocations and must free them** when no longer needed. + extern crate alloc; use alloc::ffi::CString; @@ -27,8 +56,29 @@ use hyperlight_common::flatbuffer_wrappers::function_types::{ use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode; use hyperlight_common::flatbuffer_wrappers::util::get_flatbuffer_result; use hyperlight_guest::error::{HyperlightGuestError, Result}; +use spin::Mutex; use wasmtime::{AsContextMut, Extern, Val}; +// Global tracking for return value allocations that need to be freed on next VM entry +static RETURN_VALUE_ALLOCATIONS: Mutex> = Mutex::new(Vec::new()); + +/// Track a return value allocation that should be freed on the next VM entry +fn track_return_value_allocation(addr: i32) { + RETURN_VALUE_ALLOCATIONS.lock().push(addr); +} + +/// Free all tracked return value allocations from previous VM calls +pub fn free_return_value_allocations( + ctx: &mut C, + get_export: &impl Fn(&mut C, &str) -> Option, +) -> Result<()> { + let mut allocations = RETURN_VALUE_ALLOCATIONS.lock(); + for addr in allocations.drain(..) { + free(ctx, get_export, addr)?; + } + Ok(()) +} + fn malloc( ctx: &mut C, get_export: &impl Fn(&mut C, &str) -> Option, @@ -46,6 +96,21 @@ fn malloc( Ok(addr) } +fn free( + ctx: &mut C, + get_export: &impl Fn(&mut C, &str) -> Option, + addr: i32, +) -> Result<()> { + let free = get_export(&mut *ctx, "free") + .and_then(Extern::into_func) + .ok_or(HyperlightGuestError::new( + ErrorCode::GuestError, + "free function not exported".to_string(), + ))?; + free.typed::(&mut *ctx)?.call(&mut *ctx, addr)?; + Ok(()) +} + fn write( ctx: &mut C, get_export: &impl Fn(&mut C, &str) -> Option, @@ -126,6 +191,11 @@ fn read_cstr( }) } +/// Convert a hyperlight parameter value to a wasmtime value. +/// +/// For String and VecBytes parameter types, this allocates memory in the guest's memory space +/// and returns a pointer. The guest function is responsible for freeing this memory when it is no +/// longer needed using the `free` function exported from the guest module. pub fn hl_param_to_val( mut ctx: C, get_export: impl Fn(&mut C, &str) -> Option, @@ -155,6 +225,11 @@ pub fn hl_param_to_val( } } +/// Convert guest function return values to hyperlight return value. +/// +/// For String and VecBytes return types, the guest has allocated memory in its own memory space +/// and returned pointers. The host takes ownership of these allocations and tracks them for +/// automatic cleanup on the next VM entry to prevent memory leaks. pub fn val_to_hl_result( mut ctx: C, get_export: impl Fn(&mut C, &str) -> Option, @@ -172,15 +247,21 @@ pub fn val_to_hl_result( /* todo: get_flatbuffer_result_from_bool is missing */ (ReturnType::Float, Val::F32(f)) => Ok(get_flatbuffer_result::(f32::from_bits(f))), (ReturnType::Double, Val::F64(f)) => Ok(get_flatbuffer_result::(f64::from_bits(f))), - (ReturnType::String, Val::I32(p)) => Ok(get_flatbuffer_result::<&str>( - read_cstr(&mut ctx, &get_export, p)?.to_str().map_err(|e| { - HyperlightGuestError::new( - ErrorCode::GuestError, - format!("non-UTF-8 c string in guest function return: {}", e), - ) - })?, - )), + (ReturnType::String, Val::I32(p)) => { + // Track this allocation so it can be freed on next VM entry + track_return_value_allocation(p); + Ok(get_flatbuffer_result::<&str>( + read_cstr(&mut ctx, &get_export, p)?.to_str().map_err(|e| { + HyperlightGuestError::new( + ErrorCode::GuestError, + format!("non-UTF-8 c string in guest function return: {}", e), + ) + })?, + )) + } (ReturnType::VecBytes, Val::I32(ret)) => { + // Track this allocation so it can be freed on next VM entry + track_return_value_allocation(ret); let mut size_bytes = [0; 4]; read(&mut ctx, &get_export, ret, &mut size_bytes)?; let size = i32::from_le_bytes(size_bytes); @@ -198,6 +279,11 @@ pub fn val_to_hl_result( } } +/// Convert guest-provided WASM values to hyperlight parameters for host function calls. +/// +/// For String and VecBytes parameter types, the guest passes pointers to data in its own +/// memory space. The guest retains ownership of these allocations and remains responsible +/// for freeing them. This function only reads the data without taking ownership. pub fn val_to_hl_param<'a, C: AsContextMut>( ctx: &mut C, get_export: impl Fn(&mut C, &str) -> Option, @@ -248,6 +334,11 @@ pub fn val_to_hl_param<'a, C: AsContextMut>( } } +/// Convert a hyperlight return value to a wasmtime value for host function returns. +/// +/// For String and VecBytes return types, this allocates memory in the guest's memory space +/// and returns a pointer. The guest owns these allocations and must free them when no longer needed +/// using the `free` function exported from the guest module. pub fn hl_return_to_val( ctx: &mut C, get_export: impl Fn(&mut C, &str) -> Option, diff --git a/src/wasm_runtime/src/module.rs b/src/wasm_runtime/src/module.rs index c9aec48..e3fa630 100644 --- a/src/wasm_runtime/src/module.rs +++ b/src/wasm_runtime/src/module.rs @@ -17,7 +17,7 @@ limitations under the License. use alloc::string::ToString; use alloc::vec::Vec; use alloc::{format, vec}; -use core::ops::Deref; +use core::ops::{Deref, DerefMut}; use hyperlight_common::flatbuffer_wrappers::function_call::FunctionCall; use hyperlight_common::flatbuffer_wrappers::function_types::{ @@ -34,35 +34,41 @@ use wasmtime::{Config, Engine, Linker, Module, Store, Val}; use crate::{hostfuncs, marshal, platform, wasip1}; +// Set by transition to WasmSandbox (by init_wasm_runtime) static CUR_ENGINE: Mutex> = Mutex::new(None); static CUR_LINKER: Mutex>> = Mutex::new(None); +// Set by transition to LoadedWasmSandbox (by load_wasm_module/load_wasm_module_phys) static CUR_MODULE: Mutex> = Mutex::new(None); +static CUR_STORE: Mutex>> = Mutex::new(None); +static CUR_INSTANCE: Mutex> = Mutex::new(None); #[no_mangle] -pub fn guest_dispatch_function(function_call: &FunctionCall) -> Result> { - let engine = CUR_ENGINE.lock(); - let engine = engine.deref().as_ref().ok_or(HyperlightGuestError::new( +pub fn guest_dispatch_function(function_call: FunctionCall) -> Result> { + let mut store = CUR_STORE.lock(); + let store = store.deref_mut().as_mut().ok_or(HyperlightGuestError::new( ErrorCode::GuestError, - "Wasm runtime is not initialized".to_string(), + "No wasm store available".to_string(), ))?; - let linker = CUR_LINKER.lock(); - let linker = linker.deref().as_ref().ok_or(HyperlightGuestError::new( + let instance = CUR_INSTANCE.lock(); + let instance = instance.deref().as_ref().ok_or(HyperlightGuestError::new( ErrorCode::GuestError, - "impossible: wasm runtime has no valid linker".to_string(), + "No wasm instance available".to_string(), ))?; - let module = CUR_MODULE.lock(); - let module = module.deref().as_ref().ok_or(HyperlightGuestError::new( - ErrorCode::GuestError, - "No wasm module loaded".to_string(), - ))?; - let mut store = Store::new(engine, ()); - let instance = linker.instantiate(&mut store, module)?; + + // Free any return value allocations from the previous VM call + // This implements the memory model where hyperlight owns return values + // and frees them on the next VM entry + marshal::free_return_value_allocations(&mut *store, &|ctx, name| { + instance.get_export(ctx, name) + })?; + let func = instance - .get_func(&mut store, &function_call.function_name) + .get_func(&mut *store, &function_call.function_name) .ok_or(HyperlightGuestError::new( ErrorCode::GuestError, "Function not found".to_string(), ))?; + let mut w_params = vec![]; for f_param in (function_call.parameters) .as_ref() @@ -70,7 +76,7 @@ pub fn guest_dispatch_function(function_call: &FunctionCall) -> Result> .iter() { w_params.push(marshal::hl_param_to_val( - &mut store, + &mut *store, |ctx, name| instance.get_export(ctx, name), f_param, )?); @@ -78,9 +84,9 @@ pub fn guest_dispatch_function(function_call: &FunctionCall) -> Result> let is_void = ReturnType::Void == function_call.expected_return_type; let n_results = if is_void { 0 } else { 1 }; let mut results = vec![Val::I32(0); n_results]; - func.call(&mut store, &w_params, &mut results)?; + func.call(&mut *store, &w_params, &mut results)?; marshal::val_to_hl_result( - &mut store, + &mut *store, |ctx, name| instance.get_export(ctx, name), function_call.expected_return_type, &results, @@ -124,8 +130,19 @@ fn load_wasm_module(function_call: &FunctionCall) -> Result> { &function_call.parameters.as_ref().unwrap()[1], &*CUR_ENGINE.lock(), ) { + let linker = CUR_LINKER.lock(); + let linker = linker.deref().as_ref().ok_or(HyperlightGuestError::new( + ErrorCode::GuestError, + "impossible: wasm runtime has no valid linker".to_string(), + ))?; + let module = unsafe { Module::deserialize(engine, wasm_bytes)? }; + let mut store = Store::new(engine, ()); + let instance = linker.instantiate(&mut store, &module)?; + *CUR_MODULE.lock() = Some(module); + *CUR_STORE.lock() = Some(store); + *CUR_INSTANCE.lock() = Some(instance); Ok(get_flatbuffer_result::(0)) } else { Err(HyperlightGuestError::new( @@ -141,8 +158,19 @@ fn load_wasm_module_phys(function_call: &FunctionCall) -> Result> { &function_call.parameters.as_ref().unwrap()[1], &*CUR_ENGINE.lock(), ) { + let linker = CUR_LINKER.lock(); + let linker = linker.deref().as_ref().ok_or(HyperlightGuestError::new( + ErrorCode::GuestError, + "impossible: wasm runtime has no valid linker".to_string(), + ))?; + let module = unsafe { Module::deserialize_raw(engine, platform::map_buffer(*phys, *len))? }; + let mut store = Store::new(engine, ()); + let instance = linker.instantiate(&mut store, &module)?; + *CUR_MODULE.lock() = Some(module); + *CUR_STORE.lock() = Some(store); + *CUR_INSTANCE.lock() = Some(instance); Ok(get_flatbuffer_result::<()>(())) } else { Err(HyperlightGuestError::new( diff --git a/src/wasm_runtime/src/platform.rs b/src/wasm_runtime/src/platform.rs index df15ede..bcd84cb 100644 --- a/src/wasm_runtime/src/platform.rs +++ b/src/wasm_runtime/src/platform.rs @@ -59,7 +59,7 @@ pub(crate) fn register_page_fault_handler() { // See AMD64 Architecture Programmer's Manual, Volume 2 // §8.2 Vectors, p. 245 // Table 8-1: Interrupt Vector Source and Cause - handler::handlers[14].store(page_fault_handler as usize as u64, Ordering::Release); + handler::HANDLERS[14].store(page_fault_handler as usize as u64, Ordering::Release); } // Wasmtime Embedding Interface @@ -155,7 +155,7 @@ pub extern "C" fn wasmtime_init_traps(handler: wasmtime_trap_handler_t) -> i32 { // See AMD64 Architecture Programmer's Manual, Volume 2 // §8.2 Vectors, p. 245 // Table 8-1: Interrupt Vector Source and Cause - handler::handlers[6].store(wasmtime_trap_handler as usize as u64, Ordering::Release); + handler::HANDLERS[6].store(wasmtime_trap_handler as usize as u64, Ordering::Release); // TODO: Add handlers for any other traps that wasmtime needs, // probably including at least some floating-point // exceptions diff --git a/src/wasmsamples/HelloWorld.c b/src/wasmsamples/HelloWorld.c index f71128a..22eb3d5 100644 --- a/src/wasmsamples/HelloWorld.c +++ b/src/wasmsamples/HelloWorld.c @@ -42,6 +42,7 @@ int HelloWorld(char* msg) printf("contents of buffer after snprintf: %s\n", buf); free(buf); + free(msg); // Free the msg since we own it return 0; } diff --git a/src/wasmsamples/RunWasm.c b/src/wasmsamples/RunWasm.c index 2515b4d..3d40682 100644 --- a/src/wasmsamples/RunWasm.c +++ b/src/wasmsamples/RunWasm.c @@ -36,7 +36,7 @@ int CalcFib(int n) } } -// This function receives an array of bytes followed by a length and then returns a pointer to a buffer where the first 4 bytes is the length followed by the data. +// This function receives an array of bytes followed by a length and then returns a buffer where the first 4 bytes is the length followed by the data. __attribute__((export_name("ReceiveByteArray"))) void* ReceiveByteArray(void* data, int length) { @@ -45,15 +45,17 @@ void* ReceiveByteArray(void* data, int length) { result += 4; memcpy(result, data, length); result -= 4; - return result; + free(data); // Free the guest parameter, which we own + return result; // Transfer ownership of return value to host } __attribute__((export_name("WasmPrintUsingHostPrint"))) int WasmPrintUsingHostPrint(char* msg) { - // Host Print now returns a flatbuffer buffer - HostPrint(msg); - return strlen(msg); + HostPrint(msg); // Host borrows msg + int len = strlen(msg); + free(msg); // Free the param since we own + return len; } __attribute__((export_name("PrintHelloWorld"))) @@ -67,12 +69,13 @@ __attribute__((export_name("Print"))) void Print(char* msg) { HostPrint(msg); + free(msg); // Free the msg since we own it } __attribute__((export_name("Echo"))) char* Echo(char* msg) { - return msg; + return msg; // Transfer ownership to host } __attribute__((export_name("ToUpper"), optnone)) @@ -96,6 +99,7 @@ __attribute__((export_name("PrintUpper"), optnone)) void PrintUpper(char* msg) { HostPrint(ToUpper(msg)); + free(msg); } __attribute__((export_name("KeepCPUBusy")))