All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] vfio: capability chains, sparse mmaps, device specific regions, IGD OpRegions
@ 2016-02-02  0:24 Alex Williamson
  2016-02-02  0:24 ` [PATCH 1/8] vfio: Define capability chains Alex Williamson
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Alex Williamson @ 2016-02-02  0:24 UTC (permalink / raw)
  To: alex.williamson; +Cc: linux-kernel, kvm, kraxel

We have a number of cases were we want to extend the vfio API to
provide further details in the vfio INFO ioctls.  For instance we take
it as implicit that we can't mmap over MSI-X vector tables of a BAR,
but we'd prefer to have the API define that explicitly as a sparse
mmap capable region.  We have some devices that need additional
regions, but we don't want to "burn" a region index for something
specific to a single device.  We also have the ongoing problem of
describing valid IOVA ranges for an IOMMU.  This series doesn't solve
every case of those problems, but it solves some and gives us the vfio
level API to solve the others.

To do this we use capability chains, much like they're used in PCI.
A flag bit in the INFO ioctl structure tells us whether a capability
chain is present and new fields are defined to provide the buffer
index of the first capability.  Each capability provides the start
index of the next capability along with an identifier and version of
itself.  The existing argsz field of is used to convey to the user the
necessary buffer size to retrieve all of the capabilities.  A few
helpers in the vfio core simplifies the mechanics of adding
capabilities for the bus and iommu drivers to make use of.

The sparse mmap capability solves the problem of regions which can
only be partially mmaped, such as when an MSI-X table is present.
This is also expected to be useful for vGPU support should a device
have a mix of direct access and emulated access within the same
region.

The device specific region capability allows us to easily add new
regions that are device specific.  Included here is the IGD OpRegion,
which is a host memory region exclusively for the configuration and
use of Intel graphics devices, but is not part of the device in the
PCI sense.  There are potentially other regions we can expose on this
device to further facilitate use of it.

I particularly welcome feedback on how we identify device specific
regions.  Here I've used a type and sub-type field where I've defined
one bit of the type field to identify a vendor specific type with a
mask to identify the vendor.  In the Opregion case here, that defines
an 8086 set of sub-types where I've simply defined sub-type 1 as an
IGD OpRegion.  We could of course get the vendor from the device
itself, but this method might promote code re-use if we eventually
have multiple vendors using regions for the same purpose.  At least
that's my thinking.

Appreciate feedback.  Thanks,

Alex

---

Alex Williamson (8):
      vfio: Define capability chains
      vfio: Add capability chain helpers
      vfio: Define sparse mmap capability for regions
      vfio/pci: Include sparse mmap capability for MSI-X table regions
      vfio: Define device specific region type capability
      vfio/pci: Add infrastructure for additional device specific regions
      vfio/pci: Enable virtual register in PCI config space
      vfio/pci: Intel IGD OpRegion support


 drivers/vfio/pci/Kconfig            |    4 +
 drivers/vfio/pci/Makefile           |    1 
 drivers/vfio/pci/vfio_pci.c         |  159 ++++++++++++++++++++++++++++++++++-
 drivers/vfio/pci/vfio_pci_config.c  |   34 +++++++
 drivers/vfio/pci/vfio_pci_igd.c     |  117 ++++++++++++++++++++++++++
 drivers/vfio/pci/vfio_pci_private.h |   39 +++++++++
 drivers/vfio/vfio.c                 |   54 ++++++++++++
 include/linux/vfio.h                |   11 ++
 include/uapi/linux/vfio.h           |   89 +++++++++++++++++++-
 9 files changed, 497 insertions(+), 11 deletions(-)
 create mode 100644 drivers/vfio/pci/vfio_pci_igd.c

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

* [PATCH 1/8] vfio: Define capability chains
  2016-02-02  0:24 [PATCH 0/8] vfio: capability chains, sparse mmaps, device specific regions, IGD OpRegions Alex Williamson
@ 2016-02-02  0:24 ` Alex Williamson
  2016-02-02  0:24 ` [PATCH 2/8] vfio: Add capability chain helpers Alex Williamson
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Alex Williamson @ 2016-02-02  0:24 UTC (permalink / raw)
  To: alex.williamson; +Cc: linux-kernel, kvm, kraxel

We have a few cases where we need to extend the data returned from the
INFO ioctls in VFIO.  For instance we already have devices exposed
through vfio-pci where VFIO_DEVICE_GET_REGION_INFO reports the region
as mmap-capable, but really only supports sparse mmaps, avoiding the
MSI-X table.  If we wanted to provide in-kernel emulation or extended
functionality for devices, we'd also want the ability to tell the
user not to mmap various regions, rather than forcing them to figure
it out on their own.

Another example is VFIO_IOMMU_GET_INFO.  We'd really like to expose
the actual IOVA capabilities of the IOMMU rather than letting the
user assume the address space they have available to them.  We could
add IOVA base and size fields to struct vfio_iommu_type1_info, but
what if we have multiple IOVA ranges.  For instance x86 uses a range
of addresses at 0xfee00000 for MSI vectors.  These typically are not
available for standard DMA IOVA mappings and splits our available IOVA
space into two ranges.  POWER systems have both an IOVA window below
4G as well as dynamic data window which they can use to remap all of
guest memory.

Representing variable sized arrays within a fixed structure makes it
very difficult to parse, we'd therefore like to put this data beyond
fixed fields within the data structures.  One way to do this is to
emulate capabilities in PCI configuration space.  A new flag indciates
whether capabilties are supported and a new fixed field reports the
offset of the first entry.  Users can then walk the chain to find
capabilities, adding capabilities does not require additional fields
in the fixed structure, and parsing variable sized data becomes
trivial.

This patch outlines the theory and base header structure, which
should be shared by all future users.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
 include/uapi/linux/vfio.h |   27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 7d7a4c6..d508adf 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -59,6 +59,33 @@
 #define VFIO_TYPE	(';')
 #define VFIO_BASE	100
 
+/*
+ * For extension of INFO ioctls, VFIO makes use of a capability chain
+ * designed after PCI/e capabilities.  A flag bit indicates whether
+ * this capability chain is supported and a field defined in the fixed
+ * structure defines the offset of the first capability in the chain.
+ * This field is only valid when the corresponding bit in the flags
+ * bitmap is set.  This offset field is relative to the start of the
+ * INFO buffer, as is the next field within each capability header.
+ * The id within the header is a shared address space per INFO ioctl,
+ * while the version field is specific to the capability id.  The
+ * contents following the header are specific to the capability id.
+ */
+struct vfio_info_cap_header {
+	__u16	id;		/* Identifies capability */
+	__u16	version;	/* Version specific to the capability ID */
+	__u32	next;		/* Offset of next capability */
+};
+
+/*
+ * Callers of INFO ioctls passing insufficiently sized buffers will see
+ * the capability chain flag bit set, a zero value for the first capability
+ * offset (if available within the provided argsz), and argsz will be
+ * updated to report the necessary buffer size.  For compatibility, the
+ * INFO ioctl will not report error in this case, but the capability chain
+ * will not be available.
+ */
+
 /* -------- IOCTLs for VFIO file descriptor (/dev/vfio/vfio) -------- */
 
 /**

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

* [PATCH 2/8] vfio: Add capability chain helpers
  2016-02-02  0:24 [PATCH 0/8] vfio: capability chains, sparse mmaps, device specific regions, IGD OpRegions Alex Williamson
  2016-02-02  0:24 ` [PATCH 1/8] vfio: Define capability chains Alex Williamson
