@@ -275,3 +275,200 @@ impl KvmIrqRouting {
275275 Ok ( ( ) )
276276 }
277277}
278+
279+ #[ cfg( test) ]
280+ mod test {
281+ use super :: * ;
282+ use kvm_ioctls:: { DeviceFd , Kvm , VmFd } ;
283+ use std:: path:: Path ;
284+ use vfio_ioctls:: { VfioContainer , VfioDevice } ;
285+
286+ const VFIO_PCI_MSI_IRQ_INDEX : u32 = 1 ;
287+
288+ fn create_vm_fd ( ) -> VmFd {
289+ let kvm = Kvm :: new ( ) . unwrap ( ) ;
290+ kvm. create_vm ( ) . unwrap ( )
291+ }
292+
293+ fn create_kvm_device ( vm : Arc < VmFd > ) -> DeviceFd {
294+ let mut vfio_dev = kvm_bindings:: kvm_create_device {
295+ type_ : kvm_bindings:: kvm_device_type_KVM_DEV_TYPE_VFIO,
296+ fd : 0 ,
297+ flags : 0 ,
298+ } ;
299+
300+ vm. create_device ( & mut vfio_dev) . unwrap ( )
301+ }
302+
303+ fn create_irq_group (
304+ manager : Arc < KvmIrqManager > ,
305+ vmfd : Arc < VmFd > ,
306+ ) -> Arc < dyn InterruptSourceGroup > {
307+ let base = 0 ;
308+ let count = 1 ;
309+
310+ manager
311+ . create_group ( InterruptSourceType :: LegacyIrq , base, count)
312+ . unwrap ( )
313+ }
314+
315+ fn create_msi_group (
316+ manager : Arc < KvmIrqManager > ,
317+ vmfd : Arc < VmFd > ,
318+ ) -> Arc < dyn InterruptSourceGroup > {
319+ let base = 168 ;
320+ let count = 32 ;
321+
322+ manager
323+ . create_group ( InterruptSourceType :: MsiIrq , base, count)
324+ . unwrap ( )
325+ }
326+
327+ fn create_vfio_msi_group (
328+ manager : Arc < KvmIrqManager > ,
329+ vmfd : Arc < VmFd > ,
330+ ) -> Arc < dyn InterruptSourceGroup > {
331+ let kvm_device = create_kvm_device ( vmfd. clone ( ) ) ;
332+ let kvm_device = Arc :: new ( kvm_device) ;
333+ let sysfspath_eth1: & Path = Path :: new ( "/sys/bus/pci/devices/0000:5c:00.0/" ) ;
334+ let container = Arc :: new ( VfioContainer :: new ( kvm_device) . unwrap ( ) ) ;
335+ let vfio_device = Arc :: new (
336+ VfioDevice :: new ( sysfspath_eth1, container)
337+ . map_err ( |err| println ! ( "{}" , err) )
338+ . unwrap ( ) ,
339+ ) ;
340+
341+ let count = match vfio_device. get_irq_info ( VFIO_PCI_MSI_IRQ_INDEX ) {
342+ Some ( ref info) => info. count ,
343+ None => 0 ,
344+ } ;
345+
346+ manager
347+ . create_group (
348+ InterruptSourceType :: VfioMsiIrq ( vfio_device, VFIO_PCI_MSI_IRQ_INDEX ) ,
349+ 0 ,
350+ count,
351+ )
352+ . unwrap ( )
353+ }
354+
355+ const MASTER_PIC : usize = 7 ;
356+ const SLAVE_PIC : usize = 8 ;
357+ const IOAPIC : usize = 23 ;
358+
359+ #[ test]
360+ fn test_create_kvmirqmanager ( ) {
361+ let vmfd = Arc :: new ( create_vm_fd ( ) ) ;
362+ let manager = KvmIrqManager :: new ( vmfd. clone ( ) ) ;
363+ assert ! ( vmfd. create_irq_chip( ) . is_ok( ) ) ;
364+ assert ! ( manager. initialize( ) . is_ok( ) ) ;
365+ }
366+
367+ #[ test]
368+ fn test_kvmirqmanager_opt ( ) {
369+ let vmfd = Arc :: new ( create_vm_fd ( ) ) ;
370+ assert ! ( vmfd. create_irq_chip( ) . is_ok( ) ) ;
371+ let manager = Arc :: new ( KvmIrqManager :: new ( vmfd. clone ( ) ) ) ;
372+ assert ! ( manager. initialize( ) . is_ok( ) ) ;
373+ //irq
374+ let group = create_irq_group ( manager. clone ( ) , vmfd. clone ( ) ) ;
375+ let tmp = group. clone ( ) ;
376+ assert ! ( manager. destroy_group( group) . is_ok( ) ) ;
377+ //msi
378+ let group = create_msi_group ( manager. clone ( ) , vmfd. clone ( ) ) ;
379+ let tmp = group. clone ( ) ;
380+ assert ! ( manager. destroy_group( group) . is_ok( ) ) ;
381+ //vfio msi
382+ let group = create_vfio_msi_group ( manager. clone ( ) , vmfd. clone ( ) ) ;
383+ let tmp = group. clone ( ) ;
384+ assert ! ( manager. destroy_group( group) . is_ok( ) ) ;
385+ }
386+
387+ #[ test]
388+ fn test_irqrouting_initialize_legacy ( ) {
389+ let vmfd = Arc :: new ( create_vm_fd ( ) ) ;
390+ let routing = KvmIrqRouting :: new ( vmfd. clone ( ) ) ;
391+ assert ! ( routing. initialize( ) . is_err( ) ) ;
392+ assert ! ( vmfd. create_irq_chip( ) . is_ok( ) ) ;
393+ assert ! ( routing. initialize( ) . is_ok( ) ) ;
394+ let routes = & routing. routes . lock ( ) . unwrap ( ) ;
395+ assert_eq ! ( routes. len( ) , MASTER_PIC + SLAVE_PIC + IOAPIC ) ;
396+ }
397+
398+ #[ test]
399+ fn test_routing_opt ( ) {
400+ // pub(super) fn modify(&self, entry: &kvm_irq_routing_entry) -> Result<()> {
401+ let vmfd = Arc :: new ( create_vm_fd ( ) ) ;
402+ let routing = KvmIrqRouting :: new ( vmfd. clone ( ) ) ;
403+ assert ! ( routing. initialize( ) . is_err( ) ) ;
404+ assert ! ( vmfd. create_irq_chip( ) . is_ok( ) ) ;
405+ assert ! ( routing. initialize( ) . is_ok( ) ) ;
406+
407+ let mut entry = kvm_irq_routing_entry {
408+ gsi : 8 ,
409+ type_ : KVM_IRQ_ROUTING_IRQCHIP ,
410+ ..Default :: default ( )
411+ } ;
412+
413+ // Safe because we are initializing all fields of the `irqchip` struct.
414+ unsafe {
415+ entry. u . irqchip . irqchip = 0 ;
416+ entry. u . irqchip . pin = 3 ;
417+ }
418+
419+ let entrys = vec ! [ entry. clone( ) ] ;
420+
421+ assert ! ( routing. modify( & entry) . is_err( ) ) ;
422+ assert ! ( routing. add( & entrys) . is_ok( ) ) ;
423+ unsafe {
424+ entry. u . irqchip . pin = 4 ;
425+ }
426+ assert ! ( routing. modify( & entry) . is_ok( ) ) ;
427+ assert ! ( routing. remove( & entrys) . is_ok( ) ) ;
428+ assert ! ( routing. modify( & entry) . is_err( ) ) ;
429+ }
430+
431+ #[ test]
432+ fn test_routing_commit ( ) {
433+ let vmfd = Arc :: new ( create_vm_fd ( ) ) ;
434+ let routing = KvmIrqRouting :: new ( vmfd. clone ( ) ) ;
435+
436+ assert ! ( routing. initialize( ) . is_err( ) ) ;
437+ assert ! ( vmfd. create_irq_chip( ) . is_ok( ) ) ;
438+ assert ! ( routing. initialize( ) . is_ok( ) ) ;
439+
440+ let mut entry = kvm_irq_routing_entry {
441+ gsi : 8 ,
442+ type_ : KVM_IRQ_ROUTING_IRQCHIP ,
443+ ..Default :: default ( )
444+ } ;
445+ unsafe {
446+ entry. u . irqchip . irqchip = 0 ;
447+ entry. u . irqchip . pin = 3 ;
448+ }
449+
450+ routing
451+ . routes
452+ . lock ( )
453+ . unwrap ( )
454+ . insert ( hash_key ( & entry) , entry) ;
455+ let routes = routing. routes . lock ( ) . unwrap ( ) ;
456+ assert ! ( routing. commit( & routes) . is_ok( ) ) ;
457+ }
458+
459+ #[ test]
460+ fn test_has_key ( ) {
461+ let gsi = 4 ;
462+ let mut entry = kvm_irq_routing_entry {
463+ gsi,
464+ type_ : KVM_IRQ_ROUTING_IRQCHIP ,
465+ ..Default :: default ( )
466+ } ;
467+ // Safe because we are initializing all fields of the `irqchip` struct.
468+ unsafe {
469+ entry. u . irqchip . irqchip = KVM_IRQCHIP_PIC_MASTER ;
470+ entry. u . irqchip . pin = gsi;
471+ }
472+ assert_eq ! ( hash_key( & entry) , 0x0001_0000_0004 ) ;
473+ }
474+ }
0 commit comments