KVM: selftests: Add IRQ GSI routing library functions
authorRicardo Koller <ricarkol@google.com>
Tue, 9 Nov 2021 02:39:03 +0000 (18:39 -0800)
committerMarc Zyngier <maz@kernel.org>
Tue, 28 Dec 2021 19:24:48 +0000 (19:24 +0000)
Add an architecture independent wrapper function for creating and
writing IRQ GSI routing tables. Also add a function to add irqchip
entries.

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-15-ricarkol@google.com
tools/testing/selftests/kvm/include/kvm_util.h
tools/testing/selftests/kvm/lib/kvm_util.c

index 4ba8fd4..db36e6c 100644 (file)
@@ -252,6 +252,14 @@ int _vcpu_access_device_attr(struct kvm_vm *vm, uint32_t vcpuid, uint32_t group,
 int vcpu_access_device_attr(struct kvm_vm *vm, uint32_t vcpuid, uint32_t group,
                         uint64_t attr, void *val, bool write);
 
+#define KVM_MAX_IRQ_ROUTES             4096
+
+struct kvm_irq_routing *kvm_gsi_routing_create(void);
+void kvm_gsi_routing_irqchip_add(struct kvm_irq_routing *routing,
+               uint32_t gsi, uint32_t pin);
+int _kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing);
+void kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing);
+
 const char *exit_reason_str(unsigned int exit_reason);
 
 void virt_pgd_alloc(struct kvm_vm *vm);
index 9f7210c..68b56e7 100644 (file)
@@ -2107,6 +2107,57 @@ void kvm_irq_line(struct kvm_vm *vm, uint32_t irq, int level)
        TEST_ASSERT(ret >= 0, "KVM_IRQ_LINE failed, rc: %i errno: %i", ret, errno);
 }
 
+struct kvm_irq_routing *kvm_gsi_routing_create(void)
+{
+       struct kvm_irq_routing *routing;
+       size_t size;
+
+       size = sizeof(struct kvm_irq_routing);
+       /* Allocate space for the max number of entries: this wastes 196 KBs. */
+       size += KVM_MAX_IRQ_ROUTES * sizeof(struct kvm_irq_routing_entry);
+       routing = calloc(1, size);
+       assert(routing);
+
+       return routing;
+}
+
+void kvm_gsi_routing_irqchip_add(struct kvm_irq_routing *routing,
+               uint32_t gsi, uint32_t pin)
+{
+       int i;
+
+       assert(routing);
+       assert(routing->nr < KVM_MAX_IRQ_ROUTES);
+
+       i = routing->nr;
+       routing->entries[i].gsi = gsi;
+       routing->entries[i].type = KVM_IRQ_ROUTING_IRQCHIP;
+       routing->entries[i].flags = 0;
+       routing->entries[i].u.irqchip.irqchip = 0;
+       routing->entries[i].u.irqchip.pin = pin;
+       routing->nr++;
+}
+
+int _kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing)
+{
+       int ret;
+
+       assert(routing);
+       ret = ioctl(vm_get_fd(vm), KVM_SET_GSI_ROUTING, routing);
+       free(routing);
+
+       return ret;
+}
+
+void kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing)
+{
+       int ret;
+
+       ret = _kvm_gsi_routing_write(vm, routing);
+       TEST_ASSERT(ret == 0, "KVM_SET_GSI_ROUTING failed, rc: %i errno: %i",
+                               ret, errno);
+}
+
 /*
  * VM Dump
  *