@ 2016-02-02  0:24 ` Alex Williamson
  2016-02-02  0:24 ` [PATCH 3/8] vfio: Define sparse mmap capability for regions Alex Williamson
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Alex Williamson @ 2016-02-02  0:24 UTC (permalink / raw)
  To: alex.williamson; +Cc: linux-kernel, kvm, kraxel

Allow sub-modules to easily reallocate a buffer for managing
capability chains for info ioctls.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
 drivers/vfio/vfio.c  |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/vfio.h |   11 ++++++++++
 2 files changed, 65 insertions(+)

diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 4cc961b..6fd6fa5 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -1729,6 +1729,60 @@ long vfio_external_check_extension(struct vfio_group *group, unsigned long arg)
 EXPORT_SYMBOL_GPL(vfio_external_check_extension);
 
 /**
+ * Sub-module support
+ */
+/*
+ * Helper for managing a buffer of info chain capabilities, allocate or
+ * reallocate a buffer with additional @size, filling in @id and @version
+ * of the capability.  A pointer to the new capability is returned.
+ *
+ * NB. The chain is based at the head of the buffer, so new entries are
+ * added to the tail, vfio_info_cap_shift() should be called to fixup the
+ * next offsets prior to copying to the user buffer.
+ */
+struct vfio_info_cap_header *vfio_info_cap_add(struct vfio_info_cap *caps,
+					       size_t size, u16 id, u16 version)
+{
+	void *buf;
+	struct vfio_info_cap_header *header, *tmp;
+
+	buf = krealloc(caps->buf, caps->size + size, GFP_KERNEL);
+	if (!buf) {
+		kfree(caps->buf);
+		caps->size = 0;
+		return ERR_PTR(-ENOMEM);
+	}
+
+	caps->buf = buf;
+	header = buf + caps->size;
+
+	/* Eventually copied to user buffer, zero */
+	memset(header, 0, size);
+
+	header->id = id;
+	header->version = version;
+
+	/* Add to the end of the capability chain */
+	for (tmp = caps->buf; tmp->next; tmp = (void *)tmp + tmp->next)
+		; /* nothing */
+
+	tmp->next = caps->size;
+	caps->size += size;
+
+	return header;
+}
+EXPORT_SYMBOL_GPL(vfio_info_cap_add);
+
+void vfio_info_cap_shift(struct vfio_info_cap *caps, size_t offset)
+{
+	struct vfio_info_cap_header *tmp;
+
+	for (tmp = caps->buf; tmp->next; tmp = (void *)tmp + tmp->next - offset)
+		tmp->next += offset;
+}
+EXPORT_SYMBOL_GPL(vfio_info_cap_shift);
+
+/**
  * Module/class support
  */
 static char *vfio_devnode(struct device *dev, umode_t *mode)
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 610a86a..0ecae0b 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -92,6 +92,17 @@ extern int vfio_external_user_iommu_id(struct vfio_group *group);
 extern long vfio_external_check_extension(struct vfio_group *group,
 					  unsigned long arg);
 
+/*
+ * Sub-module helpers
+ */
+struct vfio_info_cap {
+	struct vfio_info_cap_header *buf;
+	size_t size;
+};
+extern struct vfio_info_cap_header *vfio_info_cap_add(
+		struct vfio_info_cap *caps, size_t size, u16 id, u16 version);
+extern void vfio_info_cap_shift(struct vfio_info_cap *caps, size_t offset);
+
 struct pci_dev;
 #ifdef CONFIG_EEH
 extern void vfio_spapr_pci_eeh_open(struct pci_dev *pdev);

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

* [PATCH 3/8] vfio: Define sparse mmap capability for regions
  2016-02-02  0:24 [PATCH 0/8] vfio: capability chains, sparse mmaps, device specific regions, IGD OpRegions Alex Williamson
  2016-02-02  0:24 ` [PATCH 1/8] vfio: Define capability chains Alex Williamson
  2016-02-02  0:24 ` [PATCH 2/8] vfio: Add capability chain helpers Alex Williamson
@ 2016-02-02  0:24 ` Alex Williamson
  2016-02-02  0:24 ` [PATCH 4/8] vfio/pci: Include sparse mmap capability for MSI-X table regions Alex Williamson
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Alex Williamson @ 2016-02-02  0:24 UTC (permalink / raw)
  To: alex.williamson; +Cc: linux-kernel, kvm, kraxel

