All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC v2 0/4] VFIO Platform device featuring IRQ forwarding
@ 2015-05-04 12:49 ` Eric Auger
  0 siblings, 0 replies; 10+ messages in thread
From: Eric Auger @ 2015-05-04 12:49 UTC (permalink / raw)
  To: eric.auger, eric.auger, qemu-devel, alex.williamson
  Cc: b.reynal, kvmarm, christoffer.dall, patches

This series adds IRQ forwarding support in the VFIO platform device.

The VFIO platform device uses the KVM-VFIO device to enable IRQ forwarding.

Dependency List:
- QEMU KVM platform device passthrough and its dependencies
  see https://lists.gnu.org/archive/html/qemu-devel/2015-04/msg04379.html
- kernel forwarding series:
  see (https://www.mail-archive.com/kvm@vger.kernel.org/msg115253.html)

Repos:
- QEMU pieces can be found at:
  http://git.linaro.org/people/eric.auger/qemu.git
  (branch vfio_integ_v15_fwd)
- kernel pieces can be found at:
  http://git.linaro.org/people/eric.auger/linux.git
  (branch 4.1-rc1_forward)

The patch series was tested on Calxeda Midway (ARMv7) where one xgmac
is assigned to KVM host while the second one is assigned to the guest.
Reworked PCI device is not tested.

Wiki for Calxeda Midway setup:
https://wiki.linaro.org/LEG/Engineering/Virtualization/Platform_Device_Passthrough_on_Midway

History:

v1 -> v2:
- update following
  x introduction of kvm qemu_irq/gsi hash table
  x new irq connect notifier
  x 2 stage eventfd/irqfd setup which complexifies irq forwarding setup

v1:
- that code originally was in KVM platform device passthrough series (v8),
  now moved in a separate RFC since dependent on many RFCs.

Best Regards

Eric


Eric Auger (4):
  linux-headers: Update KVM header for KVM-VFIO FORWARD/UNFORWARD
  hw/vfio/common: vfio_kvm_device_fd moved in the common header
  kvm: add kvm_vfio_get_device_irq
  hw/vfio/platform: add forwarded irq support

 hw/vfio/common.c                |   2 +-
 hw/vfio/platform.c              | 103 +++++++++++++++++++++++++++++++++++++---
 include/hw/vfio/vfio-common.h   |   4 ++
 include/hw/vfio/vfio-platform.h |   3 ++
 include/sysemu/kvm.h            |   5 ++
 kvm-all.c                       |  32 +++++++++++++
 linux-headers/linux/kvm.h       |  12 +++++
 trace-events                    |   1 +
 8 files changed, 154 insertions(+), 8 deletions(-)

-- 
1.8.3.2

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC v2 0/4] VFIO Platform device featuring IRQ forwarding
@ 2015-05-04 12:49 ` Eric Auger
  0 siblings, 0 replies; 10+ messages in thread
From: Eric Auger @ 2015-05-04 12:49 UTC (permalink / raw)
  To: eric.auger, eric.auger, qemu-devel, alex.williamson; +Cc: kvmarm, patches

This series adds IRQ forwarding support in the VFIO platform device.

The VFIO platform device uses the KVM-VFIO device to enable IRQ forwarding.

Dependency List:
- QEMU KVM platform device passthrough and its dependencies
  see https://lists.gnu.org/archive/html/qemu-devel/2015-04/msg04379.html
