@@ -7,6 +7,9 @@ use gdbstub::target::ext::base::singlethread::{
77 SingleThreadBase ,
88} ;
99use gdbstub:: target:: ext:: base:: BaseOps ;
10+ use gdbstub:: target:: ext:: breakpoints:: {
11+ Breakpoints , BreakpointsOps , HwBreakpoint , HwBreakpointOps ,
12+ } ;
1013use gdbstub:: target:: ext:: section_offsets:: { Offsets , SectionOffsets } ;
1114use gdbstub:: target:: { Target , TargetError , TargetResult } ;
1215use gdbstub_arch:: x86:: reg:: X86_64CoreRegs ;
@@ -82,7 +85,6 @@ impl KvmDebug {
8285 }
8386}
8487
85- #[ allow( dead_code) ]
8688/// Gdbstub target used by the gdbstub crate to provide GDB protocol implementation
8789pub struct HyperlightKvmSandboxTarget {
8890 /// Memory manager that grants access to guest's memory
@@ -98,6 +100,9 @@ pub struct HyperlightKvmSandboxTarget {
98100 /// vCPU paused state
99101 paused : bool ,
100102
103+ /// Array of addresses for HW breakpoints
104+ hw_breakpoints : Vec < u64 > ,
105+
101106 /// Hypervisor communication channels
102107 hyp_conn : GdbConnection ,
103108}
@@ -118,6 +123,9 @@ impl HyperlightKvmSandboxTarget {
118123 entrypoint,
119124
120125 paused : false ,
126+
127+ hw_breakpoints : vec ! [ ] ,
128+
121129 hyp_conn,
122130 }
123131 }
@@ -138,6 +146,10 @@ impl HyperlightKvmSandboxTarget {
138146 pub fn get_stop_reason ( & self ) -> Result < Option < BaseStopReason < ( ) , u64 > > , GdbTargetError > {
139147 let ip = self . get_instruction_pointer ( ) ?;
140148
149+ if self . hw_breakpoints . contains ( & ip) {
150+ return Ok ( Some ( SingleThreadStopReason :: HwBreak ( ( ) ) ) ) ;
151+ }
152+
141153 if ip == self . entrypoint {
142154 return Ok ( Some ( SingleThreadStopReason :: HwBreak ( ( ) ) ) ) ;
143155 }
@@ -173,6 +185,44 @@ impl HyperlightKvmSandboxTarget {
173185 self . paused = true ;
174186 }
175187
188+ /// Add new breakpoint at provided address if there is enough space
189+ fn add_breakpoint ( & mut self , addr : u64 ) -> Result < bool , GdbTargetError > {
190+ log:: debug!( "Add breakpoint at address {:X}" , addr) ;
191+ if self . hw_breakpoints . contains ( & addr)
192+ || self . hw_breakpoints . len ( ) >= KvmDebug :: MAX_NO_OF_HW_BP
193+ {
194+ Ok ( false )
195+ } else {
196+ self . hw_breakpoints . push ( addr) ;
197+ self . debug . set_breakpoints (
198+ & self . vcpu_fd . lock ( ) . unwrap ( ) ,
199+ & self . hw_breakpoints ,
200+ false ,
201+ ) ?;
202+
203+ Ok ( true )
204+ }
205+ }
206+
207+ /// Removes breakpoint at the provided address if exists
208+ fn remove_breakpoint ( & mut self , addr : u64 ) -> Result < bool , GdbTargetError > {
209+ log:: debug!( "Remove breakpoint at address {:X}" , addr) ;
210+ if self . hw_breakpoints . contains ( & addr) {
211+ let index = self . hw_breakpoints . iter ( ) . position ( |a| * a == addr) . unwrap ( ) ;
212+ self . hw_breakpoints . copy_within ( index + 1 .., index) ;
213+ self . hw_breakpoints . pop ( ) ;
214+ self . debug . set_breakpoints (
215+ & self . vcpu_fd . lock ( ) . unwrap ( ) ,
216+ & self . hw_breakpoints ,
217+ false ,
218+ ) ?;
219+
220+ Ok ( true )
221+ } else {
222+ Ok ( false )
223+ }
224+ }
225+
176226 fn read_regs ( & self , regs : & mut X86_64CoreRegs ) -> Result < ( ) , GdbTargetError > {
177227 log:: debug!( "Read registers" ) ;
178228 let vcpu_regs = self
@@ -257,6 +307,15 @@ impl Target for HyperlightKvmSandboxTarget {
257307 type Arch = GdbTargetArch ;
258308 type Error = GdbTargetError ;
259309
310+ #[ inline( always) ]
311+ fn guard_rail_implicit_sw_breakpoints ( & self ) -> bool {
312+ true
313+ }
314+
315+ fn support_breakpoints ( & mut self ) -> Option < BreakpointsOps < Self > > {
316+ Some ( self )
317+ }
318+
260319 #[ inline( always) ]
261320 fn base_ops ( & mut self ) -> BaseOps < Self :: Arch , Self :: Error > {
262321 BaseOps :: SingleThread ( self )
@@ -353,4 +412,28 @@ impl SectionOffsets for HyperlightKvmSandboxTarget {
353412 data_seg : None ,
354413 } )
355414 }
415+ }
416+
417+ impl Breakpoints for HyperlightKvmSandboxTarget {
418+ fn support_hw_breakpoint ( & mut self ) -> Option < HwBreakpointOps < Self > > {
419+ Some ( self )
420+ }
421+ }
422+
423+ impl HwBreakpoint for HyperlightKvmSandboxTarget {
424+ fn add_hw_breakpoint (
425+ & mut self ,
426+ addr : <Self :: Arch as Arch >:: Usize ,
427+ _kind : <Self :: Arch as Arch >:: BreakpointKind ,
428+ ) -> TargetResult < bool , Self > {
429+ self . add_breakpoint ( addr) . map_err ( TargetError :: Fatal )
430+ }
431+
432+ fn remove_hw_breakpoint (
433+ & mut self ,
434+ addr : <Self :: Arch as Arch >:: Usize ,
435+ _kind : <Self :: Arch as Arch >:: BreakpointKind ,
436+ ) -> TargetResult < bool , Self > {
437+ self . remove_breakpoint ( addr) . map_err ( TargetError :: Fatal )
438+ }
356439}
0 commit comments