KVM: selftests: aarch64: Abstract the injection functions in vgic_irq
authorRicardo Koller <ricarkol@google.com>
Tue, 9 Nov 2021 02:38:56 +0000 (18:38 -0800)
committerMarc Zyngier <maz@kernel.org>
Tue, 28 Dec 2021 19:23:49 +0000 (19:23 +0000)
Build an abstraction around the injection functions, so the preparation
and checking around the actual injection can be shared between tests.
All functions are stored as pointers in arrays of kvm_inject_desc's
which include the pointer and what kind of interrupts they can inject.

Signed-off-by: Ricardo Koller <ricarkol@google.com>
Acked-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20211109023906.1091208-8-ricarkol@google.com
tools/testing/selftests/kvm/aarch64/vgic_irq.c

index e13e874..f5d76fe 100644 (file)
@@ -57,10 +57,28 @@ struct kvm_inject_args {
 /* Used on the guest side to perform the hypercall. */
 static void kvm_inject_call(kvm_inject_cmd cmd, uint32_t intid);
 
+#define KVM_INJECT(cmd, intid)                                                 \
+       kvm_inject_call(cmd, intid)
+
 /* Used on the host side to get the hypercall info. */
 static void kvm_inject_get_call(struct kvm_vm *vm, struct ucall *uc,
                struct kvm_inject_args *args);
 
+struct kvm_inject_desc {
+       kvm_inject_cmd cmd;
+       /* can inject PPIs, PPIs, and/or SPIs. */
+       bool sgi, ppi, spi;
+};
+
+static struct kvm_inject_desc inject_edge_fns[] = {
+       /*                                      sgi    ppi    spi */
+       { KVM_INJECT_EDGE_IRQ_LINE,             false, false, true },
+       { 0, },
+};
+
+#define for_each_inject_fn(t, f)                                               \
+       for ((f) = (t); (f)->cmd; (f)++)
+
 /* Shared between the guest main thread and the IRQ handlers. */
 volatile uint64_t irq_handled;
 volatile uint32_t irqnr_received[MAX_SPI + 1];
@@ -120,12 +138,12 @@ do {                                                                              \
        GUEST_ASSERT(_intid == 0 || _intid == IAR_SPURIOUS);                    \
 } while (0)
 
-static void test_kvm_irq_line(uint32_t intid)
+static void guest_inject(uint32_t intid, kvm_inject_cmd cmd)
 {
        reset_stats();
 
        asm volatile("msr daifset, #2" : : : "memory");
-       kvm_inject_call(KVM_INJECT_EDGE_IRQ_LINE, intid);
+       KVM_INJECT(cmd, intid);
 
        while (irq_handled < 1) {
                asm volatile("wfi\n"
@@ -141,10 +159,23 @@ static void test_kvm_irq_line(uint32_t intid)
        GUEST_ASSERT_IAR_EMPTY();
 }
 
+static void test_injection(struct kvm_inject_desc *f)
+{
+       if (f->sgi)
+               guest_inject(MIN_SGI, f->cmd);
+
+       if (f->ppi)
+               guest_inject(MIN_PPI, f->cmd);
+
+       if (f->spi)
+               guest_inject(MIN_SPI, f->cmd);
+}
+
 static void guest_code(void)
 {
        uint32_t i;
        uint32_t nr_irqs = 64; /* absolute minimum number of IRQs supported. */
+       struct kvm_inject_desc *f;
 
        gic_init(GIC_V3, 1, dist, redist);
 
@@ -157,7 +188,9 @@ static void guest_code(void)
 
        local_irq_enable();
 
-       test_kvm_irq_line(MIN_SPI);
+       /* Start the tests. */
+       for_each_inject_fn(inject_edge_fns, f)
+               test_injection(f);
 
        GUEST_DONE();
 }