[PATCH v7 03/15] irq: move IRQ routing into irq.c
Jean-Philippe Brucker
jean-philippe.brucker at arm.com
Wed Nov 2 07:37:23 PDT 2016
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 at arm.com>
> ---
> 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.
Thanks,
Jean-Philippe
> +
> + 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 at ozlabs.org>, 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);
>
More information about the linux-arm-kernel
mailing list