Hi Jean-Philippe, On 02/11/16 14:37, Jean-Philippe Brucker wrote: > On 20/07/16 18:04, Andre Przywara wrote: >> The current IRQ routing code in x86/irq.c is mostly implementing a >> generic KVM interface which other architectures may use too. >> Move the code to set up an MSI route into the generic irq.c file and >> guard it with the KVM_CAP_IRQ_ROUTING capability to return an error >> if the kernel does not support interrupt routing. >> This also removes the dummy implementations for all other >> architectures and only leaves the x86 specific code in x86/irq.c. >> >> Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx> >> --- >> Makefile | 4 +-- >> arm/irq.c | 9 ------ >> hw/pci-shmem.c | 2 ++ >> include/kvm/irq.h | 5 ++++ >> irq.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ >> mips/irq.c | 10 ------- >> powerpc/irq.c | 31 --------------------- >> virtio/pci.c | 21 +++++++++----- >> x86/irq.c | 45 ++++-------------------------- >> 9 files changed, 110 insertions(+), 100 deletions(-) >> delete mode 100644 arm/irq.c >> delete mode 100644 mips/irq.c >> delete mode 100644 powerpc/irq.c >> >> diff --git a/Makefile b/Makefile >> index e4a4002..8ca887f 100644 >> --- a/Makefile >> +++ b/Makefile >> @@ -138,7 +138,6 @@ ifeq ($(ARCH), powerpc) >> DEFINES += -DCONFIG_PPC >> OBJS += powerpc/boot.o >> OBJS += powerpc/ioport.o >> - OBJS += powerpc/irq.o >> OBJS += powerpc/kvm.o >> OBJS += powerpc/cpu_info.o >> OBJS += powerpc/kvm-cpu.o >> @@ -153,7 +152,7 @@ ifeq ($(ARCH), powerpc) >> endif >> >> # ARM >> -OBJS_ARM_COMMON := arm/fdt.o arm/gic.o arm/ioport.o arm/irq.o \ >> +OBJS_ARM_COMMON := arm/fdt.o arm/gic.o arm/ioport.o \ >> arm/kvm.o arm/kvm-cpu.o arm/pci.o arm/timer.o \ >> arm/pmu.o >> HDRS_ARM_COMMON := arm/include >> @@ -186,7 +185,6 @@ ifeq ($(ARCH),mips) >> ARCH_INCLUDE := mips/include >> OBJS += mips/kvm.o >> OBJS += mips/kvm-cpu.o >> - OBJS += mips/irq.o >> endif >> ### >> >> diff --git a/arm/irq.c b/arm/irq.c >> deleted file mode 100644 >> index d8f44df..0000000 >> --- a/arm/irq.c >> +++ /dev/null >> @@ -1,9 +0,0 @@ >> -#include "kvm/irq.h" >> -#include "kvm/kvm.h" >> -#include "kvm/util.h" >> - >> -int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg) >> -{ >> - die(__FUNCTION__); >> - return 0; >> -} >> diff --git a/hw/pci-shmem.c b/hw/pci-shmem.c >> index a1c5ab7..7ce98cb 100644 >> --- a/hw/pci-shmem.c >> +++ b/hw/pci-shmem.c >> @@ -136,6 +136,8 @@ int pci_shmem__get_local_irqfd(struct kvm *kvm) >> >> if (pci_shmem_pci_device.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_ENABLE)) { >> gsi = irq__add_msix_route(kvm, &msix_table[0].msg); >> + if (gsi < 0) >> + return gsi; >> } else { >> gsi = pci_shmem_pci_device.irq_line; >> } >> diff --git a/include/kvm/irq.h b/include/kvm/irq.h >> index 8a78e43..bb71521 100644 >> --- a/include/kvm/irq.h >> +++ b/include/kvm/irq.h >> @@ -10,11 +10,16 @@ >> >> struct kvm; >> >> +extern struct kvm_irq_routing *irq_routing; >> +extern int next_gsi; >> + >> int irq__alloc_line(void); >> int irq__get_nr_allocated_lines(void); >> >> int irq__init(struct kvm *kvm); >> int irq__exit(struct kvm *kvm); >> + >> +int irq__allocate_routing_entry(void); >> int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg); >> >> #endif >> diff --git a/irq.c b/irq.c >> index 71eaa05..c4b481c 100644 >> --- a/irq.c >> +++ b/irq.c >> @@ -1,7 +1,19 @@ >> +#include <stdlib.h> >> +#include <sys/ioctl.h> >> +#include <linux/types.h> >> +#include <linux/kvm.h> >> +#include <errno.h> >> + >> +#include "kvm/kvm.h" >> #include "kvm/irq.h" >> #include "kvm/kvm-arch.h" >> >> static u8 next_line = KVM_IRQ_OFFSET; >> +static int allocated_gsis = 0; >> + >> +int next_gsi; >> + >> +struct kvm_irq_routing *irq_routing = NULL; >> >> int irq__alloc_line(void) >> { >> @@ -12,3 +24,74 @@ int irq__get_nr_allocated_lines(void) >> { >> return next_line - KVM_IRQ_OFFSET; >> } >> + >> +int irq__allocate_routing_entry(void) >> +{ >> + size_t table_size = sizeof(struct kvm_irq_routing); >> + int nr_entries = 0; >> + >> + if (irq_routing) >> + nr_entries = irq_routing->nr; >> + >> + if (nr_entries < allocated_gsis) >> + return 0; >> + >> + allocated_gsis = ALIGN(nr_entries + 1, 32); >> + table_size += sizeof(struct kvm_irq_routing_entry) * allocated_gsis; >> + irq_routing = realloc(irq_routing, table_size); >> + >> + if (irq_routing == NULL) >> + return ENOMEM; > > This should be -ENOMEM. Otherwise when allocate_routing_entry fails, > add_msix_route will return this positive value, which the caller will > confuse with a GSI number. Nice catch! Thanks for that. I fixed the patch and sent out a v8 (which has one or two more fixes). Cheers, Andre. >> + >> + irq_routing->nr = nr_entries; >> + >> + return 0; >> +} >> + >> +static bool check_for_irq_routing(struct kvm *kvm) >> +{ >> + static int has_irq_routing = 0; >> + >> + if (has_irq_routing == 0) { >> + if (kvm__supports_extension(kvm, KVM_CAP_IRQ_ROUTING)) >> + has_irq_routing = 1; >> + else >> + has_irq_routing = -1; >> + } >> + >> + return has_irq_routing > 0; >> +} >> + >> +int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg) >> +{ >> + int r; >> + >> + if (!check_for_irq_routing(kvm)) >> + return -ENXIO; >> + >> + r = irq__allocate_routing_entry(); >> + if (r) >> + return r; >> + >> + irq_routing->entries[irq_routing->nr++] = >> + (struct kvm_irq_routing_entry) { >> + .gsi = next_gsi, >> + .type = KVM_IRQ_ROUTING_MSI, >> + .u.msi.address_hi = msg->address_hi, >> + .u.msi.address_lo = msg->address_lo, >> + .u.msi.data = msg->data, >> + }; >> + >> + r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing); >> + if (r) >> + return r; >> + >> + return next_gsi++; >> +} >> + >> +int __attribute__((weak)) irq__exit(struct kvm *kvm) >> +{ >> + free(irq_routing); >> + return 0; >> +} >> +dev_base_exit(irq__exit); >> diff --git a/mips/irq.c b/mips/irq.c >> deleted file mode 100644 >> index c1ff6bb..0000000 >> --- a/mips/irq.c >> +++ /dev/null >> @@ -1,10 +0,0 @@ >> -#include "kvm/irq.h" >> -#include "kvm/kvm.h" >> - >> -#include <stdlib.h> >> - >> -int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg) >> -{ >> - pr_warning("irq__add_msix_route"); >> - return 1; >> -} >> diff --git a/powerpc/irq.c b/powerpc/irq.c >> deleted file mode 100644 >> index 03f2fe7..0000000 >> --- a/powerpc/irq.c >> +++ /dev/null >> @@ -1,31 +0,0 @@ >> -/* >> - * PPC64 IRQ routines >> - * >> - * Copyright 2011 Matt Evans <matt@xxxxxxxxxx>, IBM Corporation. >> - * >> - * This program is free software; you can redistribute it and/or modify it >> - * under the terms of the GNU General Public License version 2 as published >> - * by the Free Software Foundation. >> - */ >> - >> -#include "kvm/devices.h" >> -#include "kvm/irq.h" >> -#include "kvm/kvm.h" >> -#include "kvm/util.h" >> - >> -#include <linux/types.h> >> -#include <linux/rbtree.h> >> -#include <linux/list.h> >> -#include <linux/kvm.h> >> -#include <sys/ioctl.h> >> - >> -#include <stddef.h> >> -#include <stdlib.h> >> - >> -#include "kvm/pci.h" >> - >> -int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg) >> -{ >> - die(__FUNCTION__); >> - return 0; >> -} >> diff --git a/virtio/pci.c b/virtio/pci.c >> index 90fcd64..072e5b7 100644 >> --- a/virtio/pci.c >> +++ b/virtio/pci.c >> @@ -156,7 +156,8 @@ static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_device *v >> void *data, int size, int offset) >> { >> struct virtio_pci *vpci = vdev->virtio; >> - u32 config_offset, gsi, vec; >> + u32 config_offset, vec; >> + int gsi; >> int type = virtio__get_dev_specific_field(offset - 20, virtio_pci__msix_enabled(vpci), >> &config_offset); >> if (type == VIRTIO_PCI_O_MSIX) { >> @@ -166,21 +167,27 @@ static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_device *v >> if (vec == VIRTIO_MSI_NO_VECTOR) >> break; >> >> - gsi = irq__add_msix_route(kvm, &vpci->msix_table[vec].msg); >> - >> - vpci->config_gsi = gsi; >> + gsi = irq__add_msix_route(kvm, >> + &vpci->msix_table[vec].msg); >> + if (gsi >= 0) >> + vpci->config_gsi = gsi; >> break; >> case VIRTIO_MSI_QUEUE_VECTOR: >> - vec = vpci->vq_vector[vpci->queue_selector] = ioport__read16(data); >> + vec = ioport__read16(data); >> + vpci->vq_vector[vpci->queue_selector] = vec; >> >> if (vec == VIRTIO_MSI_NO_VECTOR) >> break; >> >> - gsi = irq__add_msix_route(kvm, &vpci->msix_table[vec].msg); >> + gsi = irq__add_msix_route(kvm, >> + &vpci->msix_table[vec].msg); >> + if (gsi < 0) >> + break; >> vpci->gsis[vpci->queue_selector] = gsi; >> if (vdev->ops->notify_vq_gsi) >> vdev->ops->notify_vq_gsi(kvm, vpci->dev, >> - vpci->queue_selector, gsi); >> + vpci->queue_selector, >> + gsi); >> break; >> }; >> >> diff --git a/x86/irq.c b/x86/irq.c >> index 72177e7..db465a1 100644 >> --- a/x86/irq.c >> +++ b/x86/irq.c >> @@ -11,20 +11,15 @@ >> #include <stddef.h> >> #include <stdlib.h> >> >> -#define IRQ_MAX_GSI 64 >> #define IRQCHIP_MASTER 0 >> #define IRQCHIP_SLAVE 1 >> #define IRQCHIP_IOAPIC 2 >> >> -/* First 24 GSIs are routed between IRQCHIPs and IOAPICs */ >> -static u32 gsi = 24; >> - >> -struct kvm_irq_routing *irq_routing; >> - >> static int irq__add_routing(u32 gsi, u32 type, u32 irqchip, u32 pin) >> { >> - if (gsi >= IRQ_MAX_GSI) >> - return -ENOSPC; >> + int r = irq__allocate_routing_entry(); >> + if (r) >> + return r; >> >> irq_routing->entries[irq_routing->nr++] = >> (struct kvm_irq_routing_entry) { >> @@ -41,11 +36,6 @@ int irq__init(struct kvm *kvm) >> { >> int i, r; >> >> - irq_routing = calloc(sizeof(struct kvm_irq_routing) + >> - IRQ_MAX_GSI * sizeof(struct kvm_irq_routing_entry), 1); >> - if (irq_routing == NULL) >> - return -ENOMEM; >> - >> /* Hook first 8 GSIs to master IRQCHIP */ >> for (i = 0; i < 8; i++) >> if (i != 2) >> @@ -69,33 +59,8 @@ int irq__init(struct kvm *kvm) >> return errno; >> } >> >> - return 0; >> -} >> -dev_base_init(irq__init); >> + next_gsi = i; >> >> -int irq__exit(struct kvm *kvm) >> -{ >> - free(irq_routing); >> return 0; >> } >> -dev_base_exit(irq__exit); >> - >> -int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg) >> -{ >> - int r; >> - >> - irq_routing->entries[irq_routing->nr++] = >> - (struct kvm_irq_routing_entry) { >> - .gsi = gsi, >> - .type = KVM_IRQ_ROUTING_MSI, >> - .u.msi.address_hi = msg->address_hi, >> - .u.msi.address_lo = msg->address_lo, >> - .u.msi.data = msg->data, >> - }; >> - >> - r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing); >> - if (r) >> - return r; >> - >> - return gsi++; >> -} >> +dev_base_init(irq__init); >> > -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html