- kernel forwarding series:
  see (https://www.mail-archive.com/kvm@vger.kernel.org/msg115253.html)

Repos:
- QEMU pieces can be found at:
  http://git.linaro.org/people/eric.auger/qemu.git
  (branch vfio_integ_v15_fwd)
- kernel pieces can be found at:
  http://git.linaro.org/people/eric.auger/linux.git
  (branch 4.1-rc1_forward)

The patch series was tested on Calxeda Midway (ARMv7) where one xgmac
is assigned to KVM host while the second one is assigned to the guest.
Reworked PCI device is not tested.

Wiki for Calxeda Midway setup:
https://wiki.linaro.org/LEG/Engineering/Virtualization/Platform_Device_Passthrough_on_Midway

History:

v1 -> v2:
- update following
  x introduction of kvm qemu_irq/gsi hash table
  x new irq connect notifier
  x 2 stage eventfd/irqfd setup which complexifies irq forwarding setup

v1:
- that code originally was in KVM platform device passthrough series (v8),
  now moved in a separate RFC since dependent on many RFCs.

Best Regards

Eric


Eric Auger (4):
  linux-headers: Update KVM header for KVM-VFIO FORWARD/UNFORWARD
  hw/vfio/common: vfio_kvm_device_fd moved in the common header
  kvm: add kvm_vfio_get_device_irq
  hw/vfio/platform: add forwarded irq support

 hw/vfio/common.c                |   2 +-
 hw/vfio/platform.c              | 103 +++++++++++++++++++++++++++++++++++++---
 include/hw/vfio/vfio-common.h   |   4 ++
 include/hw/vfio/vfio-platform.h |   3 ++
 include/sysemu/kvm.h            |   5 ++
 kvm-all.c                       |  32 +++++++++++++
 linux-headers/linux/kvm.h       |  12 +++++
 trace-events                    |   1 +
 8 files changed, 154 insertions(+), 8 deletions(-)

-- 
1.8.3.2

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Qemu-devel] [RFC v2 1/4] linux-headers: Update KVM header for KVM-VFIO FORWARD/UNFORWARD
  2015-05-04 12:49 ` Eric Auger
@ 2015-05-04 12:49   ` Eric Auger
  -1 siblings, 0 replies; 10+ messages in thread
From: Eric Auger @ 2015-05-04 12:49 UTC (permalink / raw)
  To: eric.auger, eric.auger, qemu-devel, alex.williamson
  Cc: b.reynal, kvmarm, christoffer.dall, patches

Integrate updated KVM-VFIO API related to forwarded IRQ

