@@ -17,6 +17,7 @@ limitations under the License.
1717use std:: path:: Path ;
1818
1919use hyperlight_host:: func:: call_ctx:: MultiUseGuestCallContext ;
20+ use hyperlight_host:: mem:: memory_region:: { MemoryRegion , MemoryRegionFlags , MemoryRegionType } ;
2021use hyperlight_host:: sandbox:: Callable ;
2122use hyperlight_host:: sandbox_state:: sandbox:: { EvolvableSandbox , Sandbox } ;
2223use hyperlight_host:: sandbox_state:: transition:: MultiUseContextCallback ;
@@ -59,34 +60,87 @@ impl WasmSandbox {
5960 /// Before you can call guest functions in the sandbox, you must call
6061 /// this function and use the returned value to call guest functions.
6162 pub fn load_module ( self , file : impl AsRef < Path > ) -> Result < LoadedWasmSandbox > {
62- let wasm_bytes = std:: fs:: read ( file) ?;
63- self . load_module_inner ( wasm_bytes)
63+ let func = Box :: new ( move |call_ctx : & mut MultiUseGuestCallContext | {
64+ if let Ok ( len) = call_ctx. map_file_cow ( file. as_ref ( ) , 0x1_0000_0000 ) {
65+ call_ctx. call ( "LoadWasmModulePhys" , ( 0x1_0000_0000u64 , len) )
66+ } else {
67+ let wasm_bytes = std:: fs:: read ( file) ?;
68+ Self :: load_module_from_buffer_transition_func ( wasm_bytes) ( call_ctx)
69+ }
70+ } ) ;
71+ self . load_module_inner ( func)
6472 }
6573
66- /// Load a Wasm module from a buffer of bytes into the sandbox and return a `LoadedWasmSandbox`
67- /// able to execute code in the loaded Wasm Module.
74+ /// Load a Wasm module that is currently present in a buffer in
75+ /// host memory, by mapping the host memory directly into the
76+ /// sandbox.
6877 ///
69- /// Before you can call guest functions in the sandbox, you must call
70- /// this function and use the returned value to call guest functions.
71- pub fn load_module_from_buffer ( self , buffer : & [ u8 ] ) -> Result < LoadedWasmSandbox > {
72- self . load_module_inner ( buffer. to_vec ( ) )
78+ /// Depending on the host platform, there are likely alignment
79+ /// requirements of at least one page for base and len
80+ ///
81+ /// # Safety
82+ /// It is the caller's responsibility to ensure that the host side
83+ /// of the region remains intact and is not written to until the
84+ /// produced LoadedWasmSandbox is discarded or devolved.
85+ pub unsafe fn load_module_by_mapping (
86+ self ,
87+ base : * mut libc:: c_void ,
88+ len : usize ,
89+ ) -> Result < LoadedWasmSandbox > {
90+ let func = Box :: new ( move |call_ctx : & mut MultiUseGuestCallContext | {
91+ let guest_base: usize = 0x1_0000_0000 ;
92+ let rgn = MemoryRegion {
93+ host_region : base as usize ..base. wrapping_add ( len) as usize ,
94+ guest_region : guest_base..guest_base + len,
95+ flags : MemoryRegionFlags :: READ | MemoryRegionFlags :: EXECUTE ,
96+ region_type : MemoryRegionType :: Heap ,
97+ } ;
98+ if let Ok ( ( ) ) = unsafe { call_ctx. map_region ( & rgn) } {
99+ call_ctx. call ( "LoadWasmModulePhys" , ( 0x1_0000_0000u64 , len as u64 ) )
100+ } else {
101+ let wasm_bytes =
102+ unsafe { std:: slice:: from_raw_parts ( base as * const u8 , len) . to_vec ( ) } ;
103+ Self :: load_module_from_buffer_transition_func ( wasm_bytes) ( call_ctx)
104+ }
105+ } ) ;
106+ self . load_module_inner ( func)
73107 }
74108
75- fn load_module_inner ( mut self , wasm_bytes : Vec < u8 > ) -> Result < LoadedWasmSandbox > {
76- let func = Box :: new ( move |call_ctx : & mut MultiUseGuestCallContext | {
77- let len = wasm_bytes. len ( ) as i32 ;
78- let res: i32 = call_ctx. call ( "LoadWasmModule" , ( wasm_bytes, len) ) ?;
109+ // todo: take a slice rather than a vec (requires somewhat
110+ // refactoring the flatbuffers stuff maybe)
111+ fn load_module_from_buffer_transition_func (
112+ buffer : Vec < u8 > ,
113+ ) -> impl FnOnce ( & mut MultiUseGuestCallContext ) -> Result < ( ) > {
114+ move |call_ctx : & mut MultiUseGuestCallContext | {
115+ let len = buffer. len ( ) as i32 ;
116+ let res: i32 = call_ctx. call ( "LoadWasmModule" , ( buffer, len) ) ?;
79117 if res != 0 {
80118 return Err ( new_error ! (
81119 "LoadWasmModule Failed with error code {:?}" ,
82120 res
83121 ) ) ;
84122 }
85123 Ok ( ( ) )
86- } ) ;
124+ }
125+ }
87126
88- let transition_func = MultiUseContextCallback :: from ( func) ;
127+ /// Load a Wasm module from a buffer of bytes into the sandbox and return a `LoadedWasmSandbox`
128+ /// able to execute code in the loaded Wasm Module.
129+ ///
130+ /// Before you can call guest functions in the sandbox, you must call
131+ /// this function and use the returned value to call guest functions.
132+ pub fn load_module_from_buffer ( self , buffer : & [ u8 ] ) -> Result < LoadedWasmSandbox > {
133+ // TODO: get rid of this clone
134+ let func = Self :: load_module_from_buffer_transition_func ( buffer. to_vec ( ) ) ;
89135
136+ self . load_module_inner ( func)
137+ }
138+
139+ fn load_module_inner < F : FnOnce ( & mut MultiUseGuestCallContext ) -> Result < ( ) > > (
140+ mut self ,
141+ func : F ,
142+ ) -> Result < LoadedWasmSandbox > {
143+ let transition_func = MultiUseContextCallback :: from ( func) ;
90144 match self . inner . take ( ) {
91145 Some ( sbox) => {
92146 let new_sbox: MultiUseSandbox = sbox. evolve ( transition_func) ?;
0 commit comments