We can't always support mmap across an entire device region, for
example we deny mmaps covering the MSI-X table of PCI devices, but
we don't really have a way to report it.  We expect the user to
implicitly know this restriction.  We also can't split the region
because vfio-pci defines an API with fixed region index to BAR
number mapping.  We therefore define a new capability which lists
areas within the region that may be mmap'd.  In addition to the
MSI-X case, this potentially enables in-kernel emulation and
extensions to devices.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
 include/uapi/linux/vfio.h |   26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index d508adf..fde7b1e 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -221,13 +221,37 @@ struct vfio_region_info {
 #define VFIO_REGION_INFO_FLAG_READ	(1 << 0) /* Region supports read */
 #define VFIO_REGION_INFO_FLAG_WRITE	(1 << 1) /* Region supports write */
 #define VFIO_REGION_INFO_FLAG_MMAP	(1 << 2) /* Region supports mmap */
+#define VFIO_REGION_INFO_FLAG_CAPS	(1 << 3) /* Info supports caps */
 	__u32	index;		/* Region index */
-	__u32	resv;		/* Reserved for alignment */
+	__u32	cap_offset;	/* Offset within info struct of first cap */
 	__u64	size;		/* Region size (bytes) */
 	__u64	offset;		/* Region offset from start of device fd */
 };
 #define VFIO_DEVICE_GET_REGION_INFO	_IO(VFIO_TYPE, VFIO_BASE + 8)
 
