@@ -564,67 +564,80 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_device *vdev,
564
564
}
565
565
566
566
static int vfio_pci_set_ctx_trigger_single (struct eventfd_ctx * * ctx ,
567
- uint32_t flags , void * data )
567
+ unsigned int count , uint32_t flags ,
568
+ void * data )
568
569
{
569
- int32_t fd = * (int32_t * )data ;
570
-
571
- if (!(flags & VFIO_IRQ_SET_DATA_TYPE_MASK ))
572
- return - EINVAL ;
573
-
574
570
/* DATA_NONE/DATA_BOOL enables loopback testing */
575
571
if (flags & VFIO_IRQ_SET_DATA_NONE ) {
576
- if (* ctx )
577
- eventfd_signal (* ctx , 1 );
578
- return 0 ;
572
+ if (* ctx ) {
573
+ if (count ) {
574
+ eventfd_signal (* ctx , 1 );
575
+ } else {
576
+ eventfd_ctx_put (* ctx );
577
+ * ctx = NULL ;
578
+ }
579
+ return 0 ;
580
+ }
579
581
} else if (flags & VFIO_IRQ_SET_DATA_BOOL ) {
580
- uint8_t trigger = * (uint8_t * )data ;
582
+ uint8_t trigger ;
583
+
584
+ if (!count )
585
+ return - EINVAL ;
586
+
587
+ trigger = * (uint8_t * )data ;
581
588
if (trigger && * ctx )
582
589
eventfd_signal (* ctx , 1 );
583
- return 0 ;
584
- }
585
590
586
- /* Handle SET_DATA_EVENTFD */
587
- if (fd == -1 ) {
588
- if (* ctx )
589
- eventfd_ctx_put (* ctx );
590
- * ctx = NULL ;
591
591
return 0 ;
592
- } else if (fd >= 0 ) {
593
- struct eventfd_ctx * efdctx ;
594
- efdctx = eventfd_ctx_fdget (fd );
595
- if (IS_ERR (efdctx ))
596
- return PTR_ERR (efdctx );
597
- if (* ctx )
598
- eventfd_ctx_put (* ctx );
599
- * ctx = efdctx ;
592
+ } else if (flags & VFIO_IRQ_SET_DATA_EVENTFD ) {
593
+ int32_t fd ;
594
+
595
+ if (!count )
596
+ return - EINVAL ;
597
+
598
+ fd = * (int32_t * )data ;
599
+ if (fd == -1 ) {
600
+ if (* ctx )
601
+ eventfd_ctx_put (* ctx );
602
+ * ctx = NULL ;
603
+ } else if (fd >= 0 ) {
604
+ struct eventfd_ctx * efdctx ;
605
+
606
+ efdctx = eventfd_ctx_fdget (fd );
607
+ if (IS_ERR (efdctx ))
608
+ return PTR_ERR (efdctx );
609
+
610
+ if (* ctx )
611
+ eventfd_ctx_put (* ctx );
612
+
613
+ * ctx = efdctx ;
614
+ }
600
615
return 0 ;
601
- } else
602
- return - EINVAL ;
616
+ }
617
+
618
+ return - EINVAL ;
603
619
}
604
620
605
621
static int vfio_pci_set_err_trigger (struct vfio_pci_device * vdev ,
606
622
unsigned index , unsigned start ,
607
623
unsigned count , uint32_t flags , void * data )
608
624
{
609
- if (index != VFIO_PCI_ERR_IRQ_INDEX )
625
+ if (index != VFIO_PCI_ERR_IRQ_INDEX || start != 0 || count > 1 )
610
626
return - EINVAL ;
611
627
612
- /*
613
- * We should sanitize start & count, but that wasn't caught
614
- * originally, so this IRQ index must forever ignore them :-(
615
- */
616
-
617
- return vfio_pci_set_ctx_trigger_single (& vdev -> err_trigger , flags , data );
628
+ return vfio_pci_set_ctx_trigger_single (& vdev -> err_trigger ,
629
+ count , flags , data );
618
630
}
619
631
620
632
static int vfio_pci_set_req_trigger (struct vfio_pci_device * vdev ,
621
633
unsigned index , unsigned start ,
622
634
unsigned count , uint32_t flags , void * data )
623
635
{
624
- if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count != 1 )
636
+ if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count > 1 )
625
637
return - EINVAL ;
626
638
627
- return vfio_pci_set_ctx_trigger_single (& vdev -> req_trigger , flags , data );
639
+ return vfio_pci_set_ctx_trigger_single (& vdev -> req_trigger ,
640
+ count , flags , data );
628
641
}
629
642
630
643
int vfio_pci_set_irqs_ioctl (struct vfio_pci_device * vdev , uint32_t flags ,
0 commit comments