Skip to content

Commit d288c3d

Browse files
committed
extend linker to run C programs in kernel space
1 parent 5bfb7c1 commit d288c3d

File tree

1 file changed

+171
-1
lines changed

1 file changed

+171
-1
lines changed

src/wasm/mod.rs

Lines changed: 171 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use core::hint::black_box;
55
use core::mem::MaybeUninit;
66
use core::task::Poll;
77

8-
use hermit_sync::InterruptTicketMutex;
8+
use hermit_sync::{InterruptTicketMutex, Lazy};
99
use wasi::*;
1010
use wasmtime::*;
1111
use zerocopy::IntoBytes;
@@ -25,6 +25,9 @@ fn native_fibonacci(n: u64) -> u64 {
2525
}
2626
}
2727

28+
#[inline(never)]
29+
fn native_foo() {}
30+
2831
pub fn measure_fibonacci(n: u64) {
2932
const RUNS: u64 = 100;
3033
info!("Measure native_fibonacci({})", n);
@@ -73,6 +76,7 @@ pub(crate) struct WasmManager {
7376

7477
impl WasmManager {
7578
pub fn new(data: &[u8]) -> Self {
79+
static MODULE_AND_ARGS: Lazy<Vec<&[u8]>> = Lazy::new(|| vec![b"dummy\0"]);
7680
let mut config: Config = Config::new();
7781
config.memory_init_cow(false);
7882
config.memory_guard_size(8192);
@@ -235,6 +239,122 @@ impl WasmManager {
235239
},
236240
)
237241
.unwrap();
242+
linker
243+
.func_wrap(
244+
"wasi_snapshot_preview1",
245+
"args_get",
246+
|mut caller: Caller<'_, _>, argv_ptr: i32, argv_buf_ptr: i32| {
247+
if let Some(Extern::Memory(mem)) = caller.get_export("memory") {
248+
let mut pos: u32 = argv_buf_ptr as u32;
249+
for (i, element) in MODULE_AND_ARGS.iter().enumerate() {
250+
let _ = mem.write(
251+
caller.as_context_mut(),
252+
(argv_ptr + (i * size_of::<u32>()) as i32)
253+
.try_into()
254+
.unwrap(),
255+
pos.as_bytes(),
256+
);
257+
258+
let _ = mem.write(
259+
caller.as_context_mut(),
260+
pos.try_into().unwrap(),
261+
element,
262+
);
263+
264+
pos += element.len() as u32;
265+
}
266+
}
267+
ERRNO_SUCCESS.raw() as i32
268+
},
269+
)
270+
.unwrap();
271+
linker
272+
.func_wrap(
273+
"wasi_snapshot_preview1",
274+
"args_sizes_get",
275+
move |mut caller: Caller<'_, _>, number_args_ptr: i32, args_size_ptr: i32| {
276+
let nargs: u32 = MODULE_AND_ARGS.len().try_into().unwrap();
277+
// Currently, we ignore the arguments
278+
if let Some(Extern::Memory(mem)) = caller.get_export("memory") {
279+
let _ = mem.write(
280+
caller.as_context_mut(),
281+
number_args_ptr.try_into().unwrap(),
282+
nargs.as_bytes(),
283+
);
284+
285+
let nargs_size: u32 = MODULE_AND_ARGS
286+
.iter()
287+
.fold(0, |acc, arg| acc + arg.len())
288+
.try_into()
289+
.unwrap();
290+
let _ = mem.write(
291+
caller.as_context_mut(),
292+
args_size_ptr.try_into().unwrap(),
293+
nargs_size.as_bytes(),
294+
);
295+
296+
return ERRNO_SUCCESS.raw() as i32;
297+
}
298+
299+
ERRNO_INVAL.raw() as i32
300+
},
301+
)
302+
.unwrap();
303+
linker
304+
.func_wrap(
305+
"wasi_snapshot_preview1",
306+
"clock_time_get",
307+
|mut caller: Caller<'_, _>, clock_id: i32, _precision: i64, timestamp_ptr: i32| {
308+
match clock_id {
309+
0 => {
310+
let usec = crate::arch::kernel::systemtime::now_micros();
311+
if let Some(Extern::Memory(mem)) = caller.get_export("memory") {
312+
let nanos = usec * 1000;
313+
let _ = mem.write(
314+
caller.as_context_mut(),
315+
timestamp_ptr.try_into().unwrap(),
316+
nanos.as_bytes(),
317+
);
318+
319+
return ERRNO_SUCCESS.raw() as i32;
320+
}
321+
322+
ERRNO_INVAL.raw() as i32
323+
}
324+
1 => {
325+
warn!("Unsupported clock_id");
326+
ERRNO_INVAL.raw() as i32
327+
}
328+
_ => ERRNO_INVAL.raw() as i32,
329+
}
330+
},
331+
)
332+
.unwrap();
333+
linker
334+
.func_wrap("wasi_snapshot_preview1", "fd_close", |_fd: i32| {
335+
ERRNO_SUCCESS.raw() as i32
336+
})
337+
.unwrap();
338+
linker
339+
.func_wrap(
340+
"wasi_snapshot_preview1",
341+
"fd_fdstat_get",
342+
|_: i32, _: i32| {
343+
warn!("Unsupported function fd_fdstat_get");
344+
ERRNO_SUCCESS.raw() as i32
345+
},
346+
)
347+
.unwrap();
348+
linker
349+
.func_wrap(
350+
"wasi_snapshot_preview1",
351+
"fd_seek",
352+
|_: i32, _: i64, _: i32, _: i32| {
353+
warn!("Unsupported function fd_seek");
354+
ERRNO_SUCCESS.raw() as i32
355+
},
356+
)
357+
.unwrap();
238358
linker
239359
.func_wrap("wasi_snapshot_preview1", "proc_exit", |_: i32| {
240360
error!("Panic in WASM module")
@@ -298,10 +418,13 @@ async fn wasm_run() {
298418
pub extern "C" fn sys_load_binary(ptr: *const u8, len: usize) -> i32 {
299419
info!("Loading WebAssembly binary...");
300420

421+
let start = now_micros();
301422
let slice = unsafe { core::slice::from_raw_parts(ptr, len) };
302423
let wasm_manager = WasmManager::new(slice);
303424

304425
*WASM_MANAGER.lock() = Some(wasm_manager);
426+
let end = now_micros();
427+
info!("Time to initiate WASM module {} usec", end - start);
305428

306429
if let Some(ref mut wasm_manager) = crate::wasm::WASM_MANAGER.lock().as_mut() {
307430
let _ = wasm_manager.call_func::<(), ()>("hello_world", ());
@@ -312,6 +435,53 @@ pub extern "C" fn sys_load_binary(ptr: *const u8, len: usize) -> i32 {
312435
0
313436
}
314437

438+
#[hermit_macro::system]
439+
#[unsafe(no_mangle)]
440+
pub extern "C" fn sys_dhrystone() -> i32 {
441+
if let Some(ref mut wasm_manager) = WASM_MANAGER.lock().as_mut() {
442+
// And finally we can call the wasm function
443+
info!("Call function dhrystone");
444+
let _result = wasm_manager.call_func::<(), ()>("_start", ()).unwrap();
445+
}
446+
447+
0
448+
}
449+
450+
#[hermit_macro::system]
451+
#[unsafe(no_mangle)]
452+
pub extern "C" fn sys_foo() -> i32 {
453+
if let Some(ref mut wasm_manager) = WASM_MANAGER.lock().as_mut() {
454+
// And finally we can call the wasm function
455+
info!("Call function foo");
456+
let _result = wasm_manager.call_func::<(), ()>("foo", ()).unwrap();
457+
458+
const RUNS: u64 = 1000000;
459+
let start = now_micros();
460+
for _ in 0..RUNS {
461+
black_box(wasm_manager.call_func::<(), ()>("foo", ()).unwrap());
462+
}
463+
let end = now_micros();
464+
info!(
465+
"Average time to call the WASM function foo: {} nsec",
466+
(1000 * (end - start)) / RUNS
467+
);
468+
469+
let start = now_micros();
470+
for _ in 0..RUNS {
471+
black_box(native_foo());
472+
}
473+
let end = now_micros();
474+
475+
info!(
476+
"Time to call {} times the function foo: {} nsec",
477+
RUNS,
478+
1000 * (end - start)
479+
);
480+
}
481+
482+
0
483+
}
484+
315485
#[hermit_macro::system]
316486
#[unsafe(no_mangle)]
317487
pub extern "C" fn sys_fibonacci() -> i32 {

0 commit comments

Comments
 (0)