@@ -172,32 +172,95 @@ pub extern "C" fn wasmtime_init_traps(handler: wasmtime_trap_handler_t) -> i32 {
172172 0
173173}
174174
175- // The wasmtime_memory_image APIs are not yet supported.
175+ // Copy a VA range to a new VA. Old and new VA, and len, must be
176+ // page-aligned.
177+ fn copy_va_mapping ( base : * const u8 , len : usize , to_va : * mut u8 , remap_original : bool ) {
178+ // TODO: make this more efficient by directly exposing the ability
179+ // to traverse an entire VA range in
180+ // hyperlight_guest_bin::paging::virt_to_phys, and coalescing
181+ // continuous ranges there.
182+ let base_u = base as u64 ;
183+ let va_page_bases = ( base_u..( base_u + len as u64 ) ) . step_by ( vmem:: PAGE_SIZE ) ;
184+ let mappings = va_page_bases. flat_map ( paging:: virt_to_phys) ;
185+ for mapping in mappings {
186+ // TODO: Deduplicate with identical logic in hyperlight_host snapshot.
187+ let ( new_kind, was_writable) = match mapping. kind {
188+ // Skip unmapped pages, since they will be unmapped in
189+ // both the original and the new copy
190+ vmem:: MappingKind :: Unmapped => continue ,
191+ vmem:: MappingKind :: Basic ( bm) if bm. writable => ( vmem:: MappingKind :: Cow ( vmem:: CowMapping {
192+ readable : bm. readable ,
193+ executable : bm. executable ,
194+ } ) , true ) ,
195+ vmem:: MappingKind :: Basic ( bm) => ( vmem:: MappingKind :: Basic ( vmem:: BasicMapping {
196+ readable : bm. readable ,
197+ writable : false ,
198+ executable : bm. executable ,
199+ } ) , false ) ,
200+ vmem:: MappingKind :: Cow ( cm) => ( vmem:: MappingKind :: Cow ( cm) , false ) ,
201+ } ;
202+ if remap_original && was_writable {
203+ // If necessary, remap the original page as Cow, instead
204+ // of whatever it is now, to ensure that any more writes to
205+ // that region do not change the image base.
206+ //
207+ // TODO: could the table traversal needed for this be fused
208+ // with the table traversal that got the original mapping,
209+ // above?
210+ unsafe {
211+ paging:: map_region (
212+ mapping. phys_base ,
213+ mapping. virt_base as * mut u8 ,
214+ vmem:: PAGE_SIZE as u64 ,
215+ new_kind,
216+ ) ;
217+ }
218+ }
219+ // map the same pages to the new VA
220+ unsafe {
221+ paging:: map_region (
222+ mapping. phys_base ,
223+ to_va. wrapping_add ( ( mapping. virt_base - base_u) as usize ) ,
224+ vmem:: PAGE_SIZE as u64 ,
225+ new_kind,
226+ ) ;
227+ }
228+ }
229+ }
230+
231+ // Create a copy-on-write memory image from some existing VA range.
232+ // `ptr` and `len` must be page-aligned (which is guaranteed by the
233+ // wasmtime-platform.h interface).
176234#[ no_mangle]
177235pub extern "C" fn wasmtime_memory_image_new (
178- _ptr : * const u8 ,
179- _len : usize ,
236+ ptr : * const u8 ,
237+ len : usize ,
180238 ret : & mut * mut c_void ,
181239) -> i32 {
182- * ret = core:: ptr:: null_mut ( ) ;
240+ // Choose an arbitrary VA, which we will use as the memory image
241+ // identifier. We will construct the image by mapping a copy of
242+ // the original VA range here, making the original copy CoW as we
243+ // go.
244+ let new_virt = FIRST_VADDR . fetch_add ( 0x100_0000_0000 , Ordering :: Relaxed ) as * mut u8 ;
245+ copy_va_mapping ( ptr, len, new_virt, true ) ;
246+ * ret = new_virt as * mut c_void ;
183247 0
184248}
185249
186250#[ no_mangle]
187251pub extern "C" fn wasmtime_memory_image_map_at (
188- _image : * mut c_void ,
189- _addr : * mut u8 ,
190- _len : usize ,
252+ image : * mut c_void ,
253+ addr : * mut u8 ,
254+ len : usize ,
191255) -> i32 {
192- /* This should never be called because wasmtime_memory_image_new
193- * returns NULL */
194- panic ! ( "wasmtime_memory_image_map_at" ) ;
256+ copy_va_mapping ( image as * mut u8 , len, addr, false ) ;
257+ 0
195258}
196259
197260#[ no_mangle]
198261pub extern "C" fn wasmtime_memory_image_free ( _image : * mut c_void ) {
199- /* This should never be called because wasmtime_memory_image_new
200- * returns NULL */
262+ /* This should never be called in practice, because we simple
263+ * restore the snapshot rather than actually unload/destroy instances */
201264 panic ! ( "wasmtime_memory_image_free" ) ;
202265}
203266
0 commit comments