kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
To: kvm@vger.kernel.org
Cc: will.deacon@arm.com, robin.murphy@arm.com,
	lorenzo.pieralisi@arm.com, marc.zyngier@arm.com
Subject: [PATCH v2 kvmtool 03/10] irq: add irqfd helpers
Date: Thu, 22 Jun 2017 18:05:29 +0100	[thread overview]
Message-ID: <20170622170536.14319-4-jean-philippe.brucker@arm.com> (raw)
In-Reply-To: <20170622170536.14319-1-jean-philippe.brucker@arm.com>

Add helpers to add and remove IRQFD routing for both irqchips and MSIs.
We have to make a special case of IRQ lines on ARM where the
initialisation order goes like this:

 (1) Devices reserve their IRQ lines
 (2) VGIC is setup with VGIC_CTRL_INIT (in a late_init call)
 (3) MSIs are reserved lazily, when the guest needs them

Since we cannot setup IRQFD before (2), store the IRQFD routing for IRQ
lines temporarily until we're ready to submit them.

Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
---
 arm/gic.c                    | 74 +++++++++++++++++++++++++++++++++++++++++++-
 arm/include/arm-common/gic.h |  6 ++++
 hw/pci-shmem.c               |  8 +----
 include/kvm/irq.h            | 17 ++++++++++
 irq.c                        | 24 ++++++++++++++
 virtio/net.c                 |  9 ++----
 virtio/scsi.c                | 10 ++----
 7 files changed, 126 insertions(+), 22 deletions(-)

diff --git a/arm/gic.c b/arm/gic.c
index 9de6a9c9..e53f932e 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -17,6 +17,14 @@ static u64 gic_redists_base;
 static u64 gic_redists_size;
 static u64 gic_msi_base;
 static u64 gic_msi_size = 0;
+static bool vgic_is_init = false;
+
+struct kvm_irqfd_line {
+	struct kvm_irqfd	irqfd;
+	struct list_head	list;
+};
+
+static LIST_HEAD(irqfd_lines);
 
 int irqchip_parser(const struct option *opt, const char *arg, int unset)
 {
@@ -36,6 +44,25 @@ int irqchip_parser(const struct option *opt, const char *arg, int unset)
 	return 0;
 }
 
+static int irq__setup_irqfd_lines(struct kvm *kvm)
+{
+	int ret;
+	struct kvm_irqfd_line *line, *tmp;
+
+	list_for_each_entry_safe(line, tmp, &irqfd_lines, list) {
+		ret = ioctl(kvm->vm_fd, KVM_IRQFD, &line->irqfd);
+		if (ret < 0) {
+			pr_err("Failed to register IRQFD");
+			return ret;
+		}
+
+		list_del(&line->list);
+		free(line);
+	}
+
+	return 0;
+}
+
 static int irq__routing_init(struct kvm *kvm)
 {
 	int r;
@@ -282,7 +309,9 @@ static int gic__init_gic(struct kvm *kvm)
 	kvm->msix_needs_devid = kvm__supports_vm_extension(kvm,
 							   KVM_CAP_MSI_DEVID);
 
-	return 0;
+	vgic_is_init = true;
+
+	return irq__setup_irqfd_lines(kvm);
 }
 late_init(gic__init_gic)
 
@@ -359,3 +388,46 @@ void kvm__irq_trigger(struct kvm *kvm, int irq)
 	kvm__irq_line(kvm, irq, VIRTIO_IRQ_HIGH);
 	kvm__irq_line(kvm, irq, VIRTIO_IRQ_LOW);
 }
+
+int gic__add_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd,
+		   int resample_fd)
+{
+	struct kvm_irqfd_line *line;
+
+	if (vgic_is_init)
+		return irq__common_add_irqfd(kvm, gsi, trigger_fd, resample_fd);
+
+	/* Postpone the routing setup until we have a distributor */
+	line = calloc(1, sizeof(*line));
+	if (!line)
+		return -ENOMEM;
+
+	line->irqfd = (struct kvm_irqfd) {
+		.fd = trigger_fd,
+		.gsi = gsi,
+		.flags = resample_fd > 0 ? KVM_IRQFD_FLAG_RESAMPLE : 0,
+		.resamplefd = resample_fd,
+	};
+	list_add(&line->list, &irqfd_lines);
+
+	return 0;
+}
+
+void gic__del_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd)
+{
+	struct kvm_irqfd_line *line;
+
+	if (vgic_is_init) {
+		irq__common_del_irqfd(kvm, gsi, trigger_fd);
+		return;
+	}
+
+	list_for_each_entry(line, &irqfd_lines, list) {
+		if (line->irqfd.gsi != gsi)
+			continue;
+
+		list_del(&line->list);
+		free(line);
+		break;
+	}
+}
diff --git a/arm/include/arm-common/gic.h b/arm/include/arm-common/gic.h
index 433dd237..0c279aca 100644
--- a/arm/include/arm-common/gic.h
+++ b/arm/include/arm-common/gic.h
@@ -33,4 +33,10 @@ int gic__alloc_irqnum(void);
 int gic__create(struct kvm *kvm, enum irqchip_type type);
 void gic__generate_fdt_nodes(void *fdt, enum irqchip_type type);
 
