use alloc::format; use wasmi::{ Error, Externals, FuncInstance, FuncRef, ModuleImportResolver, RuntimeArgs, RuntimeValue, Signature, Trap, ValueType, }; pub struct HostExternals {} const ADD_FUNC_INDEX: usize = 0; const SEND_SIGNAL_INDEX: usize = 1; const GET_TIME_INDEX: usize = 2; impl Externals for HostExternals { fn invoke_index( &mut self, index: usize, args: RuntimeArgs, ) -> Result, Trap> { match index { ADD_FUNC_INDEX => { let a: u32 = args.nth_checked(0)?; let b: u32 = args.nth_checked(1)?; let result = a + b; println!("SYSCALL: {} + {} = {}", a, b, result); Ok(Some(RuntimeValue::I32(result as i32))) } SEND_SIGNAL_INDEX => { let pid: u32 = args.nth_checked(0)?; let signal: u32 = args.nth_checked(1)?; println!("SYSCALL: send signal {} to pid {}", signal, pid); let ret = RuntimeValue::I32(0); Ok(Some(ret)) } GET_TIME_INDEX => { use core::sync::atomic::Ordering::*; x86_64::instructions::interrupts::disable(); let tick_time = crate::kmain::TICK.load(Relaxed); x86_64::instructions::interrupts::enable(); let ret = RuntimeValue::I64(tick_time.try_into().unwrap()); Ok(Some(ret)) } _ => panic!("Unimplemented function at {}", index), } } } impl HostExternals { fn check_signature(&self, index: usize, signature: &Signature) -> bool { let (params, ret_ty): (&[ValueType], Option) = match index { ADD_FUNC_INDEX => (&[ValueType::I32, ValueType::I32], Some(ValueType::I32)), SEND_SIGNAL_INDEX => (&[ValueType::I32, ValueType::I32], Some(ValueType::I32)), GET_TIME_INDEX => (&[], Some(ValueType::I32)), _ => return false, }; signature.params() == params && signature.return_type() == ret_ty } } impl ModuleImportResolver for HostExternals { fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result { let index = match field_name { "add" => ADD_FUNC_INDEX, "send_signal" => SEND_SIGNAL_INDEX, _ => { return Err(Error::Instantiation(format!( "Export {} not found", field_name ))) } }; if !self.check_signature(index, signature) { return Err(Error::Instantiation(format!( "Export {} has a bad signature", field_name ))); } Ok(FuncInstance::alloc_host( Signature::new(&[ValueType::I32, ValueType::I32][..], Some(ValueType::I32)), index, )) } }