Update the kvm header according to the header found in
http://git.linaro.org/people/eric.auger/linux.git
branch 4.1-rc1_forward

Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
 linux-headers/linux/kvm.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index b96d978..95fea92 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -999,6 +999,9 @@ struct kvm_device_attr {
 #define  KVM_DEV_VFIO_GROUP			1
 #define   KVM_DEV_VFIO_GROUP_ADD			1
 #define   KVM_DEV_VFIO_GROUP_DEL			2
+#define  KVM_DEV_VFIO_DEVICE			2
+#define   KVM_DEV_VFIO_DEVICE_FORWARD_IRQ			1
+#define   KVM_DEV_VFIO_DEVICE_UNFORWARD_IRQ			2
 
 enum kvm_device_type {
 	KVM_DEV_TYPE_FSL_MPIC_20	= 1,
@@ -1018,6 +1021,15 @@ enum kvm_device_type {
 	KVM_DEV_TYPE_MAX,
 };
 
+struct kvm_vfio_dev_irq {
+	__u32	argsz;		/* structure length */
+	__u32	fd;		/* file descriptor of the VFIO device */
+	__u32	index;		/* VFIO device IRQ index */
+	__u32	start;		/* start of subindex range */
+	__u32	count;		/* size of subindex range */
+	__u32	gsi[];		/* gsi, ie. virtual IRQ number */
+};
+
 /*
  * ioctls for VM fds
  */
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC v2 1/4] linux-headers: Update KVM header for KVM-VFIO FORWARD/UNFORWARD
@ 2015-05-04 12:49   ` Eric Auger
  0 siblings, 0 replies; 10+ messages in thread
From: Eric Auger @ 2015-05-04 12:49 UTC (permalink / raw)
  To: eric.auger, eric.auger, qemu-devel, alex.williamson; +Cc: kvmarm, patches

Integrate updated KVM-VFIO API related to forwarded IRQ

Update the kvm header according to the header found in
http://git.linaro.org/people/eric.auger/linux.git
branch 4.1-rc1_forward

Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
 linux-headers/linux/kvm.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index b96d978..95fea92 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -999,6 +999,9 @@ struct kvm_device_attr {
 #define  KVM_DEV_VFIO_GROUP			1
 #define   KVM_DEV_VFIO_GROUP_ADD			1
 #define   KVM_DEV_VFIO_GROUP_DEL			2
+#define  KVM_DEV_VFIO_DEVICE			2
+#define   KVM_DEV_VFIO_DEVICE_FORWARD_IRQ			1
+#define   KVM_DEV_VFIO_DEVICE_UNFORWARD_IRQ			2
 
 enum kvm_device_type {
 	KVM_DEV_TYPE_FSL_MPIC_20	= 1,
@@ -1018,6 +1021,15 @@ enum kvm_device_type {
 	KVM_DEV_TYPE_MAX,
 };
 
+struct kvm_vfio_dev_irq {
+	__u32	argsz;		/* structure length */
+	__u32	fd;		/* file descriptor of the VFIO device */
+	__u32	index;		/* VFIO device IRQ index */
+	__u32	start;		/* start of subindex range */
+	__u32	count;		/* size of subindex range */
+	__u32	gsi[];		/* gsi, ie. virtual IRQ number */
+};
+
 /*
  * ioctls for VM fds
  */
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [RFC v2 2/4] hw/vfio/common: vfio_kvm_device_fd moved in the common header
  2015-05-04 12:49 ` Eric Auger
@ 2015-05-04 12:49   ` Eric Auger
  -1 siblings, 0 replies; 10+ messages in thread
From: Eric Auger @ 2015-05-04 12:49 UTC (permalink / raw)
  To: eric.auger, eric.auger, qemu-devel, alex.williamson
  Cc: b.reynal, kvmarm, christoffer.dall, patches

the device is now used in platform for forwarded IRQ setup

Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
 hw/vfio/common.c              | 2 +-
 include/hw/vfio/vfio-common.h | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index b012620..18ad67c 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -44,7 +44,7 @@ struct vfio_as_head vfio_address_spaces =
  * initialized, this file descriptor is only released on QEMU exit and
  * we'll re-use it should another vfio device be attached before then.
  */
-static int vfio_kvm_device_fd = -1;
+int vfio_kvm_device_fd = -1;
 #endif
 
 /*
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index 59a321d..53d0e68 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -40,6 +40,10 @@
 #define VFIO_ALLOW_KVM_MSI 1
 #define VFIO_ALLOW_KVM_MSIX 1
 
+#ifdef CONFIG_KVM
+extern int vfio_kvm_device_fd;
+#endif
+
 enum {
     VFIO_DEVICE_TYPE_PCI = 0,
     VFIO_DEVICE_TYPE_PLATFORM = 1,
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC v2 2/4] hw/vfio/common: vfio_kvm_device_fd moved in the common header
@ 2015-05-04 12:49   ` Eric Auger
  0 siblings, 0 replies; 10+ messages in thread
From: Eric Auger @ 2015-05-04 12:49 UTC (permalink / raw)
  To: eric.auger, eric.auger, qemu-devel, alex.williamson; +Cc: kvmarm, patches

the device is now used in platform for forwarded IRQ setup

Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
 hw/vfio/common.c              | 2 +-
 include/hw/vfio/vfio-common.h | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index b012620..18ad67c 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -44,7 +44,7 @@ struct vfio_as_head vfio_address_spaces =
  * initialized, this file descriptor is only released on QEMU exit and
  * we'll re-use it should another vfio device be attached before then.
  */
-static int vfio_kvm_device_fd = -1;
+int vfio_kvm_device_fd = -1;
 #endif
 
 /*
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index 59a321d..53d0e68 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -40,6 +40,10 @@
 #define VFIO_ALLOW_KVM_MSI 1
 #define VFIO_ALLOW_KVM_MSIX 1
 
+#ifdef CONFIG_KVM
+extern int vfio_kvm_device_fd;
+#endif
+
 enum {
     VFIO_DEVICE_TYPE_PCI = 0,
     VFIO_DEVICE_TYPE_PLATFORM = 1,
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [RFC v2 3/4] kvm: add kvm_vfio_get_device_irq
  2015-05-04 12:49 ` Eric Auger
@ 2015-05-04 12:49   ` Eric Auger
  -1 siblings, 0 replies; 10+ messages in thread
From: Eric Auger @ 2015-05-04 12:49 UTC (permalink / raw)
  To: eric.auger, eric.auger, qemu-devel, alex.williamson
  Cc: b.reynal, kvmarm, christoffer.dall, patches

Since the introduction of the qemu_irq/gsi hash table in kvm,
the gsi information is stored in kvm. New functions are introduced
to allocate/populate a kvm_vfio_dev_irq struct pointer from a
qemu_irq object and free it.

Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
 include/sysemu/kvm.h |  5 +++++
 kvm-all.c            | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index bc3f230..42cc6c4 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -423,6 +423,11 @@ int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
 int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n,
                                       qemu_irq irq);
 void kvm_irqchip_set_qemuirq_gsi(KVMState *s, qemu_irq irq, int gsi);
+struct kvm_vfio_dev_irq;
+int kvm_vfio_get_device_irq(KVMState *s, int fd, int index,
+                            int start, int count, qemu_irq irq,
+                            struct kvm_vfio_dev_irq **vfio_dev_irq);
+void kvm_vfio_put_device_irq(struct kvm_vfio_dev_irq *vfio_dev_irq);
 void kvm_pc_gsi_handler(void *opaque, int n, int level);
 void kvm_pc_setup_irq_routing(bool pci_enabled);
 void kvm_init_irq_routing(KVMState *s);
diff --git a/kvm-all.c b/kvm-all.c
index d2cb7ed..83a9689 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1454,6 +1454,38 @@ static int kvm_irqchip_create(MachineState *machine, KVMState *s)
     return 0;
 }
 
+int kvm_vfio_get_device_irq(KVMState *s, int fd, int index,
+                            int start, int count, qemu_irq irq,
+                            struct kvm_vfio_dev_irq **vfio_dev_irq)
+{
+    gpointer key, gsi;
+    gboolean found = g_hash_table_lookup_extended(s->gsimap, irq, &key, &gsi);
+    struct kvm_vfio_dev_irq *pirq;
+    __u32 *pgsi;
+    int argsz;
+
+    if (!found) {
+        return -ENXIO;
+    }
+
+    argsz = sizeof(*pirq) + sizeof(*pgsi);
+    pirq = g_malloc0(argsz);
+    pirq->argsz = argsz;
+    pirq->fd = fd;
+    pirq->index = index;
+    pirq->start = start;
+    pirq->count = count;
+    pgsi = (__u32 *)&pirq->gsi;
+    *pgsi = GPOINTER_TO_INT(gsi);
+    *vfio_dev_irq = pirq;
+    return 0;
+}
+
+void kvm_vfio_put_device_irq(struct kvm_vfio_dev_irq *vfio_dev_irq)
+{
+    g_free(vfio_dev_irq);
+}
+
 /* Find number of supported CPUs using the recommended
  * procedure from the kernel API documentation to cope with
  * older kernels that may be missing capabilities.
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC v2 3/4] kvm: add kvm_vfio_get_device_irq
@ 2015-05-04 12:49   ` Eric Auger
  0 siblings, 0 replies; 10+ messages in thread
From: Eric Auger @ 2015-05-04 12:49 UTC (permalink / raw)
  To: eric.auger, eric.auger, qemu-devel, alex.williamson; +Cc: kvmarm, patches

Since the introduction of the qemu_irq/gsi hash table in kvm,
the gsi information is stored in kvm. New functions are introduced
to allocate/populate a kvm_vfio_dev_irq struct pointer from a
qemu_irq object and free it.

Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
 include/sysemu/kvm.h |  5 +++++
 kvm-all.c            | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index bc3f230..42cc6c4 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -423,6 +423,11 @@ int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
 int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n,
                                       qemu_irq irq);
 void kvm_irqchip_set_qemuirq_gsi(KVMState *s, qemu_irq irq, int gsi);
+struct kvm_vfio_dev_irq;
+int kvm_vfio_get_device_irq(KVMState *s, int fd, int index,
+                            int start, int count, qemu_irq irq,
+                            struct kvm_vfio_dev_irq **vfio_dev_irq);
+void kvm_vfio_put_device_irq(struct kvm_vfio_dev_irq *vfio_dev_irq);
 void kvm_pc_gsi_handler(void *opaque, int n, int level);
 void kvm_pc_setup_irq_routing(bool pci_enabled);
 void kvm_init_irq_routing(KVMState *s);
diff --git a/kvm-all.c b/kvm-all.c
index d2cb7ed..83a9689 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1454,6 +1454,38 @@ static int kvm_irqchip_create(MachineState *machine, KVMState *s)
     return 0;
 }
 
+int kvm_vfio_get_device_irq(KVMState *s, int fd, int index,
+                            int start, int count, qemu_irq irq,
+                            struct kvm_vfio_dev_irq **vfio_dev_irq)
+{
+    gpointer key, gsi;
+    gboolean found = g_hash_table_lookup_extended(s->gsimap, irq, &key, &gsi);
+    struct kvm_vfio_dev_irq *pirq;
+    __u32 *pgsi;
+    int argsz;
+
+    if (!found) {
+        return -ENXIO;
+    }
+
+    argsz = sizeof(*pirq) + sizeof(*pgsi);
+    pirq = g_malloc0(argsz);
+    pirq->argsz = argsz;
+    pirq->fd = fd;
+    pirq->index = index;
+    pirq->start = start;
+    pirq->count = count;
+    pgsi = (__u32 *)&pirq->gsi;
+    *pgsi = GPOINTER_TO_INT(gsi);
+    *vfio_dev_irq = pirq;
+    return 0;
+}
+
+void kvm_vfio_put_device_irq(struct kvm_vfio_dev_irq *vfio_dev_irq)
+{
+    g_free(vfio_dev_irq);
+}
+
 /* Find number of supported CPUs using the recommended
  * procedure from the kernel API documentation to cope with
  * older kernels that may be missing capabilities.
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [RFC v2 4/4] hw/vfio/platform: add forwarded irq support
  2015-05-04 12:49 ` Eric Auger
@ 2015-05-04 12:49   ` Eric Auger
  -1 siblings, 0 replies; 10+ messages in thread
From: Eric Auger @ 2015-05-04 12:49 UTC (permalink / raw)
  To: eric.auger, eric.auger, qemu-devel, alex.williamson
  Cc: b.reynal, kvmarm, christoffer.dall, patches

Tests whether the forwarded IRQ modality is available.
In the positive device IRQs are forwarded. This control is
achieved with KVM-VFIO device. with such a modality injection
still is handled through irqfds. However end of interrupt is
not trapped anymore. As soon as the guest completes its virtual
IRQ, the corresponding physical IRQ is completed and the same
physical IRQ can hit again.

A new x-forward property enables to force forwarding off although
enabled by the kernel.

Signed-off-by: Eric Auger <eric.auger@linaro.org>

---

v1 -> v2:
- use kvm_vfio_get|put_device_irq, new irq connect notifier and
  integrate with 2 stage eventfd/irqfd setup

v1:
- moved in a separate series

v8 -> v9 (KVM platform device passthrough series):
- use new kvm_vfio_dev_irq struct

Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
 hw/vfio/platform.c              | 103 +++++++++++++++++++++++++++++++++++++---
 include/hw/vfio/vfio-platform.h |   3 ++
 trace-events                    |   1 +
 3 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
index 901b98e..52c6d59 100644
--- a/hw/vfio/platform.c
+++ b/hw/vfio/platform.c
@@ -411,6 +411,88 @@ fail_irqfd:
     return;
 }
 
+/*
+ * Functions used with forwarding capability
+ */
+
+static bool has_kvm_vfio_forward_capability(void)
+{
+    struct kvm_device_attr attr = {
+         .group = KVM_DEV_VFIO_DEVICE,
+         .attr = KVM_DEV_VFIO_DEVICE_FORWARD_IRQ};
+
+    if (ioctl(vfio_kvm_device_fd, KVM_HAS_DEVICE_ATTR, &attr) == 0) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+static void vfio_start_forward_injection(SysBusDevice *sbdev, qemu_irq irq)
+{
+    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
+    VFIOINTp *intp;
+    bool found = false;
+    struct kvm_device_attr attr = {
+         .group = KVM_DEV_VFIO_DEVICE,
+         .attr = KVM_DEV_VFIO_DEVICE_FORWARD_IRQ};
+
+    QLIST_FOREACH(intp, &vdev->intp_list, next) {
+        if (intp->qemuirq == irq) {
+            found  = true;
+            break;
+        }
+    }
+    assert(found);
+
+    if (intp->forwarded) {
+        return;
+    }
+
+    /*
+     * stop VFIO signaling and unmask the physical IRQ since
+     * forwarding cannot be set if the IRQ is active or vfio masked
+     */
+    vfio_disable_irqindex(&intp->vdev->vbasedev, intp->pin);
+    vfio_unmask_single_irqindex(&intp->vdev->vbasedev, intp->pin);
+
+    kvm_vfio_get_device_irq(kvm_state, intp->vdev->vbasedev.fd,
+                            intp->pin, 0, 1, intp->qemuirq, &intp->fwd_irq);
+
+    attr.addr = (uint64_t)(unsigned long)intp->fwd_irq;
+
+    if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr) < 0) {
+        error_report("vfio: failed to forward irq %d, do standard irqfd",
+                     intp->pin);
+        kvm_vfio_put_device_irq(intp->fwd_irq);
+    } else {
+        trace_vfio_platform_start_fwd_injection(intp->pin);
+        intp->forwarded = true;
+    }
+
+    if (kvm_irqchip_add_irqfd_notifier(kvm_state, &intp->interrupt,
+                                   &intp->unmask, irq) < 0) {
+        goto fail_irqfd;
+    }
+
+    if (vfio_set_trigger_eventfd(intp, NULL) < 0) {
+        goto fail_vfio;
+    }
+    /* only used if forwarding setup failed */
+    if (vfio_set_resample_eventfd(intp) < 0) {
+        goto fail_vfio;
+    }
+
+    intp->kvm_accel = true;
+    return;
+fail_vfio:
+    kvm_irqchip_remove_irqfd_notifier(kvm_state, &intp->interrupt, irq);
+fail_irqfd:
+    vfio_start_eventfd_injection(intp);
+    vfio_unmask_single_irqindex(&vdev->vbasedev, intp->pin);
+    return;
+}
+
 #endif /* CONFIG_KVM */
 
 /* VFIO skeleton */