+int gic__add_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd,
+		   int resample_fd);
+void gic__del_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd);
+#define irq__add_irqfd gic__add_irqfd
+#define irq__del_irqfd gic__del_irqfd
+
 #endif /* ARM_COMMON__GIC_H */
diff --git a/hw/pci-shmem.c b/hw/pci-shmem.c
index 512b5b06..107043e9 100644
--- a/hw/pci-shmem.c
+++ b/hw/pci-shmem.c
@@ -127,7 +127,6 @@ static void callback_mmio_msix(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len
 int pci_shmem__get_local_irqfd(struct kvm *kvm)
 {
 	int fd, gsi, r;
-	struct kvm_irqfd irqfd;
 
 	if (local_fd == 0) {
 		fd = eventfd(0, 0);
@@ -143,12 +142,7 @@ int pci_shmem__get_local_irqfd(struct kvm *kvm)
 			gsi = pci_shmem_pci_device.irq_line;
 		}
 
-		irqfd = (struct kvm_irqfd) {
-			.fd = fd,
-			.gsi = gsi,
-		};
-
-		r = ioctl(kvm->vm_fd, KVM_IRQFD, &irqfd);
+		r = irq__add_irqfd(kvm, gsi, fd, -1);
 		if (r < 0)
 			return r;
 
diff --git a/include/kvm/irq.h b/include/kvm/irq.h
index ee059e31..b24385b1 100644
--- a/include/kvm/irq.h
+++ b/include/kvm/irq.h
@@ -6,6 +6,7 @@
 #include <linux/list.h>
 #include <linux/kvm.h>
 
+#include "kvm/kvm-arch.h"
 #include "kvm/msi.h"
 
 struct kvm;
@@ -23,4 +24,20 @@ int irq__allocate_routing_entry(void);
 int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg, u32 device_id);
 void irq__update_msix_route(struct kvm *kvm, u32 gsi, struct msi_msg *msg);
 
+/*
+ * The function takes two eventfd arguments, trigger_fd and resample_fd. If
+ * resample_fd is <= 0, resampling is disabled and the IRQ is edge-triggered
+ */
+int irq__common_add_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd,
+			   int resample_fd);
+void irq__common_del_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd);
+
+#ifndef irq__add_irqfd
+#define irq__add_irqfd irq__common_add_irqfd
+#endif
+
+#ifndef irq__del_irqfd
+#define irq__del_irqfd irq__common_del_irqfd
+#endif
+
 #endif
diff --git a/irq.c b/irq.c
index 44040626..25fa5727 100644
--- a/irq.c
+++ b/irq.c
@@ -133,6 +133,30 @@ void irq__update_msix_route(struct kvm *kvm, u32 gsi, struct msi_msg *msg)
 		die_perror("KVM_SET_GSI_ROUTING");
 }
 
