1010
1111#include <asm/kvm.h>
1212#include <asm/kvm_para.h>
13+ #include <sys/eventfd.h>
1314#include <linux/sizes.h>
1415
1516#include "processor.h"
@@ -31,6 +32,8 @@ struct test_args {
3132 uint32_t nr_irqs ; /* number of KVM supported IRQs. */
3233 bool eoi_split ; /* 1 is eoir+dir, 0 is eoir only */
3334 bool level_sensitive ; /* 1 is level, 0 is edge */
35+ int kvm_max_routes ; /* output of KVM_CAP_IRQ_ROUTING */
36+ bool kvm_supports_irqfd ; /* output of KVM_CAP_IRQFD */
3437};
3538
3639/*
@@ -61,6 +64,7 @@ typedef enum {
6164 KVM_SET_IRQ_LINE ,
6265 KVM_SET_IRQ_LINE_HIGH ,
6366 KVM_SET_LEVEL_INFO_HIGH ,
67+ KVM_INJECT_IRQFD ,
6468} kvm_inject_cmd ;
6569
6670struct kvm_inject_args {
@@ -100,19 +104,25 @@ struct kvm_inject_desc {
100104static struct kvm_inject_desc inject_edge_fns [] = {
101105 /* sgi ppi spi */
102106 { KVM_INJECT_EDGE_IRQ_LINE , false, false, true },
107+ { KVM_INJECT_IRQFD , false, false, true },
103108 { 0 , },
104109};
105110
106111static struct kvm_inject_desc inject_level_fns [] = {
107112 /* sgi ppi spi */
108113 { KVM_SET_IRQ_LINE_HIGH , false, true, true },
109114 { KVM_SET_LEVEL_INFO_HIGH , false, true, true },
115+ { KVM_INJECT_IRQFD , false, false, true },
110116 { 0 , },
111117};
112118
113119#define for_each_inject_fn (t , f ) \
114120 for ((f) = (t); (f)->cmd; (f)++)
115121
122+ #define for_each_supported_inject_fn (args , t , f ) \
123+ for_each_inject_fn(t, f) \
124+ if ((args)->kvm_supports_irqfd || (f)->cmd != KVM_INJECT_IRQFD)
125+
116126/* Shared between the guest main thread and the IRQ handlers. */
117127volatile uint64_t irq_handled ;
118128volatile uint32_t irqnr_received [MAX_SPI + 1 ];
@@ -403,7 +413,7 @@ static void guest_code(struct test_args args)
403413 local_irq_enable ();
404414
405415 /* Start the tests. */
406- for_each_inject_fn ( inject_fns , f ) {
416+ for_each_supported_inject_fn ( & args , inject_fns , f ) {
407417 test_injection (& args , f );
408418 test_preemption (& args , f );
409419 test_injection_failure (& args , f );
@@ -455,6 +465,88 @@ void kvm_irq_set_level_info_check(int gic_fd, uint32_t intid, int level,
455465 }
456466}
457467
468+ static void kvm_set_gsi_routing_irqchip_check (struct kvm_vm * vm ,
469+ uint32_t intid , uint32_t num , uint32_t kvm_max_routes ,
470+ bool expect_failure )
471+ {
472+ struct kvm_irq_routing * routing ;
473+ int ret ;
474+ uint64_t i ;
475+
476+ assert (num <= kvm_max_routes && kvm_max_routes <= KVM_MAX_IRQ_ROUTES );
477+
478+ routing = kvm_gsi_routing_create ();
479+ for (i = intid ; i < (uint64_t )intid + num ; i ++ )
480+ kvm_gsi_routing_irqchip_add (routing , i - MIN_SPI , i - MIN_SPI );
481+
482+ if (!expect_failure ) {
483+ kvm_gsi_routing_write (vm , routing );
484+ } else {
485+ ret = _kvm_gsi_routing_write (vm , routing );
486+ /* The kernel only checks for KVM_IRQCHIP_NUM_PINS. */
487+ if (intid >= KVM_IRQCHIP_NUM_PINS )
488+ TEST_ASSERT (ret != 0 && errno == EINVAL ,
489+ "Bad intid %u did not cause KVM_SET_GSI_ROUTING "
490+ "error: rc: %i errno: %i" , intid , ret , errno );
491+ else
492+ TEST_ASSERT (ret == 0 , "KVM_SET_GSI_ROUTING "
493+ "for intid %i failed, rc: %i errno: %i" ,
494+ intid , ret , errno );
495+ }
496+ }
497+
498+ static void kvm_routing_and_irqfd_check (struct kvm_vm * vm ,
499+ uint32_t intid , uint32_t num , uint32_t kvm_max_routes ,
500+ bool expect_failure )
501+ {
502+ int fd [MAX_SPI ];
503+ uint64_t val ;
504+ int ret , f ;
505+ uint64_t i ;
506+
507+ /*
508+ * There is no way to try injecting an SGI or PPI as the interface
509+ * starts counting from the first SPI (above the private ones), so just
510+ * exit.
511+ */
512+ if (INTID_IS_SGI (intid ) || INTID_IS_PPI (intid ))
513+ return ;
514+
515+ kvm_set_gsi_routing_irqchip_check (vm , intid , num ,
516+ kvm_max_routes , expect_failure );
517+
518+ /*
519+ * If expect_failure, then just to inject anyway. These
520+ * will silently fail. And in any case, the guest will check
521+ * that no actual interrupt was injected for those cases.
522+ */
523+
524+ for (f = 0 , i = intid ; i < (uint64_t )intid + num ; i ++ , f ++ ) {
525+ fd [f ] = eventfd (0 , 0 );
526+ TEST_ASSERT (fd [f ] != -1 ,
527+ "eventfd failed, errno: %i\n" , errno );
528+ }
529+
530+ for (f = 0 , i = intid ; i < (uint64_t )intid + num ; i ++ , f ++ ) {
531+ struct kvm_irqfd irqfd = {
532+ .fd = fd [f ],
533+ .gsi = i - MIN_SPI ,
534+ };
535+ assert (i <= (uint64_t )UINT_MAX );
536+ vm_ioctl (vm , KVM_IRQFD , & irqfd );
537+ }
538+
539+ for (f = 0 , i = intid ; i < (uint64_t )intid + num ; i ++ , f ++ ) {
540+ val = 1 ;
541+ ret = write (fd [f ], & val , sizeof (uint64_t ));
542+ TEST_ASSERT (ret == sizeof (uint64_t ),
543+ "Write to KVM_IRQFD failed with ret: %d\n" , ret );
544+ }
545+
546+ for (f = 0 , i = intid ; i < (uint64_t )intid + num ; i ++ , f ++ )
547+ close (fd [f ]);
548+ }
549+
458550/* handles the valid case: intid=0xffffffff num=1 */
459551#define for_each_intid (first , num , tmp , i ) \
460552 for ((tmp) = (i) = (first); \
@@ -500,6 +592,11 @@ static void run_guest_cmd(struct kvm_vm *vm, int gic_fd,
500592 kvm_irq_set_level_info_check (gic_fd , i , 1 ,
501593 expect_failure );
502594 break ;
595+ case KVM_INJECT_IRQFD :
596+ kvm_routing_and_irqfd_check (vm , intid , num ,
597+ test_args -> kvm_max_routes ,
598+ expect_failure );
599+ break ;
503600 default :
504601 break ;
505602 }
@@ -534,6 +631,8 @@ static void test_vgic(uint32_t nr_irqs, bool level_sensitive, bool eoi_split)
534631 .nr_irqs = nr_irqs ,
535632 .level_sensitive = level_sensitive ,
536633 .eoi_split = eoi_split ,
634+ .kvm_max_routes = kvm_check_cap (KVM_CAP_IRQ_ROUTING ),
635+ .kvm_supports_irqfd = kvm_check_cap (KVM_CAP_IRQFD ),
537636 };
538637
539638 print_args (& args );
0 commit comments