@@ -55,6 +55,9 @@ pub(crate) mod windows_hypervisor_platform;
5555#[ cfg( target_os = "windows" ) ]
5656pub ( crate ) mod wrappers;
5757
58+ #[ cfg( crashdump) ]
59+ pub ( crate ) mod crashdump;
60+
5861use std:: fmt:: Debug ;
5962use std:: sync:: { Arc , Mutex } ;
6063
@@ -184,70 +187,8 @@ pub(crate) trait Hypervisor: Debug + Sync + Send {
184187 #[ cfg( target_os = "windows" ) ]
185188 fn get_partition_handle ( & self ) -> windows:: Win32 :: System :: Hypervisor :: WHV_PARTITION_HANDLE ;
186189
187- /// Dump memory to a file on crash
188- #[ cfg( all( debug_assertions, feature = "dump_on_crash" , target_os = "linux" ) ) ]
189- fn dump_on_crash ( & self , mem_regions : Vec < MemoryRegion > ) {
190- let memory_size = mem_regions
191- . iter ( )
192- . map ( |region| region. guest_region . end - region. guest_region . start )
193- . sum ( ) ;
194- if let Err ( e) = unsafe {
195- self . write_dump_file (
196- mem_regions. clone ( ) ,
197- mem_regions[ 0 ] . host_region . start as * const u8 ,
198- memory_size,
199- )
200- } {
201- println ! ( "Error dumping memory: {}" , e) ;
202- }
203- }
204-
205- /// A function that takes an address and a size and writes the memory at that address to a file in the temp/tmp directory
206- /// # Safety
207- /// This function is unsafe because it is writing memory to a file, make sure that the address is valid and that the size is correct
208- /// This function is only available when the `dump_on_crash` feature is enabled and running in debug mode
209- #[ cfg( all( feature = "dump_on_crash" , debug_assertions) ) ]
210- unsafe fn write_dump_file (
211- & self ,
212- regions : Vec < MemoryRegion > ,
213- address : * const u8 ,
214- size : usize ,
215- ) -> Result < ( ) > {
216- use std:: io:: Write ;
217-
218- use tempfile:: NamedTempFile ;
219-
220- if address. is_null ( ) || size == 0 {
221- return Err ( new_error ! ( "Invalid address or size" ) ) ;
222- }
223-
224- let hv_details = format ! ( "{:#?}" , self ) ;
225- let regions_details = format ! ( "{:#?}" , regions) ;
226-
227- // Create a temporary file
228- let mut file = NamedTempFile :: with_prefix ( "mem" ) ?;
229- let temp_path = file. path ( ) . to_path_buf ( ) ;
230-
231- file. write_all ( hv_details. as_bytes ( ) ) ?;
232- file. write_all ( b"\n " ) ?;
233- file. write_all ( regions_details. as_bytes ( ) ) ?;
234- file. write_all ( b"\n " ) ?;
235-
236- // SAFETY: Ensure the address and size are valid and accessible
237- unsafe {
238- let slice = std:: slice:: from_raw_parts ( address, size) ;
239- file. write_all ( slice) ?;
240- file. flush ( ) ?;
241- }
242- let persist_path = temp_path. with_extension ( "dmp" ) ;
243- file. persist ( & persist_path)
244- . map_err ( |e| new_error ! ( "Failed to persist file: {:?}" , e) ) ?;
245-
246- print ! ( "Memory dumped to file: {:?}" , persist_path) ;
247- log:: error!( "Memory dumped to file: {:?}" , persist_path) ;
248-
249- Ok ( ( ) )
250- }
190+ #[ cfg( crashdump) ]
191+ fn get_memory_regions ( & self ) -> & [ MemoryRegion ] ;
251192}
252193
253194/// A virtual CPU that can be run until an exit occurs
@@ -271,11 +212,15 @@ impl VirtualCPU {
271212 hv. handle_io ( port, data, rip, instruction_length, outb_handle_fn. clone ( ) ) ?
272213 }
273214 HyperlightExit :: Mmio ( addr) => {
215+ #[ cfg( crashdump) ]
216+ crashdump:: crashdump_to_tempfile ( hv) ?;
217+
274218 mem_access_fn
275219 . clone ( )
276220 . try_lock ( )
277221 . map_err ( |e| new_error ! ( "Error locking at {}:{}: {}" , file!( ) , line!( ) , e) ) ?
278222 . call ( ) ?;
223+
279224 log_then_return ! ( "MMIO access address {:#x}" , addr) ;
280225 }
281226 HyperlightExit :: AccessViolation ( addr, tried, region_permission) => {
0 commit comments