@@ -23,7 +23,7 @@ mod x86_64;
2323use std:: collections:: HashMap ;
2424use std:: ffi:: CStr ;
2525use std:: sync:: Arc ;
26- use std:: sync:: mpsc:: { Receiver , Sender } ;
26+ use std:: sync:: mpsc:: Sender ;
2727use std:: thread:: JoinHandle ;
2828
2929use libc:: { MAP_PRIVATE , MAP_SHARED } ;
@@ -97,6 +97,8 @@ pub enum Error {
9797 NotifyVmm ,
9898 #[ snafu( display( "Another VCPU thread has signaled failure" ) ) ]
9999 PeerFailure ,
100+ #[ snafu( display( "Unexpected state: {state:?}, want {want:?}" ) ) ]
101+ UnexpectedState { state : BoardState , want : BoardState } ,
100102}
101103
102104type Result < T , E = Error > = std:: result:: Result < T , E > ;
@@ -157,7 +159,7 @@ impl CpuConfig {
157159}
158160
159161#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
160- enum BoardState {
162+ pub enum BoardState {
161163 Created ,
162164 Running ,
163165 Shutdown ,
@@ -189,8 +191,8 @@ impl BoardConfig {
189191 }
190192}
191193
192- type VcpuGuard < ' a > = RwLockReadGuard < ' a , Vec < ( JoinHandle < Result < ( ) > > , Sender < ( ) > ) > > ;
193- type VcpuHandle = ( JoinHandle < Result < ( ) > > , Sender < ( ) > ) ;
194+ type VcpuGuard < ' a > = RwLockReadGuard < ' a , Vec < VcpuHandle > > ;
195+ type VcpuHandle = JoinHandle < Result < ( ) > > ;
194196
195197pub struct Board < V >
196198where
@@ -249,12 +251,17 @@ where
249251 }
250252
251253 pub fn boot ( & self ) -> Result < ( ) > {
252- let vcpus = self . vcpus . read ( ) ;
253254 let mut mp_sync = self . mp_sync . lock ( ) ;
254- mp_sync. state = BoardState :: Running ;
255- for ( _, boot_tx) in vcpus. iter ( ) {
256- boot_tx. send ( ( ) ) . unwrap ( ) ;
255+ if mp_sync. state == BoardState :: Created {
256+ mp_sync. state = BoardState :: Running ;
257+ } else {
258+ return error:: UnexpectedState {
259+ state : mp_sync. state ,
260+ want : BoardState :: Created ,
261+ }
262+ . fail ( ) ;
257263 }
264+ self . cond_var . notify_all ( ) ;
258265 Ok ( ( ) )
259266 }
260267
@@ -371,17 +378,28 @@ where
371378 Ok ( ( ) )
372379 }
373380
374- fn run_vcpu_inner (
375- & self ,
376- index : u16 ,
377- vcpu : & mut V :: Vcpu ,
378- boot_rx : & Receiver < ( ) > ,
379- ) -> Result < ( ) , Error > {
380- self . init_vcpu ( index, vcpu) ?;
381- boot_rx. recv ( ) . unwrap ( ) ;
382- if self . mp_sync . lock ( ) . state != BoardState :: Running {
381+ fn notify_vmm ( & self , index : u16 , event_tx : & Sender < u16 > ) -> Result < ( ) > {
382+ if event_tx. send ( index) . is_err ( ) {
383+ error:: NotifyVmm . fail ( )
384+ } else {
385+ Ok ( ( ) )
386+ }
387+ }
388+
389+ fn run_vcpu_inner ( & self , index : u16 , event_tx : & Sender < u16 > ) -> Result < ( ) , Error > {
390+ let mut vcpu = self . create_vcpu ( index) ?;
391+ self . notify_vmm ( index, event_tx) ?;
392+ self . init_vcpu ( index, & mut vcpu) ?;
393+
394+ let mut mp_sync = self . mp_sync . lock ( ) ;
395+ while mp_sync. state == BoardState :: Created {
396+ self . cond_var . wait ( & mut mp_sync) ;
397+ }
398+ if mp_sync. state != BoardState :: Running {
383399 return Ok ( ( ) ) ;
384400 }
401+ drop ( mp_sync) ;
402+
385403 loop {
386404 let vcpus = self . vcpus . read ( ) ;
387405 self . coco_init ( index) ?;
@@ -396,15 +414,15 @@ where
396414 }
397415 self . add_pci_devs ( ) ?;
398416 let init_state = self . load_payload ( ) ?;
399- self . init_boot_vcpu ( vcpu, & init_state) ?;
417+ self . init_boot_vcpu ( & mut vcpu, & init_state) ?;
400418 self . create_firmware_data ( & init_state) ?;
401419 }
402- self . init_ap ( index, vcpu, & vcpus) ?;
420+ self . init_ap ( index, & mut vcpu, & vcpus) ?;
403421 self . coco_finalize ( index, & vcpus) ?;
404422 self . sync_vcpus ( & vcpus) ?;
405423 drop ( vcpus) ;
406424
407- let maybe_reboot = self . vcpu_loop ( vcpu, index) ;
425+ let maybe_reboot = self . vcpu_loop ( & mut vcpu, index) ;
408426
409427 let vcpus = self . vcpus . read ( ) ;
410428 let mut mp_sync = self . mp_sync . lock ( ) ;
@@ -414,7 +432,7 @@ where
414432 } else {
415433 BoardState :: Shutdown
416434 } ;
417- for ( another, ( handle, _ ) ) in vcpus. iter ( ) . enumerate ( ) {
435+ for ( another, handle) in vcpus. iter ( ) . enumerate ( ) {
418436 if index == another as u16 {
419437 continue ;
420438 }
@@ -433,7 +451,7 @@ where
433451 self . pci_bus . segment . reset ( ) . context ( error:: ResetPci ) ?;
434452 self . memory . reset ( ) ?;
435453 }
436- self . reset_vcpu ( index, vcpu) ?;
454+ self . reset_vcpu ( index, & mut vcpu) ?;
437455
438456 if let Err ( e) = maybe_reboot {
439457 break Err ( e) ;
@@ -447,29 +465,19 @@ where
447465 }
448466 }
449467
450- fn create_vcpu ( & self , index : u16 , event_tx : & Sender < u16 > ) -> Result < V :: Vcpu > {
468+ fn create_vcpu ( & self , index : u16 ) -> Result < V :: Vcpu > {
451469 let identity = self . encode_cpu_identity ( index) ;
452470 let vcpu = self
453471 . vm
454472 . create_vcpu ( index, identity)
455473 . context ( error:: CreateVcpu { index } ) ?;
456- if event_tx. send ( index) . is_err ( ) {
457- error:: NotifyVmm . fail ( )
458- } else {
459- Ok ( vcpu)
460- }
474+ Ok ( vcpu)
461475 }
462476
463- pub fn run_vcpu (
464- & self ,
465- index : u16 ,
466- event_tx : Sender < u16 > ,
467- boot_rx : Receiver < ( ) > ,
468- ) -> Result < ( ) , Error > {
469- let mut vcpu = self . create_vcpu ( index, & event_tx) ?;
477+ pub fn run_vcpu ( & self , index : u16 , event_tx : Sender < u16 > ) -> Result < ( ) , Error > {
478+ let ret = self . run_vcpu_inner ( index, & event_tx) ;
470479
471- let ret = self . run_vcpu_inner ( index, & mut vcpu, & boot_rx) ;
472- event_tx. send ( index) . unwrap ( ) ;
480+ let _ = self . notify_vmm ( index, & event_tx) ;
473481
474482 if matches ! ( ret, Ok ( _) | Err ( Error :: PeerFailure { .. } ) ) {
475483 return Ok ( ( ) ) ;
0 commit comments