+int irq__common_add_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd,
+			   int resample_fd)
+{
+	struct kvm_irqfd irqfd = {
+		.fd		= trigger_fd,
+		.gsi		= gsi,
+		.flags		= resample_fd > 0 ? KVM_IRQFD_FLAG_RESAMPLE : 0,
+		.resamplefd	= resample_fd,
+	};
+
+	return ioctl(kvm->vm_fd, KVM_IRQFD, &irqfd);
+}
+
+void irq__common_del_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd)
+{
+	struct kvm_irqfd irqfd = {
+		.fd		= trigger_fd,
+		.gsi		= gsi,
+		.flags		= KVM_IRQFD_FLAG_DEASSIGN,
+	};
+
+	ioctl(kvm->vm_fd, KVM_IRQFD, &irqfd);
+}
+
 int __attribute__((weak)) irq__exit(struct kvm *kvm)
 {
 	free(irq_routing);
diff --git a/virtio/net.c b/virtio/net.c
index 9fb9f1ee..52645481 100644
--- a/virtio/net.c
+++ b/virtio/net.c
@@ -558,23 +558,18 @@ static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 page_size, u32 align,
 static void notify_vq_gsi(struct kvm *kvm, void *dev, u32 vq, u32 gsi)
 {
 	struct net_dev *ndev = dev;
-	struct kvm_irqfd irq;
 	struct vhost_vring_file file;
 	int r;
 
 	if (ndev->vhost_fd == 0)
 		return;
 
-	irq = (struct kvm_irqfd) {
-		.gsi	= gsi,
-		.fd	= eventfd(0, 0),
-	};
 	file = (struct vhost_vring_file) {
 		.index	= vq,
-		.fd	= irq.fd,
+		.fd	= eventfd(0, 0),
 	};
 
-	r = ioctl(kvm->vm_fd, KVM_IRQFD, &irq);
+	r = irq__add_irqfd(kvm, gsi, file.fd, -1);
 	if (r < 0)
 		die_perror("KVM_IRQFD failed");
 
diff --git a/virtio/scsi.c b/virtio/scsi.c
index 58d2353a..a429ac85 100644
--- a/virtio/scsi.c
+++ b/virtio/scsi.c
@@ -1,6 +1,7 @@
 #include "kvm/virtio-scsi.h"
 #include "kvm/virtio-pci-dev.h"
 #include "kvm/disk-image.h"
+#include "kvm/irq.h"
 #include "kvm/kvm.h"
 #include "kvm/pci.h"
 #include "kvm/ioeventfd.h"
@@ -97,22 +98,17 @@ static void notify_vq_gsi(struct kvm *kvm, void *dev, u32 vq, u32 gsi)
 {
 	struct vhost_vring_file file;
 	struct scsi_dev *sdev = dev;
-	struct kvm_irqfd irq;
 	int r;
 
 	if (sdev->vhost_fd == 0)
 		return;
 
-	irq = (struct kvm_irqfd) {
-		.gsi	= gsi,
-		.fd	= eventfd(0, 0),
-	};
 	file = (struct vhost_vring_file) {
 		.index	= vq,
-		.fd	= irq.fd,
+		.fd	= eventfd(0, 0),
 	};
 
-	r = ioctl(kvm->vm_fd, KVM_IRQFD, &irq);
+	r = irq__add_irqfd(kvm, gsi, file.fd, -1);
 	if (r < 0)
 		die_perror("KVM_IRQFD failed");
 
-- 
2.13.1

  parent reply	other threads:[~2017-06-22 17:04 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-22 17:05 [PATCH v2 kvmtool 00/10] Add PCI passthrough support with VFIO Jean-Philippe Brucker
2017-06-22 17:05 ` [PATCH v2 kvmtool 01/10] pci: add config operations callbacks on the PCI header Jean-Philippe Brucker
2017-06-22 17:05 ` [PATCH v2 kvmtool 02/10] pci: allow to specify IRQ type for PCI devices Jean-Philippe Brucker
2017-06-22 17:05 ` Jean-Philippe Brucker [this message]
2017-07-31 17:55   ` [PATCH v2 kvmtool 03/10] irq: add irqfd helpers Punit Agrawal
2017-08-02 15:17     ` Jean-Philippe Brucker
2017-06-22 17:05 ` [PATCH v2 kvmtool 04/10] Extend memory bank API with memory types Jean-Philippe Brucker
2017-06-22 17:05 ` [PATCH v2 kvmtool 05/10] pci: add capability helpers Jean-Philippe Brucker
2017-06-22 17:05 ` [PATCH v2 kvmtool 06/10] Add PCI device passthrough using VFIO Jean-Philippe Brucker
2017-07-31 17:52   ` Punit Agrawal
2017-08-02 15:17     ` Jean-Philippe Brucker
2017-08-03  9:36       ` Punit Agrawal
2017-08-03 11:24         ` Jean-Philippe Brucker
2017-06-22 17:05 ` [PATCH v2 kvmtool 07/10] vfio-pci: add MSI-X support Jean-Philippe Brucker
2017-07-31 17:49   ` Punit Agrawal
2017-08-01 16:04     ` Punit Agrawal
2017-08-02 15:18       ` Jean-Philippe Brucker
2017-08-03 10:25         ` Punit Agrawal
2017-08-03 10:53           ` Jean-Philippe Brucker
2017-08-18 17:42   ` Jean-Philippe Brucker
2017-08-22 11:25     ` Punit Agrawal
2017-06-22 17:05 ` [PATCH v2 kvmtool 08/10] vfio-pci: add MSI support Jean-Philippe Brucker
2017-06-22 17:05 ` [PATCH v2 kvmtool 09/10] Introduce reserved memory regions Jean-Philippe Brucker
2017-06-22 17:05 ` [PATCH v2 kvmtool 10/10] vfio: check reserved regions before mapping DMA Jean-Philippe Brucker

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170622170536.14319-4-jean-philippe.brucker@arm.com \
    --to=jean-philippe.brucker@arm.com \
    --cc=kvm@vger.kernel.org \
    --cc=lorenzo.pieralisi@arm.com \
    --cc=marc.zyngier@arm.com \
    --cc=robin.murphy@arm.com \
    --cc=will.deacon@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).