@@ -655,13 +737,6 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
     vbasedev->type = VFIO_DEVICE_TYPE_PLATFORM;
     vbasedev->ops = &vfio_platform_ops;
 
-#ifdef CONFIG_KVM
-    if (kvm_irqfds_enabled() && kvm_resamplefds_enabled() &&
-        vdev->irqfd_allowed) {
-        sbc->connect_irq_notifier = vfio_start_irqfd_injection;
-    }
-#endif
-
     trace_vfio_platform_realize(vbasedev->name, vdev->compat);
 
     ret = vfio_base_device_init(vbasedev);
@@ -679,6 +754,19 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
     QLIST_FOREACH(intp, &vdev->intp_list, next) {
         vfio_start_eventfd_injection(intp);
     }
+
+#ifdef CONFIG_KVM
+    if (kvm_irqfds_enabled() && kvm_resamplefds_enabled() &&
+        vdev->irqfd_allowed) {
+        if (has_kvm_vfio_forward_capability() &&
+                 vdev->forward_allowed) {
+            sbc->connect_irq_notifier = vfio_start_forward_injection;
+        } else {
+            sbc->connect_irq_notifier = vfio_start_irqfd_injection;
+        }
+    }
+#endif
+
 }
 
 static const VMStateDescription vfio_platform_vmstate = {
@@ -692,6 +780,7 @@ static Property vfio_platform_dev_properties[] = {
     DEFINE_PROP_UINT32("mmap-timeout-ms", VFIOPlatformDevice,
                        mmap_timeout, 1100),
     DEFINE_PROP_BOOL("x-irqfd", VFIOPlatformDevice, irqfd_allowed, true),
+    DEFINE_PROP_BOOL("x-forward", VFIOPlatformDevice, forward_allowed, true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h
index c5cf1d7..900f918 100644
--- a/include/hw/vfio/vfio-platform.h
+++ b/include/hw/vfio/vfio-platform.h
@@ -42,6 +42,8 @@ typedef struct VFIOINTp {
     uint8_t pin; /* index */
     uint32_t flags; /* IRQ info flags */
     bool kvm_accel; /* set when QEMU bypass through KVM enabled */
+    struct kvm_vfio_dev_irq *fwd_irq;
+    bool forwarded;
 } VFIOINTp;
 
 /* function type for user side eventfd handler */
@@ -59,6 +61,7 @@ typedef struct VFIOPlatformDevice {
     QEMUTimer *mmap_timer; /* allows fast-path resume after IRQ hit */
     QemuMutex intp_mutex; /* protect the intp_list IRQ state */
     bool irqfd_allowed; /* debug option to force irqfd on/off */
+    bool forward_allowed; /* debug option to force forwarding on/off */
 } VFIOPlatformDevice;
 
 typedef struct VFIOPlatformDeviceClass {
diff --git a/trace-events b/trace-events
index cb6381a..99d2b9c 100644
--- a/trace-events
+++ b/trace-events
@@ -1572,6 +1572,7 @@ vfio_platform_intp_inject_pending_lockheld(int pin, int fd) "Inject pending IRQ
 vfio_platform_populate_interrupts(int pin, int count, int flags) "- IRQ index %d: count %d, flags=0x%x"
 vfio_intp_interrupt_set_pending(int index) "irq %d is set PENDING"
 vfio_platform_start_irqfd_injection(int index, int fd, int resamplefd) "IRQ index=%d, fd = %d, resamplefd = %d"
+vfio_platform_start_fwd_injection(int pin) "forwarding set for IRQ pin %d"
 
 #hw/acpi/memory_hotplug.c
 mhp_acpi_invalid_slot_selected(uint32_t slot) "0x%"PRIx32
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC v2 4/4] hw/vfio/platform: add forwarded irq support
@ 2015-05-04 12:49   ` Eric Auger
  0 siblings, 0 replies; 10+ messages in thread
From: Eric Auger @ 2015-05-04 12:49 UTC (permalink / raw)
  To: eric.auger, eric.auger, qemu-devel, alex.williamson; +Cc: kvmarm, patches

Tests whether the forwarded IRQ modality is available.
In the positive device IRQs are forwarded. This control is
achieved with KVM-VFIO device. with such a modality injection
still is handled through irqfds. However end of interrupt is
not trapped anymore. As soon as the guest completes its virtual
IRQ, the corresponding physical IRQ is completed and the same
physical IRQ can hit again.

A new x-forward property enables to force forwarding off although
enabled by the kernel.

Signed-off-by: Eric Auger <eric.auger@linaro.org>

---

v1 -> v2:
- use kvm_vfio_get|put_device_irq, new irq connect notifier and
  integrate with 2 stage eventfd/irqfd setup

v1:
- moved in a separate series

v8 -> v9 (KVM platform device passthrough series):
- use new kvm_vfio_dev_irq struct

Signed-off-by: Eric Auger <eric.auger@linaro.org>
---
 hw/vfio/platform.c              | 103 +++++++++++++++++++++++++++++++++++++---
 include/hw/vfio/vfio-platform.h |   3 ++
 trace-events                    |   1 +
 3 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
index 901b98e..52c6d59 100644
--- a/hw/vfio/platform.c
+++ b/hw/vfio/platform.c
@@ -411,6 +411,88 @@ fail_irqfd:
     return;
 }
 
+/*
+ * Functions used with forwarding capability
+ */
+
+static bool has_kvm_vfio_forward_capability(void)
+{
+    struct kvm_device_attr attr = {
+         .group = KVM_DEV_VFIO_DEVICE,
+         .attr = KVM_DEV_VFIO_DEVICE_FORWARD_IRQ};
+
+    if (ioctl(vfio_kvm_device_fd, KVM_HAS_DEVICE_ATTR, &attr) == 0) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+static void vfio_start_forward_injection(SysBusDevice *sbdev, qemu_irq irq)
+{
+    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
+    VFIOINTp *intp;
+    bool found = false;
+    struct kvm_device_attr attr = {
+         .group = KVM_DEV_VFIO_DEVICE,
+         .attr = KVM_DEV_VFIO_DEVICE_FORWARD_IRQ};
+
+    QLIST_FOREACH(intp, &vdev->intp_list, next) {
+        if (intp->qemuirq == irq) {
+            found  = true;
+            break;
+        }
+    }
+    assert(found);
+
+    if (intp->forwarded) {
+        return;
+    }
+
+    /*
+     * stop VFIO signaling and unmask the physical IRQ since
+     * forwarding cannot be set if the IRQ is active or vfio masked
+     */
+    vfio_disable_irqindex(&intp->vdev->vbasedev, intp->pin);
+    vfio_unmask_single_irqindex(&intp->vdev->vbasedev, intp->pin);
+
+    kvm_vfio_get_device_irq(kvm_state, intp->vdev->vbasedev.fd,
+                            intp->pin, 0, 1, intp->qemuirq, &intp->fwd_irq);
+
+    attr.addr = (uint64_t)(unsigned long)intp->fwd_irq;
+
+    if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr) < 0) {
+        error_report("vfio: failed to forward irq %d, do standard irqfd",
+                     intp->pin);
+        kvm_vfio_put_device_irq(intp->fwd_irq);
+    } else {
+        trace_vfio_platform_start_fwd_injection(intp->pin);
+        intp->forwarded = true;
+    }
+
+    if (kvm_irqchip_add_irqfd_notifier(kvm_state, &intp->interrupt,
+                                   &intp->unmask, irq) < 0) {
+        goto fail_irqfd;
+    }
+
+    if (vfio_set_trigger_eventfd(intp, NULL) < 0) {
+        goto fail_vfio;
+    }
+    /* only used if forwarding setup failed */
+    if (vfio_set_resample_eventfd(intp) < 0) {
+        goto fail_vfio;
+    }
+
+    intp->kvm_accel = true;
+    return;
+fail_vfio:
+    kvm_irqchip_remove_irqfd_notifier(kvm_state, &intp->interrupt, irq);
+fail_irqfd:
+    vfio_start_eventfd_injection(intp);
+    vfio_unmask_single_irqindex(&vdev->vbasedev, intp->pin);
+    return;
+}
+
 #endif /* CONFIG_KVM */
 
 /* VFIO skeleton */
@@ -655,13 +737,6 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
     vbasedev->type = VFIO_DEVICE_TYPE_PLATFORM;
     vbasedev->ops = &vfio_platform_ops;
 
-#ifdef CONFIG_KVM
-    if (kvm_irqfds_enabled() && kvm_resamplefds_enabled() &&
-        vdev->irqfd_allowed) {
-        sbc->connect_irq_notifier = vfio_start_irqfd_injection;
-    }
-#endif
-
     trace_vfio_platform_realize(vbasedev->name, vdev->compat);
 
     ret = vfio_base_device_init(vbasedev);
@@ -679,6 +754,19 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
     QLIST_FOREACH(intp, &vdev->intp_list, next) {
         vfio_start_eventfd_injection(intp);
     }
+
+#ifdef CONFIG_KVM
+    if (kvm_irqfds_enabled() && kvm_resamplefds_enabled() &&
+        vdev->irqfd_allowed) {
+        if (has_kvm_vfio_forward_capability() &&
+                 vdev->forward_allowed) {
+            sbc->connect_irq_notifier = vfio_start_forward_injection;
+        } else {
+            sbc->connect_irq_notifier = vfio_start_irqfd_injection;
+        }
+    }
+#endif
+
 }
 
 static const VMStateDescription vfio_platform_vmstate = {
@@ -692,6 +780,7 @@ static Property vfio_platform_dev_properties[] = {
     DEFINE_PROP_UINT32("mmap-timeout-ms", VFIOPlatformDevice,
                        mmap_timeout, 1100),
     DEFINE_PROP_BOOL("x-irqfd", VFIOPlatformDevice, irqfd_allowed, true),
+    DEFINE_PROP_BOOL("x-forward", VFIOPlatformDevice, forward_allowed, true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h
index c5cf1d7..900f918 100644
--- a/include/hw/vfio/vfio-platform.h
+++ b/include/hw/vfio/vfio-platform.h
@@ -42,6 +42,8 @@ typedef struct VFIOINTp {
     uint8_t pin; /* index */
     uint32_t flags; /* IRQ info flags */
     bool kvm_accel; /* set when QEMU bypass through KVM enabled */
+    struct kvm_vfio_dev_irq *fwd_irq;
+    bool forwarded;
 } VFIOINTp;
 
 /* function type for user side eventfd handler */
@@ -59,6 +61,7 @@ typedef struct VFIOPlatformDevice {
     QEMUTimer *mmap_timer; /* allows fast-path resume after IRQ hit */
     QemuMutex intp_mutex; /* protect the intp_list IRQ state */
     bool irqfd_allowed; /* debug option to force irqfd on/off */
+    bool forward_allowed; /* debug option to force forwarding on/off */
 } VFIOPlatformDevice;
 
 typedef struct VFIOPlatformDeviceClass {
diff --git a/trace-events b/trace-events
index cb6381a..99d2b9c 100644
--- a/trace-events
+++ b/trace-events
@@ -1572,6 +1572,7 @@ vfio_platform_intp_inject_pending_lockheld(int pin, int fd) "Inject pending IRQ
 vfio_platform_populate_interrupts(int pin, int count, int flags) "- IRQ index %d: count %d, flags=0x%x"
 vfio_intp_interrupt_set_pending(int index) "irq %d is set PENDING"
 vfio_platform_start_irqfd_injection(int index, int fd, int resamplefd) "IRQ index=%d, fd = %d, resamplefd = %d"
+vfio_platform_start_fwd_injection(int pin) "forwarding set for IRQ pin %d"
 
 #hw/acpi/memory_hotplug.c
 mhp_acpi_invalid_slot_selected(uint32_t slot) "0x%"PRIx32
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2015-05-04 12:50 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-04 12:49 [Qemu-devel] [RFC v2 0/4] VFIO Platform device featuring IRQ forwarding Eric Auger
2015-05-04 12:49 ` Eric Auger
2015-05-04 12:49 ` [Qemu-devel] [RFC v2 1/4] linux-headers: Update KVM header for KVM-VFIO FORWARD/UNFORWARD Eric Auger
2015-05-04 12:49   ` Eric Auger
2015-05-04 12:49 ` [Qemu-devel] [RFC v2 2/4] hw/vfio/common: vfio_kvm_device_fd moved in the common header Eric Auger
2015-05-04 12:49   ` Eric Auger
2015-05-04 12:49 ` [Qemu-devel] [RFC v2 3/4] kvm: add kvm_vfio_get_device_irq Eric Auger
2015-05-04 12:49   ` Eric Auger
2015-05-04 12:49 ` [Qemu-devel] [RFC v2 4/4] hw/vfio/platform: add forwarded irq support Eric Auger
2015-05-04 12:49   ` Eric Auger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.