All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices
@ 2015-01-06 10:48 Antonios Motakis
  2015-01-06 10:48   ` Antonios Motakis
                   ` (20 more replies)
  0 siblings, 21 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	alex.williamson-H+wXaHxf7aLQT0dZR+AlfA
  Cc: eric.auger-QSEj5FYQhm4dnm+yROfE0A, marc.zyngier-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, Antonios Motakis,
	tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J,
	christoffer.dall-QSEj5FYQhm4dnm+yROfE0A

This patch series aims to implement VFIO support for platform devices that
reside behind an IOMMU. Examples of such devices are devices behind an ARM
SMMU, or behind a Samsung Exynos System MMU.

The API used is based on the existing VFIO API that is also used with PCI
devices. Only devices that include a basic set of IRQs and memory regions are
targeted; devices with complex relationships with other devices on a device
tree are not taken into account at this stage.

This patch series may be applied on the following series/patches:
 - [PATCH] driver core: amba: add device binding path 'driver_override'
 - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1

A copy can be cloned from the branch vfio-platform-v11 at:
git-9UaJU3cA/F/QT0dZR+AlfA@public.gmane.org:virtualopensystems/linux-kvm-arm.git

Changes since v10:
 - Check if interrupt is already masked when setting a new trigger
 - Fixed kasprintf with unchecked return value in VFIO AMBA driver
Changes since v9:
 - Reworked the splitting of the patches that decouple virqfd from PCI
 - Some styling issues and typos
 - Removed superfluous includes
 - AMBA devices are now named vfio-amba- suffixed by the AMBA device id
 - Several other cleanups and fixes
Changes since v8:
 - Separate irq handler for edge and level triggered interrupts
 - Mutex based lock for VFIO fd open/release
 - Fixed bug where the first region of a platform device wasn't exposed
 - Read only regions can be MMAPed only read only
 - Code cleanups
Changes since v7:
 - Some initial placeholder functionality for PIO resources
 - Cleaned up code for IRQ triggering, masking and unmasking
 - Some functionality has been removed from this series and posted separately:
   - VFIO_IOMMU_TYPE1 support for ARM SMMUs
   - IOMMU NOEXEC patches
   - driver_override functionality for AMBA devices
 - Several fixes
Changes since v6:
 - Integrated support for AMBA devices
 - Numerous cleanups and fixes
Changes since v5:
 - Full eventfd support for IRQ masking and unmasking.
 - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags in VFIO.
 - Other fixes based on reviewer comments.
Changes since v4:
 - Use static offsets for each region in the VFIO device fd
 - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
   availability via IOMMU_CAP_DMA_EXEC
 - Rebased on VFIO multi domain support:
   - IOMMU_EXEC is now available if at least one IOMMU in the container
     supports it
   - Expose IOMMU_EXEC if available via the capability VFIO_IOMMU_PROT_EXEC
 - Some bug fixes
Changes since v3:
 - Use Kim Phillips' driver_probe_device()
Changes since v2:
 - Fixed Read/Write and MMAP on device regions
 - Removed dependency on Device Tree
 - Interrupts support
 - Interrupt masking/unmasking
 - Automask level sensitive interrupts
 - Introduced VFIO_DMA_MAP_FLAG_EXEC
 - Code clean ups

Antonios Motakis (20):
  vfio/platform: initial skeleton of VFIO support for platform devices
  vfio: platform: probe to devices on the platform bus
  vfio: platform: add the VFIO PLATFORM module to Kconfig
  vfio: amba: VFIO support for AMBA devices
  vfio: amba: add the VFIO for AMBA devices module to Kconfig
  vfio/platform: return info for bound device
  vfio/platform: return info for device memory mapped IO regions
  vfio/platform: read and write support for the device fd
  vfio/platform: support MMAP of MMIO regions
  vfio/platform: return IRQ info
  vfio/platform: initial interrupts support code
  vfio/platform: trigger an interrupt via eventfd
  vfio/platform: support for level sensitive interrupts
  vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and
    export
  vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
  vfio: add local lock for virqfd instead of depending on VFIO PCI
  vfio: pass an opaque pointer on virqfd initialization
  vfio: move eventfd support code for VFIO_PCI to a separate file
  vfio: initialize the virqfd workqueue in VFIO generic code
  vfio/platform: implement IRQ masking/unmasking via an eventfd

 drivers/vfio/Kconfig                          |   1 +
 drivers/vfio/Makefile                         |   5 +-
 drivers/vfio/pci/vfio_pci.c                   |   8 -
 drivers/vfio/pci/vfio_pci_intrs.c             | 238 +-----------
 drivers/vfio/pci/vfio_pci_private.h           |   3 -
 drivers/vfio/platform/Kconfig                 |  19 +
 drivers/vfio/platform/Makefile                |   8 +
 drivers/vfio/platform/vfio_amba.c             | 115 ++++++
 drivers/vfio/platform/vfio_platform.c         | 103 +++++
 drivers/vfio/platform/vfio_platform_common.c  | 520 ++++++++++++++++++++++++++
 drivers/vfio/platform/vfio_platform_irq.c     | 340 +++++++++++++++++
 drivers/vfio/platform/vfio_platform_private.h |  82 ++++
 drivers/vfio/vfio.c                           |   8 +
 drivers/vfio/virqfd.c                         | 213 +++++++++++
 include/linux/vfio.h                          |  27 ++
 include/uapi/linux/vfio.h                     |   2 +
 16 files changed, 1456 insertions(+), 236 deletions(-)
 create mode 100644 drivers/vfio/platform/Kconfig
 create mode 100644 drivers/vfio/platform/Makefile
 create mode 100644 drivers/vfio/platform/vfio_amba.c
 create mode 100644 drivers/vfio/platform/vfio_platform.c
 create mode 100644 drivers/vfio/platform/vfio_platform_common.c
 create mode 100644 drivers/vfio/platform/vfio_platform_irq.c
 create mode 100644 drivers/vfio/platform/vfio_platform_private.h
 create mode 100644 drivers/vfio/virqfd.c

-- 
2.1.4

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

* [PATCH v11 01/20] vfio/platform: initial skeleton of VFIO support for platform devices
       [not found] ` <1420541335-17190-1-git-send-email-a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-09  8:39   ` Eric Auger
  2015-01-19 18:39   ` Alex Williamson
  2 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list, open list:VFIO DRIVER

This patch forms the common skeleton code for platform devices support
with VFIO. This will include the core functionality of VFIO_PLATFORM,
however binding to the device and discovering the device resources will
be done with the help of a separate file where any Linux platform bus
specific code will reside.

This will allow us to implement support for also discovering AMBA devices
and their resources, but still reuse a large part of the VFIO_PLATFORM
implementation.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_common.c  | 121 ++++++++++++++++++++++++++
 drivers/vfio/platform/vfio_platform_private.h |  36 ++++++++
 2 files changed, 157 insertions(+)
 create mode 100644 drivers/vfio/platform/vfio_platform_common.c
 create mode 100644 drivers/vfio/platform/vfio_platform_private.h

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
new file mode 100644
index 0000000..34d023b
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis@virtualopensystems.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/iommu.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/vfio.h>
+
+#include "vfio_platform_private.h"
+
+static void vfio_platform_release(void *device_data)
+{
+	module_put(THIS_MODULE);
+}
+
+static int vfio_platform_open(void *device_data)
+{
+	if (!try_module_get(THIS_MODULE))
+		return -ENODEV;
+
+	return 0;
+}
+
+static long vfio_platform_ioctl(void *device_data,
+				unsigned int cmd, unsigned long arg)
+{
+	if (cmd == VFIO_DEVICE_GET_INFO)
+		return -EINVAL;
+
+	else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
+		return -EINVAL;
+
+	else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
+		return -EINVAL;
+
+	else if (cmd == VFIO_DEVICE_SET_IRQS)
+		return -EINVAL;
+
+	else if (cmd == VFIO_DEVICE_RESET)
+		return -EINVAL;
+
+	return -ENOTTY;
+}
+
+static ssize_t vfio_platform_read(void *device_data, char __user *buf,
+				  size_t count, loff_t *ppos)
+{
+	return -EINVAL;
+}
+
+static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
+				   size_t count, loff_t *ppos)
+{
+	return -EINVAL;
+}
+
+static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma)
+{
+	return -EINVAL;
+}
+
+static const struct vfio_device_ops vfio_platform_ops = {
+	.name		= "vfio-platform",
+	.open		= vfio_platform_open,
+	.release	= vfio_platform_release,
+	.ioctl		= vfio_platform_ioctl,
+	.read		= vfio_platform_read,
+	.write		= vfio_platform_write,
+	.mmap		= vfio_platform_mmap,
+};
+
+int vfio_platform_probe_common(struct vfio_platform_device *vdev,
+			       struct device *dev)
+{
+	struct iommu_group *group;
+	int ret;
+
+	if (!vdev)
+		return -EINVAL;
+
+	group = iommu_group_get(dev);
+	if (!group) {
+		pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
+		return -EINVAL;
+	}
+
+	ret = vfio_add_group_dev(dev, &vfio_platform_ops, vdev);
+	if (ret) {
+		iommu_group_put(group);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vfio_platform_probe_common);
+
+struct vfio_platform_device *vfio_platform_remove_common(struct device *dev)
+{
+	struct vfio_platform_device *vdev;
+
+	vdev = vfio_del_group_dev(dev);
+	if (vdev)
+		iommu_group_put(dev->iommu_group);
+
+	return vdev;
+}
+EXPORT_SYMBOL_GPL(vfio_platform_remove_common);
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
new file mode 100644
index 0000000..062b92d
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis@virtualopensystems.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef VFIO_PLATFORM_PRIVATE_H
+#define VFIO_PLATFORM_PRIVATE_H
+
+struct vfio_platform_device {
+	/*
+	 * These fields should be filled by the bus specific binder
+	 */
+	void		*opaque;
+	const char	*name;
+	uint32_t	flags;
+	/* callbacks to discover device resources */
+	struct resource*
+		(*get_resource)(struct vfio_platform_device *vdev, int i);
+	int	(*get_irq)(struct vfio_platform_device *vdev, int i);
+};
+
+extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
+				      struct device *dev);
+extern struct vfio_platform_device *vfio_platform_remove_common
+				     (struct device *dev);
+
+#endif /* VFIO_PLATFORM_PRIVATE_H */
-- 
2.1.4


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

* [PATCH v11 01/20] vfio/platform: initial skeleton of VFIO support for platform devices
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	alex.williamson-H+wXaHxf7aLQT0dZR+AlfA
  Cc: open list:VFIO DRIVER, eric.auger-QSEj5FYQhm4dnm+yROfE0A,
	marc.zyngier-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8, open list,
	Antonios Motakis, tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J,
	christoffer.dall-QSEj5FYQhm4dnm+yROfE0A

This patch forms the common skeleton code for platform devices support
with VFIO. This will include the core functionality of VFIO_PLATFORM,
however binding to the device and discovering the device resources will
be done with the help of a separate file where any Linux platform bus
specific code will reside.

This will allow us to implement support for also discovering AMBA devices
and their resources, but still reuse a large part of the VFIO_PLATFORM
implementation.

Signed-off-by: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
---
 drivers/vfio/platform/vfio_platform_common.c  | 121 ++++++++++++++++++++++++++
 drivers/vfio/platform/vfio_platform_private.h |  36 ++++++++
 2 files changed, 157 insertions(+)
 create mode 100644 drivers/vfio/platform/vfio_platform_common.c
 create mode 100644 drivers/vfio/platform/vfio_platform_private.h

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
new file mode 100644
index 0000000..34d023b
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/iommu.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/vfio.h>
+
+#include "vfio_platform_private.h"
+
+static void vfio_platform_release(void *device_data)
+{
+	module_put(THIS_MODULE);
+}
+
+static int vfio_platform_open(void *device_data)
+{
+	if (!try_module_get(THIS_MODULE))
+		return -ENODEV;
+
+	return 0;
+}
+
+static long vfio_platform_ioctl(void *device_data,
+				unsigned int cmd, unsigned long arg)
+{
+	if (cmd == VFIO_DEVICE_GET_INFO)
+		return -EINVAL;
+
+	else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
+		return -EINVAL;
+
+	else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
+		return -EINVAL;
+
+	else if (cmd == VFIO_DEVICE_SET_IRQS)
+		return -EINVAL;
+
+	else if (cmd == VFIO_DEVICE_RESET)
+		return -EINVAL;
+
+	return -ENOTTY;
+}
+
+static ssize_t vfio_platform_read(void *device_data, char __user *buf,
+				  size_t count, loff_t *ppos)
+{
+	return -EINVAL;
+}
+
+static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
+				   size_t count, loff_t *ppos)
+{
+	return -EINVAL;
+}
+
+static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma)
+{
+	return -EINVAL;
+}
+
+static const struct vfio_device_ops vfio_platform_ops = {
+	.name		= "vfio-platform",
+	.open		= vfio_platform_open,
+	.release	= vfio_platform_release,
+	.ioctl		= vfio_platform_ioctl,
+	.read		= vfio_platform_read,
+	.write		= vfio_platform_write,
+	.mmap		= vfio_platform_mmap,
+};
+
+int vfio_platform_probe_common(struct vfio_platform_device *vdev,
+			       struct device *dev)
+{
+	struct iommu_group *group;
+	int ret;
+
+	if (!vdev)
+		return -EINVAL;
+
+	group = iommu_group_get(dev);
+	if (!group) {
+		pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
+		return -EINVAL;
+	}
+
+	ret = vfio_add_group_dev(dev, &vfio_platform_ops, vdev);
+	if (ret) {
+		iommu_group_put(group);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vfio_platform_probe_common);
+
+struct vfio_platform_device *vfio_platform_remove_common(struct device *dev)
+{
+	struct vfio_platform_device *vdev;
+
+	vdev = vfio_del_group_dev(dev);
+	if (vdev)
+		iommu_group_put(dev->iommu_group);
+
+	return vdev;
+}
+EXPORT_SYMBOL_GPL(vfio_platform_remove_common);
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
new file mode 100644
index 0000000..062b92d
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef VFIO_PLATFORM_PRIVATE_H
+#define VFIO_PLATFORM_PRIVATE_H
+
+struct vfio_platform_device {
+	/*
+	 * These fields should be filled by the bus specific binder
+	 */
+	void		*opaque;
+	const char	*name;
+	uint32_t	flags;
+	/* callbacks to discover device resources */
+	struct resource*
+		(*get_resource)(struct vfio_platform_device *vdev, int i);
+	int	(*get_irq)(struct vfio_platform_device *vdev, int i);
+};
+
+extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
+				      struct device *dev);
+extern struct vfio_platform_device *vfio_platform_remove_common
+				     (struct device *dev);
+
+#endif /* VFIO_PLATFORM_PRIVATE_H */
-- 
2.1.4

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

* [PATCH v11 02/20] vfio: platform: probe to devices on the platform bus
       [not found] ` <1420541335-17190-1-git-send-email-a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
  2015-01-08 16:58   ` [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Eric Auger
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-19 18:39   ` Alex Williamson
  2 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list, open list:VFIO DRIVER,
	open list:ABI/API

Driver to bind to Linux platform devices, and callbacks to discover their
resources to be used by the main VFIO PLATFORM code.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform.c | 103 ++++++++++++++++++++++++++++++++++
 include/uapi/linux/vfio.h             |   1 +
 2 files changed, 104 insertions(+)
 create mode 100644 drivers/vfio/platform/vfio_platform.c

diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c
new file mode 100644
index 0000000..cef645c
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis@virtualopensystems.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vfio.h>
+#include <linux/platform_device.h>
+
+#include "vfio_platform_private.h"
+
+#define DRIVER_VERSION  "0.10"
+#define DRIVER_AUTHOR   "Antonios Motakis <a.motakis@virtualopensystems.com>"
+#define DRIVER_DESC     "VFIO for platform devices - User Level meta-driver"
+
+/* probing devices from the linux platform bus */
+
+static struct resource *get_platform_resource(struct vfio_platform_device *vdev,
+					      int num)
+{
+	struct platform_device *dev = (struct platform_device *) vdev->opaque;
+	int i;
+
+	for (i = 0; i < dev->num_resources; i++) {
+		struct resource *r = &dev->resource[i];
+
+		if (resource_type(r) & (IORESOURCE_MEM|IORESOURCE_IO)) {
+			if (!num)
+				return r;
+
+			num--;
+		}
+	}
+	return NULL;
+}
+
+static int get_platform_irq(struct vfio_platform_device *vdev, int i)
+{
+	struct platform_device *pdev = (struct platform_device *) vdev->opaque;
+
+	return platform_get_irq(pdev, i);
+}
+
+static int vfio_platform_probe(struct platform_device *pdev)
+{
+	struct vfio_platform_device *vdev;
+	int ret;
+
+	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+	if (!vdev)
+		return -ENOMEM;
+
+	vdev->opaque = (void *) pdev;
+	vdev->name = pdev->name;
+	vdev->flags = VFIO_DEVICE_FLAGS_PLATFORM;
+	vdev->get_resource = get_platform_resource;
+	vdev->get_irq = get_platform_irq;
+
+	ret = vfio_platform_probe_common(vdev, &pdev->dev);
+	if (ret)
+		kfree(vdev);
+
+	return ret;
+}
+
+static int vfio_platform_remove(struct platform_device *pdev)
+{
+	struct vfio_platform_device *vdev;
+
+	vdev = vfio_platform_remove_common(&pdev->dev);
+	if (vdev) {
+		kfree(vdev);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static struct platform_driver vfio_platform_driver = {
+	.probe		= vfio_platform_probe,
+	.remove		= vfio_platform_remove,
+	.driver	= {
+		.name	= "vfio-platform",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(vfio_platform_driver);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 9ade02b..4e93a97 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -159,6 +159,7 @@ struct vfio_device_info {
 	__u32	flags;
 #define VFIO_DEVICE_FLAGS_RESET	(1 << 0)	/* Device supports reset */
 #define VFIO_DEVICE_FLAGS_PCI	(1 << 1)	/* vfio-pci device */
+#define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2)	/* vfio-platform device */
 	__u32	num_regions;	/* Max region index + 1 */
 	__u32	num_irqs;	/* Max IRQ index + 1 */
 };
-- 
2.1.4


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

* [PATCH v11 02/20] vfio: platform: probe to devices on the platform bus
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	alex.williamson-H+wXaHxf7aLQT0dZR+AlfA
  Cc: will.deacon-5wv7dgnIgG8, tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J,
	christoffer.dall-QSEj5FYQhm4dnm+yROfE0A,
	eric.auger-QSEj5FYQhm4dnm+yROfE0A,
	kim.phillips-KZfg59tc24xl57MIdRCFDg, marc.zyngier-5wv7dgnIgG8,
	Antonios Motakis, open list, open list:VFIO DRIVER,
	open list:ABI/API

Driver to bind to Linux platform devices, and callbacks to discover their
resources to be used by the main VFIO PLATFORM code.

Signed-off-by: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
---
 drivers/vfio/platform/vfio_platform.c | 103 ++++++++++++++++++++++++++++++++++
 include/uapi/linux/vfio.h             |   1 +
 2 files changed, 104 insertions(+)
 create mode 100644 drivers/vfio/platform/vfio_platform.c

diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c
new file mode 100644
index 0000000..cef645c
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vfio.h>
+#include <linux/platform_device.h>
+
+#include "vfio_platform_private.h"
+
+#define DRIVER_VERSION  "0.10"
+#define DRIVER_AUTHOR   "Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>"
+#define DRIVER_DESC     "VFIO for platform devices - User Level meta-driver"
+
+/* probing devices from the linux platform bus */
+
+static struct resource *get_platform_resource(struct vfio_platform_device *vdev,
+					      int num)
+{
+	struct platform_device *dev = (struct platform_device *) vdev->opaque;
+	int i;
+
+	for (i = 0; i < dev->num_resources; i++) {
+		struct resource *r = &dev->resource[i];
+
+		if (resource_type(r) & (IORESOURCE_MEM|IORESOURCE_IO)) {
+			if (!num)
+				return r;
+
+			num--;
+		}
+	}
+	return NULL;
+}
+
+static int get_platform_irq(struct vfio_platform_device *vdev, int i)
+{
+	struct platform_device *pdev = (struct platform_device *) vdev->opaque;
+
+	return platform_get_irq(pdev, i);
+}
+
+static int vfio_platform_probe(struct platform_device *pdev)
+{
+	struct vfio_platform_device *vdev;
+	int ret;
+
+	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+	if (!vdev)
+		return -ENOMEM;
+
+	vdev->opaque = (void *) pdev;
+	vdev->name = pdev->name;
+	vdev->flags = VFIO_DEVICE_FLAGS_PLATFORM;
+	vdev->get_resource = get_platform_resource;
+	vdev->get_irq = get_platform_irq;
+
+	ret = vfio_platform_probe_common(vdev, &pdev->dev);
+	if (ret)
+		kfree(vdev);
+
+	return ret;
+}
+
+static int vfio_platform_remove(struct platform_device *pdev)
+{
+	struct vfio_platform_device *vdev;
+
+	vdev = vfio_platform_remove_common(&pdev->dev);
+	if (vdev) {
+		kfree(vdev);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static struct platform_driver vfio_platform_driver = {
+	.probe		= vfio_platform_probe,
+	.remove		= vfio_platform_remove,
+	.driver	= {
+		.name	= "vfio-platform",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(vfio_platform_driver);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 9ade02b..4e93a97 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -159,6 +159,7 @@ struct vfio_device_info {
 	__u32	flags;
 #define VFIO_DEVICE_FLAGS_RESET	(1 << 0)	/* Device supports reset */
 #define VFIO_DEVICE_FLAGS_PCI	(1 << 1)	/* vfio-pci device */
+#define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2)	/* vfio-platform device */
 	__u32	num_regions;	/* Max region index + 1 */
 	__u32	num_irqs;	/* Max IRQ index + 1 */
 };
-- 
2.1.4

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

* [PATCH v11 02/20] vfio: platform: probe to devices on the platform bus
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	alex.williamson-H+wXaHxf7aLQT0dZR+AlfA
  Cc: will.deacon-5wv7dgnIgG8, tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J,
	christoffer.dall-QSEj5FYQhm4dnm+yROfE0A,
	eric.auger-QSEj5FYQhm4dnm+yROfE0A,
	kim.phillips-KZfg59tc24xl57MIdRCFDg, marc.zyngier-5wv7dgnIgG8,
	Antonios Motakis, open list, open list:VFIO DRIVER,
	open list:ABI/API

Driver to bind to Linux platform devices, and callbacks to discover their
resources to be used by the main VFIO PLATFORM code.

Signed-off-by: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
---
 drivers/vfio/platform/vfio_platform.c | 103 ++++++++++++++++++++++++++++++++++
 include/uapi/linux/vfio.h             |   1 +
 2 files changed, 104 insertions(+)
 create mode 100644 drivers/vfio/platform/vfio_platform.c

diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c
new file mode 100644
index 0000000..cef645c
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vfio.h>
+#include <linux/platform_device.h>
+
+#include "vfio_platform_private.h"
+
+#define DRIVER_VERSION  "0.10"
+#define DRIVER_AUTHOR   "Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>"
+#define DRIVER_DESC     "VFIO for platform devices - User Level meta-driver"
+
+/* probing devices from the linux platform bus */
+
+static struct resource *get_platform_resource(struct vfio_platform_device *vdev,
+					      int num)
+{
+	struct platform_device *dev = (struct platform_device *) vdev->opaque;
+	int i;
+
+	for (i = 0; i < dev->num_resources; i++) {
+		struct resource *r = &dev->resource[i];
+
+		if (resource_type(r) & (IORESOURCE_MEM|IORESOURCE_IO)) {
+			if (!num)
+				return r;
+
+			num--;
+		}
+	}
+	return NULL;
+}
+
+static int get_platform_irq(struct vfio_platform_device *vdev, int i)
+{
+	struct platform_device *pdev = (struct platform_device *) vdev->opaque;
+
+	return platform_get_irq(pdev, i);
+}
+
+static int vfio_platform_probe(struct platform_device *pdev)
+{
+	struct vfio_platform_device *vdev;
+	int ret;
+
+	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+	if (!vdev)
+		return -ENOMEM;
+
+	vdev->opaque = (void *) pdev;
+	vdev->name = pdev->name;
+	vdev->flags = VFIO_DEVICE_FLAGS_PLATFORM;
+	vdev->get_resource = get_platform_resource;
+	vdev->get_irq = get_platform_irq;
+
+	ret = vfio_platform_probe_common(vdev, &pdev->dev);
+	if (ret)
+		kfree(vdev);
+
+	return ret;
+}
+
+static int vfio_platform_remove(struct platform_device *pdev)
+{
+	struct vfio_platform_device *vdev;
+
+	vdev = vfio_platform_remove_common(&pdev->dev);
+	if (vdev) {
+		kfree(vdev);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static struct platform_driver vfio_platform_driver = {
+	.probe		= vfio_platform_probe,
+	.remove		= vfio_platform_remove,
+	.driver	= {
+		.name	= "vfio-platform",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(vfio_platform_driver);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 9ade02b..4e93a97 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -159,6 +159,7 @@ struct vfio_device_info {
 	__u32	flags;
 #define VFIO_DEVICE_FLAGS_RESET	(1 << 0)	/* Device supports reset */
 #define VFIO_DEVICE_FLAGS_PCI	(1 << 1)	/* vfio-pci device */
+#define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2)	/* vfio-platform device */
 	__u32	num_regions;	/* Max region index + 1 */
 	__u32	num_irqs;	/* Max IRQ index + 1 */
 };
-- 
2.1.4

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

* [PATCH v11 03/20] vfio: platform: add the VFIO PLATFORM module to Kconfig
  2015-01-06 10:48 [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Antonios Motakis
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-06 10:48   ` Antonios Motakis
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list, open list:VFIO DRIVER

Enable building the VFIO PLATFORM driver that allows to use Linux platform
devices with VFIO.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/Kconfig           | 1 +
 drivers/vfio/Makefile          | 1 +
 drivers/vfio/platform/Kconfig  | 9 +++++++++
 drivers/vfio/platform/Makefile | 4 ++++
 4 files changed, 15 insertions(+)
 create mode 100644 drivers/vfio/platform/Kconfig
 create mode 100644 drivers/vfio/platform/Makefile

diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
index a0abe04..962fb80 100644
--- a/drivers/vfio/Kconfig
+++ b/drivers/vfio/Kconfig
@@ -27,3 +27,4 @@ menuconfig VFIO
 	  If you don't know what to do here, say N.
 
 source "drivers/vfio/pci/Kconfig"
+source "drivers/vfio/platform/Kconfig"
diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index 0b035b1..dadf0ca 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
 obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
 obj-$(CONFIG_VFIO_SPAPR_EEH) += vfio_spapr_eeh.o
 obj-$(CONFIG_VFIO_PCI) += pci/
+obj-$(CONFIG_VFIO_PLATFORM) += platform/
diff --git a/drivers/vfio/platform/Kconfig b/drivers/vfio/platform/Kconfig
new file mode 100644
index 0000000..c51af17
--- /dev/null
+++ b/drivers/vfio/platform/Kconfig
@@ -0,0 +1,9 @@
+config VFIO_PLATFORM
+	tristate "VFIO support for platform devices"
+	depends on VFIO && EVENTFD && ARM
+	help
+	  Support for platform devices with VFIO. This is required to make
+	  use of platform devices present on the system using the VFIO
+	  framework.
+
+	  If you don't know what to do here, say N.
diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
new file mode 100644
index 0000000..279862b
--- /dev/null
+++ b/drivers/vfio/platform/Makefile
@@ -0,0 +1,4 @@
+
+vfio-platform-y := vfio_platform.o vfio_platform_common.o
+
+obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
-- 
2.1.4


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

* [PATCH v11 03/20] vfio: platform: add the VFIO PLATFORM module to Kconfig
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list, open list:VFIO DRIVER

Enable building the VFIO PLATFORM driver that allows to use Linux platform
devices with VFIO.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/Kconfig           | 1 +
 drivers/vfio/Makefile          | 1 +
 drivers/vfio/platform/Kconfig  | 9 +++++++++
 drivers/vfio/platform/Makefile | 4 ++++
 4 files changed, 15 insertions(+)
 create mode 100644 drivers/vfio/platform/Kconfig
 create mode 100644 drivers/vfio/platform/Makefile

diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
index a0abe04..962fb80 100644
--- a/drivers/vfio/Kconfig
+++ b/drivers/vfio/Kconfig
@@ -27,3 +27,4 @@ menuconfig VFIO
 	  If you don't know what to do here, say N.
 
 source "drivers/vfio/pci/Kconfig"
+source "drivers/vfio/platform/Kconfig"
diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index 0b035b1..dadf0ca 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
 obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
 obj-$(CONFIG_VFIO_SPAPR_EEH) += vfio_spapr_eeh.o
 obj-$(CONFIG_VFIO_PCI) += pci/
+obj-$(CONFIG_VFIO_PLATFORM) += platform/
diff --git a/drivers/vfio/platform/Kconfig b/drivers/vfio/platform/Kconfig
new file mode 100644
index 0000000..c51af17
--- /dev/null
+++ b/drivers/vfio/platform/Kconfig
@@ -0,0 +1,9 @@
+config VFIO_PLATFORM
+	tristate "VFIO support for platform devices"
+	depends on VFIO && EVENTFD && ARM
+	help
+	  Support for platform devices with VFIO. This is required to make
+	  use of platform devices present on the system using the VFIO
+	  framework.
+
+	  If you don't know what to do here, say N.
diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
new file mode 100644
index 0000000..279862b
--- /dev/null
+++ b/drivers/vfio/platform/Makefile
@@ -0,0 +1,4 @@
+
+vfio-platform-y := vfio_platform.o vfio_platform_common.o
+
+obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
-- 
2.1.4

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

* [PATCH v11 04/20] vfio: amba: VFIO support for AMBA devices
       [not found] ` <1420541335-17190-1-git-send-email-a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-09  8:39   ` Eric Auger
  2015-01-19 18:39   ` Alex Williamson
  2 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list, open list:VFIO DRIVER,
	open list:ABI/API

Add support for discovering AMBA devices with VFIO and handle them
similarly to Linux platform devices.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_amba.c | 115 ++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/vfio.h         |   1 +
 2 files changed, 116 insertions(+)
 create mode 100644 drivers/vfio/platform/vfio_amba.c

diff --git a/drivers/vfio/platform/vfio_amba.c b/drivers/vfio/platform/vfio_amba.c
new file mode 100644
index 0000000..ff0331f
--- /dev/null
+++ b/drivers/vfio/platform/vfio_amba.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis@virtualopensystems.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vfio.h>
+#include <linux/amba/bus.h>
+
+#include "vfio_platform_private.h"
+
+#define DRIVER_VERSION  "0.10"
+#define DRIVER_AUTHOR   "Antonios Motakis <a.motakis@virtualopensystems.com>"
+#define DRIVER_DESC     "VFIO for AMBA devices - User Level meta-driver"
+
+/* probing devices from the AMBA bus */
+
+static struct resource *get_amba_resource(struct vfio_platform_device *vdev,
+					  int i)
+{
+	struct amba_device *adev = (struct amba_device *) vdev->opaque;
+
+	if (i == 0)
+		return &adev->res;
+
+	return NULL;
+}
+
+static int get_amba_irq(struct vfio_platform_device *vdev, int i)
+{
+	struct amba_device *adev = (struct amba_device *) vdev->opaque;
+	int ret = 0;
+
+	if (i < AMBA_NR_IRQS)
+		ret = adev->irq[i];
+
+	/* zero is an unset IRQ for AMBA devices */
+	return ret ? ret : -ENXIO;
+}
+
+static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
+{
+	struct vfio_platform_device *vdev;
+	int ret;
+
+	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+	if (!vdev)
+		return -ENOMEM;
+
+	vdev->name = kasprintf(GFP_KERNEL, "vfio-amba-%08x", adev->periphid);
+	if (!vdev->name) {
+		kfree(vdev);
+		return -ENOMEM;
+	}
+
+	vdev->opaque = (void *) adev;
+	vdev->flags = VFIO_DEVICE_FLAGS_AMBA;
+	vdev->get_resource = get_amba_resource;
+	vdev->get_irq = get_amba_irq;
+
+	ret = vfio_platform_probe_common(vdev, &adev->dev);
+	if (ret) {
+		kfree(vdev->name);
+		kfree(vdev);
+	}
+
+	return ret;
+}
+
+static int vfio_amba_remove(struct amba_device *adev)
+{
+	struct vfio_platform_device *vdev;
+
+	vdev = vfio_platform_remove_common(&adev->dev);
+	if (vdev) {
+		kfree(vdev->name);
+		kfree(vdev);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static struct amba_id pl330_ids[] = {
+	{ 0, 0 },
+};
+
+MODULE_DEVICE_TABLE(amba, pl330_ids);
+
+static struct amba_driver vfio_amba_driver = {
+	.probe = vfio_amba_probe,
+	.remove = vfio_amba_remove,
+	.id_table = pl330_ids,
+	.drv = {
+		.name = "vfio-amba",
+		.owner = THIS_MODULE,
+	},
+};
+
+module_amba_driver(vfio_amba_driver);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 4e93a97..544d3d8 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -160,6 +160,7 @@ struct vfio_device_info {
 #define VFIO_DEVICE_FLAGS_RESET	(1 << 0)	/* Device supports reset */
 #define VFIO_DEVICE_FLAGS_PCI	(1 << 1)	/* vfio-pci device */
 #define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2)	/* vfio-platform device */
+#define VFIO_DEVICE_FLAGS_AMBA  (1 << 3)	/* vfio-amba device */
 	__u32	num_regions;	/* Max region index + 1 */
 	__u32	num_irqs;	/* Max IRQ index + 1 */
 };
-- 
2.1.4


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

* [PATCH v11 04/20] vfio: amba: VFIO support for AMBA devices
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	alex.williamson-H+wXaHxf7aLQT0dZR+AlfA
  Cc: open list:VFIO DRIVER, eric.auger-QSEj5FYQhm4dnm+yROfE0A,
	marc.zyngier-5wv7dgnIgG8, open list:ABI/API,
	will.deacon-5wv7dgnIgG8, open list, Antonios Motakis,
	tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J,
	christoffer.dall-QSEj5FYQhm4dnm+yROfE0A

Add support for discovering AMBA devices with VFIO and handle them
similarly to Linux platform devices.

Signed-off-by: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
---
 drivers/vfio/platform/vfio_amba.c | 115 ++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/vfio.h         |   1 +
 2 files changed, 116 insertions(+)
 create mode 100644 drivers/vfio/platform/vfio_amba.c

diff --git a/drivers/vfio/platform/vfio_amba.c b/drivers/vfio/platform/vfio_amba.c
new file mode 100644
index 0000000..ff0331f
--- /dev/null
+++ b/drivers/vfio/platform/vfio_amba.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vfio.h>
+#include <linux/amba/bus.h>
+
+#include "vfio_platform_private.h"
+
+#define DRIVER_VERSION  "0.10"
+#define DRIVER_AUTHOR   "Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>"
+#define DRIVER_DESC     "VFIO for AMBA devices - User Level meta-driver"
+
+/* probing devices from the AMBA bus */
+
+static struct resource *get_amba_resource(struct vfio_platform_device *vdev,
+					  int i)
+{
+	struct amba_device *adev = (struct amba_device *) vdev->opaque;
+
+	if (i == 0)
+		return &adev->res;
+
+	return NULL;
+}
+
+static int get_amba_irq(struct vfio_platform_device *vdev, int i)
+{
+	struct amba_device *adev = (struct amba_device *) vdev->opaque;
+	int ret = 0;
+
+	if (i < AMBA_NR_IRQS)
+		ret = adev->irq[i];
+
+	/* zero is an unset IRQ for AMBA devices */
+	return ret ? ret : -ENXIO;
+}
+
+static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
+{
+	struct vfio_platform_device *vdev;
+	int ret;
+
+	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+	if (!vdev)
+		return -ENOMEM;
+
+	vdev->name = kasprintf(GFP_KERNEL, "vfio-amba-%08x", adev->periphid);
+	if (!vdev->name) {
+		kfree(vdev);
+		return -ENOMEM;
+	}
+
+	vdev->opaque = (void *) adev;
+	vdev->flags = VFIO_DEVICE_FLAGS_AMBA;
+	vdev->get_resource = get_amba_resource;
+	vdev->get_irq = get_amba_irq;
+
+	ret = vfio_platform_probe_common(vdev, &adev->dev);
+	if (ret) {
+		kfree(vdev->name);
+		kfree(vdev);
+	}
+
+	return ret;
+}
+
+static int vfio_amba_remove(struct amba_device *adev)
+{
+	struct vfio_platform_device *vdev;
+
+	vdev = vfio_platform_remove_common(&adev->dev);
+	if (vdev) {
+		kfree(vdev->name);
+		kfree(vdev);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static struct amba_id pl330_ids[] = {
+	{ 0, 0 },
+};
+
+MODULE_DEVICE_TABLE(amba, pl330_ids);
+
+static struct amba_driver vfio_amba_driver = {
+	.probe = vfio_amba_probe,
+	.remove = vfio_amba_remove,
+	.id_table = pl330_ids,
+	.drv = {
+		.name = "vfio-amba",
+		.owner = THIS_MODULE,
+	},
+};
+
+module_amba_driver(vfio_amba_driver);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 4e93a97..544d3d8 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -160,6 +160,7 @@ struct vfio_device_info {
 #define VFIO_DEVICE_FLAGS_RESET	(1 << 0)	/* Device supports reset */
 #define VFIO_DEVICE_FLAGS_PCI	(1 << 1)	/* vfio-pci device */
 #define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2)	/* vfio-platform device */
+#define VFIO_DEVICE_FLAGS_AMBA  (1 << 3)	/* vfio-amba device */
 	__u32	num_regions;	/* Max region index + 1 */
 	__u32	num_irqs;	/* Max IRQ index + 1 */
 };
-- 
2.1.4

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

* [PATCH v11 05/20] vfio: amba: add the VFIO for AMBA devices module to Kconfig
  2015-01-06 10:48 [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Antonios Motakis
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-06 10:48   ` Antonios Motakis
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list:VFIO DRIVER, open list

Enable building the VFIO AMBA driver. VFIO_AMBA depends on VFIO_PLATFORM,
since it is sharing a portion of the code, and it is essentially implemented
as a platform device whose resources are discovered via AMBA specific APIs
in the kernel.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/Kconfig  | 10 ++++++++++
 drivers/vfio/platform/Makefile |  4 ++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/vfio/platform/Kconfig b/drivers/vfio/platform/Kconfig
index c51af17..c0a3bff 100644
--- a/drivers/vfio/platform/Kconfig
+++ b/drivers/vfio/platform/Kconfig
@@ -7,3 +7,13 @@ config VFIO_PLATFORM
 	  framework.
 
 	  If you don't know what to do here, say N.
+
+config VFIO_AMBA
+	tristate "VFIO support for AMBA devices"
+	depends on VFIO_PLATFORM && ARM_AMBA
+	help
+	  Support for ARM AMBA devices with VFIO. This is required to make
+	  use of ARM AMBA devices present on the system using the VFIO
+	  framework.
+
+	  If you don't know what to do here, say N.
diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
index 279862b..1957170 100644
--- a/drivers/vfio/platform/Makefile
+++ b/drivers/vfio/platform/Makefile
@@ -2,3 +2,7 @@
 vfio-platform-y := vfio_platform.o vfio_platform_common.o
 
 obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
+
+vfio-amba-y := vfio_amba.o
+
+obj-$(CONFIG_VFIO_AMBA) += vfio-amba.o
-- 
2.1.4


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

* [PATCH v11 05/20] vfio: amba: add the VFIO for AMBA devices module to Kconfig
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list:VFIO DRIVER, open list

Enable building the VFIO AMBA driver. VFIO_AMBA depends on VFIO_PLATFORM,
since it is sharing a portion of the code, and it is essentially implemented
as a platform device whose resources are discovered via AMBA specific APIs
in the kernel.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/Kconfig  | 10 ++++++++++
 drivers/vfio/platform/Makefile |  4 ++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/vfio/platform/Kconfig b/drivers/vfio/platform/Kconfig
index c51af17..c0a3bff 100644
--- a/drivers/vfio/platform/Kconfig
+++ b/drivers/vfio/platform/Kconfig
@@ -7,3 +7,13 @@ config VFIO_PLATFORM
 	  framework.
 
 	  If you don't know what to do here, say N.
+
+config VFIO_AMBA
+	tristate "VFIO support for AMBA devices"
+	depends on VFIO_PLATFORM && ARM_AMBA
+	help
+	  Support for ARM AMBA devices with VFIO. This is required to make
+	  use of ARM AMBA devices present on the system using the VFIO
+	  framework.
+
+	  If you don't know what to do here, say N.
diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
index 279862b..1957170 100644
--- a/drivers/vfio/platform/Makefile
+++ b/drivers/vfio/platform/Makefile
@@ -2,3 +2,7 @@
 vfio-platform-y := vfio_platform.o vfio_platform_common.o
 
 obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
+
+vfio-amba-y := vfio_amba.o
+
+obj-$(CONFIG_VFIO_AMBA) += vfio-amba.o
-- 
2.1.4

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

* [PATCH v11 06/20] vfio/platform: return info for bound device
       [not found] ` <1420541335-17190-1-git-send-email-a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-09  8:39   ` Eric Auger
  2015-01-19 18:39   ` Alex Williamson
  2 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list:VFIO DRIVER, open list

A VFIO userspace driver will start by opening the VFIO device
that corresponds to an IOMMU group, and will use the ioctl interface
to get the basic device info, such as number of memory regions and
interrupts, and their properties. This patch enables the
VFIO_DEVICE_GET_INFO ioctl call.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_common.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 34d023b..862b43b 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -38,10 +38,27 @@ static int vfio_platform_open(void *device_data)
 static long vfio_platform_ioctl(void *device_data,
 				unsigned int cmd, unsigned long arg)
 {
-	if (cmd == VFIO_DEVICE_GET_INFO)
-		return -EINVAL;
+	struct vfio_platform_device *vdev = device_data;
+	unsigned long minsz;
+
+	if (cmd == VFIO_DEVICE_GET_INFO) {
+		struct vfio_device_info info;
+
+		minsz = offsetofend(struct vfio_device_info, num_irqs);
+
+		if (copy_from_user(&info, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (info.argsz < minsz)
+			return -EINVAL;
+
+		info.flags = vdev->flags;
+		info.num_regions = 0;
+		info.num_irqs = 0;
+
+		return copy_to_user((void __user *)arg, &info, minsz);
 
-	else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
+	} else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
 		return -EINVAL;
 
 	else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
-- 
2.1.4


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

* [PATCH v11 06/20] vfio/platform: return info for bound device
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	alex.williamson-H+wXaHxf7aLQT0dZR+AlfA
  Cc: open list:VFIO DRIVER, eric.auger-QSEj5FYQhm4dnm+yROfE0A,
	marc.zyngier-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8, open list,
	Antonios Motakis, tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J,
	christoffer.dall-QSEj5FYQhm4dnm+yROfE0A

A VFIO userspace driver will start by opening the VFIO device
that corresponds to an IOMMU group, and will use the ioctl interface
to get the basic device info, such as number of memory regions and
interrupts, and their properties. This patch enables the
VFIO_DEVICE_GET_INFO ioctl call.

Signed-off-by: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
---
 drivers/vfio/platform/vfio_platform_common.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 34d023b..862b43b 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -38,10 +38,27 @@ static int vfio_platform_open(void *device_data)
 static long vfio_platform_ioctl(void *device_data,
 				unsigned int cmd, unsigned long arg)
 {
-	if (cmd == VFIO_DEVICE_GET_INFO)
-		return -EINVAL;
+	struct vfio_platform_device *vdev = device_data;
+	unsigned long minsz;
+
+	if (cmd == VFIO_DEVICE_GET_INFO) {
+		struct vfio_device_info info;
+
+		minsz = offsetofend(struct vfio_device_info, num_irqs);
+
+		if (copy_from_user(&info, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (info.argsz < minsz)
+			return -EINVAL;
+
+		info.flags = vdev->flags;
+		info.num_regions = 0;
+		info.num_irqs = 0;
+
+		return copy_to_user((void __user *)arg, &info, minsz);
 
-	else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
+	} else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
 		return -EINVAL;
 
 	else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
-- 
2.1.4

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

* [PATCH v11 07/20] vfio/platform: return info for device memory mapped IO regions
  2015-01-06 10:48 [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Antonios Motakis
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-06 10:48   ` Antonios Motakis
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list:VFIO DRIVER, open list

This patch enables the IOCTLs VFIO_DEVICE_GET_REGION_INFO ioctl call,
which allows the user to learn about the available MMIO resources of
a device.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_common.c  | 106 +++++++++++++++++++++++++-
 drivers/vfio/platform/vfio_platform_private.h |  22 ++++++
 2 files changed, 124 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 862b43b..2a4613c 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -22,17 +22,97 @@
 
 #include "vfio_platform_private.h"
 
+static DEFINE_MUTEX(driver_lock);
+
+static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
+{
+	int cnt = 0, i;
+
+	while (vdev->get_resource(vdev, cnt))
+		cnt++;
+
+	vdev->regions = kcalloc(cnt, sizeof(struct vfio_platform_region),
+				GFP_KERNEL);
+	if (!vdev->regions)
+		return -ENOMEM;
+
+	for (i = 0; i < cnt;  i++) {
+		struct resource *res =
+			vdev->get_resource(vdev, i);
+
+		if (!res)
+			goto err;
+
+		vdev->regions[i].addr = res->start;
+		vdev->regions[i].size = resource_size(res);
+		vdev->regions[i].flags = 0;
+
+		switch (resource_type(res)) {
+		case IORESOURCE_MEM:
+			vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_MMIO;
+			break;
+		case IORESOURCE_IO:
+			vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
+			break;
+		default:
+			goto err;
+		}
+	}
+
+	vdev->num_regions = cnt;
+
+	return 0;
+err:
+	kfree(vdev->regions);
+	return -EINVAL;
+}
+
+static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
+{
+	vdev->num_regions = 0;
+	kfree(vdev->regions);
+}
+
 static void vfio_platform_release(void *device_data)
 {
+	struct vfio_platform_device *vdev = device_data;
+
+	mutex_lock(&driver_lock);
+
+	if (!(--vdev->refcnt)) {
+		vfio_platform_regions_cleanup(vdev);
+	}
+
+	mutex_unlock(&driver_lock);
+
 	module_put(THIS_MODULE);
 }
 
 static int vfio_platform_open(void *device_data)
 {
+	struct vfio_platform_device *vdev = device_data;
+	int ret;
+
 	if (!try_module_get(THIS_MODULE))
 		return -ENODEV;
 
+	mutex_lock(&driver_lock);
+
+	if (!vdev->refcnt) {
+		ret = vfio_platform_regions_init(vdev);
+		if (ret)
+			goto err_reg;
+	}
+
+	vdev->refcnt++;
+
+	mutex_unlock(&driver_lock);
 	return 0;
+
+err_reg:
+	mutex_unlock(&driver_lock);
+	module_put(THIS_MODULE);
+	return ret;
 }
 
 static long vfio_platform_ioctl(void *device_data,
@@ -53,15 +133,33 @@ static long vfio_platform_ioctl(void *device_data,
 			return -EINVAL;
 
 		info.flags = vdev->flags;
-		info.num_regions = 0;
+		info.num_regions = vdev->num_regions;
 		info.num_irqs = 0;
 
 		return copy_to_user((void __user *)arg, &info, minsz);
 
-	} else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
-		return -EINVAL;
+	} else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
+		struct vfio_region_info info;
+
+		minsz = offsetofend(struct vfio_region_info, offset);
+
+		if (copy_from_user(&info, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (info.argsz < minsz)
+			return -EINVAL;
+
+		if (info.index >= vdev->num_regions)
+			return -EINVAL;
+
+		/* map offset to the physical address  */
+		info.offset = VFIO_PLATFORM_INDEX_TO_OFFSET(info.index);
+		info.size = vdev->regions[info.index].size;
+		info.flags = vdev->regions[info.index].flags;
+
+		return copy_to_user((void __user *)arg, &info, minsz);
 
-	else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
+	} else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
 		return -EINVAL;
 
 	else if (cmd == VFIO_DEVICE_SET_IRQS)
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 062b92d..b24729f 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -15,7 +15,29 @@
 #ifndef VFIO_PLATFORM_PRIVATE_H
 #define VFIO_PLATFORM_PRIVATE_H
 
+#define VFIO_PLATFORM_OFFSET_SHIFT   40
+#define VFIO_PLATFORM_OFFSET_MASK (((u64)(1) << VFIO_PLATFORM_OFFSET_SHIFT) - 1)
+
+#define VFIO_PLATFORM_OFFSET_TO_INDEX(off)	\
+	(off >> VFIO_PLATFORM_OFFSET_SHIFT)
+
+#define VFIO_PLATFORM_INDEX_TO_OFFSET(index)	\
+	((u64)(index) << VFIO_PLATFORM_OFFSET_SHIFT)
+
+struct vfio_platform_region {
+	u64			addr;
+	resource_size_t		size;
+	u32			flags;
+	u32			type;
+#define VFIO_PLATFORM_REGION_TYPE_MMIO	1
+#define VFIO_PLATFORM_REGION_TYPE_PIO	2
+};
+
 struct vfio_platform_device {
+	struct vfio_platform_region	*regions;
+	u32				num_regions;
+	int				refcnt;
+
 	/*
 	 * These fields should be filled by the bus specific binder
 	 */
-- 
2.1.4


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

* [PATCH v11 07/20] vfio/platform: return info for device memory mapped IO regions
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list:VFIO DRIVER, open list

This patch enables the IOCTLs VFIO_DEVICE_GET_REGION_INFO ioctl call,
which allows the user to learn about the available MMIO resources of
a device.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_common.c  | 106 +++++++++++++++++++++++++-
 drivers/vfio/platform/vfio_platform_private.h |  22 ++++++
 2 files changed, 124 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 862b43b..2a4613c 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -22,17 +22,97 @@
 
 #include "vfio_platform_private.h"
 
+static DEFINE_MUTEX(driver_lock);
+
+static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
+{
+	int cnt = 0, i;
+
+	while (vdev->get_resource(vdev, cnt))
+		cnt++;
+
+	vdev->regions = kcalloc(cnt, sizeof(struct vfio_platform_region),
+				GFP_KERNEL);
+	if (!vdev->regions)
+		return -ENOMEM;
+
+	for (i = 0; i < cnt;  i++) {
+		struct resource *res =
+			vdev->get_resource(vdev, i);
+
+		if (!res)
+			goto err;
+
+		vdev->regions[i].addr = res->start;
+		vdev->regions[i].size = resource_size(res);
+		vdev->regions[i].flags = 0;
+
+		switch (resource_type(res)) {
+		case IORESOURCE_MEM:
+			vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_MMIO;
+			break;
+		case IORESOURCE_IO:
+			vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
+			break;
+		default:
+			goto err;
+		}
+	}
+
+	vdev->num_regions = cnt;
+
+	return 0;
+err:
+	kfree(vdev->regions);
+	return -EINVAL;
+}
+
+static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
+{
+	vdev->num_regions = 0;
+	kfree(vdev->regions);
+}
+
 static void vfio_platform_release(void *device_data)
 {
+	struct vfio_platform_device *vdev = device_data;
+
+	mutex_lock(&driver_lock);
+
+	if (!(--vdev->refcnt)) {
+		vfio_platform_regions_cleanup(vdev);
+	}
+
+	mutex_unlock(&driver_lock);
+
 	module_put(THIS_MODULE);
 }
 
 static int vfio_platform_open(void *device_data)
 {
+	struct vfio_platform_device *vdev = device_data;
+	int ret;
+
 	if (!try_module_get(THIS_MODULE))
 		return -ENODEV;
 
+	mutex_lock(&driver_lock);
+
+	if (!vdev->refcnt) {
+		ret = vfio_platform_regions_init(vdev);
+		if (ret)
+			goto err_reg;
+	}
+
+	vdev->refcnt++;
+
+	mutex_unlock(&driver_lock);
 	return 0;
+
+err_reg:
+	mutex_unlock(&driver_lock);
+	module_put(THIS_MODULE);
+	return ret;
 }
 
 static long vfio_platform_ioctl(void *device_data,
@@ -53,15 +133,33 @@ static long vfio_platform_ioctl(void *device_data,
 			return -EINVAL;
 
 		info.flags = vdev->flags;
-		info.num_regions = 0;
+		info.num_regions = vdev->num_regions;
 		info.num_irqs = 0;
 
 		return copy_to_user((void __user *)arg, &info, minsz);
 
-	} else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
-		return -EINVAL;
+	} else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
+		struct vfio_region_info info;
+
+		minsz = offsetofend(struct vfio_region_info, offset);
+
+		if (copy_from_user(&info, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (info.argsz < minsz)
+			return -EINVAL;
+
+		if (info.index >= vdev->num_regions)
+			return -EINVAL;
+
+		/* map offset to the physical address  */
+		info.offset = VFIO_PLATFORM_INDEX_TO_OFFSET(info.index);
+		info.size = vdev->regions[info.index].size;
+		info.flags = vdev->regions[info.index].flags;
+
+		return copy_to_user((void __user *)arg, &info, minsz);
 
-	else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
+	} else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
 		return -EINVAL;
 
 	else if (cmd == VFIO_DEVICE_SET_IRQS)
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 062b92d..b24729f 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -15,7 +15,29 @@
 #ifndef VFIO_PLATFORM_PRIVATE_H
 #define VFIO_PLATFORM_PRIVATE_H
 
+#define VFIO_PLATFORM_OFFSET_SHIFT   40
+#define VFIO_PLATFORM_OFFSET_MASK (((u64)(1) << VFIO_PLATFORM_OFFSET_SHIFT) - 1)
+
+#define VFIO_PLATFORM_OFFSET_TO_INDEX(off)	\
+	(off >> VFIO_PLATFORM_OFFSET_SHIFT)
+
+#define VFIO_PLATFORM_INDEX_TO_OFFSET(index)	\
+	((u64)(index) << VFIO_PLATFORM_OFFSET_SHIFT)
+
+struct vfio_platform_region {
+	u64			addr;
+	resource_size_t		size;
+	u32			flags;
+	u32			type;
+#define VFIO_PLATFORM_REGION_TYPE_MMIO	1
+#define VFIO_PLATFORM_REGION_TYPE_PIO	2
+};
+
 struct vfio_platform_device {
+	struct vfio_platform_region	*regions;
+	u32				num_regions;
+	int				refcnt;
+
 	/*
 	 * These fields should be filled by the bus specific binder
 	 */
-- 
2.1.4

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

* [PATCH v11 08/20] vfio/platform: read and write support for the device fd
       [not found] ` <1420541335-17190-1-git-send-email-a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-09  8:39   ` Eric Auger
  2015-01-19 18:39   ` Alex Williamson
  2 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list:VFIO DRIVER, open list

VFIO returns a file descriptor which we can use to manipulate the memory
regions of the device. Usually, the user will mmap memory regions that are
addressable on page boundaries, however for memory regions where this is
not the case we cannot provide mmap functionality due to security concerns.
For this reason we also allow to use read and write functions to the file
descriptor pointing to the memory regions.

We implement this functionality only for MMIO regions of platform devices;
PIO regions are not being handled at this point.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_common.c  | 150 ++++++++++++++++++++++++++
 drivers/vfio/platform/vfio_platform_private.h |   1 +
 2 files changed, 151 insertions(+)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 2a4613c..fda4c30 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -50,6 +50,10 @@ static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
 		switch (resource_type(res)) {
 		case IORESOURCE_MEM:
 			vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_MMIO;
+			vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ;
+			if (!(res->flags & IORESOURCE_READONLY))
+				vdev->regions[i].flags |=
+					VFIO_REGION_INFO_FLAG_WRITE;
 			break;
 		case IORESOURCE_IO:
 			vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
@@ -69,6 +73,11 @@ err:
 
 static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
 {
+	int i;
+
+	for (i = 0; i < vdev->num_regions; i++)
+		iounmap(vdev->regions[i].ioaddr);
+
 	vdev->num_regions = 0;
 	kfree(vdev->regions);
 }
@@ -171,15 +180,156 @@ static long vfio_platform_ioctl(void *device_data,
 	return -ENOTTY;
 }
 
+static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
+				       char __user *buf, size_t count,
+				       loff_t off)
+{
+	unsigned int done = 0;
+
+	if (!reg.ioaddr) {
+		reg.ioaddr =
+			ioremap_nocache(reg.addr, reg.size);
+
+		if (!reg.ioaddr)
+			return -ENOMEM;
+	}
+
+	while (count) {
+		size_t filled;
+
+		if (count >= 4 && !(off % 4)) {
+			u32 val;
+
+			val = ioread32(reg.ioaddr + off);
+			if (copy_to_user(buf, &val, 4))
+				goto err;
+
+			filled = 4;
+		} else if (count >= 2 && !(off % 2)) {
+			u16 val;
+
+			val = ioread16(reg.ioaddr + off);
+			if (copy_to_user(buf, &val, 2))
+				goto err;
+
+			filled = 2;
+		} else {
+			u8 val;
+
+			val = ioread8(reg.ioaddr + off);
+			if (copy_to_user(buf, &val, 1))
+				goto err;
+
+			filled = 1;
+		}
+
+
+		count -= filled;
+		done += filled;
+		off += filled;
+		buf += filled;
+	}
+
+	return done;
+err:
+	return -EFAULT;
+}
+
 static ssize_t vfio_platform_read(void *device_data, char __user *buf,
 				  size_t count, loff_t *ppos)
 {
+	struct vfio_platform_device *vdev = device_data;
+	unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos);
+	loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK;
+
+	if (index >= vdev->num_regions)
+		return -EINVAL;
+
+	if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ))
+		return -EINVAL;
+
+	if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
+		return vfio_platform_read_mmio(vdev->regions[index],
+							buf, count, off);
+	else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
+		return -EINVAL; /* not implemented */
+
 	return -EINVAL;
 }
 
+static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
+					const char __user *buf, size_t count,
+					loff_t off)
+{
+	unsigned int done = 0;
+
+	if (!reg.ioaddr) {
+		reg.ioaddr =
+			ioremap_nocache(reg.addr, reg.size);
+
+		if (!reg.ioaddr)
+			return -ENOMEM;
+	}
+
+	while (count) {
+		size_t filled;
+
+		if (count >= 4 && !(off % 4)) {
+			u32 val;
+
+			if (copy_from_user(&val, buf, 4))
+				goto err;
+			iowrite32(val, reg.ioaddr + off);
+
+			filled = 4;
+		} else if (count >= 2 && !(off % 2)) {
+			u16 val;
+
+			if (copy_from_user(&val, buf, 2))
+				goto err;
+			iowrite16(val, reg.ioaddr + off);
+
+			filled = 2;
+		} else {
+			u8 val;
+
+			if (copy_from_user(&val, buf, 1))
+				goto err;
+			iowrite8(val, reg.ioaddr + off);
+
+			filled = 1;
+		}
+
+		count -= filled;
+		done += filled;
+		off += filled;
+		buf += filled;
+	}
+
+	return done;
+err:
+	return -EFAULT;
+}
+
 static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
 				   size_t count, loff_t *ppos)
 {
+	struct vfio_platform_device *vdev = device_data;
+	unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos);
+	loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK;
+
+	if (index >= vdev->num_regions)
+		return -EINVAL;
+
+	if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE))
+		return -EINVAL;
+
+	if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
+		return vfio_platform_write_mmio(vdev->regions[index],
+							buf, count, off);
+	else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
+		return -EINVAL; /* not implemented */
+
 	return -EINVAL;
 }
 
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index b24729f..1f251b2 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -31,6 +31,7 @@ struct vfio_platform_region {
 	u32			type;
 #define VFIO_PLATFORM_REGION_TYPE_MMIO	1
 #define VFIO_PLATFORM_REGION_TYPE_PIO	2
+	void __iomem		*ioaddr;
 };
 
 struct vfio_platform_device {
-- 
2.1.4


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

* [PATCH v11 08/20] vfio/platform: read and write support for the device fd
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	alex.williamson-H+wXaHxf7aLQT0dZR+AlfA
  Cc: open list:VFIO DRIVER, eric.auger-QSEj5FYQhm4dnm+yROfE0A,
	marc.zyngier-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8, open list,
	Antonios Motakis, tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J,
	christoffer.dall-QSEj5FYQhm4dnm+yROfE0A

VFIO returns a file descriptor which we can use to manipulate the memory
regions of the device. Usually, the user will mmap memory regions that are
addressable on page boundaries, however for memory regions where this is
not the case we cannot provide mmap functionality due to security concerns.
For this reason we also allow to use read and write functions to the file
descriptor pointing to the memory regions.

We implement this functionality only for MMIO regions of platform devices;
PIO regions are not being handled at this point.

Signed-off-by: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
---
 drivers/vfio/platform/vfio_platform_common.c  | 150 ++++++++++++++++++++++++++
 drivers/vfio/platform/vfio_platform_private.h |   1 +
 2 files changed, 151 insertions(+)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 2a4613c..fda4c30 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -50,6 +50,10 @@ static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
 		switch (resource_type(res)) {
 		case IORESOURCE_MEM:
 			vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_MMIO;
+			vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ;
+			if (!(res->flags & IORESOURCE_READONLY))
+				vdev->regions[i].flags |=
+					VFIO_REGION_INFO_FLAG_WRITE;
 			break;
 		case IORESOURCE_IO:
 			vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
@@ -69,6 +73,11 @@ err:
 
 static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
 {
+	int i;
+
+	for (i = 0; i < vdev->num_regions; i++)
+		iounmap(vdev->regions[i].ioaddr);
+
 	vdev->num_regions = 0;
 	kfree(vdev->regions);
 }
@@ -171,15 +180,156 @@ static long vfio_platform_ioctl(void *device_data,
 	return -ENOTTY;
 }
 
+static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
+				       char __user *buf, size_t count,
+				       loff_t off)
+{
+	unsigned int done = 0;
+
+	if (!reg.ioaddr) {
+		reg.ioaddr =
+			ioremap_nocache(reg.addr, reg.size);
+
+		if (!reg.ioaddr)
+			return -ENOMEM;
+	}
+
+	while (count) {
+		size_t filled;
+
+		if (count >= 4 && !(off % 4)) {
+			u32 val;
+
+			val = ioread32(reg.ioaddr + off);
+			if (copy_to_user(buf, &val, 4))
+				goto err;
+
+			filled = 4;
+		} else if (count >= 2 && !(off % 2)) {
+			u16 val;
+
+			val = ioread16(reg.ioaddr + off);
+			if (copy_to_user(buf, &val, 2))
+				goto err;
+
+			filled = 2;
+		} else {
+			u8 val;
+
+			val = ioread8(reg.ioaddr + off);
+			if (copy_to_user(buf, &val, 1))
+				goto err;
+
+			filled = 1;
+		}
+
+
+		count -= filled;
+		done += filled;
+		off += filled;
+		buf += filled;
+	}
+
+	return done;
+err:
+	return -EFAULT;
+}
+
 static ssize_t vfio_platform_read(void *device_data, char __user *buf,
 				  size_t count, loff_t *ppos)
 {
+	struct vfio_platform_device *vdev = device_data;
+	unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos);
+	loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK;
+
+	if (index >= vdev->num_regions)
+		return -EINVAL;
+
+	if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ))
+		return -EINVAL;
+
+	if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
+		return vfio_platform_read_mmio(vdev->regions[index],
+							buf, count, off);
+	else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
+		return -EINVAL; /* not implemented */
+
 	return -EINVAL;
 }
 
+static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
+					const char __user *buf, size_t count,
+					loff_t off)
+{
+	unsigned int done = 0;
+
+	if (!reg.ioaddr) {
+		reg.ioaddr =
+			ioremap_nocache(reg.addr, reg.size);
+
+		if (!reg.ioaddr)
+			return -ENOMEM;
+	}
+
+	while (count) {
+		size_t filled;
+
+		if (count >= 4 && !(off % 4)) {
+			u32 val;
+
+			if (copy_from_user(&val, buf, 4))
+				goto err;
+			iowrite32(val, reg.ioaddr + off);
+
+			filled = 4;
+		} else if (count >= 2 && !(off % 2)) {
+			u16 val;
+
+			if (copy_from_user(&val, buf, 2))
+				goto err;
+			iowrite16(val, reg.ioaddr + off);
+
+			filled = 2;
+		} else {
+			u8 val;
+
+			if (copy_from_user(&val, buf, 1))
+				goto err;
+			iowrite8(val, reg.ioaddr + off);
+
+			filled = 1;
+		}
+
+		count -= filled;
+		done += filled;
+		off += filled;
+		buf += filled;
+	}
+
+	return done;
+err:
+	return -EFAULT;
+}
+
 static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
 				   size_t count, loff_t *ppos)
 {
+	struct vfio_platform_device *vdev = device_data;
+	unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos);
+	loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK;
+
+	if (index >= vdev->num_regions)
+		return -EINVAL;
+
+	if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE))
+		return -EINVAL;
+
+	if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
+		return vfio_platform_write_mmio(vdev->regions[index],
+							buf, count, off);
+	else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
+		return -EINVAL; /* not implemented */
+
 	return -EINVAL;
 }
 
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index b24729f..1f251b2 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -31,6 +31,7 @@ struct vfio_platform_region {
 	u32			type;
 #define VFIO_PLATFORM_REGION_TYPE_MMIO	1
 #define VFIO_PLATFORM_REGION_TYPE_PIO	2
+	void __iomem		*ioaddr;
 };
 
 struct vfio_platform_device {
-- 
2.1.4

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

* [PATCH v11 09/20] vfio/platform: support MMAP of MMIO regions
  2015-01-06 10:48 [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Antonios Motakis
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-06 10:48   ` Antonios Motakis
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list:VFIO DRIVER, open list

Allow to memory map the MMIO regions of the device so userspace can
directly access them. PIO regions are not being handled at this point.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_common.c | 65 ++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index fda4c30..6bf78ee 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -54,6 +54,16 @@ static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
 			if (!(res->flags & IORESOURCE_READONLY))
 				vdev->regions[i].flags |=
 					VFIO_REGION_INFO_FLAG_WRITE;
+
+			/*
+			 * Only regions addressed with PAGE granularity may be
+			 * MMAPed securely.
+			 */
+			if (!(vdev->regions[i].addr & ~PAGE_MASK) &&
+					!(vdev->regions[i].size & ~PAGE_MASK))
+				vdev->regions[i].flags |=
+					VFIO_REGION_INFO_FLAG_MMAP;
+
 			break;
 		case IORESOURCE_IO:
 			vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
@@ -333,8 +343,63 @@ static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
 	return -EINVAL;
 }
 
+static int vfio_platform_mmap_mmio(struct vfio_platform_region region,
+				   struct vm_area_struct *vma)
+{
+	u64 req_len, pgoff, req_start;
+
+	req_len = vma->vm_end - vma->vm_start;
+	pgoff = vma->vm_pgoff &
+		((1U << (VFIO_PLATFORM_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
+	req_start = pgoff << PAGE_SHIFT;
+
+	if (region.size < PAGE_SIZE || req_start + req_len > region.size)
+		return -EINVAL;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff;
+
+	return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+			       req_len, vma->vm_page_prot);
+}
+
 static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma)
 {
+	struct vfio_platform_device *vdev = device_data;
+	unsigned int index;
+
+	index = vma->vm_pgoff >> (VFIO_PLATFORM_OFFSET_SHIFT - PAGE_SHIFT);
+
+	if (vma->vm_end < vma->vm_start)
+		return -EINVAL;
+	if (!(vma->vm_flags & VM_SHARED))
+		return -EINVAL;
+	if (index >= vdev->num_regions)
+		return -EINVAL;
+	if (vma->vm_start & ~PAGE_MASK)
+		return -EINVAL;
+	if (vma->vm_end & ~PAGE_MASK)
+		return -EINVAL;
+
+	if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_MMAP))
+		return -EINVAL;
+
+	if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ)
+			&& (vma->vm_flags & VM_READ))
+		return -EINVAL;
+
+	if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE)
+			&& (vma->vm_flags & VM_WRITE))
+		return -EINVAL;
+
+	vma->vm_private_data = vdev;
+
+	if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
+		return vfio_platform_mmap_mmio(vdev->regions[index], vma);
+
+	else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
+		return -EINVAL; /* not implemented */
+
 	return -EINVAL;
 }
 
-- 
2.1.4


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

* [PATCH v11 09/20] vfio/platform: support MMAP of MMIO regions
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list:VFIO DRIVER, open list

Allow to memory map the MMIO regions of the device so userspace can
directly access them. PIO regions are not being handled at this point.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_common.c | 65 ++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index fda4c30..6bf78ee 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -54,6 +54,16 @@ static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
 			if (!(res->flags & IORESOURCE_READONLY))
 				vdev->regions[i].flags |=
 					VFIO_REGION_INFO_FLAG_WRITE;
+
+			/*
+			 * Only regions addressed with PAGE granularity may be
+			 * MMAPed securely.
+			 */
+			if (!(vdev->regions[i].addr & ~PAGE_MASK) &&
+					!(vdev->regions[i].size & ~PAGE_MASK))
+				vdev->regions[i].flags |=
+					VFIO_REGION_INFO_FLAG_MMAP;
+
 			break;
 		case IORESOURCE_IO:
 			vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
@@ -333,8 +343,63 @@ static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
 	return -EINVAL;
 }
 
+static int vfio_platform_mmap_mmio(struct vfio_platform_region region,
+				   struct vm_area_struct *vma)
+{
+	u64 req_len, pgoff, req_start;
+
+	req_len = vma->vm_end - vma->vm_start;
+	pgoff = vma->vm_pgoff &
+		((1U << (VFIO_PLATFORM_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
+	req_start = pgoff << PAGE_SHIFT;
+
+	if (region.size < PAGE_SIZE || req_start + req_len > region.size)
+		return -EINVAL;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff;
+
+	return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+			       req_len, vma->vm_page_prot);
+}
+
 static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma)
 {
+	struct vfio_platform_device *vdev = device_data;
+	unsigned int index;
+
+	index = vma->vm_pgoff >> (VFIO_PLATFORM_OFFSET_SHIFT - PAGE_SHIFT);
+
+	if (vma->vm_end < vma->vm_start)
+		return -EINVAL;
+	if (!(vma->vm_flags & VM_SHARED))
+		return -EINVAL;
+	if (index >= vdev->num_regions)
+		return -EINVAL;
+	if (vma->vm_start & ~PAGE_MASK)
+		return -EINVAL;
+	if (vma->vm_end & ~PAGE_MASK)
+		return -EINVAL;
+
+	if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_MMAP))
+		return -EINVAL;
+
+	if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ)
+			&& (vma->vm_flags & VM_READ))
+		return -EINVAL;
+
+	if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE)
+			&& (vma->vm_flags & VM_WRITE))
+		return -EINVAL;
+
+	vma->vm_private_data = vdev;
+
+	if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
+		return vfio_platform_mmap_mmio(vdev->regions[index], vma);
+
+	else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
+		return -EINVAL; /* not implemented */
+
 	return -EINVAL;
 }
 
-- 
2.1.4

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

* [PATCH v11 10/20] vfio/platform: return IRQ info
  2015-01-06 10:48 [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Antonios Motakis
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-06 10:48   ` Antonios Motakis
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list, open list:VFIO DRIVER

Return information for the interrupts exposed by the device.
This patch extends VFIO_DEVICE_GET_INFO with the number of IRQs
and enables VFIO_DEVICE_GET_IRQ_INFO.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/Makefile                |  2 +-
 drivers/vfio/platform/vfio_platform_common.c  | 31 +++++++++++++---
 drivers/vfio/platform/vfio_platform_irq.c     | 51 +++++++++++++++++++++++++++
 drivers/vfio/platform/vfio_platform_private.h | 10 ++++++
 4 files changed, 89 insertions(+), 5 deletions(-)
 create mode 100644 drivers/vfio/platform/vfio_platform_irq.c

diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
index 1957170..81de144 100644
--- a/drivers/vfio/platform/Makefile
+++ b/drivers/vfio/platform/Makefile
@@ -1,5 +1,5 @@
 
-vfio-platform-y := vfio_platform.o vfio_platform_common.o
+vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o
 
 obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
 
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 6bf78ee..cf7bb08 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -100,6 +100,7 @@ static void vfio_platform_release(void *device_data)
 
 	if (!(--vdev->refcnt)) {
 		vfio_platform_regions_cleanup(vdev);
+		vfio_platform_irq_cleanup(vdev);
 	}
 
 	mutex_unlock(&driver_lock);
@@ -121,6 +122,10 @@ static int vfio_platform_open(void *device_data)
 		ret = vfio_platform_regions_init(vdev);
 		if (ret)
 			goto err_reg;
+
+		ret = vfio_platform_irq_init(vdev);
+		if (ret)
+			goto err_irq;
 	}
 
 	vdev->refcnt++;
@@ -128,6 +133,8 @@ static int vfio_platform_open(void *device_data)
 	mutex_unlock(&driver_lock);
 	return 0;
 
+err_irq:
+	vfio_platform_regions_cleanup(vdev);
 err_reg:
 	mutex_unlock(&driver_lock);
 	module_put(THIS_MODULE);
@@ -153,7 +160,7 @@ static long vfio_platform_ioctl(void *device_data,
 
 		info.flags = vdev->flags;
 		info.num_regions = vdev->num_regions;
-		info.num_irqs = 0;
+		info.num_irqs = vdev->num_irqs;
 
 		return copy_to_user((void __user *)arg, &info, minsz);
 
@@ -178,10 +185,26 @@ static long vfio_platform_ioctl(void *device_data,
 
 		return copy_to_user((void __user *)arg, &info, minsz);
 
-	} else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
-		return -EINVAL;
+	} else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
+		struct vfio_irq_info info;
+
+		minsz = offsetofend(struct vfio_irq_info, count);
+
+		if (copy_from_user(&info, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (info.argsz < minsz)
+			return -EINVAL;
+
+		if (info.index >= vdev->num_irqs)
+			return -EINVAL;
+
+		info.flags = vdev->irqs[info.index].flags;
+		info.count = vdev->irqs[info.index].count;
+
+		return copy_to_user((void __user *)arg, &info, minsz);
 
-	else if (cmd == VFIO_DEVICE_SET_IRQS)
+	} else if (cmd == VFIO_DEVICE_SET_IRQS)
 		return -EINVAL;
 
 	else if (cmd == VFIO_DEVICE_RESET)
diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c
new file mode 100644
index 0000000..c6c3ec1
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -0,0 +1,51 @@
+/*
+ * VFIO platform devices interrupt handling
+ *
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis@virtualopensystems.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/eventfd.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/vfio.h>
+#include <linux/irq.h>
+
+#include "vfio_platform_private.h"
+
+int vfio_platform_irq_init(struct vfio_platform_device *vdev)
+{
+	int cnt = 0, i;
+
+	while (vdev->get_irq(vdev, cnt) >= 0)
+		cnt++;
+
+	vdev->irqs = kcalloc(cnt, sizeof(struct vfio_platform_irq), GFP_KERNEL);
+	if (!vdev->irqs)
+		return -ENOMEM;
+
+	for (i = 0; i < cnt; i++) {
+		vdev->irqs[i].flags = 0;
+		vdev->irqs[i].count = 1;
+	}
+
+	vdev->num_irqs = cnt;
+
+	return 0;
+}
+
+void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev)
+{
+	vdev->num_irqs = 0;
+	kfree(vdev->irqs);
+}
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 1f251b2..3a29a72 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -24,6 +24,11 @@
 #define VFIO_PLATFORM_INDEX_TO_OFFSET(index)	\
 	((u64)(index) << VFIO_PLATFORM_OFFSET_SHIFT)
 
+struct vfio_platform_irq {
+	u32			flags;
+	u32			count;
+};
+
 struct vfio_platform_region {
 	u64			addr;
 	resource_size_t		size;
@@ -37,6 +42,8 @@ struct vfio_platform_region {
 struct vfio_platform_device {
 	struct vfio_platform_region	*regions;
 	u32				num_regions;
+	struct vfio_platform_irq	*irqs;
+	u32				num_irqs;
 	int				refcnt;
 
 	/*
@@ -56,4 +63,7 @@ extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 extern struct vfio_platform_device *vfio_platform_remove_common
 				     (struct device *dev);
 
+extern int vfio_platform_irq_init(struct vfio_platform_device *vdev);
+extern void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev);
+
 #endif /* VFIO_PLATFORM_PRIVATE_H */
-- 
2.1.4


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

* [PATCH v11 10/20] vfio/platform: return IRQ info
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list, open list:VFIO DRIVER

Return information for the interrupts exposed by the device.
This patch extends VFIO_DEVICE_GET_INFO with the number of IRQs
and enables VFIO_DEVICE_GET_IRQ_INFO.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/Makefile                |  2 +-
 drivers/vfio/platform/vfio_platform_common.c  | 31 +++++++++++++---
 drivers/vfio/platform/vfio_platform_irq.c     | 51 +++++++++++++++++++++++++++
 drivers/vfio/platform/vfio_platform_private.h | 10 ++++++
 4 files changed, 89 insertions(+), 5 deletions(-)
 create mode 100644 drivers/vfio/platform/vfio_platform_irq.c

diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
index 1957170..81de144 100644
--- a/drivers/vfio/platform/Makefile
+++ b/drivers/vfio/platform/Makefile
@@ -1,5 +1,5 @@
 
-vfio-platform-y := vfio_platform.o vfio_platform_common.o
+vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o
 
 obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
 
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 6bf78ee..cf7bb08 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -100,6 +100,7 @@ static void vfio_platform_release(void *device_data)
 
 	if (!(--vdev->refcnt)) {
 		vfio_platform_regions_cleanup(vdev);
+		vfio_platform_irq_cleanup(vdev);
 	}
 
 	mutex_unlock(&driver_lock);
@@ -121,6 +122,10 @@ static int vfio_platform_open(void *device_data)
 		ret = vfio_platform_regions_init(vdev);
 		if (ret)
 			goto err_reg;
+
+		ret = vfio_platform_irq_init(vdev);
+		if (ret)
+			goto err_irq;
 	}
 
 	vdev->refcnt++;
@@ -128,6 +133,8 @@ static int vfio_platform_open(void *device_data)
 	mutex_unlock(&driver_lock);
 	return 0;
 
+err_irq:
+	vfio_platform_regions_cleanup(vdev);
 err_reg:
 	mutex_unlock(&driver_lock);
 	module_put(THIS_MODULE);
@@ -153,7 +160,7 @@ static long vfio_platform_ioctl(void *device_data,
 
 		info.flags = vdev->flags;
 		info.num_regions = vdev->num_regions;
-		info.num_irqs = 0;
+		info.num_irqs = vdev->num_irqs;
 
 		return copy_to_user((void __user *)arg, &info, minsz);
 
@@ -178,10 +185,26 @@ static long vfio_platform_ioctl(void *device_data,
 
 		return copy_to_user((void __user *)arg, &info, minsz);
 
-	} else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
-		return -EINVAL;
+	} else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
+		struct vfio_irq_info info;
+
+		minsz = offsetofend(struct vfio_irq_info, count);
+
+		if (copy_from_user(&info, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (info.argsz < minsz)
+			return -EINVAL;
+
+		if (info.index >= vdev->num_irqs)
+			return -EINVAL;
+
+		info.flags = vdev->irqs[info.index].flags;
+		info.count = vdev->irqs[info.index].count;
+
+		return copy_to_user((void __user *)arg, &info, minsz);
 
-	else if (cmd == VFIO_DEVICE_SET_IRQS)
+	} else if (cmd == VFIO_DEVICE_SET_IRQS)
 		return -EINVAL;
 
 	else if (cmd == VFIO_DEVICE_RESET)
diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c
new file mode 100644
index 0000000..c6c3ec1
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -0,0 +1,51 @@
+/*
+ * VFIO platform devices interrupt handling
+ *
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis@virtualopensystems.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/eventfd.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/vfio.h>
+#include <linux/irq.h>
+
+#include "vfio_platform_private.h"
+
+int vfio_platform_irq_init(struct vfio_platform_device *vdev)
+{
+	int cnt = 0, i;
+
+	while (vdev->get_irq(vdev, cnt) >= 0)
+		cnt++;
+
+	vdev->irqs = kcalloc(cnt, sizeof(struct vfio_platform_irq), GFP_KERNEL);
+	if (!vdev->irqs)
+		return -ENOMEM;
+
+	for (i = 0; i < cnt; i++) {
+		vdev->irqs[i].flags = 0;
+		vdev->irqs[i].count = 1;
+	}
+
+	vdev->num_irqs = cnt;
+
+	return 0;
+}
+
+void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev)
+{
+	vdev->num_irqs = 0;
+	kfree(vdev->irqs);
+}
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 1f251b2..3a29a72 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -24,6 +24,11 @@
 #define VFIO_PLATFORM_INDEX_TO_OFFSET(index)	\
 	((u64)(index) << VFIO_PLATFORM_OFFSET_SHIFT)
 
+struct vfio_platform_irq {
+	u32			flags;
+	u32			count;
+};
+
 struct vfio_platform_region {
 	u64			addr;
 	resource_size_t		size;
@@ -37,6 +42,8 @@ struct vfio_platform_region {
 struct vfio_platform_device {
 	struct vfio_platform_region	*regions;
 	u32				num_regions;
+	struct vfio_platform_irq	*irqs;
+	u32				num_irqs;
 	int				refcnt;
 
 	/*
@@ -56,4 +63,7 @@ extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 extern struct vfio_platform_device *vfio_platform_remove_common
 				     (struct device *dev);
 
+extern int vfio_platform_irq_init(struct vfio_platform_device *vdev);
+extern void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev);
+
 #endif /* VFIO_PLATFORM_PRIVATE_H */
-- 
2.1.4

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

* [PATCH v11 11/20] vfio/platform: initial interrupts support code
       [not found] ` <1420541335-17190-1-git-send-email-a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-09  8:39   ` Eric Auger
  2015-01-19 18:39   ` Alex Williamson
  2 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list:VFIO DRIVER, open list

This patch is a skeleton for the VFIO_DEVICE_SET_IRQS IOCTL, around which
most IRQ functionality is implemented in VFIO.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_common.c  | 52 +++++++++++++++++++++--
 drivers/vfio/platform/vfio_platform_irq.c     | 59 +++++++++++++++++++++++++++
 drivers/vfio/platform/vfio_platform_private.h |  7 ++++
 3 files changed, 115 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index cf7bb08..a532a25 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -204,10 +204,54 @@ static long vfio_platform_ioctl(void *device_data,
 
 		return copy_to_user((void __user *)arg, &info, minsz);
 
-	} else if (cmd == VFIO_DEVICE_SET_IRQS)
-		return -EINVAL;
+	} else if (cmd == VFIO_DEVICE_SET_IRQS) {
+		struct vfio_irq_set hdr;
+		u8 *data = NULL;
+		int ret = 0;
+
+		minsz = offsetofend(struct vfio_irq_set, count);
+
+		if (copy_from_user(&hdr, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (hdr.argsz < minsz)
+			return -EINVAL;
+
+		if (hdr.index >= vdev->num_irqs)
+			return -EINVAL;
+
+		if (hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK |
+				  VFIO_IRQ_SET_ACTION_TYPE_MASK))
+			return -EINVAL;
 
-	else if (cmd == VFIO_DEVICE_RESET)
+		if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
+			size_t size;
+
+			if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL)
+				size = sizeof(uint8_t);
+			else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD)
+				size = sizeof(int32_t);
+			else
+				return -EINVAL;
+
+			if (hdr.argsz - minsz < size)
+				return -EINVAL;
+
+			data = memdup_user((void __user *)(arg + minsz), size);
+			if (IS_ERR(data))
+				return PTR_ERR(data);
+		}
+
+		mutex_lock(&vdev->igate);
+
+		ret = vfio_platform_set_irqs_ioctl(vdev, hdr.flags, hdr.index,
+						   hdr.start, hdr.count, data);
+		mutex_unlock(&vdev->igate);
+		kfree(data);
+
+		return ret;
+
+	} else if (cmd == VFIO_DEVICE_RESET)
 		return -EINVAL;
 
 	return -ENOTTY;
@@ -457,6 +501,8 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 		return ret;
 	}
 
+	mutex_init(&vdev->igate);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(vfio_platform_probe_common);
diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c
index c6c3ec1..df5c919 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -23,6 +23,56 @@
 
 #include "vfio_platform_private.h"
 
+static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
+				      unsigned index, unsigned start,
+				      unsigned count, uint32_t flags,
+				      void *data)
+{
+	return -EINVAL;
+}
+
+static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
+					unsigned index, unsigned start,
+					unsigned count, uint32_t flags,
+					void *data)
+{
+	return -EINVAL;
+}
+
+static int vfio_platform_set_irq_trigger(struct vfio_platform_device *vdev,
+					 unsigned index, unsigned start,
+					 unsigned count, uint32_t flags,
+					 void *data)
+{
+	return -EINVAL;
+}
+
+int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
+				 uint32_t flags, unsigned index, unsigned start,
+				 unsigned count, void *data)
+{
+	int (*func)(struct vfio_platform_device *vdev, unsigned index,
+		    unsigned start, unsigned count, uint32_t flags,
+		    void *data) = NULL;
+
+	switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {
+	case VFIO_IRQ_SET_ACTION_MASK:
+		func = vfio_platform_set_irq_mask;
+		break;
+	case VFIO_IRQ_SET_ACTION_UNMASK:
+		func = vfio_platform_set_irq_unmask;
+		break;
+	case VFIO_IRQ_SET_ACTION_TRIGGER:
+		func = vfio_platform_set_irq_trigger;
+		break;
+	}
+
+	if (!func)
+		return -ENOTTY;
+
+	return func(vdev, index, start, count, flags, data);
+}
+
 int vfio_platform_irq_init(struct vfio_platform_device *vdev)
 {
 	int cnt = 0, i;
@@ -35,13 +85,22 @@ int vfio_platform_irq_init(struct vfio_platform_device *vdev)
 		return -ENOMEM;
 
 	for (i = 0; i < cnt; i++) {
+		int hwirq = vdev->get_irq(vdev, i);
+
+		if (hwirq < 0)
+			goto err;
+
 		vdev->irqs[i].flags = 0;
 		vdev->irqs[i].count = 1;
+		vdev->irqs[i].hwirq = hwirq;
 	}
 
 	vdev->num_irqs = cnt;
 
 	return 0;
+err:
+	kfree(vdev->irqs);
+	return -EINVAL;
 }
 
 void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev)
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 3a29a72..61f3ed4 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -27,6 +27,7 @@
 struct vfio_platform_irq {
 	u32			flags;
 	u32			count;
+	int			hwirq;
 };
 
 struct vfio_platform_region {
@@ -45,6 +46,7 @@ struct vfio_platform_device {
 	struct vfio_platform_irq	*irqs;
 	u32				num_irqs;
 	int				refcnt;
+	struct mutex			igate;
 
 	/*
 	 * These fields should be filled by the bus specific binder
@@ -66,4 +68,9 @@ extern struct vfio_platform_device *vfio_platform_remove_common
 extern int vfio_platform_irq_init(struct vfio_platform_device *vdev);
 extern void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev);
 
+extern int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
+					uint32_t flags, unsigned index,
+					unsigned start, unsigned count,
+					void *data);
+
 #endif /* VFIO_PLATFORM_PRIVATE_H */
-- 
2.1.4


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

* [PATCH v11 11/20] vfio/platform: initial interrupts support code
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	alex.williamson-H+wXaHxf7aLQT0dZR+AlfA
  Cc: open list:VFIO DRIVER, eric.auger-QSEj5FYQhm4dnm+yROfE0A,
	marc.zyngier-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8, open list,
	Antonios Motakis, tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J,
	christoffer.dall-QSEj5FYQhm4dnm+yROfE0A

This patch is a skeleton for the VFIO_DEVICE_SET_IRQS IOCTL, around which
most IRQ functionality is implemented in VFIO.

Signed-off-by: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
---
 drivers/vfio/platform/vfio_platform_common.c  | 52 +++++++++++++++++++++--
 drivers/vfio/platform/vfio_platform_irq.c     | 59 +++++++++++++++++++++++++++
 drivers/vfio/platform/vfio_platform_private.h |  7 ++++
 3 files changed, 115 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index cf7bb08..a532a25 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -204,10 +204,54 @@ static long vfio_platform_ioctl(void *device_data,
 
 		return copy_to_user((void __user *)arg, &info, minsz);
 
-	} else if (cmd == VFIO_DEVICE_SET_IRQS)
-		return -EINVAL;
+	} else if (cmd == VFIO_DEVICE_SET_IRQS) {
+		struct vfio_irq_set hdr;
+		u8 *data = NULL;
+		int ret = 0;
+
+		minsz = offsetofend(struct vfio_irq_set, count);
+
+		if (copy_from_user(&hdr, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (hdr.argsz < minsz)
+			return -EINVAL;
+
+		if (hdr.index >= vdev->num_irqs)
+			return -EINVAL;
+
+		if (hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK |
+				  VFIO_IRQ_SET_ACTION_TYPE_MASK))
+			return -EINVAL;
 
-	else if (cmd == VFIO_DEVICE_RESET)
+		if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
+			size_t size;
+
+			if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL)
+				size = sizeof(uint8_t);
+			else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD)
+				size = sizeof(int32_t);
+			else
+				return -EINVAL;
+
+			if (hdr.argsz - minsz < size)
+				return -EINVAL;
+
+			data = memdup_user((void __user *)(arg + minsz), size);
+			if (IS_ERR(data))
+				return PTR_ERR(data);
+		}
+
+		mutex_lock(&vdev->igate);
+
+		ret = vfio_platform_set_irqs_ioctl(vdev, hdr.flags, hdr.index,
+						   hdr.start, hdr.count, data);
+		mutex_unlock(&vdev->igate);
+		kfree(data);
+
+		return ret;
+
+	} else if (cmd == VFIO_DEVICE_RESET)
 		return -EINVAL;
 
 	return -ENOTTY;
@@ -457,6 +501,8 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 		return ret;
 	}
 
+	mutex_init(&vdev->igate);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(vfio_platform_probe_common);
diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c
index c6c3ec1..df5c919 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -23,6 +23,56 @@
 
 #include "vfio_platform_private.h"
 
+static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
+				      unsigned index, unsigned start,
+				      unsigned count, uint32_t flags,
+				      void *data)
+{
+	return -EINVAL;
+}
+
+static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
+					unsigned index, unsigned start,
+					unsigned count, uint32_t flags,
+					void *data)
+{
+	return -EINVAL;
+}
+
+static int vfio_platform_set_irq_trigger(struct vfio_platform_device *vdev,
+					 unsigned index, unsigned start,
+					 unsigned count, uint32_t flags,
+					 void *data)
+{
+	return -EINVAL;
+}
+
+int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
+				 uint32_t flags, unsigned index, unsigned start,
+				 unsigned count, void *data)
+{
+	int (*func)(struct vfio_platform_device *vdev, unsigned index,
+		    unsigned start, unsigned count, uint32_t flags,
+		    void *data) = NULL;
+
+	switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {
+	case VFIO_IRQ_SET_ACTION_MASK:
+		func = vfio_platform_set_irq_mask;
+		break;
+	case VFIO_IRQ_SET_ACTION_UNMASK:
+		func = vfio_platform_set_irq_unmask;
+		break;
+	case VFIO_IRQ_SET_ACTION_TRIGGER:
+		func = vfio_platform_set_irq_trigger;
+		break;
+	}
+
+	if (!func)
+		return -ENOTTY;
+
+	return func(vdev, index, start, count, flags, data);
+}
+
 int vfio_platform_irq_init(struct vfio_platform_device *vdev)
 {
 	int cnt = 0, i;
@@ -35,13 +85,22 @@ int vfio_platform_irq_init(struct vfio_platform_device *vdev)
 		return -ENOMEM;
 
 	for (i = 0; i < cnt; i++) {
+		int hwirq = vdev->get_irq(vdev, i);
+
+		if (hwirq < 0)
+			goto err;
+
 		vdev->irqs[i].flags = 0;
 		vdev->irqs[i].count = 1;
+		vdev->irqs[i].hwirq = hwirq;
 	}
 
 	vdev->num_irqs = cnt;
 
 	return 0;
+err:
+	kfree(vdev->irqs);
+	return -EINVAL;
 }
 
 void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev)
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 3a29a72..61f3ed4 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -27,6 +27,7 @@
 struct vfio_platform_irq {
 	u32			flags;
 	u32			count;
+	int			hwirq;
 };
 
 struct vfio_platform_region {
@@ -45,6 +46,7 @@ struct vfio_platform_device {
 	struct vfio_platform_irq	*irqs;
 	u32				num_irqs;
 	int				refcnt;
+	struct mutex			igate;
 
 	/*
 	 * These fields should be filled by the bus specific binder
@@ -66,4 +68,9 @@ extern struct vfio_platform_device *vfio_platform_remove_common
 extern int vfio_platform_irq_init(struct vfio_platform_device *vdev);
 extern void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev);
 
+extern int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
+					uint32_t flags, unsigned index,
+					unsigned start, unsigned count,
+					void *data);
+
 #endif /* VFIO_PLATFORM_PRIVATE_H */
-- 
2.1.4

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

* [PATCH v11 12/20] vfio/platform: trigger an interrupt via eventfd
       [not found] ` <1420541335-17190-1-git-send-email-a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-09  8:39   ` Eric Auger
  2015-01-19 18:39   ` Alex Williamson
  2 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list:VFIO DRIVER, open list

This patch allows to set an eventfd for a platform device's interrupt,
and also to trigger the interrupt eventfd from userspace for testing.
Level sensitive interrupts are marked as maskable and are handled in
a later patch. Edge triggered interrupts are not advertised as maskable
and are implemented here using a simple and efficient IRQ handler.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_irq.c     | 102 +++++++++++++++++++++++++-
 drivers/vfio/platform/vfio_platform_private.h |   2 +
 2 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c
index df5c919..4896581 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -39,12 +39,100 @@ static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
 	return -EINVAL;
 }
 
+static irqreturn_t vfio_irq_handler(int irq, void *dev_id)
+{
+	struct vfio_platform_irq *irq_ctx = dev_id;
+
+	eventfd_signal(irq_ctx->trigger, 1);
+
+	return IRQ_HANDLED;
+}
+
+static int vfio_set_trigger(struct vfio_platform_device *vdev, int index,
+			    int fd, irq_handler_t handler)
+{
+	struct vfio_platform_irq *irq = &vdev->irqs[index];
+	struct eventfd_ctx *trigger;
+	unsigned long flags;
+	int ret;
+
+	if (irq->trigger) {
+		free_irq(irq->hwirq, irq);
+		kfree(irq->name);
+		eventfd_ctx_put(irq->trigger);
+		irq->trigger = NULL;
+	}
+
+	if (fd < 0) /* Disable only */
+		return 0;
+
+	irq->name = kasprintf(GFP_KERNEL, "vfio-irq[%d](%s)",
+						irq->hwirq, vdev->name);
+	if (!irq->name)
+		return -ENOMEM;
+
+	trigger = eventfd_ctx_fdget(fd);
+	if (IS_ERR(trigger)) {
+		kfree(irq->name);
+		return PTR_ERR(trigger);
+	}
+
+	irq->trigger = trigger;
+
+	ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
+	if (ret) {
+		kfree(irq->name);
+		eventfd_ctx_put(trigger);
+		irq->trigger = NULL;
+		return ret;
+	}
+
+	/* if the IRQ has been masked by the user before setting an eventfd,
+	 * then we need to make sure it is properly disabled */
+	spin_lock_irqsave(&irq->lock, flags);
+	if (irq->masked)
+		disable_irq_nosync(irq->hwirq);
+	spin_unlock_irqrestore(&irq->lock, flags);
+
+	return 0;
+}
+
 static int vfio_platform_set_irq_trigger(struct vfio_platform_device *vdev,
 					 unsigned index, unsigned start,
 					 unsigned count, uint32_t flags,
 					 void *data)
 {
-	return -EINVAL;
+	struct vfio_platform_irq *irq = &vdev->irqs[index];
+	irq_handler_t handler;
+
+	if (vdev->irqs[index].flags & VFIO_IRQ_INFO_AUTOMASKED)
+		return -EINVAL; /* not implemented */
+	else
+		handler = vfio_irq_handler;
+
+	if (!count && (flags & VFIO_IRQ_SET_DATA_NONE))
+		return vfio_set_trigger(vdev, index, -1, handler);
+
+	if (start != 0 || count != 1)
+		return -EINVAL;
+
+	if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+		int32_t fd = *(int32_t *)data;
+
+		return vfio_set_trigger(vdev, index, fd, handler);
+	}
+
+	if (flags & VFIO_IRQ_SET_DATA_NONE) {
+		handler(irq->hwirq, irq);
+
+	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+		uint8_t trigger = *(uint8_t *)data;
+
+		if (trigger)
+			handler(irq->hwirq, irq);
+	}
+
+	return 0;
 }
 
 int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
@@ -90,7 +178,12 @@ int vfio_platform_irq_init(struct vfio_platform_device *vdev)
 		if (hwirq < 0)
 			goto err;
 
-		vdev->irqs[i].flags = 0;
+		vdev->irqs[i].flags = VFIO_IRQ_INFO_EVENTFD;
+
+		if (irq_get_trigger_type(hwirq) & IRQ_TYPE_LEVEL_MASK)
+			vdev->irqs[i].flags |= VFIO_IRQ_INFO_MASKABLE
+						| VFIO_IRQ_INFO_AUTOMASKED;
+
 		vdev->irqs[i].count = 1;
 		vdev->irqs[i].hwirq = hwirq;
 	}
@@ -105,6 +198,11 @@ err:
 
 void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev)
 {
+	int i;
+
+	for (i = 0; i < vdev->num_irqs; i++)
+		vfio_set_trigger(vdev, i, -1, NULL);
+
 	vdev->num_irqs = 0;
 	kfree(vdev->irqs);
 }
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 61f3ed4..b705f17 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -28,6 +28,8 @@ struct vfio_platform_irq {
 	u32			flags;
 	u32			count;
 	int			hwirq;
+	char			*name;
+	struct eventfd_ctx	*trigger;
 };
 
 struct vfio_platform_region {
-- 
2.1.4


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

* [PATCH v11 12/20] vfio/platform: trigger an interrupt via eventfd
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	alex.williamson-H+wXaHxf7aLQT0dZR+AlfA
  Cc: open list:VFIO DRIVER, eric.auger-QSEj5FYQhm4dnm+yROfE0A,
	marc.zyngier-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8, open list,
	Antonios Motakis, tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J,
	christoffer.dall-QSEj5FYQhm4dnm+yROfE0A

This patch allows to set an eventfd for a platform device's interrupt,
and also to trigger the interrupt eventfd from userspace for testing.
Level sensitive interrupts are marked as maskable and are handled in
a later patch. Edge triggered interrupts are not advertised as maskable
and are implemented here using a simple and efficient IRQ handler.

Signed-off-by: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
---
 drivers/vfio/platform/vfio_platform_irq.c     | 102 +++++++++++++++++++++++++-
 drivers/vfio/platform/vfio_platform_private.h |   2 +
 2 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c
index df5c919..4896581 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -39,12 +39,100 @@ static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
 	return -EINVAL;
 }
 
+static irqreturn_t vfio_irq_handler(int irq, void *dev_id)
+{
+	struct vfio_platform_irq *irq_ctx = dev_id;
+
+	eventfd_signal(irq_ctx->trigger, 1);
+
+	return IRQ_HANDLED;
+}
+
+static int vfio_set_trigger(struct vfio_platform_device *vdev, int index,
+			    int fd, irq_handler_t handler)
+{
+	struct vfio_platform_irq *irq = &vdev->irqs[index];
+	struct eventfd_ctx *trigger;
+	unsigned long flags;
+	int ret;
+
+	if (irq->trigger) {
+		free_irq(irq->hwirq, irq);
+		kfree(irq->name);
+		eventfd_ctx_put(irq->trigger);
+		irq->trigger = NULL;
+	}
+
+	if (fd < 0) /* Disable only */
+		return 0;
+
+	irq->name = kasprintf(GFP_KERNEL, "vfio-irq[%d](%s)",
+						irq->hwirq, vdev->name);
+	if (!irq->name)
+		return -ENOMEM;
+
+	trigger = eventfd_ctx_fdget(fd);
+	if (IS_ERR(trigger)) {
+		kfree(irq->name);
+		return PTR_ERR(trigger);
+	}
+
+	irq->trigger = trigger;
+
+	ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
+	if (ret) {
+		kfree(irq->name);
+		eventfd_ctx_put(trigger);
+		irq->trigger = NULL;
+		return ret;
+	}
+
+	/* if the IRQ has been masked by the user before setting an eventfd,
+	 * then we need to make sure it is properly disabled */
+	spin_lock_irqsave(&irq->lock, flags);
+	if (irq->masked)
+		disable_irq_nosync(irq->hwirq);
+	spin_unlock_irqrestore(&irq->lock, flags);
+
+	return 0;
+}
+
 static int vfio_platform_set_irq_trigger(struct vfio_platform_device *vdev,
 					 unsigned index, unsigned start,
 					 unsigned count, uint32_t flags,
 					 void *data)
 {
-	return -EINVAL;
+	struct vfio_platform_irq *irq = &vdev->irqs[index];
+	irq_handler_t handler;
+
+	if (vdev->irqs[index].flags & VFIO_IRQ_INFO_AUTOMASKED)
+		return -EINVAL; /* not implemented */
+	else
+		handler = vfio_irq_handler;
+
+	if (!count && (flags & VFIO_IRQ_SET_DATA_NONE))
+		return vfio_set_trigger(vdev, index, -1, handler);
+
+	if (start != 0 || count != 1)
+		return -EINVAL;
+
+	if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+		int32_t fd = *(int32_t *)data;
+
+		return vfio_set_trigger(vdev, index, fd, handler);
+	}
+
+	if (flags & VFIO_IRQ_SET_DATA_NONE) {
+		handler(irq->hwirq, irq);
+
+	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+		uint8_t trigger = *(uint8_t *)data;
+
+		if (trigger)
+			handler(irq->hwirq, irq);
+	}
+
+	return 0;
 }
 
 int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
@@ -90,7 +178,12 @@ int vfio_platform_irq_init(struct vfio_platform_device *vdev)
 		if (hwirq < 0)
 			goto err;
 
-		vdev->irqs[i].flags = 0;
+		vdev->irqs[i].flags = VFIO_IRQ_INFO_EVENTFD;
+
+		if (irq_get_trigger_type(hwirq) & IRQ_TYPE_LEVEL_MASK)
+			vdev->irqs[i].flags |= VFIO_IRQ_INFO_MASKABLE
+						| VFIO_IRQ_INFO_AUTOMASKED;
+
 		vdev->irqs[i].count = 1;
 		vdev->irqs[i].hwirq = hwirq;
 	}
@@ -105,6 +198,11 @@ err:
 
 void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev)
 {
+	int i;
+
+	for (i = 0; i < vdev->num_irqs; i++)
+		vfio_set_trigger(vdev, i, -1, NULL);
+
 	vdev->num_irqs = 0;
 	kfree(vdev->irqs);
 }
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 61f3ed4..b705f17 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -28,6 +28,8 @@ struct vfio_platform_irq {
 	u32			flags;
 	u32			count;
 	int			hwirq;
+	char			*name;
+	struct eventfd_ctx	*trigger;
 };
 
 struct vfio_platform_region {
-- 
2.1.4

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

* [PATCH v11 13/20] vfio/platform: support for level sensitive interrupts
  2015-01-06 10:48 [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Antonios Motakis
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-06 10:48   ` Antonios Motakis
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list:VFIO DRIVER, open list

Level sensitive interrupts are exposed as maskable and automasked
interrupts and are masked and disabled automatically when they fire.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_irq.c     | 99 ++++++++++++++++++++++++++-
 drivers/vfio/platform/vfio_platform_private.h |  2 +
 2 files changed, 98 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c
index 4896581..b3602cb 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -23,12 +23,59 @@
 
 #include "vfio_platform_private.h"
 
+static void vfio_platform_mask(struct vfio_platform_irq *irq_ctx)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&irq_ctx->lock, flags);
+
+	if (!irq_ctx->masked) {
+		disable_irq_nosync(irq_ctx->hwirq);
+		irq_ctx->masked = true;
+	}
+
+	spin_unlock_irqrestore(&irq_ctx->lock, flags);
+}
+
 static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
 				      unsigned index, unsigned start,
 				      unsigned count, uint32_t flags,
 				      void *data)
 {
-	return -EINVAL;
+	if (start != 0 || count != 1)
+		return -EINVAL;
+
+	if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
+		return -EINVAL;
+
+	if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
+		return -EINVAL; /* not implemented yet */
+
+	if (flags & VFIO_IRQ_SET_DATA_NONE) {
+		vfio_platform_mask(&vdev->irqs[index]);
+
+	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+		uint8_t mask = *(uint8_t *)data;
+
+		if (mask)
+			vfio_platform_mask(&vdev->irqs[index]);
+	}
+
+	return 0;
+}
+
+static void vfio_platform_unmask(struct vfio_platform_irq *irq_ctx)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&irq_ctx->lock, flags);
+
+	if (irq_ctx->masked) {
+		enable_irq(irq_ctx->hwirq);
+		irq_ctx->masked = false;
+	}
+
+	spin_unlock_irqrestore(&irq_ctx->lock, flags);
 }
 
 static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
@@ -36,7 +83,50 @@ static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
 					unsigned count, uint32_t flags,
 					void *data)
 {
-	return -EINVAL;
+	if (start != 0 || count != 1)
+		return -EINVAL;
+
+	if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
+		return -EINVAL;
+
+	if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
+		return -EINVAL; /* not implemented yet */
+
+	if (flags & VFIO_IRQ_SET_DATA_NONE) {
+		vfio_platform_unmask(&vdev->irqs[index]);
+
+	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+		uint8_t unmask = *(uint8_t *)data;
+
+		if (unmask)
+			vfio_platform_unmask(&vdev->irqs[index]);
+	}
+
+	return 0;
+}
+
+static irqreturn_t vfio_automasked_irq_handler(int irq, void *dev_id)
+{
+	struct vfio_platform_irq *irq_ctx = dev_id;
+	unsigned long flags;
+	int ret = IRQ_NONE;
+
+	spin_lock_irqsave(&irq_ctx->lock, flags);
+
+	if (!irq_ctx->masked) {
+		ret = IRQ_HANDLED;
+
+		/* automask maskable interrupts */
+		disable_irq_nosync(irq_ctx->hwirq);
+		irq_ctx->masked = true;
+	}
+
+	spin_unlock_irqrestore(&irq_ctx->lock, flags);
+
+	if (ret == IRQ_HANDLED)
+		eventfd_signal(irq_ctx->trigger, 1);
+
+	return ret;
 }
 
 static irqreturn_t vfio_irq_handler(int irq, void *dev_id)
@@ -106,7 +196,7 @@ static int vfio_platform_set_irq_trigger(struct vfio_platform_device *vdev,
 	irq_handler_t handler;
 
 	if (vdev->irqs[index].flags & VFIO_IRQ_INFO_AUTOMASKED)
-		return -EINVAL; /* not implemented */
+		handler = vfio_automasked_irq_handler;
 	else
 		handler = vfio_irq_handler;
 
@@ -178,6 +268,8 @@ int vfio_platform_irq_init(struct vfio_platform_device *vdev)
 		if (hwirq < 0)
 			goto err;
 
+		spin_lock_init(&vdev->irqs[i].lock);
+
 		vdev->irqs[i].flags = VFIO_IRQ_INFO_EVENTFD;
 
 		if (irq_get_trigger_type(hwirq) & IRQ_TYPE_LEVEL_MASK)
@@ -186,6 +278,7 @@ int vfio_platform_irq_init(struct vfio_platform_device *vdev)
 
 		vdev->irqs[i].count = 1;
 		vdev->irqs[i].hwirq = hwirq;
+		vdev->irqs[i].masked = false;
 	}
 
 	vdev->num_irqs = cnt;
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index b705f17..eef6d1b 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -30,6 +30,8 @@ struct vfio_platform_irq {
 	int			hwirq;
 	char			*name;
 	struct eventfd_ctx	*trigger;
+	bool			masked;
+	spinlock_t		lock;
 };
 
 struct vfio_platform_region {
-- 
2.1.4


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

* [PATCH v11 13/20] vfio/platform: support for level sensitive interrupts
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list:VFIO DRIVER, open list

Level sensitive interrupts are exposed as maskable and automasked
interrupts and are masked and disabled automatically when they fire.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_irq.c     | 99 ++++++++++++++++++++++++++-
 drivers/vfio/platform/vfio_platform_private.h |  2 +
 2 files changed, 98 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c
index 4896581..b3602cb 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -23,12 +23,59 @@
 
 #include "vfio_platform_private.h"
 
+static void vfio_platform_mask(struct vfio_platform_irq *irq_ctx)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&irq_ctx->lock, flags);
+
+	if (!irq_ctx->masked) {
+		disable_irq_nosync(irq_ctx->hwirq);
+		irq_ctx->masked = true;
+	}
+
+	spin_unlock_irqrestore(&irq_ctx->lock, flags);
+}
+
 static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
 				      unsigned index, unsigned start,
 				      unsigned count, uint32_t flags,
 				      void *data)
 {
-	return -EINVAL;
+	if (start != 0 || count != 1)
+		return -EINVAL;
+
+	if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
+		return -EINVAL;
+
+	if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
+		return -EINVAL; /* not implemented yet */
+
+	if (flags & VFIO_IRQ_SET_DATA_NONE) {
+		vfio_platform_mask(&vdev->irqs[index]);
+
+	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+		uint8_t mask = *(uint8_t *)data;
+
+		if (mask)
+			vfio_platform_mask(&vdev->irqs[index]);
+	}
+
+	return 0;
+}
+
+static void vfio_platform_unmask(struct vfio_platform_irq *irq_ctx)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&irq_ctx->lock, flags);
+
+	if (irq_ctx->masked) {
+		enable_irq(irq_ctx->hwirq);
+		irq_ctx->masked = false;
+	}
+
+	spin_unlock_irqrestore(&irq_ctx->lock, flags);
 }
 
 static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
@@ -36,7 +83,50 @@ static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
 					unsigned count, uint32_t flags,
 					void *data)
 {
-	return -EINVAL;
+	if (start != 0 || count != 1)
+		return -EINVAL;
+
+	if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
+		return -EINVAL;
+
+	if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
+		return -EINVAL; /* not implemented yet */
+
+	if (flags & VFIO_IRQ_SET_DATA_NONE) {
+		vfio_platform_unmask(&vdev->irqs[index]);
+
+	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+		uint8_t unmask = *(uint8_t *)data;
+
+		if (unmask)
+			vfio_platform_unmask(&vdev->irqs[index]);
+	}
+
+	return 0;
+}
+
+static irqreturn_t vfio_automasked_irq_handler(int irq, void *dev_id)
+{
+	struct vfio_platform_irq *irq_ctx = dev_id;
+	unsigned long flags;
+	int ret = IRQ_NONE;
+
+	spin_lock_irqsave(&irq_ctx->lock, flags);
+
+	if (!irq_ctx->masked) {
+		ret = IRQ_HANDLED;
+
+		/* automask maskable interrupts */
+		disable_irq_nosync(irq_ctx->hwirq);
+		irq_ctx->masked = true;
+	}
+
+	spin_unlock_irqrestore(&irq_ctx->lock, flags);
+
+	if (ret == IRQ_HANDLED)
+		eventfd_signal(irq_ctx->trigger, 1);
+
+	return ret;
 }
 
 static irqreturn_t vfio_irq_handler(int irq, void *dev_id)
@@ -106,7 +196,7 @@ static int vfio_platform_set_irq_trigger(struct vfio_platform_device *vdev,
 	irq_handler_t handler;
 
 	if (vdev->irqs[index].flags & VFIO_IRQ_INFO_AUTOMASKED)
-		return -EINVAL; /* not implemented */
+		handler = vfio_automasked_irq_handler;
 	else
 		handler = vfio_irq_handler;
 
@@ -178,6 +268,8 @@ int vfio_platform_irq_init(struct vfio_platform_device *vdev)
 		if (hwirq < 0)
 			goto err;
 
+		spin_lock_init(&vdev->irqs[i].lock);
+
 		vdev->irqs[i].flags = VFIO_IRQ_INFO_EVENTFD;
 
 		if (irq_get_trigger_type(hwirq) & IRQ_TYPE_LEVEL_MASK)
@@ -186,6 +278,7 @@ int vfio_platform_irq_init(struct vfio_platform_device *vdev)
 
 		vdev->irqs[i].count = 1;
 		vdev->irqs[i].hwirq = hwirq;
+		vdev->irqs[i].masked = false;
 	}
 
 	vdev->num_irqs = cnt;
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index b705f17..eef6d1b 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -30,6 +30,8 @@ struct vfio_platform_irq {
 	int			hwirq;
 	char			*name;
 	struct eventfd_ctx	*trigger;
+	bool			masked;
+	spinlock_t		lock;
 };
 
 struct vfio_platform_region {
-- 
2.1.4


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

* [PATCH v11 14/20] vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and export
  2015-01-06 10:48 [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Antonios Motakis
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-06 10:48   ` Antonios Motakis
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, Bjorn Helgaas, Thomas Gleixner,
	Alexander Gordeev, Gavin Shan, Jiang Liu, open list:VFIO DRIVER,
	open list

We want to reuse virqfd functionality in multiple VFIO drivers; before
moving these functions to core VFIO, add the vfio_ prefix to the
virqfd_enable and virqfd_disable functions, and export them so they can
be used from other modules.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/pci/vfio_pci_intrs.c   | 30 ++++++++++++++++--------------
 drivers/vfio/pci/vfio_pci_private.h |  4 ++--
 2 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index e8d695b..0a41833d 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -126,10 +126,10 @@ static void virqfd_inject(struct work_struct *work)
 		virqfd->thread(virqfd->vdev, virqfd->data);
 }
 
-static int virqfd_enable(struct vfio_pci_device *vdev,
-			 int (*handler)(struct vfio_pci_device *, void *),
-			 void (*thread)(struct vfio_pci_device *, void *),
-			 void *data, struct virqfd **pvirqfd, int fd)
+int vfio_virqfd_enable(struct vfio_pci_device *vdev,
+		       int (*handler)(struct vfio_pci_device *, void *),
+		       void (*thread)(struct vfio_pci_device *, void *),
+		       void *data, struct virqfd **pvirqfd, int fd)
 {
 	struct fd irqfd;
 	struct eventfd_ctx *ctx;
@@ -215,9 +215,9 @@ err_fd:
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(vfio_virqfd_enable);
 
-static void virqfd_disable(struct vfio_pci_device *vdev,
-			   struct virqfd **pvirqfd)
+void vfio_virqfd_disable(struct vfio_pci_device *vdev, struct virqfd **pvirqfd)
 {
 	unsigned long flags;
 
@@ -237,6 +237,7 @@ static void virqfd_disable(struct vfio_pci_device *vdev,
 	 */
 	flush_workqueue(vfio_irqfd_cleanup_wq);
 }
+EXPORT_SYMBOL_GPL(vfio_virqfd_disable);
 
 /*
  * INTx
@@ -440,8 +441,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd)
 static void vfio_intx_disable(struct vfio_pci_device *vdev)
 {
 	vfio_intx_set_signal(vdev, -1);
-	virqfd_disable(vdev, &vdev->ctx[0].unmask);
-	virqfd_disable(vdev, &vdev->ctx[0].mask);
+	vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
+	vfio_virqfd_disable(vdev, &vdev->ctx[0].mask);
 	vdev->irq_type = VFIO_PCI_NUM_IRQS;
 	vdev->num_ctx = 0;
 	kfree(vdev->ctx);
@@ -605,8 +606,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
 	vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
 
 	for (i = 0; i < vdev->num_ctx; i++) {
-		virqfd_disable(vdev, &vdev->ctx[i].unmask);
-		virqfd_disable(vdev, &vdev->ctx[i].mask);
+		vfio_virqfd_disable(vdev, &vdev->ctx[i].unmask);
+		vfio_virqfd_disable(vdev, &vdev->ctx[i].mask);
 	}
 
 	if (msix) {
@@ -639,11 +640,12 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev,
 	} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
 		int32_t fd = *(int32_t *)data;
 		if (fd >= 0)
-			return virqfd_enable(vdev, vfio_pci_intx_unmask_handler,
-					     vfio_send_intx_eventfd, NULL,
-					     &vdev->ctx[0].unmask, fd);
+			return vfio_virqfd_enable(vdev,
+						  vfio_pci_intx_unmask_handler,
+						  vfio_send_intx_eventfd, NULL,
+						  &vdev->ctx[0].unmask, fd);
 
-		virqfd_disable(vdev, &vdev->ctx[0].unmask);
+		vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
 	}
 
 	return 0;
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h
index 671c17a..2e2f0ea 100644
--- a/drivers/vfio/pci/vfio_pci_private.h
+++ b/drivers/vfio/pci/vfio_pci_private.h
@@ -86,8 +86,8 @@ extern ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf,
 extern int vfio_pci_init_perm_bits(void);
 extern void vfio_pci_uninit_perm_bits(void);
 
-extern int vfio_pci_virqfd_init(void);
-extern void vfio_pci_virqfd_exit(void);
+extern int vfio_virqfd_init(void);
+extern void vfio_virqfd_exit(void);
 
 extern int vfio_config_init(struct vfio_pci_device *vdev);
 extern void vfio_config_free(struct vfio_pci_device *vdev);
-- 
2.1.4


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

* [PATCH v11 14/20] vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and export
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, Bjorn Helgaas, Thomas Gleixner,
	Alexander Gordeev, Gavin Shan, Jiang Liu, open list:VFIO DRIVER,
	open list

We want to reuse virqfd functionality in multiple VFIO drivers; before
moving these functions to core VFIO, add the vfio_ prefix to the
virqfd_enable and virqfd_disable functions, and export them so they can
be used from other modules.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/pci/vfio_pci_intrs.c   | 30 ++++++++++++++++--------------
 drivers/vfio/pci/vfio_pci_private.h |  4 ++--
 2 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index e8d695b..0a41833d 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -126,10 +126,10 @@ static void virqfd_inject(struct work_struct *work)
 		virqfd->thread(virqfd->vdev, virqfd->data);
 }
 
-static int virqfd_enable(struct vfio_pci_device *vdev,
-			 int (*handler)(struct vfio_pci_device *, void *),
-			 void (*thread)(struct vfio_pci_device *, void *),
-			 void *data, struct virqfd **pvirqfd, int fd)
+int vfio_virqfd_enable(struct vfio_pci_device *vdev,
+		       int (*handler)(struct vfio_pci_device *, void *),
+		       void (*thread)(struct vfio_pci_device *, void *),
+		       void *data, struct virqfd **pvirqfd, int fd)
 {
 	struct fd irqfd;
 	struct eventfd_ctx *ctx;
@@ -215,9 +215,9 @@ err_fd:
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(vfio_virqfd_enable);
 
-static void virqfd_disable(struct vfio_pci_device *vdev,
-			   struct virqfd **pvirqfd)
+void vfio_virqfd_disable(struct vfio_pci_device *vdev, struct virqfd **pvirqfd)
 {
 	unsigned long flags;
 
@@ -237,6 +237,7 @@ static void virqfd_disable(struct vfio_pci_device *vdev,
 	 */
 	flush_workqueue(vfio_irqfd_cleanup_wq);
 }
+EXPORT_SYMBOL_GPL(vfio_virqfd_disable);
 
 /*
  * INTx
@@ -440,8 +441,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd)
 static void vfio_intx_disable(struct vfio_pci_device *vdev)
 {
 	vfio_intx_set_signal(vdev, -1);
-	virqfd_disable(vdev, &vdev->ctx[0].unmask);
-	virqfd_disable(vdev, &vdev->ctx[0].mask);
+	vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
+	vfio_virqfd_disable(vdev, &vdev->ctx[0].mask);
 	vdev->irq_type = VFIO_PCI_NUM_IRQS;
 	vdev->num_ctx = 0;
 	kfree(vdev->ctx);
@@ -605,8 +606,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
 	vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
 
 	for (i = 0; i < vdev->num_ctx; i++) {
-		virqfd_disable(vdev, &vdev->ctx[i].unmask);
-		virqfd_disable(vdev, &vdev->ctx[i].mask);
+		vfio_virqfd_disable(vdev, &vdev->ctx[i].unmask);
+		vfio_virqfd_disable(vdev, &vdev->ctx[i].mask);
 	}
 
 	if (msix) {
@@ -639,11 +640,12 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev,
 	} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
 		int32_t fd = *(int32_t *)data;
 		if (fd >= 0)
-			return virqfd_enable(vdev, vfio_pci_intx_unmask_handler,
-					     vfio_send_intx_eventfd, NULL,
-					     &vdev->ctx[0].unmask, fd);
+			return vfio_virqfd_enable(vdev,
+						  vfio_pci_intx_unmask_handler,
+						  vfio_send_intx_eventfd, NULL,
+						  &vdev->ctx[0].unmask, fd);
 
-		virqfd_disable(vdev, &vdev->ctx[0].unmask);
+		vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
 	}
 
 	return 0;
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h
index 671c17a..2e2f0ea 100644
--- a/drivers/vfio/pci/vfio_pci_private.h
+++ b/drivers/vfio/pci/vfio_pci_private.h
@@ -86,8 +86,8 @@ extern ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf,
 extern int vfio_pci_init_perm_bits(void);
 extern void vfio_pci_uninit_perm_bits(void);
 
-extern int vfio_pci_virqfd_init(void);
-extern void vfio_pci_virqfd_exit(void);
+extern int vfio_virqfd_init(void);
+extern void vfio_virqfd_exit(void);
 
 extern int vfio_config_init(struct vfio_pci_device *vdev);
 extern void vfio_config_free(struct vfio_pci_device *vdev);
-- 
2.1.4

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

* [PATCH v11 15/20] vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
  2015-01-06 10:48 [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Antonios Motakis
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-06 10:48   ` Antonios Motakis
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, Gavin Shan,
	Benjamin Herrenschmidt, Alexey Kardashevskiy, Alexander Gordeev,
	Bjorn Helgaas, Jiang Liu, open list:VFIO DRIVER, open list

The functions vfio_pci_virqfd_init and vfio_pci_virqfd_exit are not really
PCI specific, since we plan to reuse the virqfd code with more VFIO drivers
in addition to VFIO_PCI.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/pci/vfio_pci.c       | 6 +++---
 drivers/vfio/pci/vfio_pci_intrs.c | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 9558da3..fc4308c 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -1012,7 +1012,7 @@ put_devs:
 static void __exit vfio_pci_cleanup(void)
 {
 	pci_unregister_driver(&vfio_pci_driver);
-	vfio_pci_virqfd_exit();
+	vfio_virqfd_exit();
 	vfio_pci_uninit_perm_bits();
 }
 
@@ -1026,7 +1026,7 @@ static int __init vfio_pci_init(void)
 		return ret;
 
 	/* Start the virqfd cleanup handler */
-	ret = vfio_pci_virqfd_init();
+	ret = vfio_virqfd_init();
 	if (ret)
 		goto out_virqfd;
 
@@ -1038,7 +1038,7 @@ static int __init vfio_pci_init(void)
 	return 0;
 
 out_driver:
-	vfio_pci_virqfd_exit();
+	vfio_virqfd_exit();
 out_virqfd:
 	vfio_pci_uninit_perm_bits();
 	return ret;
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 0a41833d..a5378d5 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -45,7 +45,7 @@ struct virqfd {
 
 static struct workqueue_struct *vfio_irqfd_cleanup_wq;
 
-int __init vfio_pci_virqfd_init(void)
+int __init vfio_virqfd_init(void)
 {
 	vfio_irqfd_cleanup_wq =
 		create_singlethread_workqueue("vfio-irqfd-cleanup");
@@ -55,7 +55,7 @@ int __init vfio_pci_virqfd_init(void)
 	return 0;
 }
 
-void vfio_pci_virqfd_exit(void)
+void vfio_virqfd_exit(void)
 {
 	destroy_workqueue(vfio_irqfd_cleanup_wq);
 }
-- 
2.1.4


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

* [PATCH v11 15/20] vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, Gavin Shan,
	Benjamin Herrenschmidt, Alexey Kardashevskiy, Alexander Gordeev,
	Bjorn Helgaas, Jiang Liu, open list:VFIO DRIVER, open list

The functions vfio_pci_virqfd_init and vfio_pci_virqfd_exit are not really
PCI specific, since we plan to reuse the virqfd code with more VFIO drivers
in addition to VFIO_PCI.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/pci/vfio_pci.c       | 6 +++---
 drivers/vfio/pci/vfio_pci_intrs.c | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 9558da3..fc4308c 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -1012,7 +1012,7 @@ put_devs:
 static void __exit vfio_pci_cleanup(void)
 {
 	pci_unregister_driver(&vfio_pci_driver);
-	vfio_pci_virqfd_exit();
+	vfio_virqfd_exit();
 	vfio_pci_uninit_perm_bits();
 }
 
@@ -1026,7 +1026,7 @@ static int __init vfio_pci_init(void)
 		return ret;
 
 	/* Start the virqfd cleanup handler */
-	ret = vfio_pci_virqfd_init();
+	ret = vfio_virqfd_init();
 	if (ret)
 		goto out_virqfd;
 
@@ -1038,7 +1038,7 @@ static int __init vfio_pci_init(void)
 	return 0;
 
 out_driver:
-	vfio_pci_virqfd_exit();
+	vfio_virqfd_exit();
 out_virqfd:
 	vfio_pci_uninit_perm_bits();
 	return ret;
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 0a41833d..a5378d5 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -45,7 +45,7 @@ struct virqfd {
 
 static struct workqueue_struct *vfio_irqfd_cleanup_wq;
 
-int __init vfio_pci_virqfd_init(void)
+int __init vfio_virqfd_init(void)
 {
 	vfio_irqfd_cleanup_wq =
 		create_singlethread_workqueue("vfio-irqfd-cleanup");
@@ -55,7 +55,7 @@ int __init vfio_pci_virqfd_init(void)
 	return 0;
 }
 
-void vfio_pci_virqfd_exit(void)
+void vfio_virqfd_exit(void)
 {
 	destroy_workqueue(vfio_irqfd_cleanup_wq);
 }
-- 
2.1.4

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

* [PATCH v11 16/20] vfio: add local lock for virqfd instead of depending on VFIO PCI
  2015-01-06 10:48 [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Antonios Motakis
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-06 10:48   ` Antonios Motakis
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, Thomas Gleixner, Gavin Shan,
	Jiang Liu, Alexander Gordeev, open list:VFIO DRIVER, open list

The Virqfd code needs to keep accesses to any struct *virqfd safe, but
this comes into play only when creating or destroying eventfds, so sharing
the same spinlock with the VFIO bus driver is not necessary.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/pci/vfio_pci_intrs.c | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index a5378d5..b35bc16 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -44,6 +44,7 @@ struct virqfd {
 };
 
 static struct workqueue_struct *vfio_irqfd_cleanup_wq;
+DEFINE_SPINLOCK(virqfd_lock);
 
 int __init vfio_virqfd_init(void)
 {
@@ -80,21 +81,21 @@ static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)
 
 	if (flags & POLLHUP) {
 		unsigned long flags;
-		spin_lock_irqsave(&virqfd->vdev->irqlock, flags);
+		spin_lock_irqsave(&virqfd_lock, flags);
 
 		/*
 		 * The eventfd is closing, if the virqfd has not yet been
 		 * queued for release, as determined by testing whether the
-		 * vdev pointer to it is still valid, queue it now.  As
+		 * virqfd pointer to it is still valid, queue it now.  As
 		 * with kvm irqfds, we know we won't race against the virqfd
-		 * going away because we hold wqh->lock to get here.
+		 * going away because we hold the lock to get here.
 		 */
 		if (*(virqfd->pvirqfd) == virqfd) {
 			*(virqfd->pvirqfd) = NULL;
 			virqfd_deactivate(virqfd);
 		}
 
-		spin_unlock_irqrestore(&virqfd->vdev->irqlock, flags);
+		spin_unlock_irqrestore(&virqfd_lock, flags);
 	}
 
 	return 0;
@@ -170,16 +171,16 @@ int vfio_virqfd_enable(struct vfio_pci_device *vdev,
 	 * we update the pointer to the virqfd under lock to avoid
 	 * pushing multiple jobs to release the same virqfd.
 	 */
-	spin_lock_irq(&vdev->irqlock);
+	spin_lock_irq(&virqfd_lock);
 
 	if (*pvirqfd) {
-		spin_unlock_irq(&vdev->irqlock);
+		spin_unlock_irq(&virqfd_lock);
 		ret = -EBUSY;
 		goto err_busy;
 	}
 	*pvirqfd = virqfd;
 
-	spin_unlock_irq(&vdev->irqlock);
+	spin_unlock_irq(&virqfd_lock);
 
 	/*
 	 * Install our own custom wake-up handling so we are notified via
@@ -217,18 +218,18 @@ err_fd:
 }
 EXPORT_SYMBOL_GPL(vfio_virqfd_enable);
 
-void vfio_virqfd_disable(struct vfio_pci_device *vdev, struct virqfd **pvirqfd)
+void vfio_virqfd_disable(struct virqfd **pvirqfd)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&vdev->irqlock, flags);
+	spin_lock_irqsave(&virqfd_lock, flags);
 
 	if (*pvirqfd) {
 		virqfd_deactivate(*pvirqfd);
 		*pvirqfd = NULL;
 	}
 
-	spin_unlock_irqrestore(&vdev->irqlock, flags);
+	spin_unlock_irqrestore(&virqfd_lock, flags);
 
 	/*
 	 * Block until we know all outstanding shutdown jobs have completed.
@@ -441,8 +442,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd)
 static void vfio_intx_disable(struct vfio_pci_device *vdev)
 {
 	vfio_intx_set_signal(vdev, -1);
-	vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
-	vfio_virqfd_disable(vdev, &vdev->ctx[0].mask);
+	vfio_virqfd_disable(&vdev->ctx[0].unmask);
+	vfio_virqfd_disable(&vdev->ctx[0].mask);
 	vdev->irq_type = VFIO_PCI_NUM_IRQS;
 	vdev->num_ctx = 0;
 	kfree(vdev->ctx);
@@ -606,8 +607,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
 	vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
 
 	for (i = 0; i < vdev->num_ctx; i++) {
-		vfio_virqfd_disable(vdev, &vdev->ctx[i].unmask);
-		vfio_virqfd_disable(vdev, &vdev->ctx[i].mask);
+		vfio_virqfd_disable(&vdev->ctx[i].unmask);
+		vfio_virqfd_disable(&vdev->ctx[i].mask);
 	}
 
 	if (msix) {
@@ -645,7 +646,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev,
 						  vfio_send_intx_eventfd, NULL,
 						  &vdev->ctx[0].unmask, fd);
 
-		vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
+		vfio_virqfd_disable(&vdev->ctx[0].unmask);
 	}
 
 	return 0;
-- 
2.1.4


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

* [PATCH v11 16/20] vfio: add local lock for virqfd instead of depending on VFIO PCI
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, Thomas Gleixner, Gavin Shan,
	Jiang Liu, Alexander Gordeev, open list:VFIO DRIVER, open list

The Virqfd code needs to keep accesses to any struct *virqfd safe, but
this comes into play only when creating or destroying eventfds, so sharing
the same spinlock with the VFIO bus driver is not necessary.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/pci/vfio_pci_intrs.c | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index a5378d5..b35bc16 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -44,6 +44,7 @@ struct virqfd {
 };
 
 static struct workqueue_struct *vfio_irqfd_cleanup_wq;
+DEFINE_SPINLOCK(virqfd_lock);
 
 int __init vfio_virqfd_init(void)
 {
@@ -80,21 +81,21 @@ static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)
 
 	if (flags & POLLHUP) {
 		unsigned long flags;
-		spin_lock_irqsave(&virqfd->vdev->irqlock, flags);
+		spin_lock_irqsave(&virqfd_lock, flags);
 
 		/*
 		 * The eventfd is closing, if the virqfd has not yet been
 		 * queued for release, as determined by testing whether the
-		 * vdev pointer to it is still valid, queue it now.  As
+		 * virqfd pointer to it is still valid, queue it now.  As
 		 * with kvm irqfds, we know we won't race against the virqfd
-		 * going away because we hold wqh->lock to get here.
+		 * going away because we hold the lock to get here.
 		 */
 		if (*(virqfd->pvirqfd) == virqfd) {
 			*(virqfd->pvirqfd) = NULL;
 			virqfd_deactivate(virqfd);
 		}
 
-		spin_unlock_irqrestore(&virqfd->vdev->irqlock, flags);
+		spin_unlock_irqrestore(&virqfd_lock, flags);
 	}
 
 	return 0;
@@ -170,16 +171,16 @@ int vfio_virqfd_enable(struct vfio_pci_device *vdev,
 	 * we update the pointer to the virqfd under lock to avoid
 	 * pushing multiple jobs to release the same virqfd.
 	 */
-	spin_lock_irq(&vdev->irqlock);
+	spin_lock_irq(&virqfd_lock);
 
 	if (*pvirqfd) {
-		spin_unlock_irq(&vdev->irqlock);
+		spin_unlock_irq(&virqfd_lock);
 		ret = -EBUSY;
 		goto err_busy;
 	}
 	*pvirqfd = virqfd;
 
-	spin_unlock_irq(&vdev->irqlock);
+	spin_unlock_irq(&virqfd_lock);
 
 	/*
 	 * Install our own custom wake-up handling so we are notified via
@@ -217,18 +218,18 @@ err_fd:
 }
 EXPORT_SYMBOL_GPL(vfio_virqfd_enable);
 
-void vfio_virqfd_disable(struct vfio_pci_device *vdev, struct virqfd **pvirqfd)
+void vfio_virqfd_disable(struct virqfd **pvirqfd)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&vdev->irqlock, flags);
+	spin_lock_irqsave(&virqfd_lock, flags);
 
 	if (*pvirqfd) {
 		virqfd_deactivate(*pvirqfd);
 		*pvirqfd = NULL;
 	}
 
-	spin_unlock_irqrestore(&vdev->irqlock, flags);
+	spin_unlock_irqrestore(&virqfd_lock, flags);
 
 	/*
 	 * Block until we know all outstanding shutdown jobs have completed.
@@ -441,8 +442,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd)
 static void vfio_intx_disable(struct vfio_pci_device *vdev)
 {
 	vfio_intx_set_signal(vdev, -1);
-	vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
-	vfio_virqfd_disable(vdev, &vdev->ctx[0].mask);
+	vfio_virqfd_disable(&vdev->ctx[0].unmask);
+	vfio_virqfd_disable(&vdev->ctx[0].mask);
 	vdev->irq_type = VFIO_PCI_NUM_IRQS;
 	vdev->num_ctx = 0;
 	kfree(vdev->ctx);
@@ -606,8 +607,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
 	vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
 
 	for (i = 0; i < vdev->num_ctx; i++) {
-		vfio_virqfd_disable(vdev, &vdev->ctx[i].unmask);
-		vfio_virqfd_disable(vdev, &vdev->ctx[i].mask);
+		vfio_virqfd_disable(&vdev->ctx[i].unmask);
+		vfio_virqfd_disable(&vdev->ctx[i].mask);
 	}
 
 	if (msix) {
@@ -645,7 +646,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev,
 						  vfio_send_intx_eventfd, NULL,
 						  &vdev->ctx[0].unmask, fd);
 
-		vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
+		vfio_virqfd_disable(&vdev->ctx[0].unmask);
 	}
 
 	return 0;
-- 
2.1.4


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

* [PATCH v11 17/20] vfio: pass an opaque pointer on virqfd initialization
  2015-01-06 10:48 [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Antonios Motakis
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-06 10:48   ` Antonios Motakis
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, Bjorn Helgaas, Gavin Shan,
	Thomas Gleixner, Alexander Gordeev, Jiang Liu,
	open list:VFIO DRIVER, open list

VFIO_PCI passes the VFIO device structure *vdev via eventfd to the handler
that implements masking/unmasking of IRQs via an eventfd. We can replace
it in the virqfd infrastructure with an opaque type so we can make use
of the mechanism from other VFIO bus drivers.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/pci/vfio_pci_intrs.c | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index b35bc16..5b5fc23 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -31,10 +31,10 @@
  * IRQfd - generic
  */
 struct virqfd {
-	struct vfio_pci_device	*vdev;
+	void			*opaque;
 	struct eventfd_ctx	*eventfd;
-	int			(*handler)(struct vfio_pci_device *, void *);
-	void			(*thread)(struct vfio_pci_device *, void *);
+	int			(*handler)(void *, void *);
+	void			(*thread)(void *, void *);
 	void			*data;
 	struct work_struct	inject;
 	wait_queue_t		wait;
@@ -74,7 +74,7 @@ static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)
 	if (flags & POLLIN) {
 		/* An event has been signaled, call function */
 		if ((!virqfd->handler ||
-		     virqfd->handler(virqfd->vdev, virqfd->data)) &&
+		     virqfd->handler(virqfd->opaque, virqfd->data)) &&
 		    virqfd->thread)
 			schedule_work(&virqfd->inject);
 	}
@@ -124,12 +124,12 @@ static void virqfd_inject(struct work_struct *work)
 {
 	struct virqfd *virqfd = container_of(work, struct virqfd, inject);
 	if (virqfd->thread)
-		virqfd->thread(virqfd->vdev, virqfd->data);
+		virqfd->thread(virqfd->opaque, virqfd->data);
 }
 
-int vfio_virqfd_enable(struct vfio_pci_device *vdev,
-		       int (*handler)(struct vfio_pci_device *, void *),
-		       void (*thread)(struct vfio_pci_device *, void *),
+int vfio_virqfd_enable(void *opaque,
+		       int (*handler)(void *, void *),
+		       void (*thread)(void *, void *),
 		       void *data, struct virqfd **pvirqfd, int fd)
 {
 	struct fd irqfd;
@@ -143,7 +143,7 @@ int vfio_virqfd_enable(struct vfio_pci_device *vdev,
 		return -ENOMEM;
 
 	virqfd->pvirqfd = pvirqfd;
-	virqfd->vdev = vdev;
+	virqfd->opaque = opaque;
 	virqfd->handler = handler;
 	virqfd->thread = thread;
 	virqfd->data = data;
@@ -196,7 +196,7 @@ int vfio_virqfd_enable(struct vfio_pci_device *vdev,
 	 * before we registered and trigger it as if we didn't miss it.
 	 */
 	if (events & POLLIN) {
-		if ((!handler || handler(vdev, data)) && thread)
+		if ((!handler || handler(opaque, data)) && thread)
 			schedule_work(&virqfd->inject);
 	}
 
@@ -243,8 +243,10 @@ EXPORT_SYMBOL_GPL(vfio_virqfd_disable);
 /*
  * INTx
  */
-static void vfio_send_intx_eventfd(struct vfio_pci_device *vdev, void *unused)
+static void vfio_send_intx_eventfd(void *opaque, void *unused)
 {
+	struct vfio_pci_device *vdev = opaque;
+
 	if (likely(is_intx(vdev) && !vdev->virq_disabled))
 		eventfd_signal(vdev->ctx[0].trigger, 1);
 }
@@ -287,9 +289,9 @@ void vfio_pci_intx_mask(struct vfio_pci_device *vdev)
  * a signal is necessary, which can then be handled via a work queue
  * or directly depending on the caller.
  */
-static int vfio_pci_intx_unmask_handler(struct vfio_pci_device *vdev,
-					void *unused)
+static int vfio_pci_intx_unmask_handler(void *opaque, void *unused)
 {
+	struct vfio_pci_device *vdev = opaque;
 	struct pci_dev *pdev = vdev->pdev;
 	unsigned long flags;
 	int ret = 0;
@@ -641,7 +643,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev,
 	} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
 		int32_t fd = *(int32_t *)data;
 		if (fd >= 0)
-			return vfio_virqfd_enable(vdev,
+			return vfio_virqfd_enable((void *) vdev,
 						  vfio_pci_intx_unmask_handler,
 						  vfio_send_intx_eventfd, NULL,
 						  &vdev->ctx[0].unmask, fd);
-- 
2.1.4


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

* [PATCH v11 17/20] vfio: pass an opaque pointer on virqfd initialization
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, Bjorn Helgaas, Gavin Shan,
	Thomas Gleixner, Alexander Gordeev, Jiang Liu,
	open list:VFIO DRIVER, open list

VFIO_PCI passes the VFIO device structure *vdev via eventfd to the handler
that implements masking/unmasking of IRQs via an eventfd. We can replace
it in the virqfd infrastructure with an opaque type so we can make use
of the mechanism from other VFIO bus drivers.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/pci/vfio_pci_intrs.c | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index b35bc16..5b5fc23 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -31,10 +31,10 @@
  * IRQfd - generic
  */
 struct virqfd {
-	struct vfio_pci_device	*vdev;
+	void			*opaque;
 	struct eventfd_ctx	*eventfd;
-	int			(*handler)(struct vfio_pci_device *, void *);
-	void			(*thread)(struct vfio_pci_device *, void *);
+	int			(*handler)(void *, void *);
+	void			(*thread)(void *, void *);
 	void			*data;
 	struct work_struct	inject;
 	wait_queue_t		wait;
@@ -74,7 +74,7 @@ static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)
 	if (flags & POLLIN) {
 		/* An event has been signaled, call function */
 		if ((!virqfd->handler ||
-		     virqfd->handler(virqfd->vdev, virqfd->data)) &&
+		     virqfd->handler(virqfd->opaque, virqfd->data)) &&
 		    virqfd->thread)
 			schedule_work(&virqfd->inject);
 	}
@@ -124,12 +124,12 @@ static void virqfd_inject(struct work_struct *work)
 {
 	struct virqfd *virqfd = container_of(work, struct virqfd, inject);
 	if (virqfd->thread)
-		virqfd->thread(virqfd->vdev, virqfd->data);
+		virqfd->thread(virqfd->opaque, virqfd->data);
 }
 
-int vfio_virqfd_enable(struct vfio_pci_device *vdev,
-		       int (*handler)(struct vfio_pci_device *, void *),
-		       void (*thread)(struct vfio_pci_device *, void *),
+int vfio_virqfd_enable(void *opaque,
+		       int (*handler)(void *, void *),
+		       void (*thread)(void *, void *),
 		       void *data, struct virqfd **pvirqfd, int fd)
 {
 	struct fd irqfd;
@@ -143,7 +143,7 @@ int vfio_virqfd_enable(struct vfio_pci_device *vdev,
 		return -ENOMEM;
 
 	virqfd->pvirqfd = pvirqfd;
-	virqfd->vdev = vdev;
+	virqfd->opaque = opaque;
 	virqfd->handler = handler;
 	virqfd->thread = thread;
 	virqfd->data = data;
@@ -196,7 +196,7 @@ int vfio_virqfd_enable(struct vfio_pci_device *vdev,
 	 * before we registered and trigger it as if we didn't miss it.
 	 */
 	if (events & POLLIN) {
-		if ((!handler || handler(vdev, data)) && thread)
+		if ((!handler || handler(opaque, data)) && thread)
 			schedule_work(&virqfd->inject);
 	}
 
@@ -243,8 +243,10 @@ EXPORT_SYMBOL_GPL(vfio_virqfd_disable);
 /*
  * INTx
  */
-static void vfio_send_intx_eventfd(struct vfio_pci_device *vdev, void *unused)
+static void vfio_send_intx_eventfd(void *opaque, void *unused)
 {
+	struct vfio_pci_device *vdev = opaque;
+
 	if (likely(is_intx(vdev) && !vdev->virq_disabled))
 		eventfd_signal(vdev->ctx[0].trigger, 1);
 }
@@ -287,9 +289,9 @@ void vfio_pci_intx_mask(struct vfio_pci_device *vdev)
  * a signal is necessary, which can then be handled via a work queue
  * or directly depending on the caller.
  */
-static int vfio_pci_intx_unmask_handler(struct vfio_pci_device *vdev,
-					void *unused)
+static int vfio_pci_intx_unmask_handler(void *opaque, void *unused)
 {
+	struct vfio_pci_device *vdev = opaque;
 	struct pci_dev *pdev = vdev->pdev;
 	unsigned long flags;
 	int ret = 0;
@@ -641,7 +643,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev,
 	} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
 		int32_t fd = *(int32_t *)data;
 		if (fd >= 0)
-			return vfio_virqfd_enable(vdev,
+			return vfio_virqfd_enable((void *) vdev,
 						  vfio_pci_intx_unmask_handler,
 						  vfio_send_intx_eventfd, NULL,
 						  &vdev->ctx[0].unmask, fd);
-- 
2.1.4


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

* [PATCH v11 18/20] vfio: move eventfd support code for VFIO_PCI to a separate file
       [not found] ` <1420541335-17190-1-git-send-email-a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-09  8:39   ` Eric Auger
  2015-01-19 18:39   ` Alex Williamson
  2 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, Alexander Gordeev, Jiang Liu,
	Bjorn Helgaas, Gavin Shan, open list, open list:VFIO DRIVER

The virqfd functionality that is used by VFIO_PCI to implement interrupt
masking and unmasking via an eventfd, is generic enough and can be reused
by another driver. Move it to a separate file in order to allow the code
to be shared.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/pci/Makefile           |   3 +-
 drivers/vfio/pci/vfio_pci_intrs.c   | 215 ------------------------------------
 drivers/vfio/pci/vfio_pci_private.h |   3 -
 drivers/vfio/virqfd.c               | 213 +++++++++++++++++++++++++++++++++++
 include/linux/vfio.h                |  27 +++++
 5 files changed, 242 insertions(+), 219 deletions(-)
 create mode 100644 drivers/vfio/virqfd.c

diff --git a/drivers/vfio/pci/Makefile b/drivers/vfio/pci/Makefile
index 1310792..c7c8644 100644
--- a/drivers/vfio/pci/Makefile
+++ b/drivers/vfio/pci/Makefile
@@ -1,4 +1,5 @@
 
-vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o
+vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o \
+	      ../virqfd.o
 
 obj-$(CONFIG_VFIO_PCI) += vfio-pci.o
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 5b5fc23..de4befc 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -19,228 +19,13 @@
 #include <linux/msi.h>
 #include <linux/pci.h>
 #include <linux/file.h>
-#include <linux/poll.h>
 #include <linux/vfio.h>
 #include <linux/wait.h>
-#include <linux/workqueue.h>
 #include <linux/slab.h>
 
 #include "vfio_pci_private.h"
 
 /*
- * IRQfd - generic
- */
-struct virqfd {
-	void			*opaque;
-	struct eventfd_ctx	*eventfd;
-	int			(*handler)(void *, void *);
-	void			(*thread)(void *, void *);
-	void			*data;
-	struct work_struct	inject;
-	wait_queue_t		wait;
-	poll_table		pt;
-	struct work_struct	shutdown;
-	struct virqfd		**pvirqfd;
-};
-
-static struct workqueue_struct *vfio_irqfd_cleanup_wq;
-DEFINE_SPINLOCK(virqfd_lock);
-
-int __init vfio_virqfd_init(void)
-{
-	vfio_irqfd_cleanup_wq =
-		create_singlethread_workqueue("vfio-irqfd-cleanup");
-	if (!vfio_irqfd_cleanup_wq)
-		return -ENOMEM;
-
-	return 0;
-}
-
-void vfio_virqfd_exit(void)
-{
-	destroy_workqueue(vfio_irqfd_cleanup_wq);
-}
-
-static void virqfd_deactivate(struct virqfd *virqfd)
-{
-	queue_work(vfio_irqfd_cleanup_wq, &virqfd->shutdown);
-}
-
-static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)
-{
-	struct virqfd *virqfd = container_of(wait, struct virqfd, wait);
-	unsigned long flags = (unsigned long)key;
-
-	if (flags & POLLIN) {
-		/* An event has been signaled, call function */
-		if ((!virqfd->handler ||
-		     virqfd->handler(virqfd->opaque, virqfd->data)) &&
-		    virqfd->thread)
-			schedule_work(&virqfd->inject);
-	}
-
-	if (flags & POLLHUP) {
-		unsigned long flags;
-		spin_lock_irqsave(&virqfd_lock, flags);
-
-		/*
-		 * The eventfd is closing, if the virqfd has not yet been
-		 * queued for release, as determined by testing whether the
-		 * virqfd pointer to it is still valid, queue it now.  As
-		 * with kvm irqfds, we know we won't race against the virqfd
-		 * going away because we hold the lock to get here.
-		 */
-		if (*(virqfd->pvirqfd) == virqfd) {
-			*(virqfd->pvirqfd) = NULL;
-			virqfd_deactivate(virqfd);
-		}
-
-		spin_unlock_irqrestore(&virqfd_lock, flags);
-	}
-
-	return 0;
-}
-
-static void virqfd_ptable_queue_proc(struct file *file,
-				     wait_queue_head_t *wqh, poll_table *pt)
-{
-	struct virqfd *virqfd = container_of(pt, struct virqfd, pt);
-	add_wait_queue(wqh, &virqfd->wait);
-}
-
-static void virqfd_shutdown(struct work_struct *work)
-{
-	struct virqfd *virqfd = container_of(work, struct virqfd, shutdown);
-	u64 cnt;
-
-	eventfd_ctx_remove_wait_queue(virqfd->eventfd, &virqfd->wait, &cnt);
-	flush_work(&virqfd->inject);
-	eventfd_ctx_put(virqfd->eventfd);
-
-	kfree(virqfd);
-}
-
-static void virqfd_inject(struct work_struct *work)
-{
-	struct virqfd *virqfd = container_of(work, struct virqfd, inject);
-	if (virqfd->thread)
-		virqfd->thread(virqfd->opaque, virqfd->data);
-}
-
-int vfio_virqfd_enable(void *opaque,
-		       int (*handler)(void *, void *),
-		       void (*thread)(void *, void *),
-		       void *data, struct virqfd **pvirqfd, int fd)
-{
-	struct fd irqfd;
-	struct eventfd_ctx *ctx;
-	struct virqfd *virqfd;
-	int ret = 0;
-	unsigned int events;
-
-	virqfd = kzalloc(sizeof(*virqfd), GFP_KERNEL);
-	if (!virqfd)
-		return -ENOMEM;
-
-	virqfd->pvirqfd = pvirqfd;
-	virqfd->opaque = opaque;
-	virqfd->handler = handler;
-	virqfd->thread = thread;
-	virqfd->data = data;
-
-	INIT_WORK(&virqfd->shutdown, virqfd_shutdown);
-	INIT_WORK(&virqfd->inject, virqfd_inject);
-
-	irqfd = fdget(fd);
-	if (!irqfd.file) {
-		ret = -EBADF;
-		goto err_fd;
-	}
-
-	ctx = eventfd_ctx_fileget(irqfd.file);
-	if (IS_ERR(ctx)) {
-		ret = PTR_ERR(ctx);
-		goto err_ctx;
-	}
-
-	virqfd->eventfd = ctx;
-
-	/*
-	 * virqfds can be released by closing the eventfd or directly
-	 * through ioctl.  These are both done through a workqueue, so
-	 * we update the pointer to the virqfd under lock to avoid
-	 * pushing multiple jobs to release the same virqfd.
-	 */
-	spin_lock_irq(&virqfd_lock);
-
-	if (*pvirqfd) {
-		spin_unlock_irq(&virqfd_lock);
-		ret = -EBUSY;
-		goto err_busy;
-	}
-	*pvirqfd = virqfd;
-
-	spin_unlock_irq(&virqfd_lock);
-
-	/*
-	 * Install our own custom wake-up handling so we are notified via
-	 * a callback whenever someone signals the underlying eventfd.
-	 */
-	init_waitqueue_func_entry(&virqfd->wait, virqfd_wakeup);
-	init_poll_funcptr(&virqfd->pt, virqfd_ptable_queue_proc);
-
-	events = irqfd.file->f_op->poll(irqfd.file, &virqfd->pt);
-
-	/*
-	 * Check if there was an event already pending on the eventfd
-	 * before we registered and trigger it as if we didn't miss it.
-	 */
-	if (events & POLLIN) {
-		if ((!handler || handler(opaque, data)) && thread)
-			schedule_work(&virqfd->inject);
-	}
-
-	/*
-	 * Do not drop the file until the irqfd is fully initialized,
-	 * otherwise we might race against the POLLHUP.
-	 */
-	fdput(irqfd);
-
-	return 0;
-err_busy:
-	eventfd_ctx_put(ctx);
-err_ctx:
-	fdput(irqfd);
-err_fd:
-	kfree(virqfd);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(vfio_virqfd_enable);
-
-void vfio_virqfd_disable(struct virqfd **pvirqfd)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&virqfd_lock, flags);
-
-	if (*pvirqfd) {
-		virqfd_deactivate(*pvirqfd);
-		*pvirqfd = NULL;
-	}
-
-	spin_unlock_irqrestore(&virqfd_lock, flags);
-
-	/*
-	 * Block until we know all outstanding shutdown jobs have completed.
-	 * Even if we don't queue the job, flush the wq to be sure it's
-	 * been released.
-	 */
-	flush_workqueue(vfio_irqfd_cleanup_wq);
-}
-EXPORT_SYMBOL_GPL(vfio_virqfd_disable);
-
-/*
  * INTx
  */
 static void vfio_send_intx_eventfd(void *opaque, void *unused)
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h
index 2e2f0ea..4c89e0e 100644
--- a/drivers/vfio/pci/vfio_pci_private.h
+++ b/drivers/vfio/pci/vfio_pci_private.h
@@ -86,9 +86,6 @@ extern ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf,
 extern int vfio_pci_init_perm_bits(void);
 extern void vfio_pci_uninit_perm_bits(void);
 
-extern int vfio_virqfd_init(void);
-extern void vfio_virqfd_exit(void);
-
 extern int vfio_config_init(struct vfio_pci_device *vdev);
 extern void vfio_config_free(struct vfio_pci_device *vdev);
 #endif /* VFIO_PCI_PRIVATE_H */
diff --git a/drivers/vfio/virqfd.c b/drivers/vfio/virqfd.c
new file mode 100644
index 0000000..5967899
--- /dev/null
+++ b/drivers/vfio/virqfd.c
@@ -0,0 +1,213 @@
+/*
+ * VFIO generic eventfd code for IRQFD support.
+ * Derived from drivers/vfio/pci/vfio_pci_intrs.c
+ *
+ * Copyright (C) 2012 Red Hat, Inc.  All rights reserved.
+ *     Author: Alex Williamson <alex.williamson@redhat.com>
+ *
+ * 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 <linux/vfio.h>
+#include <linux/eventfd.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+
+static struct workqueue_struct *vfio_irqfd_cleanup_wq;
+DEFINE_SPINLOCK(virqfd_lock);
+
+int __init vfio_virqfd_init(void)
+{
+	vfio_irqfd_cleanup_wq =
+		create_singlethread_workqueue("vfio-irqfd-cleanup");
+	if (!vfio_irqfd_cleanup_wq)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void vfio_virqfd_exit(void)
+{
+	destroy_workqueue(vfio_irqfd_cleanup_wq);
+}
+
+static void virqfd_deactivate(struct virqfd *virqfd)
+{
+	queue_work(vfio_irqfd_cleanup_wq, &virqfd->shutdown);
+}
+
+static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)
+{
+	struct virqfd *virqfd = container_of(wait, struct virqfd, wait);
+	unsigned long flags = (unsigned long)key;
+
+	if (flags & POLLIN) {
+		/* An event has been signaled, call function */
+		if ((!virqfd->handler ||
+		     virqfd->handler(virqfd->opaque, virqfd->data)) &&
+		    virqfd->thread)
+			schedule_work(&virqfd->inject);
+	}
+
+	if (flags & POLLHUP) {
+		unsigned long flags;
+		spin_lock_irqsave(&virqfd_lock, flags);
+
+		/*
+		 * The eventfd is closing, if the virqfd has not yet been
+		 * queued for release, as determined by testing whether the
+		 * virqfd pointer to it is still valid, queue it now.  As
+		 * with kvm irqfds, we know we won't race against the virqfd
+		 * going away because we hold the lock to get here.
+		 */
+		if (*(virqfd->pvirqfd) == virqfd) {
+			*(virqfd->pvirqfd) = NULL;
+			virqfd_deactivate(virqfd);
+		}
+
+		spin_unlock_irqrestore(&virqfd_lock, flags);
+	}
+
+	return 0;
+}
+
+static void virqfd_ptable_queue_proc(struct file *file,
+				     wait_queue_head_t *wqh, poll_table *pt)
+{
+	struct virqfd *virqfd = container_of(pt, struct virqfd, pt);
+	add_wait_queue(wqh, &virqfd->wait);
+}
+
+static void virqfd_shutdown(struct work_struct *work)
+{
+	struct virqfd *virqfd = container_of(work, struct virqfd, shutdown);
+	u64 cnt;
+
+	eventfd_ctx_remove_wait_queue(virqfd->eventfd, &virqfd->wait, &cnt);
+	flush_work(&virqfd->inject);
+	eventfd_ctx_put(virqfd->eventfd);
+
+	kfree(virqfd);
+}
+
+static void virqfd_inject(struct work_struct *work)
+{
+	struct virqfd *virqfd = container_of(work, struct virqfd, inject);
+	if (virqfd->thread)
+		virqfd->thread(virqfd->opaque, virqfd->data);
+}
+
+int vfio_virqfd_enable(void *opaque,
+		       int (*handler)(void *, void *),
+		       void (*thread)(void *, void *),
+		       void *data, struct virqfd **pvirqfd, int fd)
+{
+	struct fd irqfd;
+	struct eventfd_ctx *ctx;
+	struct virqfd *virqfd;
+	int ret = 0;
+	unsigned int events;
+
+	virqfd = kzalloc(sizeof(*virqfd), GFP_KERNEL);
+	if (!virqfd)
+		return -ENOMEM;
+
+	virqfd->pvirqfd = pvirqfd;
+	virqfd->opaque = opaque;
+	virqfd->handler = handler;
+	virqfd->thread = thread;
+	virqfd->data = data;
+
+	INIT_WORK(&virqfd->shutdown, virqfd_shutdown);
+	INIT_WORK(&virqfd->inject, virqfd_inject);
+
+	irqfd = fdget(fd);
+	if (!irqfd.file) {
+		ret = -EBADF;
+		goto err_fd;
+	}
+
+	ctx = eventfd_ctx_fileget(irqfd.file);
+	if (IS_ERR(ctx)) {
+		ret = PTR_ERR(ctx);
+		goto err_ctx;
+	}
+
+	virqfd->eventfd = ctx;
+
+	/*
+	 * virqfds can be released by closing the eventfd or directly
+	 * through ioctl.  These are both done through a workqueue, so
+	 * we update the pointer to the virqfd under lock to avoid
+	 * pushing multiple jobs to release the same virqfd.
+	 */
+	spin_lock_irq(&virqfd_lock);
+
+	if (*pvirqfd) {
+		spin_unlock_irq(&virqfd_lock);
+		ret = -EBUSY;
+		goto err_busy;
+	}
+	*pvirqfd = virqfd;
+
+	spin_unlock_irq(&virqfd_lock);
+
+	/*
+	 * Install our own custom wake-up handling so we are notified via
+	 * a callback whenever someone signals the underlying eventfd.
+	 */
+	init_waitqueue_func_entry(&virqfd->wait, virqfd_wakeup);
+	init_poll_funcptr(&virqfd->pt, virqfd_ptable_queue_proc);
+
+	events = irqfd.file->f_op->poll(irqfd.file, &virqfd->pt);
+
+	/*
+	 * Check if there was an event already pending on the eventfd
+	 * before we registered and trigger it as if we didn't miss it.
+	 */
+	if (events & POLLIN) {
+		if ((!handler || handler(opaque, data)) && thread)
+			schedule_work(&virqfd->inject);
+	}
+
+	/*
+	 * Do not drop the file until the irqfd is fully initialized,
+	 * otherwise we might race against the POLLHUP.
+	 */
+	fdput(irqfd);
+
+	return 0;
+err_busy:
+	eventfd_ctx_put(ctx);
+err_ctx:
+	fdput(irqfd);
+err_fd:
+	kfree(virqfd);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vfio_virqfd_enable);
+
+void vfio_virqfd_disable(struct virqfd **pvirqfd)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&virqfd_lock, flags);
+
+	if (*pvirqfd) {
+		virqfd_deactivate(*pvirqfd);
+		*pvirqfd = NULL;
+	}
+
+	spin_unlock_irqrestore(&virqfd_lock, flags);
+
+	/*
+	 * Block until we know all outstanding shutdown jobs have completed.
+	 * Even if we don't queue the job, flush the wq to be sure it's
+	 * been released.
+	 */
+	flush_workqueue(vfio_irqfd_cleanup_wq);
+}
+EXPORT_SYMBOL_GPL(vfio_virqfd_disable);
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index d320411..5d45081 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -14,6 +14,8 @@
 
 #include <linux/iommu.h>
 #include <linux/mm.h>
+#include <linux/workqueue.h>
+#include <linux/poll.h>
 #include <uapi/linux/vfio.h>
 
 /**
@@ -121,4 +123,29 @@ static inline long vfio_spapr_iommu_eeh_ioctl(struct iommu_group *group,
 	return -ENOTTY;
 }
 #endif /* CONFIG_EEH */
+
+/*
+ * IRQfd - generic
+ */
+struct virqfd {
+	void			*opaque;
+	struct eventfd_ctx	*eventfd;
+	int			(*handler)(void *, void *);
+	void			(*thread)(void *, void *);
+	void			*data;
+	struct work_struct	inject;
+	wait_queue_t		wait;
+	poll_table		pt;
+	struct work_struct	shutdown;
+	struct virqfd		**pvirqfd;
+};
+
+extern int vfio_virqfd_init(void);
+extern void vfio_virqfd_exit(void);
+extern int vfio_virqfd_enable(void *opaque,
+			      int (*handler)(void *, void *),
+			      void (*thread)(void *, void *),
+			      void *data, struct virqfd **pvirqfd, int fd);
+extern void vfio_virqfd_disable(struct virqfd **pvirqfd);
+
 #endif /* VFIO_H */
-- 
2.1.4


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

* [PATCH v11 18/20] vfio: move eventfd support code for VFIO_PCI to a separate file
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	alex.williamson-H+wXaHxf7aLQT0dZR+AlfA
  Cc: open list:VFIO DRIVER, eric.auger-QSEj5FYQhm4dnm+yROfE0A,
	marc.zyngier-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8, Gavin Shan,
	open list, Alexander Gordeev, Bjorn Helgaas, Antonios Motakis,
	tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J, Jiang Liu,
	christoffer.dall-QSEj5FYQhm4dnm+yROfE0A

The virqfd functionality that is used by VFIO_PCI to implement interrupt
masking and unmasking via an eventfd, is generic enough and can be reused
by another driver. Move it to a separate file in order to allow the code
to be shared.

Signed-off-by: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
---
 drivers/vfio/pci/Makefile           |   3 +-
 drivers/vfio/pci/vfio_pci_intrs.c   | 215 ------------------------------------
 drivers/vfio/pci/vfio_pci_private.h |   3 -
 drivers/vfio/virqfd.c               | 213 +++++++++++++++++++++++++++++++++++
 include/linux/vfio.h                |  27 +++++
 5 files changed, 242 insertions(+), 219 deletions(-)
 create mode 100644 drivers/vfio/virqfd.c

diff --git a/drivers/vfio/pci/Makefile b/drivers/vfio/pci/Makefile
index 1310792..c7c8644 100644
--- a/drivers/vfio/pci/Makefile
+++ b/drivers/vfio/pci/Makefile
@@ -1,4 +1,5 @@
 
-vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o
+vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o \
+	      ../virqfd.o
 
 obj-$(CONFIG_VFIO_PCI) += vfio-pci.o
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 5b5fc23..de4befc 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -19,228 +19,13 @@
 #include <linux/msi.h>
 #include <linux/pci.h>
 #include <linux/file.h>
-#include <linux/poll.h>
 #include <linux/vfio.h>
 #include <linux/wait.h>
-#include <linux/workqueue.h>
 #include <linux/slab.h>
 
 #include "vfio_pci_private.h"
 
 /*
- * IRQfd - generic
- */
-struct virqfd {
-	void			*opaque;
-	struct eventfd_ctx	*eventfd;
-	int			(*handler)(void *, void *);
-	void			(*thread)(void *, void *);
-	void			*data;
-	struct work_struct	inject;
-	wait_queue_t		wait;
-	poll_table		pt;
-	struct work_struct	shutdown;
-	struct virqfd		**pvirqfd;
-};
-
-static struct workqueue_struct *vfio_irqfd_cleanup_wq;
-DEFINE_SPINLOCK(virqfd_lock);
-
-int __init vfio_virqfd_init(void)
-{
-	vfio_irqfd_cleanup_wq =
-		create_singlethread_workqueue("vfio-irqfd-cleanup");
-	if (!vfio_irqfd_cleanup_wq)
-		return -ENOMEM;
-
-	return 0;
-}
-
-void vfio_virqfd_exit(void)
-{
-	destroy_workqueue(vfio_irqfd_cleanup_wq);
-}
-
-static void virqfd_deactivate(struct virqfd *virqfd)
-{
-	queue_work(vfio_irqfd_cleanup_wq, &virqfd->shutdown);
-}
-
-static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)
-{
-	struct virqfd *virqfd = container_of(wait, struct virqfd, wait);
-	unsigned long flags = (unsigned long)key;
-
-	if (flags & POLLIN) {
-		/* An event has been signaled, call function */
-		if ((!virqfd->handler ||
-		     virqfd->handler(virqfd->opaque, virqfd->data)) &&
-		    virqfd->thread)
-			schedule_work(&virqfd->inject);
-	}
-
-	if (flags & POLLHUP) {
-		unsigned long flags;
-		spin_lock_irqsave(&virqfd_lock, flags);
-
-		/*
-		 * The eventfd is closing, if the virqfd has not yet been
-		 * queued for release, as determined by testing whether the
-		 * virqfd pointer to it is still valid, queue it now.  As
-		 * with kvm irqfds, we know we won't race against the virqfd
-		 * going away because we hold the lock to get here.
-		 */
-		if (*(virqfd->pvirqfd) == virqfd) {
-			*(virqfd->pvirqfd) = NULL;
-			virqfd_deactivate(virqfd);
-		}
-
-		spin_unlock_irqrestore(&virqfd_lock, flags);
-	}
-
-	return 0;
-}
-
-static void virqfd_ptable_queue_proc(struct file *file,
-				     wait_queue_head_t *wqh, poll_table *pt)
-{
-	struct virqfd *virqfd = container_of(pt, struct virqfd, pt);
-	add_wait_queue(wqh, &virqfd->wait);
-}
-
-static void virqfd_shutdown(struct work_struct *work)
-{
-	struct virqfd *virqfd = container_of(work, struct virqfd, shutdown);
-	u64 cnt;
-
-	eventfd_ctx_remove_wait_queue(virqfd->eventfd, &virqfd->wait, &cnt);
-	flush_work(&virqfd->inject);
-	eventfd_ctx_put(virqfd->eventfd);
-
-	kfree(virqfd);
-}
-
-static void virqfd_inject(struct work_struct *work)
-{
-	struct virqfd *virqfd = container_of(work, struct virqfd, inject);
-	if (virqfd->thread)
-		virqfd->thread(virqfd->opaque, virqfd->data);
-}
-
-int vfio_virqfd_enable(void *opaque,
-		       int (*handler)(void *, void *),
-		       void (*thread)(void *, void *),
-		       void *data, struct virqfd **pvirqfd, int fd)
-{
-	struct fd irqfd;
-	struct eventfd_ctx *ctx;
-	struct virqfd *virqfd;
-	int ret = 0;
-	unsigned int events;
-
-	virqfd = kzalloc(sizeof(*virqfd), GFP_KERNEL);
-	if (!virqfd)
-		return -ENOMEM;
-
-	virqfd->pvirqfd = pvirqfd;
-	virqfd->opaque = opaque;
-	virqfd->handler = handler;
-	virqfd->thread = thread;
-	virqfd->data = data;
-
-	INIT_WORK(&virqfd->shutdown, virqfd_shutdown);
-	INIT_WORK(&virqfd->inject, virqfd_inject);
-
-	irqfd = fdget(fd);
-	if (!irqfd.file) {
-		ret = -EBADF;
-		goto err_fd;
-	}
-
-	ctx = eventfd_ctx_fileget(irqfd.file);
-	if (IS_ERR(ctx)) {
-		ret = PTR_ERR(ctx);
-		goto err_ctx;
-	}
-
-	virqfd->eventfd = ctx;
-
-	/*
-	 * virqfds can be released by closing the eventfd or directly
-	 * through ioctl.  These are both done through a workqueue, so
-	 * we update the pointer to the virqfd under lock to avoid
-	 * pushing multiple jobs to release the same virqfd.
-	 */
-	spin_lock_irq(&virqfd_lock);
-
-	if (*pvirqfd) {
-		spin_unlock_irq(&virqfd_lock);
-		ret = -EBUSY;
-		goto err_busy;
-	}
-	*pvirqfd = virqfd;
-
-	spin_unlock_irq(&virqfd_lock);
-
-	/*
-	 * Install our own custom wake-up handling so we are notified via
-	 * a callback whenever someone signals the underlying eventfd.
-	 */
-	init_waitqueue_func_entry(&virqfd->wait, virqfd_wakeup);
-	init_poll_funcptr(&virqfd->pt, virqfd_ptable_queue_proc);
-
-	events = irqfd.file->f_op->poll(irqfd.file, &virqfd->pt);
-
-	/*
-	 * Check if there was an event already pending on the eventfd
-	 * before we registered and trigger it as if we didn't miss it.
-	 */
-	if (events & POLLIN) {
-		if ((!handler || handler(opaque, data)) && thread)
-			schedule_work(&virqfd->inject);
-	}
-
-	/*
-	 * Do not drop the file until the irqfd is fully initialized,
-	 * otherwise we might race against the POLLHUP.
-	 */
-	fdput(irqfd);
-
-	return 0;
-err_busy:
-	eventfd_ctx_put(ctx);
-err_ctx:
-	fdput(irqfd);
-err_fd:
-	kfree(virqfd);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(vfio_virqfd_enable);
-
-void vfio_virqfd_disable(struct virqfd **pvirqfd)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&virqfd_lock, flags);
-
-	if (*pvirqfd) {
-		virqfd_deactivate(*pvirqfd);
-		*pvirqfd = NULL;
-	}
-
-	spin_unlock_irqrestore(&virqfd_lock, flags);
-
-	/*
-	 * Block until we know all outstanding shutdown jobs have completed.
-	 * Even if we don't queue the job, flush the wq to be sure it's
-	 * been released.
-	 */
-	flush_workqueue(vfio_irqfd_cleanup_wq);
-}
-EXPORT_SYMBOL_GPL(vfio_virqfd_disable);
-
-/*
  * INTx
  */
 static void vfio_send_intx_eventfd(void *opaque, void *unused)
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h
index 2e2f0ea..4c89e0e 100644
--- a/drivers/vfio/pci/vfio_pci_private.h
+++ b/drivers/vfio/pci/vfio_pci_private.h
@@ -86,9 +86,6 @@ extern ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf,
 extern int vfio_pci_init_perm_bits(void);
 extern void vfio_pci_uninit_perm_bits(void);
 
-extern int vfio_virqfd_init(void);
-extern void vfio_virqfd_exit(void);
-
 extern int vfio_config_init(struct vfio_pci_device *vdev);
 extern void vfio_config_free(struct vfio_pci_device *vdev);
 #endif /* VFIO_PCI_PRIVATE_H */
diff --git a/drivers/vfio/virqfd.c b/drivers/vfio/virqfd.c
new file mode 100644
index 0000000..5967899
--- /dev/null
+++ b/drivers/vfio/virqfd.c
@@ -0,0 +1,213 @@
+/*
+ * VFIO generic eventfd code for IRQFD support.
+ * Derived from drivers/vfio/pci/vfio_pci_intrs.c
+ *
+ * Copyright (C) 2012 Red Hat, Inc.  All rights reserved.
+ *     Author: Alex Williamson <alex.williamson-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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 <linux/vfio.h>
+#include <linux/eventfd.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+
+static struct workqueue_struct *vfio_irqfd_cleanup_wq;
+DEFINE_SPINLOCK(virqfd_lock);
+
+int __init vfio_virqfd_init(void)
+{
+	vfio_irqfd_cleanup_wq =
+		create_singlethread_workqueue("vfio-irqfd-cleanup");
+	if (!vfio_irqfd_cleanup_wq)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void vfio_virqfd_exit(void)
+{
+	destroy_workqueue(vfio_irqfd_cleanup_wq);
+}
+
+static void virqfd_deactivate(struct virqfd *virqfd)
+{
+	queue_work(vfio_irqfd_cleanup_wq, &virqfd->shutdown);
+}
+
+static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)
+{
+	struct virqfd *virqfd = container_of(wait, struct virqfd, wait);
+	unsigned long flags = (unsigned long)key;
+
+	if (flags & POLLIN) {
+		/* An event has been signaled, call function */
+		if ((!virqfd->handler ||
+		     virqfd->handler(virqfd->opaque, virqfd->data)) &&
+		    virqfd->thread)
+			schedule_work(&virqfd->inject);
+	}
+
+	if (flags & POLLHUP) {
+		unsigned long flags;
+		spin_lock_irqsave(&virqfd_lock, flags);
+
+		/*
+		 * The eventfd is closing, if the virqfd has not yet been
+		 * queued for release, as determined by testing whether the
+		 * virqfd pointer to it is still valid, queue it now.  As
+		 * with kvm irqfds, we know we won't race against the virqfd
+		 * going away because we hold the lock to get here.
+		 */
+		if (*(virqfd->pvirqfd) == virqfd) {
+			*(virqfd->pvirqfd) = NULL;
+			virqfd_deactivate(virqfd);
+		}
+
+		spin_unlock_irqrestore(&virqfd_lock, flags);
+	}
+
+	return 0;
+}
+
+static void virqfd_ptable_queue_proc(struct file *file,
+				     wait_queue_head_t *wqh, poll_table *pt)
+{
+	struct virqfd *virqfd = container_of(pt, struct virqfd, pt);
+	add_wait_queue(wqh, &virqfd->wait);
+}
+
+static void virqfd_shutdown(struct work_struct *work)
+{
+	struct virqfd *virqfd = container_of(work, struct virqfd, shutdown);
+	u64 cnt;
+
+	eventfd_ctx_remove_wait_queue(virqfd->eventfd, &virqfd->wait, &cnt);
+	flush_work(&virqfd->inject);
+	eventfd_ctx_put(virqfd->eventfd);
+
+	kfree(virqfd);
+}
+
+static void virqfd_inject(struct work_struct *work)
+{
+	struct virqfd *virqfd = container_of(work, struct virqfd, inject);
+	if (virqfd->thread)
+		virqfd->thread(virqfd->opaque, virqfd->data);
+}
+
+int vfio_virqfd_enable(void *opaque,
+		       int (*handler)(void *, void *),
+		       void (*thread)(void *, void *),
+		       void *data, struct virqfd **pvirqfd, int fd)
+{
+	struct fd irqfd;
+	struct eventfd_ctx *ctx;
+	struct virqfd *virqfd;
+	int ret = 0;
+	unsigned int events;
+
+	virqfd = kzalloc(sizeof(*virqfd), GFP_KERNEL);
+	if (!virqfd)
+		return -ENOMEM;
+
+	virqfd->pvirqfd = pvirqfd;
+	virqfd->opaque = opaque;
+	virqfd->handler = handler;
+	virqfd->thread = thread;
+	virqfd->data = data;
+
+	INIT_WORK(&virqfd->shutdown, virqfd_shutdown);
+	INIT_WORK(&virqfd->inject, virqfd_inject);
+
+	irqfd = fdget(fd);
+	if (!irqfd.file) {
+		ret = -EBADF;
+		goto err_fd;
+	}
+
+	ctx = eventfd_ctx_fileget(irqfd.file);
+	if (IS_ERR(ctx)) {
+		ret = PTR_ERR(ctx);
+		goto err_ctx;
+	}
+
+	virqfd->eventfd = ctx;
+
+	/*
+	 * virqfds can be released by closing the eventfd or directly
+	 * through ioctl.  These are both done through a workqueue, so
+	 * we update the pointer to the virqfd under lock to avoid
+	 * pushing multiple jobs to release the same virqfd.
+	 */
+	spin_lock_irq(&virqfd_lock);
+
+	if (*pvirqfd) {
+		spin_unlock_irq(&virqfd_lock);
+		ret = -EBUSY;
+		goto err_busy;
+	}
+	*pvirqfd = virqfd;
+
+	spin_unlock_irq(&virqfd_lock);
+
+	/*
+	 * Install our own custom wake-up handling so we are notified via
+	 * a callback whenever someone signals the underlying eventfd.
+	 */
+	init_waitqueue_func_entry(&virqfd->wait, virqfd_wakeup);
+	init_poll_funcptr(&virqfd->pt, virqfd_ptable_queue_proc);
+
+	events = irqfd.file->f_op->poll(irqfd.file, &virqfd->pt);
+
+	/*
+	 * Check if there was an event already pending on the eventfd
+	 * before we registered and trigger it as if we didn't miss it.
+	 */
+	if (events & POLLIN) {
+		if ((!handler || handler(opaque, data)) && thread)
+			schedule_work(&virqfd->inject);
+	}
+
+	/*
+	 * Do not drop the file until the irqfd is fully initialized,
+	 * otherwise we might race against the POLLHUP.
+	 */
+	fdput(irqfd);
+
+	return 0;
+err_busy:
+	eventfd_ctx_put(ctx);
+err_ctx:
+	fdput(irqfd);
+err_fd:
+	kfree(virqfd);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vfio_virqfd_enable);
+
+void vfio_virqfd_disable(struct virqfd **pvirqfd)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&virqfd_lock, flags);
+
+	if (*pvirqfd) {
+		virqfd_deactivate(*pvirqfd);
+		*pvirqfd = NULL;
+	}
+
+	spin_unlock_irqrestore(&virqfd_lock, flags);
+
+	/*
+	 * Block until we know all outstanding shutdown jobs have completed.
+	 * Even if we don't queue the job, flush the wq to be sure it's
+	 * been released.
+	 */
+	flush_workqueue(vfio_irqfd_cleanup_wq);
+}
+EXPORT_SYMBOL_GPL(vfio_virqfd_disable);
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index d320411..5d45081 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -14,6 +14,8 @@
 
 #include <linux/iommu.h>
 #include <linux/mm.h>
+#include <linux/workqueue.h>
+#include <linux/poll.h>
 #include <uapi/linux/vfio.h>
 
 /**
@@ -121,4 +123,29 @@ static inline long vfio_spapr_iommu_eeh_ioctl(struct iommu_group *group,
 	return -ENOTTY;
 }
 #endif /* CONFIG_EEH */
+
+/*
+ * IRQfd - generic
+ */
+struct virqfd {
+	void			*opaque;
+	struct eventfd_ctx	*eventfd;
+	int			(*handler)(void *, void *);
+	void			(*thread)(void *, void *);
+	void			*data;
+	struct work_struct	inject;
+	wait_queue_t		wait;
+	poll_table		pt;
+	struct work_struct	shutdown;
+	struct virqfd		**pvirqfd;
+};
+
+extern int vfio_virqfd_init(void);
+extern void vfio_virqfd_exit(void);
+extern int vfio_virqfd_enable(void *opaque,
+			      int (*handler)(void *, void *),
+			      void (*thread)(void *, void *),
+			      void *data, struct virqfd **pvirqfd, int fd);
+extern void vfio_virqfd_disable(struct virqfd **pvirqfd);
+
 #endif /* VFIO_H */
-- 
2.1.4

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

* [PATCH v11 19/20] vfio: initialize the virqfd workqueue in VFIO generic code
       [not found] ` <1420541335-17190-1-git-send-email-a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-09  8:39   ` Eric Auger
  2015-01-19 18:39   ` Alex Williamson
  2 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, Gavin Shan,
	Benjamin Herrenschmidt, Bjorn Helgaas, Alexey Kardashevskiy,
	open list:VFIO DRIVER, open list

Now we have finally completely decoupled virqfd from VFIO_PCI. We can
initialize it from the VFIO generic code, in order to safely use it from
multiple independent VFIO bus drivers.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/Makefile       | 4 +++-
 drivers/vfio/pci/Makefile   | 3 +--
 drivers/vfio/pci/vfio_pci.c | 8 --------
 drivers/vfio/vfio.c         | 8 ++++++++
 4 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index dadf0ca..d798b09 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -1,4 +1,6 @@
-obj-$(CONFIG_VFIO) += vfio.o
+vfio_core-y := vfio.o virqfd.o
+
+obj-$(CONFIG_VFIO) += vfio_core.o
 obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
 obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
 obj-$(CONFIG_VFIO_SPAPR_EEH) += vfio_spapr_eeh.o
diff --git a/drivers/vfio/pci/Makefile b/drivers/vfio/pci/Makefile
index c7c8644..1310792 100644
--- a/drivers/vfio/pci/Makefile
+++ b/drivers/vfio/pci/Makefile
@@ -1,5 +1,4 @@
 
-vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o \
-	      ../virqfd.o
+vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o
 
 obj-$(CONFIG_VFIO_PCI) += vfio-pci.o
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index fc4308c..8d156d7 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -1012,7 +1012,6 @@ put_devs:
 static void __exit vfio_pci_cleanup(void)
 {
 	pci_unregister_driver(&vfio_pci_driver);
-	vfio_virqfd_exit();
 	vfio_pci_uninit_perm_bits();
 }
 
@@ -1025,11 +1024,6 @@ static int __init vfio_pci_init(void)
 	if (ret)
 		return ret;
 
-	/* Start the virqfd cleanup handler */
-	ret = vfio_virqfd_init();
-	if (ret)
-		goto out_virqfd;
-
 	/* Register and scan for devices */
 	ret = pci_register_driver(&vfio_pci_driver);
 	if (ret)
@@ -1038,8 +1032,6 @@ static int __init vfio_pci_init(void)
 	return 0;
 
 out_driver:
-	vfio_virqfd_exit();
-out_virqfd:
 	vfio_pci_uninit_perm_bits();
 	return ret;
 }
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index f018d8d..8e84471 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -1464,6 +1464,11 @@ static int __init vfio_init(void)
 	if (ret)
 		goto err_cdev_add;
 
+	/* Start the virqfd cleanup handler used by some VFIO bus drivers */
+	ret = vfio_virqfd_init();
+	if (ret)
+		goto err_virqfd;
+
 	pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 
 	/*
@@ -1476,6 +1481,8 @@ static int __init vfio_init(void)
 
 	return 0;
 
+err_virqfd:
+	cdev_del(&vfio.group_cdev);
 err_cdev_add:
 	unregister_chrdev_region(vfio.group_devt, MINORMASK);
 err_alloc_chrdev:
@@ -1490,6 +1497,7 @@ static void __exit vfio_cleanup(void)
 {
 	WARN_ON(!list_empty(&vfio.group_list));
 
+	vfio_virqfd_exit();
 	idr_destroy(&vfio.group_idr);
 	cdev_del(&vfio.group_cdev);
 	unregister_chrdev_region(vfio.group_devt, MINORMASK);
-- 
2.1.4


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

* [PATCH v11 19/20] vfio: initialize the virqfd workqueue in VFIO generic code
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	alex.williamson-H+wXaHxf7aLQT0dZR+AlfA
  Cc: open list:VFIO DRIVER, eric.auger-QSEj5FYQhm4dnm+yROfE0A,
	marc.zyngier-5wv7dgnIgG8, Benjamin Herrenschmidt,
	will.deacon-5wv7dgnIgG8, Gavin Shan, open list,
	Alexey Kardashevskiy, Bjorn Helgaas, Antonios Motakis,
	tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J,
	christoffer.dall-QSEj5FYQhm4dnm+yROfE0A

Now we have finally completely decoupled virqfd from VFIO_PCI. We can
initialize it from the VFIO generic code, in order to safely use it from
multiple independent VFIO bus drivers.

Signed-off-by: Antonios Motakis <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
---
 drivers/vfio/Makefile       | 4 +++-
 drivers/vfio/pci/Makefile   | 3 +--
 drivers/vfio/pci/vfio_pci.c | 8 --------
 drivers/vfio/vfio.c         | 8 ++++++++
 4 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index dadf0ca..d798b09 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -1,4 +1,6 @@
-obj-$(CONFIG_VFIO) += vfio.o
+vfio_core-y := vfio.o virqfd.o
+
+obj-$(CONFIG_VFIO) += vfio_core.o
 obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
 obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
 obj-$(CONFIG_VFIO_SPAPR_EEH) += vfio_spapr_eeh.o
diff --git a/drivers/vfio/pci/Makefile b/drivers/vfio/pci/Makefile
index c7c8644..1310792 100644
--- a/drivers/vfio/pci/Makefile
+++ b/drivers/vfio/pci/Makefile
@@ -1,5 +1,4 @@
 
-vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o \
-	      ../virqfd.o
+vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o
 
 obj-$(CONFIG_VFIO_PCI) += vfio-pci.o
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index fc4308c..8d156d7 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -1012,7 +1012,6 @@ put_devs:
 static void __exit vfio_pci_cleanup(void)
 {
 	pci_unregister_driver(&vfio_pci_driver);
-	vfio_virqfd_exit();
 	vfio_pci_uninit_perm_bits();
 }
 
@@ -1025,11 +1024,6 @@ static int __init vfio_pci_init(void)
 	if (ret)
 		return ret;
 
-	/* Start the virqfd cleanup handler */
-	ret = vfio_virqfd_init();
-	if (ret)
-		goto out_virqfd;
-
 	/* Register and scan for devices */
 	ret = pci_register_driver(&vfio_pci_driver);
 	if (ret)
@@ -1038,8 +1032,6 @@ static int __init vfio_pci_init(void)
 	return 0;
 
 out_driver:
-	vfio_virqfd_exit();
-out_virqfd:
 	vfio_pci_uninit_perm_bits();
 	return ret;
 }
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index f018d8d..8e84471 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -1464,6 +1464,11 @@ static int __init vfio_init(void)
 	if (ret)
 		goto err_cdev_add;
 
+	/* Start the virqfd cleanup handler used by some VFIO bus drivers */
+	ret = vfio_virqfd_init();
+	if (ret)
+		goto err_virqfd;
+
 	pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 
 	/*
@@ -1476,6 +1481,8 @@ static int __init vfio_init(void)
 
 	return 0;
 
+err_virqfd:
+	cdev_del(&vfio.group_cdev);
 err_cdev_add:
 	unregister_chrdev_region(vfio.group_devt, MINORMASK);
 err_alloc_chrdev:
@@ -1490,6 +1497,7 @@ static void __exit vfio_cleanup(void)
 {
 	WARN_ON(!list_empty(&vfio.group_list));
 
+	vfio_virqfd_exit();
 	idr_destroy(&vfio.group_idr);
 	cdev_del(&vfio.group_cdev);
 	unregister_chrdev_region(vfio.group_devt, MINORMASK);
-- 
2.1.4

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

* [PATCH v11 20/20] vfio/platform: implement IRQ masking/unmasking via an eventfd
  2015-01-06 10:48 [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Antonios Motakis
@ 2015-01-06 10:48   ` Antonios Motakis
  2015-01-06 10:48   ` Antonios Motakis
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list:VFIO DRIVER, open list

With this patch the VFIO user will be able to set an eventfd that can be
used in order to mask and unmask IRQs of platform devices.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_irq.c     | 47 ++++++++++++++++++++++++---
 drivers/vfio/platform/vfio_platform_private.h |  2 ++
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c
index b3602cb..6ade36b 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -37,6 +37,15 @@ static void vfio_platform_mask(struct vfio_platform_irq *irq_ctx)
 	spin_unlock_irqrestore(&irq_ctx->lock, flags);
 }
 
+static int vfio_platform_mask_handler(void *opaque, void *unused)
+{
+	struct vfio_platform_irq *irq_ctx = opaque;
+
+	vfio_platform_mask(irq_ctx);
+
+	return 0;
+}
+
 static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
 				      unsigned index, unsigned start,
 				      unsigned count, uint32_t flags,
@@ -48,8 +57,18 @@ static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
 	if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
 		return -EINVAL;
 
-	if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
-		return -EINVAL; /* not implemented yet */
+	if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+		int32_t fd = *(int32_t *)data;
+
+		if (fd >= 0)
+			return vfio_virqfd_enable((void *) &vdev->irqs[index],
+						  vfio_platform_mask_handler,
+						  NULL, NULL,
+						  &vdev->irqs[index].mask, fd);
+
+		vfio_virqfd_disable(&vdev->irqs[index].mask);
+		return 0;
+	}
 
 	if (flags & VFIO_IRQ_SET_DATA_NONE) {
 		vfio_platform_mask(&vdev->irqs[index]);
@@ -78,6 +97,15 @@ static void vfio_platform_unmask(struct vfio_platform_irq *irq_ctx)
 	spin_unlock_irqrestore(&irq_ctx->lock, flags);
 }
 
+static int vfio_platform_unmask_handler(void *opaque, void *unused)
+{
+	struct vfio_platform_irq *irq_ctx = opaque;
+
+	vfio_platform_unmask(irq_ctx);
+
+	return 0;
+}
+
 static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
 					unsigned index, unsigned start,
 					unsigned count, uint32_t flags,
@@ -89,8 +117,19 @@ static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
 	if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
 		return -EINVAL;
 
-	if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
-		return -EINVAL; /* not implemented yet */
+	if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+		int32_t fd = *(int32_t *)data;
+
+		if (fd >= 0)
+			return vfio_virqfd_enable((void *) &vdev->irqs[index],
+						  vfio_platform_unmask_handler,
+						  NULL, NULL,
+						  &vdev->irqs[index].unmask,
+						  fd);
+
+		vfio_virqfd_disable(&vdev->irqs[index].unmask);
+		return 0;
+	}
 
 	if (flags & VFIO_IRQ_SET_DATA_NONE) {
 		vfio_platform_unmask(&vdev->irqs[index]);
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index eef6d1b..c3d5b4b 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -32,6 +32,8 @@ struct vfio_platform_irq {
 	struct eventfd_ctx	*trigger;
 	bool			masked;
 	spinlock_t		lock;
+	struct virqfd		*unmask;
+	struct virqfd		*mask;
 };
 
 struct vfio_platform_region {
-- 
2.1.4


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

* [PATCH v11 20/20] vfio/platform: implement IRQ masking/unmasking via an eventfd
@ 2015-01-06 10:48   ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-06 10:48 UTC (permalink / raw)
  To: kvmarm, iommu, alex.williamson
  Cc: will.deacon, tech, christoffer.dall, eric.auger, kim.phillips,
	marc.zyngier, Antonios Motakis, open list:VFIO DRIVER, open list

With this patch the VFIO user will be able to set an eventfd that can be
used in order to mask and unmask IRQs of platform devices.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_irq.c     | 47 ++++++++++++++++++++++++---
 drivers/vfio/platform/vfio_platform_private.h |  2 ++
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c
index b3602cb..6ade36b 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -37,6 +37,15 @@ static void vfio_platform_mask(struct vfio_platform_irq *irq_ctx)
 	spin_unlock_irqrestore(&irq_ctx->lock, flags);
 }
 
+static int vfio_platform_mask_handler(void *opaque, void *unused)
+{
+	struct vfio_platform_irq *irq_ctx = opaque;
+
+	vfio_platform_mask(irq_ctx);
+
+	return 0;
+}
+
 static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
 				      unsigned index, unsigned start,
 				      unsigned count, uint32_t flags,
@@ -48,8 +57,18 @@ static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
 	if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
 		return -EINVAL;
 
-	if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
-		return -EINVAL; /* not implemented yet */
+	if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+		int32_t fd = *(int32_t *)data;
+
+		if (fd >= 0)
+			return vfio_virqfd_enable((void *) &vdev->irqs[index],
+						  vfio_platform_mask_handler,
+						  NULL, NULL,
+						  &vdev->irqs[index].mask, fd);
+
+		vfio_virqfd_disable(&vdev->irqs[index].mask);
+		return 0;
+	}
 
 	if (flags & VFIO_IRQ_SET_DATA_NONE) {
 		vfio_platform_mask(&vdev->irqs[index]);
@@ -78,6 +97,15 @@ static void vfio_platform_unmask(struct vfio_platform_irq *irq_ctx)
 	spin_unlock_irqrestore(&irq_ctx->lock, flags);
 }
 
+static int vfio_platform_unmask_handler(void *opaque, void *unused)
+{
+	struct vfio_platform_irq *irq_ctx = opaque;
+
+	vfio_platform_unmask(irq_ctx);
+
+	return 0;
+}
+
 static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
 					unsigned index, unsigned start,
 					unsigned count, uint32_t flags,
@@ -89,8 +117,19 @@ static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
 	if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
 		return -EINVAL;
 
-	if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
-		return -EINVAL; /* not implemented yet */
+	if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+		int32_t fd = *(int32_t *)data;
+
+		if (fd >= 0)
+			return vfio_virqfd_enable((void *) &vdev->irqs[index],
+						  vfio_platform_unmask_handler,
+						  NULL, NULL,
+						  &vdev->irqs[index].unmask,
+						  fd);
+
+		vfio_virqfd_disable(&vdev->irqs[index].unmask);
+		return 0;
+	}
 
 	if (flags & VFIO_IRQ_SET_DATA_NONE) {
 		vfio_platform_unmask(&vdev->irqs[index]);
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index eef6d1b..c3d5b4b 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -32,6 +32,8 @@ struct vfio_platform_irq {
 	struct eventfd_ctx	*trigger;
 	bool			masked;
 	spinlock_t		lock;
+	struct virqfd		*unmask;
+	struct virqfd		*mask;
 };
 
 struct vfio_platform_region {
-- 
2.1.4


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

* Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices
       [not found] ` <1420541335-17190-1-git-send-email-a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
@ 2015-01-08 16:58   ` Eric Auger
  2015-01-09  8:39   ` Eric Auger
  2015-01-19 18:39   ` Alex Williamson
  2 siblings, 0 replies; 54+ messages in thread
From: Eric Auger @ 2015-01-08 16:58 UTC (permalink / raw)
  To: Antonios Motakis, kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	alex.williamson-H+wXaHxf7aLQT0dZR+AlfA
  Cc: marc.zyngier-5wv7dgnIgG8, tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J,
	will.deacon-5wv7dgnIgG8, christoffer.dall-QSEj5FYQhm4dnm+yROfE0A

Hi Antonios,

Tested-by: Eric Auger <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Best Regards

Eric

On 01/06/2015 11:48 AM, Antonios Motakis wrote:
> This patch series aims to implement VFIO support for platform devices that
> reside behind an IOMMU. Examples of such devices are devices behind an ARM
> SMMU, or behind a Samsung Exynos System MMU.
> 
> The API used is based on the existing VFIO API that is also used with PCI
> devices. Only devices that include a basic set of IRQs and memory regions are
> targeted; devices with complex relationships with other devices on a device
> tree are not taken into account at this stage.
> 
> This patch series may be applied on the following series/patches:
>  - [PATCH] driver core: amba: add device binding path 'driver_override'
>  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1
> 
> A copy can be cloned from the branch vfio-platform-v11 at:
> git-9UaJU3cA/F/QT0dZR+AlfA@public.gmane.org:virtualopensystems/linux-kvm-arm.git
> 
> Changes since v10:
>  - Check if interrupt is already masked when setting a new trigger
>  - Fixed kasprintf with unchecked return value in VFIO AMBA driver
> Changes since v9:
>  - Reworked the splitting of the patches that decouple virqfd from PCI
>  - Some styling issues and typos
>  - Removed superfluous includes
>  - AMBA devices are now named vfio-amba- suffixed by the AMBA device id
>  - Several other cleanups and fixes
> Changes since v8:
>  - Separate irq handler for edge and level triggered interrupts
>  - Mutex based lock for VFIO fd open/release
>  - Fixed bug where the first region of a platform device wasn't exposed
>  - Read only regions can be MMAPed only read only
>  - Code cleanups
> Changes since v7:
>  - Some initial placeholder functionality for PIO resources
>  - Cleaned up code for IRQ triggering, masking and unmasking
>  - Some functionality has been removed from this series and posted separately:
>    - VFIO_IOMMU_TYPE1 support for ARM SMMUs
>    - IOMMU NOEXEC patches
>    - driver_override functionality for AMBA devices
>  - Several fixes
> Changes since v6:
>  - Integrated support for AMBA devices
>  - Numerous cleanups and fixes
> Changes since v5:
>  - Full eventfd support for IRQ masking and unmasking.
>  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags in VFIO.
>  - Other fixes based on reviewer comments.
> Changes since v4:
>  - Use static offsets for each region in the VFIO device fd
>  - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
>    availability via IOMMU_CAP_DMA_EXEC
>  - Rebased on VFIO multi domain support:
>    - IOMMU_EXEC is now available if at least one IOMMU in the container
>      supports it
>    - Expose IOMMU_EXEC if available via the capability VFIO_IOMMU_PROT_EXEC
>  - Some bug fixes
> Changes since v3:
>  - Use Kim Phillips' driver_probe_device()
> Changes since v2:
>  - Fixed Read/Write and MMAP on device regions
>  - Removed dependency on Device Tree
>  - Interrupts support
>  - Interrupt masking/unmasking
>  - Automask level sensitive interrupts
>  - Introduced VFIO_DMA_MAP_FLAG_EXEC
>  - Code clean ups
> 
> Antonios Motakis (20):
>   vfio/platform: initial skeleton of VFIO support for platform devices
>   vfio: platform: probe to devices on the platform bus
>   vfio: platform: add the VFIO PLATFORM module to Kconfig
>   vfio: amba: VFIO support for AMBA devices
>   vfio: amba: add the VFIO for AMBA devices module to Kconfig
>   vfio/platform: return info for bound device
>   vfio/platform: return info for device memory mapped IO regions
>   vfio/platform: read and write support for the device fd
>   vfio/platform: support MMAP of MMIO regions
>   vfio/platform: return IRQ info
>   vfio/platform: initial interrupts support code
>   vfio/platform: trigger an interrupt via eventfd
>   vfio/platform: support for level sensitive interrupts
>   vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and
>     export
>   vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
>   vfio: add local lock for virqfd instead of depending on VFIO PCI
>   vfio: pass an opaque pointer on virqfd initialization
>   vfio: move eventfd support code for VFIO_PCI to a separate file
>   vfio: initialize the virqfd workqueue in VFIO generic code
>   vfio/platform: implement IRQ masking/unmasking via an eventfd
> 
>  drivers/vfio/Kconfig                          |   1 +
>  drivers/vfio/Makefile                         |   5 +-
>  drivers/vfio/pci/vfio_pci.c                   |   8 -
>  drivers/vfio/pci/vfio_pci_intrs.c             | 238 +-----------
>  drivers/vfio/pci/vfio_pci_private.h           |   3 -
>  drivers/vfio/platform/Kconfig                 |  19 +
>  drivers/vfio/platform/Makefile                |   8 +
>  drivers/vfio/platform/vfio_amba.c             | 115 ++++++
>  drivers/vfio/platform/vfio_platform.c         | 103 +++++
>  drivers/vfio/platform/vfio_platform_common.c  | 520 ++++++++++++++++++++++++++
>  drivers/vfio/platform/vfio_platform_irq.c     | 340 +++++++++++++++++
>  drivers/vfio/platform/vfio_platform_private.h |  82 ++++
>  drivers/vfio/vfio.c                           |   8 +
>  drivers/vfio/virqfd.c                         | 213 +++++++++++
>  include/linux/vfio.h                          |  27 ++
>  include/uapi/linux/vfio.h                     |   2 +
>  16 files changed, 1456 insertions(+), 236 deletions(-)
>  create mode 100644 drivers/vfio/platform/Kconfig
>  create mode 100644 drivers/vfio/platform/Makefile
>  create mode 100644 drivers/vfio/platform/vfio_amba.c
>  create mode 100644 drivers/vfio/platform/vfio_platform.c
>  create mode 100644 drivers/vfio/platform/vfio_platform_common.c
>  create mode 100644 drivers/vfio/platform/vfio_platform_irq.c
>  create mode 100644 drivers/vfio/platform/vfio_platform_private.h
>  create mode 100644 drivers/vfio/virqfd.c
> 

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

* Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices
       [not found] ` <1420541335-17190-1-git-send-email-a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
  2015-01-08 16:58   ` [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Eric Auger
@ 2015-01-09  8:39   ` Eric Auger
       [not found]     ` <54AF93AB.9030302-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  2015-01-19 18:39   ` Alex Williamson
  2 siblings, 1 reply; 54+ messages in thread
From: Eric Auger @ 2015-01-09  8:39 UTC (permalink / raw)
  To: Antonios Motakis, kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	alex.williamson-H+wXaHxf7aLQT0dZR+AlfA
  Cc: marc.zyngier-5wv7dgnIgG8, tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J,
	will.deacon-5wv7dgnIgG8, christoffer.dall-QSEj5FYQhm4dnm+yROfE0A

Hi Antonios,

when moving to 3.19rc3 I observe a regression with my xgmac use case
(real-time change?).

I guess what happens is when I kill a first qemu session, guest does not
have time to complete the virtual IRQ and the unmask is not performed by
the virqfd handler. When starting a new QEMU session, the irqfd
signalling is put in place again but since the masked field is set, the
IRQ is left unmasked (v11 modification in vfio_set_trigger).

The problem is that we don't discriminate between user mask action and
automasked handler action. In case the user did not mask, I think we
should reset the masked field when doing the free_irq. What do you think?

Best Regards

Eric

On 01/06/2015 11:48 AM, Antonios Motakis wrote:
> This patch series aims to implement VFIO support for platform devices that
> reside behind an IOMMU. Examples of such devices are devices behind an ARM
> SMMU, or behind a Samsung Exynos System MMU.
> 
> The API used is based on the existing VFIO API that is also used with PCI
> devices. Only devices that include a basic set of IRQs and memory regions are
> targeted; devices with complex relationships with other devices on a device
> tree are not taken into account at this stage.
> 
> This patch series may be applied on the following series/patches:
>  - [PATCH] driver core: amba: add device binding path 'driver_override'
>  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1
> 
> A copy can be cloned from the branch vfio-platform-v11 at:
> git-9UaJU3cA/F/QT0dZR+AlfA@public.gmane.org:virtualopensystems/linux-kvm-arm.git
> 
> Changes since v10:
>  - Check if interrupt is already masked when setting a new trigger
>  - Fixed kasprintf with unchecked return value in VFIO AMBA driver
> Changes since v9:
>  - Reworked the splitting of the patches that decouple virqfd from PCI
>  - Some styling issues and typos
>  - Removed superfluous includes
>  - AMBA devices are now named vfio-amba- suffixed by the AMBA device id
>  - Several other cleanups and fixes
> Changes since v8:
>  - Separate irq handler for edge and level triggered interrupts
>  - Mutex based lock for VFIO fd open/release
>  - Fixed bug where the first region of a platform device wasn't exposed
>  - Read only regions can be MMAPed only read only
>  - Code cleanups
> Changes since v7:
>  - Some initial placeholder functionality for PIO resources
>  - Cleaned up code for IRQ triggering, masking and unmasking
>  - Some functionality has been removed from this series and posted separately:
>    - VFIO_IOMMU_TYPE1 support for ARM SMMUs
>    - IOMMU NOEXEC patches
>    - driver_override functionality for AMBA devices
>  - Several fixes
> Changes since v6:
>  - Integrated support for AMBA devices
>  - Numerous cleanups and fixes
> Changes since v5:
>  - Full eventfd support for IRQ masking and unmasking.
>  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags in VFIO.
>  - Other fixes based on reviewer comments.
> Changes since v4:
>  - Use static offsets for each region in the VFIO device fd
>  - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
>    availability via IOMMU_CAP_DMA_EXEC
>  - Rebased on VFIO multi domain support:
>    - IOMMU_EXEC is now available if at least one IOMMU in the container
>      supports it
>    - Expose IOMMU_EXEC if available via the capability VFIO_IOMMU_PROT_EXEC
>  - Some bug fixes
> Changes since v3:
>  - Use Kim Phillips' driver_probe_device()
> Changes since v2:
>  - Fixed Read/Write and MMAP on device regions
>  - Removed dependency on Device Tree
>  - Interrupts support
>  - Interrupt masking/unmasking
>  - Automask level sensitive interrupts
>  - Introduced VFIO_DMA_MAP_FLAG_EXEC
>  - Code clean ups
> 
> Antonios Motakis (20):
>   vfio/platform: initial skeleton of VFIO support for platform devices
>   vfio: platform: probe to devices on the platform bus
>   vfio: platform: add the VFIO PLATFORM module to Kconfig
>   vfio: amba: VFIO support for AMBA devices
>   vfio: amba: add the VFIO for AMBA devices module to Kconfig
>   vfio/platform: return info for bound device
>   vfio/platform: return info for device memory mapped IO regions
>   vfio/platform: read and write support for the device fd
>   vfio/platform: support MMAP of MMIO regions
>   vfio/platform: return IRQ info
>   vfio/platform: initial interrupts support code
>   vfio/platform: trigger an interrupt via eventfd
>   vfio/platform: support for level sensitive interrupts
>   vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and
>     export
>   vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
>   vfio: add local lock for virqfd instead of depending on VFIO PCI
>   vfio: pass an opaque pointer on virqfd initialization
>   vfio: move eventfd support code for VFIO_PCI to a separate file
>   vfio: initialize the virqfd workqueue in VFIO generic code
>   vfio/platform: implement IRQ masking/unmasking via an eventfd
> 
>  drivers/vfio/Kconfig                          |   1 +
>  drivers/vfio/Makefile                         |   5 +-
>  drivers/vfio/pci/vfio_pci.c                   |   8 -
>  drivers/vfio/pci/vfio_pci_intrs.c             | 238 +-----------
>  drivers/vfio/pci/vfio_pci_private.h           |   3 -
>  drivers/vfio/platform/Kconfig                 |  19 +
>  drivers/vfio/platform/Makefile                |   8 +
>  drivers/vfio/platform/vfio_amba.c             | 115 ++++++
>  drivers/vfio/platform/vfio_platform.c         | 103 +++++
>  drivers/vfio/platform/vfio_platform_common.c  | 520 ++++++++++++++++++++++++++
>  drivers/vfio/platform/vfio_platform_irq.c     | 340 +++++++++++++++++
>  drivers/vfio/platform/vfio_platform_private.h |  82 ++++
>  drivers/vfio/vfio.c                           |   8 +
>  drivers/vfio/virqfd.c                         | 213 +++++++++++
>  include/linux/vfio.h                          |  27 ++
>  include/uapi/linux/vfio.h                     |   2 +
>  16 files changed, 1456 insertions(+), 236 deletions(-)
>  create mode 100644 drivers/vfio/platform/Kconfig
>  create mode 100644 drivers/vfio/platform/Makefile
>  create mode 100644 drivers/vfio/platform/vfio_amba.c
>  create mode 100644 drivers/vfio/platform/vfio_platform.c
>  create mode 100644 drivers/vfio/platform/vfio_platform_common.c
>  create mode 100644 drivers/vfio/platform/vfio_platform_irq.c
>  create mode 100644 drivers/vfio/platform/vfio_platform_private.h
>  create mode 100644 drivers/vfio/virqfd.c
> 

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

* Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices
       [not found]     ` <54AF93AB.9030302-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2015-01-09 11:33       ` Antonios Motakis
       [not found]         ` <CAG8rG2yc1ityUwswPiTR_w5f3tSeX_KB2g06HcPCPARXPHGvfg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 54+ messages in thread
From: Antonios Motakis @ 2015-01-09 11:33 UTC (permalink / raw)
  To: Eric Auger
  Cc: Baptiste Reynal, Marc Zyngier, Will Deacon, Linux IOMMU,
	VirtualOpenSystems Technical Team, kvm-arm, Christoffer Dall

On Fri, Jan 9, 2015 at 9:39 AM, Eric Auger <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> Hi Antonios,
>
> when moving to 3.19rc3 I observe a regression with my xgmac use case
> (real-time change?).
>
> I guess what happens is when I kill a first qemu session, guest does not
> have time to complete the virtual IRQ and the unmask is not performed by
> the virqfd handler. When starting a new QEMU session, the irqfd
> signalling is put in place again but since the masked field is set, the
> IRQ is left unmasked (v11 modification in vfio_set_trigger).
>
> The problem is that we don't discriminate between user mask action and
> automasked handler action. In case the user did not mask, I think we
> should reset the masked field when doing the free_irq. What do you think?

Hello Eric,

I agree, we should reset the masked field for future users.

Best regards
Antonios

>
> Best Regards
>
> Eric
>
> On 01/06/2015 11:48 AM, Antonios Motakis wrote:
>> This patch series aims to implement VFIO support for platform devices that
>> reside behind an IOMMU. Examples of such devices are devices behind an ARM
>> SMMU, or behind a Samsung Exynos System MMU.
>>
>> The API used is based on the existing VFIO API that is also used with PCI
>> devices. Only devices that include a basic set of IRQs and memory regions are
>> targeted; devices with complex relationships with other devices on a device
>> tree are not taken into account at this stage.
>>
>> This patch series may be applied on the following series/patches:
>>  - [PATCH] driver core: amba: add device binding path 'driver_override'
>>  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1
>>
>> A copy can be cloned from the branch vfio-platform-v11 at:
>> git-9UaJU3cA/F/QT0dZR+AlfA@public.gmane.org:virtualopensystems/linux-kvm-arm.git
>>
>> Changes since v10:
>>  - Check if interrupt is already masked when setting a new trigger
>>  - Fixed kasprintf with unchecked return value in VFIO AMBA driver
>> Changes since v9:
>>  - Reworked the splitting of the patches that decouple virqfd from PCI
>>  - Some styling issues and typos
>>  - Removed superfluous includes
>>  - AMBA devices are now named vfio-amba- suffixed by the AMBA device id
>>  - Several other cleanups and fixes
>> Changes since v8:
>>  - Separate irq handler for edge and level triggered interrupts
>>  - Mutex based lock for VFIO fd open/release
>>  - Fixed bug where the first region of a platform device wasn't exposed
>>  - Read only regions can be MMAPed only read only
>>  - Code cleanups
>> Changes since v7:
>>  - Some initial placeholder functionality for PIO resources
>>  - Cleaned up code for IRQ triggering, masking and unmasking
>>  - Some functionality has been removed from this series and posted separately:
>>    - VFIO_IOMMU_TYPE1 support for ARM SMMUs
>>    - IOMMU NOEXEC patches
>>    - driver_override functionality for AMBA devices
>>  - Several fixes
>> Changes since v6:
>>  - Integrated support for AMBA devices
>>  - Numerous cleanups and fixes
>> Changes since v5:
>>  - Full eventfd support for IRQ masking and unmasking.
>>  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags in VFIO.
>>  - Other fixes based on reviewer comments.
>> Changes since v4:
>>  - Use static offsets for each region in the VFIO device fd
>>  - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
>>    availability via IOMMU_CAP_DMA_EXEC
>>  - Rebased on VFIO multi domain support:
>>    - IOMMU_EXEC is now available if at least one IOMMU in the container
>>      supports it
>>    - Expose IOMMU_EXEC if available via the capability VFIO_IOMMU_PROT_EXEC
>>  - Some bug fixes
>> Changes since v3:
>>  - Use Kim Phillips' driver_probe_device()
>> Changes since v2:
>>  - Fixed Read/Write and MMAP on device regions
>>  - Removed dependency on Device Tree
>>  - Interrupts support
>>  - Interrupt masking/unmasking
>>  - Automask level sensitive interrupts
>>  - Introduced VFIO_DMA_MAP_FLAG_EXEC
>>  - Code clean ups
>>
>> Antonios Motakis (20):
>>   vfio/platform: initial skeleton of VFIO support for platform devices
>>   vfio: platform: probe to devices on the platform bus
>>   vfio: platform: add the VFIO PLATFORM module to Kconfig
>>   vfio: amba: VFIO support for AMBA devices
>>   vfio: amba: add the VFIO for AMBA devices module to Kconfig
>>   vfio/platform: return info for bound device
>>   vfio/platform: return info for device memory mapped IO regions
>>   vfio/platform: read and write support for the device fd
>>   vfio/platform: support MMAP of MMIO regions
>>   vfio/platform: return IRQ info
>>   vfio/platform: initial interrupts support code
>>   vfio/platform: trigger an interrupt via eventfd
>>   vfio/platform: support for level sensitive interrupts
>>   vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and
>>     export
>>   vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
>>   vfio: add local lock for virqfd instead of depending on VFIO PCI
>>   vfio: pass an opaque pointer on virqfd initialization
>>   vfio: move eventfd support code for VFIO_PCI to a separate file
>>   vfio: initialize the virqfd workqueue in VFIO generic code
>>   vfio/platform: implement IRQ masking/unmasking via an eventfd
>>
>>  drivers/vfio/Kconfig                          |   1 +
>>  drivers/vfio/Makefile                         |   5 +-
>>  drivers/vfio/pci/vfio_pci.c                   |   8 -
>>  drivers/vfio/pci/vfio_pci_intrs.c             | 238 +-----------
>>  drivers/vfio/pci/vfio_pci_private.h           |   3 -
>>  drivers/vfio/platform/Kconfig                 |  19 +
>>  drivers/vfio/platform/Makefile                |   8 +
>>  drivers/vfio/platform/vfio_amba.c             | 115 ++++++
>>  drivers/vfio/platform/vfio_platform.c         | 103 +++++
>>  drivers/vfio/platform/vfio_platform_common.c  | 520 ++++++++++++++++++++++++++
>>  drivers/vfio/platform/vfio_platform_irq.c     | 340 +++++++++++++++++
>>  drivers/vfio/platform/vfio_platform_private.h |  82 ++++
>>  drivers/vfio/vfio.c                           |   8 +
>>  drivers/vfio/virqfd.c                         | 213 +++++++++++
>>  include/linux/vfio.h                          |  27 ++
>>  include/uapi/linux/vfio.h                     |   2 +
>>  16 files changed, 1456 insertions(+), 236 deletions(-)
>>  create mode 100644 drivers/vfio/platform/Kconfig
>>  create mode 100644 drivers/vfio/platform/Makefile
>>  create mode 100644 drivers/vfio/platform/vfio_amba.c
>>  create mode 100644 drivers/vfio/platform/vfio_platform.c
>>  create mode 100644 drivers/vfio/platform/vfio_platform_common.c
>>  create mode 100644 drivers/vfio/platform/vfio_platform_irq.c
>>  create mode 100644 drivers/vfio/platform/vfio_platform_private.h
>>  create mode 100644 drivers/vfio/virqfd.c
>>
>

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

* Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices
       [not found]         ` <CAG8rG2yc1ityUwswPiTR_w5f3tSeX_KB2g06HcPCPARXPHGvfg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2015-01-16 13:25           ` Baptiste Reynal
       [not found]             ` <CAN9JPjERBVnGku8_BJuesMnzJyQYUgz6rJhL_VrCOgLVQuXyuw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 54+ messages in thread
From: Baptiste Reynal @ 2015-01-16 13:25 UTC (permalink / raw)
  To: Antonios Motakis
  Cc: Eric Auger, Marc Zyngier, Will Deacon, Linux IOMMU,
	VirtualOpenSystems Technical Team, kvm-arm, Christoffer Dall


[-- Attachment #1.1: Type: text/plain, Size: 7518 bytes --]

Hello Eric,

I'm not sure I understand the issue here. I tried to reproduce the bug by
triggering an interrupt without unmasking it, but the interrupt is unmasked
when the program access to the device (vfio_platform_open reinit IRQs).

May I have more details on the bug ?

Thanks

On Fri, Jan 9, 2015 at 12:33 PM, Antonios Motakis <
a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org> wrote:

> On Fri, Jan 9, 2015 at 9:39 AM, Eric Auger <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> > Hi Antonios,
> >
> > when moving to 3.19rc3 I observe a regression with my xgmac use case
> > (real-time change?).
> >
> > I guess what happens is when I kill a first qemu session, guest does not
> > have time to complete the virtual IRQ and the unmask is not performed by
> > the virqfd handler. When starting a new QEMU session, the irqfd
> > signalling is put in place again but since the masked field is set, the
> > IRQ is left unmasked (v11 modification in vfio_set_trigger).
> >
> > The problem is that we don't discriminate between user mask action and
> > automasked handler action. In case the user did not mask, I think we
> > should reset the masked field when doing the free_irq. What do you think?
>
> Hello Eric,
>
> I agree, we should reset the masked field for future users.
>
> Best regards
> Antonios
>
> >
> > Best Regards
> >
> > Eric
> >
> > On 01/06/2015 11:48 AM, Antonios Motakis wrote:
> >> This patch series aims to implement VFIO support for platform devices
> that
> >> reside behind an IOMMU. Examples of such devices are devices behind an
> ARM
> >> SMMU, or behind a Samsung Exynos System MMU.
> >>
> >> The API used is based on the existing VFIO API that is also used with
> PCI
> >> devices. Only devices that include a basic set of IRQs and memory
> regions are
> >> targeted; devices with complex relationships with other devices on a
> device
> >> tree are not taken into account at this stage.
> >>
> >> This patch series may be applied on the following series/patches:
> >>  - [PATCH] driver core: amba: add device binding path 'driver_override'
> >>  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with
> VFIO_IOMMU_TYPE1
> >>
> >> A copy can be cloned from the branch vfio-platform-v11 at:
> >> git-9UaJU3cA/F/QT0dZR+AlfA@public.gmane.org:virtualopensystems/linux-kvm-arm.git
> >>
> >> Changes since v10:
> >>  - Check if interrupt is already masked when setting a new trigger
> >>  - Fixed kasprintf with unchecked return value in VFIO AMBA driver
> >> Changes since v9:
> >>  - Reworked the splitting of the patches that decouple virqfd from PCI
> >>  - Some styling issues and typos
> >>  - Removed superfluous includes
> >>  - AMBA devices are now named vfio-amba- suffixed by the AMBA device id
> >>  - Several other cleanups and fixes
> >> Changes since v8:
> >>  - Separate irq handler for edge and level triggered interrupts
> >>  - Mutex based lock for VFIO fd open/release
> >>  - Fixed bug where the first region of a platform device wasn't exposed
> >>  - Read only regions can be MMAPed only read only
> >>  - Code cleanups
> >> Changes since v7:
> >>  - Some initial placeholder functionality for PIO resources
> >>  - Cleaned up code for IRQ triggering, masking and unmasking
> >>  - Some functionality has been removed from this series and posted
> separately:
> >>    - VFIO_IOMMU_TYPE1 support for ARM SMMUs
> >>    - IOMMU NOEXEC patches
> >>    - driver_override functionality for AMBA devices
> >>  - Several fixes
> >> Changes since v6:
> >>  - Integrated support for AMBA devices
> >>  - Numerous cleanups and fixes
> >> Changes since v5:
> >>  - Full eventfd support for IRQ masking and unmasking.
> >>  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags in VFIO.
> >>  - Other fixes based on reviewer comments.
> >> Changes since v4:
> >>  - Use static offsets for each region in the VFIO device fd
> >>  - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
> >>    availability via IOMMU_CAP_DMA_EXEC
> >>  - Rebased on VFIO multi domain support:
> >>    - IOMMU_EXEC is now available if at least one IOMMU in the container
> >>      supports it
> >>    - Expose IOMMU_EXEC if available via the capability
> VFIO_IOMMU_PROT_EXEC
> >>  - Some bug fixes
> >> Changes since v3:
> >>  - Use Kim Phillips' driver_probe_device()
> >> Changes since v2:
> >>  - Fixed Read/Write and MMAP on device regions
> >>  - Removed dependency on Device Tree
> >>  - Interrupts support
> >>  - Interrupt masking/unmasking
> >>  - Automask level sensitive interrupts
> >>  - Introduced VFIO_DMA_MAP_FLAG_EXEC
> >>  - Code clean ups
> >>
> >> Antonios Motakis (20):
> >>   vfio/platform: initial skeleton of VFIO support for platform devices
> >>   vfio: platform: probe to devices on the platform bus
> >>   vfio: platform: add the VFIO PLATFORM module to Kconfig
> >>   vfio: amba: VFIO support for AMBA devices
> >>   vfio: amba: add the VFIO for AMBA devices module to Kconfig
> >>   vfio/platform: return info for bound device
> >>   vfio/platform: return info for device memory mapped IO regions
> >>   vfio/platform: read and write support for the device fd
> >>   vfio/platform: support MMAP of MMIO regions
> >>   vfio/platform: return IRQ info
> >>   vfio/platform: initial interrupts support code
> >>   vfio/platform: trigger an interrupt via eventfd
> >>   vfio/platform: support for level sensitive interrupts
> >>   vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and
> >>     export
> >>   vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
> >>   vfio: add local lock for virqfd instead of depending on VFIO PCI
> >>   vfio: pass an opaque pointer on virqfd initialization
> >>   vfio: move eventfd support code for VFIO_PCI to a separate file
> >>   vfio: initialize the virqfd workqueue in VFIO generic code
> >>   vfio/platform: implement IRQ masking/unmasking via an eventfd
> >>
> >>  drivers/vfio/Kconfig                          |   1 +
> >>  drivers/vfio/Makefile                         |   5 +-
> >>  drivers/vfio/pci/vfio_pci.c                   |   8 -
> >>  drivers/vfio/pci/vfio_pci_intrs.c             | 238 +-----------
> >>  drivers/vfio/pci/vfio_pci_private.h           |   3 -
> >>  drivers/vfio/platform/Kconfig                 |  19 +
> >>  drivers/vfio/platform/Makefile                |   8 +
> >>  drivers/vfio/platform/vfio_amba.c             | 115 ++++++
> >>  drivers/vfio/platform/vfio_platform.c         | 103 +++++
> >>  drivers/vfio/platform/vfio_platform_common.c  | 520
> ++++++++++++++++++++++++++
> >>  drivers/vfio/platform/vfio_platform_irq.c     | 340 +++++++++++++++++
> >>  drivers/vfio/platform/vfio_platform_private.h |  82 ++++
> >>  drivers/vfio/vfio.c                           |   8 +
> >>  drivers/vfio/virqfd.c                         | 213 +++++++++++
> >>  include/linux/vfio.h                          |  27 ++
> >>  include/uapi/linux/vfio.h                     |   2 +
> >>  16 files changed, 1456 insertions(+), 236 deletions(-)
> >>  create mode 100644 drivers/vfio/platform/Kconfig
> >>  create mode 100644 drivers/vfio/platform/Makefile
> >>  create mode 100644 drivers/vfio/platform/vfio_amba.c
> >>  create mode 100644 drivers/vfio/platform/vfio_platform.c
> >>  create mode 100644 drivers/vfio/platform/vfio_platform_common.c
> >>  create mode 100644 drivers/vfio/platform/vfio_platform_irq.c
> >>  create mode 100644 drivers/vfio/platform/vfio_platform_private.h
> >>  create mode 100644 drivers/vfio/virqfd.c
> >>
> >
>

[-- Attachment #1.2: Type: text/html, Size: 9546 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices
       [not found]             ` <CAN9JPjERBVnGku8_BJuesMnzJyQYUgz6rJhL_VrCOgLVQuXyuw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2015-01-19 10:17               ` Eric Auger
       [not found]                 ` <54BCD9A6.4050501-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 54+ messages in thread
From: Eric Auger @ 2015-01-19 10:17 UTC (permalink / raw)
  To: Baptiste Reynal, Antonios Motakis
  Cc: Marc Zyngier, Will Deacon, Linux IOMMU,
	VirtualOpenSystems Technical Team, kvm-arm, Christoffer Dall

Hi Baptiste,

sorry I was off on Friday. you're right I missed the masked field was
reset on init. Nethertheless with current QEMU VFIO code, IRQ runs on
the first run and not on the second one. I investigate on my side ...

Best Regards

Eric




On 01/16/2015 02:25 PM, Baptiste Reynal wrote:
> Hello Eric,
> 
> I'm not sure I understand the issue here. I tried to reproduce the bug
> by triggering an interrupt without unmasking it, but the interrupt is
> unmasked when the program access to the device (vfio_platform_open
> reinit IRQs).
> 
> May I have more details on the bug ?
> 
> Thanks
> 
> On Fri, Jan 9, 2015 at 12:33 PM, Antonios Motakis
> <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org
> <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>> wrote:
> 
>     On Fri, Jan 9, 2015 at 9:39 AM, Eric Auger <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org
>     <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>> wrote:
>     > Hi Antonios,
>     >
>     > when moving to 3.19rc3 I observe a regression with my xgmac use case
>     > (real-time change?).
>     >
>     > I guess what happens is when I kill a first qemu session, guest does not
>     > have time to complete the virtual IRQ and the unmask is not performed by
>     > the virqfd handler. When starting a new QEMU session, the irqfd
>     > signalling is put in place again but since the masked field is set, the
>     > IRQ is left unmasked (v11 modification in vfio_set_trigger).
>     >
>     > The problem is that we don't discriminate between user mask action and
>     > automasked handler action. In case the user did not mask, I think we
>     > should reset the masked field when doing the free_irq. What do you think?
> 
>     Hello Eric,
> 
>     I agree, we should reset the masked field for future users.
> 
>     Best regards
>     Antonios
> 
>     >
>     > Best Regards
>     >
>     > Eric
>     >
>     > On 01/06/2015 11:48 AM, Antonios Motakis wrote:
>     >> This patch series aims to implement VFIO support for platform
>     devices that
>     >> reside behind an IOMMU. Examples of such devices are devices
>     behind an ARM
>     >> SMMU, or behind a Samsung Exynos System MMU.
>     >>
>     >> The API used is based on the existing VFIO API that is also used
>     with PCI
>     >> devices. Only devices that include a basic set of IRQs and memory
>     regions are
>     >> targeted; devices with complex relationships with other devices
>     on a device
>     >> tree are not taken into account at this stage.
>     >>
>     >> This patch series may be applied on the following series/patches:
>     >>  - [PATCH] driver core: amba: add device binding path
>     'driver_override'
>     >>  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with
>     VFIO_IOMMU_TYPE1
>     >>
>     >> A copy can be cloned from the branch vfio-platform-v11 at:
>     >> git-9UaJU3cA/F/QT0dZR+AlfA@public.gmane.org:virtualopensystems/linux-kvm-arm.git
>     >>
>     >> Changes since v10:
>     >>  - Check if interrupt is already masked when setting a new trigger
>     >>  - Fixed kasprintf with unchecked return value in VFIO AMBA driver
>     >> Changes since v9:
>     >>  - Reworked the splitting of the patches that decouple virqfd
>     from PCI
>     >>  - Some styling issues and typos
>     >>  - Removed superfluous includes
>     >>  - AMBA devices are now named vfio-amba- suffixed by the AMBA
>     device id
>     >>  - Several other cleanups and fixes
>     >> Changes since v8:
>     >>  - Separate irq handler for edge and level triggered interrupts
>     >>  - Mutex based lock for VFIO fd open/release
>     >>  - Fixed bug where the first region of a platform device wasn't
>     exposed
>     >>  - Read only regions can be MMAPed only read only
>     >>  - Code cleanups
>     >> Changes since v7:
>     >>  - Some initial placeholder functionality for PIO resources
>     >>  - Cleaned up code for IRQ triggering, masking and unmasking
>     >>  - Some functionality has been removed from this series and
>     posted separately:
>     >>    - VFIO_IOMMU_TYPE1 support for ARM SMMUs
>     >>    - IOMMU NOEXEC patches
>     >>    - driver_override functionality for AMBA devices
>     >>  - Several fixes
>     >> Changes since v6:
>     >>  - Integrated support for AMBA devices
>     >>  - Numerous cleanups and fixes
>     >> Changes since v5:
>     >>  - Full eventfd support for IRQ masking and unmasking.
>     >>  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags
>     in VFIO.
>     >>  - Other fixes based on reviewer comments.
>     >> Changes since v4:
>     >>  - Use static offsets for each region in the VFIO device fd
>     >>  - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
>     >>    availability via IOMMU_CAP_DMA_EXEC
>     >>  - Rebased on VFIO multi domain support:
>     >>    - IOMMU_EXEC is now available if at least one IOMMU in the
>     container
>     >>      supports it
>     >>    - Expose IOMMU_EXEC if available via the capability
>     VFIO_IOMMU_PROT_EXEC
>     >>  - Some bug fixes
>     >> Changes since v3:
>     >>  - Use Kim Phillips' driver_probe_device()
>     >> Changes since v2:
>     >>  - Fixed Read/Write and MMAP on device regions
>     >>  - Removed dependency on Device Tree
>     >>  - Interrupts support
>     >>  - Interrupt masking/unmasking
>     >>  - Automask level sensitive interrupts
>     >>  - Introduced VFIO_DMA_MAP_FLAG_EXEC
>     >>  - Code clean ups
>     >>
>     >> Antonios Motakis (20):
>     >>   vfio/platform: initial skeleton of VFIO support for platform
>     devices
>     >>   vfio: platform: probe to devices on the platform bus
>     >>   vfio: platform: add the VFIO PLATFORM module to Kconfig
>     >>   vfio: amba: VFIO support for AMBA devices
>     >>   vfio: amba: add the VFIO for AMBA devices module to Kconfig
>     >>   vfio/platform: return info for bound device
>     >>   vfio/platform: return info for device memory mapped IO regions
>     >>   vfio/platform: read and write support for the device fd
>     >>   vfio/platform: support MMAP of MMIO regions
>     >>   vfio/platform: return IRQ info
>     >>   vfio/platform: initial interrupts support code
>     >>   vfio/platform: trigger an interrupt via eventfd
>     >>   vfio/platform: support for level sensitive interrupts
>     >>   vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and
>     >>     export
>     >>   vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
>     >>   vfio: add local lock for virqfd instead of depending on VFIO PCI
>     >>   vfio: pass an opaque pointer on virqfd initialization
>     >>   vfio: move eventfd support code for VFIO_PCI to a separate file
>     >>   vfio: initialize the virqfd workqueue in VFIO generic code
>     >>   vfio/platform: implement IRQ masking/unmasking via an eventfd
>     >>
>     >>  drivers/vfio/Kconfig                          |   1 +
>     >>  drivers/vfio/Makefile                         |   5 +-
>     >>  drivers/vfio/pci/vfio_pci.c                   |   8 -
>     >>  drivers/vfio/pci/vfio_pci_intrs.c             | 238 +-----------
>     >>  drivers/vfio/pci/vfio_pci_private.h           |   3 -
>     >>  drivers/vfio/platform/Kconfig                 |  19 +
>     >>  drivers/vfio/platform/Makefile                |   8 +
>     >>  drivers/vfio/platform/vfio_amba.c             | 115 ++++++
>     >>  drivers/vfio/platform/vfio_platform.c         | 103 +++++
>     >>  drivers/vfio/platform/vfio_platform_common.c  | 520
>     ++++++++++++++++++++++++++
>     >>  drivers/vfio/platform/vfio_platform_irq.c     | 340
>     +++++++++++++++++
>     >>  drivers/vfio/platform/vfio_platform_private.h |  82 ++++
>     >>  drivers/vfio/vfio.c                           |   8 +
>     >>  drivers/vfio/virqfd.c                         | 213 +++++++++++
>     >>  include/linux/vfio.h                          |  27 ++
>     >>  include/uapi/linux/vfio.h                     |   2 +
>     >>  16 files changed, 1456 insertions(+), 236 deletions(-)
>     >>  create mode 100644 drivers/vfio/platform/Kconfig
>     >>  create mode 100644 drivers/vfio/platform/Makefile
>     >>  create mode 100644 drivers/vfio/platform/vfio_amba.c
>     >>  create mode 100644 drivers/vfio/platform/vfio_platform.c
>     >>  create mode 100644 drivers/vfio/platform/vfio_platform_common.c
>     >>  create mode 100644 drivers/vfio/platform/vfio_platform_irq.c
>     >>  create mode 100644 drivers/vfio/platform/vfio_platform_private.h
>     >>  create mode 100644 drivers/vfio/virqfd.c
>     >>
>     >
> 
> 

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

* Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices
       [not found]                 ` <54BCD9A6.4050501-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2015-01-19 12:27                   ` Eric Auger
       [not found]                     ` <54BCF846.1070906-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 54+ messages in thread
From: Eric Auger @ 2015-01-19 12:27 UTC (permalink / raw)
  To: Baptiste Reynal, Antonios Motakis
  Cc: Marc Zyngier, Will Deacon, Linux IOMMU,
	VirtualOpenSystems Technical Team, kvm-arm, Christoffer Dall

Hi Baptiste,

I think what happens on the second qemu run is:

an IRQ hits immediatly after request_irq
automasked handler sets masked = true
in vfio_set_trigger following condition becomes true
        if (irq->masked)
                disable_irq_nosync(irq->hwirq);
IRQ is disabled twice, in handler and in vfio_set_trigger while there is
a single enable in resamplefd handler.
To me you should prevent from entering ISR between request_irq and
disable_irq.

It does not happen on the first run because no IRQ hit.

Please let me know if you share this understanding.

Best Regards

Eric

On 01/19/2015 11:17 AM, Eric Auger wrote:
> Hi Baptiste,
> 
> sorry I was off on Friday. you're right I missed the masked field was
> reset on init. Nethertheless with current QEMU VFIO code, IRQ runs on
> the first run and not on the second one. I investigate on my side ...
> 
> Best Regards
> 
> Eric
> 
> 
> 
> 
> On 01/16/2015 02:25 PM, Baptiste Reynal wrote:
>> Hello Eric,
>>
>> I'm not sure I understand the issue here. I tried to reproduce the bug
>> by triggering an interrupt without unmasking it, but the interrupt is
>> unmasked when the program access to the device (vfio_platform_open
>> reinit IRQs).
>>
>> May I have more details on the bug ?
>>
>> Thanks
>>
>> On Fri, Jan 9, 2015 at 12:33 PM, Antonios Motakis
>> <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org
>> <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>> wrote:
>>
>>     On Fri, Jan 9, 2015 at 9:39 AM, Eric Auger <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org
>>     <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>> wrote:
>>     > Hi Antonios,
>>     >
>>     > when moving to 3.19rc3 I observe a regression with my xgmac use case
>>     > (real-time change?).
>>     >
>>     > I guess what happens is when I kill a first qemu session, guest does not
>>     > have time to complete the virtual IRQ and the unmask is not performed by
>>     > the virqfd handler. When starting a new QEMU session, the irqfd
>>     > signalling is put in place again but since the masked field is set, the
>>     > IRQ is left unmasked (v11 modification in vfio_set_trigger).
>>     >
>>     > The problem is that we don't discriminate between user mask action and
>>     > automasked handler action. In case the user did not mask, I think we
>>     > should reset the masked field when doing the free_irq. What do you think?
>>
>>     Hello Eric,
>>
>>     I agree, we should reset the masked field for future users.
>>
>>     Best regards
>>     Antonios
>>
>>     >
>>     > Best Regards
>>     >
>>     > Eric
>>     >
>>     > On 01/06/2015 11:48 AM, Antonios Motakis wrote:
>>     >> This patch series aims to implement VFIO support for platform
>>     devices that
>>     >> reside behind an IOMMU. Examples of such devices are devices
>>     behind an ARM
>>     >> SMMU, or behind a Samsung Exynos System MMU.
>>     >>
>>     >> The API used is based on the existing VFIO API that is also used
>>     with PCI
>>     >> devices. Only devices that include a basic set of IRQs and memory
>>     regions are
>>     >> targeted; devices with complex relationships with other devices
>>     on a device
>>     >> tree are not taken into account at this stage.
>>     >>
>>     >> This patch series may be applied on the following series/patches:
>>     >>  - [PATCH] driver core: amba: add device binding path
>>     'driver_override'
>>     >>  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with
>>     VFIO_IOMMU_TYPE1
>>     >>
>>     >> A copy can be cloned from the branch vfio-platform-v11 at:
>>     >> git-9UaJU3cA/F/QT0dZR+AlfA@public.gmane.org:virtualopensystems/linux-kvm-arm.git
>>     >>
>>     >> Changes since v10:
>>     >>  - Check if interrupt is already masked when setting a new trigger
>>     >>  - Fixed kasprintf with unchecked return value in VFIO AMBA driver
>>     >> Changes since v9:
>>     >>  - Reworked the splitting of the patches that decouple virqfd
>>     from PCI
>>     >>  - Some styling issues and typos
>>     >>  - Removed superfluous includes
>>     >>  - AMBA devices are now named vfio-amba- suffixed by the AMBA
>>     device id
>>     >>  - Several other cleanups and fixes
>>     >> Changes since v8:
>>     >>  - Separate irq handler for edge and level triggered interrupts
>>     >>  - Mutex based lock for VFIO fd open/release
>>     >>  - Fixed bug where the first region of a platform device wasn't
>>     exposed
>>     >>  - Read only regions can be MMAPed only read only
>>     >>  - Code cleanups
>>     >> Changes since v7:
>>     >>  - Some initial placeholder functionality for PIO resources
>>     >>  - Cleaned up code for IRQ triggering, masking and unmasking
>>     >>  - Some functionality has been removed from this series and
>>     posted separately:
>>     >>    - VFIO_IOMMU_TYPE1 support for ARM SMMUs
>>     >>    - IOMMU NOEXEC patches
>>     >>    - driver_override functionality for AMBA devices
>>     >>  - Several fixes
>>     >> Changes since v6:
>>     >>  - Integrated support for AMBA devices
>>     >>  - Numerous cleanups and fixes
>>     >> Changes since v5:
>>     >>  - Full eventfd support for IRQ masking and unmasking.
>>     >>  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags
>>     in VFIO.
>>     >>  - Other fixes based on reviewer comments.
>>     >> Changes since v4:
>>     >>  - Use static offsets for each region in the VFIO device fd
>>     >>  - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
>>     >>    availability via IOMMU_CAP_DMA_EXEC
>>     >>  - Rebased on VFIO multi domain support:
>>     >>    - IOMMU_EXEC is now available if at least one IOMMU in the
>>     container
>>     >>      supports it
>>     >>    - Expose IOMMU_EXEC if available via the capability
>>     VFIO_IOMMU_PROT_EXEC
>>     >>  - Some bug fixes
>>     >> Changes since v3:
>>     >>  - Use Kim Phillips' driver_probe_device()
>>     >> Changes since v2:
>>     >>  - Fixed Read/Write and MMAP on device regions
>>     >>  - Removed dependency on Device Tree
>>     >>  - Interrupts support
>>     >>  - Interrupt masking/unmasking
>>     >>  - Automask level sensitive interrupts
>>     >>  - Introduced VFIO_DMA_MAP_FLAG_EXEC
>>     >>  - Code clean ups
>>     >>
>>     >> Antonios Motakis (20):
>>     >>   vfio/platform: initial skeleton of VFIO support for platform
>>     devices
>>     >>   vfio: platform: probe to devices on the platform bus
>>     >>   vfio: platform: add the VFIO PLATFORM module to Kconfig
>>     >>   vfio: amba: VFIO support for AMBA devices
>>     >>   vfio: amba: add the VFIO for AMBA devices module to Kconfig
>>     >>   vfio/platform: return info for bound device
>>     >>   vfio/platform: return info for device memory mapped IO regions
>>     >>   vfio/platform: read and write support for the device fd
>>     >>   vfio/platform: support MMAP of MMIO regions
>>     >>   vfio/platform: return IRQ info
>>     >>   vfio/platform: initial interrupts support code
>>     >>   vfio/platform: trigger an interrupt via eventfd
>>     >>   vfio/platform: support for level sensitive interrupts
>>     >>   vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and
>>     >>     export
>>     >>   vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
>>     >>   vfio: add local lock for virqfd instead of depending on VFIO PCI
>>     >>   vfio: pass an opaque pointer on virqfd initialization
>>     >>   vfio: move eventfd support code for VFIO_PCI to a separate file
>>     >>   vfio: initialize the virqfd workqueue in VFIO generic code
>>     >>   vfio/platform: implement IRQ masking/unmasking via an eventfd
>>     >>
>>     >>  drivers/vfio/Kconfig                          |   1 +
>>     >>  drivers/vfio/Makefile                         |   5 +-
>>     >>  drivers/vfio/pci/vfio_pci.c                   |   8 -
>>     >>  drivers/vfio/pci/vfio_pci_intrs.c             | 238 +-----------
>>     >>  drivers/vfio/pci/vfio_pci_private.h           |   3 -
>>     >>  drivers/vfio/platform/Kconfig                 |  19 +
>>     >>  drivers/vfio/platform/Makefile                |   8 +
>>     >>  drivers/vfio/platform/vfio_amba.c             | 115 ++++++
>>     >>  drivers/vfio/platform/vfio_platform.c         | 103 +++++
>>     >>  drivers/vfio/platform/vfio_platform_common.c  | 520
>>     ++++++++++++++++++++++++++
>>     >>  drivers/vfio/platform/vfio_platform_irq.c     | 340
>>     +++++++++++++++++
>>     >>  drivers/vfio/platform/vfio_platform_private.h |  82 ++++
>>     >>  drivers/vfio/vfio.c                           |   8 +
>>     >>  drivers/vfio/virqfd.c                         | 213 +++++++++++
>>     >>  include/linux/vfio.h                          |  27 ++
>>     >>  include/uapi/linux/vfio.h                     |   2 +
>>     >>  16 files changed, 1456 insertions(+), 236 deletions(-)
>>     >>  create mode 100644 drivers/vfio/platform/Kconfig
>>     >>  create mode 100644 drivers/vfio/platform/Makefile
>>     >>  create mode 100644 drivers/vfio/platform/vfio_amba.c
>>     >>  create mode 100644 drivers/vfio/platform/vfio_platform.c
>>     >>  create mode 100644 drivers/vfio/platform/vfio_platform_common.c
>>     >>  create mode 100644 drivers/vfio/platform/vfio_platform_irq.c
>>     >>  create mode 100644 drivers/vfio/platform/vfio_platform_private.h
>>     >>  create mode 100644 drivers/vfio/virqfd.c
>>     >>
>>     >
>>
>>
> 

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

* Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices
       [not found]                     ` <54BCF846.1070906-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2015-01-19 17:00                       ` Baptiste Reynal
       [not found]                         ` <CAN9JPjF5sAH-UNKtBhfiHK7cQJBwNwg2UEcrj8sv9Em6MnBVxg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 54+ messages in thread
From: Baptiste Reynal @ 2015-01-19 17:00 UTC (permalink / raw)
  To: Eric Auger
  Cc: Marc Zyngier, Will Deacon, Linux IOMMU, Antonios Motakis,
	VirtualOpenSystems Technical Team, kvm-arm, Christoffer Dall


[-- Attachment #1.1: Type: text/plain, Size: 11591 bytes --]

Hi Eric,

Thanks for taking time about this issue. I agree with you, there is a
problem here. While I think on a better fix and to be sure the problem is
here, may you try this patch and tell me if the problem is solved ? (This
should work as the automasked_irq_handler doesn't do anything if the IRQ is
masked).

If you have a suggestion on a fix, you're welcome :)

diff --git a/drivers/vfio/platform/vfio_platform_irq.c
b/drivers/vfio/platform/vfio_platform_irq.c
index 6ade36b..c9bac80 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -184,6 +184,7 @@ static int vfio_set_trigger(struct vfio_platform_device
*vdev, int index,
        struct eventfd_ctx *trigger;
        unsigned long flags;
        int ret;
+       bool masked;

        if (irq->trigger) {
                free_irq(irq->hwirq, irq);
@@ -208,6 +209,8 @@ static int vfio_set_trigger(struct vfio_platform_device
*vdev, int index,

        irq->trigger = trigger;

+       masked = irq->masked;
+
        ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
        if (ret) {
                kfree(irq->name);
@@ -219,7 +222,7 @@ static int vfio_set_trigger(struct vfio_platform_device
*vdev, int index,
        /* if the IRQ has been masked by the user before setting an eventfd,
         * then we need to make sure it is properly disabled */
        spin_lock_irqsave(&irq->lock, flags);
-       if (irq->masked)
+       if (masked)
                disable_irq_nosync(irq->hwirq);
        spin_unlock_irqrestore(&irq->lock, flags);

On Mon, Jan 19, 2015 at 1:27 PM, Eric Auger <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:

> Hi Baptiste,
>
> I think what happens on the second qemu run is:
>
> an IRQ hits immediatly after request_irq
> automasked handler sets masked = true
> in vfio_set_trigger following condition becomes true
>         if (irq->masked)
>                 disable_irq_nosync(irq->hwirq);
> IRQ is disabled twice, in handler and in vfio_set_trigger while there is
> a single enable in resamplefd handler.
> To me you should prevent from entering ISR between request_irq and
> disable_irq.
>
> It does not happen on the first run because no IRQ hit.
>
> Please let me know if you share this understanding.
>
> Best Regards
>
> Eric
>
> On 01/19/2015 11:17 AM, Eric Auger wrote:
> > Hi Baptiste,
> >
> > sorry I was off on Friday. you're right I missed the masked field was
> > reset on init. Nethertheless with current QEMU VFIO code, IRQ runs on
> > the first run and not on the second one. I investigate on my side ...
> >
> > Best Regards
> >
> > Eric
> >
> >
> >
> >
> > On 01/16/2015 02:25 PM, Baptiste Reynal wrote:
> >> Hello Eric,
> >>
> >> I'm not sure I understand the issue here. I tried to reproduce the bug
> >> by triggering an interrupt without unmasking it, but the interrupt is
> >> unmasked when the program access to the device (vfio_platform_open
> >> reinit IRQs).
> >>
> >> May I have more details on the bug ?
> >>
> >> Thanks
> >>
> >> On Fri, Jan 9, 2015 at 12:33 PM, Antonios Motakis
> >> <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org
> >> <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>> wrote:
> >>
> >>     On Fri, Jan 9, 2015 at 9:39 AM, Eric Auger <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org
> >>     <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>> wrote:
> >>     > Hi Antonios,
> >>     >
> >>     > when moving to 3.19rc3 I observe a regression with my xgmac use
> case
> >>     > (real-time change?).
> >>     >
> >>     > I guess what happens is when I kill a first qemu session, guest
> does not
> >>     > have time to complete the virtual IRQ and the unmask is not
> performed by
> >>     > the virqfd handler. When starting a new QEMU session, the irqfd
> >>     > signalling is put in place again but since the masked field is
> set, the
> >>     > IRQ is left unmasked (v11 modification in vfio_set_trigger).
> >>     >
> >>     > The problem is that we don't discriminate between user mask
> action and
> >>     > automasked handler action. In case the user did not mask, I think
> we
> >>     > should reset the masked field when doing the free_irq. What do
> you think?
> >>
> >>     Hello Eric,
> >>
> >>     I agree, we should reset the masked field for future users.
> >>
> >>     Best regards
> >>     Antonios
> >>
> >>     >
> >>     > Best Regards
> >>     >
> >>     > Eric
> >>     >
> >>     > On 01/06/2015 11:48 AM, Antonios Motakis wrote:
> >>     >> This patch series aims to implement VFIO support for platform
> >>     devices that
> >>     >> reside behind an IOMMU. Examples of such devices are devices
> >>     behind an ARM
> >>     >> SMMU, or behind a Samsung Exynos System MMU.
> >>     >>
> >>     >> The API used is based on the existing VFIO API that is also used
> >>     with PCI
> >>     >> devices. Only devices that include a basic set of IRQs and memory
> >>     regions are
> >>     >> targeted; devices with complex relationships with other devices
> >>     on a device
> >>     >> tree are not taken into account at this stage.
> >>     >>
> >>     >> This patch series may be applied on the following series/patches:
> >>     >>  - [PATCH] driver core: amba: add device binding path
> >>     'driver_override'
> >>     >>  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with
> >>     VFIO_IOMMU_TYPE1
> >>     >>
> >>     >> A copy can be cloned from the branch vfio-platform-v11 at:
> >>     >> git-9UaJU3cA/F/QT0dZR+AlfA@public.gmane.org:virtualopensystems/linux-kvm-arm.git
> >>     >>
> >>     >> Changes since v10:
> >>     >>  - Check if interrupt is already masked when setting a new
> trigger
> >>     >>  - Fixed kasprintf with unchecked return value in VFIO AMBA
> driver
> >>     >> Changes since v9:
> >>     >>  - Reworked the splitting of the patches that decouple virqfd
> >>     from PCI
> >>     >>  - Some styling issues and typos
> >>     >>  - Removed superfluous includes
> >>     >>  - AMBA devices are now named vfio-amba- suffixed by the AMBA
> >>     device id
> >>     >>  - Several other cleanups and fixes
> >>     >> Changes since v8:
> >>     >>  - Separate irq handler for edge and level triggered interrupts
> >>     >>  - Mutex based lock for VFIO fd open/release
> >>     >>  - Fixed bug where the first region of a platform device wasn't
> >>     exposed
> >>     >>  - Read only regions can be MMAPed only read only
> >>     >>  - Code cleanups
> >>     >> Changes since v7:
> >>     >>  - Some initial placeholder functionality for PIO resources
> >>     >>  - Cleaned up code for IRQ triggering, masking and unmasking
> >>     >>  - Some functionality has been removed from this series and
> >>     posted separately:
> >>     >>    - VFIO_IOMMU_TYPE1 support for ARM SMMUs
> >>     >>    - IOMMU NOEXEC patches
> >>     >>    - driver_override functionality for AMBA devices
> >>     >>  - Several fixes
> >>     >> Changes since v6:
> >>     >>  - Integrated support for AMBA devices
> >>     >>  - Numerous cleanups and fixes
> >>     >> Changes since v5:
> >>     >>  - Full eventfd support for IRQ masking and unmasking.
> >>     >>  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags
> >>     in VFIO.
> >>     >>  - Other fixes based on reviewer comments.
> >>     >> Changes since v4:
> >>     >>  - Use static offsets for each region in the VFIO device fd
> >>     >>  - Include patch in the series for the ARM SMMU to expose
> IOMMU_EXEC
> >>     >>    availability via IOMMU_CAP_DMA_EXEC
> >>     >>  - Rebased on VFIO multi domain support:
> >>     >>    - IOMMU_EXEC is now available if at least one IOMMU in the
> >>     container
> >>     >>      supports it
> >>     >>    - Expose IOMMU_EXEC if available via the capability
> >>     VFIO_IOMMU_PROT_EXEC
> >>     >>  - Some bug fixes
> >>     >> Changes since v3:
> >>     >>  - Use Kim Phillips' driver_probe_device()
> >>     >> Changes since v2:
> >>     >>  - Fixed Read/Write and MMAP on device regions
> >>     >>  - Removed dependency on Device Tree
> >>     >>  - Interrupts support
> >>     >>  - Interrupt masking/unmasking
> >>     >>  - Automask level sensitive interrupts
> >>     >>  - Introduced VFIO_DMA_MAP_FLAG_EXEC
> >>     >>  - Code clean ups
> >>     >>
> >>     >> Antonios Motakis (20):
> >>     >>   vfio/platform: initial skeleton of VFIO support for platform
> >>     devices
> >>     >>   vfio: platform: probe to devices on the platform bus
> >>     >>   vfio: platform: add the VFIO PLATFORM module to Kconfig
> >>     >>   vfio: amba: VFIO support for AMBA devices
> >>     >>   vfio: amba: add the VFIO for AMBA devices module to Kconfig
> >>     >>   vfio/platform: return info for bound device
> >>     >>   vfio/platform: return info for device memory mapped IO regions
> >>     >>   vfio/platform: read and write support for the device fd
> >>     >>   vfio/platform: support MMAP of MMIO regions
> >>     >>   vfio/platform: return IRQ info
> >>     >>   vfio/platform: initial interrupts support code
> >>     >>   vfio/platform: trigger an interrupt via eventfd
> >>     >>   vfio/platform: support for level sensitive interrupts
> >>     >>   vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable
> and
> >>     >>     export
> >>     >>   vfio: virqfd: rename vfio_pci_virqfd_init and
> vfio_pci_virqfd_exit
> >>     >>   vfio: add local lock for virqfd instead of depending on VFIO
> PCI
> >>     >>   vfio: pass an opaque pointer on virqfd initialization
> >>     >>   vfio: move eventfd support code for VFIO_PCI to a separate file
> >>     >>   vfio: initialize the virqfd workqueue in VFIO generic code
> >>     >>   vfio/platform: implement IRQ masking/unmasking via an eventfd
> >>     >>
> >>     >>  drivers/vfio/Kconfig                          |   1 +
> >>     >>  drivers/vfio/Makefile                         |   5 +-
> >>     >>  drivers/vfio/pci/vfio_pci.c                   |   8 -
> >>     >>  drivers/vfio/pci/vfio_pci_intrs.c             | 238 +-----------
> >>     >>  drivers/vfio/pci/vfio_pci_private.h           |   3 -
> >>     >>  drivers/vfio/platform/Kconfig                 |  19 +
> >>     >>  drivers/vfio/platform/Makefile                |   8 +
> >>     >>  drivers/vfio/platform/vfio_amba.c             | 115 ++++++
> >>     >>  drivers/vfio/platform/vfio_platform.c         | 103 +++++
> >>     >>  drivers/vfio/platform/vfio_platform_common.c  | 520
> >>     ++++++++++++++++++++++++++
> >>     >>  drivers/vfio/platform/vfio_platform_irq.c     | 340
> >>     +++++++++++++++++
> >>     >>  drivers/vfio/platform/vfio_platform_private.h |  82 ++++
> >>     >>  drivers/vfio/vfio.c                           |   8 +
> >>     >>  drivers/vfio/virqfd.c                         | 213 +++++++++++
> >>     >>  include/linux/vfio.h                          |  27 ++
> >>     >>  include/uapi/linux/vfio.h                     |   2 +
> >>     >>  16 files changed, 1456 insertions(+), 236 deletions(-)
> >>     >>  create mode 100644 drivers/vfio/platform/Kconfig
> >>     >>  create mode 100644 drivers/vfio/platform/Makefile
> >>     >>  create mode 100644 drivers/vfio/platform/vfio_amba.c
> >>     >>  create mode 100644 drivers/vfio/platform/vfio_platform.c
> >>     >>  create mode 100644 drivers/vfio/platform/vfio_platform_common.c
> >>     >>  create mode 100644 drivers/vfio/platform/vfio_platform_irq.c
> >>     >>  create mode 100644 drivers/vfio/platform/vfio_platform_private.h
> >>     >>  create mode 100644 drivers/vfio/virqfd.c
> >>     >>
> >>     >
> >>
> >>
> >
>
>

[-- Attachment #1.2: Type: text/html, Size: 15964 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices
       [not found]                         ` <CAN9JPjF5sAH-UNKtBhfiHK7cQJBwNwg2UEcrj8sv9Em6MnBVxg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2015-01-19 18:09                           ` Eric Auger
       [not found]                             ` <54BD4857.3070707-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 54+ messages in thread
From: Eric Auger @ 2015-01-19 18:09 UTC (permalink / raw)
  To: Baptiste Reynal
  Cc: Marc Zyngier, Will Deacon, Linux IOMMU, Antonios Motakis,
	VirtualOpenSystems Technical Team, kvm-arm, Christoffer Dall

Hi Baptiste,

yes it fixes the issue in my use case.

Best Regards

Eric

On 01/19/2015 06:00 PM, Baptiste Reynal wrote:
> Hi Eric,
> 
> Thanks for taking time about this issue. I agree with you, there is a
> problem here. While I think on a better fix and to be sure the problem
> is here, may you try this patch and tell me if the problem is solved ?
> (This should work as the automasked_irq_handler doesn't do anything if
> the IRQ is masked).
> 
> If you have a suggestion on a fix, you're welcome :)
> 
> diff --git a/drivers/vfio/platform/vfio_platform_irq.c
> b/drivers/vfio/platform/vfio_platform_irq.c
> index 6ade36b..c9bac80 100644
> --- a/drivers/vfio/platform/vfio_platform_irq.c
> +++ b/drivers/vfio/platform/vfio_platform_irq.c
> @@ -184,6 +184,7 @@ static int vfio_set_trigger(struct
> vfio_platform_device *vdev, int index,
>         struct eventfd_ctx *trigger;
>         unsigned long flags;
>         int ret;
> +       bool masked;
>  
>         if (irq->trigger) {
>                 free_irq(irq->hwirq, irq);
> @@ -208,6 +209,8 @@ static int vfio_set_trigger(struct
> vfio_platform_device *vdev, int index,
>  
>         irq->trigger = trigger;
>  
> +       masked = irq->masked;
> +
>         ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
>         if (ret) {
>                 kfree(irq->name);
> @@ -219,7 +222,7 @@ static int vfio_set_trigger(struct
> vfio_platform_device *vdev, int index,
>         /* if the IRQ has been masked by the user before setting an eventfd,
>          * then we need to make sure it is properly disabled */
>         spin_lock_irqsave(&irq->lock, flags);
> -       if (irq->masked)
> +       if (masked)
>                 disable_irq_nosync(irq->hwirq);
>         spin_unlock_irqrestore(&irq->lock, flags);
> 
> On Mon, Jan 19, 2015 at 1:27 PM, Eric Auger <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org
> <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>> wrote:
> 
>     Hi Baptiste,
> 
>     I think what happens on the second qemu run is:
> 
>     an IRQ hits immediatly after request_irq
>     automasked handler sets masked = true
>     in vfio_set_trigger following condition becomes true
>             if (irq->masked)
>                     disable_irq_nosync(irq->hwirq);
>     IRQ is disabled twice, in handler and in vfio_set_trigger while there is
>     a single enable in resamplefd handler.
>     To me you should prevent from entering ISR between request_irq and
>     disable_irq.
> 
>     It does not happen on the first run because no IRQ hit.
> 
>     Please let me know if you share this understanding.
> 
>     Best Regards
> 
>     Eric
> 
>     On 01/19/2015 11:17 AM, Eric Auger wrote:
>     > Hi Baptiste,
>     >
>     > sorry I was off on Friday. you're right I missed the masked field was
>     > reset on init. Nethertheless with current QEMU VFIO code, IRQ runs on
>     > the first run and not on the second one. I investigate on my side ...
>     >
>     > Best Regards
>     >
>     > Eric
>     >
>     >
>     >
>     >
>     > On 01/16/2015 02:25 PM, Baptiste Reynal wrote:
>     >> Hello Eric,
>     >>
>     >> I'm not sure I understand the issue here. I tried to reproduce
>     the bug
>     >> by triggering an interrupt without unmasking it, but the interrupt is
>     >> unmasked when the program access to the device (vfio_platform_open
>     >> reinit IRQs).
>     >>
>     >> May I have more details on the bug ?
>     >>
>     >> Thanks
>     >>
>     >> On Fri, Jan 9, 2015 at 12:33 PM, Antonios Motakis
>     >> <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org
>     <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
>     >> <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org
>     <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>>> wrote:
>     >>
>     >>     On Fri, Jan 9, 2015 at 9:39 AM, Eric Auger
>     <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>     >>     <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org
>     <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>>> wrote:
>     >>     > Hi Antonios,
>     >>     >
>     >>     > when moving to 3.19rc3 I observe a regression with my xgmac
>     use case
>     >>     > (real-time change?).
>     >>     >
>     >>     > I guess what happens is when I kill a first qemu session,
>     guest does not
>     >>     > have time to complete the virtual IRQ and the unmask is not
>     performed by
>     >>     > the virqfd handler. When starting a new QEMU session, the irqfd
>     >>     > signalling is put in place again but since the masked field
>     is set, the
>     >>     > IRQ is left unmasked (v11 modification in vfio_set_trigger).
>     >>     >
>     >>     > The problem is that we don't discriminate between user mask
>     action and
>     >>     > automasked handler action. In case the user did not mask, I
>     think we
>     >>     > should reset the masked field when doing the free_irq. What
>     do you think?
>     >>
>     >>     Hello Eric,
>     >>
>     >>     I agree, we should reset the masked field for future users.
>     >>
>     >>     Best regards
>     >>     Antonios
>     >>
>     >>     >
>     >>     > Best Regards
>     >>     >
>     >>     > Eric
>     >>     >
>     >>     > On 01/06/2015 11:48 AM, Antonios Motakis wrote:
>     >>     >> This patch series aims to implement VFIO support for platform
>     >>     devices that
>     >>     >> reside behind an IOMMU. Examples of such devices are devices
>     >>     behind an ARM
>     >>     >> SMMU, or behind a Samsung Exynos System MMU.
>     >>     >>
>     >>     >> The API used is based on the existing VFIO API that is
>     also used
>     >>     with PCI
>     >>     >> devices. Only devices that include a basic set of IRQs and
>     memory
>     >>     regions are
>     >>     >> targeted; devices with complex relationships with other
>     devices
>     >>     on a device
>     >>     >> tree are not taken into account at this stage.
>     >>     >>
>     >>     >> This patch series may be applied on the following
>     series/patches:
>     >>     >>  - [PATCH] driver core: amba: add device binding path
>     >>     'driver_override'
>     >>     >>  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with
>     >>     VFIO_IOMMU_TYPE1
>     >>     >>
>     >>     >> A copy can be cloned from the branch vfio-platform-v11 at:
>     >>     >> git-9UaJU3cA/F/QT0dZR+AlfA@public.gmane.org:virtualopensystems/linux-kvm-arm.git
>     >>     >>
>     >>     >> Changes since v10:
>     >>     >>  - Check if interrupt is already masked when setting a new
>     trigger
>     >>     >>  - Fixed kasprintf with unchecked return value in VFIO
>     AMBA driver
>     >>     >> Changes since v9:
>     >>     >>  - Reworked the splitting of the patches that decouple virqfd
>     >>     from PCI
>     >>     >>  - Some styling issues and typos
>     >>     >>  - Removed superfluous includes
>     >>     >>  - AMBA devices are now named vfio-amba- suffixed by the AMBA
>     >>     device id
>     >>     >>  - Several other cleanups and fixes
>     >>     >> Changes since v8:
>     >>     >>  - Separate irq handler for edge and level triggered
>     interrupts
>     >>     >>  - Mutex based lock for VFIO fd open/release
>     >>     >>  - Fixed bug where the first region of a platform device
>     wasn't
>     >>     exposed
>     >>     >>  - Read only regions can be MMAPed only read only
>     >>     >>  - Code cleanups
>     >>     >> Changes since v7:
>     >>     >>  - Some initial placeholder functionality for PIO resources
>     >>     >>  - Cleaned up code for IRQ triggering, masking and unmasking
>     >>     >>  - Some functionality has been removed from this series and
>     >>     posted separately:
>     >>     >>    - VFIO_IOMMU_TYPE1 support for ARM SMMUs
>     >>     >>    - IOMMU NOEXEC patches
>     >>     >>    - driver_override functionality for AMBA devices
>     >>     >>  - Several fixes
>     >>     >> Changes since v6:
>     >>     >>  - Integrated support for AMBA devices
>     >>     >>  - Numerous cleanups and fixes
>     >>     >> Changes since v5:
>     >>     >>  - Full eventfd support for IRQ masking and unmasking.
>     >>     >>  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related
>     flags
>     >>     in VFIO.
>     >>     >>  - Other fixes based on reviewer comments.
>     >>     >> Changes since v4:
>     >>     >>  - Use static offsets for each region in the VFIO device fd
>     >>     >>  - Include patch in the series for the ARM SMMU to expose
>     IOMMU_EXEC
>     >>     >>    availability via IOMMU_CAP_DMA_EXEC
>     >>     >>  - Rebased on VFIO multi domain support:
>     >>     >>    - IOMMU_EXEC is now available if at least one IOMMU in the
>     >>     container
>     >>     >>      supports it
>     >>     >>    - Expose IOMMU_EXEC if available via the capability
>     >>     VFIO_IOMMU_PROT_EXEC
>     >>     >>  - Some bug fixes
>     >>     >> Changes since v3:
>     >>     >>  - Use Kim Phillips' driver_probe_device()
>     >>     >> Changes since v2:
>     >>     >>  - Fixed Read/Write and MMAP on device regions
>     >>     >>  - Removed dependency on Device Tree
>     >>     >>  - Interrupts support
>     >>     >>  - Interrupt masking/unmasking
>     >>     >>  - Automask level sensitive interrupts
>     >>     >>  - Introduced VFIO_DMA_MAP_FLAG_EXEC
>     >>     >>  - Code clean ups
>     >>     >>
>     >>     >> Antonios Motakis (20):
>     >>     >>   vfio/platform: initial skeleton of VFIO support for platform
>     >>     devices
>     >>     >>   vfio: platform: probe to devices on the platform bus
>     >>     >>   vfio: platform: add the VFIO PLATFORM module to Kconfig
>     >>     >>   vfio: amba: VFIO support for AMBA devices
>     >>     >>   vfio: amba: add the VFIO for AMBA devices module to Kconfig
>     >>     >>   vfio/platform: return info for bound device
>     >>     >>   vfio/platform: return info for device memory mapped IO
>     regions
>     >>     >>   vfio/platform: read and write support for the device fd
>     >>     >>   vfio/platform: support MMAP of MMIO regions
>     >>     >>   vfio/platform: return IRQ info
>     >>     >>   vfio/platform: initial interrupts support code
>     >>     >>   vfio/platform: trigger an interrupt via eventfd
>     >>     >>   vfio/platform: support for level sensitive interrupts
>     >>     >>   vfio: add a vfio_ prefix to virqfd_enable and
>     virqfd_disable and
>     >>     >>     export
>     >>     >>   vfio: virqfd: rename vfio_pci_virqfd_init and
>     vfio_pci_virqfd_exit
>     >>     >>   vfio: add local lock for virqfd instead of depending on
>     VFIO PCI
>     >>     >>   vfio: pass an opaque pointer on virqfd initialization
>     >>     >>   vfio: move eventfd support code for VFIO_PCI to a
>     separate file
>     >>     >>   vfio: initialize the virqfd workqueue in VFIO generic code
>     >>     >>   vfio/platform: implement IRQ masking/unmasking via an
>     eventfd
>     >>     >>
>     >>     >>  drivers/vfio/Kconfig                          |   1 +
>     >>     >>  drivers/vfio/Makefile                         |   5 +-
>     >>     >>  drivers/vfio/pci/vfio_pci.c                   |   8 -
>     >>     >>  drivers/vfio/pci/vfio_pci_intrs.c             | 238
>     +-----------
>     >>     >>  drivers/vfio/pci/vfio_pci_private.h           |   3 -
>     >>     >>  drivers/vfio/platform/Kconfig                 |  19 +
>     >>     >>  drivers/vfio/platform/Makefile                |   8 +
>     >>     >>  drivers/vfio/platform/vfio_amba.c             | 115 ++++++
>     >>     >>  drivers/vfio/platform/vfio_platform.c         | 103 +++++
>     >>     >>  drivers/vfio/platform/vfio_platform_common.c  | 520
>     >>     ++++++++++++++++++++++++++
>     >>     >>  drivers/vfio/platform/vfio_platform_irq.c     | 340
>     >>     +++++++++++++++++
>     >>     >>  drivers/vfio/platform/vfio_platform_private.h |  82 ++++
>     >>     >>  drivers/vfio/vfio.c                           |   8 +
>     >>     >>  drivers/vfio/virqfd.c                         | 213
>     +++++++++++
>     >>     >>  include/linux/vfio.h                          |  27 ++
>     >>     >>  include/uapi/linux/vfio.h                     |   2 +
>     >>     >>  16 files changed, 1456 insertions(+), 236 deletions(-)
>     >>     >>  create mode 100644 drivers/vfio/platform/Kconfig
>     >>     >>  create mode 100644 drivers/vfio/platform/Makefile
>     >>     >>  create mode 100644 drivers/vfio/platform/vfio_amba.c
>     >>     >>  create mode 100644 drivers/vfio/platform/vfio_platform.c
>     >>     >>  create mode 100644
>     drivers/vfio/platform/vfio_platform_common.c
>     >>     >>  create mode 100644 drivers/vfio/platform/vfio_platform_irq.c
>     >>     >>  create mode 100644
>     drivers/vfio/platform/vfio_platform_private.h
>     >>     >>  create mode 100644 drivers/vfio/virqfd.c
>     >>     >>
>     >>     >
>     >>
>     >>
>     >
> 
> 

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

* Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices
       [not found] ` <1420541335-17190-1-git-send-email-a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
  2015-01-08 16:58   ` [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Eric Auger
  2015-01-09  8:39   ` Eric Auger
@ 2015-01-19 18:39   ` Alex Williamson
       [not found]     ` <1421692750.6130.377.camel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2 siblings, 1 reply; 54+ messages in thread
From: Alex Williamson @ 2015-01-19 18:39 UTC (permalink / raw)
  To: Antonios Motakis
  Cc: eric.auger-QSEj5FYQhm4dnm+yROfE0A, marc.zyngier-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J,
	kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	christoffer.dall-QSEj5FYQhm4dnm+yROfE0A

On Tue, 2015-01-06 at 11:48 +0100, Antonios Motakis wrote:
> This patch series aims to implement VFIO support for platform devices that
> reside behind an IOMMU. Examples of such devices are devices behind an ARM
> SMMU, or behind a Samsung Exynos System MMU.
> 
> The API used is based on the existing VFIO API that is also used with PCI
> devices. Only devices that include a basic set of IRQs and memory regions are
> targeted; devices with complex relationships with other devices on a device
> tree are not taken into account at this stage.
> 
> This patch series may be applied on the following series/patches:
>  - [PATCH] driver core: amba: add device binding path 'driver_override'

Are we stalled from feature bloat again?  What if we dropped amba
support for now, is there still a useful patch series remaining?

>  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1

Is there anything blocking this series now?  I think we were waiting on
the NOEXEC stuff for the iommu branch, which I think is now in v3.19-rc,
right?

Otherwise it looks like there's at least another revision required to
this series to resolve the mask issue reported by Eric.  Is that
correct?  Thanks,

Alex

> A copy can be cloned from the branch vfio-platform-v11 at:
> git-9UaJU3cA/F/QT0dZR+AlfA@public.gmane.org:virtualopensystems/linux-kvm-arm.git
> 
> Changes since v10:
>  - Check if interrupt is already masked when setting a new trigger
>  - Fixed kasprintf with unchecked return value in VFIO AMBA driver
> Changes since v9:
>  - Reworked the splitting of the patches that decouple virqfd from PCI
>  - Some styling issues and typos
>  - Removed superfluous includes
>  - AMBA devices are now named vfio-amba- suffixed by the AMBA device id
>  - Several other cleanups and fixes
> Changes since v8:
>  - Separate irq handler for edge and level triggered interrupts
>  - Mutex based lock for VFIO fd open/release
>  - Fixed bug where the first region of a platform device wasn't exposed
>  - Read only regions can be MMAPed only read only
>  - Code cleanups
> Changes since v7:
>  - Some initial placeholder functionality for PIO resources
>  - Cleaned up code for IRQ triggering, masking and unmasking
>  - Some functionality has been removed from this series and posted separately:
>    - VFIO_IOMMU_TYPE1 support for ARM SMMUs
>    - IOMMU NOEXEC patches
>    - driver_override functionality for AMBA devices
>  - Several fixes
> Changes since v6:
>  - Integrated support for AMBA devices
>  - Numerous cleanups and fixes
> Changes since v5:
>  - Full eventfd support for IRQ masking and unmasking.
>  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags in VFIO.
>  - Other fixes based on reviewer comments.
> Changes since v4:
>  - Use static offsets for each region in the VFIO device fd
>  - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
>    availability via IOMMU_CAP_DMA_EXEC
>  - Rebased on VFIO multi domain support:
>    - IOMMU_EXEC is now available if at least one IOMMU in the container
>      supports it
>    - Expose IOMMU_EXEC if available via the capability VFIO_IOMMU_PROT_EXEC
>  - Some bug fixes
> Changes since v3:
>  - Use Kim Phillips' driver_probe_device()
> Changes since v2:
>  - Fixed Read/Write and MMAP on device regions
>  - Removed dependency on Device Tree
>  - Interrupts support
>  - Interrupt masking/unmasking
>  - Automask level sensitive interrupts
>  - Introduced VFIO_DMA_MAP_FLAG_EXEC
>  - Code clean ups
> 
> Antonios Motakis (20):
>   vfio/platform: initial skeleton of VFIO support for platform devices
>   vfio: platform: probe to devices on the platform bus
>   vfio: platform: add the VFIO PLATFORM module to Kconfig
>   vfio: amba: VFIO support for AMBA devices
>   vfio: amba: add the VFIO for AMBA devices module to Kconfig
>   vfio/platform: return info for bound device
>   vfio/platform: return info for device memory mapped IO regions
>   vfio/platform: read and write support for the device fd
>   vfio/platform: support MMAP of MMIO regions
>   vfio/platform: return IRQ info
>   vfio/platform: initial interrupts support code
>   vfio/platform: trigger an interrupt via eventfd
>   vfio/platform: support for level sensitive interrupts
>   vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and
>     export
>   vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
>   vfio: add local lock for virqfd instead of depending on VFIO PCI
>   vfio: pass an opaque pointer on virqfd initialization
>   vfio: move eventfd support code for VFIO_PCI to a separate file
>   vfio: initialize the virqfd workqueue in VFIO generic code
>   vfio/platform: implement IRQ masking/unmasking via an eventfd
> 
>  drivers/vfio/Kconfig                          |   1 +
>  drivers/vfio/Makefile                         |   5 +-
>  drivers/vfio/pci/vfio_pci.c                   |   8 -
>  drivers/vfio/pci/vfio_pci_intrs.c             | 238 +-----------
>  drivers/vfio/pci/vfio_pci_private.h           |   3 -
>  drivers/vfio/platform/Kconfig                 |  19 +
>  drivers/vfio/platform/Makefile                |   8 +
>  drivers/vfio/platform/vfio_amba.c             | 115 ++++++
>  drivers/vfio/platform/vfio_platform.c         | 103 +++++
>  drivers/vfio/platform/vfio_platform_common.c  | 520 ++++++++++++++++++++++++++
>  drivers/vfio/platform/vfio_platform_irq.c     | 340 +++++++++++++++++
>  drivers/vfio/platform/vfio_platform_private.h |  82 ++++
>  drivers/vfio/vfio.c                           |   8 +
>  drivers/vfio/virqfd.c                         | 213 +++++++++++
>  include/linux/vfio.h                          |  27 ++
>  include/uapi/linux/vfio.h                     |   2 +
>  16 files changed, 1456 insertions(+), 236 deletions(-)
>  create mode 100644 drivers/vfio/platform/Kconfig
>  create mode 100644 drivers/vfio/platform/Makefile
>  create mode 100644 drivers/vfio/platform/vfio_amba.c
>  create mode 100644 drivers/vfio/platform/vfio_platform.c
>  create mode 100644 drivers/vfio/platform/vfio_platform_common.c
>  create mode 100644 drivers/vfio/platform/vfio_platform_irq.c
>  create mode 100644 drivers/vfio/platform/vfio_platform_private.h
>  create mode 100644 drivers/vfio/virqfd.c
> 

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

* Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices
       [not found]                             ` <54BD4857.3070707-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2015-01-20 15:10                               ` Baptiste Reynal
       [not found]                                 ` <CAN9JPjEhUhjgnDAMmMGxgFoLkhqQYgvsKeZ2+oDKzWMCe+qzhw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 54+ messages in thread
From: Baptiste Reynal @ 2015-01-20 15:10 UTC (permalink / raw)
  To: Eric Auger
  Cc: Marc Zyngier, Will Deacon, Linux IOMMU, Antonios Motakis,
	VirtualOpenSystems Technical Team, kvm-arm, Christoffer Dall


[-- Attachment #1.1: Type: text/plain, Size: 15098 bytes --]

This fix should work, in a more elegant way. Could you confirm ?

I'm sorry I don't have any means to reproduce the bug on my side ...

Thanks,
Baptiste

diff --git a/drivers/vfio/platform/vfio_platform_irq.c
b/drivers/vfio/platform/vfio_platform_irq.c
index 6ade36b..f5f3de0 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -208,6 +208,7 @@ static int vfio_set_trigger(struct vfio_platform_device
*vdev, int index,

        irq->trigger = trigger;

+       irq_set_status_flags(irq->hwirq, IRQ_NOAUTOEN);
        ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
        if (ret) {
                kfree(irq->name);
@@ -216,12 +217,8 @@ static int vfio_set_trigger(struct
vfio_platform_device *vdev, int index,
                return ret;
        }

-       /* if the IRQ has been masked by the user before setting an eventfd,
-        * then we need to make sure it is properly disabled */
-       spin_lock_irqsave(&irq->lock, flags);
-       if (irq->masked)
-               disable_irq_nosync(irq->hwirq);
-       spin_unlock_irqrestore(&irq->lock, flags);
+       if (!irq->masked)
+               enable_irq(irq->hwirq);

        return 0;
 }

On Mon, Jan 19, 2015 at 7:09 PM, Eric Auger <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:

> Hi Baptiste,
>
> yes it fixes the issue in my use case.
>
> Best Regards
>
> Eric
>
> On 01/19/2015 06:00 PM, Baptiste Reynal wrote:
> > Hi Eric,
> >
> > Thanks for taking time about this issue. I agree with you, there is a
> > problem here. While I think on a better fix and to be sure the problem
> > is here, may you try this patch and tell me if the problem is solved ?
> > (This should work as the automasked_irq_handler doesn't do anything if
> > the IRQ is masked).
> >
> > If you have a suggestion on a fix, you're welcome :)
> >
> > diff --git a/drivers/vfio/platform/vfio_platform_irq.c
> > b/drivers/vfio/platform/vfio_platform_irq.c
> > index 6ade36b..c9bac80 100644
> > --- a/drivers/vfio/platform/vfio_platform_irq.c
> > +++ b/drivers/vfio/platform/vfio_platform_irq.c
> > @@ -184,6 +184,7 @@ static int vfio_set_trigger(struct
> > vfio_platform_device *vdev, int index,
> >         struct eventfd_ctx *trigger;
> >         unsigned long flags;
> >         int ret;
> > +       bool masked;
> >
> >         if (irq->trigger) {
> >                 free_irq(irq->hwirq, irq);
> > @@ -208,6 +209,8 @@ static int vfio_set_trigger(struct
> > vfio_platform_device *vdev, int index,
> >
> >         irq->trigger = trigger;
> >
> > +       masked = irq->masked;
> > +
> >         ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
> >         if (ret) {
> >                 kfree(irq->name);
> > @@ -219,7 +222,7 @@ static int vfio_set_trigger(struct
> > vfio_platform_device *vdev, int index,
> >         /* if the IRQ has been masked by the user before setting an
> eventfd,
> >          * then we need to make sure it is properly disabled */
> >         spin_lock_irqsave(&irq->lock, flags);
> > -       if (irq->masked)
> > +       if (masked)
> >                 disable_irq_nosync(irq->hwirq);
> >         spin_unlock_irqrestore(&irq->lock, flags);
> >
> > On Mon, Jan 19, 2015 at 1:27 PM, Eric Auger <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org
> > <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>> wrote:
> >
> >     Hi Baptiste,
> >
> >     I think what happens on the second qemu run is:
> >
> >     an IRQ hits immediatly after request_irq
> >     automasked handler sets masked = true
> >     in vfio_set_trigger following condition becomes true
> >             if (irq->masked)
> >                     disable_irq_nosync(irq->hwirq);
> >     IRQ is disabled twice, in handler and in vfio_set_trigger while
> there is
> >     a single enable in resamplefd handler.
> >     To me you should prevent from entering ISR between request_irq and
> >     disable_irq.
> >
> >     It does not happen on the first run because no IRQ hit.
> >
> >     Please let me know if you share this understanding.
> >
> >     Best Regards
> >
> >     Eric
> >
> >     On 01/19/2015 11:17 AM, Eric Auger wrote:
> >     > Hi Baptiste,
> >     >
> >     > sorry I was off on Friday. you're right I missed the masked field
> was
> >     > reset on init. Nethertheless with current QEMU VFIO code, IRQ runs
> on
> >     > the first run and not on the second one. I investigate on my side
> ...
> >     >
> >     > Best Regards
> >     >
> >     > Eric
> >     >
> >     >
> >     >
> >     >
> >     > On 01/16/2015 02:25 PM, Baptiste Reynal wrote:
> >     >> Hello Eric,
> >     >>
> >     >> I'm not sure I understand the issue here. I tried to reproduce
> >     the bug
> >     >> by triggering an interrupt without unmasking it, but the
> interrupt is
> >     >> unmasked when the program access to the device (vfio_platform_open
> >     >> reinit IRQs).
> >     >>
> >     >> May I have more details on the bug ?
> >     >>
> >     >> Thanks
> >     >>
> >     >> On Fri, Jan 9, 2015 at 12:33 PM, Antonios Motakis
> >     >> <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org
> >     <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
> >     >> <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org
> >     <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>>> wrote:
> >     >>
> >     >>     On Fri, Jan 9, 2015 at 9:39 AM, Eric Auger
> >     <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> >     >>     <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org
> >     <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>>> wrote:
> >     >>     > Hi Antonios,
> >     >>     >
> >     >>     > when moving to 3.19rc3 I observe a regression with my xgmac
> >     use case
> >     >>     > (real-time change?).
> >     >>     >
> >     >>     > I guess what happens is when I kill a first qemu session,
> >     guest does not
> >     >>     > have time to complete the virtual IRQ and the unmask is not
> >     performed by
> >     >>     > the virqfd handler. When starting a new QEMU session, the
> irqfd
> >     >>     > signalling is put in place again but since the masked field
> >     is set, the
> >     >>     > IRQ is left unmasked (v11 modification in vfio_set_trigger).
> >     >>     >
> >     >>     > The problem is that we don't discriminate between user mask
> >     action and
> >     >>     > automasked handler action. In case the user did not mask, I
> >     think we
> >     >>     > should reset the masked field when doing the free_irq. What
> >     do you think?
> >     >>
> >     >>     Hello Eric,
> >     >>
> >     >>     I agree, we should reset the masked field for future users.
> >     >>
> >     >>     Best regards
> >     >>     Antonios
> >     >>
> >     >>     >
> >     >>     > Best Regards
> >     >>     >
> >     >>     > Eric
> >     >>     >
> >     >>     > On 01/06/2015 11:48 AM, Antonios Motakis wrote:
> >     >>     >> This patch series aims to implement VFIO support for
> platform
> >     >>     devices that
> >     >>     >> reside behind an IOMMU. Examples of such devices are
> devices
> >     >>     behind an ARM
> >     >>     >> SMMU, or behind a Samsung Exynos System MMU.
> >     >>     >>
> >     >>     >> The API used is based on the existing VFIO API that is
> >     also used
> >     >>     with PCI
> >     >>     >> devices. Only devices that include a basic set of IRQs and
> >     memory
> >     >>     regions are
> >     >>     >> targeted; devices with complex relationships with other
> >     devices
> >     >>     on a device
> >     >>     >> tree are not taken into account at this stage.
> >     >>     >>
> >     >>     >> This patch series may be applied on the following
> >     series/patches:
> >     >>     >>  - [PATCH] driver core: amba: add device binding path
> >     >>     'driver_override'
> >     >>     >>  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with
> >     >>     VFIO_IOMMU_TYPE1
> >     >>     >>
> >     >>     >> A copy can be cloned from the branch vfio-platform-v11 at:
> >     >>     >> git-9UaJU3cA/F/QT0dZR+AlfA@public.gmane.org:virtualopensystems/linux-kvm-arm.git
> >     >>     >>
> >     >>     >> Changes since v10:
> >     >>     >>  - Check if interrupt is already masked when setting a new
> >     trigger
> >     >>     >>  - Fixed kasprintf with unchecked return value in VFIO
> >     AMBA driver
> >     >>     >> Changes since v9:
> >     >>     >>  - Reworked the splitting of the patches that decouple
> virqfd
> >     >>     from PCI
> >     >>     >>  - Some styling issues and typos
> >     >>     >>  - Removed superfluous includes
> >     >>     >>  - AMBA devices are now named vfio-amba- suffixed by the
> AMBA
> >     >>     device id
> >     >>     >>  - Several other cleanups and fixes
> >     >>     >> Changes since v8:
> >     >>     >>  - Separate irq handler for edge and level triggered
> >     interrupts
> >     >>     >>  - Mutex based lock for VFIO fd open/release
> >     >>     >>  - Fixed bug where the first region of a platform device
> >     wasn't
> >     >>     exposed
> >     >>     >>  - Read only regions can be MMAPed only read only
> >     >>     >>  - Code cleanups
> >     >>     >> Changes since v7:
> >     >>     >>  - Some initial placeholder functionality for PIO resources
> >     >>     >>  - Cleaned up code for IRQ triggering, masking and
> unmasking
> >     >>     >>  - Some functionality has been removed from this series and
> >     >>     posted separately:
> >     >>     >>    - VFIO_IOMMU_TYPE1 support for ARM SMMUs
> >     >>     >>    - IOMMU NOEXEC patches
> >     >>     >>    - driver_override functionality for AMBA devices
> >     >>     >>  - Several fixes
> >     >>     >> Changes since v6:
> >     >>     >>  - Integrated support for AMBA devices
> >     >>     >>  - Numerous cleanups and fixes
> >     >>     >> Changes since v5:
> >     >>     >>  - Full eventfd support for IRQ masking and unmasking.
> >     >>     >>  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related
> >     flags
> >     >>     in VFIO.
> >     >>     >>  - Other fixes based on reviewer comments.
> >     >>     >> Changes since v4:
> >     >>     >>  - Use static offsets for each region in the VFIO device fd
> >     >>     >>  - Include patch in the series for the ARM SMMU to expose
> >     IOMMU_EXEC
> >     >>     >>    availability via IOMMU_CAP_DMA_EXEC
> >     >>     >>  - Rebased on VFIO multi domain support:
> >     >>     >>    - IOMMU_EXEC is now available if at least one IOMMU in
> the
> >     >>     container
> >     >>     >>      supports it
> >     >>     >>    - Expose IOMMU_EXEC if available via the capability
> >     >>     VFIO_IOMMU_PROT_EXEC
> >     >>     >>  - Some bug fixes
> >     >>     >> Changes since v3:
> >     >>     >>  - Use Kim Phillips' driver_probe_device()
> >     >>     >> Changes since v2:
> >     >>     >>  - Fixed Read/Write and MMAP on device regions
> >     >>     >>  - Removed dependency on Device Tree
> >     >>     >>  - Interrupts support
> >     >>     >>  - Interrupt masking/unmasking
> >     >>     >>  - Automask level sensitive interrupts
> >     >>     >>  - Introduced VFIO_DMA_MAP_FLAG_EXEC
> >     >>     >>  - Code clean ups
> >     >>     >>
> >     >>     >> Antonios Motakis (20):
> >     >>     >>   vfio/platform: initial skeleton of VFIO support for
> platform
> >     >>     devices
> >     >>     >>   vfio: platform: probe to devices on the platform bus
> >     >>     >>   vfio: platform: add the VFIO PLATFORM module to Kconfig
> >     >>     >>   vfio: amba: VFIO support for AMBA devices
> >     >>     >>   vfio: amba: add the VFIO for AMBA devices module to
> Kconfig
> >     >>     >>   vfio/platform: return info for bound device
> >     >>     >>   vfio/platform: return info for device memory mapped IO
> >     regions
> >     >>     >>   vfio/platform: read and write support for the device fd
> >     >>     >>   vfio/platform: support MMAP of MMIO regions
> >     >>     >>   vfio/platform: return IRQ info
> >     >>     >>   vfio/platform: initial interrupts support code
> >     >>     >>   vfio/platform: trigger an interrupt via eventfd
> >     >>     >>   vfio/platform: support for level sensitive interrupts
> >     >>     >>   vfio: add a vfio_ prefix to virqfd_enable and
> >     virqfd_disable and
> >     >>     >>     export
> >     >>     >>   vfio: virqfd: rename vfio_pci_virqfd_init and
> >     vfio_pci_virqfd_exit
> >     >>     >>   vfio: add local lock for virqfd instead of depending on
> >     VFIO PCI
> >     >>     >>   vfio: pass an opaque pointer on virqfd initialization
> >     >>     >>   vfio: move eventfd support code for VFIO_PCI to a
> >     separate file
> >     >>     >>   vfio: initialize the virqfd workqueue in VFIO generic
> code
> >     >>     >>   vfio/platform: implement IRQ masking/unmasking via an
> >     eventfd
> >     >>     >>
> >     >>     >>  drivers/vfio/Kconfig                          |   1 +
> >     >>     >>  drivers/vfio/Makefile                         |   5 +-
> >     >>     >>  drivers/vfio/pci/vfio_pci.c                   |   8 -
> >     >>     >>  drivers/vfio/pci/vfio_pci_intrs.c             | 238
> >     +-----------
> >     >>     >>  drivers/vfio/pci/vfio_pci_private.h           |   3 -
> >     >>     >>  drivers/vfio/platform/Kconfig                 |  19 +
> >     >>     >>  drivers/vfio/platform/Makefile                |   8 +
> >     >>     >>  drivers/vfio/platform/vfio_amba.c             | 115 ++++++
> >     >>     >>  drivers/vfio/platform/vfio_platform.c         | 103 +++++
> >     >>     >>  drivers/vfio/platform/vfio_platform_common.c  | 520
> >     >>     ++++++++++++++++++++++++++
> >     >>     >>  drivers/vfio/platform/vfio_platform_irq.c     | 340
> >     >>     +++++++++++++++++
> >     >>     >>  drivers/vfio/platform/vfio_platform_private.h |  82 ++++
> >     >>     >>  drivers/vfio/vfio.c                           |   8 +
> >     >>     >>  drivers/vfio/virqfd.c                         | 213
> >     +++++++++++
> >     >>     >>  include/linux/vfio.h                          |  27 ++
> >     >>     >>  include/uapi/linux/vfio.h                     |   2 +
> >     >>     >>  16 files changed, 1456 insertions(+), 236 deletions(-)
> >     >>     >>  create mode 100644 drivers/vfio/platform/Kconfig
> >     >>     >>  create mode 100644 drivers/vfio/platform/Makefile
> >     >>     >>  create mode 100644 drivers/vfio/platform/vfio_amba.c
> >     >>     >>  create mode 100644 drivers/vfio/platform/vfio_platform.c
> >     >>     >>  create mode 100644
> >     drivers/vfio/platform/vfio_platform_common.c
> >     >>     >>  create mode 100644
> drivers/vfio/platform/vfio_platform_irq.c
> >     >>     >>  create mode 100644
> >     drivers/vfio/platform/vfio_platform_private.h
> >     >>     >>  create mode 100644 drivers/vfio/virqfd.c
> >     >>     >>
> >     >>     >
> >     >>
> >     >>
> >     >
> >
> >
>
>

[-- Attachment #1.2: Type: text/html, Size: 21982 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices
       [not found]                                 ` <CAN9JPjEhUhjgnDAMmMGxgFoLkhqQYgvsKeZ2+oDKzWMCe+qzhw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2015-01-20 16:33                                   ` Eric Auger
  0 siblings, 0 replies; 54+ messages in thread
From: Eric Auger @ 2015-01-20 16:33 UTC (permalink / raw)
  To: Baptiste Reynal
  Cc: Marc Zyngier, Will Deacon, Linux IOMMU, Antonios Motakis,
	VirtualOpenSystems Technical Team, kvm-arm, Christoffer Dall

On 01/20/2015 04:10 PM, Baptiste Reynal wrote:
> This fix should work, in a more elegant way. Could you confirm ?
> 
> I'm sorry I don't have any means to reproduce the bug on my side ...


Hi Baptiste,

No Problem. It looks OK to me and runs fine in my xgmac use case.

Best Regards

Eric
> 
> Thanks,
> Baptiste
> 
> diff --git a/drivers/vfio/platform/vfio_platform_irq.c
> b/drivers/vfio/platform/vfio_platform_irq.c
> index 6ade36b..f5f3de0 100644
> --- a/drivers/vfio/platform/vfio_platform_irq.c
> +++ b/drivers/vfio/platform/vfio_platform_irq.c
> @@ -208,6 +208,7 @@ static int vfio_set_trigger(struct
> vfio_platform_device *vdev, int index,
>  
>         irq->trigger = trigger;
>  
> +       irq_set_status_flags(irq->hwirq, IRQ_NOAUTOEN);
>         ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
>         if (ret) {
>                 kfree(irq->name);
> @@ -216,12 +217,8 @@ static int vfio_set_trigger(struct
> vfio_platform_device *vdev, int index,
>                 return ret;
>         }
>  
> -       /* if the IRQ has been masked by the user before setting an eventfd,
> -        * then we need to make sure it is properly disabled */
> -       spin_lock_irqsave(&irq->lock, flags);
> -       if (irq->masked)
> -               disable_irq_nosync(irq->hwirq);
> -       spin_unlock_irqrestore(&irq->lock, flags);
> +       if (!irq->masked)
> +               enable_irq(irq->hwirq);
>  
>         return 0;
>  }
> 
> On Mon, Jan 19, 2015 at 7:09 PM, Eric Auger <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org
> <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>> wrote:
> 
>     Hi Baptiste,
> 
>     yes it fixes the issue in my use case.
> 
>     Best Regards
> 
>     Eric
> 
>     On 01/19/2015 06:00 PM, Baptiste Reynal wrote:
>     > Hi Eric,
>     >
>     > Thanks for taking time about this issue. I agree with you, there is a
>     > problem here. While I think on a better fix and to be sure the problem
>     > is here, may you try this patch and tell me if the problem is solved ?
>     > (This should work as the automasked_irq_handler doesn't do anything if
>     > the IRQ is masked).
>     >
>     > If you have a suggestion on a fix, you're welcome :)
>     >
>     > diff --git a/drivers/vfio/platform/vfio_platform_irq.c
>     > b/drivers/vfio/platform/vfio_platform_irq.c
>     > index 6ade36b..c9bac80 100644
>     > --- a/drivers/vfio/platform/vfio_platform_irq.c
>     > +++ b/drivers/vfio/platform/vfio_platform_irq.c
>     > @@ -184,6 +184,7 @@ static int vfio_set_trigger(struct
>     > vfio_platform_device *vdev, int index,
>     >         struct eventfd_ctx *trigger;
>     >         unsigned long flags;
>     >         int ret;
>     > +       bool masked;
>     >
>     >         if (irq->trigger) {
>     >                 free_irq(irq->hwirq, irq);
>     > @@ -208,6 +209,8 @@ static int vfio_set_trigger(struct
>     > vfio_platform_device *vdev, int index,
>     >
>     >         irq->trigger = trigger;
>     >
>     > +       masked = irq->masked;
>     > +
>     >         ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
>     >         if (ret) {
>     >                 kfree(irq->name);
>     > @@ -219,7 +222,7 @@ static int vfio_set_trigger(struct
>     > vfio_platform_device *vdev, int index,
>     >         /* if the IRQ has been masked by the user before setting
>     an eventfd,
>     >          * then we need to make sure it is properly disabled */
>     >         spin_lock_irqsave(&irq->lock, flags);
>     > -       if (irq->masked)
>     > +       if (masked)
>     >                 disable_irq_nosync(irq->hwirq);
>     >         spin_unlock_irqrestore(&irq->lock, flags);
>     >
>     > On Mon, Jan 19, 2015 at 1:27 PM, Eric Auger <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org
>     <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>     > <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>>> wrote:
>     >
>     >     Hi Baptiste,
>     >
>     >     I think what happens on the second qemu run is:
>     >
>     >     an IRQ hits immediatly after request_irq
>     >     automasked handler sets masked = true
>     >     in vfio_set_trigger following condition becomes true
>     >             if (irq->masked)
>     >                     disable_irq_nosync(irq->hwirq);
>     >     IRQ is disabled twice, in handler and in vfio_set_trigger
>     while there is
>     >     a single enable in resamplefd handler.
>     >     To me you should prevent from entering ISR between request_irq and
>     >     disable_irq.
>     >
>     >     It does not happen on the first run because no IRQ hit.
>     >
>     >     Please let me know if you share this understanding.
>     >
>     >     Best Regards
>     >
>     >     Eric
>     >
>     >     On 01/19/2015 11:17 AM, Eric Auger wrote:
>     >     > Hi Baptiste,
>     >     >
>     >     > sorry I was off on Friday. you're right I missed the masked
>     field was
>     >     > reset on init. Nethertheless with current QEMU VFIO code,
>     IRQ runs on
>     >     > the first run and not on the second one. I investigate on my
>     side ...
>     >     >
>     >     > Best Regards
>     >     >
>     >     > Eric
>     >     >
>     >     >
>     >     >
>     >     >
>     >     > On 01/16/2015 02:25 PM, Baptiste Reynal wrote:
>     >     >> Hello Eric,
>     >     >>
>     >     >> I'm not sure I understand the issue here. I tried to reproduce
>     >     the bug
>     >     >> by triggering an interrupt without unmasking it, but the
>     interrupt is
>     >     >> unmasked when the program access to the device
>     (vfio_platform_open
>     >     >> reinit IRQs).
>     >     >>
>     >     >> May I have more details on the bug ?
>     >     >>
>     >     >> Thanks
>     >     >>
>     >     >> On Fri, Jan 9, 2015 at 12:33 PM, Antonios Motakis
>     >     >> <a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org
>     <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
>     >     <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org
>     <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>>
>     >     >> <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org
>     <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
>     >     <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org
>     <mailto:a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>>>> wrote:
>     >     >>
>     >     >>     On Fri, Jan 9, 2015 at 9:39 AM, Eric Auger
>     >     <eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>     <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>>
>     >     >>     <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org
>     <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>     >     <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org
>     <mailto:eric.auger-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>>>> wrote:
>     >     >>     > Hi Antonios,
>     >     >>     >
>     >     >>     > when moving to 3.19rc3 I observe a regression with my
>     xgmac
>     >     use case
>     >     >>     > (real-time change?).
>     >     >>     >
>     >     >>     > I guess what happens is when I kill a first qemu session,
>     >     guest does not
>     >     >>     > have time to complete the virtual IRQ and the unmask
>     is not
>     >     performed by
>     >     >>     > the virqfd handler. When starting a new QEMU session,
>     the irqfd
>     >     >>     > signalling is put in place again but since the masked
>     field
>     >     is set, the
>     >     >>     > IRQ is left unmasked (v11 modification in
>     vfio_set_trigger).
>     >     >>     >
>     >     >>     > The problem is that we don't discriminate between
>     user mask
>     >     action and
>     >     >>     > automasked handler action. In case the user did not
>     mask, I
>     >     think we
>     >     >>     > should reset the masked field when doing the
>     free_irq. What
>     >     do you think?
>     >     >>
>     >     >>     Hello Eric,
>     >     >>
>     >     >>     I agree, we should reset the masked field for future users.
>     >     >>
>     >     >>     Best regards
>     >     >>     Antonios
>     >     >>
>     >     >>     >
>     >     >>     > Best Regards
>     >     >>     >
>     >     >>     > Eric
>     >     >>     >
>     >     >>     > On 01/06/2015 11:48 AM, Antonios Motakis wrote:
>     >     >>     >> This patch series aims to implement VFIO support for
>     platform
>     >     >>     devices that
>     >     >>     >> reside behind an IOMMU. Examples of such devices are
>     devices
>     >     >>     behind an ARM
>     >     >>     >> SMMU, or behind a Samsung Exynos System MMU.
>     >     >>     >>
>     >     >>     >> The API used is based on the existing VFIO API that is
>     >     also used
>     >     >>     with PCI
>     >     >>     >> devices. Only devices that include a basic set of
>     IRQs and
>     >     memory
>     >     >>     regions are
>     >     >>     >> targeted; devices with complex relationships with other
>     >     devices
>     >     >>     on a device
>     >     >>     >> tree are not taken into account at this stage.
>     >     >>     >>
>     >     >>     >> This patch series may be applied on the following
>     >     series/patches:
>     >     >>     >>  - [PATCH] driver core: amba: add device binding path
>     >     >>     'driver_override'
>     >     >>     >>  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS
>     with
>     >     >>     VFIO_IOMMU_TYPE1
>     >     >>     >>
>     >     >>     >> A copy can be cloned from the branch
>     vfio-platform-v11 at:
>     >     >>     >> git-9UaJU3cA/F/QT0dZR+AlfA@public.gmane.org:virtualopensystems/linux-kvm-arm.git
>     >     >>     >>
>     >     >>     >> Changes since v10:
>     >     >>     >>  - Check if interrupt is already masked when setting
>     a new
>     >     trigger
>     >     >>     >>  - Fixed kasprintf with unchecked return value in VFIO
>     >     AMBA driver
>     >     >>     >> Changes since v9:
>     >     >>     >>  - Reworked the splitting of the patches that
>     decouple virqfd
>     >     >>     from PCI
>     >     >>     >>  - Some styling issues and typos
>     >     >>     >>  - Removed superfluous includes
>     >     >>     >>  - AMBA devices are now named vfio-amba- suffixed by
>     the AMBA
>     >     >>     device id
>     >     >>     >>  - Several other cleanups and fixes
>     >     >>     >> Changes since v8:
>     >     >>     >>  - Separate irq handler for edge and level triggered
>     >     interrupts
>     >     >>     >>  - Mutex based lock for VFIO fd open/release
>     >     >>     >>  - Fixed bug where the first region of a platform device
>     >     wasn't
>     >     >>     exposed
>     >     >>     >>  - Read only regions can be MMAPed only read only
>     >     >>     >>  - Code cleanups
>     >     >>     >> Changes since v7:
>     >     >>     >>  - Some initial placeholder functionality for PIO
>     resources
>     >     >>     >>  - Cleaned up code for IRQ triggering, masking and
>     unmasking
>     >     >>     >>  - Some functionality has been removed from this
>     series and
>     >     >>     posted separately:
>     >     >>     >>    - VFIO_IOMMU_TYPE1 support for ARM SMMUs
>     >     >>     >>    - IOMMU NOEXEC patches
>     >     >>     >>    - driver_override functionality for AMBA devices
>     >     >>     >>  - Several fixes
>     >     >>     >> Changes since v6:
>     >     >>     >>  - Integrated support for AMBA devices
>     >     >>     >>  - Numerous cleanups and fixes
>     >     >>     >> Changes since v5:
>     >     >>     >>  - Full eventfd support for IRQ masking and unmasking.
>     >     >>     >>  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with
>     related
>     >     flags
>     >     >>     in VFIO.
>     >     >>     >>  - Other fixes based on reviewer comments.
>     >     >>     >> Changes since v4:
>     >     >>     >>  - Use static offsets for each region in the VFIO
>     device fd
>     >     >>     >>  - Include patch in the series for the ARM SMMU to
>     expose
>     >     IOMMU_EXEC
>     >     >>     >>    availability via IOMMU_CAP_DMA_EXEC
>     >     >>     >>  - Rebased on VFIO multi domain support:
>     >     >>     >>    - IOMMU_EXEC is now available if at least one
>     IOMMU in the
>     >     >>     container
>     >     >>     >>      supports it
>     >     >>     >>    - Expose IOMMU_EXEC if available via the capability
>     >     >>     VFIO_IOMMU_PROT_EXEC
>     >     >>     >>  - Some bug fixes
>     >     >>     >> Changes since v3:
>     >     >>     >>  - Use Kim Phillips' driver_probe_device()
>     >     >>     >> Changes since v2:
>     >     >>     >>  - Fixed Read/Write and MMAP on device regions
>     >     >>     >>  - Removed dependency on Device Tree
>     >     >>     >>  - Interrupts support
>     >     >>     >>  - Interrupt masking/unmasking
>     >     >>     >>  - Automask level sensitive interrupts
>     >     >>     >>  - Introduced VFIO_DMA_MAP_FLAG_EXEC
>     >     >>     >>  - Code clean ups
>     >     >>     >>
>     >     >>     >> Antonios Motakis (20):
>     >     >>     >>   vfio/platform: initial skeleton of VFIO support
>     for platform
>     >     >>     devices
>     >     >>     >>   vfio: platform: probe to devices on the platform bus
>     >     >>     >>   vfio: platform: add the VFIO PLATFORM module to
>     Kconfig
>     >     >>     >>   vfio: amba: VFIO support for AMBA devices
>     >     >>     >>   vfio: amba: add the VFIO for AMBA devices module
>     to Kconfig
>     >     >>     >>   vfio/platform: return info for bound device
>     >     >>     >>   vfio/platform: return info for device memory mapped IO
>     >     regions
>     >     >>     >>   vfio/platform: read and write support for the
>     device fd
>     >     >>     >>   vfio/platform: support MMAP of MMIO regions
>     >     >>     >>   vfio/platform: return IRQ info
>     >     >>     >>   vfio/platform: initial interrupts support code
>     >     >>     >>   vfio/platform: trigger an interrupt via eventfd
>     >     >>     >>   vfio/platform: support for level sensitive interrupts
>     >     >>     >>   vfio: add a vfio_ prefix to virqfd_enable and
>     >     virqfd_disable and
>     >     >>     >>     export
>     >     >>     >>   vfio: virqfd: rename vfio_pci_virqfd_init and
>     >     vfio_pci_virqfd_exit
>     >     >>     >>   vfio: add local lock for virqfd instead of
>     depending on
>     >     VFIO PCI
>     >     >>     >>   vfio: pass an opaque pointer on virqfd initialization
>     >     >>     >>   vfio: move eventfd support code for VFIO_PCI to a
>     >     separate file
>     >     >>     >>   vfio: initialize the virqfd workqueue in VFIO
>     generic code
>     >     >>     >>   vfio/platform: implement IRQ masking/unmasking via an
>     >     eventfd
>     >     >>     >>
>     >     >>     >>  drivers/vfio/Kconfig                          |   1 +
>     >     >>     >>  drivers/vfio/Makefile                         |   5 +-
>     >     >>     >>  drivers/vfio/pci/vfio_pci.c                   |   8 -
>     >     >>     >>  drivers/vfio/pci/vfio_pci_intrs.c             | 238
>     >     +-----------
>     >     >>     >>  drivers/vfio/pci/vfio_pci_private.h           |   3 -
>     >     >>     >>  drivers/vfio/platform/Kconfig                 |  19 +
>     >     >>     >>  drivers/vfio/platform/Makefile                |   8 +
>     >     >>     >>  drivers/vfio/platform/vfio_amba.c             | 115
>     ++++++
>     >     >>     >>  drivers/vfio/platform/vfio_platform.c         | 103
>     +++++
>     >     >>     >>  drivers/vfio/platform/vfio_platform_common.c  | 520
>     >     >>     ++++++++++++++++++++++++++
>     >     >>     >>  drivers/vfio/platform/vfio_platform_irq.c     | 340
>     >     >>     +++++++++++++++++
>     >     >>     >>  drivers/vfio/platform/vfio_platform_private.h |  82
>     ++++
>     >     >>     >>  drivers/vfio/vfio.c                           |   8 +
>     >     >>     >>  drivers/vfio/virqfd.c                         | 213
>     >     +++++++++++
>     >     >>     >>  include/linux/vfio.h                          |  27 ++
>     >     >>     >>  include/uapi/linux/vfio.h                     |   2 +
>     >     >>     >>  16 files changed, 1456 insertions(+), 236 deletions(-)
>     >     >>     >>  create mode 100644 drivers/vfio/platform/Kconfig
>     >     >>     >>  create mode 100644 drivers/vfio/platform/Makefile
>     >     >>     >>  create mode 100644 drivers/vfio/platform/vfio_amba.c
>     >     >>     >>  create mode 100644
>     drivers/vfio/platform/vfio_platform.c
>     >     >>     >>  create mode 100644
>     >     drivers/vfio/platform/vfio_platform_common.c
>     >     >>     >>  create mode 100644
>     drivers/vfio/platform/vfio_platform_irq.c
>     >     >>     >>  create mode 100644
>     >     drivers/vfio/platform/vfio_platform_private.h
>     >     >>     >>  create mode 100644 drivers/vfio/virqfd.c
>     >     >>     >>
>     >     >>     >
>     >     >>
>     >     >>
>     >     >
>     >
>     >
> 
> 

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

* Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices
       [not found]     ` <1421692750.6130.377.camel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2015-01-21 12:54       ` Antonios Motakis
  0 siblings, 0 replies; 54+ messages in thread
From: Antonios Motakis @ 2015-01-21 12:54 UTC (permalink / raw)
  To: Alex Williamson
  Cc: Eric Auger, Marc Zyngier, Will Deacon, Linux IOMMU,
	VirtualOpenSystems Technical Team, kvm-arm, Christoffer Dall

Hello Alex,

On Mon, Jan 19, 2015 at 7:39 PM, Alex Williamson
<alex.williamson-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>
> On Tue, 2015-01-06 at 11:48 +0100, Antonios Motakis wrote:
> > This patch series aims to implement VFIO support for platform devices that
> > reside behind an IOMMU. Examples of such devices are devices behind an ARM
> > SMMU, or behind a Samsung Exynos System MMU.
> >
> > The API used is based on the existing VFIO API that is also used with PCI
> > devices. Only devices that include a basic set of IRQs and memory regions are
> > targeted; devices with complex relationships with other devices on a device
> > tree are not taken into account at this stage.
> >
> > This patch series may be applied on the following series/patches:
> >  - [PATCH] driver core: amba: add device binding path 'driver_override'
>
> Are we stalled from feature bloat again?  What if we dropped amba
> support for now, is there still a useful patch series remaining?

With AMBA support removed from v12, I believe we are not stalled anymore.
The two AMBA patches could be merged later, and applied manually in
the meantime by those who do their testing on the PL330 DMA
controller.

>
> >  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1
>
> Is there anything blocking this series now?  I think we were waiting on
> the NOEXEC stuff for the iommu branch, which I think is now in v3.19-rc,
> right?
>
> Otherwise it looks like there's at least another revision required to
> this series to resolve the mask issue reported by Eric.  Is that
> correct?  Thanks,

Yes, correct on both points.

With Baptiste's touch ups to v12, these should be resolved.

Best regards,
Antonios

>
> Alex
>
> > A copy can be cloned from the branch vfio-platform-v11 at:
> > git-9UaJU3cA/F/QT0dZR+AlfA@public.gmane.org:virtualopensystems/linux-kvm-arm.git
> >
> > Changes since v10:
> >  - Check if interrupt is already masked when setting a new trigger
> >  - Fixed kasprintf with unchecked return value in VFIO AMBA driver
> > Changes since v9:
> >  - Reworked the splitting of the patches that decouple virqfd from PCI
> >  - Some styling issues and typos
> >  - Removed superfluous includes
> >  - AMBA devices are now named vfio-amba- suffixed by the AMBA device id
> >  - Several other cleanups and fixes
> > Changes since v8:
> >  - Separate irq handler for edge and level triggered interrupts
> >  - Mutex based lock for VFIO fd open/release
> >  - Fixed bug where the first region of a platform device wasn't exposed
> >  - Read only regions can be MMAPed only read only
> >  - Code cleanups
> > Changes since v7:
> >  - Some initial placeholder functionality for PIO resources
> >  - Cleaned up code for IRQ triggering, masking and unmasking
> >  - Some functionality has been removed from this series and posted separately:
> >    - VFIO_IOMMU_TYPE1 support for ARM SMMUs
> >    - IOMMU NOEXEC patches
> >    - driver_override functionality for AMBA devices
> >  - Several fixes
> > Changes since v6:
> >  - Integrated support for AMBA devices
> >  - Numerous cleanups and fixes
> > Changes since v5:
> >  - Full eventfd support for IRQ masking and unmasking.
> >  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags in VFIO.
> >  - Other fixes based on reviewer comments.
> > Changes since v4:
> >  - Use static offsets for each region in the VFIO device fd
> >  - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
> >    availability via IOMMU_CAP_DMA_EXEC
> >  - Rebased on VFIO multi domain support:
> >    - IOMMU_EXEC is now available if at least one IOMMU in the container
> >      supports it
> >    - Expose IOMMU_EXEC if available via the capability VFIO_IOMMU_PROT_EXEC
> >  - Some bug fixes
> > Changes since v3:
> >  - Use Kim Phillips' driver_probe_device()
> > Changes since v2:
> >  - Fixed Read/Write and MMAP on device regions
> >  - Removed dependency on Device Tree
> >  - Interrupts support
> >  - Interrupt masking/unmasking
> >  - Automask level sensitive interrupts
> >  - Introduced VFIO_DMA_MAP_FLAG_EXEC
> >  - Code clean ups
> >
> > Antonios Motakis (20):
> >   vfio/platform: initial skeleton of VFIO support for platform devices
> >   vfio: platform: probe to devices on the platform bus
> >   vfio: platform: add the VFIO PLATFORM module to Kconfig
> >   vfio: amba: VFIO support for AMBA devices
> >   vfio: amba: add the VFIO for AMBA devices module to Kconfig
> >   vfio/platform: return info for bound device
> >   vfio/platform: return info for device memory mapped IO regions
> >   vfio/platform: read and write support for the device fd
> >   vfio/platform: support MMAP of MMIO regions
> >   vfio/platform: return IRQ info
> >   vfio/platform: initial interrupts support code
> >   vfio/platform: trigger an interrupt via eventfd
> >   vfio/platform: support for level sensitive interrupts
> >   vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and
> >     export
> >   vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
> >   vfio: add local lock for virqfd instead of depending on VFIO PCI
> >   vfio: pass an opaque pointer on virqfd initialization
> >   vfio: move eventfd support code for VFIO_PCI to a separate file
> >   vfio: initialize the virqfd workqueue in VFIO generic code
> >   vfio/platform: implement IRQ masking/unmasking via an eventfd
> >
> >  drivers/vfio/Kconfig                          |   1 +
> >  drivers/vfio/Makefile                         |   5 +-
> >  drivers/vfio/pci/vfio_pci.c                   |   8 -
> >  drivers/vfio/pci/vfio_pci_intrs.c             | 238 +-----------
> >  drivers/vfio/pci/vfio_pci_private.h           |   3 -
> >  drivers/vfio/platform/Kconfig                 |  19 +
> >  drivers/vfio/platform/Makefile                |   8 +
> >  drivers/vfio/platform/vfio_amba.c             | 115 ++++++
> >  drivers/vfio/platform/vfio_platform.c         | 103 +++++
> >  drivers/vfio/platform/vfio_platform_common.c  | 520 ++++++++++++++++++++++++++
> >  drivers/vfio/platform/vfio_platform_irq.c     | 340 +++++++++++++++++
> >  drivers/vfio/platform/vfio_platform_private.h |  82 ++++
> >  drivers/vfio/vfio.c                           |   8 +
> >  drivers/vfio/virqfd.c                         | 213 +++++++++++
> >  include/linux/vfio.h                          |  27 ++
> >  include/uapi/linux/vfio.h                     |   2 +
> >  16 files changed, 1456 insertions(+), 236 deletions(-)
> >  create mode 100644 drivers/vfio/platform/Kconfig
> >  create mode 100644 drivers/vfio/platform/Makefile
> >  create mode 100644 drivers/vfio/platform/vfio_amba.c
> >  create mode 100644 drivers/vfio/platform/vfio_platform.c
> >  create mode 100644 drivers/vfio/platform/vfio_platform_common.c
> >  create mode 100644 drivers/vfio/platform/vfio_platform_irq.c
> >  create mode 100644 drivers/vfio/platform/vfio_platform_private.h
> >  create mode 100644 drivers/vfio/virqfd.c
> >
>
>
>

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

end of thread, other threads:[~2015-01-21 12:54 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-06 10:48 [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 01/20] vfio/platform: initial skeleton of VFIO support for platform devices Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 02/20] vfio: platform: probe to devices on the platform bus Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 03/20] vfio: platform: add the VFIO PLATFORM module to Kconfig Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 04/20] vfio: amba: VFIO support for AMBA devices Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 05/20] vfio: amba: add the VFIO for AMBA devices module to Kconfig Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 06/20] vfio/platform: return info for bound device Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 07/20] vfio/platform: return info for device memory mapped IO regions Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 08/20] vfio/platform: read and write support for the device fd Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 09/20] vfio/platform: support MMAP of MMIO regions Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 10/20] vfio/platform: return IRQ info Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 11/20] vfio/platform: initial interrupts support code Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 12/20] vfio/platform: trigger an interrupt via eventfd Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 13/20] vfio/platform: support for level sensitive interrupts Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 14/20] vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and export Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 15/20] vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 16/20] vfio: add local lock for virqfd instead of depending on VFIO PCI Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 17/20] vfio: pass an opaque pointer on virqfd initialization Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 18/20] vfio: move eventfd support code for VFIO_PCI to a separate file Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 19/20] vfio: initialize the virqfd workqueue in VFIO generic code Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
2015-01-06 10:48 ` [PATCH v11 20/20] vfio/platform: implement IRQ masking/unmasking via an eventfd Antonios Motakis
2015-01-06 10:48   ` Antonios Motakis
     [not found] ` <1420541335-17190-1-git-send-email-a.motakis-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
2015-01-08 16:58   ` [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices Eric Auger
2015-01-09  8:39   ` Eric Auger
     [not found]     ` <54AF93AB.9030302-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-01-09 11:33       ` Antonios Motakis
     [not found]         ` <CAG8rG2yc1ityUwswPiTR_w5f3tSeX_KB2g06HcPCPARXPHGvfg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-01-16 13:25           ` Baptiste Reynal
     [not found]             ` <CAN9JPjERBVnGku8_BJuesMnzJyQYUgz6rJhL_VrCOgLVQuXyuw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-01-19 10:17               ` Eric Auger
     [not found]                 ` <54BCD9A6.4050501-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-01-19 12:27                   ` Eric Auger
     [not found]                     ` <54BCF846.1070906-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-01-19 17:00                       ` Baptiste Reynal
     [not found]                         ` <CAN9JPjF5sAH-UNKtBhfiHK7cQJBwNwg2UEcrj8sv9Em6MnBVxg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-01-19 18:09                           ` Eric Auger
     [not found]                             ` <54BD4857.3070707-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-01-20 15:10                               ` Baptiste Reynal
     [not found]                                 ` <CAN9JPjEhUhjgnDAMmMGxgFoLkhqQYgvsKeZ2+oDKzWMCe+qzhw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-01-20 16:33                                   ` Eric Auger
2015-01-19 18:39   ` Alex Williamson
     [not found]     ` <1421692750.6130.377.camel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-01-21 12:54       ` Antonios Motakis

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.