@@ -377,6 +377,7 @@ pub(crate) mod tests {
377377
378378    use  super :: * ; 
379379    use  crate :: devices:: virtio:: device:: IrqTrigger ; 
380+     use  crate :: devices:: virtio:: device_status:: DEVICE_NEEDS_RESET ; 
380381    use  crate :: devices:: virtio:: ActivateError ; 
381382    use  crate :: utilities:: test_utils:: single_region_mem; 
382383    use  crate :: vstate:: memory:: GuestMemoryMmap ; 
@@ -390,6 +391,7 @@ pub(crate) mod tests {
390391        queues :  Vec < Queue > , 
391392        device_activated :  bool , 
392393        config_bytes :  [ u8 ;  0xeff ] , 
394+         activate_should_error :  bool , 
393395    } 
394396
395397    impl  DummyDevice  { 
@@ -405,6 +407,7 @@ pub(crate) mod tests {
405407                queues :  vec ! [ Queue :: new( 16 ) ,  Queue :: new( 32 ) ] , 
406408                device_activated :  false , 
407409                config_bytes :  [ 0 ;  0xeff ] , 
410+                 activate_should_error :  false , 
408411            } 
409412        } 
410413
@@ -458,7 +461,11 @@ pub(crate) mod tests {
458461
459462        fn  activate ( & mut  self ,  _:  GuestMemoryMmap )  -> Result < ( ) ,  ActivateError >  { 
460463            self . device_activated  = true ; 
461-             Ok ( ( ) ) 
464+             if  self . activate_should_error  { 
465+                 Err ( ActivateError :: BadActivate ) 
466+             }  else  { 
467+                 Ok ( ( ) ) 
468+             } 
462469        } 
463470
464471        fn  is_activated ( & self )  -> bool  { 
@@ -831,6 +838,63 @@ pub(crate) mod tests {
831838        assert_eq ! ( read_le_u32( & buf[ ..] ) ,  1 ) ; 
832839    } 
833840
841+     #[ test]  
842+     fn  test_bus_device_activate_failure ( )  { 
843+         let  m = single_region_mem ( 0x1000 ) ; 
844+         let  device = DummyDevice  { 
845+             activate_should_error :  true , 
846+             ..DummyDevice :: new ( ) 
847+         } ; 
848+         let  mut  d = MmioTransport :: new ( m,  Arc :: new ( Mutex :: new ( device) ) ,  false ) ; 
849+ 
850+         set_device_status ( & mut  d,  device_status:: ACKNOWLEDGE ) ; 
851+         set_device_status ( & mut  d,  device_status:: ACKNOWLEDGE  | device_status:: DRIVER ) ; 
852+         set_device_status ( 
853+             & mut  d, 
854+             device_status:: ACKNOWLEDGE  | device_status:: DRIVER  | device_status:: FEATURES_OK , 
855+         ) ; 
856+ 
857+         let  mut  buf = [ 0 ;  4 ] ; 
858+         let  queue_len = d. locked_device ( ) . queues ( ) . len ( ) ; 
859+         for  q in  0 ..queue_len { 
860+             d. queue_select  = q. try_into ( ) . unwrap ( ) ; 
861+             write_le_u32 ( & mut  buf[ ..] ,  16 ) ; 
862+             d. bus_write ( 0x38 ,  & buf[ ..] ) ; 
863+             write_le_u32 ( & mut  buf[ ..] ,  1 ) ; 
864+             d. bus_write ( 0x44 ,  & buf[ ..] ) ; 
865+         } 
866+         assert ! ( d. are_queues_valid( ) ) ; 
867+         assert_eq ! ( 
868+             d. locked_device( ) . interrupt_status( ) . load( Ordering :: SeqCst ) , 
869+             0 
870+         ) ; 
871+ 
872+         set_device_status ( 
873+             & mut  d, 
874+             device_status:: ACKNOWLEDGE 
875+                 | device_status:: DRIVER 
876+                 | device_status:: FEATURES_OK 
877+                 | device_status:: DRIVER_OK , 
878+         ) ; 
879+ 
880+         // Failure in activate results in `DEVICE_NEEDS_RESET` status being set 
881+         assert_ne ! ( d. device_status &  DEVICE_NEEDS_RESET ,  0 ) ; 
882+         // We injected an interrupt of type "configuration change" 
883+         assert_eq ! ( 
884+             d. locked_device( ) . interrupt_status( ) . load( Ordering :: SeqCst ) , 
885+             VIRTIO_MMIO_INT_CONFIG 
886+         ) ; 
887+         // We actually wrote to the eventfd 
888+         assert_eq ! ( 
889+             d. locked_device( ) 
890+                 . interrupt_trigger( ) 
891+                 . irq_evt
892+                 . read( ) 
893+                 . unwrap( ) , 
894+             1 
895+         ) ; 
896+     } 
897+ 
834898    fn  activate_device ( d :  & mut  MmioTransport )  { 
835899        set_device_status ( d,  device_status:: ACKNOWLEDGE ) ; 
836900        set_device_status ( d,  device_status:: ACKNOWLEDGE  | device_status:: DRIVER ) ; 
0 commit comments