@@ -11,6 +11,7 @@ use std::sync::{Arc, Mutex, MutexGuard};
1111
1212use vmm_sys_util:: eventfd:: EventFd ;
1313
14+ use super :: { VirtioInterrupt , VirtioInterruptType } ;
1415use crate :: devices:: virtio:: device:: VirtioDevice ;
1516use crate :: devices:: virtio:: device_status;
1617use crate :: devices:: virtio:: queue:: Queue ;
@@ -375,13 +376,56 @@ pub enum IrqType {
375376 Vring ,
376377}
377378
379+ impl From < VirtioInterruptType > for IrqType {
380+ fn from ( interrupt_type : VirtioInterruptType ) -> Self {
381+ match interrupt_type {
382+ VirtioInterruptType :: Config => IrqType :: Config ,
383+ VirtioInterruptType :: Queue ( _) => IrqType :: Vring ,
384+ }
385+ }
386+ }
387+
378388/// Helper struct that is responsible for triggering guest IRQs
379389#[ derive( Debug ) ]
380390pub struct IrqTrigger {
381391 pub ( crate ) irq_status : Arc < AtomicU32 > ,
382392 pub ( crate ) irq_evt : EventFd ,
383393}
384394
395+ impl VirtioInterrupt for IrqTrigger {
396+ fn trigger ( & self , interrupt_type : VirtioInterruptType ) -> Result < ( ) , std:: io:: Error > {
397+ match interrupt_type {
398+ VirtioInterruptType :: Config => self . trigger_irq ( IrqType :: Config ) ,
399+ VirtioInterruptType :: Queue ( _) => self . trigger_irq ( IrqType :: Vring ) ,
400+ }
401+ }
402+
403+ fn notifier ( & self , _interrupt_type : VirtioInterruptType ) -> Option < & EventFd > {
404+ Some ( & self . irq_evt )
405+ }
406+
407+ fn status ( & self ) -> Arc < AtomicU32 > {
408+ self . irq_status . clone ( )
409+ }
410+
411+ #[ cfg( test) ]
412+ fn has_pending_interrupt ( & self , interrupt_type : VirtioInterruptType ) -> bool {
413+ if let Ok ( num_irqs) = self . irq_evt . read ( ) {
414+ if num_irqs == 0 {
415+ return false ;
416+ }
417+
418+ let irq_status = self . irq_status . load ( Ordering :: SeqCst ) ;
419+ return matches ! (
420+ ( irq_status, interrupt_type. into( ) ) ,
421+ ( VIRTIO_MMIO_INT_CONFIG , IrqType :: Config ) | ( VIRTIO_MMIO_INT_VRING , IrqType :: Vring )
422+ ) ;
423+ }
424+
425+ false
426+ }
427+ }
428+
385429impl IrqTrigger {
386430 pub fn new ( ) -> std:: io:: Result < Self > {
387431 Ok ( Self {
@@ -993,6 +1037,25 @@ pub(crate) mod tests {
9931037 assert ! ( d. locked_device( ) . is_activated( ) ) ;
9941038 }
9951039
1040+ impl IrqTrigger {
1041+ pub fn has_pending_irq ( & self , irq_type : IrqType ) -> bool {
1042+ if let Ok ( num_irqs) = self . irq_evt . read ( ) {
1043+ if num_irqs == 0 {
1044+ return false ;
1045+ }
1046+
1047+ let irq_status = self . irq_status . load ( Ordering :: SeqCst ) ;
1048+ return matches ! (
1049+ ( irq_status, irq_type) ,
1050+ ( VIRTIO_MMIO_INT_CONFIG , IrqType :: Config )
1051+ | ( VIRTIO_MMIO_INT_VRING , IrqType :: Vring )
1052+ ) ;
1053+ }
1054+
1055+ false
1056+ }
1057+ }
1058+
9961059 #[ test]
9971060 fn test_bus_device_reset ( ) {
9981061 let m = single_region_mem ( 0x1000 ) ;
@@ -1053,44 +1116,29 @@ pub(crate) mod tests {
10531116 assert_eq ! ( dummy_dev. acked_features( ) , 24 ) ;
10541117 }
10551118
1056- impl IrqTrigger {
1057- pub fn has_pending_irq ( & self , irq_type : IrqType ) -> bool {
1058- if let Ok ( num_irqs) = self . irq_evt . read ( ) {
1059- if num_irqs == 0 {
1060- return false ;
1061- }
1062-
1063- let irq_status = self . irq_status . load ( Ordering :: SeqCst ) ;
1064- return matches ! (
1065- ( irq_status, irq_type) ,
1066- ( VIRTIO_MMIO_INT_CONFIG , IrqType :: Config )
1067- | ( VIRTIO_MMIO_INT_VRING , IrqType :: Vring )
1068- ) ;
1069- }
1070-
1071- false
1072- }
1073- }
1074-
10751119 #[ test]
10761120 fn irq_trigger ( ) {
10771121 let irq_trigger = IrqTrigger :: new ( ) . unwrap ( ) ;
10781122 assert_eq ! ( irq_trigger. irq_status. load( Ordering :: SeqCst ) , 0 ) ;
10791123
10801124 // Check that there are no pending irqs.
1081- assert ! ( !irq_trigger. has_pending_irq ( IrqType :: Config ) ) ;
1082- assert ! ( !irq_trigger. has_pending_irq ( IrqType :: Vring ) ) ;
1125+ assert ! ( !irq_trigger. has_pending_interrupt ( VirtioInterruptType :: Config ) ) ;
1126+ assert ! ( !irq_trigger. has_pending_interrupt ( VirtioInterruptType :: Queue ( 0 ) ) ) ;
10831127
10841128 // Check that trigger_irq() correctly generates irqs.
1085- irq_trigger. trigger_irq ( IrqType :: Config ) . unwrap ( ) ;
1086- assert ! ( irq_trigger. has_pending_irq ( IrqType :: Config ) ) ;
1129+ irq_trigger. trigger ( VirtioInterruptType :: Config ) . unwrap ( ) ;
1130+ assert ! ( irq_trigger. has_pending_interrupt ( VirtioInterruptType :: Config ) ) ;
10871131 irq_trigger. irq_status . store ( 0 , Ordering :: SeqCst ) ;
1088- irq_trigger. trigger_irq ( IrqType :: Vring ) . unwrap ( ) ;
1089- assert ! ( irq_trigger. has_pending_irq ( IrqType :: Vring ) ) ;
1132+ irq_trigger. trigger ( VirtioInterruptType :: Queue ( 0 ) ) . unwrap ( ) ;
1133+ assert ! ( irq_trigger. has_pending_interrupt ( VirtioInterruptType :: Queue ( 0 ) ) ) ;
10901134
10911135 // Check trigger_irq() failure case (irq_evt is full).
10921136 irq_trigger. irq_evt . write ( u64:: MAX - 1 ) . unwrap ( ) ;
1093- irq_trigger. trigger_irq ( IrqType :: Config ) . unwrap_err ( ) ;
1094- irq_trigger. trigger_irq ( IrqType :: Vring ) . unwrap_err ( ) ;
1137+ irq_trigger
1138+ . trigger ( VirtioInterruptType :: Config )
1139+ . unwrap_err ( ) ;
1140+ irq_trigger
1141+ . trigger ( VirtioInterruptType :: Queue ( 0 ) )
1142+ . unwrap_err ( ) ;
10951143 }
10961144}
0 commit comments