1
+ use std:: collections:: HashMap ;
1
2
use std:: sync:: { Arc , Mutex } ;
2
3
3
4
use crossbeam_channel:: TryRecvError ;
@@ -10,7 +11,7 @@ use gdbstub::target::ext::base::singlethread::{
10
11
} ;
11
12
use gdbstub:: target:: ext:: base:: BaseOps ;
12
13
use gdbstub:: target:: ext:: breakpoints:: {
13
- Breakpoints , BreakpointsOps , HwBreakpoint , HwBreakpointOps ,
14
+ Breakpoints , BreakpointsOps , HwBreakpoint , HwBreakpointOps , SwBreakpoint , SwBreakpointOps ,
14
15
} ;
15
16
use gdbstub:: target:: ext:: section_offsets:: { Offsets , SectionOffsets } ;
16
17
use gdbstub:: target:: { Target , TargetError , TargetResult } ;
@@ -19,7 +20,7 @@ use gdbstub_arch::x86::X86_64_SSE as GdbTargetArch;
19
20
use hyperlight_common:: mem:: PAGE_SIZE ;
20
21
use kvm_bindings:: {
21
22
kvm_guest_debug, kvm_regs, KVM_GUESTDBG_ENABLE , KVM_GUESTDBG_SINGLESTEP ,
22
- KVM_GUESTDBG_USE_HW_BP ,
23
+ KVM_GUESTDBG_USE_HW_BP , KVM_GUESTDBG_USE_SW_BP ,
23
24
} ;
24
25
use kvm_ioctls:: VcpuFd ;
25
26
@@ -29,6 +30,13 @@ use crate::mem::layout::SandboxMemoryLayout;
29
30
use crate :: mem:: mgr:: SandboxMemoryManager ;
30
31
use crate :: mem:: shared_mem:: { GuestSharedMemory , SharedMemory } ;
31
32
33
+ /// Software Breakpoint size in memory
34
+ const SW_BP_SIZE : usize = 1 ;
35
+ /// Software Breakpoinnt opcode
36
+ const SW_BP_OP : u8 = 0xCC ;
37
+ /// Software Breakpoint written to memory
38
+ const SW_BP : [ u8 ; SW_BP_SIZE ] = [ SW_BP_OP ] ;
39
+
32
40
/// KVM Debug struct
33
41
/// This struct is used to abstract the internal details of the kvm
34
42
/// guest debugging settings
@@ -42,7 +50,7 @@ impl KvmDebug {
42
50
43
51
pub fn new ( ) -> Self {
44
52
let dbg = kvm_guest_debug {
45
- control : KVM_GUESTDBG_ENABLE ,
53
+ control : KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP ,
46
54
..Default :: default ( )
47
55
} ;
48
56
@@ -106,6 +114,8 @@ pub struct HyperlightKvmSandboxTarget {
106
114
107
115
/// Array of addresses for HW breakpoints
108
116
hw_breakpoints : Vec < u64 > ,
117
+ /// Array of addresses for SW breakpoints
118
+ sw_breakpoints : HashMap < u64 , [ u8 ; SW_BP_SIZE ] > ,
109
119
110
120
/// Hypervisor communication channels
111
121
hyp_conn : GdbConnection ,
@@ -130,6 +140,7 @@ impl HyperlightKvmSandboxTarget {
130
140
single_step : false ,
131
141
132
142
hw_breakpoints : vec ! [ ] ,
143
+ sw_breakpoints : HashMap :: new ( ) ,
133
144
134
145
hyp_conn,
135
146
}
@@ -437,6 +448,9 @@ impl Breakpoints for HyperlightKvmSandboxTarget {
437
448
fn support_hw_breakpoint ( & mut self ) -> Option < HwBreakpointOps < Self > > {
438
449
Some ( self )
439
450
}
451
+ fn support_sw_breakpoint ( & mut self ) -> Option < SwBreakpointOps < ' _ , Self > > {
452
+ Some ( self )
453
+ }
440
454
}
441
455
442
456
impl HwBreakpoint for HyperlightKvmSandboxTarget {
@@ -496,6 +510,55 @@ impl HwBreakpoint for HyperlightKvmSandboxTarget {
496
510
}
497
511
}
498
512
513
+ impl SwBreakpoint for HyperlightKvmSandboxTarget {
514
+ /// Adds a software breakpoint by setting a specific operation code at the
515
+ /// address so when the vCPU hits it, it knows it is a software breakpoint.
516
+ ///
517
+ /// The existing data at the address is saved so it can be restored when
518
+ /// removing the breakpoint
519
+ fn add_sw_breakpoint (
520
+ & mut self ,
521
+ addr : <Self :: Arch as Arch >:: Usize ,
522
+ _kind : <Self :: Arch as Arch >:: BreakpointKind ,
523
+ ) -> TargetResult < bool , Self > {
524
+ log:: debug!( "Add sw breakpoint at address {:X}" , addr) ;
525
+ let addr = self . translate_gva ( addr) . map_err ( TargetError :: Fatal ) ?;
526
+
527
+ if self . sw_breakpoints . contains_key ( & addr) {
528
+ return Ok ( true ) ;
529
+ }
530
+
531
+ let mut save_data = [ 0u8 ; SW_BP_SIZE ] ;
532
+ self . read_addrs ( addr, & mut save_data) ?;
533
+ self . write_addrs ( addr, & SW_BP ) ?;
534
+
535
+ self . sw_breakpoints . insert ( addr, save_data) ;
536
+
537
+ Ok ( true )
538
+ }
539
+
540
+ /// Removes a software breakpoint by restoring the saved data at the corresponding
541
+ /// address
542
+ fn remove_sw_breakpoint (
543
+ & mut self ,
544
+ addr : <Self :: Arch as Arch >:: Usize ,
545
+ _kind : <Self :: Arch as Arch >:: BreakpointKind ,
546
+ ) -> TargetResult < bool , Self > {
547
+ log:: debug!( "Remove sw breakpoint at address {:X}" , addr) ;
548
+
549
+ let addr = self . translate_gva ( addr) . map_err ( TargetError :: Fatal ) ?;
550
+
551
+ if self . sw_breakpoints . contains_key ( & addr) {
552
+ let save_data = self
553
+ . sw_breakpoints
554
+ . remove ( & addr)
555
+ . expect ( "Expected the hashmap to contain the address" ) ;
556
+ self . write_addrs ( addr, & save_data) ?;
557
+
558
+ Ok ( true )
559
+ } else {
560
+ Ok ( false )
561
+ }
499
562
}
500
563
}
501
564
@@ -518,4 +581,4 @@ impl SingleThreadSingleStep for HyperlightKvmSandboxTarget {
518
581
self . set_single_step ( true ) ?;
519
582
self . resume_vcpu ( )
520
583
}
521
- }
584
+ }
0 commit comments