+/*
+ * The sparse mmap capability allows finer granularity of specifying areas
+ * within a region with mmap support.  When specified, the user should only
+ * mmap the offset ranges specified by the areas array.  mmaps outside of the
+ * areas specified may fail (such as the range covering a PCI MSI-X table) or
+ * may result in improper device behavior.
+ *
+ * The structures below define version 1 of this capability.
+ */
+#define VFIO_REGION_INFO_CAP_SPARSE_MMAP	1
+
+struct vfio_region_sparse_mmap_area {
+	__u64	offset;	/* Offset of mmap'able area within region */
+	__u64	size;	/* Size of mmap'able area */
+};
+
+struct vfio_region_info_cap_sparse_mmap {
+	struct vfio_info_cap_header header;
+	__u32	nr_areas;
+	__u32	reserved;
+	struct vfio_region_sparse_mmap_area areas[];
+};
+
 /**
  * VFIO_DEVICE_GET_IRQ_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 9,
  *				    struct vfio_irq_info)

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

* [PATCH 4/8] vfio/pci: Include sparse mmap capability for MSI-X table regions
  2016-02-02  0:24 [PATCH 0/8] vfio: capability chains, sparse mmaps, device specific regions, IGD OpRegions Alex Williamson
                   ` (2 preceding siblings ...)
  2016-02-02  0:24 ` [PATCH 3/8] vfio: Define sparse mmap capability for regions Alex Williamson
@ 2016-02-02  0:24 ` Alex Williamson
  2016-02-02  0:24 ` [PATCH 5/8] vfio: Define device specific region type capability Alex Williamson
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Alex Williamson @ 2016-02-02  0:24 UTC (permalink / raw)
  To: alex.williamson; +Cc: linux-kernel, kvm, kraxel

vfio-pci has never allowed the user to directly mmap the MSI-X vector
table, but we've always relied on implicit knowledge of the user that
they cannot do this.  Now that we have capability chains that we can
expose in the region info ioctl and a sparse mmap capability that
represents the sub-areas within the region that can be mmap'd, we can
make the mmap constraints more explicit.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
 drivers/vfio/pci/vfio_pci.c |   73 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 72 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 2760a7b..4682207 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -421,6 +421,48 @@ static int vfio_pci_for_each_slot_or_bus(struct pci_dev *pdev,
 	return walk.ret;
 }
 
+static int msix_sparse_mmap_cap(struct vfio_pci_device *vdev,
+				struct vfio_info_cap *caps)
+{
+	struct vfio_info_cap_header *header;
+	struct vfio_region_info_cap_sparse_mmap *sparse;
+	size_t end, size;
+	int nr_areas = 2, i = 0;
+
+	end = pci_resource_len(vdev->pdev, vdev->msix_bar);
+
+	/* If MSI-X table is aligned to the start or end, only one area */
+	if (((vdev->msix_offset & PAGE_MASK) == 0) ||
+	    (PAGE_ALIGN(vdev->msix_offset + vdev->msix_size) >= end))
+		nr_areas = 1;
+
+	size = sizeof(*sparse) + (nr_areas * sizeof(*sparse->areas));
+
+	header = vfio_info_cap_add(caps, size,
+				   VFIO_REGION_INFO_CAP_SPARSE_MMAP, 1);
+	if (IS_ERR(header))
+		return PTR_ERR(header);
+
+	sparse = container_of(header,
+			      struct vfio_region_info_cap_sparse_mmap, header);
+	sparse->nr_areas = nr_areas;
+
+	if (vdev->msix_offset & PAGE_MASK) {
+		sparse->areas[i].offset = 0;
+		sparse->areas[i].size = vdev->msix_offset & PAGE_MASK;
+		i++;
+	}
+
+	if (PAGE_ALIGN(vdev->msix_offset + vdev->msix_size) < end) {
+		sparse->areas[i].offset = PAGE_ALIGN(vdev->msix_offset +
+						     vdev->msix_size);
+		sparse->areas[i].size = end - sparse->areas[i].offset;
+		i++;
+	}
+
+	return 0;
+}
+
 static long vfio_pci_ioctl(void *device_data,
 			   unsigned int cmd, unsigned long arg)
 {
@@ -451,6 +493,8 @@ static long vfio_pci_ioctl(void *device_data,
 	} else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
 		struct pci_dev *pdev = vdev->pdev;
 		struct vfio_region_info info;
+		struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
+		int ret;
 
 		minsz = offsetofend(struct vfio_region_info, offset);
 
@@ -479,8 +523,15 @@ static long vfio_pci_ioctl(void *device_data,
 				     VFIO_REGION_INFO_FLAG_WRITE;
 			if (IS_ENABLED(CONFIG_VFIO_PCI_MMAP) &&
 			    pci_resource_flags(pdev, info.index) &
-			    IORESOURCE_MEM && info.size >= PAGE_SIZE)
+			    IORESOURCE_MEM && info.size >= PAGE_SIZE) {
 				info.flags |= VFIO_REGION_INFO_FLAG_MMAP;
+				if (info.index == vdev->msix_bar) {
+					ret = msix_sparse_mmap_cap(vdev, &caps);
+					if (ret)
+						return ret;
+				}
+			}
+
 			break;
 		case VFIO_PCI_ROM_REGION_INDEX:
 		{
@@ -520,6 +571,26 @@ static long vfio_pci_ioctl(void *device_data,
 			return -EINVAL;
 		}
 
+		if (caps.size) {
+			info.flags |= VFIO_REGION_INFO_FLAG_CAPS;
+			if (info.argsz < sizeof(info) + caps.size) {
+				info.argsz = sizeof(info) + caps.size;
+				info.cap_offset = 0;
+			} else {
+				vfio_info_cap_shift(&caps, sizeof(info));
+				ret = copy_to_user((void __user *)arg +
+						   sizeof(info), caps.buf,
+						   caps.size);
+				if (ret) {
+					kfree(caps.buf);
+					return ret;
+				}
+				info.cap_offset = sizeof(info);
+			}
+
+			kfree(caps.buf);
+		}
+
 		return copy_to_user((void __user *)arg, &info, minsz);
 
 	} else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {

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

* [PATCH 5/8] vfio: Define device specific region type capability
  2016-02-02  0:24 [PATCH 0/8] vfio: capability chains, sparse mmaps, device specific regions, IGD OpRegions Alex Williamson
                   ` (3 preceding siblings ...)
  2016-02-02  0:24 ` [PATCH 4/8] vfio/pci: Include sparse mmap capability for MSI-X table regions Alex Williamson
@ 2016-02-02  0:24 ` Alex Williamson
  2016-02-02  0:24 ` [PATCH 6/8] vfio/pci: Add infrastructure for additional device specific regions Alex Williamson
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Alex Williamson @ 2016-02-02  0:24 UTC (permalink / raw)
  To: alex.williamson; +Cc: linux-kernel, kvm, kraxel

To this point vfio has only provided an interface to the user that
allows them to determine the number of regions and specifics about
each region.  What the region represents is left to the vfio bus
driver.  vfio-pci chooses to use fixed indexes for fixed resources,
index 0 is BAR0, 1 is BAR1,... 7 is config space, etc.  This works
pretty well since all PCI devices have these regions, even if they
don't necessarily populate all of them.  Then we start to add things
like VGA, which only certain device even support.  We added this the
same way, but now we've wasted a region index, and due to our offset
implementation the corresponding address space, for all devices.

Rather than continuing that process, let's try to make regions self
describing by including a capability that defines their type.  For
vfio-pci we'll make the current VFIO_PCI_NUM_REGIONS fixed, defining
the end of the static indexes and the beginning of self describing
regions.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
 include/uapi/linux/vfio.h |   31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index fde7b1e..1c37a0e 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -252,6 +252,34 @@ struct vfio_region_info_cap_sparse_mmap {
 	struct vfio_region_sparse_mmap_area areas[];
 };
 
+/*
+ * The device specific type capability allows regions unique to a specific
+ * device or class of devices to be exposed.  This helps solve the problem for
+ * vfio bus drivers of defining which region indexes correspond to which region
+ * on the device, without needing to resort to static indexes, as done by
+ * vfio-pci.  For instance, if we were to go back in time, we might remove
+ * VFIO_PCI_VGA_REGION_INDEX and let vfio-pci simply define that all indexes
+ * greater than or equal to VFIO_PCI_NUM_REGIONS are device specific and we'd
+ * make a "VGA" device specific type to describe the VGA access space.  This
+ * means that non-VGA devices wouldn't need to waste this index, and thus the
+ * address space associated with it due to implementation of device file
+ * descriptor offsets in vfio-pci.
+ *
+ * The current implementation is now part of the user ABI, so we can't use this
+ * for VGA, but there are other upcoming use cases, such as opregions for Intel
+ * IGD devices and framebuffers for vGPU devices.  We missed VGA, but we'll
+ * use this for future additions.
+ *
+ * The structure below defines version 1 of this capability.
+ */
+#define VFIO_REGION_INFO_CAP_TYPE	2
+
+struct vfio_region_info_cap_type {
+	struct vfio_info_cap_header header;
+	__u32 type;	/* global per bus driver */
+	__u32 subtype;	/* type specific */
+};
+
 /**
  * VFIO_DEVICE_GET_IRQ_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 9,
  *				    struct vfio_irq_info)
@@ -387,7 +415,8 @@ enum {
 	 * between described ranges are unimplemented.
 	 */
 	VFIO_PCI_VGA_REGION_INDEX,
-	VFIO_PCI_NUM_REGIONS
+	VFIO_PCI_NUM_REGIONS = 9 /* Fixed user ABI, region indexes >=9 use */
+				 /* device specific cap to define content. */
 };
 
 enum {

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

* [PATCH 6/8] vfio/pci: Add infrastructure for additional device specific regions
  2016-02-02  0:24 [PATCH 0/8] vfio: capability chains, sparse mmaps, device specific regions, IGD OpRegions Alex Williamson
                   ` (4 preceding siblings ...)
  2016-02-02  0:24 ` [PATCH 5/8] vfio: Define device specific region type capability Alex Williamson
@ 2016-02-02  0:24 ` Alex Williamson
  2016-02-02  0:24 ` [PATCH 7/8] vfio/pci: Enable virtual register in PCI config space Alex Williamson
  2016-02-02  0:24 ` [PATCH 8/8] vfio/pci: Intel IGD OpRegion support Alex Williamson
  7 siblings, 0 replies; 9+ messages in thread
From: Alex Williamson @ 2016-02-02  0:24 UTC (permalink / raw)
  To: alex.williamson; +Cc: linux-kernel, kvm, kraxel

Add support for additional regions with indexes started after the
already defined fixed regions.  Device specific code can register
these regions with the new vfio_pci_register_dev_region() function.
The ops structure per region currently only includes read/write
access and a release function, allowing automatic cleanup when the
device is closed.  mmap support is only missing here because it's
not needed by the first user queued for this support.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
 drivers/vfio/pci/vfio_pci.c         |   81 +++++++++++++++++++++++++++++++++--
 drivers/vfio/pci/vfio_pci_private.h |   27 ++++++++++++
 2 files changed, 103 insertions(+), 5 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 4682207..813a2e6 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -175,7 +175,7 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
 static void vfio_pci_disable(struct vfio_pci_device *vdev)
 {
 	struct pci_dev *pdev = vdev->pdev;
-	int bar;
+	int i, bar;
 
 	/* Stop the device from further DMA */
 	pci_clear_master(pdev);
@@ -186,6 +186,13 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
 
 	vdev->virq_disabled = false;
 
+	for (i = 0; i < vdev->num_regions; i++)
+		vdev->region[i].ops->release(vdev, &vdev->region[i]);
+
+	vdev->num_regions = 0;
+	kfree(vdev->region);
+	vdev->region = NULL; /* don't krealloc a freed pointer */
+
 	vfio_config_free(vdev);
 
 	for (bar = PCI_STD_RESOURCES; bar <= PCI_STD_RESOURCE_END; bar++) {
@@ -463,6 +470,51 @@ static int msix_sparse_mmap_cap(struct vfio_pci_device *vdev,
 	return 0;
 }
 
+static int region_type_cap(struct vfio_pci_device *vdev,
+			   struct vfio_info_cap *caps,
+			   unsigned int type, unsigned int subtype)
+{
+	struct vfio_info_cap_header *header;
+	struct vfio_region_info_cap_type *cap;
+
+	header = vfio_info_cap_add(caps, sizeof(*cap),
+				   VFIO_REGION_INFO_CAP_TYPE, 1);
+	if (IS_ERR(header))
+		return PTR_ERR(header);
+
+	cap = container_of(header, struct vfio_region_info_cap_type, header);
+	cap->type = type;
+	cap->subtype = subtype;
+
+	return 0;
+}
+
+int vfio_pci_register_dev_region(struct vfio_pci_device *vdev,
+				 unsigned int type, unsigned int subtype,
+				 const struct vfio_pci_regops *ops,
+				 size_t size, u32 flags, void *data)
+{
+	struct vfio_pci_region *region;
+
+	region = krealloc(vdev->region,
+			  (vdev->num_regions + 1) * sizeof(*region),
+			  GFP_KERNEL);
+	if (!region)
+		return -ENOMEM;
+
+	vdev->region = region;
+	vdev->region[vdev->num_regions].type = type;
+	vdev->region[vdev->num_regions].subtype = subtype;
+	vdev->region[vdev->num_regions].ops = ops;
+	vdev->region[vdev->num_regions].size = size;
+	vdev->region[vdev->num_regions].flags = flags;
+	vdev->region[vdev->num_regions].data = data;
+
+	vdev->num_regions++;
+
+	return 0;
+}
+
 static long vfio_pci_ioctl(void *device_data,
 			   unsigned int cmd, unsigned long arg)
 {
@@ -485,7 +537,7 @@ static long vfio_pci_ioctl(void *device_data,
 		if (vdev->reset_works)
 			info.flags |= VFIO_DEVICE_FLAGS_RESET;
 
-		info.num_regions = VFIO_PCI_NUM_REGIONS;
+		info.num_regions = VFIO_PCI_NUM_REGIONS + vdev->num_regions;
 		info.num_irqs = VFIO_PCI_NUM_IRQS;
 
 		return copy_to_user((void __user *)arg, &info, minsz);
@@ -494,7 +546,7 @@ static long vfio_pci_ioctl(void *device_data,
 		struct pci_dev *pdev = vdev->pdev;
 		struct vfio_region_info info;
 		struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
-		int ret;
+		int i, ret;
 
 		minsz = offsetofend(struct vfio_region_info, offset);
 
@@ -568,7 +620,21 @@ static long vfio_pci_ioctl(void *device_data,
 
 			break;
 		default:
-			return -EINVAL;
+			if (info.index >=
+			    VFIO_PCI_NUM_REGIONS + vdev->num_regions)
+				return -EINVAL;
+
+			i = info.index - VFIO_PCI_NUM_REGIONS;
+
+			info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
+			info.size = vdev->region[i].size;
+			info.flags = vdev->region[i].flags;
+
+			ret = region_type_cap(vdev, &caps,
+					      vdev->region[i].type,
+					      vdev->region[i].subtype);
+			if (ret)
+				return ret;
 		}
 
 		if (caps.size) {
@@ -866,7 +932,7 @@ static ssize_t vfio_pci_rw(void *device_data, char __user *buf,
 	unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos);
 	struct vfio_pci_device *vdev = device_data;
 
-	if (index >= VFIO_PCI_NUM_REGIONS)
+	if (index >= VFIO_PCI_NUM_REGIONS + vdev->num_regions)
 		return -EINVAL;
 
 	switch (index) {
@@ -883,6 +949,10 @@ static ssize_t vfio_pci_rw(void *device_data, char __user *buf,
 
 	case VFIO_PCI_VGA_REGION_INDEX:
 		return vfio_pci_vga_rw(vdev, buf, count, ppos, iswrite);
+	default:
+		index -= VFIO_PCI_NUM_REGIONS;
+		return vdev->region[index].ops->rw(vdev, buf,
+						   count, ppos, iswrite);
 	}
 
 	return -EINVAL;
@@ -1065,6 +1135,7 @@ static void vfio_pci_remove(struct pci_dev *pdev)
 		return;
 
 	vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev);
+	kfree(vdev->region);
 	kfree(vdev);
 
 	if (vfio_pci_is_vga(pdev)) {
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h
index 0e7394f..0710bda 100644
--- a/drivers/vfio/pci/vfio_pci_private.h
+++ b/drivers/vfio/pci/vfio_pci_private.h
@@ -14,6 +14,7 @@
 #include <linux/mutex.h>
 #include <linux/pci.h>
 #include <linux/irqbypass.h>
+#include <linux/types.h>
 
 #ifndef VFIO_PCI_PRIVATE_H
 #define VFIO_PCI_PRIVATE_H
@@ -33,6 +34,25 @@ struct vfio_pci_irq_ctx {
 	struct irq_bypass_producer	producer;
 };
 
+struct vfio_pci_device;
+struct vfio_pci_region;
+
+struct vfio_pci_regops {
+	size_t	(*rw)(struct vfio_pci_device *vdev, char __user *buf,
+		      size_t count, loff_t *ppos, bool iswrite);
+	void	(*release)(struct vfio_pci_device *vdev,
+			   struct vfio_pci_region *region);
+};
+
+struct vfio_pci_region {
+	u32				type;
+	u32				subtype;
+	const struct vfio_pci_regops	*ops;
+	void				*data;
+	size_t				size;
+	u32				flags;
+};
+
 struct vfio_pci_device {
 	struct pci_dev		*pdev;
 	void __iomem		*barmap[PCI_STD_RESOURCE_END + 1];
@@ -45,6 +65,8 @@ struct vfio_pci_device {
 	struct vfio_pci_irq_ctx	*ctx;
 	int			num_ctx;
 	int			irq_type;
+	int			num_regions;
+	struct vfio_pci_region	*region;
 	u8			msi_qmax;
 	u8			msix_bar;
 	u16			msix_size;
@@ -91,4 +113,9 @@ extern void vfio_pci_uninit_perm_bits(void);
 
 extern int vfio_config_init(struct vfio_pci_device *vdev);
 extern void vfio_config_free(struct vfio_pci_device *vdev);
+
+extern int vfio_pci_register_dev_region(struct vfio_pci_device *vdev,
+					unsigned int type, unsigned int subtype,
+					const struct vfio_pci_regops *ops,
+					size_t size, u32 flags, void *data);
 #endif /* VFIO_PCI_PRIVATE_H */

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

* [PATCH 7/8] vfio/pci: Enable virtual register in PCI config space
  2016-02-02  0:24 [PATCH 0/8] vfio: capability chains, sparse mmaps, device specific regions, IGD OpRegions Alex Williamson
                   ` (5 preceding siblings ...)
  2016-02-02  0:24 ` [PATCH 6/8] vfio/pci: Add infrastructure for additional device specific regions Alex Williamson
@ 2016-02-02  0:24 ` Alex Williamson
  2016-02-02  0:24 ` [PATCH 8/8] vfio/pci: Intel IGD OpRegion support Alex Williamson
  7 siblings, 0 replies; 9+ messages in thread
From: Alex Williamson @ 2016-02-02  0:24 UTC (permalink / raw)
  To: alex.williamson; +Cc: linux-kernel, kvm, kraxel

Typically config space for a device is mapped out into capability
specific handlers and unassigned space.  The latter allows direct
read/write access to config space.  Sometimes we know about registers
living in this void space and would like an easy way to virtualize
them, similar to how BAR registers are managed.  To do this, create
one more pseudo (fake) PCI capability to be handled as purely virtual
space.  Reads and writes are serviced entirely from virtual config
space.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
 drivers/vfio/pci/vfio_pci_config.c  |   34 ++++++++++++++++++++++++++++++----
 drivers/vfio/pci/vfio_pci_private.h |    4 ++++
 2 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
index fe2b470..88dc646 100644
--- a/drivers/vfio/pci/vfio_pci_config.c
+++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -33,9 +33,8 @@
 
 #define PCI_CFG_SPACE_SIZE	256
 
-/* Useful "pseudo" capabilities */
+/* Fake capability ID for standard config space */
 #define PCI_CAP_ID_BASIC	0
-#define PCI_CAP_ID_INVALID	0xFF
 
 #define is_bar(offset)	\
 	((offset >= PCI_BASE_ADDRESS_0 && offset < PCI_BASE_ADDRESS_5 + 4) || \
@@ -301,6 +300,23 @@ static int vfio_raw_config_read(struct vfio_pci_device *vdev, int pos,
 	return count;
 }
 
+/* Virt access uses only virtualization */
+static int vfio_virt_config_write(struct vfio_pci_device *vdev, int pos,
+				  int count, struct perm_bits *perm,
+				  int offset, __le32 val)
+{
+	memcpy(vdev->vconfig + pos, &val, count);
+	return count;
+}
+
+static int vfio_virt_config_read(struct vfio_pci_device *vdev, int pos,
+				 int count, struct perm_bits *perm,
+				 int offset, __le32 *val)
+{
+	memcpy(val, vdev->vconfig + pos, count);
+	return count;
+}
+
 /* Default capability regions to read-only, no-virtualization */
 static struct perm_bits cap_perms[PCI_CAP_ID_MAX + 1] = {
 	[0 ... PCI_CAP_ID_MAX] = { .readfn = vfio_direct_config_read }
@@ -319,6 +335,11 @@ static struct perm_bits unassigned_perms = {
 	.writefn = vfio_raw_config_write
 };
 
+static struct perm_bits virt_perms = {
+	.readfn = vfio_virt_config_read,
+	.writefn = vfio_virt_config_write
+};
+
 static void free_perm_bits(struct perm_bits *perm)
 {
 	kfree(perm->virt);
@@ -1332,6 +1353,8 @@ static int vfio_cap_init(struct vfio_pci_device *vdev)
 				pos + i, map[pos + i], cap);
 		}
 
+		BUILD_BUG_ON(PCI_CAP_ID_MAX >= PCI_CAP_ID_INVALID_VIRT);
+
 		memset(map + pos, cap, len);
 		ret = vfio_fill_vconfig_bytes(vdev, pos, len);
 		if (ret)
@@ -1419,9 +1442,9 @@ static int vfio_ecap_init(struct vfio_pci_device *vdev)
 		/*
 		 * Even though ecap is 2 bytes, we're currently a long way
 		 * from exceeding 1 byte capabilities.  If we ever make it
-		 * up to 0xFF we'll need to up this to a two-byte, byte map.
+		 * up to 0xFE we'll need to up this to a two-byte, byte map.
 		 */
-		BUILD_BUG_ON(PCI_EXT_CAP_ID_MAX >= PCI_CAP_ID_INVALID);
+		BUILD_BUG_ON(PCI_EXT_CAP_ID_MAX >= PCI_CAP_ID_INVALID_VIRT);
 
 		memset(map + epos, ecap, len);
 		ret = vfio_fill_vconfig_bytes(vdev, epos, len);
@@ -1597,6 +1620,9 @@ static ssize_t vfio_config_do_rw(struct vfio_pci_device *vdev, char __user *buf,
 	if (cap_id == PCI_CAP_ID_INVALID) {
 		perm = &unassigned_perms;
 		cap_start = *ppos;
+	} else if (cap_id == PCI_CAP_ID_INVALID_VIRT) {
+		perm = &virt_perms;
+		cap_start = *ppos;
 	} else {
 		if (*ppos >= PCI_CFG_SPACE_SIZE) {
 			WARN_ON(cap_id > PCI_EXT_CAP_ID_MAX);
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h
index 0710bda..b1e4032 100644
--- a/drivers/vfio/pci/vfio_pci_private.h
+++ b/drivers/vfio/pci/vfio_pci_private.h
@@ -25,6 +25,10 @@
 #define VFIO_PCI_INDEX_TO_OFFSET(index)	((u64)(index) << VFIO_PCI_OFFSET_SHIFT)
 #define VFIO_PCI_OFFSET_MASK	(((u64)(1) << VFIO_PCI_OFFSET_SHIFT) - 1)
 
+/* Special capability IDs predefined access */
+#define PCI_CAP_ID_INVALID		0xFF	/* default raw access */
+#define PCI_CAP_ID_INVALID_VIRT		0xFE	/* default virt access */
+
 struct vfio_pci_irq_ctx {
 	struct eventfd_ctx	*trigger;
 	struct virqfd		*unmask;

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

* [PATCH 8/8] vfio/pci: Intel IGD OpRegion support
  2016-02-02  0:24 [PATCH 0/8] vfio: capability chains, sparse mmaps, device specific regions, IGD OpRegions Alex Williamson
                   ` (6 preceding siblings ...)
  2016-02-02  0:24 ` [PATCH 7/8] vfio/pci: Enable virtual register in PCI config space Alex Williamson
@ 2016-02-02  0:24 ` Alex Williamson
  7 siblings, 0 replies; 9+ messages in thread
From: Alex Williamson @ 2016-02-02  0:24 UTC (permalink / raw)
  To: alex.williamson; +Cc: linux-kernel, kvm, kraxel

This is the first consumer of vfio device specific resource support,
providing read-write access to the OpRegion for Intel graphics devices.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
 drivers/vfio/pci/Kconfig            |    4 +
 drivers/vfio/pci/Makefile           |    1 
 drivers/vfio/pci/vfio_pci.c         |    7 ++
 drivers/vfio/pci/vfio_pci_igd.c     |  117 +++++++++++++++++++++++++++++++++++
 drivers/vfio/pci/vfio_pci_private.h |    8 ++
 include/uapi/linux/vfio.h           |    5 +
 6 files changed, 142 insertions(+)
 create mode 100644 drivers/vfio/pci/vfio_pci_igd.c

diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig
index 02912f1..24ee260 100644
--- a/drivers/vfio/pci/Kconfig
+++ b/drivers/vfio/pci/Kconfig
@@ -26,3 +26,7 @@ config VFIO_PCI_MMAP
 config VFIO_PCI_INTX
 	depends on VFIO_PCI
 	def_bool y if !S390
+
+config VFIO_PCI_IGD
+	depends on VFIO_PCI
+	def_bool y if X86
diff --git a/drivers/vfio/pci/Makefile b/drivers/vfio/pci/Makefile
index 1310792..76d8ec0 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-$(CONFIG_VFIO_PCI_IGD) += vfio_pci_igd.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 813a2e6..cb2624d 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -169,6 +169,13 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
 	if (!vfio_vga_disabled() && vfio_pci_is_vga(pdev))
 		vdev->has_vga = true;
 
+
+	if (vfio_pci_is_vga(pdev) && pdev->vendor == PCI_VENDOR_ID_INTEL) {
+		if (vfio_pci_igd_opregion_init(vdev) == 0)
+			dev_info(&pdev->dev,
+				 "Intel IGD OpRegion support enabled\n");
+	}
+
 	return 0;
 }
 
diff --git a/drivers/vfio/pci/vfio_pci_igd.c b/drivers/vfio/pci/vfio_pci_igd.c
new file mode 100644
index 0000000..4ab4c9a
--- /dev/null
+++ b/drivers/vfio/pci/vfio_pci_igd.c
@@ -0,0 +1,117 @@
+/*
+ * VFIO PCI Intel Graphics support
+ *
+ * Copyright (C) 2016 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.
+ *
+ * Register a device specific region through which to provide read-only
+ * access to the Intel IGD opregion.  The register defining the opregion
+ * address is also virtualized to prevent user modification.
+ */
+
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <linux/uaccess.h>
+#include <linux/vfio.h>
+
+#include "vfio_pci_private.h"
+
+#define OPREGION_SIGNATURE	"IntelGraphicsMem"
+#define OPREGION_SIZE		(8 * 1024)
+#define OPREGION_PCI_ADDR	0xfc
+
+static size_t vfio_pci_igd_rw(struct vfio_pci_device *vdev, char __user *buf,
+			      size_t count, loff_t *ppos, bool iswrite)
+{
+	unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) - VFIO_PCI_NUM_REGIONS;
+	void *base = vdev->region[i].data;
+	loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
+
+	if (pos >= vdev->region[i].size)
+		return -EINVAL;
+
+	count = min(count, (size_t)(vdev->region[i].size - pos));
+
+	if (iswrite) {
+		if (copy_from_user(base + pos, buf, count))
+			return -EFAULT;
+	} else {
+		if (copy_to_user(buf, base + pos, count))
+			return -EFAULT;
+	}
+
+	*ppos += count;
+
+	return count;
+}
+
+static void vfio_pci_igd_release(struct vfio_pci_device *vdev,
+				 struct vfio_pci_region *region)
+{
+	memunmap(region->data);
+}
+
+static const struct vfio_pci_regops vfio_pci_igd_regops = {
+	.rw		= vfio_pci_igd_rw,
+	.release	= vfio_pci_igd_release,
+};
+
+int vfio_pci_igd_opregion_init(struct vfio_pci_device *vdev)
+{
+	__le32 *dwordp = (__le32 *)(vdev->vconfig + OPREGION_PCI_ADDR);
+	u32 addr, size;
+	void *base;
+	int ret;
+
+	ret = pci_read_config_dword(vdev->pdev, OPREGION_PCI_ADDR, &addr);
+	if (ret)
+		return ret;
+
+	if (!addr || !(~addr))
+		return -ENODEV;
+
+	base = memremap(addr, OPREGION_SIZE, MEMREMAP_WB);
+	if (!base)
+		return -ENOMEM;
+
+	if (memcmp(base, OPREGION_SIGNATURE, 16)) {
+		memunmap(base);
+		return -EINVAL;
+	}
+
+	size = le32_to_cpu(*(__le32 *)(base + 16));
+	if (!size) {
+		memunmap(base);
+		return -EINVAL;
+	}
+
+	size *= 1024; /* In KB */
+
+	if (size != OPREGION_SIZE) {
+		memunmap(base);
+		base = memremap(addr, size, MEMREMAP_WB);
+		if (!base)
+			return -ENOMEM;
+	}
+
+	ret = vfio_pci_register_dev_region(vdev,
+		PCI_VENDOR_ID_INTEL | VFIO_REGION_TYPE_PCI_VENDOR_TYPE,
+		VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION,
+		&vfio_pci_igd_regops, size,
+		VFIO_REGION_INFO_FLAG_READ | VFIO_REGION_INFO_FLAG_WRITE, base);
+	if (ret) {
+		memunmap(base);
+		return ret;
+	}
+
+	/* Fill vconfig with the hw value and virtualize register */
+	*dwordp = cpu_to_le32(addr);
+	memset(vdev->pci_config_map + OPREGION_PCI_ADDR,
+	       PCI_CAP_ID_INVALID_VIRT, 4);
+
+	return ret;
+}
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h
index b1e4032..19f7699 100644
--- a/drivers/vfio/pci/vfio_pci_private.h
+++ b/drivers/vfio/pci/vfio_pci_private.h
@@ -122,4 +122,12 @@ extern int vfio_pci_register_dev_region(struct vfio_pci_device *vdev,
 					unsigned int type, unsigned int subtype,
 					const struct vfio_pci_regops *ops,
 					size_t size, u32 flags, void *data);
