@@ -377,6 +377,7 @@ pub(crate) mod tests {
377
377
378
378
use super :: * ;
379
379
use crate :: devices:: virtio:: device:: IrqTrigger ;
380
+ use crate :: devices:: virtio:: device_status:: DEVICE_NEEDS_RESET ;
380
381
use crate :: devices:: virtio:: ActivateError ;
381
382
use crate :: utilities:: test_utils:: single_region_mem;
382
383
use crate :: vstate:: memory:: GuestMemoryMmap ;
@@ -390,6 +391,7 @@ pub(crate) mod tests {
390
391
queues : Vec < Queue > ,
391
392
device_activated : bool ,
392
393
config_bytes : [ u8 ; 0xeff ] ,
394
+ activate_should_error : bool ,
393
395
}
394
396
395
397
impl DummyDevice {
@@ -405,6 +407,7 @@ pub(crate) mod tests {
405
407
queues : vec ! [ Queue :: new( 16 ) , Queue :: new( 32 ) ] ,
406
408
device_activated : false ,
407
409
config_bytes : [ 0 ; 0xeff ] ,
410
+ activate_should_error : false ,
408
411
}
409
412
}
410
413
@@ -458,7 +461,11 @@ pub(crate) mod tests {
458
461
459
462
fn activate ( & mut self , _: GuestMemoryMmap ) -> Result < ( ) , ActivateError > {
460
463
self . device_activated = true ;
461
- Ok ( ( ) )
464
+ if self . activate_should_error {
465
+ Err ( ActivateError :: BadActivate )
466
+ } else {
467
+ Ok ( ( ) )
468
+ }
462
469
}
463
470
464
471
fn is_activated ( & self ) -> bool {
@@ -831,6 +838,63 @@ pub(crate) mod tests {
831
838
assert_eq ! ( read_le_u32( & buf[ ..] ) , 1 ) ;
832
839
}
833
840
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
+
834
898
fn activate_device ( d : & mut MmioTransport ) {
835
899
set_device_status ( d, device_status:: ACKNOWLEDGE ) ;
836
900
set_device_status ( d, device_status:: ACKNOWLEDGE | device_status:: DRIVER ) ;
0 commit comments