Skip to content

Commit 975ae5e

Browse files
jsturtevantCopilot
andcommitted
Fix Wasmtime latest runtime compatibility
Map Wasmtime 45 direct errors into Hyperlight guest errors and avoid latest-only component post_return deprecation while preserving LTS behavior. Run clippy with the latest and LTS Wasmtime feature sets separately so mutually exclusive features are not enabled together. Signed-off-by: James Sturtevant <jsturtevant@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent ce354ed commit 975ae5e

9 files changed

Lines changed: 190 additions & 129 deletions

File tree

Justfile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ latest-release:= if os() == "windows" {"$(git tag -l --sort=v:refname | select -
66
wit-world := if os() == "windows" { "$env:WIT_WORLD=\"" + justfile_directory() + "\\src\\tests\\rust_guests\\component_sample\\wit\\component-world.wasm" + "\";" } else { "WIT_WORLD=" + justfile_directory() + "/src/tests/rust_guests/component_sample/wit/component-world.wasm" }
77
wit-world-c := if os() == "windows" { "$env:WIT_WORLD=\"" + justfile_directory() + "\\src\\tests\\c_guests\\wasmsamples\\components\\runcomponent-world.wasm" + "\";" } else { "WIT_WORLD=" + justfile_directory() + "/src/tests/c_guests/wasmsamples/components/runcomponent-world.wasm" }
88
wit-world-name-greeter := if os() == "windows" { "$env:WIT_WORLD_NAME=\"greeter-world\";" } else { "WIT_WORLD_NAME=greeter-world" }
9+
workspace-features-latest := "hyperlight-wasm/function_call_metrics,hyperlight-wasm/print_debug,hyperlight-wasm/crashdump,hyperlight-wasm/gdb,hyperlight-wasm/kvm,hyperlight-wasm/mshv3,hyperlight-wasm/pulley,hyperlight-wasm/trace_guest,hyperlight-wasm/wasmtime_latest,hyperlight-wasm-aot/gdb"
10+
workspace-features-lts := "hyperlight-wasm/function_call_metrics,hyperlight-wasm/print_debug,hyperlight-wasm/crashdump,hyperlight-wasm/gdb,hyperlight-wasm/kvm,hyperlight-wasm/mshv3,hyperlight-wasm/trace_guest,hyperlight-wasm/wasmtime_lts,hyperlight-wasm-aot/gdb"
911

1012
set windows-shell := ["pwsh.exe", "-NoLogo", "-Command"]
1113

@@ -91,12 +93,13 @@ fmt:
9193
cd src/hyperlight_wasm_macro && cargo +nightly fmt -v --all
9294

9395
clippy target=default-target: (check target)
94-
cargo clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --all-features -- -D warnings
96+
cargo clippy --workspace --exclude hyperlight-wasm-runtime --exclude hyperlight-wasm-macro --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --no-default-features --features {{ workspace-features-latest }} -- -D warnings
97+
cargo clippy --workspace --exclude hyperlight-wasm-runtime --exclude hyperlight-wasm-macro --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --no-default-features --features {{ workspace-features-lts }} -- -D warnings
9598
cd src/tests/rust_guests/rust_wasm_samples && cargo clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --all-features -- -D warnings
9699
cd src/tests/rust_guests/component_sample && cargo clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --all-features -- -D warnings
97100
cd src/tests/rust_guests/greeter_sample && cargo clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --all-features -- -D warnings
98101
# hyperlight_wasm_runtime has mutually exclusive wasmtime features, so we run clippy for each separately with all other features
99-
cd src/hyperlight_wasm_runtime && cargo hyperlight clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --features wasmtime_latest,gdb,trace_guest,pulley -- -D warnings
102+
cd src/hyperlight_wasm_runtime && cargo hyperlight clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --no-default-features --features wasmtime_latest,gdb,trace_guest,pulley -- -D warnings
100103
cd src/hyperlight_wasm_runtime && cargo hyperlight clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --no-default-features --features wasmtime_lts,gdb,trace_guest -- -D warnings
101104
cd src/hyperlight_wasm_macro && cargo clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --all-features -- -D warnings
102105

src/hyperlight_wasm_macro/src/wasmguest.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -214,17 +214,28 @@ fn emit_wasm_function_call(
214214
let rwt = match result {
215215
None => {
216216
quote! {
217-
let func = instance.get_typed_func::<(#(#pwts,)*), ()>(&mut *store, func_idx)?;
218-
func.call(&mut *store, (#(#pus,)*))?;
219-
func.post_return(&mut *store)?;
217+
let func = instance
218+
.get_typed_func::<(#(#pwts,)*), ()>(&mut *store, func_idx)
219+
.map_err(crate::map_wasmtime_error)?;
220+
func.call(&mut *store, (#(#pus,)*))
221+
.map_err(crate::map_wasmtime_error)?;
222+
#[cfg(feature = "wasmtime_lts")]
223+
func.post_return(&mut *store)
224+
.map_err(crate::map_wasmtime_error)?;
220225
}
221226
}
222227
_ => {
223228
let r = rtypes::emit_func_result(s, result);
224229
quote! {
225-
let func = instance.get_typed_func::<(#(#pwts,)*), ((#r,))>(&mut *store, func_idx)?;
226-
let #ret = func.call(&mut *store, (#(#pus,)*))?.0;
227-
func.post_return(&mut *store)?;
230+
let func = instance
231+
.get_typed_func::<(#(#pwts,)*), ((#r,))>(&mut *store, func_idx)
232+
.map_err(crate::map_wasmtime_error)?;
233+
let #ret = func.call(&mut *store, (#(#pus,)*))
234+
.map_err(crate::map_wasmtime_error)?
235+
.0;
236+
#[cfg(feature = "wasmtime_lts")]
237+
func.post_return(&mut *store)
238+
.map_err(crate::map_wasmtime_error)?;
228239
}
229240
}
230241
};

src/hyperlight_wasm_runtime/build.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,7 @@ fn main() {
4444
// Multiple wasmtime versions present; pick based on feature
4545
wasmtime_packages
4646
.iter()
47-
.find(|p| {
48-
(use_lts && p.version.major <= 36) || (!use_lts && p.version.major > 36)
49-
})
47+
.find(|p| (use_lts && p.version.major <= 36) || (!use_lts && p.version.major > 36))
5048
.unwrap_or_else(|| panic!("wasmtime dependency not found for lts={}", use_lts))
5149
.version
5250
.clone()

src/hyperlight_wasm_runtime/src/component.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use tracing::instrument;
3434
use wasmtime::component::{Component, Instance, Linker};
3535
use wasmtime::{Config, Engine, Store};
3636

37-
use crate::platform;
37+
use crate::{map_wasmtime_error, platform};
3838

3939
static CUR_ENGINE: Mutex<Option<Engine>> = Mutex::new(None);
4040
static CUR_LINKER: Mutex<Option<Linker<()>>> = Mutex::new(None);
@@ -55,7 +55,8 @@ fn load_component_common(engine: &Engine, component: Component) -> Result<()> {
5555
let instance = (*CUR_LINKER.lock())
5656
.as_ref()
5757
.unwrap()
58-
.instantiate(&mut store, &component)?;
58+
.instantiate(&mut store, &component)
59+
.map_err(map_wasmtime_error)?;
5960
*CUR_STORE.lock() = Some(store);
6061
*CUR_INSTANCE.lock() = Some(instance);
6162
Ok(())
@@ -72,7 +73,8 @@ fn load_wasm_module(function_call: FunctionCall) -> Result<Vec<u8>> {
7273
&function_call.parameters.as_ref().unwrap()[1],
7374
&*CUR_ENGINE.lock(),
7475
) {
75-
let component = unsafe { Component::deserialize(engine, wasm_bytes)? };
76+
let component =
77+
unsafe { Component::deserialize(engine, wasm_bytes).map_err(map_wasmtime_error)? };
7678
load_component_common(engine, component)?;
7779
Ok(get_flatbuffer_result::<i32>(0))
7880
} else {
@@ -90,8 +92,10 @@ fn load_wasm_module_phys(function_call: FunctionCall) -> Result<Vec<u8>> {
9092
&function_call.parameters.as_ref().unwrap()[1],
9193
&*CUR_ENGINE.lock(),
9294
) {
93-
let component =
94-
unsafe { Component::deserialize_raw(engine, platform::map_buffer(*phys, *len))? };
95+
let component = unsafe {
96+
Component::deserialize_raw(engine, platform::map_buffer(*phys, *len))
97+
.map_err(map_wasmtime_error)?
98+
};
9599
load_component_common(engine, component)?;
96100
Ok(get_flatbuffer_result::<()>(()))
97101
} else {

src/hyperlight_wasm_runtime/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ limitations under the License.
1919

2020
extern crate alloc;
2121

22+
use alloc::string::ToString;
23+
24+
use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
25+
use hyperlight_guest::error::HyperlightGuestError;
26+
2227
// Re-export wasmtime based on expected version
2328
#[cfg(all(feature = "wasmtime_latest", feature = "wasmtime_lts"))]
2429
compile_error!(
@@ -33,6 +38,10 @@ extern crate wasmtime;
3338
#[cfg(feature = "wasmtime_lts")]
3439
extern crate wasmtime_lts as wasmtime;
3540

41+
pub(crate) fn map_wasmtime_error(error: wasmtime::Error) -> HyperlightGuestError {
42+
HyperlightGuestError::new(ErrorCode::GuestError, error.to_string())
43+
}
44+
3645
mod platform;
3746

3847
#[cfg(not(component))]

src/hyperlight_wasm_runtime/src/marshal.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ use spin::Mutex;
6060
use tracing::instrument;
6161
use wasmtime::{AsContextMut, Extern, Val};
6262

63+
use crate::map_wasmtime_error;
64+
6365
// Global tracking for return value allocations that need to be freed on next VM entry
6466
static RETURN_VALUE_ALLOCATIONS: Mutex<Vec<i32>> = Mutex::new(Vec::new());
6567

@@ -95,8 +97,10 @@ fn malloc<C: AsContextMut>(
9597
"malloc function not exported".to_string(),
9698
))?;
9799
let addr = malloc
98-
.typed::<i32, i32>(&mut *ctx)?
99-
.call(&mut *ctx, len as i32)?;
100+
.typed::<i32, i32>(&mut *ctx)
101+
.map_err(map_wasmtime_error)?
102+
.call(&mut *ctx, len as i32)
103+
.map_err(map_wasmtime_error)?;
100104
Ok(addr)
101105
}
102106

@@ -112,7 +116,10 @@ fn free<C: AsContextMut>(
112116
ErrorCode::GuestError,
113117
"free function not exported".to_string(),
114118
))?;
115-
free.typed::<i32, ()>(&mut *ctx)?.call(&mut *ctx, addr)?;
119+
free.typed::<i32, ()>(&mut *ctx)
120+
.map_err(map_wasmtime_error)?
121+
.call(&mut *ctx, addr)
122+
.map_err(map_wasmtime_error)?;
116123
Ok(())
117124
}
118125

src/hyperlight_wasm_runtime/src/module.rs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use spin::Mutex;
3333
use tracing::instrument;
3434
use wasmtime::{Config, Engine, Linker, Module, Store, Val};
3535

36-
use crate::{hostfuncs, marshal, platform, wasip1};
36+
use crate::{hostfuncs, map_wasmtime_error, marshal, platform, wasip1};
3737

3838
// Set by transition to WasmSandbox (by init_wasm_runtime)
3939
static CUR_ENGINE: Mutex<Option<Engine>> = Mutex::new(None);
@@ -86,7 +86,8 @@ pub fn guest_dispatch_function(function_call: FunctionCall) -> Result<Vec<u8>> {
8686
let is_void = ReturnType::Void == function_call.expected_return_type;
8787
let n_results = if is_void { 0 } else { 1 };
8888
let mut results = vec![Val::I32(0); n_results];
89-
func.call(&mut *store, &w_params, &mut results)?;
89+
func.call(&mut *store, &w_params, &mut results)
90+
.map_err(map_wasmtime_error)?;
9091
marshal::val_to_hl_result(
9192
&mut *store,
9293
|ctx, name| instance.get_export(ctx, name),
@@ -119,7 +120,7 @@ fn init_wasm_runtime(function_call: FunctionCall) -> Result<Vec<u8>> {
119120
"Failed to set wasmtime target: pulley64".to_string(),
120121
)
121122
})?;
122-
let engine = Engine::new(&config)?;
123+
let engine = Engine::new(&config).map_err(map_wasmtime_error)?;
123124
let mut linker = Linker::new(&engine);
124125
wasip1::register_handlers(&mut linker)?;
125126

@@ -157,15 +158,17 @@ fn init_wasm_runtime(function_call: FunctionCall) -> Result<Vec<u8>> {
157158

158159
for hostfunc in hostfuncs.iter() {
159160
let captured = hostfunc.clone();
160-
linker.func_new(
161-
"env",
162-
&hostfunc.function_name,
163-
hostfuncs::hostfunc_type(hostfunc, &engine)?,
164-
move |c, ps, rs| {
165-
hostfuncs::call(&captured, c, ps, rs)
166-
.map_err(|e| wasmtime::Error::msg(format!("{:?}", e)))
167-
},
168-
)?;
161+
linker
162+
.func_new(
163+
"env",
164+
&hostfunc.function_name,
165+
hostfuncs::hostfunc_type(hostfunc, &engine)?,
166+
move |c, ps, rs| {
167+
hostfuncs::call(&captured, c, ps, rs)
168+
.map_err(|e| wasmtime::Error::msg(format!("{:?}", e)))
169+
},
170+
)
171+
.map_err(map_wasmtime_error)?;
169172
}
170173

171174
*CUR_ENGINE.lock() = Some(engine);
@@ -190,9 +193,12 @@ fn load_wasm_module(function_call: FunctionCall) -> Result<Vec<u8>> {
190193
"impossible: wasm runtime has no valid linker".to_string(),
191194
))?;
192195

193-
let module = unsafe { Module::deserialize(engine, wasm_bytes)? };
196+
let module =
197+
unsafe { Module::deserialize(engine, wasm_bytes).map_err(map_wasmtime_error)? };
194198
let mut store = Store::new(engine, ());
195-
let instance = linker.instantiate(&mut store, &module)?;
199+
let instance = linker
200+
.instantiate(&mut store, &module)
201+
.map_err(map_wasmtime_error)?;
196202

197203
*CUR_MODULE.lock() = Some(module);
198204
*CUR_STORE.lock() = Some(store);
@@ -219,9 +225,14 @@ fn load_wasm_module_phys(function_call: FunctionCall) -> Result<Vec<u8>> {
219225
"impossible: wasm runtime has no valid linker".to_string(),
220226
))?;
221227

222-
let module = unsafe { Module::deserialize_raw(engine, platform::map_buffer(*phys, *len))? };
228+
let module = unsafe {
229+
Module::deserialize_raw(engine, platform::map_buffer(*phys, *len))
230+
.map_err(map_wasmtime_error)?
231+
};
223232
let mut store = Store::new(engine, ());
224-
let instance = linker.instantiate(&mut store, &module)?;
233+
let instance = linker
234+
.instantiate(&mut store, &module)
235+
.map_err(map_wasmtime_error)?;
225236

226237
*CUR_MODULE.lock() = Some(module);
227238
*CUR_STORE.lock() = Some(store);

src/hyperlight_wasm_runtime/src/platform.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ pub(crate) fn register_page_fault_handler() {
6565
// See AMD64 Architecture Programmer's Manual, Volume 2
6666
// §8.2 Vectors, p. 245
6767
// Table 8-1: Interrupt Vector Source and Cause
68-
arch::HANDLERS[14].store(page_fault_handler as usize as u64, Ordering::Release);
68+
arch::HANDLERS[14].store(
69+
page_fault_handler as *const () as usize as u64,
70+
Ordering::Release,
71+
);
6972
}
7073

7174
// Wasmtime Embedding Interface
@@ -161,7 +164,10 @@ pub extern "C" fn wasmtime_init_traps(handler: wasmtime_trap_handler_t) -> i32 {
161164
// See AMD64 Architecture Programmer's Manual, Volume 2
162165
// §8.2 Vectors, p. 245
163166
// Table 8-1: Interrupt Vector Source and Cause
164-
arch::HANDLERS[6].store(wasmtime_trap_handler as usize as u64, Ordering::Release);
167+
arch::HANDLERS[6].store(
168+
wasmtime_trap_handler as *const () as usize as u64,
169+
Ordering::Release,
170+
);
165171
// TODO: Add handlers for any other traps that wasmtime needs,
166172
// probably including at least some floating-point
167173
// exceptions

0 commit comments

Comments
 (0)