From b0e617446756ce35953aeddb295d49c5d0e02ded Mon Sep 17 00:00:00 2001 From: nattthebear Date: Wed, 8 Jul 2020 13:54:47 -0400 Subject: [PATCH] minor cleanup --- waterbox/waterboxhost/README.md | 13 +++++++---- waterbox/waterboxhost/src/context/mod.rs | 25 +++++++++++++++++---- waterbox/waterboxhost/src/context/thunks.rs | 3 +++ waterbox/waterboxhost/src/host.rs | 8 +------ 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/waterbox/waterboxhost/README.md b/waterbox/waterboxhost/README.md index 2ffe472e77..0d4edbdef9 100644 --- a/waterbox/waterboxhost/README.md +++ b/waterbox/waterboxhost/README.md @@ -14,10 +14,10 @@ get going: `wbx_activate_host()` 2. Connect exports from the guest executable to your host system `wbx_get_proc_addr()` -3. Run the guest system's init, using function pointers it exposed through wbx_get_proc_addr() +3. Run the guest system's init, using function pointers it exposed through `wbx_get_proc_addr()` 4. Get ready to take savestates `wbx_seal()` -5. Run emulation, using frameadvance or other advance functions exposed by the guest through wbx_get_proc_addr() +5. Run emulation, using frameadvance or other advance functions exposed by the guest through `wbx_get_proc_addr()` 6. Save and load states as needed `wbx_save_state()` `wbx_load_state()` @@ -25,8 +25,13 @@ get going: `wbx_deactivate_host()` `wbx_destroy_host()` -If you're keeping around multiple hosts that may compete for the same address space, use `wbx_activate_host` and `wbx_deactivate_host` -to switch between them. If you'd like to expose files to the virtual filesystem, see `wbx_mount_file` and `wbx_unmount_file` +Some more advanced features: + +* If you're keeping around multiple hosts that may compete for the same address space, + use `wbx_activate_host()` and `wbx_deactivate_host()` to switch between them. +* If you'd like to expose files to the virtual filesystem, see `wbx_mount_file()` and `wbx_unmount_file()`. +* If you need to call dynamically exposed functions that are not part of the static exports, see `wbx_get_callin_addr()`. +* If you'd like the guest code to be able to call callbacks that you pass to it, see `wbx_get_callback_addr()`. ## Building diff --git a/waterbox/waterboxhost/src/context/mod.rs b/waterbox/waterboxhost/src/context/mod.rs index 7839652c56..88707cf8db 100644 --- a/waterbox/waterboxhost/src/context/mod.rs +++ b/waterbox/waterboxhost/src/context/mod.rs @@ -14,7 +14,7 @@ const CALL_GUEST_SIMPLE_ADDR: usize = ORG + 64; pub const CALLBACK_SLOTS: usize = 64; /// Retrieves a function pointer suitable for sending to the guest that will cause -/// the host to callback to `slot` when called +/// the host to callback to `slot` when called. Slot must be less than CALLBACK_SLOTS pub fn get_callback_ptr(slot: usize) -> usize{ assert!(slot < CALLBACK_SLOTS); ORG + 0x100 + slot * 16 @@ -52,27 +52,44 @@ pub fn call_guest_simple(entry_point: usize, context: &mut Context) -> usize{ unsafe { (CALL_GUEST_SIMPLE.f)(entry_point, context) } } - +/// Allowed type for callback functions that Waterbox cores can make back into the real world. pub type ExternalCallback = extern "sysv64" fn( a1: usize, a2: usize, a3: usize, a4: usize, a5: usize, a6: usize) -> usize; +/// Allowed type of the syscall service function pub type SyscallCallback = extern "sysv64" fn( a1: usize, a2: usize, a3: usize, a4: usize, a5: usize, a6: usize, nr: SyscallNumber, h: &mut ActivatedWaterboxHost) -> SyscallReturn; +/// Structure used to track information for calls into waterbox code /// Layout must be synced with interop.s #[repr(C)] pub struct Context { + /// Used internally to track the host's most recent rsp when transitioned to Waterbox code. pub host_rsp: usize, + /// Sets the guest's starting rsp, and used internally to track the guest's most recent rsp when transitioned to extcall or syscall pub guest_rsp: usize, + /// syscall service function pub dispatch_syscall: SyscallCallback, + /// This will be passed as the final parameter to dispatch_syscall, and is not otherwise used by the context tracking code pub host_ptr: usize, + /// Host function pointers that will be called when the guest calls an extcall slot thunk (returned from `get_callback_ptr`) pub extcall_slots: [Option; 64], } - +impl Context { + /// Returns a suitably initialized context. It's almost ready to use, but host_ptr must be set before each usage + pub fn new(initial_guest_rsp: usize, dispatch_syscall: SyscallCallback) -> Context { + Context { + host_rsp: 0, + guest_rsp: initial_guest_rsp, + dispatch_syscall, + host_ptr: 0, + extcall_slots: [None; 64] + } + } +} #[cfg(unix)] thread_local!(static TIB: Box<[usize; 4]> = Box::new([0usize; 4])); - /// Prepares this host thread to be allowed to call guest code. Noop if already called. /// Only needs to happen once per host thread pub fn prepare_thread() { diff --git a/waterbox/waterboxhost/src/context/thunks.rs b/waterbox/waterboxhost/src/context/thunks.rs index 0d1b5d855e..98535b86e8 100644 --- a/waterbox/waterboxhost/src/context/thunks.rs +++ b/waterbox/waterboxhost/src/context/thunks.rs @@ -11,6 +11,7 @@ use std::collections::HashMap; const THUNK_SIZE: usize = 32; +/// tracks thunks for calling into waterbox code pub struct ThunkManager { memory: AddressRange, lookup: HashMap, @@ -25,6 +26,8 @@ impl ThunkManager { } /// Generates a thunk for calling into waterbox. /// Only valid so long as this ThunkManager is alive and set_context_ptr is kept up to date + /// See also `call_guest_simple`, which directly performs a call of the sort that these thunks do, but requires + /// Context to be passed at the time of call and cannot pass arguments to the guest pub fn get_thunk_for_proc(&mut self, guest_entry_point: usize, context: *mut Context) -> anyhow::Result { match self.lookup.get(&guest_entry_point) { Some(p) => return Ok(*p), diff --git a/waterbox/waterboxhost/src/host.rs b/waterbox/waterboxhost/src/host.rs index 4791883e32..57666fec6d 100644 --- a/waterbox/waterboxhost/src/host.rs +++ b/waterbox/waterboxhost/src/host.rs @@ -41,13 +41,7 @@ impl WaterboxHost { active: false, sealed: false, image_file, - context: Context { - host_rsp: 0, - guest_rsp: layout.main_thread.end(), - dispatch_syscall: syscall, - host_ptr: 0, - extcall_slots: [None; 64], - }, + context: Context::new(layout.main_thread.end(), syscall), thunks, });