@@ -65,6 +65,7 @@ pub(crate) fn is_hypervisor_present() -> bool {
6565
6666#[ cfg( gdb) ]
6767mod debug {
68+ use std:: collections:: HashMap ;
6869 use std:: sync:: { Arc , Mutex } ;
6970
7071 use hyperlight_common:: mem:: PAGE_SIZE ;
@@ -80,6 +81,13 @@ mod debug {
8081 use crate :: mem:: layout:: SandboxMemoryLayout ;
8182 use crate :: { new_error, Result } ;
8283
84+ /// Software Breakpoint size in memory
85+ pub const SW_BP_SIZE : usize = 1 ;
86+ /// Software Breakpoinnt opcode
87+ const SW_BP_OP : u8 = 0xCC ;
88+ /// Software Breakpoint written to memory
89+ pub const SW_BP : [ u8 ; SW_BP_SIZE ] = [ SW_BP_OP ] ;
90+
8391 /// KVM Debug struct
8492 /// This struct is used to abstract the internal details of the kvm
8593 /// guest debugging settings
@@ -90,6 +98,8 @@ mod debug {
9098
9199 /// Array of addresses for HW breakpoints
92100 hw_breakpoints : Vec < u64 > ,
101+ /// Saves the bytes modified to enable sw breakpoints
102+ sw_breakpoints : HashMap < u64 , [ u8 ; SW_BP_SIZE ] > ,
93103
94104 /// Sent to KVM for enabling guest debug
95105 pub dbg_cfg : kvm_guest_debug ,
@@ -107,6 +117,7 @@ mod debug {
107117 Self {
108118 single_step : false ,
109119 hw_breakpoints : vec ! [ ] ,
120+ sw_breakpoints : HashMap :: new ( ) ,
110121 dbg_cfg : dbg,
111122 }
112123 }
@@ -380,6 +391,69 @@ mod debug {
380391 }
381392 }
382393
394+ pub fn add_sw_breakpoint (
395+ & mut self ,
396+ addr : u64 ,
397+ dbg_mem_access_fn : Arc < Mutex < dyn DbgMemAccessHandlerCaller > > ,
398+ ) -> Result < bool > {
399+ let addr = {
400+ let debug = self
401+ . debug
402+ . as_ref ( )
403+ . ok_or_else ( || new_error ! ( "Debug is not enabled" ) ) ?;
404+ let addr = self . translate_gva ( addr) ?;
405+ if debug. sw_breakpoints . contains_key ( & addr) {
406+ return Ok ( true ) ;
407+ }
408+
409+ addr
410+ } ;
411+
412+ let mut save_data = [ 0 ; SW_BP_SIZE ] ;
413+ self . read_addrs ( addr, & mut save_data[ ..] , dbg_mem_access_fn. clone ( ) ) ?;
414+ self . write_addrs ( addr, & SW_BP , dbg_mem_access_fn. clone ( ) ) ?;
415+
416+ {
417+ let debug = self
418+ . debug
419+ . as_mut ( )
420+ . ok_or_else ( || new_error ! ( "Debug is not enabled" ) ) ?;
421+ debug. sw_breakpoints . insert ( addr, save_data) ;
422+ }
423+
424+ Ok ( true )
425+ }
426+
427+ pub fn remove_sw_breakpoint (
428+ & mut self ,
429+ addr : u64 ,
430+ dbg_mem_access_fn : Arc < Mutex < dyn DbgMemAccessHandlerCaller > > ,
431+ ) -> Result < bool > {
432+ let ( ret, data) = {
433+ let addr = self . translate_gva ( addr) ?;
434+ let debug = self
435+ . debug
436+ . as_mut ( )
437+ . ok_or_else ( || new_error ! ( "Debug is not enabled" ) ) ?;
438+
439+ if debug. sw_breakpoints . contains_key ( & addr) {
440+ let save_data = debug
441+ . sw_breakpoints
442+ . remove ( & addr)
443+ . expect ( "Expected the hashmap to contain the address" ) ;
444+
445+ ( true , Some ( save_data) )
446+ } else {
447+ ( false , None )
448+ }
449+ } ;
450+
451+ if ret {
452+ self . write_addrs ( addr, & data. unwrap ( ) , dbg_mem_access_fn. clone ( ) ) ?;
453+ }
454+
455+ Ok ( ret)
456+ }
383457
384458 /// Get the reason the vCPU has stopped
385459 pub fn get_stop_reason ( & self ) -> Result < VcpuStopReason > {
@@ -394,6 +468,9 @@ mod debug {
394468
395469 let ip = self . get_instruction_pointer ( ) ?;
396470 let gpa = self . translate_gva ( ip) ?;
471+ if debug. sw_breakpoints . contains_key ( & gpa) {
472+ return Ok ( VcpuStopReason :: SwBp ) ;
473+ }
397474
398475 if debug. hw_breakpoints . contains ( & gpa) {
399476 return Ok ( VcpuStopReason :: HwBp ) ;
@@ -418,6 +495,13 @@ mod debug {
418495 . expect ( "Add hw breakpoint error" ) ;
419496 Ok ( DebugResponse :: AddHwBreakpoint ( res) )
420497 }
498+ DebugMsg :: AddSwBreakpoint ( addr) => {
499+ let res = self
500+ . add_sw_breakpoint ( addr, dbg_mem_access_fn. clone ( ) )
501+ . expect ( "Add sw breakpoint error" ) ;
502+
503+ Ok ( DebugResponse :: AddSwBreakpoint ( res) )
504+ }
421505 DebugMsg :: Continue => {
422506 self . set_single_step ( false ) ?;
423507 Ok ( DebugResponse :: Continue )
@@ -454,6 +538,12 @@ mod debug {
454538 . expect ( "Remove hw breakpoint error" ) ;
455539 Ok ( DebugResponse :: RemoveHwBreakpoint ( res) )
456540 }
541+ DebugMsg :: RemoveSwBreakpoint ( addr) => {
542+ let res = self
543+ . remove_sw_breakpoint ( addr, dbg_mem_access_fn. clone ( ) )
544+ . expect ( "Remove sw breakpoint error" ) ;
545+ Ok ( DebugResponse :: RemoveSwBreakpoint ( res) )
546+ }
457547 DebugMsg :: Step => {
458548 self . set_single_step ( true ) ?;
459549 Ok ( DebugResponse :: Step )
0 commit comments