@@ -57,11 +57,16 @@ pub struct MmioTransport {
57
57
pub ( crate ) config_generation : u32 ,
58
58
mem : GuestMemoryMmap ,
59
59
pub ( crate ) interrupt_status : Arc < AtomicU32 > ,
60
+ pub is_vhost_user : bool ,
60
61
}
61
62
62
63
impl MmioTransport {
63
64
/// Constructs a new MMIO transport for the given virtio device.
64
- pub fn new ( mem : GuestMemoryMmap , device : Arc < Mutex < dyn VirtioDevice > > ) -> MmioTransport {
65
+ pub fn new (
66
+ mem : GuestMemoryMmap ,
67
+ device : Arc < Mutex < dyn VirtioDevice > > ,
68
+ is_vhost_user : bool ,
69
+ ) -> MmioTransport {
65
70
let interrupt_status = device. lock ( ) . expect ( "Poisoned lock" ) . interrupt_status ( ) ;
66
71
67
72
MmioTransport {
@@ -73,6 +78,7 @@ impl MmioTransport {
73
78
config_generation : 0 ,
74
79
mem,
75
80
interrupt_status,
81
+ is_vhost_user,
76
82
}
77
83
}
78
84
@@ -239,7 +245,19 @@ impl MmioTransport {
239
245
}
240
246
0x34 => self . with_queue ( 0 , |q| u32:: from ( q. get_max_size ( ) ) ) ,
241
247
0x44 => self . with_queue ( 0 , |q| u32:: from ( q. ready ) ) ,
242
- 0x60 => self . interrupt_status . load ( Ordering :: SeqCst ) ,
248
+ 0x60 => {
249
+ // For vhost-user backed devices we can only report
250
+ // `VIRTIO_MMIO_INT_VRING` (bit 0 set) value, as any
251
+ // changes to the interrupt status value cannot be propagated
252
+ // back to FC from vhost-user-backend. This also means that backed should
253
+ // not change device configuration as it also requires update to the
254
+ // interrupt status (bit 1 set).
255
+ if !self . is_vhost_user {
256
+ self . interrupt_status . load ( Ordering :: SeqCst )
257
+ } else {
258
+ VIRTIO_MMIO_INT_VRING
259
+ }
260
+ }
243
261
0x70 => self . device_status ,
244
262
0xfc => self . config_generation ,
245
263
_ => {
@@ -440,7 +458,7 @@ pub(crate) mod tests {
440
458
let mut dummy = DummyDevice :: new ( ) ;
441
459
// Validate reset is no-op.
442
460
assert ! ( dummy. reset( ) . is_none( ) ) ;
443
- let mut d = MmioTransport :: new ( m, Arc :: new ( Mutex :: new ( dummy) ) ) ;
461
+ let mut d = MmioTransport :: new ( m, Arc :: new ( Mutex :: new ( dummy) ) , false ) ;
444
462
445
463
// We just make sure here that the implementation of a mmio device behaves as we expect,
446
464
// given a known virtio device implementation (the dummy device).
@@ -469,7 +487,7 @@ pub(crate) mod tests {
469
487
#[ test]
470
488
fn test_bus_device_read ( ) {
471
489
let m = GuestMemoryMmap :: from_raw_regions ( & [ ( GuestAddress ( 0 ) , 0x1000 ) ] , false ) . unwrap ( ) ;
472
- let mut d = MmioTransport :: new ( m, Arc :: new ( Mutex :: new ( DummyDevice :: new ( ) ) ) ) ;
490
+ let mut d = MmioTransport :: new ( m, Arc :: new ( Mutex :: new ( DummyDevice :: new ( ) ) ) , false ) ;
473
491
474
492
let mut buf = vec ! [ 0xff , 0 , 0xfe , 0 ] ;
475
493
let buf_copy = buf. to_vec ( ) ;
@@ -520,6 +538,11 @@ pub(crate) mod tests {
520
538
d. bus_read ( 0x60 , & mut buf[ ..] ) ;
521
539
assert_eq ! ( read_le_u32( & buf[ ..] ) , 111 ) ;
522
540
541
+ d. is_vhost_user = true ;
542
+ d. interrupt_status . store ( 222 , Ordering :: SeqCst ) ;
543
+ d. bus_read ( 0x60 , & mut buf[ ..] ) ;
544
+ assert_eq ! ( read_le_u32( & buf[ ..] ) , VIRTIO_MMIO_INT_VRING ) ;
545
+
523
546
d. bus_read ( 0x70 , & mut buf[ ..] ) ;
524
547
assert_eq ! ( read_le_u32( & buf[ ..] ) , 0 ) ;
525
548
@@ -548,7 +571,7 @@ pub(crate) mod tests {
548
571
fn test_bus_device_write ( ) {
549
572
let m = GuestMemoryMmap :: from_raw_regions ( & [ ( GuestAddress ( 0 ) , 0x1000 ) ] , false ) . unwrap ( ) ;
550
573
let dummy_dev = Arc :: new ( Mutex :: new ( DummyDevice :: new ( ) ) ) ;
551
- let mut d = MmioTransport :: new ( m, dummy_dev. clone ( ) ) ;
574
+ let mut d = MmioTransport :: new ( m, dummy_dev. clone ( ) , false ) ;
552
575
let mut buf = vec ! [ 0 ; 5 ] ;
553
576
write_le_u32 ( & mut buf[ ..4 ] , 1 ) ;
554
577
@@ -706,7 +729,7 @@ pub(crate) mod tests {
706
729
#[ test]
707
730
fn test_bus_device_activate ( ) {
708
731
let m = GuestMemoryMmap :: from_raw_regions ( & [ ( GuestAddress ( 0 ) , 0x1000 ) ] , false ) . unwrap ( ) ;
709
- let mut d = MmioTransport :: new ( m, Arc :: new ( Mutex :: new ( DummyDevice :: new ( ) ) ) ) ;
732
+ let mut d = MmioTransport :: new ( m, Arc :: new ( Mutex :: new ( DummyDevice :: new ( ) ) ) , false ) ;
710
733
711
734
assert ! ( !d. are_queues_valid( ) ) ;
712
735
assert ! ( !d. locked_device( ) . is_activated( ) ) ;
@@ -824,7 +847,7 @@ pub(crate) mod tests {
824
847
#[ test]
825
848
fn test_bus_device_reset ( ) {
826
849
let m = GuestMemoryMmap :: from_raw_regions ( & [ ( GuestAddress ( 0 ) , 0x1000 ) ] , false ) . unwrap ( ) ;
827
- let mut d = MmioTransport :: new ( m, Arc :: new ( Mutex :: new ( DummyDevice :: new ( ) ) ) ) ;
850
+ let mut d = MmioTransport :: new ( m, Arc :: new ( Mutex :: new ( DummyDevice :: new ( ) ) ) , false ) ;
828
851
let mut buf = [ 0 ; 4 ] ;
829
852
830
853
assert ! ( !d. are_queues_valid( ) ) ;
0 commit comments