@@ -39,38 +39,47 @@ use crate::utils::u64_to_usize;
3939use crate :: vstate:: vcpu:: VcpuSendEventError ;
4040use crate :: { FcExitCode , VcpuEvent , VcpuResponse , Vmm } ;
4141
42- #[ derive( Debug ) ]
42+ #[ derive( Debug , Clone , Copy ) ]
4343/// Stores the current state of a Vcpu with a copy of the Vcpu file descriptor
4444struct VcpuState {
4545 single_step : bool ,
4646 paused : bool ,
47- vcpu_fd : VcpuFd ,
47+ // vcpu_fd: VcpuFd,
4848}
4949
50- impl VcpuState {
51- /// Constructs a new instance of a VcpuState from a VcpuFd
52- fn from_vcpu_fd ( vcpu_fd : VcpuFd ) -> Self {
50+ impl Default for VcpuState {
51+ fn default ( ) -> Self {
5352 Self {
5453 single_step : false ,
5554 paused : false ,
56- vcpu_fd,
5755 }
5856 }
57+ }
58+
59+ impl VcpuState {
60+ /// Constructs a new instance of a VcpuState from a VcpuFd
61+ // fn from_vcpu_fd(vcpu_fd: VcpuFd) -> Self {
62+ // Self {
63+ // single_step: false,
64+ // paused: false,
65+ // vcpu_fd,
66+ // }
67+ // }
5968
6069 /// Disables single stepping on the Vcpu state
6170 fn reset_vcpu_state ( & mut self ) {
6271 self . single_step = false ;
6372 }
6473
65- /// Updates the kvm debug flags set against the Vcpu with a check
66- fn update_kvm_debug ( & self , hw_breakpoints : & [ GuestAddress ] ) -> Result < ( ) , GdbTargetError > {
67- if !self . paused {
68- info ! ( "Attempted to update kvm debug on a non paused Vcpu" ) ;
69- return Ok ( ( ) ) ;
70- }
71-
72- arch:: vcpu_set_debug ( & self . vcpu_fd , hw_breakpoints, self . single_step )
73- }
74+ // / / Updates the kvm debug flags set against the Vcpu with a check
75+ // fn update_kvm_debug(&self, hw_breakpoints: &[GuestAddress]) -> Result<(), GdbTargetError> {
76+ // if !self.paused {
77+ // info!("Attempted to update kvm debug on a non paused Vcpu");
78+ // return Ok(());
79+ // }
80+ //
81+ // arch::vcpu_set_debug(&self.vcpu_fd, hw_breakpoints, self.single_step)
82+ // }
7483}
7584
7685/// Errors from interactions between GDB and the VMM
@@ -185,7 +194,7 @@ impl FirecrackerTarget {
185194 gdb_event : Receiver < usize > ,
186195 entry_addr : GuestAddress ,
187196 ) -> Self {
188- let mut vcpu_state: Vec < _ > = vcpu_fds . into_iter ( ) . map ( VcpuState :: from_vcpu_fd ) . collect ( ) ;
197+ let mut vcpu_state = vec ! [ VcpuState :: default ( ) ; vmm . lock ( ) . unwrap ( ) . vcpus_handles . len ( ) ] ;
189198 // By default vcpu 1 will be paused at the entry point
190199 vcpu_state[ 0 ] . paused = true ;
191200
@@ -202,16 +211,34 @@ impl FirecrackerTarget {
202211 }
203212 }
204213
214+ fn update_vcpu_kvm_debug (
215+ & self ,
216+ vcpu_idx : usize ,
217+ hw_breakpoints : & [ GuestAddress ] ,
218+ ) -> Result < ( ) , GdbTargetError > {
219+ let state = & self . vcpu_state [ vcpu_idx] ;
220+ if !state. paused {
221+ info ! ( "Attempted to update kvm debug on a non paused Vcpu" ) ;
222+ return Ok ( ( ) ) ;
223+ }
224+
225+ let vcpu_fd = & self . vmm . lock ( ) . unwrap ( ) . vcpus_handles [ vcpu_idx] . vcpu_fd ;
226+ arch:: vcpu_set_debug ( vcpu_fd, hw_breakpoints, state. single_step )
227+ }
228+
205229 /// Retrieves the currently paused Vcpu id returns an error if there is no currently paused Vcpu
206230 fn get_paused_vcpu_id ( & self ) -> Result < Tid , GdbTargetError > {
207231 self . paused_vcpu . ok_or ( GdbTargetError :: NoPausedVcpu )
208232 }
209233
210- /// Retrieves the currently paused Vcpu state returns an error if there is no currently paused
211- /// Vcpu
212- fn get_paused_vcpu ( & self ) -> Result < & VcpuState , GdbTargetError > {
213- let vcpu_index = tid_to_vcpuid ( self . get_paused_vcpu_id ( ) ?) ;
214- Ok ( & self . vcpu_state [ vcpu_index] )
234+ fn get_paused_vcpu_idx ( & self ) -> Result < usize , GdbTargetError > {
235+ Ok ( tid_to_vcpuid ( self . get_paused_vcpu_id ( ) ?) )
236+ }
237+
238+ fn get_vcpu_fd ( & self , vcpu_idx : usize ) -> Result < & VcpuFd , GdbTargetError > {
239+ // let vcpu_index = tid_to_vcpuid(self.get_paused_vcpu_id()?);
240+ // Ok(&self.vcpu_state[vcpu_index])
241+ Ok ( & self . vmm . lock ( ) . unwrap ( ) . vcpus_handles [ vcpu_idx] . vcpu_fd )
215242 }
216243
217244 /// Updates state to reference the currently paused Vcpu and store that the cpu is currently
@@ -224,9 +251,9 @@ impl FirecrackerTarget {
224251 /// Resumes execution of all paused Vcpus, update them with current kvm debug info
225252 /// and resumes
226253 fn resume_all_vcpus ( & mut self ) -> Result < ( ) , GdbTargetError > {
227- self . vcpu_state
228- . iter ( )
229- . try_for_each ( |state| state . update_kvm_debug ( & self . hw_breakpoints ) ) ? ;
254+ for idx in 0 .. self . vcpu_state . len ( ) {
255+ self . update_vcpu_kvm_debug ( idx , & self . hw_breakpoints ) ? ;
256+ }
230257
231258 for cpu_id in 0 ..self . vcpu_state . len ( ) {
232259 let tid = vcpuid_to_tid ( cpu_id) ?;
@@ -274,8 +301,8 @@ impl FirecrackerTarget {
274301
275302 /// A helper function to allow the event loop to inject this breakpoint back into the Vcpu
276303 pub fn inject_bp_to_guest ( & mut self , tid : Tid ) -> Result < ( ) , GdbTargetError > {
277- let vcpu_state = & mut self . vcpu_state [ tid_to_vcpuid ( tid) ] ;
278- arch:: vcpu_inject_bp ( & vcpu_state . vcpu_fd , & self . hw_breakpoints , false )
304+ let vcpu_fd = self . get_vcpu_fd ( tid_to_vcpuid ( tid) ) ? ;
305+ arch:: vcpu_inject_bp ( vcpu_fd, & self . hw_breakpoints , false )
279306 }
280307
281308 /// Resumes the Vcpu, will return early if the Vcpu is already running
@@ -307,21 +334,23 @@ impl FirecrackerTarget {
307334 & self ,
308335 tid : Tid ,
309336 ) -> Result < Option < BaseStopReason < Tid , u64 > > , GdbTargetError > {
310- let vcpu_state = & self . vcpu_state [ tid_to_vcpuid ( tid) ] ;
337+ let vcpu_idx = tid_to_vcpuid ( tid) ;
338+ let vcpu_state = & self . vcpu_state [ vcpu_idx] ;
311339 if vcpu_state. single_step {
312340 return Ok ( Some ( MultiThreadStopReason :: SignalWithThread {
313341 tid,
314342 signal : Signal :: SIGTRAP ,
315343 } ) ) ;
316344 }
317345
318- let Ok ( ip) = arch:: get_instruction_pointer ( & vcpu_state. vcpu_fd ) else {
346+ let vcpu_fd = self . get_vcpu_fd ( vcpu_idx) ?;
347+ let Ok ( ip) = arch:: get_instruction_pointer ( vcpu_fd) else {
319348 // If we error here we return an arbitrary Software Breakpoint, GDB will handle
320349 // this gracefully
321350 return Ok ( Some ( MultiThreadStopReason :: SwBreak ( tid) ) ) ;
322351 } ;
323352
324- let gpa = arch:: translate_gva ( & vcpu_state . vcpu_fd , ip, & self . vmm . lock ( ) . unwrap ( ) ) ?;
353+ let gpa = arch:: translate_gva ( vcpu_fd, ip, & self . vmm . lock ( ) . unwrap ( ) ) ?;
325354 if self . sw_breakpoints . contains_key ( & gpa) {
326355 return Ok ( Some ( MultiThreadStopReason :: SwBreak ( tid) ) ) ;
327356 }
@@ -364,14 +393,18 @@ impl Target for FirecrackerTarget {
364393impl MultiThreadBase for FirecrackerTarget {
365394 /// Reads the registers for the Vcpu
366395 fn read_registers ( & mut self , regs : & mut CoreRegs , tid : Tid ) -> TargetResult < ( ) , Self > {
367- arch:: read_registers ( & self . vcpu_state [ tid_to_vcpuid ( tid) ] . vcpu_fd , regs) ?;
396+ let vcpu_idx = tid_to_vcpuid ( tid) ;
397+ let vcpu_fd = self . get_vcpu_fd ( vcpu_idx) ?;
398+ arch:: read_registers ( vcpu_fd, regs) ?;
368399
369400 Ok ( ( ) )
370401 }
371402
372403 /// Writes to the registers for the Vcpu
373404 fn write_registers ( & mut self , regs : & CoreRegs , tid : Tid ) -> TargetResult < ( ) , Self > {
374- arch:: write_registers ( & self . vcpu_state [ tid_to_vcpuid ( tid) ] . vcpu_fd , regs) ?;
405+ let vcpu_idx = tid_to_vcpuid ( tid) ;
406+ let vcpu_fd = self . get_vcpu_fd ( vcpu_idx) ?;
407+ arch:: write_registers ( vcpu_fd, regs) ?;
375408
376409 Ok ( ( ) )
377410 }
@@ -384,12 +417,14 @@ impl MultiThreadBase for FirecrackerTarget {
384417 tid : Tid ,
385418 ) -> TargetResult < usize , Self > {
386419 let data_len = data. len ( ) ;
387- let vcpu_state = & self . vcpu_state [ tid_to_vcpuid ( tid) ] ;
420+ let vcpu_idx = tid_to_vcpuid ( tid) ;
421+ let vcpu_state = & self . vcpu_state [ vcpu_idx] ;
422+ let vcpu_fd = self . get_vcpu_fd ( vcpu_idx) ?;
388423
389424 let vmm = & self . vmm . lock ( ) . expect ( "Error locking vmm in read addr" ) ;
390425
391426 while !data. is_empty ( ) {
392- let gpa = arch:: translate_gva ( & vcpu_state . vcpu_fd , gva, & vmm) . map_err ( |e| {
427+ let gpa = arch:: translate_gva ( vcpu_fd, gva, & vmm) . map_err ( |e| {
393428 error ! ( "Error {e:?} translating gva on read address: {gva:#X}" ) ;
394429 } ) ?;
395430
@@ -420,11 +455,13 @@ impl MultiThreadBase for FirecrackerTarget {
420455 mut data : & [ u8 ] ,
421456 tid : Tid ,
422457 ) -> TargetResult < ( ) , Self > {
423- let vcpu_state = & self . vcpu_state [ tid_to_vcpuid ( tid) ] ;
458+ let vcpu_idx = tid_to_vcpuid ( tid) ;
459+ let vcpu_state = & self . vcpu_state [ vcpu_idx] ;
460+ let vcpu_fd = self . get_vcpu_fd ( vcpu_idx) ?;
424461 let vmm = & self . vmm . lock ( ) . expect ( "Error locking vmm in write addr" ) ;
425462
426463 while !data. is_empty ( ) {
427- let gpa = arch:: translate_gva ( & vcpu_state . vcpu_fd , gva, & vmm) . map_err ( |e| {
464+ let gpa = arch:: translate_gva ( vcpu_fd, gva, & vmm) . map_err ( |e| {
428465 error ! ( "Error {e:?} translating gva on read address: {gva:#X}" ) ;
429466 } ) ?;
430467
@@ -546,8 +583,8 @@ impl HwBreakpoint for FirecrackerTarget {
546583 return Ok ( false ) ;
547584 }
548585
549- let state = self . get_paused_vcpu ( ) ?;
550- state . update_kvm_debug ( & self . hw_breakpoints ) ?;
586+ let vcpu_idx = self . get_paused_vcpu_idx ( ) ?;
587+ self . update_vcpu_kvm_debug ( vcpu_idx , & self . hw_breakpoints ) ?;
551588
552589 Ok ( true )
553590 }
@@ -563,8 +600,8 @@ impl HwBreakpoint for FirecrackerTarget {
563600 Some ( pos) => self . hw_breakpoints . remove ( pos) ,
564601 } ;
565602
566- let state = self . get_paused_vcpu ( ) ?;
567- state . update_kvm_debug ( & self . hw_breakpoints ) ?;
603+ let vcpu_idx = self . get_paused_vcpu_idx ( ) ?;
604+ self . update_vcpu_kvm_debug ( vcpu_idx , & self . hw_breakpoints ) ?;
568605
569606 Ok ( true )
570607 }
@@ -580,11 +617,8 @@ impl SwBreakpoint for FirecrackerTarget {
580617 addr : <Self :: Arch as Arch >:: Usize ,
581618 _kind : <Self :: Arch as Arch >:: BreakpointKind ,
582619 ) -> TargetResult < bool , Self > {
583- let gpa = arch:: translate_gva (
584- & self . get_paused_vcpu ( ) ?. vcpu_fd ,
585- addr,
586- & self . vmm . lock ( ) . unwrap ( ) ,
587- ) ?;
620+ let vcpu_fd = self . get_vcpu_fd ( self . get_paused_vcpu_idx ( ) ?) ?;
621+ let gpa = arch:: translate_gva ( vcpu_fd, addr, & self . vmm . lock ( ) . unwrap ( ) ) ?;
588622
589623 if self . sw_breakpoints . contains_key ( & gpa) {
590624 return Ok ( true ) ;
@@ -608,11 +642,8 @@ impl SwBreakpoint for FirecrackerTarget {
608642 addr : <Self :: Arch as Arch >:: Usize ,
609643 _kind : <Self :: Arch as Arch >:: BreakpointKind ,
610644 ) -> TargetResult < bool , Self > {
611- let gpa = arch:: translate_gva (
612- & self . get_paused_vcpu ( ) ?. vcpu_fd ,
613- addr,
614- & self . vmm . lock ( ) . unwrap ( ) ,
615- ) ?;
645+ let vcpu_fd = self . get_vcpu_fd ( self . get_paused_vcpu_idx ( ) ?) ?;
646+ let gpa = arch:: translate_gva ( vcpu_fd, addr, & self . vmm . lock ( ) . unwrap ( ) ) ?;
616647
617648 if let Some ( removed) = self . sw_breakpoints . remove ( & gpa) {
618649 self . write_addrs ( addr, & removed, self . get_paused_vcpu_id ( ) ?) ?;
0 commit comments