@@ -18,10 +18,6 @@ use gdbstub::target::ext::breakpoints::{
18
18
} ;
19
19
use gdbstub:: target:: ext:: thread_extra_info:: { ThreadExtraInfo , ThreadExtraInfoOps } ;
20
20
use gdbstub:: target:: { Target , TargetError , TargetResult } ;
21
- #[ cfg( target_arch = "aarch64" ) ]
22
- use gdbstub_arch:: aarch64:: reg:: AArch64CoreRegs as CoreRegs ;
23
- #[ cfg( target_arch = "aarch64" ) ]
24
- use gdbstub_arch:: aarch64:: AArch64 as GdbArch ;
25
21
#[ cfg( target_arch = "x86_64" ) ]
26
22
use gdbstub_arch:: x86:: reg:: X86_64CoreRegs as CoreRegs ;
27
23
#[ cfg( target_arch = "x86_64" ) ]
@@ -30,7 +26,8 @@ use kvm_bindings::kvm_regs;
30
26
use vm_memory:: { Bytes , GuestAddress } ;
31
27
32
28
use crate :: logger:: { error, info} ;
33
- use crate :: { FcExitCode , VcpuEvent , VcpuHandle , VcpuResponse , Vmm } ;
29
+ use crate :: vstate:: vcpu:: VcpuError ;
30
+ use crate :: { arch, FcExitCode , VcpuEvent , VcpuHandle , VcpuResponse , Vmm } ;
34
31
35
32
const X86_SW_BP_OP : u8 = 0xCC ;
36
33
@@ -51,6 +48,12 @@ pub enum Error {
51
48
VCPURequestError ,
52
49
/// No currently paused Vcpu error
53
50
NoPausedVCpu ,
51
+ /// Error when setting vcpu debug flags
52
+ VcpuKvmError ,
53
+ /// Server socket Error
54
+ ServerSocketError ,
55
+ /// Error with creating GDB thread
56
+ GdbThreadError ,
54
57
}
55
58
56
59
impl < E > From < Error > for TargetError < E > {
@@ -72,7 +75,7 @@ pub struct FirecrackerTarget {
72
75
hw_breakpoints : Vec < GuestAddress > ,
73
76
sw_breakpoints : HashMap < <GdbArch as Arch >:: Usize , [ u8 ; 1 ] > ,
74
77
75
- vcpu_state : HashMap < Tid , VCpuState > ,
78
+ vcpu_state : Vec < VCpuState > ,
76
79
77
80
paused_vcpu : Option < Tid > ,
78
81
}
@@ -98,22 +101,19 @@ impl FirecrackerTarget {
98
101
/// will handle requests from GDB and perform the appropriate actions, while also updating GDB
99
102
/// with the state of the VMM / VCPU's as we hit debug events
100
103
pub fn new ( vmm : Arc < Mutex < Vmm > > , gdb_event : Receiver < usize > , entry_addr : GuestAddress ) -> Self {
101
- let mut vcpu_state = HashMap :: new ( ) ;
102
104
let cpu_count = {
103
105
vmm. lock ( )
104
106
. expect ( "Exception unlocking vmm" )
105
107
. vcpus_handles
106
108
. len ( )
107
109
} ;
108
110
109
- for cpu_id in 0 ..cpu_count {
110
- let new_state = VCpuState {
111
+ let vcpu_state = ( 0 ..cpu_count)
112
+ . map ( |_| VCpuState {
111
113
paused : false ,
112
114
single_step : false ,
113
- } ;
114
-
115
- vcpu_state. insert ( cpuid_to_tid ( cpu_id) , new_state) ;
116
- }
115
+ } )
116
+ . collect ( ) ;
117
117
118
118
Self {
119
119
vmm,
@@ -138,24 +138,19 @@ impl FirecrackerTarget {
138
138
/// This is used to notify the target that the provided Tid
139
139
/// is in a paused state
140
140
pub fn notify_paused_vcpu ( & mut self , tid : Tid ) {
141
- let found = match self . vcpu_state . get_mut ( & tid) {
142
- Some ( res) => res,
143
- None => {
144
- info ! ( "TID {tid} was not known." ) ;
145
- return ;
146
- }
147
- } ;
148
-
141
+ let found = & mut self . vcpu_state [ tid_to_cpuid ( tid) ] ;
149
142
found. paused = true ;
143
+
150
144
self . paused_vcpu = Some ( tid) ;
151
145
}
152
146
153
147
fn resume_execution ( & mut self ) -> Result < ( ) , Error > {
154
148
let to_resume: Vec < Tid > = self
155
149
. vcpu_state
156
150
. iter ( )
157
- . filter_map ( |( tid, state) | match state. paused {
158
- true => Some ( * tid) ,
151
+ . enumerate ( )
152
+ . filter_map ( |( cpu_id, state) | match state. paused {
153
+ true => Some ( cpuid_to_tid ( cpu_id) ) ,
159
154
false => None ,
160
155
} )
161
156
. collect ( ) ;
@@ -165,7 +160,7 @@ impl FirecrackerTarget {
165
160
self . request_resume ( tid) ?;
166
161
}
167
162
168
- self . vcpu_state . iter_mut ( ) . for_each ( |( _ , state) | {
163
+ self . vcpu_state . iter_mut ( ) . for_each ( |state| {
169
164
state. paused = false ;
170
165
} ) ;
171
166
@@ -179,7 +174,7 @@ impl FirecrackerTarget {
179
174
}
180
175
181
176
fn reset_all_states ( & mut self ) {
182
- for ( _ , value) in self . vcpu_state . iter_mut ( ) {
177
+ for value in self . vcpu_state . iter_mut ( ) {
183
178
Self :: reset_vcpu_state ( value) ;
184
179
}
185
180
}
@@ -194,13 +189,7 @@ impl FirecrackerTarget {
194
189
195
190
/// This method can be used to manually pause the requested vcpu
196
191
pub fn request_pause ( & mut self , tid : Tid ) -> Result < ( ) , Error > {
197
- let vcpu_state = match self . vcpu_state . get_mut ( & tid) {
198
- Some ( res) => res,
199
- None => {
200
- info ! ( "Attempted to pause a vcpu we have no state for." ) ;
201
- return Err ( Error :: VCPURequestError ) ;
202
- }
203
- } ;
192
+ let vcpu_state = & mut self . vcpu_state [ tid_to_cpuid ( tid) ] ;
204
193
205
194
if vcpu_state. paused {
206
195
info ! ( "Attempted to pause a vcpu already paused." ) ;
@@ -268,13 +257,7 @@ impl FirecrackerTarget {
268
257
/// Used to request the specified core to resume execution. The function
269
258
/// will return early if the vcpu is already paused and not currently running
270
259
pub fn request_resume ( & mut self , tid : Tid ) -> Result < ( ) , Error > {
271
- let vcpu_state = match self . vcpu_state . get_mut ( & tid) {
272
- Some ( res) => res,
273
- None => {
274
- error ! ( "Attempted to resume a vcpu we have no state for." ) ;
275
- return Err ( Error :: VCPURequestError ) ;
276
- }
277
- } ;
260
+ let vcpu_state = & mut self . vcpu_state [ tid_to_cpuid ( tid) ] ;
278
261
279
262
if !vcpu_state. paused {
280
263
info ! ( "Attempted to resume a vcpu already running." ) ;
@@ -288,6 +271,7 @@ impl FirecrackerTarget {
288
271
cpu_handle
289
272
. send_event ( VcpuEvent :: Resume )
290
273
. expect ( "Error sending message to vcpu" ) ;
274
+
291
275
let response = cpu_handle
292
276
. response_receiver ( )
293
277
. recv ( )
@@ -305,13 +289,7 @@ impl FirecrackerTarget {
305
289
let cpu_handle =
306
290
& self . vmm . lock ( ) . expect ( "error unlocking vmm" ) . vcpus_handles [ tid_to_cpuid ( tid) ] ;
307
291
308
- let vcpu_state = match self . vcpu_state . get ( & tid) {
309
- Some ( res) => res,
310
- None => {
311
- error ! ( "Attempted to write kvm debug to a vcpu we have no state for." ) ;
312
- return Err ( Error :: VCPURequestError ) ;
313
- }
314
- } ;
292
+ let vcpu_state = & self . vcpu_state [ tid_to_cpuid ( tid) ] ;
315
293
316
294
cpu_handle
317
295
. send_event ( VcpuEvent :: SetKvmDebug (
@@ -325,6 +303,7 @@ impl FirecrackerTarget {
325
303
error ! ( "Response resume : {message}" ) ;
326
304
Err ( Error :: VCPURequestError )
327
305
}
306
+ Ok ( VcpuResponse :: Error ( VcpuError :: GdbRequest ( e) ) ) => Err ( e) ,
328
307
Err ( _) => Err ( Error :: VCPURequestError ) ,
329
308
_ => Ok ( ( ) ) ,
330
309
}
@@ -340,7 +319,10 @@ impl FirecrackerTarget {
340
319
. expect ( "Error recieving message from vcpu" ) ;
341
320
342
321
if let VcpuResponse :: GvaTranslation ( response) = response {
343
- return Ok ( response) ;
322
+ return match response {
323
+ Some ( res) => Ok ( res. into ( ) ) ,
324
+ None => Err ( Error :: VCPURequestError ) ,
325
+ } ;
344
326
}
345
327
346
328
if let VcpuResponse :: NotAllowed ( message) = response {
@@ -364,6 +346,7 @@ impl FirecrackerTarget {
364
346
error ! ( "Response resume : {message}" ) ;
365
347
Err ( Error :: VCPURequestError )
366
348
}
349
+ Ok ( VcpuResponse :: Error ( VcpuError :: GdbRequest ( e) ) ) => Err ( e) ,
367
350
Err ( _) => Err ( Error :: VCPURequestError ) ,
368
351
_ => Ok ( ( ) ) ,
369
352
}
@@ -387,13 +370,7 @@ impl FirecrackerTarget {
387
370
}
388
371
389
372
let cpu_regs = self . get_regs ( tid) ;
390
-
391
- let vcpu_state = match self . vcpu_state . get ( & tid) {
392
- Some ( res) => res,
393
- None => {
394
- return None ;
395
- }
396
- } ;
373
+ let vcpu_state = & mut self . vcpu_state [ tid_to_cpuid ( tid) ] ;
397
374
398
375
if vcpu_state. single_step {
399
376
return Some ( MultiThreadStopReason :: SignalWithThread {
@@ -539,7 +516,7 @@ impl MultiThreadBase for FirecrackerTarget {
539
516
}
540
517
} ;
541
518
542
- let psize = 4096 ;
519
+ let psize = arch :: PAGE_SIZE ;
543
520
let read_len = std:: cmp:: min ( len - total_read, psize - ( paddr & ( psize - 1 ) ) ) ;
544
521
545
522
if memory
@@ -629,13 +606,7 @@ impl MultiThreadResume for FirecrackerTarget {
629
606
tid : Tid ,
630
607
_signal : Option < Signal > ,
631
608
) -> Result < ( ) , Self :: Error > {
632
- let vcpu_state = match self . vcpu_state . get_mut ( & tid) {
633
- Some ( res) => res,
634
- None => {
635
- error ! ( "Attempted to set action on a vcpu we have no state for." ) ;
636
- return Err ( Error :: VCPURequestError ) ;
637
- }
638
- } ;
609
+ let vcpu_state = & mut self . vcpu_state [ tid_to_cpuid ( tid) ] ;
639
610
vcpu_state. single_step = false ;
640
611
641
612
Ok ( ( ) )
@@ -663,13 +634,7 @@ impl MultiThreadSingleStep for FirecrackerTarget {
663
634
tid : Tid ,
664
635
_signal : Option < Signal > ,
665
636
) -> Result < ( ) , Self :: Error > {
666
- let vcpu_state = match self . vcpu_state . get_mut ( & tid) {
667
- Some ( res) => res,
668
- None => {
669
- info ! ( "Attempted to set action on a vcpu we have no state for." ) ;
670
- return Ok ( ( ) ) ;
671
- }
672
- } ;
637
+ let vcpu_state = & mut self . vcpu_state [ tid_to_cpuid ( tid) ] ;
673
638
vcpu_state. single_step = true ;
674
639
675
640
Ok ( ( ) )
0 commit comments