+#ifdef CONFIG_VFIO_PCI_IGD
+extern int vfio_pci_igd_opregion_init(struct vfio_pci_device *vdev);
+#else
+static inline int vfio_pci_igd_opregion_init(struct vfio_pci_device *vdev)
+{
+	return -ENODEV;
+}
+#endif
 #endif /* VFIO_PCI_PRIVATE_H */
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 1c37a0e..e622982 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -280,6 +280,11 @@ struct vfio_region_info_cap_type {
 	__u32 subtype;	/* type specific */
 };
 
+#define VFIO_REGION_TYPE_PCI_VENDOR_TYPE	(1 << 31)
+#define VFIO_REGION_TYPE_PCI_VENDOR_MASK	(0xffff)
+
+#define VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION	(1)
+
 /**
  * VFIO_DEVICE_GET_IRQ_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 9,
  *				    struct vfio_irq_info)

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

end of thread, other threads:[~2016-02-02  0:24 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-02  0:24 [PATCH 0/8] vfio: capability chains, sparse mmaps, device specific regions, IGD OpRegions Alex Williamson
2016-02-02  0:24 ` [PATCH 1/8] vfio: Define capability chains Alex Williamson
2016-02-02  0:24 ` [PATCH 2/8] vfio: Add capability chain helpers Alex Williamson
2016-02-02  0:24 ` [PATCH 3/8] vfio: Define sparse mmap capability for regions Alex Williamson
2016-02-02  0:24 ` [PATCH 4/8] vfio/pci: Include sparse mmap capability for MSI-X table regions Alex Williamson
2016-02-02  0:24 ` [PATCH 5/8] vfio: Define device specific region type capability Alex Williamson
2016-02-02  0:24 ` [PATCH 6/8] vfio/pci: Add infrastructure for additional device specific regions Alex Williamson
2016-02-02  0:24 ` [PATCH 7/8] vfio/pci: Enable virtual register in PCI config space Alex Williamson
2016-02-02  0:24 ` [PATCH 8/8] vfio/pci: Intel IGD OpRegion support Alex Williamson

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.