@@ -144,8 +144,7 @@ impl KVMDriver {
144144 . set_entrypoint_bp ( )
145145 . map_err ( |_| new_error ! ( "Cannot set entrypoint breakpoint" ) ) ?;
146146
147- let _ =
148- gdb:: create_gdb_thread ( target) . map_err ( |_| new_error ! ( "Cannot create GDB thread" ) ) ?;
147+ gdb:: create_gdb_thread ( target) . map_err ( |_| new_error ! ( "Cannot create GDB thread" ) ) ?;
149148
150149 Ok ( gdb_conn)
151150 }
@@ -162,6 +161,63 @@ impl KVMDriver {
162161 vcpu_fd. set_sregs ( & sregs) ?;
163162 Ok ( ( ) )
164163 }
164+
165+ #[ instrument( err( Debug ) , skip_all, parent = Span :: current( ) , level = "Trace" ) ]
166+ fn run_once ( & mut self ) -> Result < HyperlightExit > {
167+ let result = match self . vcpu_fd . lock ( ) . unwrap ( ) . run ( ) {
168+ Ok ( VcpuExit :: Hlt ) => {
169+ crate :: debug!( "KVM - Halt Details : {:#?}" , & self ) ;
170+ HyperlightExit :: Halt ( )
171+ }
172+ Ok ( VcpuExit :: IoOut ( port, data) ) => {
173+ // because vcpufd.run() mutably borrows self we cannot pass self to crate::debug! macro here
174+ crate :: debug!( "KVM IO Details : \n Port : {}\n Data : {:?}" , port, data) ;
175+ // KVM does not need to set RIP or instruction length so these are set to 0
176+ HyperlightExit :: IoOut ( port, data. to_vec ( ) , 0 , 0 )
177+ }
178+ Ok ( VcpuExit :: MmioRead ( addr, _) ) => {
179+ crate :: debug!( "KVM MMIO Read -Details: Address: {} \n {:#?}" , addr, & self ) ;
180+
181+ match self . get_memory_access_violation (
182+ addr as usize ,
183+ & self . mem_regions ,
184+ MemoryRegionFlags :: READ ,
185+ ) {
186+ Some ( access_violation_exit) => access_violation_exit,
187+ None => HyperlightExit :: Mmio ( addr) ,
188+ }
189+ }
190+ Ok ( VcpuExit :: MmioWrite ( addr, _) ) => {
191+ crate :: debug!( "KVM MMIO Write -Details: Address: {} \n {:#?}" , addr, & self ) ;
192+
193+ match self . get_memory_access_violation (
194+ addr as usize ,
195+ & self . mem_regions ,
196+ MemoryRegionFlags :: WRITE ,
197+ ) {
198+ Some ( access_violation_exit) => access_violation_exit,
199+ None => HyperlightExit :: Mmio ( addr) ,
200+ }
201+ }
202+ #[ cfg( gdb) ]
203+ Ok ( VcpuExit :: Debug ( _) ) => HyperlightExit :: Debug ,
204+ Err ( e) => match e. errno ( ) {
205+ // we send a signal to the thread to cancel execution this results in EINTR being returned by KVM so we return Cancelled
206+ libc:: EINTR => HyperlightExit :: Cancelled ( ) ,
207+ libc:: EAGAIN => HyperlightExit :: Retry ( ) ,
208+ _ => {
209+ crate :: debug!( "KVM Error -Details: Address: {} \n {:#?}" , e, & self ) ;
210+ log_then_return ! ( "Error running VCPU {:?}" , e) ;
211+ }
212+ } ,
213+ Ok ( other) => {
214+ crate :: debug!( "KVM Other Exit {:?}" , other) ;
215+ HyperlightExit :: Unknown ( format ! ( "Unexpected KVM Exit {:?}" , other) )
216+ }
217+ } ;
218+
219+ Ok ( result)
220+ }
165221}
166222
167223impl Debug for KVMDriver {
@@ -303,48 +359,13 @@ impl Hypervisor for KVMDriver {
303359
304360 #[ instrument( err( Debug ) , skip_all, parent = Span :: current( ) , level = "Trace" ) ]
305361 fn run ( & mut self ) -> Result < HyperlightExit > {
306- let result = loop {
307- let mut vcpu_fd = self . vcpu_fd . lock ( ) . unwrap ( ) ;
308- let result = match vcpu_fd. run ( ) {
309- Ok ( VcpuExit :: Hlt ) => {
310- crate :: debug!( "KVM - Halt Details : {:#?}" , & self ) ;
311- HyperlightExit :: Halt ( )
312- }
313- Ok ( VcpuExit :: IoOut ( port, data) ) => {
314- // because vcpufd.run() mutably borrows self we cannot pass self to crate::debug! macro here
315- crate :: debug!( "KVM IO Details : \n Port : {}\n Data : {:?}" , port, data) ;
316- // KVM does not need to set RIP or instruction length so these are set to 0
317- HyperlightExit :: IoOut ( port, data. to_vec ( ) , 0 , 0 )
318- }
319- Ok ( VcpuExit :: MmioRead ( addr, _) ) => {
320- crate :: debug!( "KVM MMIO Read -Details: Address: {} \n {:#?}" , addr, & self ) ;
321-
322- match self . get_memory_access_violation (
323- addr as usize ,
324- & self . mem_regions ,
325- MemoryRegionFlags :: READ ,
326- ) {
327- Some ( access_violation_exit) => access_violation_exit,
328- None => HyperlightExit :: Mmio ( addr) ,
329- }
330- }
331- Ok ( VcpuExit :: MmioWrite ( addr, _) ) => {
332- crate :: debug!( "KVM MMIO Write -Details: Address: {} \n {:#?}" , addr, & self ) ;
333-
334- match self . get_memory_access_violation (
335- addr as usize ,
336- & self . mem_regions ,
337- MemoryRegionFlags :: WRITE ,
338- ) {
339- Some ( access_violation_exit) => access_violation_exit,
340- None => HyperlightExit :: Mmio ( addr) ,
341- }
342- }
343- #[ cfg( gdb) ]
344- Ok ( VcpuExit :: Debug ( arch) ) => {
345- // Drop so that the gdb thread can acquire the VcpuFd
346- drop ( vcpu_fd) ;
347- log:: debug!( "Sending gdb message to notify KVM_EXIT_DEBUG {:?}" , arch) ;
362+ #[ cfg( gdb) ]
363+ loop {
364+ let mut result = self . run_once ( ) ;
365+
366+ result = match result {
367+ Ok ( HyperlightExit :: Debug ) => {
368+ log:: debug!( "Sending gdb message to notify KVM_EXIT_DEBUG" ) ;
348369 self . gdb_conn
349370 . send ( DebugMessage :: VcpuStoppedEv )
350371 . map_err ( |e| {
@@ -359,10 +380,12 @@ impl Hypervisor for KVMDriver {
359380 self . gdb_conn . send ( DebugMessage :: RspOk ) . map_err ( |e| {
360381 new_error ! (
361382 "Couldn't signal vCPU event received to GDB
362- thread: {:?}" ,
383+ thread: {:?}" ,
363384 e
364385 )
365386 } ) ?;
387+
388+ // Run one more time
366389 continue ;
367390 }
368391 e => {
@@ -374,29 +397,18 @@ impl Hypervisor for KVMDriver {
374397 }
375398 }
376399
377- HyperlightExit :: Unknown (
400+ Ok ( HyperlightExit :: Unknown (
378401 "KVM Debug Exit failed to receive debug event from GDB" . to_string ( ) ,
379- )
380- }
381- Err ( e) => match e. errno ( ) {
382- // we send a signal to the thread to cancel execution this results in EINTR being returned by KVM so we return Cancelled
383- libc:: EINTR => HyperlightExit :: Cancelled ( ) ,
384- libc:: EAGAIN => HyperlightExit :: Retry ( ) ,
385- _ => {
386- crate :: debug!( "KVM Error -Details: Address: {} \n {:#?}" , e, & self ) ;
387- log_then_return ! ( "Error running VCPU {:?}" , e) ;
388- }
389- } ,
390- Ok ( other) => {
391- crate :: debug!( "KVM Other Exit {:?}" , other) ;
392- HyperlightExit :: Unknown ( format ! ( "Unexpected KVM Exit {:?}" , other) )
402+ ) )
393403 }
404+ e => e,
394405 } ;
395406
396407 break result;
397- } ;
408+ }
398409
399- Ok ( result)
410+ #[ cfg( not( gdb) ) ]
411+ self . run_once ( )
400412 }
401413
402414 #[ instrument( skip_all, parent = Span :: current( ) , level = "Trace" ) ]
0 commit comments