All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g
@ 2017-05-27  8:38 ` Xiaoguang Chen
  0 siblings, 0 replies; 74+ messages in thread
From: Xiaoguang Chen @ 2017-05-27  8:38 UTC (permalink / raw)
  To: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian
  Cc: Xiaoguang Chen

v5->v6:
1) align the dma-buf life cycle with the vfio device.
2) add the dma-buf releated operations in a separate patch.
3) i915 releated changes.

v4->v5:
1) fix bug while checking whether the gem obj is gvt's dma-buf when user
change caching mode or domains. Add a helper function to do it.
2) add definition for the query plane and create dma-buf.

v3->v4:
1) fix bug while checking whether the gem obj is gvt's dma-buf when set
caching mode or doamins.

v2->v3:
1) add a field gvt_plane_info in the drm_i915_gem_obj structure to save
the decoded plane information to avoid look up while need the plane info.
2) declare a new flag I915_GEM_OBJECT_IS_GVT_DMABUF in drm_i915_gem_object
to represent the gem obj for gvt's dma-buf. The tiling mode, caching mode
and domains can not be changed for this kind of gem object.
3) change dma-buf related information to be more generic. So other vendor
can use the same interface.

v1->v2:
1) create a management fd for dma-buf operations.
2) alloc gem object's backing storage in gem obj's get_pages() callback.

This patch set adds the dma-buf support for intel GVT-g.
dma-buf is a uniform mechanism to share DMA buffers across different
devices and sub-systems.
dma-buf for intel GVT-g is mainly used to share the vgpu's framebuffer
to other users or sub-systems so they can use the dma-buf to show the
desktop of a vm which uses intel vgpu.

The main idea is we create a gem object and set vgpu's framebuffer as
the backing storage of this gem object. And associate this gem obj
to a dma-buf object then export this dma-buf at the meantime
generate a file descriptor for this dma-buf. Finally deliver this file
descriptor to user space. And user can use this dma-buf fd to do render
or other operations.
User need to create a fd(for intel GVT-g dma-buf support it is a:dma-buf
management fd) then user can use this fd to query the plane information
or create a dma-buf. The life cycle of this fd is managed by GVT-g user
do not need to care about that.

We have an example program on how to use the dma-buf. You can download
the program to have a try. Good luck :)
git repo: https://github.com/01org/igvtg-qemu branch:kvmgt_dmabuf_example

Xiaoguang Chen (6):
  drm/i915/gvt: Extend the GVT-g architecture to support vfio device
    region
  drm/i915/gvt: OpRegion support for GVT-g
  drm/i915/gvt: Frame buffer decoder support for GVT-g
  vfio: Define vfio based vgpu's dma-buf operations
  drm/i915/gvt: Dmabuf support for GVT-g
  drm/i915/gvt: Adding interface so user space can get the dma-buf

 drivers/gpu/drm/i915/gvt/Makefile      |   3 +-
 drivers/gpu/drm/i915/gvt/display.c     |   2 +-
 drivers/gpu/drm/i915/gvt/display.h     |   2 +
 drivers/gpu/drm/i915/gvt/dmabuf.c      | 281 +++++++++++++++++++
 drivers/gpu/drm/i915/gvt/dmabuf.h      |  42 +++
 drivers/gpu/drm/i915/gvt/fb_decoder.c  | 479 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/fb_decoder.h  | 166 ++++++++++++
 drivers/gpu/drm/i915/gvt/gvt.c         |   2 +
 drivers/gpu/drm/i915/gvt/gvt.h         |   7 +
 drivers/gpu/drm/i915/gvt/kvmgt.c       | 262 +++++++++++++++++-
 drivers/gpu/drm/i915/gvt/opregion.c    |   8 +-
 drivers/gpu/drm/i915/gvt/vgpu.c        |   1 +
 drivers/gpu/drm/i915/i915_gem.c        |  26 +-
 drivers/gpu/drm/i915/i915_gem_object.h |   9 +
 include/uapi/linux/vfio.h              |  50 ++++
 15 files changed, 1333 insertions(+), 7 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gvt/dmabuf.c
 create mode 100644 drivers/gpu/drm/i915/gvt/dmabuf.h
 create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.c
 create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.h

-- 
2.7.4

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

* [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g
@ 2017-05-27  8:38 ` Xiaoguang Chen
  0 siblings, 0 replies; 74+ messages in thread
From: Xiaoguang Chen @ 2017-05-27  8:38 UTC (permalink / raw)
  To: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian
  Cc: Xiaoguang Chen

v5->v6:
1) align the dma-buf life cycle with the vfio device.
2) add the dma-buf releated operations in a separate patch.
3) i915 releated changes.

v4->v5:
1) fix bug while checking whether the gem obj is gvt's dma-buf when user
change caching mode or domains. Add a helper function to do it.
2) add definition for the query plane and create dma-buf.

v3->v4:
1) fix bug while checking whether the gem obj is gvt's dma-buf when set
caching mode or doamins.

v2->v3:
1) add a field gvt_plane_info in the drm_i915_gem_obj structure to save
the decoded plane information to avoid look up while need the plane info.
2) declare a new flag I915_GEM_OBJECT_IS_GVT_DMABUF in drm_i915_gem_object
to represent the gem obj for gvt's dma-buf. The tiling mode, caching mode
and domains can not be changed for this kind of gem object.
3) change dma-buf related information to be more generic. So other vendor
can use the same interface.

v1->v2:
1) create a management fd for dma-buf operations.
2) alloc gem object's backing storage in gem obj's get_pages() callback.

This patch set adds the dma-buf support for intel GVT-g.
dma-buf is a uniform mechanism to share DMA buffers across different
devices and sub-systems.
dma-buf for intel GVT-g is mainly used to share the vgpu's framebuffer
to other users or sub-systems so they can use the dma-buf to show the
desktop of a vm which uses intel vgpu.

The main idea is we create a gem object and set vgpu's framebuffer as
the backing storage of this gem object. And associate this gem obj
to a dma-buf object then export this dma-buf at the meantime
generate a file descriptor for this dma-buf. Finally deliver this file
descriptor to user space. And user can use this dma-buf fd to do render
or other operations.
User need to create a fd(for intel GVT-g dma-buf support it is a:dma-buf
management fd) then user can use this fd to query the plane information
or create a dma-buf. The life cycle of this fd is managed by GVT-g user
do not need to care about that.

We have an example program on how to use the dma-buf. You can download
the program to have a try. Good luck :)
git repo: https://github.com/01org/igvtg-qemu branch:kvmgt_dmabuf_example

Xiaoguang Chen (6):
  drm/i915/gvt: Extend the GVT-g architecture to support vfio device
    region
  drm/i915/gvt: OpRegion support for GVT-g
  drm/i915/gvt: Frame buffer decoder support for GVT-g
  vfio: Define vfio based vgpu's dma-buf operations
  drm/i915/gvt: Dmabuf support for GVT-g
  drm/i915/gvt: Adding interface so user space can get the dma-buf

 drivers/gpu/drm/i915/gvt/Makefile      |   3 +-
 drivers/gpu/drm/i915/gvt/display.c     |   2 +-
 drivers/gpu/drm/i915/gvt/display.h     |   2 +
 drivers/gpu/drm/i915/gvt/dmabuf.c      | 281 +++++++++++++++++++
 drivers/gpu/drm/i915/gvt/dmabuf.h      |  42 +++
 drivers/gpu/drm/i915/gvt/fb_decoder.c  | 479 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/fb_decoder.h  | 166 ++++++++++++
 drivers/gpu/drm/i915/gvt/gvt.c         |   2 +
 drivers/gpu/drm/i915/gvt/gvt.h         |   7 +
 drivers/gpu/drm/i915/gvt/kvmgt.c       | 262 +++++++++++++++++-
 drivers/gpu/drm/i915/gvt/opregion.c    |   8 +-
 drivers/gpu/drm/i915/gvt/vgpu.c        |   1 +
 drivers/gpu/drm/i915/i915_gem.c        |  26 +-
 drivers/gpu/drm/i915/i915_gem_object.h |   9 +
 include/uapi/linux/vfio.h              |  50 ++++
 15 files changed, 1333 insertions(+), 7 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gvt/dmabuf.c
 create mode 100644 drivers/gpu/drm/i915/gvt/dmabuf.h
 create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.c
 create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.h

-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH v6 1/6] drm/i915/gvt: Extend the GVT-g architecture to support vfio device region
  2017-05-27  8:38 ` Xiaoguang Chen
@ 2017-05-27  8:38   ` Xiaoguang Chen
  -1 siblings, 0 replies; 74+ messages in thread
From: Xiaoguang Chen @ 2017-05-27  8:38 UTC (permalink / raw)
  To: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian
  Cc: Xiaoguang Chen

Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
---
 drivers/gpu/drm/i915/gvt/kvmgt.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 1ae0b40..3c6a02b 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -53,11 +53,21 @@ static const struct intel_gvt_ops *intel_gvt_ops;
 #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)
 
+struct vfio_region;
+struct intel_vgpu_regops {
+	size_t (*rw)(struct intel_vgpu *vgpu, char *buf,
+			size_t count, loff_t *ppos, bool iswrite);
+	void (*release)(struct intel_vgpu *vgpu,
+			struct vfio_region *region);
+};
+
 struct vfio_region {
 	u32				type;
 	u32				subtype;
 	size_t				size;
 	u32				flags;
+	const struct intel_vgpu_regops	*ops;
+	void				*data;
 };
 
 struct kvmgt_pgfn {
@@ -642,7 +652,7 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,
 	int ret = -EINVAL;
 
 
-	if (index >= VFIO_PCI_NUM_REGIONS) {
+	if (index >= VFIO_PCI_NUM_REGIONS + vgpu->vdev.num_regions) {
 		gvt_vgpu_err("invalid index: %u\n", index);
 		return -EINVAL;
 	}
@@ -676,8 +686,11 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,
 	case VFIO_PCI_BAR5_REGION_INDEX:
 	case VFIO_PCI_VGA_REGION_INDEX:
 	case VFIO_PCI_ROM_REGION_INDEX:
+		break;
 	default:
-		gvt_vgpu_err("unsupported region: %u\n", index);
+		index -= VFIO_PCI_NUM_REGIONS;
+		return vgpu->vdev.region[index].ops->rw(vgpu, buf, count,
+				ppos, is_write);
 	}
 
 	return ret == 0 ? count : ret;
@@ -940,7 +953,8 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
 
 		info.flags = VFIO_DEVICE_FLAGS_PCI;
 		info.flags |= VFIO_DEVICE_FLAGS_RESET;
-		info.num_regions = VFIO_PCI_NUM_REGIONS;
+		info.num_regions = VFIO_PCI_NUM_REGIONS +
+				vgpu->vdev.num_regions;
 		info.num_irqs = VFIO_PCI_NUM_IRQS;
 
 		return copy_to_user((void __user *)arg, &info, minsz) ?
@@ -1061,6 +1075,7 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		}
 
 		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;
-- 
2.7.4

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

* [PATCH v6 1/6] drm/i915/gvt: Extend the GVT-g architecture to support vfio device region
@ 2017-05-27  8:38   ` Xiaoguang Chen
  0 siblings, 0 replies; 74+ messages in thread
From: Xiaoguang Chen @ 2017-05-27  8:38 UTC (permalink / raw)
  To: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian
  Cc: Xiaoguang Chen

Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
---
 drivers/gpu/drm/i915/gvt/kvmgt.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 1ae0b40..3c6a02b 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -53,11 +53,21 @@ static const struct intel_gvt_ops *intel_gvt_ops;
 #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)
 
+struct vfio_region;
+struct intel_vgpu_regops {
+	size_t (*rw)(struct intel_vgpu *vgpu, char *buf,
+			size_t count, loff_t *ppos, bool iswrite);
+	void (*release)(struct intel_vgpu *vgpu,
+			struct vfio_region *region);
+};
+
 struct vfio_region {
 	u32				type;
 	u32				subtype;
 	size_t				size;
 	u32				flags;
+	const struct intel_vgpu_regops	*ops;
+	void				*data;
 };
 
 struct kvmgt_pgfn {
@@ -642,7 +652,7 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,
 	int ret = -EINVAL;
 
 
-	if (index >= VFIO_PCI_NUM_REGIONS) {
+	if (index >= VFIO_PCI_NUM_REGIONS + vgpu->vdev.num_regions) {
 		gvt_vgpu_err("invalid index: %u\n", index);
 		return -EINVAL;
 	}
@@ -676,8 +686,11 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,
 	case VFIO_PCI_BAR5_REGION_INDEX:
 	case VFIO_PCI_VGA_REGION_INDEX:
 	case VFIO_PCI_ROM_REGION_INDEX:
+		break;
 	default:
-		gvt_vgpu_err("unsupported region: %u\n", index);
+		index -= VFIO_PCI_NUM_REGIONS;
+		return vgpu->vdev.region[index].ops->rw(vgpu, buf, count,
+				ppos, is_write);
 	}
 
 	return ret == 0 ? count : ret;
@@ -940,7 +953,8 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
 
 		info.flags = VFIO_DEVICE_FLAGS_PCI;
 		info.flags |= VFIO_DEVICE_FLAGS_RESET;
-		info.num_regions = VFIO_PCI_NUM_REGIONS;
+		info.num_regions = VFIO_PCI_NUM_REGIONS +
+				vgpu->vdev.num_regions;
 		info.num_irqs = VFIO_PCI_NUM_IRQS;
 
 		return copy_to_user((void __user *)arg, &info, minsz) ?
@@ -1061,6 +1075,7 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		}
 
 		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;
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g
  2017-05-27  8:38 ` Xiaoguang Chen
@ 2017-05-27  8:38   ` Xiaoguang Chen
  -1 siblings, 0 replies; 74+ messages in thread
From: Xiaoguang Chen @ 2017-05-27  8:38 UTC (permalink / raw)
  To: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian
  Cc: Xiaoguang Chen, Bing Niu

OpRegion is needed to support display related operation for
intel vgpu.

A vfio device region is added to intel vgpu to deliver the
host OpRegion information to user space so user space can
construct the OpRegion for vgpu.

Signed-off-by: Bing Niu <bing.niu@intel.com>
Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
---
 drivers/gpu/drm/i915/gvt/kvmgt.c    | 97 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/opregion.c |  8 ++-
 2 files changed, 104 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 3c6a02b..389f072 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -53,6 +53,8 @@ static const struct intel_gvt_ops *intel_gvt_ops;
 #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)
 
+#define OPREGION_SIGNATURE "IntelGraphicsMem"
+
 struct vfio_region;
 struct intel_vgpu_regops {
 	size_t (*rw)(struct intel_vgpu *vgpu, char *buf,
@@ -436,6 +438,92 @@ static void kvmgt_protect_table_del(struct kvmgt_guest_info *info,
 	}
 }
 
+static size_t intel_vgpu_reg_rw_opregion(struct intel_vgpu *vgpu, char *buf,
+		size_t count, loff_t *ppos, bool iswrite)
+{
+	unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) -
+			VFIO_PCI_NUM_REGIONS;
+	void *base = vgpu->vdev.region[i].data;
+	loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
+
+	if (pos >= vgpu->vdev.region[i].size || iswrite) {
+		gvt_vgpu_err("invalid op or offset for Intel vgpu OpRegion\n");
+		return -EINVAL;
+	}
+	count = min(count, (size_t)(vgpu->vdev.region[i].size - pos));
+	memcpy(buf, base + pos, count);
+
+	return count;
+}
+
+static void intel_vgpu_reg_release_opregion(struct intel_vgpu *vgpu,
+		struct vfio_region *region)
+{
+	memunmap(region->data);
+}
+
+static const struct intel_vgpu_regops intel_vgpu_regops_opregion = {
+	.rw = intel_vgpu_reg_rw_opregion,
+	.release = intel_vgpu_reg_release_opregion,
+};
+
+static int intel_vgpu_register_reg(struct intel_vgpu *vgpu,
+		unsigned int type, unsigned int subtype,
+		const struct intel_vgpu_regops *ops,
+		size_t size, u32 flags, void *data)
+{
+	struct vfio_region *region;
+
+	region = krealloc(vgpu->vdev.region,
+			(vgpu->vdev.num_regions + 1) * sizeof(*region),
+			GFP_KERNEL);
+	if (!region)
+		return -ENOMEM;
+
+	vgpu->vdev.region = region;
+	vgpu->vdev.region[vgpu->vdev.num_regions].type = type;
+	vgpu->vdev.region[vgpu->vdev.num_regions].subtype = subtype;
+	vgpu->vdev.region[vgpu->vdev.num_regions].ops = ops;
+	vgpu->vdev.region[vgpu->vdev.num_regions].size = size;
+	vgpu->vdev.region[vgpu->vdev.num_regions].flags = flags;
+	vgpu->vdev.region[vgpu->vdev.num_regions].data = data;
+	vgpu->vdev.num_regions++;
+
+	return 0;
+}
+
+static int intel_vgpu_reg_init_opregion(struct intel_vgpu *vgpu)
+{
+	unsigned int addr;
+	void *base;
+	int ret;
+
+	addr = vgpu->gvt->opregion.opregion_pa;
+	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;
+	}
+
+	ret = intel_vgpu_register_reg(vgpu,
+			PCI_VENDOR_ID_INTEL | VFIO_REGION_TYPE_PCI_VENDOR_TYPE,
+			VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION,
+			&intel_vgpu_regops_opregion, OPREGION_SIZE,
+			VFIO_REGION_INFO_FLAG_READ, base);
+	if (ret) {
+		memunmap(base);
+		return ret;
+	}
+
+	return ret;
+}
+
 static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
 {
 	struct intel_vgpu *vgpu = NULL;
@@ -467,6 +555,15 @@ static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
 	vgpu->vdev.mdev = mdev;
 	mdev_set_drvdata(mdev, vgpu);
 
+	ret = intel_vgpu_reg_init_opregion(vgpu);
+	if (ret) {
+		gvt_vgpu_err("create OpRegion failed\n");
+		goto out;
+	}
+
+	gvt_dbg_core("create OpRegion succeeded for mdev:%s\n",
+			dev_name(mdev_dev(mdev)));
+
 	gvt_dbg_core("intel_vgpu_create succeeded for mdev: %s\n",
 		     dev_name(mdev_dev(mdev)));
 	ret = 0;
diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c
index 3117991..5c7496d 100644
--- a/drivers/gpu/drm/i915/gvt/opregion.c
+++ b/drivers/gpu/drm/i915/gvt/opregion.c
@@ -114,6 +114,7 @@ void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu)
 int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
 {
 	int ret;
+	unsigned long pfn;
 
 	gvt_dbg_core("vgpu%d: init vgpu opregion\n", vgpu->id);
 
@@ -127,7 +128,12 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
 		ret = map_vgpu_opregion(vgpu, true);
 		if (ret)
 			return ret;
-	}
+	} else {
+		pfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gpa >> PAGE_SHIFT);
+		vgpu_opregion(vgpu)->va = memremap(pfn << PAGE_SHIFT,
+						INTEL_GVT_OPREGION_SIZE,
+						MEMREMAP_WB);
+		}
 
 	return 0;
 }
-- 
2.7.4

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

* [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g
@ 2017-05-27  8:38   ` Xiaoguang Chen
  0 siblings, 0 replies; 74+ messages in thread
From: Xiaoguang Chen @ 2017-05-27  8:38 UTC (permalink / raw)
  To: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian
  Cc: Xiaoguang Chen

OpRegion is needed to support display related operation for
intel vgpu.

A vfio device region is added to intel vgpu to deliver the
host OpRegion information to user space so user space can
construct the OpRegion for vgpu.

Signed-off-by: Bing Niu <bing.niu@intel.com>
Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
---
 drivers/gpu/drm/i915/gvt/kvmgt.c    | 97 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/opregion.c |  8 ++-
 2 files changed, 104 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 3c6a02b..389f072 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -53,6 +53,8 @@ static const struct intel_gvt_ops *intel_gvt_ops;
 #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)
 
+#define OPREGION_SIGNATURE "IntelGraphicsMem"
+
 struct vfio_region;
 struct intel_vgpu_regops {
 	size_t (*rw)(struct intel_vgpu *vgpu, char *buf,
@@ -436,6 +438,92 @@ static void kvmgt_protect_table_del(struct kvmgt_guest_info *info,
 	}
 }
 
+static size_t intel_vgpu_reg_rw_opregion(struct intel_vgpu *vgpu, char *buf,
+		size_t count, loff_t *ppos, bool iswrite)
+{
+	unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) -
+			VFIO_PCI_NUM_REGIONS;
+	void *base = vgpu->vdev.region[i].data;
+	loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
+
+	if (pos >= vgpu->vdev.region[i].size || iswrite) {
+		gvt_vgpu_err("invalid op or offset for Intel vgpu OpRegion\n");
+		return -EINVAL;
+	}
+	count = min(count, (size_t)(vgpu->vdev.region[i].size - pos));
+	memcpy(buf, base + pos, count);
+
+	return count;
+}
+
+static void intel_vgpu_reg_release_opregion(struct intel_vgpu *vgpu,
+		struct vfio_region *region)
+{
+	memunmap(region->data);
+}
+
+static const struct intel_vgpu_regops intel_vgpu_regops_opregion = {
+	.rw = intel_vgpu_reg_rw_opregion,
+	.release = intel_vgpu_reg_release_opregion,
+};
+
+static int intel_vgpu_register_reg(struct intel_vgpu *vgpu,
+		unsigned int type, unsigned int subtype,
+		const struct intel_vgpu_regops *ops,
+		size_t size, u32 flags, void *data)
+{
+	struct vfio_region *region;
+
+	region = krealloc(vgpu->vdev.region,
+			(vgpu->vdev.num_regions + 1) * sizeof(*region),
+			GFP_KERNEL);
+	if (!region)
+		return -ENOMEM;
+
+	vgpu->vdev.region = region;
+	vgpu->vdev.region[vgpu->vdev.num_regions].type = type;
+	vgpu->vdev.region[vgpu->vdev.num_regions].subtype = subtype;
+	vgpu->vdev.region[vgpu->vdev.num_regions].ops = ops;
+	vgpu->vdev.region[vgpu->vdev.num_regions].size = size;
+	vgpu->vdev.region[vgpu->vdev.num_regions].flags = flags;
+	vgpu->vdev.region[vgpu->vdev.num_regions].data = data;
+	vgpu->vdev.num_regions++;
+
+	return 0;
+}
+
+static int intel_vgpu_reg_init_opregion(struct intel_vgpu *vgpu)
+{
+	unsigned int addr;
+	void *base;
+	int ret;
+
+	addr = vgpu->gvt->opregion.opregion_pa;
+	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;
+	}
+
+	ret = intel_vgpu_register_reg(vgpu,
+			PCI_VENDOR_ID_INTEL | VFIO_REGION_TYPE_PCI_VENDOR_TYPE,
+			VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION,
+			&intel_vgpu_regops_opregion, OPREGION_SIZE,
+			VFIO_REGION_INFO_FLAG_READ, base);
+	if (ret) {
+		memunmap(base);
+		return ret;
+	}
+
+	return ret;
+}
+
 static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
 {
 	struct intel_vgpu *vgpu = NULL;
@@ -467,6 +555,15 @@ static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
 	vgpu->vdev.mdev = mdev;
 	mdev_set_drvdata(mdev, vgpu);
 
+	ret = intel_vgpu_reg_init_opregion(vgpu);
+	if (ret) {
+		gvt_vgpu_err("create OpRegion failed\n");
+		goto out;
+	}
+
+	gvt_dbg_core("create OpRegion succeeded for mdev:%s\n",
+			dev_name(mdev_dev(mdev)));
+
 	gvt_dbg_core("intel_vgpu_create succeeded for mdev: %s\n",
 		     dev_name(mdev_dev(mdev)));
 	ret = 0;
diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c
index 3117991..5c7496d 100644
--- a/drivers/gpu/drm/i915/gvt/opregion.c
+++ b/drivers/gpu/drm/i915/gvt/opregion.c
@@ -114,6 +114,7 @@ void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu)
 int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
 {
 	int ret;
+	unsigned long pfn;
 
 	gvt_dbg_core("vgpu%d: init vgpu opregion\n", vgpu->id);
 
@@ -127,7 +128,12 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
 		ret = map_vgpu_opregion(vgpu, true);
 		if (ret)
 			return ret;
-	}
+	} else {
+		pfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gpa >> PAGE_SHIFT);
+		vgpu_opregion(vgpu)->va = memremap(pfn << PAGE_SHIFT,
+						INTEL_GVT_OPREGION_SIZE,
+						MEMREMAP_WB);
+		}
 
 	return 0;
 }
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH v6 3/6] drm/i915/gvt: Frame buffer decoder support for GVT-g
  2017-05-27  8:38 ` Xiaoguang Chen
@ 2017-05-27  8:38   ` Xiaoguang Chen
  -1 siblings, 0 replies; 74+ messages in thread
From: Xiaoguang Chen @ 2017-05-27  8:38 UTC (permalink / raw)
  To: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian
  Cc: Xiaoguang Chen

decode frambuffer attributes of primary, cursor and sprite plane

Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
---
 drivers/gpu/drm/i915/gvt/Makefile     |   3 +-
 drivers/gpu/drm/i915/gvt/display.c    |   2 +-
 drivers/gpu/drm/i915/gvt/display.h    |   2 +
 drivers/gpu/drm/i915/gvt/fb_decoder.c | 479 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/fb_decoder.h | 166 ++++++++++++
 drivers/gpu/drm/i915/gvt/gvt.h        |   1 +
 6 files changed, 651 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.c
 create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.h

diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile
index b123c20..192ca26 100644
--- a/drivers/gpu/drm/i915/gvt/Makefile
+++ b/drivers/gpu/drm/i915/gvt/Makefile
@@ -1,7 +1,8 @@
 GVT_DIR := gvt
 GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \
 	interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \
-	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o
+	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o \
+	fb_decoder.o
 
 ccflags-y				+= -I$(src) -I$(src)/$(GVT_DIR) -Wall
 i915-y					+= $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
index e0261fc..f5f63c5 100644
--- a/drivers/gpu/drm/i915/gvt/display.c
+++ b/drivers/gpu/drm/i915/gvt/display.c
@@ -67,7 +67,7 @@ static int edp_pipe_is_enabled(struct intel_vgpu *vgpu)
 	return 1;
 }
 
-static int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
+int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
 {
 	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
 
diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h
index d73de22..b46b868 100644
--- a/drivers/gpu/drm/i915/gvt/display.h
+++ b/drivers/gpu/drm/i915/gvt/display.h
@@ -179,4 +179,6 @@ int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution);
 void intel_vgpu_reset_display(struct intel_vgpu *vgpu);
 void intel_vgpu_clean_display(struct intel_vgpu *vgpu);
 
+int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe);
+
 #endif
diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.c b/drivers/gpu/drm/i915/gvt/fb_decoder.c
new file mode 100644
index 0000000..d4404fd
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/fb_decoder.c
@@ -0,0 +1,479 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Kevin Tian <kevin.tian@intel.com>
+ *
+ * Contributors:
+ *    Bing Niu <bing.niu@intel.com>
+ *    Xu Han <xu.han@intel.com>
+ *    Ping Gao <ping.a.gao@intel.com>
+ *    Xiaoguang Chen <xiaoguang.chen@intel.com>
+ *    Yang Liu <yang2.liu@intel.com>
+ *
+ */
+
+#include <uapi/drm/drm_fourcc.h>
+#include "i915_drv.h"
+#include "gvt.h"
+
+/* The below definitions are required by guest. */
+// [63:0] x:R:G:B 16:16:16:16 little endian
+#define DRM_FORMAT_XRGB161616_GVT  fourcc_code('X', 'R', '4', '8')
+// [63:0] x:B:G:R 16:16:16:16 little endian
+#define DRM_FORMAT_XBGR161616_GVT  fourcc_code('X', 'B', '4', '8')
+
+#define FORMAT_NUM	16
+struct pixel_format {
+	int	drm_format;	/* Pixel format in DRM definition */
+	int	bpp;		/* Bits per pixel, 0 indicates invalid */
+	char *desc;		/* The description */
+};
+
+/* non-supported format has bpp default to 0 */
+static struct pixel_format primary_pixel_formats[FORMAT_NUM] = {
+	[0x2] = {DRM_FORMAT_C8, 8, "8-bit Indexed"},
+	[0x5] = {DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"},
+	[0x6] = {DRM_FORMAT_XRGB8888, 32,
+		"32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"},
+	[0x8] = {DRM_FORMAT_XBGR2101010, 32,
+		"32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"},
+	[0xa] = {DRM_FORMAT_XRGB2101010, 32,
+		"32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"},
+	[0xc] = {DRM_FORMAT_XRGB161616_GVT, 64,
+		"64-bit RGBX Floating Point(16:16:16:16 MSB-X:B:G:R)"},
+	[0xe] = {DRM_FORMAT_XBGR8888, 32,
+		"32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"},
+};
+
+/* non-supported format has bpp default to 0 */
+static struct pixel_format skl_pixel_formats[] = {
+	{DRM_FORMAT_YUYV, 16, "16-bit packed YUYV (8:8:8:8 MSB-V:Y2:U:Y1)"},
+	{DRM_FORMAT_UYVY, 16, "16-bit packed UYVY (8:8:8:8 MSB-Y2:V:Y1:U)"},
+	{DRM_FORMAT_YVYU, 16, "16-bit packed YVYU (8:8:8:8 MSB-U:Y2:V:Y1)"},
+	{DRM_FORMAT_VYUY, 16, "16-bit packed VYUY (8:8:8:8 MSB-Y2:U:Y1:V)"},
+
+	{DRM_FORMAT_C8, 8, "8-bit Indexed"},
+	{DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"},
+	{DRM_FORMAT_ABGR8888, 32, "32-bit RGBA (8:8:8:8 MSB-A:B:G:R)"},
+	{DRM_FORMAT_XBGR8888, 32, "32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"},
+
+	{DRM_FORMAT_ARGB8888, 32, "32-bit BGRA (8:8:8:8 MSB-A:R:G:B)"},
+	{DRM_FORMAT_XRGB8888, 32, "32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"},
+	{DRM_FORMAT_XBGR2101010, 32, "32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"},
+	{DRM_FORMAT_XRGB2101010, 32, "32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"},
+
+	{DRM_FORMAT_XRGB161616_GVT, 64,
+		"64-bit XRGB (16:16:16:16 MSB-X:R:G:B)"},
+	{DRM_FORMAT_XBGR161616_GVT, 64,
+		"64-bit XBGR (16:16:16:16 MSB-X:B:G:R)"},
+
+	/* non-supported format has bpp default to 0 */
+	{0, 0, NULL},
+};
+
+static int skl_format_to_drm(int format, bool rgb_order, bool alpha,
+	int yuv_order)
+{
+	int skl_pixel_formats_index = 14;
+
+	switch (format) {
+	case PLANE_CTL_FORMAT_INDEXED:
+		skl_pixel_formats_index = 4;
+		break;
+	case PLANE_CTL_FORMAT_RGB_565:
+		skl_pixel_formats_index = 5;
+		break;
+	case PLANE_CTL_FORMAT_XRGB_8888:
+		if (rgb_order)
+			skl_pixel_formats_index = alpha ? 6 : 7;
+		else
+			skl_pixel_formats_index = alpha ? 8 : 9;
+		break;
+	case PLANE_CTL_FORMAT_XRGB_2101010:
+		skl_pixel_formats_index = rgb_order ? 10 : 11;
+		break;
+
+	case PLANE_CTL_FORMAT_XRGB_16161616F:
+		skl_pixel_formats_index = rgb_order ? 12 : 13;
+		break;
+
+	case PLANE_CTL_FORMAT_YUV422:
+		skl_pixel_formats_index = yuv_order >> 16;
+		if (skl_pixel_formats_index > 3)
+			return -EINVAL;
+		break;
+
+	default:
+		break;
+	}
+
+	return skl_pixel_formats_index;
+}
+
+static u32 intel_vgpu_get_stride(struct intel_vgpu *vgpu, int pipe,
+	u32 tiled, int stride_mask, int bpp)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+	u32 stride_reg = vgpu_vreg(vgpu, DSPSTRIDE(pipe)) & stride_mask;
+	u32 stride = stride_reg;
+
+	if (IS_SKYLAKE(dev_priv)) {
+		switch (tiled) {
+		case PLANE_CTL_TILED_LINEAR:
+			stride = stride_reg * 64;
+			break;
+		case PLANE_CTL_TILED_X:
+			stride = stride_reg * 512;
+			break;
+		case PLANE_CTL_TILED_Y:
+			stride = stride_reg * 128;
+			break;
+		case PLANE_CTL_TILED_YF:
+			if (bpp == 8)
+				stride = stride_reg * 64;
+			else if (bpp == 16 || bpp == 32 || bpp == 64)
+				stride = stride_reg * 128;
+			else
+				gvt_dbg_core("skl: unsupported bpp:%d\n", bpp);
+			break;
+		default:
+			gvt_dbg_core("skl: unsupported tile format:%x\n",
+				tiled);
+		}
+	}
+
+	return stride;
+}
+
+static int intel_vgpu_decode_primary_plane_format(struct intel_vgpu *vgpu,
+	int pipe, struct intel_vgpu_primary_plane_format *plane)
+{
+	u32	val, fmt;
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+	val = vgpu_vreg(vgpu, DSPCNTR(pipe));
+	plane->enabled = !!(val & DISPLAY_PLANE_ENABLE);
+	if (!plane->enabled)
+		return 0;
+
+	if (IS_SKYLAKE(dev_priv)) {
+		plane->tiled = (val & PLANE_CTL_TILED_MASK) >>
+		_PLANE_CTL_TILED_SHIFT;
+		fmt = skl_format_to_drm(
+			val & PLANE_CTL_FORMAT_MASK,
+			val & PLANE_CTL_ORDER_RGBX,
+			val & PLANE_CTL_ALPHA_MASK,
+			val & PLANE_CTL_YUV422_ORDER_MASK);
+		plane->bpp = skl_pixel_formats[fmt].bpp;
+		plane->drm_format = skl_pixel_formats[fmt].drm_format;
+	} else {
+		plane->tiled = !!(val & DISPPLANE_TILED);
+		fmt = (val & DISPPLANE_PIXFORMAT_MASK) >> _PRI_PLANE_FMT_SHIFT;
+		plane->bpp = primary_pixel_formats[fmt].bpp;
+		plane->drm_format = primary_pixel_formats[fmt].drm_format;
+	}
+
+	if ((IS_SKYLAKE(dev_priv) && !skl_pixel_formats[fmt].bpp)
+		|| (!IS_SKYLAKE(dev_priv) &&
+			!primary_pixel_formats[fmt].bpp)) {
+		gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt);
+		return -EINVAL;
+	}
+
+	plane->hw_format = fmt;
+
+	plane->base = vgpu_vreg(vgpu, DSPSURF(pipe)) & GTT_PAGE_MASK;
+
+	plane->stride = intel_vgpu_get_stride(vgpu, pipe, (plane->tiled << 10),
+		(IS_SKYLAKE(dev_priv)) ? (_PRI_PLANE_STRIDE_MASK >> 6) :
+		_PRI_PLANE_STRIDE_MASK, plane->bpp);
+
+	plane->width = (vgpu_vreg(vgpu, PIPESRC(pipe)) & _PIPE_H_SRCSZ_MASK) >>
+		_PIPE_H_SRCSZ_SHIFT;
+	plane->width += 1;
+	plane->height = (vgpu_vreg(vgpu, PIPESRC(pipe)) &
+			_PIPE_V_SRCSZ_MASK) >> _PIPE_V_SRCSZ_SHIFT;
+	plane->height += 1;	/* raw height is one minus the real value */
+
+	val = vgpu_vreg(vgpu, DSPTILEOFF(pipe));
+	plane->x_offset = (val & _PRI_PLANE_X_OFF_MASK) >>
+		_PRI_PLANE_X_OFF_SHIFT;
+	plane->y_offset = (val & _PRI_PLANE_Y_OFF_MASK) >>
+		_PRI_PLANE_Y_OFF_SHIFT;
+
+	return 0;
+}
+
+#define CURSOR_MODE_NUM	(1 << 6)
+struct cursor_mode_format {
+	int	drm_format;	/* Pixel format in DRM definition */
+	u8	bpp;		/* Bits per pixel; 0 indicates invalid */
+	u32	width;		/* In pixel */
+	u32	height;		/* In lines */
+	char	*desc;		/* The description */
+};
+
+/* non-supported format has bpp default to 0 */
+static struct cursor_mode_format cursor_pixel_formats[CURSOR_MODE_NUM] = {
+	[0x22]  = {DRM_FORMAT_ARGB8888, 32, 128, 128, "128x128 32bpp ARGB"},
+	[0x23]  = {DRM_FORMAT_ARGB8888, 32, 256, 256, "256x256 32bpp ARGB"},
+	[0x27]  = {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"},
+	[0x7]  = {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"},
+};
+
+static int intel_vgpu_decode_cursor_plane_format(struct intel_vgpu *vgpu,
+	int pipe, struct intel_vgpu_cursor_plane_format *plane)
+{
+	u32 val, mode;
+	u32 alpha_plane, alpha_force;
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+	val = vgpu_vreg(vgpu, CURCNTR(pipe));
+	mode = val & CURSOR_MODE;
+	plane->enabled = (mode != CURSOR_MODE_DISABLE);
+	if (!plane->enabled)
+		return 0;
+
+	if (!cursor_pixel_formats[mode].bpp) {
+		gvt_vgpu_err("Non-supported cursor mode (0x%x)\n", mode);
+		return -EINVAL;
+	}
+	plane->mode = mode;
+	plane->bpp = cursor_pixel_formats[mode].bpp;
+	plane->drm_format = cursor_pixel_formats[mode].drm_format;
+	plane->width = cursor_pixel_formats[mode].width;
+	plane->height = cursor_pixel_formats[mode].height;
+
+	alpha_plane = (val & _CURSOR_ALPHA_PLANE_MASK) >>
+				_CURSOR_ALPHA_PLANE_SHIFT;
+	alpha_force = (val & _CURSOR_ALPHA_FORCE_MASK) >>
+				_CURSOR_ALPHA_FORCE_SHIFT;
+	if (alpha_plane || alpha_force)
+		gvt_dbg_core("alpha_plane=0x%x, alpha_force=0x%x\n",
+			alpha_plane, alpha_force);
+
+	plane->base = vgpu_vreg(vgpu, CURBASE(pipe)) & GTT_PAGE_MASK;
+
+	val = vgpu_vreg(vgpu, CURPOS(pipe));
+	plane->x_pos = (val & _CURSOR_POS_X_MASK) >> _CURSOR_POS_X_SHIFT;
+	plane->x_sign = (val & _CURSOR_SIGN_X_MASK) >> _CURSOR_SIGN_X_SHIFT;
+	plane->y_pos = (val & _CURSOR_POS_Y_MASK) >> _CURSOR_POS_Y_SHIFT;
+	plane->y_sign = (val & _CURSOR_SIGN_Y_MASK) >> _CURSOR_SIGN_Y_SHIFT;
+
+	return 0;
+}
+
+#define FORMAT_NUM_SRRITE	(1 << 3)
+
+static struct pixel_format sprite_pixel_formats[FORMAT_NUM_SRRITE] = {
+	[0x0]  = {DRM_FORMAT_YUV422, 16, "YUV 16-bit 4:2:2 packed"},
+	[0x1]  = {DRM_FORMAT_XRGB2101010, 32, "RGB 32-bit 2:10:10:10"},
+	[0x2]  = {DRM_FORMAT_XRGB8888, 32, "RGB 32-bit 8:8:8:8"},
+	[0x3]  = {DRM_FORMAT_XRGB161616_GVT, 64,
+		    "RGB 64-bit 16:16:16:16 Floating Point"},
+	[0x4] = {DRM_FORMAT_AYUV, 32,
+		"YUV 32-bit 4:4:4 packed (8:8:8:8 MSB-X:Y:U:V)"},
+};
+
+static int intel_vgpu_decode_sprite_plane_format(struct intel_vgpu *vgpu,
+	int pipe, struct intel_vgpu_sprite_plane_format *plane)
+{
+	u32 val, fmt;
+	u32 width;
+	u32 color_order, yuv_order;
+	int drm_format;
+
+	val = vgpu_vreg(vgpu, SPRCTL(pipe));
+	plane->enabled = !!(val & SPRITE_ENABLE);
+	if (!plane->enabled)
+		return 0;
+
+	plane->tiled = !!(val & SPRITE_TILED);
+	color_order = !!(val & SPRITE_RGB_ORDER_RGBX);
+	yuv_order = (val & SPRITE_YUV_BYTE_ORDER_MASK) >>
+				_SPRITE_YUV_ORDER_SHIFT;
+
+	fmt = (val & SPRITE_PIXFORMAT_MASK) >> _SPRITE_FMT_SHIFT;
+	if (!sprite_pixel_formats[fmt].bpp) {
+		gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt);
+		return -EINVAL;
+	}
+	plane->hw_format = fmt;
+	plane->bpp = sprite_pixel_formats[fmt].bpp;
+	drm_format = sprite_pixel_formats[fmt].drm_format;
+
+	/* Order of RGB values in an RGBxxx buffer may be ordered RGB or
+	 * BGR depending on the state of the color_order field
+	 */
+	if (!color_order) {
+		if (drm_format == DRM_FORMAT_XRGB2101010)
+			drm_format = DRM_FORMAT_XBGR2101010;
+		else if (drm_format == DRM_FORMAT_XRGB8888)
+			drm_format = DRM_FORMAT_XBGR8888;
+	}
+
+	if (drm_format == DRM_FORMAT_YUV422) {
+		switch (yuv_order) {
+		case	0:
+			drm_format = DRM_FORMAT_YUYV;
+			break;
+		case	1:
+			drm_format = DRM_FORMAT_UYVY;
+			break;
+		case	2:
+			drm_format = DRM_FORMAT_YVYU;
+			break;
+		case	3:
+			drm_format = DRM_FORMAT_VYUY;
+			break;
+		default:
+			/* yuv_order has only 2 bits */
+			break;
+		}
+	}
+
+	plane->drm_format = drm_format;
+
+	plane->base = vgpu_vreg(vgpu, SPRSURF(pipe)) & GTT_PAGE_MASK;
+	plane->width = vgpu_vreg(vgpu, SPRSTRIDE(pipe)) &
+				_SPRITE_STRIDE_MASK;
+	plane->width /= plane->bpp / 8;	/* raw width in bytes */
+
+	val = vgpu_vreg(vgpu, SPRSIZE(pipe));
+	plane->height = (val & _SPRITE_SIZE_HEIGHT_MASK) >>
+		_SPRITE_SIZE_HEIGHT_SHIFT;
+	width = (val & _SPRITE_SIZE_WIDTH_MASK) >> _SPRITE_SIZE_WIDTH_SHIFT;
+	plane->height += 1;	/* raw height is one minus the real value */
+	width += 1;		/* raw width is one minus the real value */
+	if (plane->width != width)
+		gvt_dbg_core("sprite_plane: plane->width=%d, width=%d\n",
+			plane->width, width);
+
+	val = vgpu_vreg(vgpu, SPRPOS(pipe));
+	plane->x_pos = (val & _SPRITE_POS_X_MASK) >> _SPRITE_POS_X_SHIFT;
+	plane->y_pos = (val & _SPRITE_POS_Y_MASK) >> _SPRITE_POS_Y_SHIFT;
+
+	val = vgpu_vreg(vgpu, SPROFFSET(pipe));
+	plane->x_offset = (val & _SPRITE_OFFSET_START_X_MASK) >>
+			   _SPRITE_OFFSET_START_X_SHIFT;
+	plane->y_offset = (val & _SPRITE_OFFSET_START_Y_MASK) >>
+			   _SPRITE_OFFSET_START_Y_SHIFT;
+	return 0;
+}
+
+static int intel_vgpu_decode_fb_format(struct intel_gvt *gvt, int id,
+	struct intel_vgpu_fb_format *fb)
+{
+	int i;
+	struct intel_vgpu *vgpu = NULL;
+	int ret = 0;
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+
+	if (!fb)
+		return -EINVAL;
+
+	/* TODO: use fine-grained refcnt later */
+	mutex_lock(&gvt->lock);
+
+	for_each_active_vgpu(gvt, vgpu, i)
+		if (vgpu->id == id)
+			break;
+
+	if (!vgpu) {
+		gvt_vgpu_err("Invalid vgpu ID (%d)\n", id);
+		mutex_unlock(&gvt->lock);
+		return -ENODEV;
+	}
+
+	for (i = 0; i < I915_MAX_PIPES; i++) {
+		struct intel_vgpu_pipe_format *pipe = &fb->pipes[i];
+		u32 ddi_func_ctl = vgpu_vreg(vgpu, TRANS_DDI_FUNC_CTL(i));
+
+		if (!(ddi_func_ctl & TRANS_DDI_FUNC_ENABLE)) {
+			pipe->ddi_port = DDI_PORT_NONE;
+		} else {
+			u32 port = (ddi_func_ctl & TRANS_DDI_PORT_MASK) >>
+						TRANS_DDI_PORT_SHIFT;
+			if (port <= DDI_PORT_E)
+				pipe->ddi_port = port;
+			else
+				pipe->ddi_port = DDI_PORT_NONE;
+		}
+
+		ret |= intel_vgpu_decode_primary_plane_format(vgpu,
+			i, &pipe->primary);
+		ret |= intel_vgpu_decode_sprite_plane_format(vgpu,
+			i, &pipe->sprite);
+		ret |= intel_vgpu_decode_cursor_plane_format(vgpu,
+			i, &pipe->cursor);
+
+		if (ret) {
+			gvt_vgpu_err("Decode format error for pipe(%d)\n", i);
+			ret = -EINVAL;
+			break;
+		}
+	}
+
+	mutex_unlock(&gvt->lock);
+
+	return ret;
+}
+
+/**
+ * intel_vgpu_decode_plane - Decode plane based on plane id
+ * @dev: drm device
+ * @vgpu: input vgpu
+ * This function is called for decoding plane
+ *
+ * Returns:
+ * pipe on success, NULL if failed.
+ */
+struct intel_vgpu_pipe_format *intel_vgpu_decode_plane(struct drm_device *dev,
+		struct intel_vgpu *vgpu)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_vgpu_fb_format fb;
+	struct intel_vgpu_pipe_format *pipe;
+	int i;
+
+	if (intel_vgpu_decode_fb_format(dev_priv->gvt, vgpu->id, &fb))
+		return NULL;
+
+	for (i = 0; i < I915_MAX_PIPES; i++)
+		if (pipe_is_enabled(vgpu, i))
+			break;
+	if (i >= I915_MAX_PIPES) {
+		gvt_dbg_core("No enabled pipes\n");
+		return NULL;
+	}
+	pipe = &fb.pipes[i];
+
+	if (!pipe || !pipe->primary.enabled) {
+		gvt_dbg_core("Invalid pipe_id :%d\n", i);
+		return NULL;
+	}
+
+	return pipe;
+}
+
diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.h b/drivers/gpu/drm/i915/gvt/fb_decoder.h
new file mode 100644
index 0000000..04300af
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/fb_decoder.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Kevin Tian <kevin.tian@intel.com>
+ *
+ * Contributors:
+ *    Bing Niu <bing.niu@intel.com>
+ *    Xu Han <xu.han@intel.com>
+ *    Ping Gao <ping.a.gao@intel.com>
+ *    Xiaoguang Chen <xiaoguang.chen@intel.com>
+ *    Yang Liu <yang2.liu@intel.com>
+ *
+ */
+
+#ifndef _GVT_FB_DECODER_H_
+#define _GVT_FB_DECODER_H_
+
+#define _PLANE_CTL_FORMAT_SHIFT		24
+#define _PLANE_CTL_TILED_SHIFT		10
+#define _PIPE_V_SRCSZ_SHIFT		0
+#define _PIPE_V_SRCSZ_MASK		(0xfff << _PIPE_V_SRCSZ_SHIFT)
+#define _PIPE_H_SRCSZ_SHIFT		16
+#define _PIPE_H_SRCSZ_MASK		(0x1fff << _PIPE_H_SRCSZ_SHIFT)
+
+#define _PRI_PLANE_FMT_SHIFT		26
+#define _PRI_PLANE_STRIDE_MASK		(0x3ff << 6)
+#define _PRI_PLANE_X_OFF_SHIFT		0
+#define _PRI_PLANE_X_OFF_MASK		(0x1fff << _PRI_PLANE_X_OFF_SHIFT)
+#define _PRI_PLANE_Y_OFF_SHIFT		16
+#define _PRI_PLANE_Y_OFF_MASK		(0xfff << _PRI_PLANE_Y_OFF_SHIFT)
+
+#define _CURSOR_MODE			0x3f
+#define _CURSOR_ALPHA_FORCE_SHIFT	8
+#define _CURSOR_ALPHA_FORCE_MASK	(0x3 << _CURSOR_ALPHA_FORCE_SHIFT)
+#define _CURSOR_ALPHA_PLANE_SHIFT	10
+#define _CURSOR_ALPHA_PLANE_MASK	(0x3 << _CURSOR_ALPHA_PLANE_SHIFT)
+#define _CURSOR_POS_X_SHIFT		0
+#define _CURSOR_POS_X_MASK		(0x1fff << _CURSOR_POS_X_SHIFT)
+#define _CURSOR_SIGN_X_SHIFT		15
+#define _CURSOR_SIGN_X_MASK		(1 << _CURSOR_SIGN_X_SHIFT)
+#define _CURSOR_POS_Y_SHIFT		16
+#define _CURSOR_POS_Y_MASK		(0xfff << _CURSOR_POS_Y_SHIFT)
+#define _CURSOR_SIGN_Y_SHIFT		31
+#define _CURSOR_SIGN_Y_MASK		(1 << _CURSOR_SIGN_Y_SHIFT)
+
+#define _SPRITE_FMT_SHIFT		25
+#define _SPRITE_COLOR_ORDER_SHIFT	20
+#define _SPRITE_YUV_ORDER_SHIFT		16
+#define _SPRITE_STRIDE_SHIFT		6
+#define _SPRITE_STRIDE_MASK		(0x1ff << _SPRITE_STRIDE_SHIFT)
+#define _SPRITE_SIZE_WIDTH_SHIFT	0
+#define _SPRITE_SIZE_HEIGHT_SHIFT	16
+#define _SPRITE_SIZE_WIDTH_MASK		(0x1fff << _SPRITE_SIZE_WIDTH_SHIFT)
+#define _SPRITE_SIZE_HEIGHT_MASK	(0xfff << _SPRITE_SIZE_HEIGHT_SHIFT)
+#define _SPRITE_POS_X_SHIFT		0
+#define _SPRITE_POS_Y_SHIFT		16
+#define _SPRITE_POS_X_MASK		(0x1fff << _SPRITE_POS_X_SHIFT)
+#define _SPRITE_POS_Y_MASK		(0xfff << _SPRITE_POS_Y_SHIFT)
+#define _SPRITE_OFFSET_START_X_SHIFT	0
+#define _SPRITE_OFFSET_START_Y_SHIFT	16
+#define _SPRITE_OFFSET_START_X_MASK	(0x1fff << _SPRITE_OFFSET_START_X_SHIFT)
+#define _SPRITE_OFFSET_START_Y_MASK	(0xfff << _SPRITE_OFFSET_START_Y_SHIFT)
+
+enum GVT_FB_EVENT {
+	FB_MODE_SET_START = 1,
+	FB_MODE_SET_END,
+	FB_DISPLAY_FLIP,
+};
+
+enum DDI_PORT {
+	DDI_PORT_NONE	= 0,
+	DDI_PORT_B	= 1,
+	DDI_PORT_C	= 2,
+	DDI_PORT_D	= 3,
+	DDI_PORT_E	= 4
+};
+
+struct intel_gvt;
+
+struct gvt_fb_notify_msg {
+	unsigned int vm_id;
+	unsigned int pipe_id; /* id starting from 0 */
+	unsigned int plane_id; /* primary, cursor, or sprite */
+};
+
+/* color space conversion and gamma correction are not included */
+struct intel_vgpu_primary_plane_format {
+	u8	enabled;	/* plane is enabled */
+	u8	tiled;		/* X-tiled */
+	u8	bpp;		/* bits per pixel */
+	u32	hw_format;	/* format field in the PRI_CTL register */
+	u32	drm_format;	/* format in DRM definition */
+	u32	base;		/* framebuffer base in graphics memory */
+	u32	x_offset;	/* in pixels */
+	u32	y_offset;	/* in lines */
+	u32	width;		/* in pixels */
+	u32	height;		/* in lines */
+	u32	stride;		/* in bytes */
+};
+
+struct intel_vgpu_sprite_plane_format {
+	u8	enabled;	/* plane is enabled */
+	u8	tiled;		/* X-tiled */
+	u8	bpp;		/* bits per pixel */
+	u32	hw_format;	/* format field in the SPR_CTL register */
+	u32	drm_format;	/* format in DRM definition */
+	u32	base;		/* sprite base in graphics memory */
+	u32	x_pos;		/* in pixels */
+	u32	y_pos;		/* in lines */
+	u32	x_offset;	/* in pixels */
+	u32	y_offset;	/* in lines */
+	u32	width;		/* in pixels */
+	u32	height;		/* in lines */
+};
+
+struct intel_vgpu_cursor_plane_format {
+	u8	enabled;
+	u8	mode;		/* cursor mode select */
+	u8	bpp;		/* bits per pixel */
+	u32	drm_format;	/* format in DRM definition */
+	u32	base;		/* cursor base in graphics memory */
+	u32	x_pos;		/* in pixels */
+	u32	y_pos;		/* in lines */
+	u8	x_sign;		/* X Position Sign */
+	u8	y_sign;		/* Y Position Sign */
+	u32	width;		/* in pixels */
+	u32	height;		/* in lines */
+	u32	x_hot;		/* in pixels */
+	u32	y_hot;		/* in pixels */
+};
+
+struct intel_vgpu_pipe_format {
+	struct intel_vgpu_primary_plane_format	primary;
+	struct intel_vgpu_sprite_plane_format	sprite;
+	struct intel_vgpu_cursor_plane_format	cursor;
+	enum DDI_PORT ddi_port;  /* the DDI port that pipe is connected to */
+};
+
+struct intel_vgpu_fb_format {
+	struct intel_vgpu_pipe_format	pipes[4];
+};
+
+struct intel_vgpu_pipe_format *intel_vgpu_decode_plane(struct drm_device *dev,
+		struct intel_vgpu *vgpu);
+
+#endif
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index 930732e..c42266c 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -46,6 +46,7 @@
 #include "sched_policy.h"
 #include "render.h"
 #include "cmd_parser.h"
+#include "fb_decoder.h"
 
 #define GVT_MAX_VGPU 8
 
-- 
2.7.4

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

* [PATCH v6 3/6] drm/i915/gvt: Frame buffer decoder support for GVT-g
@ 2017-05-27  8:38   ` Xiaoguang Chen
  0 siblings, 0 replies; 74+ messages in thread
From: Xiaoguang Chen @ 2017-05-27  8:38 UTC (permalink / raw)
  To: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian
  Cc: Xiaoguang Chen

decode frambuffer attributes of primary, cursor and sprite plane

Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
---
 drivers/gpu/drm/i915/gvt/Makefile     |   3 +-
 drivers/gpu/drm/i915/gvt/display.c    |   2 +-
 drivers/gpu/drm/i915/gvt/display.h    |   2 +
 drivers/gpu/drm/i915/gvt/fb_decoder.c | 479 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/fb_decoder.h | 166 ++++++++++++
 drivers/gpu/drm/i915/gvt/gvt.h        |   1 +
 6 files changed, 651 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.c
 create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.h

diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile
index b123c20..192ca26 100644
--- a/drivers/gpu/drm/i915/gvt/Makefile
+++ b/drivers/gpu/drm/i915/gvt/Makefile
@@ -1,7 +1,8 @@
 GVT_DIR := gvt
 GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \
 	interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \
-	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o
+	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o \
+	fb_decoder.o
 
 ccflags-y				+= -I$(src) -I$(src)/$(GVT_DIR) -Wall
 i915-y					+= $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
index e0261fc..f5f63c5 100644
--- a/drivers/gpu/drm/i915/gvt/display.c
+++ b/drivers/gpu/drm/i915/gvt/display.c
@@ -67,7 +67,7 @@ static int edp_pipe_is_enabled(struct intel_vgpu *vgpu)
 	return 1;
 }
 
-static int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
+int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
 {
 	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
 
diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h
index d73de22..b46b868 100644
--- a/drivers/gpu/drm/i915/gvt/display.h
+++ b/drivers/gpu/drm/i915/gvt/display.h
@@ -179,4 +179,6 @@ int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution);
 void intel_vgpu_reset_display(struct intel_vgpu *vgpu);
 void intel_vgpu_clean_display(struct intel_vgpu *vgpu);
 
+int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe);
+
 #endif
diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.c b/drivers/gpu/drm/i915/gvt/fb_decoder.c
new file mode 100644
index 0000000..d4404fd
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/fb_decoder.c
@@ -0,0 +1,479 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Kevin Tian <kevin.tian@intel.com>
+ *
+ * Contributors:
+ *    Bing Niu <bing.niu@intel.com>
+ *    Xu Han <xu.han@intel.com>
+ *    Ping Gao <ping.a.gao@intel.com>
+ *    Xiaoguang Chen <xiaoguang.chen@intel.com>
+ *    Yang Liu <yang2.liu@intel.com>
+ *
+ */
+
+#include <uapi/drm/drm_fourcc.h>
+#include "i915_drv.h"
+#include "gvt.h"
+
+/* The below definitions are required by guest. */
+// [63:0] x:R:G:B 16:16:16:16 little endian
+#define DRM_FORMAT_XRGB161616_GVT  fourcc_code('X', 'R', '4', '8')
+// [63:0] x:B:G:R 16:16:16:16 little endian
+#define DRM_FORMAT_XBGR161616_GVT  fourcc_code('X', 'B', '4', '8')
+
+#define FORMAT_NUM	16
+struct pixel_format {
+	int	drm_format;	/* Pixel format in DRM definition */
+	int	bpp;		/* Bits per pixel, 0 indicates invalid */
+	char *desc;		/* The description */
+};
+
+/* non-supported format has bpp default to 0 */
+static struct pixel_format primary_pixel_formats[FORMAT_NUM] = {
+	[0x2] = {DRM_FORMAT_C8, 8, "8-bit Indexed"},
+	[0x5] = {DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"},
+	[0x6] = {DRM_FORMAT_XRGB8888, 32,
+		"32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"},
+	[0x8] = {DRM_FORMAT_XBGR2101010, 32,
+		"32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"},
+	[0xa] = {DRM_FORMAT_XRGB2101010, 32,
+		"32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"},
+	[0xc] = {DRM_FORMAT_XRGB161616_GVT, 64,
+		"64-bit RGBX Floating Point(16:16:16:16 MSB-X:B:G:R)"},
+	[0xe] = {DRM_FORMAT_XBGR8888, 32,
+		"32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"},
+};
+
+/* non-supported format has bpp default to 0 */
+static struct pixel_format skl_pixel_formats[] = {
+	{DRM_FORMAT_YUYV, 16, "16-bit packed YUYV (8:8:8:8 MSB-V:Y2:U:Y1)"},
+	{DRM_FORMAT_UYVY, 16, "16-bit packed UYVY (8:8:8:8 MSB-Y2:V:Y1:U)"},
+	{DRM_FORMAT_YVYU, 16, "16-bit packed YVYU (8:8:8:8 MSB-U:Y2:V:Y1)"},
+	{DRM_FORMAT_VYUY, 16, "16-bit packed VYUY (8:8:8:8 MSB-Y2:U:Y1:V)"},
+
+	{DRM_FORMAT_C8, 8, "8-bit Indexed"},
+	{DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"},
+	{DRM_FORMAT_ABGR8888, 32, "32-bit RGBA (8:8:8:8 MSB-A:B:G:R)"},
+	{DRM_FORMAT_XBGR8888, 32, "32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"},
+
+	{DRM_FORMAT_ARGB8888, 32, "32-bit BGRA (8:8:8:8 MSB-A:R:G:B)"},
+	{DRM_FORMAT_XRGB8888, 32, "32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"},
+	{DRM_FORMAT_XBGR2101010, 32, "32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"},
+	{DRM_FORMAT_XRGB2101010, 32, "32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"},
+
+	{DRM_FORMAT_XRGB161616_GVT, 64,
+		"64-bit XRGB (16:16:16:16 MSB-X:R:G:B)"},
+	{DRM_FORMAT_XBGR161616_GVT, 64,
+		"64-bit XBGR (16:16:16:16 MSB-X:B:G:R)"},
+
+	/* non-supported format has bpp default to 0 */
+	{0, 0, NULL},
+};
+
+static int skl_format_to_drm(int format, bool rgb_order, bool alpha,
+	int yuv_order)
+{
+	int skl_pixel_formats_index = 14;
+
+	switch (format) {
+	case PLANE_CTL_FORMAT_INDEXED:
+		skl_pixel_formats_index = 4;
+		break;
+	case PLANE_CTL_FORMAT_RGB_565:
+		skl_pixel_formats_index = 5;
+		break;
+	case PLANE_CTL_FORMAT_XRGB_8888:
+		if (rgb_order)
+			skl_pixel_formats_index = alpha ? 6 : 7;
+		else
+			skl_pixel_formats_index = alpha ? 8 : 9;
+		break;
+	case PLANE_CTL_FORMAT_XRGB_2101010:
+		skl_pixel_formats_index = rgb_order ? 10 : 11;
+		break;
+
+	case PLANE_CTL_FORMAT_XRGB_16161616F:
+		skl_pixel_formats_index = rgb_order ? 12 : 13;
+		break;
+
+	case PLANE_CTL_FORMAT_YUV422:
+		skl_pixel_formats_index = yuv_order >> 16;
+		if (skl_pixel_formats_index > 3)
+			return -EINVAL;
+		break;
+
+	default:
+		break;
+	}
+
+	return skl_pixel_formats_index;
+}
+
+static u32 intel_vgpu_get_stride(struct intel_vgpu *vgpu, int pipe,
+	u32 tiled, int stride_mask, int bpp)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+	u32 stride_reg = vgpu_vreg(vgpu, DSPSTRIDE(pipe)) & stride_mask;
+	u32 stride = stride_reg;
+
+	if (IS_SKYLAKE(dev_priv)) {
+		switch (tiled) {
+		case PLANE_CTL_TILED_LINEAR:
+			stride = stride_reg * 64;
+			break;
+		case PLANE_CTL_TILED_X:
+			stride = stride_reg * 512;
+			break;
+		case PLANE_CTL_TILED_Y:
+			stride = stride_reg * 128;
+			break;
+		case PLANE_CTL_TILED_YF:
+			if (bpp == 8)
+				stride = stride_reg * 64;
+			else if (bpp == 16 || bpp == 32 || bpp == 64)
+				stride = stride_reg * 128;
+			else
+				gvt_dbg_core("skl: unsupported bpp:%d\n", bpp);
+			break;
+		default:
+			gvt_dbg_core("skl: unsupported tile format:%x\n",
+				tiled);
+		}
+	}
+
+	return stride;
+}
+
+static int intel_vgpu_decode_primary_plane_format(struct intel_vgpu *vgpu,
+	int pipe, struct intel_vgpu_primary_plane_format *plane)
+{
+	u32	val, fmt;
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+	val = vgpu_vreg(vgpu, DSPCNTR(pipe));
+	plane->enabled = !!(val & DISPLAY_PLANE_ENABLE);
+	if (!plane->enabled)
+		return 0;
+
+	if (IS_SKYLAKE(dev_priv)) {
+		plane->tiled = (val & PLANE_CTL_TILED_MASK) >>
+		_PLANE_CTL_TILED_SHIFT;
+		fmt = skl_format_to_drm(
+			val & PLANE_CTL_FORMAT_MASK,
+			val & PLANE_CTL_ORDER_RGBX,
+			val & PLANE_CTL_ALPHA_MASK,
+			val & PLANE_CTL_YUV422_ORDER_MASK);
+		plane->bpp = skl_pixel_formats[fmt].bpp;
+		plane->drm_format = skl_pixel_formats[fmt].drm_format;
+	} else {
+		plane->tiled = !!(val & DISPPLANE_TILED);
+		fmt = (val & DISPPLANE_PIXFORMAT_MASK) >> _PRI_PLANE_FMT_SHIFT;
+		plane->bpp = primary_pixel_formats[fmt].bpp;
+		plane->drm_format = primary_pixel_formats[fmt].drm_format;
+	}
+
+	if ((IS_SKYLAKE(dev_priv) && !skl_pixel_formats[fmt].bpp)
+		|| (!IS_SKYLAKE(dev_priv) &&
+			!primary_pixel_formats[fmt].bpp)) {
+		gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt);
+		return -EINVAL;
+	}
+
+	plane->hw_format = fmt;
+
+	plane->base = vgpu_vreg(vgpu, DSPSURF(pipe)) & GTT_PAGE_MASK;
+
+	plane->stride = intel_vgpu_get_stride(vgpu, pipe, (plane->tiled << 10),
+		(IS_SKYLAKE(dev_priv)) ? (_PRI_PLANE_STRIDE_MASK >> 6) :
+		_PRI_PLANE_STRIDE_MASK, plane->bpp);
+
+	plane->width = (vgpu_vreg(vgpu, PIPESRC(pipe)) & _PIPE_H_SRCSZ_MASK) >>
+		_PIPE_H_SRCSZ_SHIFT;
+	plane->width += 1;
+	plane->height = (vgpu_vreg(vgpu, PIPESRC(pipe)) &
+			_PIPE_V_SRCSZ_MASK) >> _PIPE_V_SRCSZ_SHIFT;
+	plane->height += 1;	/* raw height is one minus the real value */
+
+	val = vgpu_vreg(vgpu, DSPTILEOFF(pipe));
+	plane->x_offset = (val & _PRI_PLANE_X_OFF_MASK) >>
+		_PRI_PLANE_X_OFF_SHIFT;
+	plane->y_offset = (val & _PRI_PLANE_Y_OFF_MASK) >>
+		_PRI_PLANE_Y_OFF_SHIFT;
+
+	return 0;
+}
+
+#define CURSOR_MODE_NUM	(1 << 6)
+struct cursor_mode_format {
+	int	drm_format;	/* Pixel format in DRM definition */
+	u8	bpp;		/* Bits per pixel; 0 indicates invalid */
+	u32	width;		/* In pixel */
+	u32	height;		/* In lines */
+	char	*desc;		/* The description */
+};
+
+/* non-supported format has bpp default to 0 */
+static struct cursor_mode_format cursor_pixel_formats[CURSOR_MODE_NUM] = {
+	[0x22]  = {DRM_FORMAT_ARGB8888, 32, 128, 128, "128x128 32bpp ARGB"},
+	[0x23]  = {DRM_FORMAT_ARGB8888, 32, 256, 256, "256x256 32bpp ARGB"},
+	[0x27]  = {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"},
+	[0x7]  = {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"},
+};
+
+static int intel_vgpu_decode_cursor_plane_format(struct intel_vgpu *vgpu,
+	int pipe, struct intel_vgpu_cursor_plane_format *plane)
+{
+	u32 val, mode;
+	u32 alpha_plane, alpha_force;
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+	val = vgpu_vreg(vgpu, CURCNTR(pipe));
+	mode = val & CURSOR_MODE;
+	plane->enabled = (mode != CURSOR_MODE_DISABLE);
+	if (!plane->enabled)
+		return 0;
+
+	if (!cursor_pixel_formats[mode].bpp) {
+		gvt_vgpu_err("Non-supported cursor mode (0x%x)\n", mode);
+		return -EINVAL;
+	}
+	plane->mode = mode;
+	plane->bpp = cursor_pixel_formats[mode].bpp;
+	plane->drm_format = cursor_pixel_formats[mode].drm_format;
+	plane->width = cursor_pixel_formats[mode].width;
+	plane->height = cursor_pixel_formats[mode].height;
+
+	alpha_plane = (val & _CURSOR_ALPHA_PLANE_MASK) >>
+				_CURSOR_ALPHA_PLANE_SHIFT;
+	alpha_force = (val & _CURSOR_ALPHA_FORCE_MASK) >>
+				_CURSOR_ALPHA_FORCE_SHIFT;
+	if (alpha_plane || alpha_force)
+		gvt_dbg_core("alpha_plane=0x%x, alpha_force=0x%x\n",
+			alpha_plane, alpha_force);
+
+	plane->base = vgpu_vreg(vgpu, CURBASE(pipe)) & GTT_PAGE_MASK;
+
+	val = vgpu_vreg(vgpu, CURPOS(pipe));
+	plane->x_pos = (val & _CURSOR_POS_X_MASK) >> _CURSOR_POS_X_SHIFT;
+	plane->x_sign = (val & _CURSOR_SIGN_X_MASK) >> _CURSOR_SIGN_X_SHIFT;
+	plane->y_pos = (val & _CURSOR_POS_Y_MASK) >> _CURSOR_POS_Y_SHIFT;
+	plane->y_sign = (val & _CURSOR_SIGN_Y_MASK) >> _CURSOR_SIGN_Y_SHIFT;
+
+	return 0;
+}
+
+#define FORMAT_NUM_SRRITE	(1 << 3)
+
+static struct pixel_format sprite_pixel_formats[FORMAT_NUM_SRRITE] = {
+	[0x0]  = {DRM_FORMAT_YUV422, 16, "YUV 16-bit 4:2:2 packed"},
+	[0x1]  = {DRM_FORMAT_XRGB2101010, 32, "RGB 32-bit 2:10:10:10"},
+	[0x2]  = {DRM_FORMAT_XRGB8888, 32, "RGB 32-bit 8:8:8:8"},
+	[0x3]  = {DRM_FORMAT_XRGB161616_GVT, 64,
+		    "RGB 64-bit 16:16:16:16 Floating Point"},
+	[0x4] = {DRM_FORMAT_AYUV, 32,
+		"YUV 32-bit 4:4:4 packed (8:8:8:8 MSB-X:Y:U:V)"},
+};
+
+static int intel_vgpu_decode_sprite_plane_format(struct intel_vgpu *vgpu,
+	int pipe, struct intel_vgpu_sprite_plane_format *plane)
+{
+	u32 val, fmt;
+	u32 width;
+	u32 color_order, yuv_order;
+	int drm_format;
+
+	val = vgpu_vreg(vgpu, SPRCTL(pipe));
+	plane->enabled = !!(val & SPRITE_ENABLE);
+	if (!plane->enabled)
+		return 0;
+
+	plane->tiled = !!(val & SPRITE_TILED);
+	color_order = !!(val & SPRITE_RGB_ORDER_RGBX);
+	yuv_order = (val & SPRITE_YUV_BYTE_ORDER_MASK) >>
+				_SPRITE_YUV_ORDER_SHIFT;
+
+	fmt = (val & SPRITE_PIXFORMAT_MASK) >> _SPRITE_FMT_SHIFT;
+	if (!sprite_pixel_formats[fmt].bpp) {
+		gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt);
+		return -EINVAL;
+	}
+	plane->hw_format = fmt;
+	plane->bpp = sprite_pixel_formats[fmt].bpp;
+	drm_format = sprite_pixel_formats[fmt].drm_format;
+
+	/* Order of RGB values in an RGBxxx buffer may be ordered RGB or
+	 * BGR depending on the state of the color_order field
+	 */
+	if (!color_order) {
+		if (drm_format == DRM_FORMAT_XRGB2101010)
+			drm_format = DRM_FORMAT_XBGR2101010;
+		else if (drm_format == DRM_FORMAT_XRGB8888)
+			drm_format = DRM_FORMAT_XBGR8888;
+	}
+
+	if (drm_format == DRM_FORMAT_YUV422) {
+		switch (yuv_order) {
+		case	0:
+			drm_format = DRM_FORMAT_YUYV;
+			break;
+		case	1:
+			drm_format = DRM_FORMAT_UYVY;
+			break;
+		case	2:
+			drm_format = DRM_FORMAT_YVYU;
+			break;
+		case	3:
+			drm_format = DRM_FORMAT_VYUY;
+			break;
+		default:
+			/* yuv_order has only 2 bits */
+			break;
+		}
+	}
+
+	plane->drm_format = drm_format;
+
+	plane->base = vgpu_vreg(vgpu, SPRSURF(pipe)) & GTT_PAGE_MASK;
+	plane->width = vgpu_vreg(vgpu, SPRSTRIDE(pipe)) &
+				_SPRITE_STRIDE_MASK;
+	plane->width /= plane->bpp / 8;	/* raw width in bytes */
+
+	val = vgpu_vreg(vgpu, SPRSIZE(pipe));
+	plane->height = (val & _SPRITE_SIZE_HEIGHT_MASK) >>
+		_SPRITE_SIZE_HEIGHT_SHIFT;
+	width = (val & _SPRITE_SIZE_WIDTH_MASK) >> _SPRITE_SIZE_WIDTH_SHIFT;
+	plane->height += 1;	/* raw height is one minus the real value */
+	width += 1;		/* raw width is one minus the real value */
+	if (plane->width != width)
+		gvt_dbg_core("sprite_plane: plane->width=%d, width=%d\n",
+			plane->width, width);
+
+	val = vgpu_vreg(vgpu, SPRPOS(pipe));
+	plane->x_pos = (val & _SPRITE_POS_X_MASK) >> _SPRITE_POS_X_SHIFT;
+	plane->y_pos = (val & _SPRITE_POS_Y_MASK) >> _SPRITE_POS_Y_SHIFT;
+
+	val = vgpu_vreg(vgpu, SPROFFSET(pipe));
+	plane->x_offset = (val & _SPRITE_OFFSET_START_X_MASK) >>
+			   _SPRITE_OFFSET_START_X_SHIFT;
+	plane->y_offset = (val & _SPRITE_OFFSET_START_Y_MASK) >>
+			   _SPRITE_OFFSET_START_Y_SHIFT;
+	return 0;
+}
+
+static int intel_vgpu_decode_fb_format(struct intel_gvt *gvt, int id,
+	struct intel_vgpu_fb_format *fb)
+{
+	int i;
+	struct intel_vgpu *vgpu = NULL;
+	int ret = 0;
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+
+	if (!fb)
+		return -EINVAL;
+
+	/* TODO: use fine-grained refcnt later */
+	mutex_lock(&gvt->lock);
+
+	for_each_active_vgpu(gvt, vgpu, i)
+		if (vgpu->id == id)
+			break;
+
+	if (!vgpu) {
+		gvt_vgpu_err("Invalid vgpu ID (%d)\n", id);
+		mutex_unlock(&gvt->lock);
+		return -ENODEV;
+	}
+
+	for (i = 0; i < I915_MAX_PIPES; i++) {
+		struct intel_vgpu_pipe_format *pipe = &fb->pipes[i];
+		u32 ddi_func_ctl = vgpu_vreg(vgpu, TRANS_DDI_FUNC_CTL(i));
+
+		if (!(ddi_func_ctl & TRANS_DDI_FUNC_ENABLE)) {
+			pipe->ddi_port = DDI_PORT_NONE;
+		} else {
+			u32 port = (ddi_func_ctl & TRANS_DDI_PORT_MASK) >>
+						TRANS_DDI_PORT_SHIFT;
+			if (port <= DDI_PORT_E)
+				pipe->ddi_port = port;
+			else
+				pipe->ddi_port = DDI_PORT_NONE;
+		}
+
+		ret |= intel_vgpu_decode_primary_plane_format(vgpu,
+			i, &pipe->primary);
+		ret |= intel_vgpu_decode_sprite_plane_format(vgpu,
+			i, &pipe->sprite);
+		ret |= intel_vgpu_decode_cursor_plane_format(vgpu,
+			i, &pipe->cursor);
+
+		if (ret) {
+			gvt_vgpu_err("Decode format error for pipe(%d)\n", i);
+			ret = -EINVAL;
+			break;
+		}
+	}
+
+	mutex_unlock(&gvt->lock);
+
+	return ret;
+}
+
+/**
+ * intel_vgpu_decode_plane - Decode plane based on plane id
+ * @dev: drm device
+ * @vgpu: input vgpu
+ * This function is called for decoding plane
+ *
+ * Returns:
+ * pipe on success, NULL if failed.
+ */
+struct intel_vgpu_pipe_format *intel_vgpu_decode_plane(struct drm_device *dev,
+		struct intel_vgpu *vgpu)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_vgpu_fb_format fb;
+	struct intel_vgpu_pipe_format *pipe;
+	int i;
+
+	if (intel_vgpu_decode_fb_format(dev_priv->gvt, vgpu->id, &fb))
+		return NULL;
+
+	for (i = 0; i < I915_MAX_PIPES; i++)
+		if (pipe_is_enabled(vgpu, i))
+			break;
+	if (i >= I915_MAX_PIPES) {
+		gvt_dbg_core("No enabled pipes\n");
+		return NULL;
+	}
+	pipe = &fb.pipes[i];
+
+	if (!pipe || !pipe->primary.enabled) {
+		gvt_dbg_core("Invalid pipe_id :%d\n", i);
+		return NULL;
+	}
+
+	return pipe;
+}
+
diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.h b/drivers/gpu/drm/i915/gvt/fb_decoder.h
new file mode 100644
index 0000000..04300af
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/fb_decoder.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Kevin Tian <kevin.tian@intel.com>
+ *
+ * Contributors:
+ *    Bing Niu <bing.niu@intel.com>
+ *    Xu Han <xu.han@intel.com>
+ *    Ping Gao <ping.a.gao@intel.com>
+ *    Xiaoguang Chen <xiaoguang.chen@intel.com>
+ *    Yang Liu <yang2.liu@intel.com>
+ *
+ */
+
+#ifndef _GVT_FB_DECODER_H_
+#define _GVT_FB_DECODER_H_
+
+#define _PLANE_CTL_FORMAT_SHIFT		24
+#define _PLANE_CTL_TILED_SHIFT		10
+#define _PIPE_V_SRCSZ_SHIFT		0
+#define _PIPE_V_SRCSZ_MASK		(0xfff << _PIPE_V_SRCSZ_SHIFT)
+#define _PIPE_H_SRCSZ_SHIFT		16
+#define _PIPE_H_SRCSZ_MASK		(0x1fff << _PIPE_H_SRCSZ_SHIFT)
+
+#define _PRI_PLANE_FMT_SHIFT		26
+#define _PRI_PLANE_STRIDE_MASK		(0x3ff << 6)
+#define _PRI_PLANE_X_OFF_SHIFT		0
+#define _PRI_PLANE_X_OFF_MASK		(0x1fff << _PRI_PLANE_X_OFF_SHIFT)
+#define _PRI_PLANE_Y_OFF_SHIFT		16
+#define _PRI_PLANE_Y_OFF_MASK		(0xfff << _PRI_PLANE_Y_OFF_SHIFT)
+
+#define _CURSOR_MODE			0x3f
+#define _CURSOR_ALPHA_FORCE_SHIFT	8
+#define _CURSOR_ALPHA_FORCE_MASK	(0x3 << _CURSOR_ALPHA_FORCE_SHIFT)
+#define _CURSOR_ALPHA_PLANE_SHIFT	10
+#define _CURSOR_ALPHA_PLANE_MASK	(0x3 << _CURSOR_ALPHA_PLANE_SHIFT)
+#define _CURSOR_POS_X_SHIFT		0
+#define _CURSOR_POS_X_MASK		(0x1fff << _CURSOR_POS_X_SHIFT)
+#define _CURSOR_SIGN_X_SHIFT		15
+#define _CURSOR_SIGN_X_MASK		(1 << _CURSOR_SIGN_X_SHIFT)
+#define _CURSOR_POS_Y_SHIFT		16
+#define _CURSOR_POS_Y_MASK		(0xfff << _CURSOR_POS_Y_SHIFT)
+#define _CURSOR_SIGN_Y_SHIFT		31
+#define _CURSOR_SIGN_Y_MASK		(1 << _CURSOR_SIGN_Y_SHIFT)
+
+#define _SPRITE_FMT_SHIFT		25
+#define _SPRITE_COLOR_ORDER_SHIFT	20
+#define _SPRITE_YUV_ORDER_SHIFT		16
+#define _SPRITE_STRIDE_SHIFT		6
+#define _SPRITE_STRIDE_MASK		(0x1ff << _SPRITE_STRIDE_SHIFT)
+#define _SPRITE_SIZE_WIDTH_SHIFT	0
+#define _SPRITE_SIZE_HEIGHT_SHIFT	16
+#define _SPRITE_SIZE_WIDTH_MASK		(0x1fff << _SPRITE_SIZE_WIDTH_SHIFT)
+#define _SPRITE_SIZE_HEIGHT_MASK	(0xfff << _SPRITE_SIZE_HEIGHT_SHIFT)
+#define _SPRITE_POS_X_SHIFT		0
+#define _SPRITE_POS_Y_SHIFT		16
+#define _SPRITE_POS_X_MASK		(0x1fff << _SPRITE_POS_X_SHIFT)
+#define _SPRITE_POS_Y_MASK		(0xfff << _SPRITE_POS_Y_SHIFT)
+#define _SPRITE_OFFSET_START_X_SHIFT	0
+#define _SPRITE_OFFSET_START_Y_SHIFT	16
+#define _SPRITE_OFFSET_START_X_MASK	(0x1fff << _SPRITE_OFFSET_START_X_SHIFT)
+#define _SPRITE_OFFSET_START_Y_MASK	(0xfff << _SPRITE_OFFSET_START_Y_SHIFT)
+
+enum GVT_FB_EVENT {
+	FB_MODE_SET_START = 1,
+	FB_MODE_SET_END,
+	FB_DISPLAY_FLIP,
+};
+
+enum DDI_PORT {
+	DDI_PORT_NONE	= 0,
+	DDI_PORT_B	= 1,
+	DDI_PORT_C	= 2,
+	DDI_PORT_D	= 3,
+	DDI_PORT_E	= 4
+};
+
+struct intel_gvt;
+
+struct gvt_fb_notify_msg {
+	unsigned int vm_id;
+	unsigned int pipe_id; /* id starting from 0 */
+	unsigned int plane_id; /* primary, cursor, or sprite */
+};
+
+/* color space conversion and gamma correction are not included */
+struct intel_vgpu_primary_plane_format {
+	u8	enabled;	/* plane is enabled */
+	u8	tiled;		/* X-tiled */
+	u8	bpp;		/* bits per pixel */
+	u32	hw_format;	/* format field in the PRI_CTL register */
+	u32	drm_format;	/* format in DRM definition */
+	u32	base;		/* framebuffer base in graphics memory */
+	u32	x_offset;	/* in pixels */
+	u32	y_offset;	/* in lines */
+	u32	width;		/* in pixels */
+	u32	height;		/* in lines */
+	u32	stride;		/* in bytes */
+};
+
+struct intel_vgpu_sprite_plane_format {
+	u8	enabled;	/* plane is enabled */
+	u8	tiled;		/* X-tiled */
+	u8	bpp;		/* bits per pixel */
+	u32	hw_format;	/* format field in the SPR_CTL register */
+	u32	drm_format;	/* format in DRM definition */
+	u32	base;		/* sprite base in graphics memory */
+	u32	x_pos;		/* in pixels */
+	u32	y_pos;		/* in lines */
+	u32	x_offset;	/* in pixels */
+	u32	y_offset;	/* in lines */
+	u32	width;		/* in pixels */
+	u32	height;		/* in lines */
+};
+
+struct intel_vgpu_cursor_plane_format {
+	u8	enabled;
+	u8	mode;		/* cursor mode select */
+	u8	bpp;		/* bits per pixel */
+	u32	drm_format;	/* format in DRM definition */
+	u32	base;		/* cursor base in graphics memory */
+	u32	x_pos;		/* in pixels */
+	u32	y_pos;		/* in lines */
+	u8	x_sign;		/* X Position Sign */
+	u8	y_sign;		/* Y Position Sign */
+	u32	width;		/* in pixels */
+	u32	height;		/* in lines */
+	u32	x_hot;		/* in pixels */
+	u32	y_hot;		/* in pixels */
+};
+
+struct intel_vgpu_pipe_format {
+	struct intel_vgpu_primary_plane_format	primary;
+	struct intel_vgpu_sprite_plane_format	sprite;
+	struct intel_vgpu_cursor_plane_format	cursor;
+	enum DDI_PORT ddi_port;  /* the DDI port that pipe is connected to */
+};
+
+struct intel_vgpu_fb_format {
+	struct intel_vgpu_pipe_format	pipes[4];
+};
+
+struct intel_vgpu_pipe_format *intel_vgpu_decode_plane(struct drm_device *dev,
+		struct intel_vgpu *vgpu);
+
+#endif
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index 930732e..c42266c 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -46,6 +46,7 @@
 #include "sched_policy.h"
 #include "render.h"
 #include "cmd_parser.h"
+#include "fb_decoder.h"
 
 #define GVT_MAX_VGPU 8
 
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
  2017-05-27  8:38 ` Xiaoguang Chen
                   ` (3 preceding siblings ...)
  (?)
@ 2017-05-27  8:38 ` Xiaoguang Chen
  2017-05-29  7:20     ` Gerd Hoffmann
  -1 siblings, 1 reply; 74+ messages in thread
From: Xiaoguang Chen @ 2017-05-27  8:38 UTC (permalink / raw)
  To: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian
  Cc: Xiaoguang Chen

Here we defined a new ioctl to create a fd for a vfio device based on
the input type. Now only one type is supported that is a dma-buf
management fd.
Two ioctls are defined for the dma-buf management fd: query the vfio
vgpu's plane information and create a dma-buf for a plane.

Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
---
 include/uapi/linux/vfio.h | 50 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index ae46105..308e7a2 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -502,6 +502,56 @@ struct vfio_pci_hot_reset {
 
 #define VFIO_DEVICE_PCI_HOT_RESET	_IO(VFIO_TYPE, VFIO_BASE + 13)
 
+/**
+ * VFIO_DEVICE_GET_FD - _IO(VFIO_TYPE, VFIO_BASE + 14, __u32)
+ *
+ * Create a fd for a vfio device based on the input type
+ * Vendor driver should handle this ioctl to create a fd and manage the
+ * life cycle of this fd.
+ *
+ * Return: a fd if vendor support that type, -errno if not supported
+ */
+
+#define VFIO_DEVICE_GET_FD	_IO(VFIO_TYPE, VFIO_BASE + 14)
+
+#define VFIO_DEVICE_DMABUF_MGR_FD	0 /* Supported fd types */
+
+/*
+ * VFIO_DEVICE_QUERY_PLANE - _IO(VFIO_TYPE, VFIO_BASE + 15, struct plane_info)
+ * Query plane information for a plane
+ */
+struct vfio_vgpu_plane_info {
+	__u32 argsz;
+	__u32 flags;
+	__u32 plane_id;
+	__u32 drm_format;
+	__u32 width;
+	__u32 height;
+	__u32 stride;
+	__u32 start;
+	__u32 x_pos;
+	__u32 y_pos;
+	__u64 drm_format_mod;
+	__u32 size;
+	__u32 pad;
+};
+
+#define VFIO_DEVICE_QUERY_PLANE _IO(VFIO_TYPE, VFIO_BASE + 15)
+
+/*
+ * VFIO_DEVICE_CREATE_DMABUF - _IO(VFIO, VFIO_BASE + 16, struct dmabuf_info)
+ *
+ * Create a dma-buf for a plane
+ */
+struct vfio_vgpu_dmabuf_info {
+	__u32 argsz;
+	__u32 flags;
+	struct vfio_vgpu_plane_info plane_info;
+	__s32 fd;
+	__u32 pad;
+};
+#define VFIO_DEVICE_CREATE_DMABUF _IO(VFIO_TYPE, VFIO_BASE + 16)
+
 /* -------- API for Type1 VFIO IOMMU -------- */
 
 /**
-- 
2.7.4

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

* [PATCH v6 5/6] drm/i915/gvt: Dmabuf support for GVT-g
  2017-05-27  8:38 ` Xiaoguang Chen
@ 2017-05-27  8:38   ` Xiaoguang Chen
  -1 siblings, 0 replies; 74+ messages in thread
From: Xiaoguang Chen @ 2017-05-27  8:38 UTC (permalink / raw)
  To: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian
  Cc: Xiaoguang Chen

dmabuf for GVT-g can be exported to users who can use the dmabuf to show
the desktop of vm which use intel vgpu.

Currently we provide query and create new dmabuf operations.

Users of dmabuf can cache some created dmabufs and related information
such as the framebuffer's address, size, tiling mode, width, height etc.
When refresh the screen first query the currnet vgpu's frambuffer and
compare with the cached ones(address, size, tiling, width, height etc)
if found one then reuse the found dmabuf to gain performance improvment.

If there is no dmabuf created yet or not found in the cached dmabufs then
need to create a new dmabuf. To create a dmabuf first a gem object will
be created and the backing storage of this gem object is the vgpu's
framebuffer(primary/cursor).
Set caching mode, change tiling mode and set domains of this gem object
is not supported.
Then associate this gem object to a dmabuf and export this dmabuf.
A file descriptor will be generated for this dmabuf and this file
descriptor can be sent to user space to do display.

Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
---
 drivers/gpu/drm/i915/gvt/Makefile      |   2 +-
 drivers/gpu/drm/i915/gvt/dmabuf.c      | 269 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/dmabuf.h      |  37 +++++
 drivers/gpu/drm/i915/gvt/gvt.h         |   1 +
 drivers/gpu/drm/i915/i915_gem.c        |  26 +++-
 drivers/gpu/drm/i915/i915_gem_object.h |   9 ++
 6 files changed, 342 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gvt/dmabuf.c
 create mode 100644 drivers/gpu/drm/i915/gvt/dmabuf.h

diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile
index 192ca26..e480f7d 100644
--- a/drivers/gpu/drm/i915/gvt/Makefile
+++ b/drivers/gpu/drm/i915/gvt/Makefile
@@ -2,7 +2,7 @@ GVT_DIR := gvt
 GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \
 	interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \
 	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o \
-	fb_decoder.o
+	fb_decoder.o dmabuf.o
 
 ccflags-y				+= -I$(src) -I$(src)/$(GVT_DIR) -Wall
 i915-y					+= $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
new file mode 100644
index 0000000..c831e91
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2017 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ *    Xiaoguang Chen <xiaoguang.chen@intel.com>
+ */
+
+#include <linux/dma-buf.h>
+#include <drm/drmP.h>
+#include <linux/vfio.h>
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+#define GEN8_DECODE_PTE(pte) (pte & GENMASK_ULL(63, 12))
+
+static struct sg_table *intel_vgpu_gem_get_pages(
+		struct drm_i915_gem_object *obj)
+{
+	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+	struct sg_table *st;
+	struct scatterlist *sg;
+	int i, ret;
+	gen8_pte_t __iomem *gtt_entries;
+	struct intel_vgpu_fb_info *fb_info;
+
+	fb_info = (struct intel_vgpu_fb_info *)obj->gvt_info;
+	if (WARN_ON(!fb_info))
+		return ERR_PTR(-ENODEV);
+
+	st = kmalloc(sizeof(*st), GFP_KERNEL);
+	if (!st) {
+		ret = -ENOMEM;
+		return ERR_PTR(ret);
+	}
+
+	ret = sg_alloc_table(st, fb_info->fb_size, GFP_KERNEL);
+	if (ret) {
+		kfree(st);
+		return ERR_PTR(ret);
+	}
+	gtt_entries = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm +
+		(fb_info->fb_addr >> PAGE_SHIFT);
+	for_each_sg(st->sgl, sg, fb_info->fb_size, i) {
+		sg->offset = 0;
+		sg->length = PAGE_SIZE;
+		sg_dma_address(sg) =
+			GEN8_DECODE_PTE(readq(&gtt_entries[i]));
+		sg_dma_len(sg) = PAGE_SIZE;
+	}
+
+	return st;
+}
+
+static void intel_vgpu_gem_put_pages(struct drm_i915_gem_object *obj,
+		struct sg_table *pages)
+{
+	sg_free_table(pages);
+	kfree(pages);
+}
+
+static const struct drm_i915_gem_object_ops intel_vgpu_gem_ops = {
+	.flags = I915_GEM_OBJECT_IS_PROXY,
+	.get_pages = intel_vgpu_gem_get_pages,
+	.put_pages = intel_vgpu_gem_put_pages,
+};
+
+static struct drm_i915_gem_object *intel_vgpu_create_gem(struct drm_device *dev,
+		struct vfio_vgpu_plane_info *info)
+{
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_gem_object *obj;
+
+	obj = i915_gem_object_alloc(dev_priv);
+	if (obj == NULL)
+		return NULL;
+
+	drm_gem_private_object_init(dev, &obj->base,
+		info->size << PAGE_SHIFT);
+	i915_gem_object_init(obj, &intel_vgpu_gem_ops);
+
+	obj->base.read_domains = I915_GEM_DOMAIN_GTT;
+	obj->base.write_domain = 0;
+	/* Change tiling mode from user space is not supported to a GVT-g's
+	 * dma-buf gem object.
+	 * We increase the obj's framebuffer_references to disable this kind
+	 * of operation.
+	 */
+	obj->framebuffer_references++;
+	if (IS_SKYLAKE(dev_priv)) {
+		unsigned int tiling_mode = 0;
+		unsigned int stride = 0;
+
+		switch (info->drm_format_mod << 10) {
+		case PLANE_CTL_TILED_LINEAR:
+			tiling_mode = I915_TILING_NONE;
+			break;
+		case PLANE_CTL_TILED_X:
+			tiling_mode = I915_TILING_X;
+			stride = info->stride;
+			break;
+		case PLANE_CTL_TILED_Y:
+			tiling_mode = I915_TILING_Y;
+			stride = info->stride;
+			break;
+		default:
+			gvt_dbg_core("not supported tiling mode\n");
+		}
+		obj->tiling_and_stride = tiling_mode | stride;
+	} else {
+		obj->tiling_and_stride = info->drm_format_mod ?
+					I915_TILING_X : 0;
+	}
+
+	return obj;
+}
+
+static int intel_vgpu_get_plane_info(struct drm_device *dev,
+		struct intel_vgpu *vgpu, struct vfio_vgpu_plane_info *info)
+{
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct intel_vgpu_primary_plane_format *p;
+	struct intel_vgpu_cursor_plane_format *c;
+	struct intel_vgpu_pipe_format *pipe;
+	int plane_id = info->plane_id;
+
+	pipe = intel_vgpu_decode_plane(dev, vgpu);
+	if (pipe == NULL)
+		return -ENODEV;
+
+	if (plane_id == PLANE_PRIMARY) {
+		p = &pipe->primary;
+		if (p != NULL) {
+			info->start = p->base;
+			info->width = p->width;
+			info->height = p->height;
+			info->stride = p->stride;
+			info->drm_format = p->drm_format;
+			info->drm_format_mod = p->tiled;
+			info->size = (((p->stride * p->height * p->bpp) / 8) +
+					(PAGE_SIZE - 1)) >> PAGE_SHIFT;
+		} else {
+			gvt_vgpu_err("invalid primary plane\n");
+			return -EINVAL;
+		}
+	} else if (plane_id == PLANE_CURSOR) {
+		c = &pipe->cursor;
+		if (c != NULL) {
+			info->start = c->base;
+			info->width = c->width;
+			info->height = c->height;
+			info->stride = c->width * (c->bpp / 8);
+			info->drm_format = c->drm_format;
+			info->drm_format_mod = 0;
+			info->x_pos = c->x_pos;
+			info->y_pos = c->y_pos;
+			info->size = (((info->stride * c->height * c->bpp) / 8)
+					+ (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+		} else {
+			gvt_vgpu_err("invalid cursor plane\n");
+			return -EINVAL;
+		}
+	} else {
+		gvt_vgpu_err("invalid plane id:%d\n", plane_id);
+		return -EINVAL;
+	}
+
+	if (info->size == 0) {
+		gvt_vgpu_err("fb size is zero\n");
+		return -EINVAL;
+	}
+
+	if (info->start & (PAGE_SIZE - 1)) {
+		gvt_vgpu_err("Not aligned fb address:0x%x\n", info->start);
+		return -EFAULT;
+	}
+	if (((info->start >> PAGE_SHIFT) + info->size) >
+		ggtt_total_entries(&dev_priv->ggtt)) {
+		gvt_vgpu_err("Invalid GTT offset or size\n");
+		return -EFAULT;
+	}
+
+	if (!intel_gvt_ggtt_validate_range(vgpu, info->start, info->size)) {
+		gvt_vgpu_err("invalid gma addr\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args)
+{
+	struct drm_device *dev = &vgpu->gvt->dev_priv->drm;
+	struct vfio_vgpu_plane_info *info = args;
+
+	return intel_vgpu_get_plane_info(dev, vgpu, info);
+}
+
+int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args)
+{
+	struct dma_buf *dmabuf;
+	struct drm_i915_gem_object *obj;
+	struct drm_device *dev = &vgpu->gvt->dev_priv->drm;
+	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
+	struct intel_vgpu_fb_info *fb_info;
+	int ret;
+
+	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
+	if (ret != 0)
+		return ret;
+
+	obj = intel_vgpu_create_gem(dev, &gvt_dmabuf->plane_info);
+	if (obj == NULL) {
+		gvt_vgpu_err("create gvt gem obj failed:%d\n", vgpu->id);
+		return -ENOMEM;
+	}
+	fb_info = kmalloc(sizeof(*fb_info), GFP_KERNEL);
+	if (!fb_info) {
+		i915_gem_object_put(obj);
+		gvt_vgpu_err("allocate intel vgpu fb info failed\n");
+		return -ENOMEM;
+	}
+	fb_info->fb_addr = gvt_dmabuf->plane_info.start;
+	fb_info->fb_size = gvt_dmabuf->plane_info.size;
+	fb_info->vgpu = vgpu;
+	obj->gvt_info = fb_info;
+
+	dmabuf = i915_gem_prime_export(dev, &obj->base, DRM_CLOEXEC | DRM_RDWR);
+
+	if (IS_ERR(dmabuf)) {
+		kfree(fb_info);
+		i915_gem_object_free(obj);
+		gvt_vgpu_err("export dma-buf failed\n");
+		return PTR_ERR(dmabuf);
+	}
+
+	ret = dma_buf_fd(dmabuf, DRM_CLOEXEC | DRM_RDWR);
+	if (ret < 0) {
+		kfree(fb_info);
+		i915_gem_object_free(obj);
+		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
+		return ret;
+	}
+	gvt_dmabuf->fd = ret;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h b/drivers/gpu/drm/i915/gvt/dmabuf.h
new file mode 100644
index 0000000..8be9979
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _GVT_DMABUF_H_
+#define _GVT_DMABUF_H_
+
+struct intel_vgpu_fb_info {
+	struct intel_vgpu *vgpu;
+	uint32_t fb_addr;
+	uint32_t fb_size;
+};
+
+int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);
+int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args);
+
+#endif
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index c42266c..763a8c5 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -47,6 +47,7 @@
 #include "render.h"
 #include "cmd_parser.h"
 #include "fb_decoder.h"
+#include "dmabuf.h"
 
 #define GVT_MAX_VGPU 8
 
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 0c1cbe9..14be3b0 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1609,6 +1609,12 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
 	if (!obj)
 		return -ENOENT;
 
+	/* proxy gem object does not support setting domain */
+	if (i915_gem_object_is_proxy(obj)) {
+		i915_gem_object_put(obj);
+		return -EPERM;
+	}
+
 	/* Try to flush the object off the GPU without holding the lock.
 	 * We will repeat the flush holding the lock in the normal manner
 	 * to catch cases where we are gazumped.
@@ -1677,6 +1683,12 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
 	if (!obj)
 		return -ENOENT;
 
+	/* proxy gem obj does not support this operation */
+	if (i915_gem_object_is_proxy(obj)) {
+		i915_gem_object_put(obj);
+		return -EPERM;
+	}
+
 	/* Pinned buffers may be scanout, so flush the cache */
 	i915_gem_object_flush_if_display(obj);
 	i915_gem_object_put(obj);
@@ -1727,7 +1739,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
 	 */
 	if (!obj->base.filp) {
 		i915_gem_object_put(obj);
-		return -EINVAL;
+		return -EPERM;
 	}
 
 	addr = vm_mmap(obj->base.filp, 0, args->size,
@@ -3717,6 +3729,12 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
 	if (!obj)
 		return -ENOENT;
 
+	/* proxy gem obj does not support setting caching mode */
+	if (i915_gem_object_is_proxy(obj)) {
+		i915_gem_object_put(obj);
+		return -EPERM;
+	}
+
 	if (obj->cache_level == level)
 		goto out;
 
@@ -4168,6 +4186,12 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
 	if (!obj)
 		return -ENOENT;
 
+	/* proxy gem obj does not support changing backding storage */
+	if (i915_gem_object_is_proxy(obj)) {
+		i915_gem_object_put(obj);
+		return -EPERM;
+	}
+
 	err = mutex_lock_interruptible(&obj->mm.lock);
 	if (err)
 		goto out;
diff --git a/drivers/gpu/drm/i915/i915_gem_object.h b/drivers/gpu/drm/i915/i915_gem_object.h
index 174cf92..be18a43 100644
--- a/drivers/gpu/drm/i915/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/i915_gem_object.h
@@ -39,6 +39,7 @@ struct drm_i915_gem_object_ops {
 	unsigned int flags;
 #define I915_GEM_OBJECT_HAS_STRUCT_PAGE 0x1
 #define I915_GEM_OBJECT_IS_SHRINKABLE   0x2
+#define I915_GEM_OBJECT_IS_PROXY	0x4
 
 	/* Interface between the GEM object and its backing storage.
 	 * get_pages() is called once prior to the use of the associated set
@@ -184,6 +185,8 @@ struct drm_i915_gem_object {
 		} userptr;
 
 		unsigned long scratch;
+
+		void *gvt_info;
 	};
 
 	/** for phys allocated objects */
@@ -286,6 +289,12 @@ i915_gem_object_is_shrinkable(const struct drm_i915_gem_object *obj)
 }
 
 static inline bool
+i915_gem_object_is_proxy(const struct drm_i915_gem_object *obj)
+{
+	return obj->ops->flags & I915_GEM_OBJECT_IS_PROXY;
+}
+
+static inline bool
 i915_gem_object_is_active(const struct drm_i915_gem_object *obj)
 {
 	return obj->active_count;
-- 
2.7.4

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

* [PATCH v6 5/6] drm/i915/gvt: Dmabuf support for GVT-g
@ 2017-05-27  8:38   ` Xiaoguang Chen
  0 siblings, 0 replies; 74+ messages in thread
From: Xiaoguang Chen @ 2017-05-27  8:38 UTC (permalink / raw)
  To: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian
  Cc: Xiaoguang Chen

dmabuf for GVT-g can be exported to users who can use the dmabuf to show
the desktop of vm which use intel vgpu.

Currently we provide query and create new dmabuf operations.

Users of dmabuf can cache some created dmabufs and related information
such as the framebuffer's address, size, tiling mode, width, height etc.
When refresh the screen first query the currnet vgpu's frambuffer and
compare with the cached ones(address, size, tiling, width, height etc)
if found one then reuse the found dmabuf to gain performance improvment.

If there is no dmabuf created yet or not found in the cached dmabufs then
need to create a new dmabuf. To create a dmabuf first a gem object will
be created and the backing storage of this gem object is the vgpu's
framebuffer(primary/cursor).
Set caching mode, change tiling mode and set domains of this gem object
is not supported.
Then associate this gem object to a dmabuf and export this dmabuf.
A file descriptor will be generated for this dmabuf and this file
descriptor can be sent to user space to do display.

Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
---
 drivers/gpu/drm/i915/gvt/Makefile      |   2 +-
 drivers/gpu/drm/i915/gvt/dmabuf.c      | 269 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/dmabuf.h      |  37 +++++
 drivers/gpu/drm/i915/gvt/gvt.h         |   1 +
 drivers/gpu/drm/i915/i915_gem.c        |  26 +++-
 drivers/gpu/drm/i915/i915_gem_object.h |   9 ++
 6 files changed, 342 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gvt/dmabuf.c
 create mode 100644 drivers/gpu/drm/i915/gvt/dmabuf.h

diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile
index 192ca26..e480f7d 100644
--- a/drivers/gpu/drm/i915/gvt/Makefile
+++ b/drivers/gpu/drm/i915/gvt/Makefile
@@ -2,7 +2,7 @@ GVT_DIR := gvt
 GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \
 	interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \
 	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o \
-	fb_decoder.o
+	fb_decoder.o dmabuf.o
 
 ccflags-y				+= -I$(src) -I$(src)/$(GVT_DIR) -Wall
 i915-y					+= $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
new file mode 100644
index 0000000..c831e91
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2017 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ *    Xiaoguang Chen <xiaoguang.chen@intel.com>
+ */
+
+#include <linux/dma-buf.h>
+#include <drm/drmP.h>
+#include <linux/vfio.h>
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+#define GEN8_DECODE_PTE(pte) (pte & GENMASK_ULL(63, 12))
+
+static struct sg_table *intel_vgpu_gem_get_pages(
+		struct drm_i915_gem_object *obj)
+{
+	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+	struct sg_table *st;
+	struct scatterlist *sg;
+	int i, ret;
+	gen8_pte_t __iomem *gtt_entries;
+	struct intel_vgpu_fb_info *fb_info;
+
+	fb_info = (struct intel_vgpu_fb_info *)obj->gvt_info;
+	if (WARN_ON(!fb_info))
+		return ERR_PTR(-ENODEV);
+
+	st = kmalloc(sizeof(*st), GFP_KERNEL);
+	if (!st) {
+		ret = -ENOMEM;
+		return ERR_PTR(ret);
+	}
+
+	ret = sg_alloc_table(st, fb_info->fb_size, GFP_KERNEL);
+	if (ret) {
+		kfree(st);
+		return ERR_PTR(ret);
+	}
+	gtt_entries = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm +
+		(fb_info->fb_addr >> PAGE_SHIFT);
+	for_each_sg(st->sgl, sg, fb_info->fb_size, i) {
+		sg->offset = 0;
+		sg->length = PAGE_SIZE;
+		sg_dma_address(sg) =
+			GEN8_DECODE_PTE(readq(&gtt_entries[i]));
+		sg_dma_len(sg) = PAGE_SIZE;
+	}
+
+	return st;
+}
+
+static void intel_vgpu_gem_put_pages(struct drm_i915_gem_object *obj,
+		struct sg_table *pages)
+{
+	sg_free_table(pages);
+	kfree(pages);
+}
+
+static const struct drm_i915_gem_object_ops intel_vgpu_gem_ops = {
+	.flags = I915_GEM_OBJECT_IS_PROXY,
+	.get_pages = intel_vgpu_gem_get_pages,
+	.put_pages = intel_vgpu_gem_put_pages,
+};
+
+static struct drm_i915_gem_object *intel_vgpu_create_gem(struct drm_device *dev,
+		struct vfio_vgpu_plane_info *info)
+{
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_gem_object *obj;
+
+	obj = i915_gem_object_alloc(dev_priv);
+	if (obj == NULL)
+		return NULL;
+
+	drm_gem_private_object_init(dev, &obj->base,
+		info->size << PAGE_SHIFT);
+	i915_gem_object_init(obj, &intel_vgpu_gem_ops);
+
+	obj->base.read_domains = I915_GEM_DOMAIN_GTT;
+	obj->base.write_domain = 0;
+	/* Change tiling mode from user space is not supported to a GVT-g's
+	 * dma-buf gem object.
+	 * We increase the obj's framebuffer_references to disable this kind
+	 * of operation.
+	 */
+	obj->framebuffer_references++;
+	if (IS_SKYLAKE(dev_priv)) {
+		unsigned int tiling_mode = 0;
+		unsigned int stride = 0;
+
+		switch (info->drm_format_mod << 10) {
+		case PLANE_CTL_TILED_LINEAR:
+			tiling_mode = I915_TILING_NONE;
+			break;
+		case PLANE_CTL_TILED_X:
+			tiling_mode = I915_TILING_X;
+			stride = info->stride;
+			break;
+		case PLANE_CTL_TILED_Y:
+			tiling_mode = I915_TILING_Y;
+			stride = info->stride;
+			break;
+		default:
+			gvt_dbg_core("not supported tiling mode\n");
+		}
+		obj->tiling_and_stride = tiling_mode | stride;
+	} else {
+		obj->tiling_and_stride = info->drm_format_mod ?
+					I915_TILING_X : 0;
+	}
+
+	return obj;
+}
+
+static int intel_vgpu_get_plane_info(struct drm_device *dev,
+		struct intel_vgpu *vgpu, struct vfio_vgpu_plane_info *info)
+{
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct intel_vgpu_primary_plane_format *p;
+	struct intel_vgpu_cursor_plane_format *c;
+	struct intel_vgpu_pipe_format *pipe;
+	int plane_id = info->plane_id;
+
+	pipe = intel_vgpu_decode_plane(dev, vgpu);
+	if (pipe == NULL)
+		return -ENODEV;
+
+	if (plane_id == PLANE_PRIMARY) {
+		p = &pipe->primary;
+		if (p != NULL) {
+			info->start = p->base;
+			info->width = p->width;
+			info->height = p->height;
+			info->stride = p->stride;
+			info->drm_format = p->drm_format;
+			info->drm_format_mod = p->tiled;
+			info->size = (((p->stride * p->height * p->bpp) / 8) +
+					(PAGE_SIZE - 1)) >> PAGE_SHIFT;
+		} else {
+			gvt_vgpu_err("invalid primary plane\n");
+			return -EINVAL;
+		}
+	} else if (plane_id == PLANE_CURSOR) {
+		c = &pipe->cursor;
+		if (c != NULL) {
+			info->start = c->base;
+			info->width = c->width;
+			info->height = c->height;
+			info->stride = c->width * (c->bpp / 8);
+			info->drm_format = c->drm_format;
+			info->drm_format_mod = 0;
+			info->x_pos = c->x_pos;
+			info->y_pos = c->y_pos;
+			info->size = (((info->stride * c->height * c->bpp) / 8)
+					+ (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+		} else {
+			gvt_vgpu_err("invalid cursor plane\n");
+			return -EINVAL;
+		}
+	} else {
+		gvt_vgpu_err("invalid plane id:%d\n", plane_id);
+		return -EINVAL;
+	}
+
+	if (info->size == 0) {
+		gvt_vgpu_err("fb size is zero\n");
+		return -EINVAL;
+	}
+
+	if (info->start & (PAGE_SIZE - 1)) {
+		gvt_vgpu_err("Not aligned fb address:0x%x\n", info->start);
+		return -EFAULT;
+	}
+	if (((info->start >> PAGE_SHIFT) + info->size) >
+		ggtt_total_entries(&dev_priv->ggtt)) {
+		gvt_vgpu_err("Invalid GTT offset or size\n");
+		return -EFAULT;
+	}
+
+	if (!intel_gvt_ggtt_validate_range(vgpu, info->start, info->size)) {
+		gvt_vgpu_err("invalid gma addr\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args)
+{
+	struct drm_device *dev = &vgpu->gvt->dev_priv->drm;
+	struct vfio_vgpu_plane_info *info = args;
+
+	return intel_vgpu_get_plane_info(dev, vgpu, info);
+}
+
+int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args)
+{
+	struct dma_buf *dmabuf;
+	struct drm_i915_gem_object *obj;
+	struct drm_device *dev = &vgpu->gvt->dev_priv->drm;
+	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
+	struct intel_vgpu_fb_info *fb_info;
+	int ret;
+
+	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
+	if (ret != 0)
+		return ret;
+
+	obj = intel_vgpu_create_gem(dev, &gvt_dmabuf->plane_info);
+	if (obj == NULL) {
+		gvt_vgpu_err("create gvt gem obj failed:%d\n", vgpu->id);
+		return -ENOMEM;
+	}
+	fb_info = kmalloc(sizeof(*fb_info), GFP_KERNEL);
+	if (!fb_info) {
+		i915_gem_object_put(obj);
+		gvt_vgpu_err("allocate intel vgpu fb info failed\n");
+		return -ENOMEM;
+	}
+	fb_info->fb_addr = gvt_dmabuf->plane_info.start;
+	fb_info->fb_size = gvt_dmabuf->plane_info.size;
+	fb_info->vgpu = vgpu;
+	obj->gvt_info = fb_info;
+
+	dmabuf = i915_gem_prime_export(dev, &obj->base, DRM_CLOEXEC | DRM_RDWR);
+
+	if (IS_ERR(dmabuf)) {
+		kfree(fb_info);
+		i915_gem_object_free(obj);
+		gvt_vgpu_err("export dma-buf failed\n");
+		return PTR_ERR(dmabuf);
+	}
+
+	ret = dma_buf_fd(dmabuf, DRM_CLOEXEC | DRM_RDWR);
+	if (ret < 0) {
+		kfree(fb_info);
+		i915_gem_object_free(obj);
+		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
+		return ret;
+	}
+	gvt_dmabuf->fd = ret;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h b/drivers/gpu/drm/i915/gvt/dmabuf.h
new file mode 100644
index 0000000..8be9979
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _GVT_DMABUF_H_
+#define _GVT_DMABUF_H_
+
+struct intel_vgpu_fb_info {
+	struct intel_vgpu *vgpu;
+	uint32_t fb_addr;
+	uint32_t fb_size;
+};
+
+int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);
+int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args);
+
+#endif
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index c42266c..763a8c5 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -47,6 +47,7 @@
 #include "render.h"
 #include "cmd_parser.h"
 #include "fb_decoder.h"
+#include "dmabuf.h"
 
 #define GVT_MAX_VGPU 8
 
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 0c1cbe9..14be3b0 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1609,6 +1609,12 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
 	if (!obj)
 		return -ENOENT;
 
+	/* proxy gem object does not support setting domain */
+	if (i915_gem_object_is_proxy(obj)) {
+		i915_gem_object_put(obj);
+		return -EPERM;
+	}
+
 	/* Try to flush the object off the GPU without holding the lock.
 	 * We will repeat the flush holding the lock in the normal manner
 	 * to catch cases where we are gazumped.
@@ -1677,6 +1683,12 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
 	if (!obj)
 		return -ENOENT;
 
+	/* proxy gem obj does not support this operation */
+	if (i915_gem_object_is_proxy(obj)) {
+		i915_gem_object_put(obj);
+		return -EPERM;
+	}
+
 	/* Pinned buffers may be scanout, so flush the cache */
 	i915_gem_object_flush_if_display(obj);
 	i915_gem_object_put(obj);
@@ -1727,7 +1739,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
 	 */
 	if (!obj->base.filp) {
 		i915_gem_object_put(obj);
-		return -EINVAL;
+		return -EPERM;
 	}
 
 	addr = vm_mmap(obj->base.filp, 0, args->size,
@@ -3717,6 +3729,12 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
 	if (!obj)
 		return -ENOENT;
 
+	/* proxy gem obj does not support setting caching mode */
+	if (i915_gem_object_is_proxy(obj)) {
+		i915_gem_object_put(obj);
+		return -EPERM;
+	}
+
 	if (obj->cache_level == level)
 		goto out;
 
@@ -4168,6 +4186,12 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
 	if (!obj)
 		return -ENOENT;
 
+	/* proxy gem obj does not support changing backding storage */
+	if (i915_gem_object_is_proxy(obj)) {
+		i915_gem_object_put(obj);
+		return -EPERM;
+	}
+
 	err = mutex_lock_interruptible(&obj->mm.lock);
 	if (err)
 		goto out;
diff --git a/drivers/gpu/drm/i915/i915_gem_object.h b/drivers/gpu/drm/i915/i915_gem_object.h
index 174cf92..be18a43 100644
--- a/drivers/gpu/drm/i915/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/i915_gem_object.h
@@ -39,6 +39,7 @@ struct drm_i915_gem_object_ops {
 	unsigned int flags;
 #define I915_GEM_OBJECT_HAS_STRUCT_PAGE 0x1
 #define I915_GEM_OBJECT_IS_SHRINKABLE   0x2
+#define I915_GEM_OBJECT_IS_PROXY	0x4
 
 	/* Interface between the GEM object and its backing storage.
 	 * get_pages() is called once prior to the use of the associated set
@@ -184,6 +185,8 @@ struct drm_i915_gem_object {
 		} userptr;
 
 		unsigned long scratch;
+
+		void *gvt_info;
 	};
 
 	/** for phys allocated objects */
@@ -286,6 +289,12 @@ i915_gem_object_is_shrinkable(const struct drm_i915_gem_object *obj)
 }
 
 static inline bool
+i915_gem_object_is_proxy(const struct drm_i915_gem_object *obj)
+{
+	return obj->ops->flags & I915_GEM_OBJECT_IS_PROXY;
+}
+
+static inline bool
 i915_gem_object_is_active(const struct drm_i915_gem_object *obj)
 {
 	return obj->active_count;
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
  2017-05-27  8:38 ` Xiaoguang Chen
@ 2017-05-27  8:38   ` Xiaoguang Chen
  -1 siblings, 0 replies; 74+ messages in thread
From: Xiaoguang Chen @ 2017-05-27  8:38 UTC (permalink / raw)
  To: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian
  Cc: Xiaoguang Chen

User space should create the management fd for the dma-buf operation first.
Then user can query the plane information and create dma-buf if necessary
using the management fd.

Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
---
 drivers/gpu/drm/i915/gvt/dmabuf.c |  12 ++++
 drivers/gpu/drm/i915/gvt/dmabuf.h |   5 ++
 drivers/gpu/drm/i915/gvt/gvt.c    |   2 +
 drivers/gpu/drm/i915/gvt/gvt.h    |   5 ++
 drivers/gpu/drm/i915/gvt/kvmgt.c  | 144 ++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/vgpu.c   |   1 +
 6 files changed, 169 insertions(+)

diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
index c831e91..9759e9a 100644
--- a/drivers/gpu/drm/i915/gvt/dmabuf.c
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
@@ -226,6 +226,7 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args)
 	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
 	struct intel_vgpu_fb_info *fb_info;
 	int ret;
+	struct intel_vgpu_dmabuf_obj *dmabuf_obj;
 
 	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
 	if (ret != 0)
@@ -263,6 +264,17 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args)
 		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
 		return ret;
 	}
+	dmabuf_obj = kmalloc(sizeof(*dmabuf_obj), GFP_KERNEL);
+	if (dmabuf_obj == NULL) {
+		kfree(fb_info);
+		i915_gem_object_put(obj);
+		gvt_vgpu_err("alloc dmabuf_obj failed\n");
+		return -ENOMEM;
+	}
+	dmabuf_obj->obj = obj;
+	INIT_LIST_HEAD(&dmabuf_obj->list);
+	list_add_tail(&dmabuf_obj->list, &vgpu->dmabuf_obj_list_head);
+
 	gvt_dmabuf->fd = ret;
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h b/drivers/gpu/drm/i915/gvt/dmabuf.h
index 8be9979..cafa781 100644
--- a/drivers/gpu/drm/i915/gvt/dmabuf.h
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
@@ -31,6 +31,11 @@ struct intel_vgpu_fb_info {
 	uint32_t fb_size;
 };
 
+struct intel_vgpu_dmabuf_obj {
+	struct drm_i915_gem_object *obj;
+	struct list_head list;
+};
+
 int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);
 int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args);
 
diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c
index 2032917..dbc3f86 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.c
+++ b/drivers/gpu/drm/i915/gvt/gvt.c
@@ -54,6 +54,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {
 	.vgpu_reset = intel_gvt_reset_vgpu,
 	.vgpu_activate = intel_gvt_activate_vgpu,
 	.vgpu_deactivate = intel_gvt_deactivate_vgpu,
+	.vgpu_query_plane = intel_vgpu_query_plane,
+	.vgpu_create_dmabuf = intel_vgpu_create_dmabuf,
 };
 
 /**
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index 763a8c5..a855797 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -185,8 +185,11 @@ struct intel_vgpu {
 		struct kvm *kvm;
 		struct work_struct release_work;
 		atomic_t released;
+		struct vfio_device *vfio_device;
 	} vdev;
 #endif
+	int dmabuf_mgr_fd;
+	struct list_head dmabuf_obj_list_head;
 };
 
 struct intel_gvt_gm {
@@ -467,6 +470,8 @@ struct intel_gvt_ops {
 	void (*vgpu_reset)(struct intel_vgpu *);
 	void (*vgpu_activate)(struct intel_vgpu *);
 	void (*vgpu_deactivate)(struct intel_vgpu *);
+	int (*vgpu_query_plane)(struct intel_vgpu *vgpu, void *);
+	int (*vgpu_create_dmabuf)(struct intel_vgpu *vgpu, void *);
 };
 
 
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 389f072..a079080 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -41,6 +41,7 @@
 #include <linux/kvm_host.h>
 #include <linux/vfio.h>
 #include <linux/mdev.h>
+#include <linux/anon_inodes.h>
 
 #include "i915_drv.h"
 #include "gvt.h"
@@ -524,6 +525,125 @@ static int intel_vgpu_reg_init_opregion(struct intel_vgpu *vgpu)
 	return ret;
 }
 
+static int kvmgt_get_vfio_device(struct intel_vgpu *vgpu)
+{
+	struct vfio_device *device;
+
+	device = vfio_device_get_from_dev(mdev_dev(vgpu->vdev.mdev));
+	if (device == NULL)
+		return -ENODEV;
+	vgpu->vdev.vfio_device = device;
+
+	return 0;
+}
+
+static void kvmgt_put_vfio_device(struct intel_vgpu *vgpu)
+{
+	vfio_device_put(vgpu->vdev.vfio_device);
+}
+
+static int intel_vgpu_dmabuf_mgr_fd_mmap(struct file *file,
+		struct vm_area_struct *vma)
+{
+	return -EPERM;
+}
+
+static int intel_vgpu_dmabuf_mgr_fd_release(struct inode *inode,
+		struct file *filp)
+{
+	struct intel_vgpu *vgpu = filp->private_data;
+	struct intel_vgpu_dmabuf_obj *obj;
+	struct list_head *pos;
+
+	if (WARN_ON(!vgpu->vdev.vfio_device))
+		return -ENODEV;
+
+	list_for_each(pos, &vgpu->dmabuf_obj_list_head) {
+		obj = container_of(pos, struct intel_vgpu_dmabuf_obj, list);
+		if (WARN_ON(!obj))
+			return -ENODEV;
+		kfree(obj->obj->gvt_info);
+		i915_gem_object_put(obj->obj);
+		kfree(obj);
+		kvmgt_put_vfio_device(vgpu);
+	}
+	kvmgt_put_vfio_device(vgpu);
+
+	return 0;
+}
+
+static long intel_vgpu_dmabuf_mgr_fd_ioctl(struct file *filp,
+		unsigned int ioctl, unsigned long arg)
+{
+	struct intel_vgpu *vgpu = filp->private_data;
+	int minsz;
+	int ret;
+	struct fd f;
+
+	f = fdget(vgpu->dmabuf_mgr_fd);
+	if (!f.file)
+		return -EBADF;
+
+	if (ioctl == VFIO_DEVICE_QUERY_PLANE) {
+		struct vfio_vgpu_plane_info info;
+
+		minsz = offsetofend(struct vfio_vgpu_plane_info, resv);
+		if (copy_from_user(&info, (void __user *)arg, minsz)) {
+			fdput(f);
+			return -EFAULT;
+		}
+		if (info.argsz < minsz) {
+			fdput(f);
+			return -EINVAL;
+		}
+		ret = intel_gvt_ops->vgpu_query_plane(vgpu, &info);
+		if (ret != 0) {
+			fdput(f);
+			gvt_vgpu_err("query plane failed:%d\n", ret);
+			return -EINVAL;
+		}
+		fdput(f);
+		return copy_to_user((void __user *)arg, &info, minsz) ?
+								-EFAULT : 0;
+	} else if (ioctl == VFIO_DEVICE_CREATE_DMABUF) {
+		struct vfio_vgpu_dmabuf_info dmabuf;
+
+		minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);
+		if (copy_from_user(&dmabuf, (void __user *)arg, minsz)) {
+			fdput(f);
+			return -EFAULT;
+		}
+		if (dmabuf.argsz < minsz) {
+			fdput(f);
+			return -EINVAL;
+		}
+		ret = kvmgt_get_vfio_device(vgpu);
+		if (ret != 0)
+			return ret;
+
+		ret = intel_gvt_ops->vgpu_create_dmabuf(vgpu, &dmabuf);
+		if (ret != 0) {
+			kvmgt_put_vfio_device(vgpu);
+			fdput(f);
+			return -EINVAL;
+		}
+		fdput(f);
+		return copy_to_user((void __user *)arg, &dmabuf, minsz) ?
+								-EFAULT : 0;
+	}
+
+	fdput(f);
+	gvt_vgpu_err("unsupported dmabuf operation\n");
+
+	return -EINVAL;
+}
+
+static const struct file_operations intel_vgpu_dmabuf_mgr_fd_ops = {
+	.release        = intel_vgpu_dmabuf_mgr_fd_release,
+	.unlocked_ioctl = intel_vgpu_dmabuf_mgr_fd_ioctl,
+	.mmap           = intel_vgpu_dmabuf_mgr_fd_mmap,
+	.llseek         = noop_llseek,
+};
 static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
 {
 	struct intel_vgpu *vgpu = NULL;
@@ -1259,6 +1379,30 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
 	} else if (cmd == VFIO_DEVICE_RESET) {
 		intel_gvt_ops->vgpu_reset(vgpu);
 		return 0;
+	} else if (cmd == VFIO_DEVICE_GET_FD) {
+		int fd;
+		u32 type;
+		int ret;
+
+		if (copy_from_user(&type, (void __user *)arg, sizeof(type)))
+			return -EINVAL;
+		if (type != VFIO_DEVICE_DMABUF_MGR_FD)
+			return -EINVAL;
+
+		ret = kvmgt_get_vfio_device(vgpu);
+		if (ret != 0)
+			return ret;
+
+		fd = anon_inode_getfd("intel-vgpu-dmabuf-mgr-fd",
+			&intel_vgpu_dmabuf_mgr_fd_ops,
+			vgpu, O_RDWR | O_CLOEXEC);
+		if (fd < 0) {
+			gvt_vgpu_err("create dmabuf mgr fd failed\n");
+			return -EINVAL;
+		}
+		vgpu->dmabuf_mgr_fd = fd;
+
+		return fd;
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
index 6e3cbd8..af6fc74 100644
--- a/drivers/gpu/drm/i915/gvt/vgpu.c
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -346,6 +346,7 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
 	vgpu->gvt = gvt;
 	vgpu->sched_ctl.weight = param->weight;
 	bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
+	INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
 
 	intel_vgpu_init_cfg_space(vgpu, param->primary);
 
-- 
2.7.4

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

* [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
@ 2017-05-27  8:38   ` Xiaoguang Chen
  0 siblings, 0 replies; 74+ messages in thread
From: Xiaoguang Chen @ 2017-05-27  8:38 UTC (permalink / raw)
  To: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian
  Cc: Xiaoguang Chen

User space should create the management fd for the dma-buf operation first.
Then user can query the plane information and create dma-buf if necessary
using the management fd.

Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
---
 drivers/gpu/drm/i915/gvt/dmabuf.c |  12 ++++
 drivers/gpu/drm/i915/gvt/dmabuf.h |   5 ++
 drivers/gpu/drm/i915/gvt/gvt.c    |   2 +
 drivers/gpu/drm/i915/gvt/gvt.h    |   5 ++
 drivers/gpu/drm/i915/gvt/kvmgt.c  | 144 ++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/vgpu.c   |   1 +
 6 files changed, 169 insertions(+)

diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
index c831e91..9759e9a 100644
--- a/drivers/gpu/drm/i915/gvt/dmabuf.c
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
@@ -226,6 +226,7 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args)
 	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
 	struct intel_vgpu_fb_info *fb_info;
 	int ret;
+	struct intel_vgpu_dmabuf_obj *dmabuf_obj;
 
 	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
 	if (ret != 0)
@@ -263,6 +264,17 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args)
 		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
 		return ret;
 	}
+	dmabuf_obj = kmalloc(sizeof(*dmabuf_obj), GFP_KERNEL);
+	if (dmabuf_obj == NULL) {
+		kfree(fb_info);
+		i915_gem_object_put(obj);
+		gvt_vgpu_err("alloc dmabuf_obj failed\n");
+		return -ENOMEM;
+	}
+	dmabuf_obj->obj = obj;
+	INIT_LIST_HEAD(&dmabuf_obj->list);
+	list_add_tail(&dmabuf_obj->list, &vgpu->dmabuf_obj_list_head);
+
 	gvt_dmabuf->fd = ret;
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h b/drivers/gpu/drm/i915/gvt/dmabuf.h
index 8be9979..cafa781 100644
--- a/drivers/gpu/drm/i915/gvt/dmabuf.h
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
@@ -31,6 +31,11 @@ struct intel_vgpu_fb_info {
 	uint32_t fb_size;
 };
 
+struct intel_vgpu_dmabuf_obj {
+	struct drm_i915_gem_object *obj;
+	struct list_head list;
+};
+
 int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);
 int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args);
 
diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c
index 2032917..dbc3f86 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.c
+++ b/drivers/gpu/drm/i915/gvt/gvt.c
@@ -54,6 +54,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {
 	.vgpu_reset = intel_gvt_reset_vgpu,
 	.vgpu_activate = intel_gvt_activate_vgpu,
 	.vgpu_deactivate = intel_gvt_deactivate_vgpu,
+	.vgpu_query_plane = intel_vgpu_query_plane,
+	.vgpu_create_dmabuf = intel_vgpu_create_dmabuf,
 };
 
 /**
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index 763a8c5..a855797 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -185,8 +185,11 @@ struct intel_vgpu {
 		struct kvm *kvm;
 		struct work_struct release_work;
 		atomic_t released;
+		struct vfio_device *vfio_device;
 	} vdev;
 #endif
+	int dmabuf_mgr_fd;
+	struct list_head dmabuf_obj_list_head;
 };
 
 struct intel_gvt_gm {
@@ -467,6 +470,8 @@ struct intel_gvt_ops {
 	void (*vgpu_reset)(struct intel_vgpu *);
 	void (*vgpu_activate)(struct intel_vgpu *);
 	void (*vgpu_deactivate)(struct intel_vgpu *);
+	int (*vgpu_query_plane)(struct intel_vgpu *vgpu, void *);
+	int (*vgpu_create_dmabuf)(struct intel_vgpu *vgpu, void *);
 };
 
 
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 389f072..a079080 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -41,6 +41,7 @@
 #include <linux/kvm_host.h>
 #include <linux/vfio.h>
 #include <linux/mdev.h>
+#include <linux/anon_inodes.h>
 
 #include "i915_drv.h"
 #include "gvt.h"
@@ -524,6 +525,125 @@ static int intel_vgpu_reg_init_opregion(struct intel_vgpu *vgpu)
 	return ret;
 }
 
+static int kvmgt_get_vfio_device(struct intel_vgpu *vgpu)
+{
+	struct vfio_device *device;
+
+	device = vfio_device_get_from_dev(mdev_dev(vgpu->vdev.mdev));
+	if (device == NULL)
+		return -ENODEV;
+	vgpu->vdev.vfio_device = device;
+
+	return 0;
+}
+
+static void kvmgt_put_vfio_device(struct intel_vgpu *vgpu)
+{
+	vfio_device_put(vgpu->vdev.vfio_device);
+}
+
+static int intel_vgpu_dmabuf_mgr_fd_mmap(struct file *file,
+		struct vm_area_struct *vma)
+{
+	return -EPERM;
+}
+
+static int intel_vgpu_dmabuf_mgr_fd_release(struct inode *inode,
+		struct file *filp)
+{
+	struct intel_vgpu *vgpu = filp->private_data;
+	struct intel_vgpu_dmabuf_obj *obj;
+	struct list_head *pos;
+
+	if (WARN_ON(!vgpu->vdev.vfio_device))
+		return -ENODEV;
+
+	list_for_each(pos, &vgpu->dmabuf_obj_list_head) {
+		obj = container_of(pos, struct intel_vgpu_dmabuf_obj, list);
+		if (WARN_ON(!obj))
+			return -ENODEV;
+		kfree(obj->obj->gvt_info);
+		i915_gem_object_put(obj->obj);
+		kfree(obj);
+		kvmgt_put_vfio_device(vgpu);
+	}
+	kvmgt_put_vfio_device(vgpu);
+
+	return 0;
+}
+
+static long intel_vgpu_dmabuf_mgr_fd_ioctl(struct file *filp,
+		unsigned int ioctl, unsigned long arg)
+{
+	struct intel_vgpu *vgpu = filp->private_data;
+	int minsz;
+	int ret;
+	struct fd f;
+
+	f = fdget(vgpu->dmabuf_mgr_fd);
+	if (!f.file)
+		return -EBADF;
+
+	if (ioctl == VFIO_DEVICE_QUERY_PLANE) {
+		struct vfio_vgpu_plane_info info;
+
+		minsz = offsetofend(struct vfio_vgpu_plane_info, resv);
+		if (copy_from_user(&info, (void __user *)arg, minsz)) {
+			fdput(f);
+			return -EFAULT;
+		}
+		if (info.argsz < minsz) {
+			fdput(f);
+			return -EINVAL;
+		}
+		ret = intel_gvt_ops->vgpu_query_plane(vgpu, &info);
+		if (ret != 0) {
+			fdput(f);
+			gvt_vgpu_err("query plane failed:%d\n", ret);
+			return -EINVAL;
+		}
+		fdput(f);
+		return copy_to_user((void __user *)arg, &info, minsz) ?
+								-EFAULT : 0;
+	} else if (ioctl == VFIO_DEVICE_CREATE_DMABUF) {
+		struct vfio_vgpu_dmabuf_info dmabuf;
+
+		minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);
+		if (copy_from_user(&dmabuf, (void __user *)arg, minsz)) {
+			fdput(f);
+			return -EFAULT;
+		}
+		if (dmabuf.argsz < minsz) {
+			fdput(f);
+			return -EINVAL;
+		}
+		ret = kvmgt_get_vfio_device(vgpu);
+		if (ret != 0)
+			return ret;
+
+		ret = intel_gvt_ops->vgpu_create_dmabuf(vgpu, &dmabuf);
+		if (ret != 0) {
+			kvmgt_put_vfio_device(vgpu);
+			fdput(f);
+			return -EINVAL;
+		}
+		fdput(f);
+		return copy_to_user((void __user *)arg, &dmabuf, minsz) ?
+								-EFAULT : 0;
+	}
+
+	fdput(f);
+	gvt_vgpu_err("unsupported dmabuf operation\n");
+
+	return -EINVAL;
+}
+
+static const struct file_operations intel_vgpu_dmabuf_mgr_fd_ops = {
+	.release        = intel_vgpu_dmabuf_mgr_fd_release,
+	.unlocked_ioctl = intel_vgpu_dmabuf_mgr_fd_ioctl,
+	.mmap           = intel_vgpu_dmabuf_mgr_fd_mmap,
+	.llseek         = noop_llseek,
+};
 static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
 {
 	struct intel_vgpu *vgpu = NULL;
@@ -1259,6 +1379,30 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
 	} else if (cmd == VFIO_DEVICE_RESET) {
 		intel_gvt_ops->vgpu_reset(vgpu);
 		return 0;
+	} else if (cmd == VFIO_DEVICE_GET_FD) {
+		int fd;
+		u32 type;
+		int ret;
+
+		if (copy_from_user(&type, (void __user *)arg, sizeof(type)))
+			return -EINVAL;
+		if (type != VFIO_DEVICE_DMABUF_MGR_FD)
+			return -EINVAL;
+
+		ret = kvmgt_get_vfio_device(vgpu);
+		if (ret != 0)
+			return ret;
+
+		fd = anon_inode_getfd("intel-vgpu-dmabuf-mgr-fd",
+			&intel_vgpu_dmabuf_mgr_fd_ops,
+			vgpu, O_RDWR | O_CLOEXEC);
+		if (fd < 0) {
+			gvt_vgpu_err("create dmabuf mgr fd failed\n");
+			return -EINVAL;
+		}
+		vgpu->dmabuf_mgr_fd = fd;
+
+		return fd;
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
index 6e3cbd8..af6fc74 100644
--- a/drivers/gpu/drm/i915/gvt/vgpu.c
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -346,6 +346,7 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
 	vgpu->gvt = gvt;
 	vgpu->sched_ctl.weight = param->weight;
 	bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
+	INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
 
 	intel_vgpu_init_cfg_space(vgpu, param->primary);
 
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* ✗ Fi.CI.BAT: failure for drm/i915/gvt: dma-buf support for GVT-g (rev6)
  2017-05-27  8:38 ` Xiaoguang Chen
                   ` (6 preceding siblings ...)
  (?)
@ 2017-05-27  8:44 ` Patchwork
  -1 siblings, 0 replies; 74+ messages in thread
From: Patchwork @ 2017-05-27  8:44 UTC (permalink / raw)
  To: Xiaoguang Chen; +Cc: intel-gfx

== Series Details ==

Series: drm/i915/gvt: dma-buf support for GVT-g (rev6)
URL   : https://patchwork.freedesktop.org/series/23686/
State : failure

== Summary ==

  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  CHK     include/generated/bounds.h
  CHK     include/generated/timeconst.h
  CHK     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
  CHK     scripts/mod/devicetable-offsets.h
  CHK     include/generated/compile.h
  CHK     kernel/config_data.h
  CC [M]  drivers/gpu/drm/i915/i915_drv.o
In file included from drivers/gpu/drm/i915/i915_vma.h:34:0,
                 from drivers/gpu/drm/i915/intel_uc.h:31,
                 from drivers/gpu/drm/i915/i915_drv.h:61,
                 from drivers/gpu/drm/i915/i915_drv.c:49:
drivers/gpu/drm/i915/i915_gem_object.h:40:1: error: expected specifier-qualifier-list before ‘<<’ token
 <<<<<<< 391b5aa3660577581466b0d4594e1a61fae843bd
 ^
drivers/gpu/drm/i915/i915_gem_object.h:40:9: error: invalid suffix "b5aa3660577581466b0d4594e1a61fae843bd" on integer constant
 <<<<<<< 391b5aa3660577581466b0d4594e1a61fae843bd
         ^
drivers/gpu/drm/i915/i915_gem_object.h:44:0: error: "I915_GEM_OBJECT_HAS_STRUCT_PAGE" redefined [-Werror]
 #define I915_GEM_OBJECT_HAS_STRUCT_PAGE 0x1
 ^
drivers/gpu/drm/i915/i915_gem_object.h:41:0: note: this is the location of the previous definition
 #define I915_GEM_OBJECT_HAS_STRUCT_PAGE BIT(0)
 ^
drivers/gpu/drm/i915/i915_gem_object.h:45:0: error: "I915_GEM_OBJECT_IS_SHRINKABLE" redefined [-Werror]
 #define I915_GEM_OBJECT_IS_SHRINKABLE   0x2
 ^
drivers/gpu/drm/i915/i915_gem_object.h:42:0: note: this is the location of the previous definition
 #define I915_GEM_OBJECT_IS_SHRINKABLE   BIT(1)
 ^
cc1: all warnings being treated as errors
scripts/Makefile.build:302: recipe for target 'drivers/gpu/drm/i915/i915_drv.o' failed
make[4]: *** [drivers/gpu/drm/i915/i915_drv.o] Error 1
scripts/Makefile.build:561: recipe for target 'drivers/gpu/drm/i915' failed
make[3]: *** [drivers/gpu/drm/i915] Error 2
scripts/Makefile.build:561: recipe for target 'drivers/gpu/drm' failed
make[2]: *** [drivers/gpu/drm] Error 2
scripts/Makefile.build:561: recipe for target 'drivers/gpu' failed
make[1]: *** [drivers/gpu] Error 2
Makefile:1016: recipe for target 'drivers' failed
make: *** [drivers] Error 2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
  2017-05-27  8:38 ` [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations Xiaoguang Chen
@ 2017-05-29  7:20     ` Gerd Hoffmann
  0 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-05-29  7:20 UTC (permalink / raw)
  To: Xiaoguang Chen, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian

> +struct vfio_vgpu_dmabuf_info {
> +	__u32 argsz;
> +	__u32 flags;
> +	struct vfio_vgpu_plane_info plane_info;
> +	__s32 fd;
> +	__u32 pad;
> +};

Hmm, now you have argsz and flags twice in vfio_vgpu_dmabuf_info ...

I think we should have something like this:

struct vfio_vgpu_plane_info {
        __u64 start;
        __u64 drm_format_mod;
        __u32 drm_format;
        __u32 width;
        __u32 height;
        __u32 stride;
        __u32 size;
        __u32 x_pos;
        __u32 y_pos;
        __u32 padding;
};

struct vfio_vgpu_query_plane {
	__u32 argsz;
	__u32 flags;
	struct vfio_vgpu_plane_info plane_info;
        __u32 plane_id;
        __u32 padding;
};

struct vfio_vgpu_create_dmabuf {
	__u32 argsz;
	__u32 flags;
	struct vfio_vgpu_plane_info plane_info;
        __u32 plane_id;
        __s32 fd;
};

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
@ 2017-05-29  7:20     ` Gerd Hoffmann
  0 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-05-29  7:20 UTC (permalink / raw)
  To: Xiaoguang Chen, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian

> +struct vfio_vgpu_dmabuf_info {
> +	__u32 argsz;
> +	__u32 flags;
> +	struct vfio_vgpu_plane_info plane_info;
> +	__s32 fd;
> +	__u32 pad;
> +};

Hmm, now you have argsz and flags twice in vfio_vgpu_dmabuf_info ...

I think we should have something like this:

struct vfio_vgpu_plane_info {
        __u64 start;
        __u64 drm_format_mod;
        __u32 drm_format;
        __u32 width;
        __u32 height;
        __u32 stride;
        __u32 size;
        __u32 x_pos;
        __u32 y_pos;
        __u32 padding;
};

struct vfio_vgpu_query_plane {
	__u32 argsz;
	__u32 flags;
	struct vfio_vgpu_plane_info plane_info;
        __u32 plane_id;
        __u32 padding;
};

struct vfio_vgpu_create_dmabuf {
	__u32 argsz;
	__u32 flags;
	struct vfio_vgpu_plane_info plane_info;
        __u32 plane_id;
        __s32 fd;
};
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g
  2017-05-27  8:38 ` Xiaoguang Chen
@ 2017-05-30 10:23   ` Gerd Hoffmann
  -1 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-05-30 10:23 UTC (permalink / raw)
  To: Xiaoguang Chen, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian

  Hi,

> This patch set adds the dma-buf support for intel GVT-g.
> dma-buf is a uniform mechanism to share DMA buffers across different
> devices and sub-systems.
> dma-buf for intel GVT-g is mainly used to share the vgpu's
> framebuffer
> to other users or sub-systems so they can use the dma-buf to show the
> desktop of a vm which uses intel vgpu.

Which branch is this based on?
Applying to gvt-stable-4.11 doesn't work.
Applying to drm-intel-next doesn't work either ...

cheers,
  Gerd

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

* Re: [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g
@ 2017-05-30 10:23   ` Gerd Hoffmann
  0 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-05-30 10:23 UTC (permalink / raw)
  To: Xiaoguang Chen, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian

  Hi,

> This patch set adds the dma-buf support for intel GVT-g.
> dma-buf is a uniform mechanism to share DMA buffers across different
> devices and sub-systems.
> dma-buf for intel GVT-g is mainly used to share the vgpu's
> framebuffer
> to other users or sub-systems so they can use the dma-buf to show the
> desktop of a vm which uses intel vgpu.

Which branch is this based on?
Applying to gvt-stable-4.11 doesn't work.
Applying to drm-intel-next doesn't work either ...

cheers,
  Gerd
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* RE: [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g
  2017-05-30 10:23   ` Gerd Hoffmann
@ 2017-05-31  2:29     ` Chen, Xiaoguang
  -1 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-05-31  2:29 UTC (permalink / raw)
  To: Gerd Hoffmann, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, Lv, Zhiyuan, intel-gvt-dev, Wang, Zhi A, Tian, Kevin

Hi Gerd,

It is based on 4.12.0-rc1

>-----Original Message-----
>From: Gerd Hoffmann [mailto:kraxel@redhat.com]
>Sent: Tuesday, May 30, 2017 6:24 PM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
>alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
>gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g
>
>  Hi,
>
>> This patch set adds the dma-buf support for intel GVT-g.
>> dma-buf is a uniform mechanism to share DMA buffers across different
>> devices and sub-systems.
>> dma-buf for intel GVT-g is mainly used to share the vgpu's framebuffer
>> to other users or sub-systems so they can use the dma-buf to show the
>> desktop of a vm which uses intel vgpu.
>
>Which branch is this based on?
>Applying to gvt-stable-4.11 doesn't work.
>Applying to drm-intel-next doesn't work either ...
>
>cheers,
>  Gerd

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

* Re: [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g
@ 2017-05-31  2:29     ` Chen, Xiaoguang
  0 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-05-31  2:29 UTC (permalink / raw)
  To: Gerd Hoffmann, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, Lv, Zhiyuan, intel-gvt-dev, Wang, Zhi A, Tian, Kevin

Hi Gerd,

It is based on 4.12.0-rc1

>-----Original Message-----
>From: Gerd Hoffmann [mailto:kraxel@redhat.com]
>Sent: Tuesday, May 30, 2017 6:24 PM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
>alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
>gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g
>
>  Hi,
>
>> This patch set adds the dma-buf support for intel GVT-g.
>> dma-buf is a uniform mechanism to share DMA buffers across different
>> devices and sub-systems.
>> dma-buf for intel GVT-g is mainly used to share the vgpu's framebuffer
>> to other users or sub-systems so they can use the dma-buf to show the
>> desktop of a vm which uses intel vgpu.
>
>Which branch is this based on?
>Applying to gvt-stable-4.11 doesn't work.
>Applying to drm-intel-next doesn't work either ...
>
>cheers,
>  Gerd
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g
  2017-05-27  8:38   ` Xiaoguang Chen
@ 2017-05-31  4:47     ` Zhenyu Wang
  -1 siblings, 0 replies; 74+ messages in thread
From: Zhenyu Wang @ 2017-05-31  4:47 UTC (permalink / raw)
  To: Xiaoguang Chen
  Cc: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian, Bing Niu

[-- Attachment #1: Type: text/plain, Size: 5679 bytes --]

On 2017.05.27 16:38:48 +0800, Xiaoguang Chen wrote:
> OpRegion is needed to support display related operation for
> intel vgpu.
> 
> A vfio device region is added to intel vgpu to deliver the
> host OpRegion information to user space so user space can
> construct the OpRegion for vgpu.
> 
> Signed-off-by: Bing Niu <bing.niu@intel.com>
> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
> ---
>  drivers/gpu/drm/i915/gvt/kvmgt.c    | 97 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/gvt/opregion.c |  8 ++-
>  2 files changed, 104 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 3c6a02b..389f072 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -53,6 +53,8 @@ static const struct intel_gvt_ops *intel_gvt_ops;
>  #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)
>  
> +#define OPREGION_SIGNATURE "IntelGraphicsMem"
> +
>  struct vfio_region;
>  struct intel_vgpu_regops {
>  	size_t (*rw)(struct intel_vgpu *vgpu, char *buf,
> @@ -436,6 +438,92 @@ static void kvmgt_protect_table_del(struct kvmgt_guest_info *info,
>  	}
>  }
>  
> +static size_t intel_vgpu_reg_rw_opregion(struct intel_vgpu *vgpu, char *buf,
> +		size_t count, loff_t *ppos, bool iswrite)
> +{
> +	unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) -
> +			VFIO_PCI_NUM_REGIONS;
> +	void *base = vgpu->vdev.region[i].data;
> +	loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
> +
> +	if (pos >= vgpu->vdev.region[i].size || iswrite) {
> +		gvt_vgpu_err("invalid op or offset for Intel vgpu OpRegion\n");
> +		return -EINVAL;
> +	}
> +	count = min(count, (size_t)(vgpu->vdev.region[i].size - pos));
> +	memcpy(buf, base + pos, count);
> +
> +	return count;
> +}
> +
> +static void intel_vgpu_reg_release_opregion(struct intel_vgpu *vgpu,
> +		struct vfio_region *region)
> +{
> +	memunmap(region->data);
> +}
> +
> +static const struct intel_vgpu_regops intel_vgpu_regops_opregion = {
> +	.rw = intel_vgpu_reg_rw_opregion,
> +	.release = intel_vgpu_reg_release_opregion,
> +};
> +
> +static int intel_vgpu_register_reg(struct intel_vgpu *vgpu,
> +		unsigned int type, unsigned int subtype,
> +		const struct intel_vgpu_regops *ops,
> +		size_t size, u32 flags, void *data)
> +{
> +	struct vfio_region *region;
> +
> +	region = krealloc(vgpu->vdev.region,
> +			(vgpu->vdev.num_regions + 1) * sizeof(*region),
> +			GFP_KERNEL);
> +	if (!region)
> +		return -ENOMEM;
> +
> +	vgpu->vdev.region = region;
> +	vgpu->vdev.region[vgpu->vdev.num_regions].type = type;
> +	vgpu->vdev.region[vgpu->vdev.num_regions].subtype = subtype;
> +	vgpu->vdev.region[vgpu->vdev.num_regions].ops = ops;
> +	vgpu->vdev.region[vgpu->vdev.num_regions].size = size;
> +	vgpu->vdev.region[vgpu->vdev.num_regions].flags = flags;
> +	vgpu->vdev.region[vgpu->vdev.num_regions].data = data;
> +	vgpu->vdev.num_regions++;
> +
> +	return 0;
> +}
> +
> +static int intel_vgpu_reg_init_opregion(struct intel_vgpu *vgpu)
> +{
> +	unsigned int addr;
> +	void *base;
> +	int ret;
> +
> +	addr = vgpu->gvt->opregion.opregion_pa;
> +	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;
> +	}
> +
> +	ret = intel_vgpu_register_reg(vgpu,
> +			PCI_VENDOR_ID_INTEL | VFIO_REGION_TYPE_PCI_VENDOR_TYPE,
> +			VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION,
> +			&intel_vgpu_regops_opregion, OPREGION_SIZE,
> +			VFIO_REGION_INFO_FLAG_READ, base);
> +	if (ret) {
> +		memunmap(base);
> +		return ret;
> +	}
> +
> +	return ret;
> +}
> +
>  static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
>  {
>  	struct intel_vgpu *vgpu = NULL;
> @@ -467,6 +555,15 @@ static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
>  	vgpu->vdev.mdev = mdev;
>  	mdev_set_drvdata(mdev, vgpu);
>  
> +	ret = intel_vgpu_reg_init_opregion(vgpu);
> +	if (ret) {
> +		gvt_vgpu_err("create OpRegion failed\n");
> +		goto out;
> +	}

Still need to handle error path for created vgpu.

> +
> +	gvt_dbg_core("create OpRegion succeeded for mdev:%s\n",
> +			dev_name(mdev_dev(mdev)));
> +
>  	gvt_dbg_core("intel_vgpu_create succeeded for mdev: %s\n",
>  		     dev_name(mdev_dev(mdev)));
>  	ret = 0;
> diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c
> index 3117991..5c7496d 100644
> --- a/drivers/gpu/drm/i915/gvt/opregion.c
> +++ b/drivers/gpu/drm/i915/gvt/opregion.c
> @@ -114,6 +114,7 @@ void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu)
>  int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
>  {
>  	int ret;
> +	unsigned long pfn;
>  
>  	gvt_dbg_core("vgpu%d: init vgpu opregion\n", vgpu->id);
>  
> @@ -127,7 +128,12 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
>  		ret = map_vgpu_opregion(vgpu, true);
>  		if (ret)
>  			return ret;
> -	}
> +	} else {
> +		pfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gpa >> PAGE_SHIFT);
> +		vgpu_opregion(vgpu)->va = memremap(pfn << PAGE_SHIFT,
> +						INTEL_GVT_OPREGION_SIZE,
> +						MEMREMAP_WB);
> +		}

better to use switch for explicit KVM case, and no return check?

>  
>  	return 0;
>  }
> -- 
> 2.7.4
> 

-- 
Open Source Technology Center, Intel ltd.

$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

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

* Re: [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g
@ 2017-05-31  4:47     ` Zhenyu Wang
  0 siblings, 0 replies; 74+ messages in thread
From: Zhenyu Wang @ 2017-05-31  4:47 UTC (permalink / raw)
  To: Xiaoguang Chen; +Cc: intel-gfx, linux-kernel, kraxel, intel-gvt-dev, zhiyuan.lv


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

On 2017.05.27 16:38:48 +0800, Xiaoguang Chen wrote:
> OpRegion is needed to support display related operation for
> intel vgpu.
> 
> A vfio device region is added to intel vgpu to deliver the
> host OpRegion information to user space so user space can
> construct the OpRegion for vgpu.
> 
> Signed-off-by: Bing Niu <bing.niu@intel.com>
> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
> ---
>  drivers/gpu/drm/i915/gvt/kvmgt.c    | 97 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/gvt/opregion.c |  8 ++-
>  2 files changed, 104 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 3c6a02b..389f072 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -53,6 +53,8 @@ static const struct intel_gvt_ops *intel_gvt_ops;
>  #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)
>  
> +#define OPREGION_SIGNATURE "IntelGraphicsMem"
> +
>  struct vfio_region;
>  struct intel_vgpu_regops {
>  	size_t (*rw)(struct intel_vgpu *vgpu, char *buf,
> @@ -436,6 +438,92 @@ static void kvmgt_protect_table_del(struct kvmgt_guest_info *info,
>  	}
>  }
>  
> +static size_t intel_vgpu_reg_rw_opregion(struct intel_vgpu *vgpu, char *buf,
> +		size_t count, loff_t *ppos, bool iswrite)
> +{
> +	unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) -
> +			VFIO_PCI_NUM_REGIONS;
> +	void *base = vgpu->vdev.region[i].data;
> +	loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
> +
> +	if (pos >= vgpu->vdev.region[i].size || iswrite) {
> +		gvt_vgpu_err("invalid op or offset for Intel vgpu OpRegion\n");
> +		return -EINVAL;
> +	}
> +	count = min(count, (size_t)(vgpu->vdev.region[i].size - pos));
> +	memcpy(buf, base + pos, count);
> +
> +	return count;
> +}
> +
> +static void intel_vgpu_reg_release_opregion(struct intel_vgpu *vgpu,
> +		struct vfio_region *region)
> +{
> +	memunmap(region->data);
> +}
> +
> +static const struct intel_vgpu_regops intel_vgpu_regops_opregion = {
> +	.rw = intel_vgpu_reg_rw_opregion,
> +	.release = intel_vgpu_reg_release_opregion,
> +};
> +
> +static int intel_vgpu_register_reg(struct intel_vgpu *vgpu,
> +		unsigned int type, unsigned int subtype,
> +		const struct intel_vgpu_regops *ops,
> +		size_t size, u32 flags, void *data)
> +{
> +	struct vfio_region *region;
> +
> +	region = krealloc(vgpu->vdev.region,
> +			(vgpu->vdev.num_regions + 1) * sizeof(*region),
> +			GFP_KERNEL);
> +	if (!region)
> +		return -ENOMEM;
> +
> +	vgpu->vdev.region = region;
> +	vgpu->vdev.region[vgpu->vdev.num_regions].type = type;
> +	vgpu->vdev.region[vgpu->vdev.num_regions].subtype = subtype;
> +	vgpu->vdev.region[vgpu->vdev.num_regions].ops = ops;
> +	vgpu->vdev.region[vgpu->vdev.num_regions].size = size;
> +	vgpu->vdev.region[vgpu->vdev.num_regions].flags = flags;
> +	vgpu->vdev.region[vgpu->vdev.num_regions].data = data;
> +	vgpu->vdev.num_regions++;
> +
> +	return 0;
> +}
> +
> +static int intel_vgpu_reg_init_opregion(struct intel_vgpu *vgpu)
> +{
> +	unsigned int addr;
> +	void *base;
> +	int ret;
> +
> +	addr = vgpu->gvt->opregion.opregion_pa;
> +	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;
> +	}
> +
> +	ret = intel_vgpu_register_reg(vgpu,
> +			PCI_VENDOR_ID_INTEL | VFIO_REGION_TYPE_PCI_VENDOR_TYPE,
> +			VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION,
> +			&intel_vgpu_regops_opregion, OPREGION_SIZE,
> +			VFIO_REGION_INFO_FLAG_READ, base);
> +	if (ret) {
> +		memunmap(base);
> +		return ret;
> +	}
> +
> +	return ret;
> +}
> +
>  static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
>  {
>  	struct intel_vgpu *vgpu = NULL;
> @@ -467,6 +555,15 @@ static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
>  	vgpu->vdev.mdev = mdev;
>  	mdev_set_drvdata(mdev, vgpu);
>  
> +	ret = intel_vgpu_reg_init_opregion(vgpu);
> +	if (ret) {
> +		gvt_vgpu_err("create OpRegion failed\n");
> +		goto out;
> +	}

Still need to handle error path for created vgpu.

> +
> +	gvt_dbg_core("create OpRegion succeeded for mdev:%s\n",
> +			dev_name(mdev_dev(mdev)));
> +
>  	gvt_dbg_core("intel_vgpu_create succeeded for mdev: %s\n",
>  		     dev_name(mdev_dev(mdev)));
>  	ret = 0;
> diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c
> index 3117991..5c7496d 100644
> --- a/drivers/gpu/drm/i915/gvt/opregion.c
> +++ b/drivers/gpu/drm/i915/gvt/opregion.c
> @@ -114,6 +114,7 @@ void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu)
>  int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
>  {
>  	int ret;
> +	unsigned long pfn;
>  
>  	gvt_dbg_core("vgpu%d: init vgpu opregion\n", vgpu->id);
>  
> @@ -127,7 +128,12 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
>  		ret = map_vgpu_opregion(vgpu, true);
>  		if (ret)
>  			return ret;
> -	}
> +	} else {
> +		pfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gpa >> PAGE_SHIFT);
> +		vgpu_opregion(vgpu)->va = memremap(pfn << PAGE_SHIFT,
> +						INTEL_GVT_OPREGION_SIZE,
> +						MEMREMAP_WB);
> +		}

better to use switch for explicit KVM case, and no return check?

>  
>  	return 0;
>  }
> -- 
> 2.7.4
> 

-- 
Open Source Technology Center, Intel ltd.

$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

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

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 3/6] drm/i915/gvt: Frame buffer decoder support for GVT-g
  2017-05-27  8:38   ` Xiaoguang Chen
@ 2017-05-31  5:12     ` Zhenyu Wang
  -1 siblings, 0 replies; 74+ messages in thread
From: Zhenyu Wang @ 2017-05-31  5:12 UTC (permalink / raw)
  To: Xiaoguang Chen
  Cc: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian

[-- Attachment #1: Type: text/plain, Size: 19785 bytes --]

On 2017.05.27 16:38:49 +0800, Xiaoguang Chen wrote:
> decode frambuffer attributes of primary, cursor and sprite plane
> 
> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
> ---
>  drivers/gpu/drm/i915/gvt/Makefile     |   3 +-
>  drivers/gpu/drm/i915/gvt/display.c    |   2 +-
>  drivers/gpu/drm/i915/gvt/display.h    |   2 +
>  drivers/gpu/drm/i915/gvt/fb_decoder.c | 479 ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/gvt/fb_decoder.h | 166 ++++++++++++
>  drivers/gpu/drm/i915/gvt/gvt.h        |   1 +
>  6 files changed, 651 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.c
>  create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.h
> 
> diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile
> index b123c20..192ca26 100644
> --- a/drivers/gpu/drm/i915/gvt/Makefile
> +++ b/drivers/gpu/drm/i915/gvt/Makefile
> @@ -1,7 +1,8 @@
>  GVT_DIR := gvt
>  GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \
>  	interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \
> -	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o
> +	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o \
> +	fb_decoder.o
>  
>  ccflags-y				+= -I$(src) -I$(src)/$(GVT_DIR) -Wall
>  i915-y					+= $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
> diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
> index e0261fc..f5f63c5 100644
> --- a/drivers/gpu/drm/i915/gvt/display.c
> +++ b/drivers/gpu/drm/i915/gvt/display.c
> @@ -67,7 +67,7 @@ static int edp_pipe_is_enabled(struct intel_vgpu *vgpu)
>  	return 1;
>  }
>  
> -static int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
> +int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
>  {
>  	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
>  
> diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h
> index d73de22..b46b868 100644
> --- a/drivers/gpu/drm/i915/gvt/display.h
> +++ b/drivers/gpu/drm/i915/gvt/display.h
> @@ -179,4 +179,6 @@ int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution);
>  void intel_vgpu_reset_display(struct intel_vgpu *vgpu);
>  void intel_vgpu_clean_display(struct intel_vgpu *vgpu);
>  
> +int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe);
> +
>  #endif
> diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.c b/drivers/gpu/drm/i915/gvt/fb_decoder.c
> new file mode 100644
> index 0000000..d4404fd
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.c
> @@ -0,0 +1,479 @@
> +/*
> + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + *
> + * Authors:
> + *    Kevin Tian <kevin.tian@intel.com>
> + *
> + * Contributors:
> + *    Bing Niu <bing.niu@intel.com>
> + *    Xu Han <xu.han@intel.com>
> + *    Ping Gao <ping.a.gao@intel.com>
> + *    Xiaoguang Chen <xiaoguang.chen@intel.com>
> + *    Yang Liu <yang2.liu@intel.com>
> + *
> + */
> +
> +#include <uapi/drm/drm_fourcc.h>
> +#include "i915_drv.h"
> +#include "gvt.h"
> +
> +/* The below definitions are required by guest. */
> +// [63:0] x:R:G:B 16:16:16:16 little endian
> +#define DRM_FORMAT_XRGB161616_GVT  fourcc_code('X', 'R', '4', '8')
> +// [63:0] x:B:G:R 16:16:16:16 little endian
> +#define DRM_FORMAT_XBGR161616_GVT  fourcc_code('X', 'B', '4', '8')
> +

Should be added to drm_fourcc?

> +#define FORMAT_NUM	16

PRIMARY_FORMAT_NUM

> +struct pixel_format {
> +	int	drm_format;	/* Pixel format in DRM definition */
> +	int	bpp;		/* Bits per pixel, 0 indicates invalid */
> +	char *desc;		/* The description */
> +};
> +
> +/* non-supported format has bpp default to 0 */
> +static struct pixel_format primary_pixel_formats[FORMAT_NUM] = {
> +	[0x2] = {DRM_FORMAT_C8, 8, "8-bit Indexed"},
> +	[0x5] = {DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"},
> +	[0x6] = {DRM_FORMAT_XRGB8888, 32,
> +		"32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"},
> +	[0x8] = {DRM_FORMAT_XBGR2101010, 32,
> +		"32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"},
> +	[0xa] = {DRM_FORMAT_XRGB2101010, 32,
> +		"32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"},
> +	[0xc] = {DRM_FORMAT_XRGB161616_GVT, 64,
> +		"64-bit RGBX Floating Point(16:16:16:16 MSB-X:B:G:R)"},
> +	[0xe] = {DRM_FORMAT_XBGR8888, 32,
> +		"32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"},
> +};

might explicitly say this is bdw_pixel_formats?

> +
> +/* non-supported format has bpp default to 0 */
> +static struct pixel_format skl_pixel_formats[] = {
> +	{DRM_FORMAT_YUYV, 16, "16-bit packed YUYV (8:8:8:8 MSB-V:Y2:U:Y1)"},
> +	{DRM_FORMAT_UYVY, 16, "16-bit packed UYVY (8:8:8:8 MSB-Y2:V:Y1:U)"},
> +	{DRM_FORMAT_YVYU, 16, "16-bit packed YVYU (8:8:8:8 MSB-U:Y2:V:Y1)"},
> +	{DRM_FORMAT_VYUY, 16, "16-bit packed VYUY (8:8:8:8 MSB-Y2:U:Y1:V)"},
> +
> +	{DRM_FORMAT_C8, 8, "8-bit Indexed"},
> +	{DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"},
> +	{DRM_FORMAT_ABGR8888, 32, "32-bit RGBA (8:8:8:8 MSB-A:B:G:R)"},
> +	{DRM_FORMAT_XBGR8888, 32, "32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"},
> +
> +	{DRM_FORMAT_ARGB8888, 32, "32-bit BGRA (8:8:8:8 MSB-A:R:G:B)"},
> +	{DRM_FORMAT_XRGB8888, 32, "32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"},
> +	{DRM_FORMAT_XBGR2101010, 32, "32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"},
> +	{DRM_FORMAT_XRGB2101010, 32, "32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"},
> +
> +	{DRM_FORMAT_XRGB161616_GVT, 64,
> +		"64-bit XRGB (16:16:16:16 MSB-X:R:G:B)"},
> +	{DRM_FORMAT_XBGR161616_GVT, 64,
> +		"64-bit XBGR (16:16:16:16 MSB-X:B:G:R)"},
> +
> +	/* non-supported format has bpp default to 0 */
> +	{0, 0, NULL},
> +};
> +
> +static int skl_format_to_drm(int format, bool rgb_order, bool alpha,
> +	int yuv_order)
> +{
> +	int skl_pixel_formats_index = 14;
> +
> +	switch (format) {
> +	case PLANE_CTL_FORMAT_INDEXED:
> +		skl_pixel_formats_index = 4;
> +		break;
> +	case PLANE_CTL_FORMAT_RGB_565:
> +		skl_pixel_formats_index = 5;
> +		break;
> +	case PLANE_CTL_FORMAT_XRGB_8888:
> +		if (rgb_order)
> +			skl_pixel_formats_index = alpha ? 6 : 7;
> +		else
> +			skl_pixel_formats_index = alpha ? 8 : 9;
> +		break;
> +	case PLANE_CTL_FORMAT_XRGB_2101010:
> +		skl_pixel_formats_index = rgb_order ? 10 : 11;
> +		break;
> +
> +	case PLANE_CTL_FORMAT_XRGB_16161616F:
> +		skl_pixel_formats_index = rgb_order ? 12 : 13;
> +		break;
> +
> +	case PLANE_CTL_FORMAT_YUV422:
> +		skl_pixel_formats_index = yuv_order >> 16;
> +		if (skl_pixel_formats_index > 3)
> +			return -EINVAL;
> +		break;
> +
> +	default:
> +		break;
> +	}
> +
> +	return skl_pixel_formats_index;
> +}
> +
> +static u32 intel_vgpu_get_stride(struct intel_vgpu *vgpu, int pipe,
> +	u32 tiled, int stride_mask, int bpp)
> +{
> +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
> +
> +	u32 stride_reg = vgpu_vreg(vgpu, DSPSTRIDE(pipe)) & stride_mask;
> +	u32 stride = stride_reg;
> +
> +	if (IS_SKYLAKE(dev_priv)) {
> +		switch (tiled) {
> +		case PLANE_CTL_TILED_LINEAR:
> +			stride = stride_reg * 64;
> +			break;
> +		case PLANE_CTL_TILED_X:
> +			stride = stride_reg * 512;
> +			break;
> +		case PLANE_CTL_TILED_Y:
> +			stride = stride_reg * 128;
> +			break;
> +		case PLANE_CTL_TILED_YF:
> +			if (bpp == 8)
> +				stride = stride_reg * 64;
> +			else if (bpp == 16 || bpp == 32 || bpp == 64)
> +				stride = stride_reg * 128;
> +			else
> +				gvt_dbg_core("skl: unsupported bpp:%d\n", bpp);
> +			break;
> +		default:
> +			gvt_dbg_core("skl: unsupported tile format:%x\n",
> +				tiled);
> +		}
> +	}
> +
> +	return stride;
> +}
> +
> +static int intel_vgpu_decode_primary_plane_format(struct intel_vgpu *vgpu,
> +	int pipe, struct intel_vgpu_primary_plane_format *plane)
> +{
> +	u32	val, fmt;
> +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
> +
> +	val = vgpu_vreg(vgpu, DSPCNTR(pipe));
> +	plane->enabled = !!(val & DISPLAY_PLANE_ENABLE);
> +	if (!plane->enabled)
> +		return 0;
> +
> +	if (IS_SKYLAKE(dev_priv)) {
> +		plane->tiled = (val & PLANE_CTL_TILED_MASK) >>
> +		_PLANE_CTL_TILED_SHIFT;
> +		fmt = skl_format_to_drm(
> +			val & PLANE_CTL_FORMAT_MASK,
> +			val & PLANE_CTL_ORDER_RGBX,
> +			val & PLANE_CTL_ALPHA_MASK,
> +			val & PLANE_CTL_YUV422_ORDER_MASK);
> +		plane->bpp = skl_pixel_formats[fmt].bpp;
> +		plane->drm_format = skl_pixel_formats[fmt].drm_format;
> +	} else {
> +		plane->tiled = !!(val & DISPPLANE_TILED);
> +		fmt = (val & DISPPLANE_PIXFORMAT_MASK) >> _PRI_PLANE_FMT_SHIFT;
> +		plane->bpp = primary_pixel_formats[fmt].bpp;
> +		plane->drm_format = primary_pixel_formats[fmt].drm_format;
> +	}
> +
> +	if ((IS_SKYLAKE(dev_priv) && !skl_pixel_formats[fmt].bpp)
> +		|| (!IS_SKYLAKE(dev_priv) &&
> +			!primary_pixel_formats[fmt].bpp)) {

Just if (!plane->bpp)?

> +		gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt);
> +		return -EINVAL;
> +	}
> +
> +	plane->hw_format = fmt;
> +
> +	plane->base = vgpu_vreg(vgpu, DSPSURF(pipe)) & GTT_PAGE_MASK;
> +
> +	plane->stride = intel_vgpu_get_stride(vgpu, pipe, (plane->tiled << 10),
> +		(IS_SKYLAKE(dev_priv)) ? (_PRI_PLANE_STRIDE_MASK >> 6) :
> +		_PRI_PLANE_STRIDE_MASK, plane->bpp);
> +
> +	plane->width = (vgpu_vreg(vgpu, PIPESRC(pipe)) & _PIPE_H_SRCSZ_MASK) >>
> +		_PIPE_H_SRCSZ_SHIFT;
> +	plane->width += 1;
> +	plane->height = (vgpu_vreg(vgpu, PIPESRC(pipe)) &
> +			_PIPE_V_SRCSZ_MASK) >> _PIPE_V_SRCSZ_SHIFT;
> +	plane->height += 1;	/* raw height is one minus the real value */
> +
> +	val = vgpu_vreg(vgpu, DSPTILEOFF(pipe));
> +	plane->x_offset = (val & _PRI_PLANE_X_OFF_MASK) >>
> +		_PRI_PLANE_X_OFF_SHIFT;
> +	plane->y_offset = (val & _PRI_PLANE_Y_OFF_MASK) >>
> +		_PRI_PLANE_Y_OFF_SHIFT;
> +
> +	return 0;
> +}
> +
> +#define CURSOR_MODE_NUM	(1 << 6)

CURSOR_FORMAT_NUM

> +struct cursor_mode_format {
> +	int	drm_format;	/* Pixel format in DRM definition */
> +	u8	bpp;		/* Bits per pixel; 0 indicates invalid */
> +	u32	width;		/* In pixel */
> +	u32	height;		/* In lines */
> +	char	*desc;		/* The description */
> +};
> +
> +/* non-supported format has bpp default to 0 */
> +static struct cursor_mode_format cursor_pixel_formats[CURSOR_MODE_NUM] = {
> +	[0x22]  = {DRM_FORMAT_ARGB8888, 32, 128, 128, "128x128 32bpp ARGB"},
> +	[0x23]  = {DRM_FORMAT_ARGB8888, 32, 256, 256, "256x256 32bpp ARGB"},
> +	[0x27]  = {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"},
> +	[0x7]  = {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"},
> +};
> +
> +static int intel_vgpu_decode_cursor_plane_format(struct intel_vgpu *vgpu,
> +	int pipe, struct intel_vgpu_cursor_plane_format *plane)
> +{
> +	u32 val, mode;
> +	u32 alpha_plane, alpha_force;
> +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
> +
> +	val = vgpu_vreg(vgpu, CURCNTR(pipe));
> +	mode = val & CURSOR_MODE;
> +	plane->enabled = (mode != CURSOR_MODE_DISABLE);
> +	if (!plane->enabled)
> +		return 0;
> +
> +	if (!cursor_pixel_formats[mode].bpp) {
> +		gvt_vgpu_err("Non-supported cursor mode (0x%x)\n", mode);
> +		return -EINVAL;
> +	}
> +	plane->mode = mode;
> +	plane->bpp = cursor_pixel_formats[mode].bpp;
> +	plane->drm_format = cursor_pixel_formats[mode].drm_format;
> +	plane->width = cursor_pixel_formats[mode].width;
> +	plane->height = cursor_pixel_formats[mode].height;
> +
> +	alpha_plane = (val & _CURSOR_ALPHA_PLANE_MASK) >>
> +				_CURSOR_ALPHA_PLANE_SHIFT;
> +	alpha_force = (val & _CURSOR_ALPHA_FORCE_MASK) >>
> +				_CURSOR_ALPHA_FORCE_SHIFT;
> +	if (alpha_plane || alpha_force)
> +		gvt_dbg_core("alpha_plane=0x%x, alpha_force=0x%x\n",
> +			alpha_plane, alpha_force);
> +
> +	plane->base = vgpu_vreg(vgpu, CURBASE(pipe)) & GTT_PAGE_MASK;
> +
> +	val = vgpu_vreg(vgpu, CURPOS(pipe));
> +	plane->x_pos = (val & _CURSOR_POS_X_MASK) >> _CURSOR_POS_X_SHIFT;
> +	plane->x_sign = (val & _CURSOR_SIGN_X_MASK) >> _CURSOR_SIGN_X_SHIFT;
> +	plane->y_pos = (val & _CURSOR_POS_Y_MASK) >> _CURSOR_POS_Y_SHIFT;
> +	plane->y_sign = (val & _CURSOR_SIGN_Y_MASK) >> _CURSOR_SIGN_Y_SHIFT;
> +
> +	return 0;
> +}
> +
> +#define FORMAT_NUM_SRRITE	(1 << 3)
> +

SPRITE_FORMAT_NUM

> +static struct pixel_format sprite_pixel_formats[FORMAT_NUM_SRRITE] = {
> +	[0x0]  = {DRM_FORMAT_YUV422, 16, "YUV 16-bit 4:2:2 packed"},
> +	[0x1]  = {DRM_FORMAT_XRGB2101010, 32, "RGB 32-bit 2:10:10:10"},
> +	[0x2]  = {DRM_FORMAT_XRGB8888, 32, "RGB 32-bit 8:8:8:8"},
> +	[0x3]  = {DRM_FORMAT_XRGB161616_GVT, 64,
> +		    "RGB 64-bit 16:16:16:16 Floating Point"},
> +	[0x4] = {DRM_FORMAT_AYUV, 32,
> +		"YUV 32-bit 4:4:4 packed (8:8:8:8 MSB-X:Y:U:V)"},
> +};
> +
> +static int intel_vgpu_decode_sprite_plane_format(struct intel_vgpu *vgpu,
> +	int pipe, struct intel_vgpu_sprite_plane_format *plane)
> +{
> +	u32 val, fmt;
> +	u32 width;
> +	u32 color_order, yuv_order;
> +	int drm_format;
> +
> +	val = vgpu_vreg(vgpu, SPRCTL(pipe));
> +	plane->enabled = !!(val & SPRITE_ENABLE);
> +	if (!plane->enabled)
> +		return 0;
> +
> +	plane->tiled = !!(val & SPRITE_TILED);
> +	color_order = !!(val & SPRITE_RGB_ORDER_RGBX);
> +	yuv_order = (val & SPRITE_YUV_BYTE_ORDER_MASK) >>
> +				_SPRITE_YUV_ORDER_SHIFT;
> +
> +	fmt = (val & SPRITE_PIXFORMAT_MASK) >> _SPRITE_FMT_SHIFT;
> +	if (!sprite_pixel_formats[fmt].bpp) {
> +		gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt);
> +		return -EINVAL;
> +	}
> +	plane->hw_format = fmt;
> +	plane->bpp = sprite_pixel_formats[fmt].bpp;
> +	drm_format = sprite_pixel_formats[fmt].drm_format;
> +
> +	/* Order of RGB values in an RGBxxx buffer may be ordered RGB or
> +	 * BGR depending on the state of the color_order field
> +	 */
> +	if (!color_order) {
> +		if (drm_format == DRM_FORMAT_XRGB2101010)
> +			drm_format = DRM_FORMAT_XBGR2101010;
> +		else if (drm_format == DRM_FORMAT_XRGB8888)
> +			drm_format = DRM_FORMAT_XBGR8888;
> +	}
> +
> +	if (drm_format == DRM_FORMAT_YUV422) {
> +		switch (yuv_order) {
> +		case	0:

no extra space

> +			drm_format = DRM_FORMAT_YUYV;
> +			break;
> +		case	1:
> +			drm_format = DRM_FORMAT_UYVY;
> +			break;
> +		case	2:
> +			drm_format = DRM_FORMAT_YVYU;
> +			break;
> +		case	3:
> +			drm_format = DRM_FORMAT_VYUY;
> +			break;
> +		default:
> +			/* yuv_order has only 2 bits */
> +			break;
> +		}
> +	}
> +
> +	plane->drm_format = drm_format;
> +
> +	plane->base = vgpu_vreg(vgpu, SPRSURF(pipe)) & GTT_PAGE_MASK;
> +	plane->width = vgpu_vreg(vgpu, SPRSTRIDE(pipe)) &
> +				_SPRITE_STRIDE_MASK;
> +	plane->width /= plane->bpp / 8;	/* raw width in bytes */
> +
> +	val = vgpu_vreg(vgpu, SPRSIZE(pipe));
> +	plane->height = (val & _SPRITE_SIZE_HEIGHT_MASK) >>
> +		_SPRITE_SIZE_HEIGHT_SHIFT;
> +	width = (val & _SPRITE_SIZE_WIDTH_MASK) >> _SPRITE_SIZE_WIDTH_SHIFT;
> +	plane->height += 1;	/* raw height is one minus the real value */
> +	width += 1;		/* raw width is one minus the real value */
> +	if (plane->width != width)
> +		gvt_dbg_core("sprite_plane: plane->width=%d, width=%d\n",
> +			plane->width, width);

should report error?

> +static int intel_vgpu_decode_fb_format(struct intel_gvt *gvt, int id,
> +	struct intel_vgpu_fb_format *fb)
> +{
> +	int i;
> +	struct intel_vgpu *vgpu = NULL;
> +	int ret = 0;
> +	struct drm_i915_private *dev_priv = gvt->dev_priv;
> +
> +	if (!fb)
> +		return -EINVAL;
> +
> +	/* TODO: use fine-grained refcnt later */
> +	mutex_lock(&gvt->lock);
> +
> +	for_each_active_vgpu(gvt, vgpu, i)
> +		if (vgpu->id == id)
> +			break;
> +
> +	if (!vgpu) {
> +		gvt_vgpu_err("Invalid vgpu ID (%d)\n", id);
> +		mutex_unlock(&gvt->lock);
> +		return -ENODEV;
> +	}
> +
> +	for (i = 0; i < I915_MAX_PIPES; i++) {
> +		struct intel_vgpu_pipe_format *pipe = &fb->pipes[i];
> +		u32 ddi_func_ctl = vgpu_vreg(vgpu, TRANS_DDI_FUNC_CTL(i));
> +
> +		if (!(ddi_func_ctl & TRANS_DDI_FUNC_ENABLE)) {
> +			pipe->ddi_port = DDI_PORT_NONE;
> +		} else {
> +			u32 port = (ddi_func_ctl & TRANS_DDI_PORT_MASK) >>
> +						TRANS_DDI_PORT_SHIFT;
> +			if (port <= DDI_PORT_E)
> +				pipe->ddi_port = port;
> +			else
> +				pipe->ddi_port = DDI_PORT_NONE;
> +		}
> +
> +		ret |= intel_vgpu_decode_primary_plane_format(vgpu,
> +			i, &pipe->primary);
> +		ret |= intel_vgpu_decode_sprite_plane_format(vgpu,
> +			i, &pipe->sprite);
> +		ret |= intel_vgpu_decode_cursor_plane_format(vgpu,
> +			i, &pipe->cursor);
> +
> +		if (ret) {
> +			gvt_vgpu_err("Decode format error for pipe(%d)\n", i);
> +			ret = -EINVAL;
> +			break;
> +		}
> +	}
> +
> +	mutex_unlock(&gvt->lock);
> +
> +	return ret;
> +}
> +
> +/**
> + * intel_vgpu_decode_plane - Decode plane based on plane id
> + * @dev: drm device
> + * @vgpu: input vgpu
> + * This function is called for decoding plane
> + *
> + * Returns:
> + * pipe on success, NULL if failed.
> + */
> +struct intel_vgpu_pipe_format *intel_vgpu_decode_plane(struct drm_device *dev,
> +		struct intel_vgpu *vgpu)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_vgpu_fb_format fb;
> +	struct intel_vgpu_pipe_format *pipe;
> +	int i;
> +
> +	if (intel_vgpu_decode_fb_format(dev_priv->gvt, vgpu->id, &fb))
> +		return NULL;
> +
> +	for (i = 0; i < I915_MAX_PIPES; i++)
> +		if (pipe_is_enabled(vgpu, i))
> +			break;
> +	if (i >= I915_MAX_PIPES) {
> +		gvt_dbg_core("No enabled pipes\n");
> +		return NULL;
> +	}

Looks this check should be moved in above decode_fb_format function which
doesn't check if pipe is actually enabled.

> +	pipe = &fb.pipes[i];
> +
> +	if (!pipe || !pipe->primary.enabled) {
> +		gvt_dbg_core("Invalid pipe_id :%d\n", i);
> +		return NULL;
> +	}

And this function is to find primary plane actually? Should name it like
intel_vgpu_decode_primary_plane().

> +
> +	return pipe;
> +}
> +
> diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.h b/drivers/gpu/drm/i915/gvt/fb_decoder.h
> new file mode 100644
> index 0000000..04300af
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.h
> +
> +struct intel_vgpu_pipe_format {
> +	struct intel_vgpu_primary_plane_format	primary;
> +	struct intel_vgpu_sprite_plane_format	sprite;
> +	struct intel_vgpu_cursor_plane_format	cursor;
> +	enum DDI_PORT ddi_port;  /* the DDI port that pipe is connected to */
> +};
> +
> +struct intel_vgpu_fb_format {
> +	struct intel_vgpu_pipe_format	pipes[4];
> +};

Should use MAX_PIPE definition.

-- 
Open Source Technology Center, Intel ltd.

$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

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

* Re: [PATCH v6 3/6] drm/i915/gvt: Frame buffer decoder support for GVT-g
@ 2017-05-31  5:12     ` Zhenyu Wang
  0 siblings, 0 replies; 74+ messages in thread
From: Zhenyu Wang @ 2017-05-31  5:12 UTC (permalink / raw)
  To: Xiaoguang Chen; +Cc: intel-gfx, linux-kernel, kraxel, intel-gvt-dev, zhiyuan.lv


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

On 2017.05.27 16:38:49 +0800, Xiaoguang Chen wrote:
> decode frambuffer attributes of primary, cursor and sprite plane
> 
> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
> ---
>  drivers/gpu/drm/i915/gvt/Makefile     |   3 +-
>  drivers/gpu/drm/i915/gvt/display.c    |   2 +-
>  drivers/gpu/drm/i915/gvt/display.h    |   2 +
>  drivers/gpu/drm/i915/gvt/fb_decoder.c | 479 ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/gvt/fb_decoder.h | 166 ++++++++++++
>  drivers/gpu/drm/i915/gvt/gvt.h        |   1 +
>  6 files changed, 651 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.c
>  create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.h
> 
> diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile
> index b123c20..192ca26 100644
> --- a/drivers/gpu/drm/i915/gvt/Makefile
> +++ b/drivers/gpu/drm/i915/gvt/Makefile
> @@ -1,7 +1,8 @@
>  GVT_DIR := gvt
>  GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \
>  	interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \
> -	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o
> +	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o \
> +	fb_decoder.o
>  
>  ccflags-y				+= -I$(src) -I$(src)/$(GVT_DIR) -Wall
>  i915-y					+= $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
> diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
> index e0261fc..f5f63c5 100644
> --- a/drivers/gpu/drm/i915/gvt/display.c
> +++ b/drivers/gpu/drm/i915/gvt/display.c
> @@ -67,7 +67,7 @@ static int edp_pipe_is_enabled(struct intel_vgpu *vgpu)
>  	return 1;
>  }
>  
> -static int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
> +int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
>  {
>  	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
>  
> diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h
> index d73de22..b46b868 100644
> --- a/drivers/gpu/drm/i915/gvt/display.h
> +++ b/drivers/gpu/drm/i915/gvt/display.h
> @@ -179,4 +179,6 @@ int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution);
>  void intel_vgpu_reset_display(struct intel_vgpu *vgpu);
>  void intel_vgpu_clean_display(struct intel_vgpu *vgpu);
>  
> +int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe);
> +
>  #endif
> diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.c b/drivers/gpu/drm/i915/gvt/fb_decoder.c
> new file mode 100644
> index 0000000..d4404fd
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.c
> @@ -0,0 +1,479 @@
> +/*
> + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + *
> + * Authors:
> + *    Kevin Tian <kevin.tian@intel.com>
> + *
> + * Contributors:
> + *    Bing Niu <bing.niu@intel.com>
> + *    Xu Han <xu.han@intel.com>
> + *    Ping Gao <ping.a.gao@intel.com>
> + *    Xiaoguang Chen <xiaoguang.chen@intel.com>
> + *    Yang Liu <yang2.liu@intel.com>
> + *
> + */
> +
> +#include <uapi/drm/drm_fourcc.h>
> +#include "i915_drv.h"
> +#include "gvt.h"
> +
> +/* The below definitions are required by guest. */
> +// [63:0] x:R:G:B 16:16:16:16 little endian
> +#define DRM_FORMAT_XRGB161616_GVT  fourcc_code('X', 'R', '4', '8')
> +// [63:0] x:B:G:R 16:16:16:16 little endian
> +#define DRM_FORMAT_XBGR161616_GVT  fourcc_code('X', 'B', '4', '8')
> +

Should be added to drm_fourcc?

> +#define FORMAT_NUM	16

PRIMARY_FORMAT_NUM

> +struct pixel_format {
> +	int	drm_format;	/* Pixel format in DRM definition */
> +	int	bpp;		/* Bits per pixel, 0 indicates invalid */
> +	char *desc;		/* The description */
> +};
> +
> +/* non-supported format has bpp default to 0 */
> +static struct pixel_format primary_pixel_formats[FORMAT_NUM] = {
> +	[0x2] = {DRM_FORMAT_C8, 8, "8-bit Indexed"},
> +	[0x5] = {DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"},
> +	[0x6] = {DRM_FORMAT_XRGB8888, 32,
> +		"32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"},
> +	[0x8] = {DRM_FORMAT_XBGR2101010, 32,
> +		"32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"},
> +	[0xa] = {DRM_FORMAT_XRGB2101010, 32,
> +		"32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"},
> +	[0xc] = {DRM_FORMAT_XRGB161616_GVT, 64,
> +		"64-bit RGBX Floating Point(16:16:16:16 MSB-X:B:G:R)"},
> +	[0xe] = {DRM_FORMAT_XBGR8888, 32,
> +		"32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"},
> +};

might explicitly say this is bdw_pixel_formats?

> +
> +/* non-supported format has bpp default to 0 */
> +static struct pixel_format skl_pixel_formats[] = {
> +	{DRM_FORMAT_YUYV, 16, "16-bit packed YUYV (8:8:8:8 MSB-V:Y2:U:Y1)"},
> +	{DRM_FORMAT_UYVY, 16, "16-bit packed UYVY (8:8:8:8 MSB-Y2:V:Y1:U)"},
> +	{DRM_FORMAT_YVYU, 16, "16-bit packed YVYU (8:8:8:8 MSB-U:Y2:V:Y1)"},
> +	{DRM_FORMAT_VYUY, 16, "16-bit packed VYUY (8:8:8:8 MSB-Y2:U:Y1:V)"},
> +
> +	{DRM_FORMAT_C8, 8, "8-bit Indexed"},
> +	{DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"},
> +	{DRM_FORMAT_ABGR8888, 32, "32-bit RGBA (8:8:8:8 MSB-A:B:G:R)"},
> +	{DRM_FORMAT_XBGR8888, 32, "32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"},
> +
> +	{DRM_FORMAT_ARGB8888, 32, "32-bit BGRA (8:8:8:8 MSB-A:R:G:B)"},
> +	{DRM_FORMAT_XRGB8888, 32, "32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"},
> +	{DRM_FORMAT_XBGR2101010, 32, "32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"},
> +	{DRM_FORMAT_XRGB2101010, 32, "32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"},
> +
> +	{DRM_FORMAT_XRGB161616_GVT, 64,
> +		"64-bit XRGB (16:16:16:16 MSB-X:R:G:B)"},
> +	{DRM_FORMAT_XBGR161616_GVT, 64,
> +		"64-bit XBGR (16:16:16:16 MSB-X:B:G:R)"},
> +
> +	/* non-supported format has bpp default to 0 */
> +	{0, 0, NULL},
> +};
> +
> +static int skl_format_to_drm(int format, bool rgb_order, bool alpha,
> +	int yuv_order)
> +{
> +	int skl_pixel_formats_index = 14;
> +
> +	switch (format) {
> +	case PLANE_CTL_FORMAT_INDEXED:
> +		skl_pixel_formats_index = 4;
> +		break;
> +	case PLANE_CTL_FORMAT_RGB_565:
> +		skl_pixel_formats_index = 5;
> +		break;
> +	case PLANE_CTL_FORMAT_XRGB_8888:
> +		if (rgb_order)
> +			skl_pixel_formats_index = alpha ? 6 : 7;
> +		else
> +			skl_pixel_formats_index = alpha ? 8 : 9;
> +		break;
> +	case PLANE_CTL_FORMAT_XRGB_2101010:
> +		skl_pixel_formats_index = rgb_order ? 10 : 11;
> +		break;
> +
> +	case PLANE_CTL_FORMAT_XRGB_16161616F:
> +		skl_pixel_formats_index = rgb_order ? 12 : 13;
> +		break;
> +
> +	case PLANE_CTL_FORMAT_YUV422:
> +		skl_pixel_formats_index = yuv_order >> 16;
> +		if (skl_pixel_formats_index > 3)
> +			return -EINVAL;
> +		break;
> +
> +	default:
> +		break;
> +	}
> +
> +	return skl_pixel_formats_index;
> +}
> +
> +static u32 intel_vgpu_get_stride(struct intel_vgpu *vgpu, int pipe,
> +	u32 tiled, int stride_mask, int bpp)
> +{
> +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
> +
> +	u32 stride_reg = vgpu_vreg(vgpu, DSPSTRIDE(pipe)) & stride_mask;
> +	u32 stride = stride_reg;
> +
> +	if (IS_SKYLAKE(dev_priv)) {
> +		switch (tiled) {
> +		case PLANE_CTL_TILED_LINEAR:
> +			stride = stride_reg * 64;
> +			break;
> +		case PLANE_CTL_TILED_X:
> +			stride = stride_reg * 512;
> +			break;
> +		case PLANE_CTL_TILED_Y:
> +			stride = stride_reg * 128;
> +			break;
> +		case PLANE_CTL_TILED_YF:
> +			if (bpp == 8)
> +				stride = stride_reg * 64;
> +			else if (bpp == 16 || bpp == 32 || bpp == 64)
> +				stride = stride_reg * 128;
> +			else
> +				gvt_dbg_core("skl: unsupported bpp:%d\n", bpp);
> +			break;
> +		default:
> +			gvt_dbg_core("skl: unsupported tile format:%x\n",
> +				tiled);
> +		}
> +	}
> +
> +	return stride;
> +}
> +
> +static int intel_vgpu_decode_primary_plane_format(struct intel_vgpu *vgpu,
> +	int pipe, struct intel_vgpu_primary_plane_format *plane)
> +{
> +	u32	val, fmt;
> +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
> +
> +	val = vgpu_vreg(vgpu, DSPCNTR(pipe));
> +	plane->enabled = !!(val & DISPLAY_PLANE_ENABLE);
> +	if (!plane->enabled)
> +		return 0;
> +
> +	if (IS_SKYLAKE(dev_priv)) {
> +		plane->tiled = (val & PLANE_CTL_TILED_MASK) >>
> +		_PLANE_CTL_TILED_SHIFT;
> +		fmt = skl_format_to_drm(
> +			val & PLANE_CTL_FORMAT_MASK,
> +			val & PLANE_CTL_ORDER_RGBX,
> +			val & PLANE_CTL_ALPHA_MASK,
> +			val & PLANE_CTL_YUV422_ORDER_MASK);
> +		plane->bpp = skl_pixel_formats[fmt].bpp;
> +		plane->drm_format = skl_pixel_formats[fmt].drm_format;
> +	} else {
> +		plane->tiled = !!(val & DISPPLANE_TILED);
> +		fmt = (val & DISPPLANE_PIXFORMAT_MASK) >> _PRI_PLANE_FMT_SHIFT;
> +		plane->bpp = primary_pixel_formats[fmt].bpp;
> +		plane->drm_format = primary_pixel_formats[fmt].drm_format;
> +	}
> +
> +	if ((IS_SKYLAKE(dev_priv) && !skl_pixel_formats[fmt].bpp)
> +		|| (!IS_SKYLAKE(dev_priv) &&
> +			!primary_pixel_formats[fmt].bpp)) {

Just if (!plane->bpp)?

> +		gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt);
> +		return -EINVAL;
> +	}
> +
> +	plane->hw_format = fmt;
> +
> +	plane->base = vgpu_vreg(vgpu, DSPSURF(pipe)) & GTT_PAGE_MASK;
> +
> +	plane->stride = intel_vgpu_get_stride(vgpu, pipe, (plane->tiled << 10),
> +		(IS_SKYLAKE(dev_priv)) ? (_PRI_PLANE_STRIDE_MASK >> 6) :
> +		_PRI_PLANE_STRIDE_MASK, plane->bpp);
> +
> +	plane->width = (vgpu_vreg(vgpu, PIPESRC(pipe)) & _PIPE_H_SRCSZ_MASK) >>
> +		_PIPE_H_SRCSZ_SHIFT;
> +	plane->width += 1;
> +	plane->height = (vgpu_vreg(vgpu, PIPESRC(pipe)) &
> +			_PIPE_V_SRCSZ_MASK) >> _PIPE_V_SRCSZ_SHIFT;
> +	plane->height += 1;	/* raw height is one minus the real value */
> +
> +	val = vgpu_vreg(vgpu, DSPTILEOFF(pipe));
> +	plane->x_offset = (val & _PRI_PLANE_X_OFF_MASK) >>
> +		_PRI_PLANE_X_OFF_SHIFT;
> +	plane->y_offset = (val & _PRI_PLANE_Y_OFF_MASK) >>
> +		_PRI_PLANE_Y_OFF_SHIFT;
> +
> +	return 0;
> +}
> +
> +#define CURSOR_MODE_NUM	(1 << 6)

CURSOR_FORMAT_NUM

> +struct cursor_mode_format {
> +	int	drm_format;	/* Pixel format in DRM definition */
> +	u8	bpp;		/* Bits per pixel; 0 indicates invalid */
> +	u32	width;		/* In pixel */
> +	u32	height;		/* In lines */
> +	char	*desc;		/* The description */
> +};
> +
> +/* non-supported format has bpp default to 0 */
> +static struct cursor_mode_format cursor_pixel_formats[CURSOR_MODE_NUM] = {
> +	[0x22]  = {DRM_FORMAT_ARGB8888, 32, 128, 128, "128x128 32bpp ARGB"},
> +	[0x23]  = {DRM_FORMAT_ARGB8888, 32, 256, 256, "256x256 32bpp ARGB"},
> +	[0x27]  = {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"},
> +	[0x7]  = {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"},
> +};
> +
> +static int intel_vgpu_decode_cursor_plane_format(struct intel_vgpu *vgpu,
> +	int pipe, struct intel_vgpu_cursor_plane_format *plane)
> +{
> +	u32 val, mode;
> +	u32 alpha_plane, alpha_force;
> +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
> +
> +	val = vgpu_vreg(vgpu, CURCNTR(pipe));
> +	mode = val & CURSOR_MODE;
> +	plane->enabled = (mode != CURSOR_MODE_DISABLE);
> +	if (!plane->enabled)
> +		return 0;
> +
> +	if (!cursor_pixel_formats[mode].bpp) {
> +		gvt_vgpu_err("Non-supported cursor mode (0x%x)\n", mode);
> +		return -EINVAL;
> +	}
> +	plane->mode = mode;
> +	plane->bpp = cursor_pixel_formats[mode].bpp;
> +	plane->drm_format = cursor_pixel_formats[mode].drm_format;
> +	plane->width = cursor_pixel_formats[mode].width;
> +	plane->height = cursor_pixel_formats[mode].height;
> +
> +	alpha_plane = (val & _CURSOR_ALPHA_PLANE_MASK) >>
> +				_CURSOR_ALPHA_PLANE_SHIFT;
> +	alpha_force = (val & _CURSOR_ALPHA_FORCE_MASK) >>
> +				_CURSOR_ALPHA_FORCE_SHIFT;
> +	if (alpha_plane || alpha_force)
> +		gvt_dbg_core("alpha_plane=0x%x, alpha_force=0x%x\n",
> +			alpha_plane, alpha_force);
> +
> +	plane->base = vgpu_vreg(vgpu, CURBASE(pipe)) & GTT_PAGE_MASK;
> +
> +	val = vgpu_vreg(vgpu, CURPOS(pipe));
> +	plane->x_pos = (val & _CURSOR_POS_X_MASK) >> _CURSOR_POS_X_SHIFT;
> +	plane->x_sign = (val & _CURSOR_SIGN_X_MASK) >> _CURSOR_SIGN_X_SHIFT;
> +	plane->y_pos = (val & _CURSOR_POS_Y_MASK) >> _CURSOR_POS_Y_SHIFT;
> +	plane->y_sign = (val & _CURSOR_SIGN_Y_MASK) >> _CURSOR_SIGN_Y_SHIFT;
> +
> +	return 0;
> +}
> +
> +#define FORMAT_NUM_SRRITE	(1 << 3)
> +

SPRITE_FORMAT_NUM

> +static struct pixel_format sprite_pixel_formats[FORMAT_NUM_SRRITE] = {
> +	[0x0]  = {DRM_FORMAT_YUV422, 16, "YUV 16-bit 4:2:2 packed"},
> +	[0x1]  = {DRM_FORMAT_XRGB2101010, 32, "RGB 32-bit 2:10:10:10"},
> +	[0x2]  = {DRM_FORMAT_XRGB8888, 32, "RGB 32-bit 8:8:8:8"},
> +	[0x3]  = {DRM_FORMAT_XRGB161616_GVT, 64,
> +		    "RGB 64-bit 16:16:16:16 Floating Point"},
> +	[0x4] = {DRM_FORMAT_AYUV, 32,
> +		"YUV 32-bit 4:4:4 packed (8:8:8:8 MSB-X:Y:U:V)"},
> +};
> +
> +static int intel_vgpu_decode_sprite_plane_format(struct intel_vgpu *vgpu,
> +	int pipe, struct intel_vgpu_sprite_plane_format *plane)
> +{
> +	u32 val, fmt;
> +	u32 width;
> +	u32 color_order, yuv_order;
> +	int drm_format;
> +
> +	val = vgpu_vreg(vgpu, SPRCTL(pipe));
> +	plane->enabled = !!(val & SPRITE_ENABLE);
> +	if (!plane->enabled)
> +		return 0;
> +
> +	plane->tiled = !!(val & SPRITE_TILED);
> +	color_order = !!(val & SPRITE_RGB_ORDER_RGBX);
> +	yuv_order = (val & SPRITE_YUV_BYTE_ORDER_MASK) >>
> +				_SPRITE_YUV_ORDER_SHIFT;
> +
> +	fmt = (val & SPRITE_PIXFORMAT_MASK) >> _SPRITE_FMT_SHIFT;
> +	if (!sprite_pixel_formats[fmt].bpp) {
> +		gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt);
> +		return -EINVAL;
> +	}
> +	plane->hw_format = fmt;
> +	plane->bpp = sprite_pixel_formats[fmt].bpp;
> +	drm_format = sprite_pixel_formats[fmt].drm_format;
> +
> +	/* Order of RGB values in an RGBxxx buffer may be ordered RGB or
> +	 * BGR depending on the state of the color_order field
> +	 */
> +	if (!color_order) {
> +		if (drm_format == DRM_FORMAT_XRGB2101010)
> +			drm_format = DRM_FORMAT_XBGR2101010;
> +		else if (drm_format == DRM_FORMAT_XRGB8888)
> +			drm_format = DRM_FORMAT_XBGR8888;
> +	}
> +
> +	if (drm_format == DRM_FORMAT_YUV422) {
> +		switch (yuv_order) {
> +		case	0:

no extra space

> +			drm_format = DRM_FORMAT_YUYV;
> +			break;
> +		case	1:
> +			drm_format = DRM_FORMAT_UYVY;
> +			break;
> +		case	2:
> +			drm_format = DRM_FORMAT_YVYU;
> +			break;
> +		case	3:
> +			drm_format = DRM_FORMAT_VYUY;
> +			break;
> +		default:
> +			/* yuv_order has only 2 bits */
> +			break;
> +		}
> +	}
> +
> +	plane->drm_format = drm_format;
> +
> +	plane->base = vgpu_vreg(vgpu, SPRSURF(pipe)) & GTT_PAGE_MASK;
> +	plane->width = vgpu_vreg(vgpu, SPRSTRIDE(pipe)) &
> +				_SPRITE_STRIDE_MASK;
> +	plane->width /= plane->bpp / 8;	/* raw width in bytes */
> +
> +	val = vgpu_vreg(vgpu, SPRSIZE(pipe));
> +	plane->height = (val & _SPRITE_SIZE_HEIGHT_MASK) >>
> +		_SPRITE_SIZE_HEIGHT_SHIFT;
> +	width = (val & _SPRITE_SIZE_WIDTH_MASK) >> _SPRITE_SIZE_WIDTH_SHIFT;
> +	plane->height += 1;	/* raw height is one minus the real value */
> +	width += 1;		/* raw width is one minus the real value */
> +	if (plane->width != width)
> +		gvt_dbg_core("sprite_plane: plane->width=%d, width=%d\n",
> +			plane->width, width);

should report error?

> +static int intel_vgpu_decode_fb_format(struct intel_gvt *gvt, int id,
> +	struct intel_vgpu_fb_format *fb)
> +{
> +	int i;
> +	struct intel_vgpu *vgpu = NULL;
> +	int ret = 0;
> +	struct drm_i915_private *dev_priv = gvt->dev_priv;
> +
> +	if (!fb)
> +		return -EINVAL;
> +
> +	/* TODO: use fine-grained refcnt later */
> +	mutex_lock(&gvt->lock);
> +
> +	for_each_active_vgpu(gvt, vgpu, i)
> +		if (vgpu->id == id)
> +			break;
> +
> +	if (!vgpu) {
> +		gvt_vgpu_err("Invalid vgpu ID (%d)\n", id);
> +		mutex_unlock(&gvt->lock);
> +		return -ENODEV;
> +	}
> +
> +	for (i = 0; i < I915_MAX_PIPES; i++) {
> +		struct intel_vgpu_pipe_format *pipe = &fb->pipes[i];
> +		u32 ddi_func_ctl = vgpu_vreg(vgpu, TRANS_DDI_FUNC_CTL(i));
> +
> +		if (!(ddi_func_ctl & TRANS_DDI_FUNC_ENABLE)) {
> +			pipe->ddi_port = DDI_PORT_NONE;
> +		} else {
> +			u32 port = (ddi_func_ctl & TRANS_DDI_PORT_MASK) >>
> +						TRANS_DDI_PORT_SHIFT;
> +			if (port <= DDI_PORT_E)
> +				pipe->ddi_port = port;
> +			else
> +				pipe->ddi_port = DDI_PORT_NONE;
> +		}
> +
> +		ret |= intel_vgpu_decode_primary_plane_format(vgpu,
> +			i, &pipe->primary);
> +		ret |= intel_vgpu_decode_sprite_plane_format(vgpu,
> +			i, &pipe->sprite);
> +		ret |= intel_vgpu_decode_cursor_plane_format(vgpu,
> +			i, &pipe->cursor);
> +
> +		if (ret) {
> +			gvt_vgpu_err("Decode format error for pipe(%d)\n", i);
> +			ret = -EINVAL;
> +			break;
> +		}
> +	}
> +
> +	mutex_unlock(&gvt->lock);
> +
> +	return ret;
> +}
> +
> +/**
> + * intel_vgpu_decode_plane - Decode plane based on plane id
> + * @dev: drm device
> + * @vgpu: input vgpu
> + * This function is called for decoding plane
> + *
> + * Returns:
> + * pipe on success, NULL if failed.
> + */
> +struct intel_vgpu_pipe_format *intel_vgpu_decode_plane(struct drm_device *dev,
> +		struct intel_vgpu *vgpu)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_vgpu_fb_format fb;
> +	struct intel_vgpu_pipe_format *pipe;
> +	int i;
> +
> +	if (intel_vgpu_decode_fb_format(dev_priv->gvt, vgpu->id, &fb))
> +		return NULL;
> +
> +	for (i = 0; i < I915_MAX_PIPES; i++)
> +		if (pipe_is_enabled(vgpu, i))
> +			break;
> +	if (i >= I915_MAX_PIPES) {
> +		gvt_dbg_core("No enabled pipes\n");
> +		return NULL;
> +	}

Looks this check should be moved in above decode_fb_format function which
doesn't check if pipe is actually enabled.

> +	pipe = &fb.pipes[i];
> +
> +	if (!pipe || !pipe->primary.enabled) {
> +		gvt_dbg_core("Invalid pipe_id :%d\n", i);
> +		return NULL;
> +	}

And this function is to find primary plane actually? Should name it like
intel_vgpu_decode_primary_plane().

> +
> +	return pipe;
> +}
> +
> diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.h b/drivers/gpu/drm/i915/gvt/fb_decoder.h
> new file mode 100644
> index 0000000..04300af
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.h
> +
> +struct intel_vgpu_pipe_format {
> +	struct intel_vgpu_primary_plane_format	primary;
> +	struct intel_vgpu_sprite_plane_format	sprite;
> +	struct intel_vgpu_cursor_plane_format	cursor;
> +	enum DDI_PORT ddi_port;  /* the DDI port that pipe is connected to */
> +};
> +
> +struct intel_vgpu_fb_format {
> +	struct intel_vgpu_pipe_format	pipes[4];
> +};

Should use MAX_PIPE definition.

-- 
Open Source Technology Center, Intel ltd.

$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

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

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* RE: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
  2017-05-29  7:20     ` Gerd Hoffmann
@ 2017-05-31  6:18       ` Chen, Xiaoguang
  -1 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-05-31  6:18 UTC (permalink / raw)
  To: Gerd Hoffmann, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, Lv, Zhiyuan, intel-gvt-dev, Wang, Zhi A, Tian, Kevin

Hi,

>-----Original Message-----
>From: Gerd Hoffmann [mailto:kraxel@redhat.com]
>Sent: Monday, May 29, 2017 3:20 PM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
>alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
>gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
>
>> +struct vfio_vgpu_dmabuf_info {
>> +	__u32 argsz;
>> +	__u32 flags;
>> +	struct vfio_vgpu_plane_info plane_info;
>> +	__s32 fd;
>> +	__u32 pad;
>> +};
>
>Hmm, now you have argsz and flags twice in vfio_vgpu_dmabuf_info ...
>
>I think we should have something like this:
>
>struct vfio_vgpu_plane_info {
>        __u64 start;
>        __u64 drm_format_mod;
>        __u32 drm_format;
>        __u32 width;
>        __u32 height;
>        __u32 stride;
>        __u32 size;
>        __u32 x_pos;
>        __u32 y_pos;
>        __u32 padding;
>};
>
>struct vfio_vgpu_query_plane {
>	__u32 argsz;
>	__u32 flags;
>	struct vfio_vgpu_plane_info plane_info;
>        __u32 plane_id;
>        __u32 padding;
>};
>
>struct vfio_vgpu_create_dmabuf {
>	__u32 argsz;
>	__u32 flags;
>	struct vfio_vgpu_plane_info plane_info;
>        __u32 plane_id;
>        __s32 fd;
>};
Good suggestion will apply in the next version.
Thanks for review :)

Chenxg.

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
@ 2017-05-31  6:18       ` Chen, Xiaoguang
  0 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-05-31  6:18 UTC (permalink / raw)
  To: Gerd Hoffmann, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, Lv, Zhiyuan, intel-gvt-dev, Wang, Zhi A, Tian, Kevin

Hi,

>-----Original Message-----
>From: Gerd Hoffmann [mailto:kraxel@redhat.com]
>Sent: Monday, May 29, 2017 3:20 PM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
>alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
>gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
>
>> +struct vfio_vgpu_dmabuf_info {
>> +	__u32 argsz;
>> +	__u32 flags;
>> +	struct vfio_vgpu_plane_info plane_info;
>> +	__s32 fd;
>> +	__u32 pad;
>> +};
>
>Hmm, now you have argsz and flags twice in vfio_vgpu_dmabuf_info ...
>
>I think we should have something like this:
>
>struct vfio_vgpu_plane_info {
>        __u64 start;
>        __u64 drm_format_mod;
>        __u32 drm_format;
>        __u32 width;
>        __u32 height;
>        __u32 stride;
>        __u32 size;
>        __u32 x_pos;
>        __u32 y_pos;
>        __u32 padding;
>};
>
>struct vfio_vgpu_query_plane {
>	__u32 argsz;
>	__u32 flags;
>	struct vfio_vgpu_plane_info plane_info;
>        __u32 plane_id;
>        __u32 padding;
>};
>
>struct vfio_vgpu_create_dmabuf {
>	__u32 argsz;
>	__u32 flags;
>	struct vfio_vgpu_plane_info plane_info;
>        __u32 plane_id;
>        __s32 fd;
>};
Good suggestion will apply in the next version.
Thanks for review :)

Chenxg.
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* RE: [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g
  2017-05-31  4:47     ` Zhenyu Wang
@ 2017-05-31  6:22       ` Chen, Xiaoguang
  -1 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-05-31  6:22 UTC (permalink / raw)
  To: Zhenyu Wang
  Cc: Tian, Kevin, intel-gfx, linux-kernel, chris, alex.williamson,
	kraxel, Niu, Bing, intel-gvt-dev, Wang, Zhi A, Lv, Zhiyuan

Hi 

>-----Original Message-----
>From: intel-gvt-dev [mailto:intel-gvt-dev-bounces@lists.freedesktop.org] On
>Behalf Of Zhenyu Wang
>Sent: Wednesday, May 31, 2017 12:47 PM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
>Cc: Tian, Kevin <kevin.tian@intel.com>; intel-gfx@lists.freedesktop.org; linux-
>kernel@vger.kernel.org; zhenyuw@linux.intel.com; chris@chris-wilson.co.uk;
>alex.williamson@redhat.com; kraxel@redhat.com; Niu, Bing
><bing.niu@intel.com>; intel-gvt-dev@lists.freedesktop.org; Wang, Zhi A
><zhi.a.wang@intel.com>; Lv, Zhiyuan <zhiyuan.lv@intel.com>
>Subject: Re: [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g
>
>On 2017.05.27 16:38:48 +0800, Xiaoguang Chen wrote:
>> OpRegion is needed to support display related operation for intel
>> vgpu.
>>
>> A vfio device region is added to intel vgpu to deliver the host
>> OpRegion information to user space so user space can construct the
>> OpRegion for vgpu.
>>
>> Signed-off-by: Bing Niu <bing.niu@intel.com>
>> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
>> ---
>>  drivers/gpu/drm/i915/gvt/kvmgt.c    | 97
>+++++++++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/i915/gvt/opregion.c |  8 ++-
>>  2 files changed, 104 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
>> b/drivers/gpu/drm/i915/gvt/kvmgt.c
>> index 3c6a02b..389f072 100644
>> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
>> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
>> @@ -53,6 +53,8 @@ static const struct intel_gvt_ops *intel_gvt_ops;
>> #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)
>>
>> +#define OPREGION_SIGNATURE "IntelGraphicsMem"
>> +
>>  struct vfio_region;
>>  struct intel_vgpu_regops {
>>  	size_t (*rw)(struct intel_vgpu *vgpu, char *buf, @@ -436,6 +438,92
>> @@ static void kvmgt_protect_table_del(struct kvmgt_guest_info *info,
>>  	}
>>  }
>>
>> +static size_t intel_vgpu_reg_rw_opregion(struct intel_vgpu *vgpu, char *buf,
>> +		size_t count, loff_t *ppos, bool iswrite) {
>> +	unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) -
>> +			VFIO_PCI_NUM_REGIONS;
>> +	void *base = vgpu->vdev.region[i].data;
>> +	loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
>> +
>> +	if (pos >= vgpu->vdev.region[i].size || iswrite) {
>> +		gvt_vgpu_err("invalid op or offset for Intel vgpu OpRegion\n");
>> +		return -EINVAL;
>> +	}
>> +	count = min(count, (size_t)(vgpu->vdev.region[i].size - pos));
>> +	memcpy(buf, base + pos, count);
>> +
>> +	return count;
>> +}
>> +
>> +static void intel_vgpu_reg_release_opregion(struct intel_vgpu *vgpu,
>> +		struct vfio_region *region)
>> +{
>> +	memunmap(region->data);
>> +}
>> +
>> +static const struct intel_vgpu_regops intel_vgpu_regops_opregion = {
>> +	.rw = intel_vgpu_reg_rw_opregion,
>> +	.release = intel_vgpu_reg_release_opregion, };
>> +
>> +static int intel_vgpu_register_reg(struct intel_vgpu *vgpu,
>> +		unsigned int type, unsigned int subtype,
>> +		const struct intel_vgpu_regops *ops,
>> +		size_t size, u32 flags, void *data) {
>> +	struct vfio_region *region;
>> +
>> +	region = krealloc(vgpu->vdev.region,
>> +			(vgpu->vdev.num_regions + 1) * sizeof(*region),
>> +			GFP_KERNEL);
>> +	if (!region)
>> +		return -ENOMEM;
>> +
>> +	vgpu->vdev.region = region;
>> +	vgpu->vdev.region[vgpu->vdev.num_regions].type = type;
>> +	vgpu->vdev.region[vgpu->vdev.num_regions].subtype = subtype;
>> +	vgpu->vdev.region[vgpu->vdev.num_regions].ops = ops;
>> +	vgpu->vdev.region[vgpu->vdev.num_regions].size = size;
>> +	vgpu->vdev.region[vgpu->vdev.num_regions].flags = flags;
>> +	vgpu->vdev.region[vgpu->vdev.num_regions].data = data;
>> +	vgpu->vdev.num_regions++;
>> +
>> +	return 0;
>> +}
>> +
>> +static int intel_vgpu_reg_init_opregion(struct intel_vgpu *vgpu) {
>> +	unsigned int addr;
>> +	void *base;
>> +	int ret;
>> +
>> +	addr = vgpu->gvt->opregion.opregion_pa;
>> +	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;
>> +	}
>> +
>> +	ret = intel_vgpu_register_reg(vgpu,
>> +			PCI_VENDOR_ID_INTEL |
>VFIO_REGION_TYPE_PCI_VENDOR_TYPE,
>> +			VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION,
>> +			&intel_vgpu_regops_opregion, OPREGION_SIZE,
>> +			VFIO_REGION_INFO_FLAG_READ, base);
>> +	if (ret) {
>> +		memunmap(base);
>> +		return ret;
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>>  static int intel_vgpu_create(struct kobject *kobj, struct mdev_device
>> *mdev)  {
>>  	struct intel_vgpu *vgpu = NULL;
>> @@ -467,6 +555,15 @@ static int intel_vgpu_create(struct kobject *kobj,
>struct mdev_device *mdev)
>>  	vgpu->vdev.mdev = mdev;
>>  	mdev_set_drvdata(mdev, vgpu);
>>
>> +	ret = intel_vgpu_reg_init_opregion(vgpu);
>> +	if (ret) {
>> +		gvt_vgpu_err("create OpRegion failed\n");
>> +		goto out;
>> +	}
>
>Still need to handle error path for created vgpu.
Just checked the code, if initialize the opregion failed we should first release vfio/mdev releated work(maybe call intel_vgpu_release function)  and then destroy the vgpu. Will update in the next version.

>
>> +
>> +	gvt_dbg_core("create OpRegion succeeded for mdev:%s\n",
>> +			dev_name(mdev_dev(mdev)));
>> +
>>  	gvt_dbg_core("intel_vgpu_create succeeded for mdev: %s\n",
>>  		     dev_name(mdev_dev(mdev)));
>>  	ret = 0;
>> diff --git a/drivers/gpu/drm/i915/gvt/opregion.c
>> b/drivers/gpu/drm/i915/gvt/opregion.c
>> index 3117991..5c7496d 100644
>> --- a/drivers/gpu/drm/i915/gvt/opregion.c
>> +++ b/drivers/gpu/drm/i915/gvt/opregion.c
>> @@ -114,6 +114,7 @@ void intel_vgpu_clean_opregion(struct intel_vgpu
>> *vgpu)  int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
>> {
>>  	int ret;
>> +	unsigned long pfn;
>>
>>  	gvt_dbg_core("vgpu%d: init vgpu opregion\n", vgpu->id);
>>
>> @@ -127,7 +128,12 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu,
>u32 gpa)
>>  		ret = map_vgpu_opregion(vgpu, true);
>>  		if (ret)
>>  			return ret;
>> -	}
>> +	} else {
>> +		pfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gpa >>
>PAGE_SHIFT);
>> +		vgpu_opregion(vgpu)->va = memremap(pfn << PAGE_SHIFT,
>> +						INTEL_GVT_OPREGION_SIZE,
>> +						MEMREMAP_WB);
>> +		}
>
>better to use switch for explicit KVM case, and no return check?
Will update and add NULL check.

Thanks for review.
>
>>
>>  	return 0;
>>  }
>> --
>> 2.7.4
>>
>
>--
>Open Source Technology Center, Intel ltd.
>
>$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827

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

* Re: [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g
@ 2017-05-31  6:22       ` Chen, Xiaoguang
  0 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-05-31  6:22 UTC (permalink / raw)
  To: Zhenyu Wang; +Cc: intel-gfx, linux-kernel, kraxel, intel-gvt-dev, Lv, Zhiyuan

Hi 

>-----Original Message-----
>From: intel-gvt-dev [mailto:intel-gvt-dev-bounces@lists.freedesktop.org] On
>Behalf Of Zhenyu Wang
>Sent: Wednesday, May 31, 2017 12:47 PM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
>Cc: Tian, Kevin <kevin.tian@intel.com>; intel-gfx@lists.freedesktop.org; linux-
>kernel@vger.kernel.org; zhenyuw@linux.intel.com; chris@chris-wilson.co.uk;
>alex.williamson@redhat.com; kraxel@redhat.com; Niu, Bing
><bing.niu@intel.com>; intel-gvt-dev@lists.freedesktop.org; Wang, Zhi A
><zhi.a.wang@intel.com>; Lv, Zhiyuan <zhiyuan.lv@intel.com>
>Subject: Re: [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g
>
>On 2017.05.27 16:38:48 +0800, Xiaoguang Chen wrote:
>> OpRegion is needed to support display related operation for intel
>> vgpu.
>>
>> A vfio device region is added to intel vgpu to deliver the host
>> OpRegion information to user space so user space can construct the
>> OpRegion for vgpu.
>>
>> Signed-off-by: Bing Niu <bing.niu@intel.com>
>> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
>> ---
>>  drivers/gpu/drm/i915/gvt/kvmgt.c    | 97
>+++++++++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/i915/gvt/opregion.c |  8 ++-
>>  2 files changed, 104 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
>> b/drivers/gpu/drm/i915/gvt/kvmgt.c
>> index 3c6a02b..389f072 100644
>> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
>> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
>> @@ -53,6 +53,8 @@ static const struct intel_gvt_ops *intel_gvt_ops;
>> #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)
>>
>> +#define OPREGION_SIGNATURE "IntelGraphicsMem"
>> +
>>  struct vfio_region;
>>  struct intel_vgpu_regops {
>>  	size_t (*rw)(struct intel_vgpu *vgpu, char *buf, @@ -436,6 +438,92
>> @@ static void kvmgt_protect_table_del(struct kvmgt_guest_info *info,
>>  	}
>>  }
>>
>> +static size_t intel_vgpu_reg_rw_opregion(struct intel_vgpu *vgpu, char *buf,
>> +		size_t count, loff_t *ppos, bool iswrite) {
>> +	unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) -
>> +			VFIO_PCI_NUM_REGIONS;
>> +	void *base = vgpu->vdev.region[i].data;
>> +	loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
>> +
>> +	if (pos >= vgpu->vdev.region[i].size || iswrite) {
>> +		gvt_vgpu_err("invalid op or offset for Intel vgpu OpRegion\n");
>> +		return -EINVAL;
>> +	}
>> +	count = min(count, (size_t)(vgpu->vdev.region[i].size - pos));
>> +	memcpy(buf, base + pos, count);
>> +
>> +	return count;
>> +}
>> +
>> +static void intel_vgpu_reg_release_opregion(struct intel_vgpu *vgpu,
>> +		struct vfio_region *region)
>> +{
>> +	memunmap(region->data);
>> +}
>> +
>> +static const struct intel_vgpu_regops intel_vgpu_regops_opregion = {
>> +	.rw = intel_vgpu_reg_rw_opregion,
>> +	.release = intel_vgpu_reg_release_opregion, };
>> +
>> +static int intel_vgpu_register_reg(struct intel_vgpu *vgpu,
>> +		unsigned int type, unsigned int subtype,
>> +		const struct intel_vgpu_regops *ops,
>> +		size_t size, u32 flags, void *data) {
>> +	struct vfio_region *region;
>> +
>> +	region = krealloc(vgpu->vdev.region,
>> +			(vgpu->vdev.num_regions + 1) * sizeof(*region),
>> +			GFP_KERNEL);
>> +	if (!region)
>> +		return -ENOMEM;
>> +
>> +	vgpu->vdev.region = region;
>> +	vgpu->vdev.region[vgpu->vdev.num_regions].type = type;
>> +	vgpu->vdev.region[vgpu->vdev.num_regions].subtype = subtype;
>> +	vgpu->vdev.region[vgpu->vdev.num_regions].ops = ops;
>> +	vgpu->vdev.region[vgpu->vdev.num_regions].size = size;
>> +	vgpu->vdev.region[vgpu->vdev.num_regions].flags = flags;
>> +	vgpu->vdev.region[vgpu->vdev.num_regions].data = data;
>> +	vgpu->vdev.num_regions++;
>> +
>> +	return 0;
>> +}
>> +
>> +static int intel_vgpu_reg_init_opregion(struct intel_vgpu *vgpu) {
>> +	unsigned int addr;
>> +	void *base;
>> +	int ret;
>> +
>> +	addr = vgpu->gvt->opregion.opregion_pa;
>> +	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;
>> +	}
>> +
>> +	ret = intel_vgpu_register_reg(vgpu,
>> +			PCI_VENDOR_ID_INTEL |
>VFIO_REGION_TYPE_PCI_VENDOR_TYPE,
>> +			VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION,
>> +			&intel_vgpu_regops_opregion, OPREGION_SIZE,
>> +			VFIO_REGION_INFO_FLAG_READ, base);
>> +	if (ret) {
>> +		memunmap(base);
>> +		return ret;
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>>  static int intel_vgpu_create(struct kobject *kobj, struct mdev_device
>> *mdev)  {
>>  	struct intel_vgpu *vgpu = NULL;
>> @@ -467,6 +555,15 @@ static int intel_vgpu_create(struct kobject *kobj,
>struct mdev_device *mdev)
>>  	vgpu->vdev.mdev = mdev;
>>  	mdev_set_drvdata(mdev, vgpu);
>>
>> +	ret = intel_vgpu_reg_init_opregion(vgpu);
>> +	if (ret) {
>> +		gvt_vgpu_err("create OpRegion failed\n");
>> +		goto out;
>> +	}
>
>Still need to handle error path for created vgpu.
Just checked the code, if initialize the opregion failed we should first release vfio/mdev releated work(maybe call intel_vgpu_release function)  and then destroy the vgpu. Will update in the next version.

>
>> +
>> +	gvt_dbg_core("create OpRegion succeeded for mdev:%s\n",
>> +			dev_name(mdev_dev(mdev)));
>> +
>>  	gvt_dbg_core("intel_vgpu_create succeeded for mdev: %s\n",
>>  		     dev_name(mdev_dev(mdev)));
>>  	ret = 0;
>> diff --git a/drivers/gpu/drm/i915/gvt/opregion.c
>> b/drivers/gpu/drm/i915/gvt/opregion.c
>> index 3117991..5c7496d 100644
>> --- a/drivers/gpu/drm/i915/gvt/opregion.c
>> +++ b/drivers/gpu/drm/i915/gvt/opregion.c
>> @@ -114,6 +114,7 @@ void intel_vgpu_clean_opregion(struct intel_vgpu
>> *vgpu)  int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
>> {
>>  	int ret;
>> +	unsigned long pfn;
>>
>>  	gvt_dbg_core("vgpu%d: init vgpu opregion\n", vgpu->id);
>>
>> @@ -127,7 +128,12 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu,
>u32 gpa)
>>  		ret = map_vgpu_opregion(vgpu, true);
>>  		if (ret)
>>  			return ret;
>> -	}
>> +	} else {
>> +		pfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gpa >>
>PAGE_SHIFT);
>> +		vgpu_opregion(vgpu)->va = memremap(pfn << PAGE_SHIFT,
>> +						INTEL_GVT_OPREGION_SIZE,
>> +						MEMREMAP_WB);
>> +		}
>
>better to use switch for explicit KVM case, and no return check?
Will update and add NULL check.

Thanks for review.
>
>>
>>  	return 0;
>>  }
>> --
>> 2.7.4
>>
>
>--
>Open Source Technology Center, Intel ltd.
>
>$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g
  2017-05-31  6:22       ` Chen, Xiaoguang
@ 2017-05-31  6:30         ` Zhenyu Wang
  -1 siblings, 0 replies; 74+ messages in thread
From: Zhenyu Wang @ 2017-05-31  6:30 UTC (permalink / raw)
  To: Chen, Xiaoguang
  Cc: Tian, Kevin, intel-gfx, linux-kernel, chris, alex.williamson,
	kraxel, Niu, Bing, intel-gvt-dev, Wang, Zhi A, Lv, Zhiyuan

[-- Attachment #1: Type: text/plain, Size: 856 bytes --]

On 2017.05.31 06:22:28 +0000, Chen, Xiaoguang wrote:
> >> @@ -467,6 +555,15 @@ static int intel_vgpu_create(struct kobject *kobj,
> >struct mdev_device *mdev)
> >>  	vgpu->vdev.mdev = mdev;
> >>  	mdev_set_drvdata(mdev, vgpu);
> >>
> >> +	ret = intel_vgpu_reg_init_opregion(vgpu);
> >> +	if (ret) {
> >> +		gvt_vgpu_err("create OpRegion failed\n");
> >> +		goto out;
> >> +	}
> >
> >Still need to handle error path for created vgpu.
> Just checked the code, if initialize the opregion failed we should first release vfio/mdev releated work(maybe call intel_vgpu_release function)  and then destroy the vgpu. Will update in the next version.
> 

Better to init opregion inside of create vgpu and do proper error
handling there too.

-- 
Open Source Technology Center, Intel ltd.

$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

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

* Re: [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g
@ 2017-05-31  6:30         ` Zhenyu Wang
  0 siblings, 0 replies; 74+ messages in thread
From: Zhenyu Wang @ 2017-05-31  6:30 UTC (permalink / raw)
  To: Chen, Xiaoguang
  Cc: Tian, Kevin, intel-gfx, linux-kernel, chris, alex.williamson,
	kraxel, Niu, Bing, intel-gvt-dev, Wang, Zhi A, Lv, Zhiyuan

[-- Attachment #1: Type: text/plain, Size: 856 bytes --]

On 2017.05.31 06:22:28 +0000, Chen, Xiaoguang wrote:
> >> @@ -467,6 +555,15 @@ static int intel_vgpu_create(struct kobject *kobj,
> >struct mdev_device *mdev)
> >>  	vgpu->vdev.mdev = mdev;
> >>  	mdev_set_drvdata(mdev, vgpu);
> >>
> >> +	ret = intel_vgpu_reg_init_opregion(vgpu);
> >> +	if (ret) {
> >> +		gvt_vgpu_err("create OpRegion failed\n");
> >> +		goto out;
> >> +	}
> >
> >Still need to handle error path for created vgpu.
> Just checked the code, if initialize the opregion failed we should first release vfio/mdev releated work(maybe call intel_vgpu_release function)  and then destroy the vgpu. Will update in the next version.
> 

Better to init opregion inside of create vgpu and do proper error
handling there too.

-- 
Open Source Technology Center, Intel ltd.

$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

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

* RE: [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g
  2017-05-31  6:30         ` Zhenyu Wang
@ 2017-05-31  6:44           ` Chen, Xiaoguang
  -1 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-05-31  6:44 UTC (permalink / raw)
  To: Zhenyu Wang
  Cc: Tian, Kevin, intel-gfx, linux-kernel, chris, alex.williamson,
	kraxel, Niu, Bing, intel-gvt-dev, Wang, Zhi A, Lv, Zhiyuan



>-----Original Message-----
>From: Zhenyu Wang [mailto:zhenyuw@linux.intel.com]
>Sent: Wednesday, May 31, 2017 2:30 PM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
>Cc: Tian, Kevin <kevin.tian@intel.com>; intel-gfx@lists.freedesktop.org; linux-
>kernel@vger.kernel.org; chris@chris-wilson.co.uk; alex.williamson@redhat.com;
>kraxel@redhat.com; Niu, Bing <bing.niu@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Lv, Zhiyuan
><zhiyuan.lv@intel.com>
>Subject: Re: [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g
>
>On 2017.05.31 06:22:28 +0000, Chen, Xiaoguang wrote:
>> >> @@ -467,6 +555,15 @@ static int intel_vgpu_create(struct kobject
>> >> *kobj,
>> >struct mdev_device *mdev)
>> >>  	vgpu->vdev.mdev = mdev;
>> >>  	mdev_set_drvdata(mdev, vgpu);
>> >>
>> >> +	ret = intel_vgpu_reg_init_opregion(vgpu);
>> >> +	if (ret) {
>> >> +		gvt_vgpu_err("create OpRegion failed\n");
>> >> +		goto out;
>> >> +	}
>> >
>> >Still need to handle error path for created vgpu.
>> Just checked the code, if initialize the opregion failed we should first release
>vfio/mdev releated work(maybe call intel_vgpu_release function)  and then
>destroy the vgpu. Will update in the next version.
>>
>
>Better to init opregion inside of create vgpu and do proper error handling there
>too.
Then we must add a new entry in intel_gvt_mpt interface something like "create_opregion".

>
>--
>Open Source Technology Center, Intel ltd.
>
>$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827

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

* Re: [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g
@ 2017-05-31  6:44           ` Chen, Xiaoguang
  0 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-05-31  6:44 UTC (permalink / raw)
  To: Zhenyu Wang; +Cc: intel-gfx, linux-kernel, kraxel, intel-gvt-dev, Lv, Zhiyuan



>-----Original Message-----
>From: Zhenyu Wang [mailto:zhenyuw@linux.intel.com]
>Sent: Wednesday, May 31, 2017 2:30 PM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
>Cc: Tian, Kevin <kevin.tian@intel.com>; intel-gfx@lists.freedesktop.org; linux-
>kernel@vger.kernel.org; chris@chris-wilson.co.uk; alex.williamson@redhat.com;
>kraxel@redhat.com; Niu, Bing <bing.niu@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Lv, Zhiyuan
><zhiyuan.lv@intel.com>
>Subject: Re: [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g
>
>On 2017.05.31 06:22:28 +0000, Chen, Xiaoguang wrote:
>> >> @@ -467,6 +555,15 @@ static int intel_vgpu_create(struct kobject
>> >> *kobj,
>> >struct mdev_device *mdev)
>> >>  	vgpu->vdev.mdev = mdev;
>> >>  	mdev_set_drvdata(mdev, vgpu);
>> >>
>> >> +	ret = intel_vgpu_reg_init_opregion(vgpu);
>> >> +	if (ret) {
>> >> +		gvt_vgpu_err("create OpRegion failed\n");
>> >> +		goto out;
>> >> +	}
>> >
>> >Still need to handle error path for created vgpu.
>> Just checked the code, if initialize the opregion failed we should first release
>vfio/mdev releated work(maybe call intel_vgpu_release function)  and then
>destroy the vgpu. Will update in the next version.
>>
>
>Better to init opregion inside of create vgpu and do proper error handling there
>too.
Then we must add a new entry in intel_gvt_mpt interface something like "create_opregion".

>
>--
>Open Source Technology Center, Intel ltd.
>
>$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* RE: [PATCH v6 3/6] drm/i915/gvt: Frame buffer decoder support for GVT-g
  2017-05-31  5:12     ` Zhenyu Wang
@ 2017-05-31  6:46       ` Chen, Xiaoguang
  -1 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-05-31  6:46 UTC (permalink / raw)
  To: Zhenyu Wang
  Cc: alex.williamson, kraxel, chris, intel-gfx, linux-kernel, Lv,
	Zhiyuan, intel-gvt-dev, Wang, Zhi A, Tian, Kevin



>-----Original Message-----
>From: Zhenyu Wang [mailto:zhenyuw@linux.intel.com]
>Sent: Wednesday, May 31, 2017 1:12 PM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
>Cc: alex.williamson@redhat.com; kraxel@redhat.com; chris@chris-wilson.co.uk;
>intel-gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 3/6] drm/i915/gvt: Frame buffer decoder support for GVT-
>g
>
>On 2017.05.27 16:38:49 +0800, Xiaoguang Chen wrote:
>> decode frambuffer attributes of primary, cursor and sprite plane
>>
>> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
>> ---
>>  drivers/gpu/drm/i915/gvt/Makefile     |   3 +-
>>  drivers/gpu/drm/i915/gvt/display.c    |   2 +-
>>  drivers/gpu/drm/i915/gvt/display.h    |   2 +
>>  drivers/gpu/drm/i915/gvt/fb_decoder.c | 479
>> ++++++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/i915/gvt/fb_decoder.h | 166 ++++++++++++
>>  drivers/gpu/drm/i915/gvt/gvt.h        |   1 +
>>  6 files changed, 651 insertions(+), 2 deletions(-)  create mode
>> 100644 drivers/gpu/drm/i915/gvt/fb_decoder.c
>>  create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.h
>>
>> diff --git a/drivers/gpu/drm/i915/gvt/Makefile
>> b/drivers/gpu/drm/i915/gvt/Makefile
>> index b123c20..192ca26 100644
>> --- a/drivers/gpu/drm/i915/gvt/Makefile
>> +++ b/drivers/gpu/drm/i915/gvt/Makefile
>> @@ -1,7 +1,8 @@
>>  GVT_DIR := gvt
>>  GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o
>firmware.o \
>>  	interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \
>> -	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o
>> +	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o \
>> +	fb_decoder.o
>>
>>  ccflags-y				+= -I$(src) -I$(src)/$(GVT_DIR) -Wall
>>  i915-y					+= $(addprefix $(GVT_DIR)/,
>$(GVT_SOURCE))
>> diff --git a/drivers/gpu/drm/i915/gvt/display.c
>> b/drivers/gpu/drm/i915/gvt/display.c
>> index e0261fc..f5f63c5 100644
>> --- a/drivers/gpu/drm/i915/gvt/display.c
>> +++ b/drivers/gpu/drm/i915/gvt/display.c
>> @@ -67,7 +67,7 @@ static int edp_pipe_is_enabled(struct intel_vgpu *vgpu)
>>  	return 1;
>>  }
>>
>> -static int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
>> +int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
>>  {
>>  	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
>>
>> diff --git a/drivers/gpu/drm/i915/gvt/display.h
>> b/drivers/gpu/drm/i915/gvt/display.h
>> index d73de22..b46b868 100644
>> --- a/drivers/gpu/drm/i915/gvt/display.h
>> +++ b/drivers/gpu/drm/i915/gvt/display.h
>> @@ -179,4 +179,6 @@ int intel_vgpu_init_display(struct intel_vgpu
>> *vgpu, u64 resolution);  void intel_vgpu_reset_display(struct
>> intel_vgpu *vgpu);  void intel_vgpu_clean_display(struct intel_vgpu
>> *vgpu);
>>
>> +int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe);
>> +
>>  #endif
>> diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.c
>> b/drivers/gpu/drm/i915/gvt/fb_decoder.c
>> new file mode 100644
>> index 0000000..d4404fd
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.c
>> @@ -0,0 +1,479 @@
>> +/*
>> + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
>> + *
>> + * Permission is hereby granted, free of charge, to any person
>> +obtaining a
>> + * copy of this software and associated documentation files (the
>> +"Software"),
>> + * to deal in the Software without restriction, including without
>> +limitation
>> + * the rights to use, copy, modify, merge, publish, distribute,
>> +sublicense,
>> + * and/or sell copies of the Software, and to permit persons to whom
>> +the
>> + * Software is furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice (including
>> +the next
>> + * paragraph) shall be included in all copies or substantial portions
>> +of the
>> + * Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> +EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> +MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO
>EVENT
>> +SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
>DAMAGES
>> +OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> +ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> +DEALINGS IN THE
>> + * SOFTWARE.
>> + *
>> + * Authors:
>> + *    Kevin Tian <kevin.tian@intel.com>
>> + *
>> + * Contributors:
>> + *    Bing Niu <bing.niu@intel.com>
>> + *    Xu Han <xu.han@intel.com>
>> + *    Ping Gao <ping.a.gao@intel.com>
>> + *    Xiaoguang Chen <xiaoguang.chen@intel.com>
>> + *    Yang Liu <yang2.liu@intel.com>
>> + *
>> + */
>> +
>> +#include <uapi/drm/drm_fourcc.h>
>> +#include "i915_drv.h"
>> +#include "gvt.h"
>> +
>> +/* The below definitions are required by guest. */ // [63:0] x:R:G:B
>> +16:16:16:16 little endian #define DRM_FORMAT_XRGB161616_GVT
>> +fourcc_code('X', 'R', '4', '8') // [63:0] x:B:G:R 16:16:16:16 little
>> +endian #define DRM_FORMAT_XBGR161616_GVT  fourcc_code('X', 'B', '4',
>> +'8')
>> +
>
>Should be added to drm_fourcc?
Will add to drm_fourcc.

>
>> +#define FORMAT_NUM	16
>
>PRIMARY_FORMAT_NUM
>
>> +struct pixel_format {
>> +	int	drm_format;	/* Pixel format in DRM definition */
>> +	int	bpp;		/* Bits per pixel, 0 indicates invalid */
>> +	char *desc;		/* The description */
>> +};
>> +
>> +/* non-supported format has bpp default to 0 */ static struct
>> +pixel_format primary_pixel_formats[FORMAT_NUM] = {
>> +	[0x2] = {DRM_FORMAT_C8, 8, "8-bit Indexed"},
>> +	[0x5] = {DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"},
>> +	[0x6] = {DRM_FORMAT_XRGB8888, 32,
>> +		"32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"},
>> +	[0x8] = {DRM_FORMAT_XBGR2101010, 32,
>> +		"32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"},
>> +	[0xa] = {DRM_FORMAT_XRGB2101010, 32,
>> +		"32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"},
>> +	[0xc] = {DRM_FORMAT_XRGB161616_GVT, 64,
>> +		"64-bit RGBX Floating Point(16:16:16:16 MSB-X:B:G:R)"},
>> +	[0xe] = {DRM_FORMAT_XBGR8888, 32,
>> +		"32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"}, };
>
>might explicitly say this is bdw_pixel_formats?
Good suggestion :)

>
>> +
>> +/* non-supported format has bpp default to 0 */ static struct
>> +pixel_format skl_pixel_formats[] = {
>> +	{DRM_FORMAT_YUYV, 16, "16-bit packed YUYV (8:8:8:8 MSB-
>V:Y2:U:Y1)"},
>> +	{DRM_FORMAT_UYVY, 16, "16-bit packed UYVY (8:8:8:8 MSB-
>Y2:V:Y1:U)"},
>> +	{DRM_FORMAT_YVYU, 16, "16-bit packed YVYU (8:8:8:8 MSB-
>U:Y2:V:Y1)"},
>> +	{DRM_FORMAT_VYUY, 16, "16-bit packed VYUY (8:8:8:8 MSB-
>Y2:U:Y1:V)"},
>> +
>> +	{DRM_FORMAT_C8, 8, "8-bit Indexed"},
>> +	{DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"},
>> +	{DRM_FORMAT_ABGR8888, 32, "32-bit RGBA (8:8:8:8 MSB-A:B:G:R)"},
>> +	{DRM_FORMAT_XBGR8888, 32, "32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"},
>> +
>> +	{DRM_FORMAT_ARGB8888, 32, "32-bit BGRA (8:8:8:8 MSB-A:R:G:B)"},
>> +	{DRM_FORMAT_XRGB8888, 32, "32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"},
>> +	{DRM_FORMAT_XBGR2101010, 32, "32-bit RGBX (2:10:10:10 MSB-
>X:B:G:R)"},
>> +	{DRM_FORMAT_XRGB2101010, 32, "32-bit BGRX (2:10:10:10
>> +MSB-X:R:G:B)"},
>> +
>> +	{DRM_FORMAT_XRGB161616_GVT, 64,
>> +		"64-bit XRGB (16:16:16:16 MSB-X:R:G:B)"},
>> +	{DRM_FORMAT_XBGR161616_GVT, 64,
>> +		"64-bit XBGR (16:16:16:16 MSB-X:B:G:R)"},
>> +
>> +	/* non-supported format has bpp default to 0 */
>> +	{0, 0, NULL},
>> +};
>> +
>> +static int skl_format_to_drm(int format, bool rgb_order, bool alpha,
>> +	int yuv_order)
>> +{
>> +	int skl_pixel_formats_index = 14;
>> +
>> +	switch (format) {
>> +	case PLANE_CTL_FORMAT_INDEXED:
>> +		skl_pixel_formats_index = 4;
>> +		break;
>> +	case PLANE_CTL_FORMAT_RGB_565:
>> +		skl_pixel_formats_index = 5;
>> +		break;
>> +	case PLANE_CTL_FORMAT_XRGB_8888:
>> +		if (rgb_order)
>> +			skl_pixel_formats_index = alpha ? 6 : 7;
>> +		else
>> +			skl_pixel_formats_index = alpha ? 8 : 9;
>> +		break;
>> +	case PLANE_CTL_FORMAT_XRGB_2101010:
>> +		skl_pixel_formats_index = rgb_order ? 10 : 11;
>> +		break;
>> +
>> +	case PLANE_CTL_FORMAT_XRGB_16161616F:
>> +		skl_pixel_formats_index = rgb_order ? 12 : 13;
>> +		break;
>> +
>> +	case PLANE_CTL_FORMAT_YUV422:
>> +		skl_pixel_formats_index = yuv_order >> 16;
>> +		if (skl_pixel_formats_index > 3)
>> +			return -EINVAL;
>> +		break;
>> +
>> +	default:
>> +		break;
>> +	}
>> +
>> +	return skl_pixel_formats_index;
>> +}
>> +
>> +static u32 intel_vgpu_get_stride(struct intel_vgpu *vgpu, int pipe,
>> +	u32 tiled, int stride_mask, int bpp) {
>> +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
>> +
>> +	u32 stride_reg = vgpu_vreg(vgpu, DSPSTRIDE(pipe)) & stride_mask;
>> +	u32 stride = stride_reg;
>> +
>> +	if (IS_SKYLAKE(dev_priv)) {
>> +		switch (tiled) {
>> +		case PLANE_CTL_TILED_LINEAR:
>> +			stride = stride_reg * 64;
>> +			break;
>> +		case PLANE_CTL_TILED_X:
>> +			stride = stride_reg * 512;
>> +			break;
>> +		case PLANE_CTL_TILED_Y:
>> +			stride = stride_reg * 128;
>> +			break;
>> +		case PLANE_CTL_TILED_YF:
>> +			if (bpp == 8)
>> +				stride = stride_reg * 64;
>> +			else if (bpp == 16 || bpp == 32 || bpp == 64)
>> +				stride = stride_reg * 128;
>> +			else
>> +				gvt_dbg_core("skl: unsupported bpp:%d\n", bpp);
>> +			break;
>> +		default:
>> +			gvt_dbg_core("skl: unsupported tile format:%x\n",
>> +				tiled);
>> +		}
>> +	}
>> +
>> +	return stride;
>> +}
>> +
>> +static int intel_vgpu_decode_primary_plane_format(struct intel_vgpu *vgpu,
>> +	int pipe, struct intel_vgpu_primary_plane_format *plane) {
>> +	u32	val, fmt;
>> +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
>> +
>> +	val = vgpu_vreg(vgpu, DSPCNTR(pipe));
>> +	plane->enabled = !!(val & DISPLAY_PLANE_ENABLE);
>> +	if (!plane->enabled)
>> +		return 0;
>> +
>> +	if (IS_SKYLAKE(dev_priv)) {
>> +		plane->tiled = (val & PLANE_CTL_TILED_MASK) >>
>> +		_PLANE_CTL_TILED_SHIFT;
>> +		fmt = skl_format_to_drm(
>> +			val & PLANE_CTL_FORMAT_MASK,
>> +			val & PLANE_CTL_ORDER_RGBX,
>> +			val & PLANE_CTL_ALPHA_MASK,
>> +			val & PLANE_CTL_YUV422_ORDER_MASK);
>> +		plane->bpp = skl_pixel_formats[fmt].bpp;
>> +		plane->drm_format = skl_pixel_formats[fmt].drm_format;
>> +	} else {
>> +		plane->tiled = !!(val & DISPPLANE_TILED);
>> +		fmt = (val & DISPPLANE_PIXFORMAT_MASK) >>
>_PRI_PLANE_FMT_SHIFT;
>> +		plane->bpp = primary_pixel_formats[fmt].bpp;
>> +		plane->drm_format = primary_pixel_formats[fmt].drm_format;
>> +	}
>> +
>> +	if ((IS_SKYLAKE(dev_priv) && !skl_pixel_formats[fmt].bpp)
>> +		|| (!IS_SKYLAKE(dev_priv) &&
>> +			!primary_pixel_formats[fmt].bpp)) {
>
>Just if (!plane->bpp)?
Good suggestion :)

>
>> +		gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt);
>> +		return -EINVAL;
>> +	}
>> +
>> +	plane->hw_format = fmt;
>> +
>> +	plane->base = vgpu_vreg(vgpu, DSPSURF(pipe)) & GTT_PAGE_MASK;
>> +
>> +	plane->stride = intel_vgpu_get_stride(vgpu, pipe, (plane->tiled << 10),
>> +		(IS_SKYLAKE(dev_priv)) ? (_PRI_PLANE_STRIDE_MASK >> 6) :
>> +		_PRI_PLANE_STRIDE_MASK, plane->bpp);
>> +
>> +	plane->width = (vgpu_vreg(vgpu, PIPESRC(pipe)) &
>_PIPE_H_SRCSZ_MASK) >>
>> +		_PIPE_H_SRCSZ_SHIFT;
>> +	plane->width += 1;
>> +	plane->height = (vgpu_vreg(vgpu, PIPESRC(pipe)) &
>> +			_PIPE_V_SRCSZ_MASK) >> _PIPE_V_SRCSZ_SHIFT;
>> +	plane->height += 1;	/* raw height is one minus the real value */
>> +
>> +	val = vgpu_vreg(vgpu, DSPTILEOFF(pipe));
>> +	plane->x_offset = (val & _PRI_PLANE_X_OFF_MASK) >>
>> +		_PRI_PLANE_X_OFF_SHIFT;
>> +	plane->y_offset = (val & _PRI_PLANE_Y_OFF_MASK) >>
>> +		_PRI_PLANE_Y_OFF_SHIFT;
>> +
>> +	return 0;
>> +}
>> +
>> +#define CURSOR_MODE_NUM	(1 << 6)
>
>CURSOR_FORMAT_NUM
>
>> +struct cursor_mode_format {
>> +	int	drm_format;	/* Pixel format in DRM definition */
>> +	u8	bpp;		/* Bits per pixel; 0 indicates invalid */
>> +	u32	width;		/* In pixel */
>> +	u32	height;		/* In lines */
>> +	char	*desc;		/* The description */
>> +};
>> +
>> +/* non-supported format has bpp default to 0 */ static struct
>> +cursor_mode_format cursor_pixel_formats[CURSOR_MODE_NUM] = {
>> +	[0x22]  = {DRM_FORMAT_ARGB8888, 32, 128, 128, "128x128 32bpp
>ARGB"},
>> +	[0x23]  = {DRM_FORMAT_ARGB8888, 32, 256, 256, "256x256 32bpp
>ARGB"},
>> +	[0x27]  = {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"},
>> +	[0x7]  = {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"}, };
>> +
>> +static int intel_vgpu_decode_cursor_plane_format(struct intel_vgpu *vgpu,
>> +	int pipe, struct intel_vgpu_cursor_plane_format *plane) {
>> +	u32 val, mode;
>> +	u32 alpha_plane, alpha_force;
>> +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
>> +
>> +	val = vgpu_vreg(vgpu, CURCNTR(pipe));
>> +	mode = val & CURSOR_MODE;
>> +	plane->enabled = (mode != CURSOR_MODE_DISABLE);
>> +	if (!plane->enabled)
>> +		return 0;
>> +
>> +	if (!cursor_pixel_formats[mode].bpp) {
>> +		gvt_vgpu_err("Non-supported cursor mode (0x%x)\n", mode);
>> +		return -EINVAL;
>> +	}
>> +	plane->mode = mode;
>> +	plane->bpp = cursor_pixel_formats[mode].bpp;
>> +	plane->drm_format = cursor_pixel_formats[mode].drm_format;
>> +	plane->width = cursor_pixel_formats[mode].width;
>> +	plane->height = cursor_pixel_formats[mode].height;
>> +
>> +	alpha_plane = (val & _CURSOR_ALPHA_PLANE_MASK) >>
>> +				_CURSOR_ALPHA_PLANE_SHIFT;
>> +	alpha_force = (val & _CURSOR_ALPHA_FORCE_MASK) >>
>> +				_CURSOR_ALPHA_FORCE_SHIFT;
>> +	if (alpha_plane || alpha_force)
>> +		gvt_dbg_core("alpha_plane=0x%x, alpha_force=0x%x\n",
>> +			alpha_plane, alpha_force);
>> +
>> +	plane->base = vgpu_vreg(vgpu, CURBASE(pipe)) & GTT_PAGE_MASK;
>> +
>> +	val = vgpu_vreg(vgpu, CURPOS(pipe));
>> +	plane->x_pos = (val & _CURSOR_POS_X_MASK) >>
>_CURSOR_POS_X_SHIFT;
>> +	plane->x_sign = (val & _CURSOR_SIGN_X_MASK) >>
>_CURSOR_SIGN_X_SHIFT;
>> +	plane->y_pos = (val & _CURSOR_POS_Y_MASK) >>
>_CURSOR_POS_Y_SHIFT;
>> +	plane->y_sign = (val & _CURSOR_SIGN_Y_MASK) >>
>_CURSOR_SIGN_Y_SHIFT;
>> +
>> +	return 0;
>> +}
>> +
>> +#define FORMAT_NUM_SRRITE	(1 << 3)
>> +
>
>SPRITE_FORMAT_NUM
>
>> +static struct pixel_format sprite_pixel_formats[FORMAT_NUM_SRRITE] = {
>> +	[0x0]  = {DRM_FORMAT_YUV422, 16, "YUV 16-bit 4:2:2 packed"},
>> +	[0x1]  = {DRM_FORMAT_XRGB2101010, 32, "RGB 32-bit 2:10:10:10"},
>> +	[0x2]  = {DRM_FORMAT_XRGB8888, 32, "RGB 32-bit 8:8:8:8"},
>> +	[0x3]  = {DRM_FORMAT_XRGB161616_GVT, 64,
>> +		    "RGB 64-bit 16:16:16:16 Floating Point"},
>> +	[0x4] = {DRM_FORMAT_AYUV, 32,
>> +		"YUV 32-bit 4:4:4 packed (8:8:8:8 MSB-X:Y:U:V)"}, };
>> +
>> +static int intel_vgpu_decode_sprite_plane_format(struct intel_vgpu *vgpu,
>> +	int pipe, struct intel_vgpu_sprite_plane_format *plane) {
>> +	u32 val, fmt;
>> +	u32 width;
>> +	u32 color_order, yuv_order;
>> +	int drm_format;
>> +
>> +	val = vgpu_vreg(vgpu, SPRCTL(pipe));
>> +	plane->enabled = !!(val & SPRITE_ENABLE);
>> +	if (!plane->enabled)
>> +		return 0;
>> +
>> +	plane->tiled = !!(val & SPRITE_TILED);
>> +	color_order = !!(val & SPRITE_RGB_ORDER_RGBX);
>> +	yuv_order = (val & SPRITE_YUV_BYTE_ORDER_MASK) >>
>> +				_SPRITE_YUV_ORDER_SHIFT;
>> +
>> +	fmt = (val & SPRITE_PIXFORMAT_MASK) >> _SPRITE_FMT_SHIFT;
>> +	if (!sprite_pixel_formats[fmt].bpp) {
>> +		gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt);
>> +		return -EINVAL;
>> +	}
>> +	plane->hw_format = fmt;
>> +	plane->bpp = sprite_pixel_formats[fmt].bpp;
>> +	drm_format = sprite_pixel_formats[fmt].drm_format;
>> +
>> +	/* Order of RGB values in an RGBxxx buffer may be ordered RGB or
>> +	 * BGR depending on the state of the color_order field
>> +	 */
>> +	if (!color_order) {
>> +		if (drm_format == DRM_FORMAT_XRGB2101010)
>> +			drm_format = DRM_FORMAT_XBGR2101010;
>> +		else if (drm_format == DRM_FORMAT_XRGB8888)
>> +			drm_format = DRM_FORMAT_XBGR8888;
>> +	}
>> +
>> +	if (drm_format == DRM_FORMAT_YUV422) {
>> +		switch (yuv_order) {
>> +		case	0:
>
>no extra space
>
>> +			drm_format = DRM_FORMAT_YUYV;
>> +			break;
>> +		case	1:
>> +			drm_format = DRM_FORMAT_UYVY;
>> +			break;
>> +		case	2:
>> +			drm_format = DRM_FORMAT_YVYU;
>> +			break;
>> +		case	3:
>> +			drm_format = DRM_FORMAT_VYUY;
>> +			break;
>> +		default:
>> +			/* yuv_order has only 2 bits */
>> +			break;
>> +		}
>> +	}
>> +
>> +	plane->drm_format = drm_format;
>> +
>> +	plane->base = vgpu_vreg(vgpu, SPRSURF(pipe)) & GTT_PAGE_MASK;
>> +	plane->width = vgpu_vreg(vgpu, SPRSTRIDE(pipe)) &
>> +				_SPRITE_STRIDE_MASK;
>> +	plane->width /= plane->bpp / 8;	/* raw width in bytes */
>> +
>> +	val = vgpu_vreg(vgpu, SPRSIZE(pipe));
>> +	plane->height = (val & _SPRITE_SIZE_HEIGHT_MASK) >>
>> +		_SPRITE_SIZE_HEIGHT_SHIFT;
>> +	width = (val & _SPRITE_SIZE_WIDTH_MASK) >>
>_SPRITE_SIZE_WIDTH_SHIFT;
>> +	plane->height += 1;	/* raw height is one minus the real value */
>> +	width += 1;		/* raw width is one minus the real value */
>> +	if (plane->width != width)
>> +		gvt_dbg_core("sprite_plane: plane->width=%d, width=%d\n",
>> +			plane->width, width);
>
>should report error?
OK.

>
>> +static int intel_vgpu_decode_fb_format(struct intel_gvt *gvt, int id,
>> +	struct intel_vgpu_fb_format *fb)
>> +{
>> +	int i;
>> +	struct intel_vgpu *vgpu = NULL;
>> +	int ret = 0;
>> +	struct drm_i915_private *dev_priv = gvt->dev_priv;
>> +
>> +	if (!fb)
>> +		return -EINVAL;
>> +
>> +	/* TODO: use fine-grained refcnt later */
>> +	mutex_lock(&gvt->lock);
>> +
>> +	for_each_active_vgpu(gvt, vgpu, i)
>> +		if (vgpu->id == id)
>> +			break;
>> +
>> +	if (!vgpu) {
>> +		gvt_vgpu_err("Invalid vgpu ID (%d)\n", id);
>> +		mutex_unlock(&gvt->lock);
>> +		return -ENODEV;
>> +	}
>> +
>> +	for (i = 0; i < I915_MAX_PIPES; i++) {
>> +		struct intel_vgpu_pipe_format *pipe = &fb->pipes[i];
>> +		u32 ddi_func_ctl = vgpu_vreg(vgpu, TRANS_DDI_FUNC_CTL(i));
>> +
>> +		if (!(ddi_func_ctl & TRANS_DDI_FUNC_ENABLE)) {
>> +			pipe->ddi_port = DDI_PORT_NONE;
>> +		} else {
>> +			u32 port = (ddi_func_ctl & TRANS_DDI_PORT_MASK) >>
>> +						TRANS_DDI_PORT_SHIFT;
>> +			if (port <= DDI_PORT_E)
>> +				pipe->ddi_port = port;
>> +			else
>> +				pipe->ddi_port = DDI_PORT_NONE;
>> +		}
>> +
>> +		ret |= intel_vgpu_decode_primary_plane_format(vgpu,
>> +			i, &pipe->primary);
>> +		ret |= intel_vgpu_decode_sprite_plane_format(vgpu,
>> +			i, &pipe->sprite);
>> +		ret |= intel_vgpu_decode_cursor_plane_format(vgpu,
>> +			i, &pipe->cursor);
>> +
>> +		if (ret) {
>> +			gvt_vgpu_err("Decode format error for pipe(%d)\n", i);
>> +			ret = -EINVAL;
>> +			break;
>> +		}
>> +	}
>> +
>> +	mutex_unlock(&gvt->lock);
>> +
>> +	return ret;
>> +}
>> +
>> +/**
>> + * intel_vgpu_decode_plane - Decode plane based on plane id
>> + * @dev: drm device
>> + * @vgpu: input vgpu
>> + * This function is called for decoding plane
>> + *
>> + * Returns:
>> + * pipe on success, NULL if failed.
>> + */
>> +struct intel_vgpu_pipe_format *intel_vgpu_decode_plane(struct drm_device
>*dev,
>> +		struct intel_vgpu *vgpu)
>> +{
>> +	struct drm_i915_private *dev_priv = dev->dev_private;
>> +	struct intel_vgpu_fb_format fb;
>> +	struct intel_vgpu_pipe_format *pipe;
>> +	int i;
>> +
>> +	if (intel_vgpu_decode_fb_format(dev_priv->gvt, vgpu->id, &fb))
>> +		return NULL;
>> +
>> +	for (i = 0; i < I915_MAX_PIPES; i++)
>> +		if (pipe_is_enabled(vgpu, i))
>> +			break;
>> +	if (i >= I915_MAX_PIPES) {
>> +		gvt_dbg_core("No enabled pipes\n");
>> +		return NULL;
>> +	}
>
>Looks this check should be moved in above decode_fb_format function which
>doesn't check if pipe is actually enabled.
Good suggestion :)

>
>> +	pipe = &fb.pipes[i];
>> +
>> +	if (!pipe || !pipe->primary.enabled) {
>> +		gvt_dbg_core("Invalid pipe_id :%d\n", i);
>> +		return NULL;
>> +	}
>
>And this function is to find primary plane actually? Should name it like
>intel_vgpu_decode_primary_plane().
Not exactly. This function will decode plane based on the input plane id in our case: primary plane and cursor plane.

>
>> +
>> +	return pipe;
>> +}
>> +
>> diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.h
>> b/drivers/gpu/drm/i915/gvt/fb_decoder.h
>> new file mode 100644
>> index 0000000..04300af
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.h
>> +
>> +struct intel_vgpu_pipe_format {
>> +	struct intel_vgpu_primary_plane_format	primary;
>> +	struct intel_vgpu_sprite_plane_format	sprite;
>> +	struct intel_vgpu_cursor_plane_format	cursor;
>> +	enum DDI_PORT ddi_port;  /* the DDI port that pipe is connected to
>> +*/ };
>> +
>> +struct intel_vgpu_fb_format {
>> +	struct intel_vgpu_pipe_format	pipes[4];
>> +};
>
>Should use MAX_PIPE definition.
>
>--
>Open Source Technology Center, Intel ltd.
>
>$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827

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

* Re: [PATCH v6 3/6] drm/i915/gvt: Frame buffer decoder support for GVT-g
@ 2017-05-31  6:46       ` Chen, Xiaoguang
  0 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-05-31  6:46 UTC (permalink / raw)
  To: Zhenyu Wang; +Cc: intel-gfx, linux-kernel, kraxel, intel-gvt-dev, Lv, Zhiyuan



>-----Original Message-----
>From: Zhenyu Wang [mailto:zhenyuw@linux.intel.com]
>Sent: Wednesday, May 31, 2017 1:12 PM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
>Cc: alex.williamson@redhat.com; kraxel@redhat.com; chris@chris-wilson.co.uk;
>intel-gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 3/6] drm/i915/gvt: Frame buffer decoder support for GVT-
>g
>
>On 2017.05.27 16:38:49 +0800, Xiaoguang Chen wrote:
>> decode frambuffer attributes of primary, cursor and sprite plane
>>
>> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
>> ---
>>  drivers/gpu/drm/i915/gvt/Makefile     |   3 +-
>>  drivers/gpu/drm/i915/gvt/display.c    |   2 +-
>>  drivers/gpu/drm/i915/gvt/display.h    |   2 +
>>  drivers/gpu/drm/i915/gvt/fb_decoder.c | 479
>> ++++++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/i915/gvt/fb_decoder.h | 166 ++++++++++++
>>  drivers/gpu/drm/i915/gvt/gvt.h        |   1 +
>>  6 files changed, 651 insertions(+), 2 deletions(-)  create mode
>> 100644 drivers/gpu/drm/i915/gvt/fb_decoder.c
>>  create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.h
>>
>> diff --git a/drivers/gpu/drm/i915/gvt/Makefile
>> b/drivers/gpu/drm/i915/gvt/Makefile
>> index b123c20..192ca26 100644
>> --- a/drivers/gpu/drm/i915/gvt/Makefile
>> +++ b/drivers/gpu/drm/i915/gvt/Makefile
>> @@ -1,7 +1,8 @@
>>  GVT_DIR := gvt
>>  GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o
>firmware.o \
>>  	interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \
>> -	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o
>> +	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o \
>> +	fb_decoder.o
>>
>>  ccflags-y				+= -I$(src) -I$(src)/$(GVT_DIR) -Wall
>>  i915-y					+= $(addprefix $(GVT_DIR)/,
>$(GVT_SOURCE))
>> diff --git a/drivers/gpu/drm/i915/gvt/display.c
>> b/drivers/gpu/drm/i915/gvt/display.c
>> index e0261fc..f5f63c5 100644
>> --- a/drivers/gpu/drm/i915/gvt/display.c
>> +++ b/drivers/gpu/drm/i915/gvt/display.c
>> @@ -67,7 +67,7 @@ static int edp_pipe_is_enabled(struct intel_vgpu *vgpu)
>>  	return 1;
>>  }
>>
>> -static int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
>> +int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
>>  {
>>  	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
>>
>> diff --git a/drivers/gpu/drm/i915/gvt/display.h
>> b/drivers/gpu/drm/i915/gvt/display.h
>> index d73de22..b46b868 100644
>> --- a/drivers/gpu/drm/i915/gvt/display.h
>> +++ b/drivers/gpu/drm/i915/gvt/display.h
>> @@ -179,4 +179,6 @@ int intel_vgpu_init_display(struct intel_vgpu
>> *vgpu, u64 resolution);  void intel_vgpu_reset_display(struct
>> intel_vgpu *vgpu);  void intel_vgpu_clean_display(struct intel_vgpu
>> *vgpu);
>>
>> +int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe);
>> +
>>  #endif
>> diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.c
>> b/drivers/gpu/drm/i915/gvt/fb_decoder.c
>> new file mode 100644
>> index 0000000..d4404fd
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.c
>> @@ -0,0 +1,479 @@
>> +/*
>> + * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
>> + *
>> + * Permission is hereby granted, free of charge, to any person
>> +obtaining a
>> + * copy of this software and associated documentation files (the
>> +"Software"),
>> + * to deal in the Software without restriction, including without
>> +limitation
>> + * the rights to use, copy, modify, merge, publish, distribute,
>> +sublicense,
>> + * and/or sell copies of the Software, and to permit persons to whom
>> +the
>> + * Software is furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice (including
>> +the next
>> + * paragraph) shall be included in all copies or substantial portions
>> +of the
>> + * Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> +EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> +MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO
>EVENT
>> +SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
>DAMAGES
>> +OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> +ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> +DEALINGS IN THE
>> + * SOFTWARE.
>> + *
>> + * Authors:
>> + *    Kevin Tian <kevin.tian@intel.com>
>> + *
>> + * Contributors:
>> + *    Bing Niu <bing.niu@intel.com>
>> + *    Xu Han <xu.han@intel.com>
>> + *    Ping Gao <ping.a.gao@intel.com>
>> + *    Xiaoguang Chen <xiaoguang.chen@intel.com>
>> + *    Yang Liu <yang2.liu@intel.com>
>> + *
>> + */
>> +
>> +#include <uapi/drm/drm_fourcc.h>
>> +#include "i915_drv.h"
>> +#include "gvt.h"
>> +
>> +/* The below definitions are required by guest. */ // [63:0] x:R:G:B
>> +16:16:16:16 little endian #define DRM_FORMAT_XRGB161616_GVT
>> +fourcc_code('X', 'R', '4', '8') // [63:0] x:B:G:R 16:16:16:16 little
>> +endian #define DRM_FORMAT_XBGR161616_GVT  fourcc_code('X', 'B', '4',
>> +'8')
>> +
>
>Should be added to drm_fourcc?
Will add to drm_fourcc.

>
>> +#define FORMAT_NUM	16
>
>PRIMARY_FORMAT_NUM
>
>> +struct pixel_format {
>> +	int	drm_format;	/* Pixel format in DRM definition */
>> +	int	bpp;		/* Bits per pixel, 0 indicates invalid */
>> +	char *desc;		/* The description */
>> +};
>> +
>> +/* non-supported format has bpp default to 0 */ static struct
>> +pixel_format primary_pixel_formats[FORMAT_NUM] = {
>> +	[0x2] = {DRM_FORMAT_C8, 8, "8-bit Indexed"},
>> +	[0x5] = {DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"},
>> +	[0x6] = {DRM_FORMAT_XRGB8888, 32,
>> +		"32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"},
>> +	[0x8] = {DRM_FORMAT_XBGR2101010, 32,
>> +		"32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"},
>> +	[0xa] = {DRM_FORMAT_XRGB2101010, 32,
>> +		"32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"},
>> +	[0xc] = {DRM_FORMAT_XRGB161616_GVT, 64,
>> +		"64-bit RGBX Floating Point(16:16:16:16 MSB-X:B:G:R)"},
>> +	[0xe] = {DRM_FORMAT_XBGR8888, 32,
>> +		"32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"}, };
>
>might explicitly say this is bdw_pixel_formats?
Good suggestion :)

>
>> +
>> +/* non-supported format has bpp default to 0 */ static struct
>> +pixel_format skl_pixel_formats[] = {
>> +	{DRM_FORMAT_YUYV, 16, "16-bit packed YUYV (8:8:8:8 MSB-
>V:Y2:U:Y1)"},
>> +	{DRM_FORMAT_UYVY, 16, "16-bit packed UYVY (8:8:8:8 MSB-
>Y2:V:Y1:U)"},
>> +	{DRM_FORMAT_YVYU, 16, "16-bit packed YVYU (8:8:8:8 MSB-
>U:Y2:V:Y1)"},
>> +	{DRM_FORMAT_VYUY, 16, "16-bit packed VYUY (8:8:8:8 MSB-
>Y2:U:Y1:V)"},
>> +
>> +	{DRM_FORMAT_C8, 8, "8-bit Indexed"},
>> +	{DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"},
>> +	{DRM_FORMAT_ABGR8888, 32, "32-bit RGBA (8:8:8:8 MSB-A:B:G:R)"},
>> +	{DRM_FORMAT_XBGR8888, 32, "32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"},
>> +
>> +	{DRM_FORMAT_ARGB8888, 32, "32-bit BGRA (8:8:8:8 MSB-A:R:G:B)"},
>> +	{DRM_FORMAT_XRGB8888, 32, "32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"},
>> +	{DRM_FORMAT_XBGR2101010, 32, "32-bit RGBX (2:10:10:10 MSB-
>X:B:G:R)"},
>> +	{DRM_FORMAT_XRGB2101010, 32, "32-bit BGRX (2:10:10:10
>> +MSB-X:R:G:B)"},
>> +
>> +	{DRM_FORMAT_XRGB161616_GVT, 64,
>> +		"64-bit XRGB (16:16:16:16 MSB-X:R:G:B)"},
>> +	{DRM_FORMAT_XBGR161616_GVT, 64,
>> +		"64-bit XBGR (16:16:16:16 MSB-X:B:G:R)"},
>> +
>> +	/* non-supported format has bpp default to 0 */
>> +	{0, 0, NULL},
>> +};
>> +
>> +static int skl_format_to_drm(int format, bool rgb_order, bool alpha,
>> +	int yuv_order)
>> +{
>> +	int skl_pixel_formats_index = 14;
>> +
>> +	switch (format) {
>> +	case PLANE_CTL_FORMAT_INDEXED:
>> +		skl_pixel_formats_index = 4;
>> +		break;
>> +	case PLANE_CTL_FORMAT_RGB_565:
>> +		skl_pixel_formats_index = 5;
>> +		break;
>> +	case PLANE_CTL_FORMAT_XRGB_8888:
>> +		if (rgb_order)
>> +			skl_pixel_formats_index = alpha ? 6 : 7;
>> +		else
>> +			skl_pixel_formats_index = alpha ? 8 : 9;
>> +		break;
>> +	case PLANE_CTL_FORMAT_XRGB_2101010:
>> +		skl_pixel_formats_index = rgb_order ? 10 : 11;
>> +		break;
>> +
>> +	case PLANE_CTL_FORMAT_XRGB_16161616F:
>> +		skl_pixel_formats_index = rgb_order ? 12 : 13;
>> +		break;
>> +
>> +	case PLANE_CTL_FORMAT_YUV422:
>> +		skl_pixel_formats_index = yuv_order >> 16;
>> +		if (skl_pixel_formats_index > 3)
>> +			return -EINVAL;
>> +		break;
>> +
>> +	default:
>> +		break;
>> +	}
>> +
>> +	return skl_pixel_formats_index;
>> +}
>> +
>> +static u32 intel_vgpu_get_stride(struct intel_vgpu *vgpu, int pipe,
>> +	u32 tiled, int stride_mask, int bpp) {
>> +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
>> +
>> +	u32 stride_reg = vgpu_vreg(vgpu, DSPSTRIDE(pipe)) & stride_mask;
>> +	u32 stride = stride_reg;
>> +
>> +	if (IS_SKYLAKE(dev_priv)) {
>> +		switch (tiled) {
>> +		case PLANE_CTL_TILED_LINEAR:
>> +			stride = stride_reg * 64;
>> +			break;
>> +		case PLANE_CTL_TILED_X:
>> +			stride = stride_reg * 512;
>> +			break;
>> +		case PLANE_CTL_TILED_Y:
>> +			stride = stride_reg * 128;
>> +			break;
>> +		case PLANE_CTL_TILED_YF:
>> +			if (bpp == 8)
>> +				stride = stride_reg * 64;
>> +			else if (bpp == 16 || bpp == 32 || bpp == 64)
>> +				stride = stride_reg * 128;
>> +			else
>> +				gvt_dbg_core("skl: unsupported bpp:%d\n", bpp);
>> +			break;
>> +		default:
>> +			gvt_dbg_core("skl: unsupported tile format:%x\n",
>> +				tiled);
>> +		}
>> +	}
>> +
>> +	return stride;
>> +}
>> +
>> +static int intel_vgpu_decode_primary_plane_format(struct intel_vgpu *vgpu,
>> +	int pipe, struct intel_vgpu_primary_plane_format *plane) {
>> +	u32	val, fmt;
>> +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
>> +
>> +	val = vgpu_vreg(vgpu, DSPCNTR(pipe));
>> +	plane->enabled = !!(val & DISPLAY_PLANE_ENABLE);
>> +	if (!plane->enabled)
>> +		return 0;
>> +
>> +	if (IS_SKYLAKE(dev_priv)) {
>> +		plane->tiled = (val & PLANE_CTL_TILED_MASK) >>
>> +		_PLANE_CTL_TILED_SHIFT;
>> +		fmt = skl_format_to_drm(
>> +			val & PLANE_CTL_FORMAT_MASK,
>> +			val & PLANE_CTL_ORDER_RGBX,
>> +			val & PLANE_CTL_ALPHA_MASK,
>> +			val & PLANE_CTL_YUV422_ORDER_MASK);
>> +		plane->bpp = skl_pixel_formats[fmt].bpp;
>> +		plane->drm_format = skl_pixel_formats[fmt].drm_format;
>> +	} else {
>> +		plane->tiled = !!(val & DISPPLANE_TILED);
>> +		fmt = (val & DISPPLANE_PIXFORMAT_MASK) >>
>_PRI_PLANE_FMT_SHIFT;
>> +		plane->bpp = primary_pixel_formats[fmt].bpp;
>> +		plane->drm_format = primary_pixel_formats[fmt].drm_format;
>> +	}
>> +
>> +	if ((IS_SKYLAKE(dev_priv) && !skl_pixel_formats[fmt].bpp)
>> +		|| (!IS_SKYLAKE(dev_priv) &&
>> +			!primary_pixel_formats[fmt].bpp)) {
>
>Just if (!plane->bpp)?
Good suggestion :)

>
>> +		gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt);
>> +		return -EINVAL;
>> +	}
>> +
>> +	plane->hw_format = fmt;
>> +
>> +	plane->base = vgpu_vreg(vgpu, DSPSURF(pipe)) & GTT_PAGE_MASK;
>> +
>> +	plane->stride = intel_vgpu_get_stride(vgpu, pipe, (plane->tiled << 10),
>> +		(IS_SKYLAKE(dev_priv)) ? (_PRI_PLANE_STRIDE_MASK >> 6) :
>> +		_PRI_PLANE_STRIDE_MASK, plane->bpp);
>> +
>> +	plane->width = (vgpu_vreg(vgpu, PIPESRC(pipe)) &
>_PIPE_H_SRCSZ_MASK) >>
>> +		_PIPE_H_SRCSZ_SHIFT;
>> +	plane->width += 1;
>> +	plane->height = (vgpu_vreg(vgpu, PIPESRC(pipe)) &
>> +			_PIPE_V_SRCSZ_MASK) >> _PIPE_V_SRCSZ_SHIFT;
>> +	plane->height += 1;	/* raw height is one minus the real value */
>> +
>> +	val = vgpu_vreg(vgpu, DSPTILEOFF(pipe));
>> +	plane->x_offset = (val & _PRI_PLANE_X_OFF_MASK) >>
>> +		_PRI_PLANE_X_OFF_SHIFT;
>> +	plane->y_offset = (val & _PRI_PLANE_Y_OFF_MASK) >>
>> +		_PRI_PLANE_Y_OFF_SHIFT;
>> +
>> +	return 0;
>> +}
>> +
>> +#define CURSOR_MODE_NUM	(1 << 6)
>
>CURSOR_FORMAT_NUM
>
>> +struct cursor_mode_format {
>> +	int	drm_format;	/* Pixel format in DRM definition */
>> +	u8	bpp;		/* Bits per pixel; 0 indicates invalid */
>> +	u32	width;		/* In pixel */
>> +	u32	height;		/* In lines */
>> +	char	*desc;		/* The description */
>> +};
>> +
>> +/* non-supported format has bpp default to 0 */ static struct
>> +cursor_mode_format cursor_pixel_formats[CURSOR_MODE_NUM] = {
>> +	[0x22]  = {DRM_FORMAT_ARGB8888, 32, 128, 128, "128x128 32bpp
>ARGB"},
>> +	[0x23]  = {DRM_FORMAT_ARGB8888, 32, 256, 256, "256x256 32bpp
>ARGB"},
>> +	[0x27]  = {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"},
>> +	[0x7]  = {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"}, };
>> +
>> +static int intel_vgpu_decode_cursor_plane_format(struct intel_vgpu *vgpu,
>> +	int pipe, struct intel_vgpu_cursor_plane_format *plane) {
>> +	u32 val, mode;
>> +	u32 alpha_plane, alpha_force;
>> +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
>> +
>> +	val = vgpu_vreg(vgpu, CURCNTR(pipe));
>> +	mode = val & CURSOR_MODE;
>> +	plane->enabled = (mode != CURSOR_MODE_DISABLE);
>> +	if (!plane->enabled)
>> +		return 0;
>> +
>> +	if (!cursor_pixel_formats[mode].bpp) {
>> +		gvt_vgpu_err("Non-supported cursor mode (0x%x)\n", mode);
>> +		return -EINVAL;
>> +	}
>> +	plane->mode = mode;
>> +	plane->bpp = cursor_pixel_formats[mode].bpp;
>> +	plane->drm_format = cursor_pixel_formats[mode].drm_format;
>> +	plane->width = cursor_pixel_formats[mode].width;
>> +	plane->height = cursor_pixel_formats[mode].height;
>> +
>> +	alpha_plane = (val & _CURSOR_ALPHA_PLANE_MASK) >>
>> +				_CURSOR_ALPHA_PLANE_SHIFT;
>> +	alpha_force = (val & _CURSOR_ALPHA_FORCE_MASK) >>
>> +				_CURSOR_ALPHA_FORCE_SHIFT;
>> +	if (alpha_plane || alpha_force)
>> +		gvt_dbg_core("alpha_plane=0x%x, alpha_force=0x%x\n",
>> +			alpha_plane, alpha_force);
>> +
>> +	plane->base = vgpu_vreg(vgpu, CURBASE(pipe)) & GTT_PAGE_MASK;
>> +
>> +	val = vgpu_vreg(vgpu, CURPOS(pipe));
>> +	plane->x_pos = (val & _CURSOR_POS_X_MASK) >>
>_CURSOR_POS_X_SHIFT;
>> +	plane->x_sign = (val & _CURSOR_SIGN_X_MASK) >>
>_CURSOR_SIGN_X_SHIFT;
>> +	plane->y_pos = (val & _CURSOR_POS_Y_MASK) >>
>_CURSOR_POS_Y_SHIFT;
>> +	plane->y_sign = (val & _CURSOR_SIGN_Y_MASK) >>
>_CURSOR_SIGN_Y_SHIFT;
>> +
>> +	return 0;
>> +}
>> +
>> +#define FORMAT_NUM_SRRITE	(1 << 3)
>> +
>
>SPRITE_FORMAT_NUM
>
>> +static struct pixel_format sprite_pixel_formats[FORMAT_NUM_SRRITE] = {
>> +	[0x0]  = {DRM_FORMAT_YUV422, 16, "YUV 16-bit 4:2:2 packed"},
>> +	[0x1]  = {DRM_FORMAT_XRGB2101010, 32, "RGB 32-bit 2:10:10:10"},
>> +	[0x2]  = {DRM_FORMAT_XRGB8888, 32, "RGB 32-bit 8:8:8:8"},
>> +	[0x3]  = {DRM_FORMAT_XRGB161616_GVT, 64,
>> +		    "RGB 64-bit 16:16:16:16 Floating Point"},
>> +	[0x4] = {DRM_FORMAT_AYUV, 32,
>> +		"YUV 32-bit 4:4:4 packed (8:8:8:8 MSB-X:Y:U:V)"}, };
>> +
>> +static int intel_vgpu_decode_sprite_plane_format(struct intel_vgpu *vgpu,
>> +	int pipe, struct intel_vgpu_sprite_plane_format *plane) {
>> +	u32 val, fmt;
>> +	u32 width;
>> +	u32 color_order, yuv_order;
>> +	int drm_format;
>> +
>> +	val = vgpu_vreg(vgpu, SPRCTL(pipe));
>> +	plane->enabled = !!(val & SPRITE_ENABLE);
>> +	if (!plane->enabled)
>> +		return 0;
>> +
>> +	plane->tiled = !!(val & SPRITE_TILED);
>> +	color_order = !!(val & SPRITE_RGB_ORDER_RGBX);
>> +	yuv_order = (val & SPRITE_YUV_BYTE_ORDER_MASK) >>
>> +				_SPRITE_YUV_ORDER_SHIFT;
>> +
>> +	fmt = (val & SPRITE_PIXFORMAT_MASK) >> _SPRITE_FMT_SHIFT;
>> +	if (!sprite_pixel_formats[fmt].bpp) {
>> +		gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt);
>> +		return -EINVAL;
>> +	}
>> +	plane->hw_format = fmt;
>> +	plane->bpp = sprite_pixel_formats[fmt].bpp;
>> +	drm_format = sprite_pixel_formats[fmt].drm_format;
>> +
>> +	/* Order of RGB values in an RGBxxx buffer may be ordered RGB or
>> +	 * BGR depending on the state of the color_order field
>> +	 */
>> +	if (!color_order) {
>> +		if (drm_format == DRM_FORMAT_XRGB2101010)
>> +			drm_format = DRM_FORMAT_XBGR2101010;
>> +		else if (drm_format == DRM_FORMAT_XRGB8888)
>> +			drm_format = DRM_FORMAT_XBGR8888;
>> +	}
>> +
>> +	if (drm_format == DRM_FORMAT_YUV422) {
>> +		switch (yuv_order) {
>> +		case	0:
>
>no extra space
>
>> +			drm_format = DRM_FORMAT_YUYV;
>> +			break;
>> +		case	1:
>> +			drm_format = DRM_FORMAT_UYVY;
>> +			break;
>> +		case	2:
>> +			drm_format = DRM_FORMAT_YVYU;
>> +			break;
>> +		case	3:
>> +			drm_format = DRM_FORMAT_VYUY;
>> +			break;
>> +		default:
>> +			/* yuv_order has only 2 bits */
>> +			break;
>> +		}
>> +	}
>> +
>> +	plane->drm_format = drm_format;
>> +
>> +	plane->base = vgpu_vreg(vgpu, SPRSURF(pipe)) & GTT_PAGE_MASK;
>> +	plane->width = vgpu_vreg(vgpu, SPRSTRIDE(pipe)) &
>> +				_SPRITE_STRIDE_MASK;
>> +	plane->width /= plane->bpp / 8;	/* raw width in bytes */
>> +
>> +	val = vgpu_vreg(vgpu, SPRSIZE(pipe));
>> +	plane->height = (val & _SPRITE_SIZE_HEIGHT_MASK) >>
>> +		_SPRITE_SIZE_HEIGHT_SHIFT;
>> +	width = (val & _SPRITE_SIZE_WIDTH_MASK) >>
>_SPRITE_SIZE_WIDTH_SHIFT;
>> +	plane->height += 1;	/* raw height is one minus the real value */
>> +	width += 1;		/* raw width is one minus the real value */
>> +	if (plane->width != width)
>> +		gvt_dbg_core("sprite_plane: plane->width=%d, width=%d\n",
>> +			plane->width, width);
>
>should report error?
OK.

>
>> +static int intel_vgpu_decode_fb_format(struct intel_gvt *gvt, int id,
>> +	struct intel_vgpu_fb_format *fb)
>> +{
>> +	int i;
>> +	struct intel_vgpu *vgpu = NULL;
>> +	int ret = 0;
>> +	struct drm_i915_private *dev_priv = gvt->dev_priv;
>> +
>> +	if (!fb)
>> +		return -EINVAL;
>> +
>> +	/* TODO: use fine-grained refcnt later */
>> +	mutex_lock(&gvt->lock);
>> +
>> +	for_each_active_vgpu(gvt, vgpu, i)
>> +		if (vgpu->id == id)
>> +			break;
>> +
>> +	if (!vgpu) {
>> +		gvt_vgpu_err("Invalid vgpu ID (%d)\n", id);
>> +		mutex_unlock(&gvt->lock);
>> +		return -ENODEV;
>> +	}
>> +
>> +	for (i = 0; i < I915_MAX_PIPES; i++) {
>> +		struct intel_vgpu_pipe_format *pipe = &fb->pipes[i];
>> +		u32 ddi_func_ctl = vgpu_vreg(vgpu, TRANS_DDI_FUNC_CTL(i));
>> +
>> +		if (!(ddi_func_ctl & TRANS_DDI_FUNC_ENABLE)) {
>> +			pipe->ddi_port = DDI_PORT_NONE;
>> +		} else {
>> +			u32 port = (ddi_func_ctl & TRANS_DDI_PORT_MASK) >>
>> +						TRANS_DDI_PORT_SHIFT;
>> +			if (port <= DDI_PORT_E)
>> +				pipe->ddi_port = port;
>> +			else
>> +				pipe->ddi_port = DDI_PORT_NONE;
>> +		}
>> +
>> +		ret |= intel_vgpu_decode_primary_plane_format(vgpu,
>> +			i, &pipe->primary);
>> +		ret |= intel_vgpu_decode_sprite_plane_format(vgpu,
>> +			i, &pipe->sprite);
>> +		ret |= intel_vgpu_decode_cursor_plane_format(vgpu,
>> +			i, &pipe->cursor);
>> +
>> +		if (ret) {
>> +			gvt_vgpu_err("Decode format error for pipe(%d)\n", i);
>> +			ret = -EINVAL;
>> +			break;
>> +		}
>> +	}
>> +
>> +	mutex_unlock(&gvt->lock);
>> +
>> +	return ret;
>> +}
>> +
>> +/**
>> + * intel_vgpu_decode_plane - Decode plane based on plane id
>> + * @dev: drm device
>> + * @vgpu: input vgpu
>> + * This function is called for decoding plane
>> + *
>> + * Returns:
>> + * pipe on success, NULL if failed.
>> + */
>> +struct intel_vgpu_pipe_format *intel_vgpu_decode_plane(struct drm_device
>*dev,
>> +		struct intel_vgpu *vgpu)
>> +{
>> +	struct drm_i915_private *dev_priv = dev->dev_private;
>> +	struct intel_vgpu_fb_format fb;
>> +	struct intel_vgpu_pipe_format *pipe;
>> +	int i;
>> +
>> +	if (intel_vgpu_decode_fb_format(dev_priv->gvt, vgpu->id, &fb))
>> +		return NULL;
>> +
>> +	for (i = 0; i < I915_MAX_PIPES; i++)
>> +		if (pipe_is_enabled(vgpu, i))
>> +			break;
>> +	if (i >= I915_MAX_PIPES) {
>> +		gvt_dbg_core("No enabled pipes\n");
>> +		return NULL;
>> +	}
>
>Looks this check should be moved in above decode_fb_format function which
>doesn't check if pipe is actually enabled.
Good suggestion :)

>
>> +	pipe = &fb.pipes[i];
>> +
>> +	if (!pipe || !pipe->primary.enabled) {
>> +		gvt_dbg_core("Invalid pipe_id :%d\n", i);
>> +		return NULL;
>> +	}
>
>And this function is to find primary plane actually? Should name it like
>intel_vgpu_decode_primary_plane().
Not exactly. This function will decode plane based on the input plane id in our case: primary plane and cursor plane.

>
>> +
>> +	return pipe;
>> +}
>> +
>> diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.h
>> b/drivers/gpu/drm/i915/gvt/fb_decoder.h
>> new file mode 100644
>> index 0000000..04300af
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.h
>> +
>> +struct intel_vgpu_pipe_format {
>> +	struct intel_vgpu_primary_plane_format	primary;
>> +	struct intel_vgpu_sprite_plane_format	sprite;
>> +	struct intel_vgpu_cursor_plane_format	cursor;
>> +	enum DDI_PORT ddi_port;  /* the DDI port that pipe is connected to
>> +*/ };
>> +
>> +struct intel_vgpu_fb_format {
>> +	struct intel_vgpu_pipe_format	pipes[4];
>> +};
>
>Should use MAX_PIPE definition.
>
>--
>Open Source Technology Center, Intel ltd.
>
>$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g
  2017-05-31  2:29     ` Chen, Xiaoguang
@ 2017-05-31  8:59       ` Gerd Hoffmann
  -1 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-05-31  8:59 UTC (permalink / raw)
  To: Chen, Xiaoguang, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, Lv, Zhiyuan, intel-gvt-dev, Wang, Zhi A, Tian, Kevin

On Wed, 2017-05-31 at 02:29 +0000, Chen, Xiaoguang wrote:
> Hi Gerd,
> 
> It is based on 4.12.0-rc1

Applies, good.
But then fails to build:

error: ‘struct vfio_vgpu_dmabuf_info’ has no member named ‘resv’

gvt/kvmgt.c:611:11: note: in expansion of macro ‘offsetofend’
   minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);

/me wonders how this was tested ...

cheers,
  Gerd

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

* Re: [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g
@ 2017-05-31  8:59       ` Gerd Hoffmann
  0 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-05-31  8:59 UTC (permalink / raw)
  To: Chen, Xiaoguang, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, Lv, Zhiyuan, intel-gvt-dev, Wang, Zhi A, Tian, Kevin

On Wed, 2017-05-31 at 02:29 +0000, Chen, Xiaoguang wrote:
> Hi Gerd,
> 
> It is based on 4.12.0-rc1

Applies, good.
But then fails to build:

error: ‘struct vfio_vgpu_dmabuf_info’ has no member named ‘resv’

gvt/kvmgt.c:611:11: note: in expansion of macro ‘offsetofend’
   minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);

/me wonders how this was tested ...

cheers,
  Gerd
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* RE: [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g
  2017-05-31  8:59       ` Gerd Hoffmann
@ 2017-05-31  9:07         ` Chen, Xiaoguang
  -1 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-05-31  9:07 UTC (permalink / raw)
  To: Gerd Hoffmann, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, Lv, Zhiyuan, intel-gvt-dev, Wang, Zhi A, Tian, Kevin

Hi Gerd,

I found this problem once I sent the patches :(

I checked the uapi definitions and found it is usually called pad to do the aligning. So I changed the 'resv' to 'pad' in the patch but forgot to update it in the last patch and did not test after the "small" change. Next time I will test even when the change is very small.

I will change this in the next version.
Sorry for the mistake.

>-----Original Message-----
>From: Gerd Hoffmann [mailto:kraxel@redhat.com]
>Sent: Wednesday, May 31, 2017 4:59 PM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
>alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
>gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g
>
>On Wed, 2017-05-31 at 02:29 +0000, Chen, Xiaoguang wrote:
>> Hi Gerd,
>>
>> It is based on 4.12.0-rc1
>
>Applies, good.
>But then fails to build:
>
>error: ‘struct vfio_vgpu_dmabuf_info’ has no member named ‘resv’
>
>gvt/kvmgt.c:611:11: note: in expansion of macro ‘offsetofend’
>   minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);
>
>/me wonders how this was tested ...
>
>cheers,
>  Gerd

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

* Re: [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g
@ 2017-05-31  9:07         ` Chen, Xiaoguang
  0 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-05-31  9:07 UTC (permalink / raw)
  To: Gerd Hoffmann, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, Lv, Zhiyuan, intel-gvt-dev, Wang, Zhi A, Tian, Kevin

Hi Gerd,

I found this problem once I sent the patches :(

I checked the uapi definitions and found it is usually called pad to do the aligning. So I changed the 'resv' to 'pad' in the patch but forgot to update it in the last patch and did not test after the "small" change. Next time I will test even when the change is very small.

I will change this in the next version.
Sorry for the mistake.

>-----Original Message-----
>From: Gerd Hoffmann [mailto:kraxel@redhat.com]
>Sent: Wednesday, May 31, 2017 4:59 PM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
>alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
>gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g
>
>On Wed, 2017-05-31 at 02:29 +0000, Chen, Xiaoguang wrote:
>> Hi Gerd,
>>
>> It is based on 4.12.0-rc1
>
>Applies, good.
>But then fails to build:
>
>error: ‘struct vfio_vgpu_dmabuf_info’ has no member named ‘resv’
>
>gvt/kvmgt.c:611:11: note: in expansion of macro ‘offsetofend’
>   minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);
>
>/me wonders how this was tested ...
>
>cheers,
>  Gerd
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 5/6] drm/i915/gvt: Dmabuf support for GVT-g
  2017-05-27  8:38   ` Xiaoguang Chen
@ 2017-05-31 12:04     ` Gerd Hoffmann
  -1 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-05-31 12:04 UTC (permalink / raw)
  To: Xiaoguang Chen, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian

On Sat, 2017-05-27 at 16:38 +0800, Xiaoguang Chen wrote:
> +       if (plane_id == PLANE_PRIMARY) {

Should be DRM_PLANE_TYPE_PRIMARY (likewise for the cursor).

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

* Re: [PATCH v6 5/6] drm/i915/gvt: Dmabuf support for GVT-g
@ 2017-05-31 12:04     ` Gerd Hoffmann
  0 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-05-31 12:04 UTC (permalink / raw)
  To: Xiaoguang Chen, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian

On Sat, 2017-05-27 at 16:38 +0800, Xiaoguang Chen wrote:
> +       if (plane_id == PLANE_PRIMARY) {

Should be DRM_PLANE_TYPE_PRIMARY (likewise for the cursor).
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
  2017-05-31  6:18       ` Chen, Xiaoguang
@ 2017-05-31 17:22         ` Kirti Wankhede
  -1 siblings, 0 replies; 74+ messages in thread
From: Kirti Wankhede @ 2017-05-31 17:22 UTC (permalink / raw)
  To: Chen, Xiaoguang, Gerd Hoffmann, alex.williamson, chris,
	intel-gfx, linux-kernel, zhenyuw, Lv, Zhiyuan, intel-gvt-dev,
	Wang, Zhi A, Tian, Kevin



On 5/31/2017 11:48 AM, Chen, Xiaoguang wrote:
> Hi,
> 
>> -----Original Message-----
>> From: Gerd Hoffmann [mailto:kraxel@redhat.com]
>> Sent: Monday, May 29, 2017 3:20 PM
>> To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
>> alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
>> gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>> zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>> dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
>> <kevin.tian@intel.com>
>> Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
>>
>>> +struct vfio_vgpu_dmabuf_info {
>>> +	__u32 argsz;
>>> +	__u32 flags;
>>> +	struct vfio_vgpu_plane_info plane_info;
>>> +	__s32 fd;
>>> +	__u32 pad;
>>> +};
>>
>> Hmm, now you have argsz and flags twice in vfio_vgpu_dmabuf_info ...
>>
>> I think we should have something like this:
>>
>> struct vfio_vgpu_plane_info {
>>         __u64 start;
>>         __u64 drm_format_mod;
>>         __u32 drm_format;
>>         __u32 width;
>>         __u32 height;
>>         __u32 stride;
>>         __u32 size;
>>         __u32 x_pos;
>>         __u32 y_pos;
>>        __u32 padding;
>> };
>>
>> struct vfio_vgpu_query_plane {
>> 	__u32 argsz;
>> 	__u32 flags;
>> 	struct vfio_vgpu_plane_info plane_info;
>>        __u32 plane_id;
>>        __u32 padding;
>> };
>>
>> struct vfio_vgpu_create_dmabuf {
>> 	__u32 argsz;
>> 	__u32 flags;
>> 	struct vfio_vgpu_plane_info plane_info;
>>        __u32 plane_id;
>>        __s32 fd;
>> };
> Good suggestion will apply in the next version.
> Thanks for review :)
> 

Can you define what are the expected values of 'flags' would be?

Thanks,
Kirti

> Chenxg.
> 

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
@ 2017-05-31 17:22         ` Kirti Wankhede
  0 siblings, 0 replies; 74+ messages in thread
From: Kirti Wankhede @ 2017-05-31 17:22 UTC (permalink / raw)
  To: Chen, Xiaoguang, Gerd Hoffmann, alex.williamson, chris,
	intel-gfx, linux-kernel, zhenyuw, Lv, Zhiyuan, intel-gvt-dev,
	Wang, Zhi A, Tian, Kevin



On 5/31/2017 11:48 AM, Chen, Xiaoguang wrote:
> Hi,
> 
>> -----Original Message-----
>> From: Gerd Hoffmann [mailto:kraxel@redhat.com]
>> Sent: Monday, May 29, 2017 3:20 PM
>> To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
>> alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
>> gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>> zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>> dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
>> <kevin.tian@intel.com>
>> Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
>>
>>> +struct vfio_vgpu_dmabuf_info {
>>> +	__u32 argsz;
>>> +	__u32 flags;
>>> +	struct vfio_vgpu_plane_info plane_info;
>>> +	__s32 fd;
>>> +	__u32 pad;
>>> +};
>>
>> Hmm, now you have argsz and flags twice in vfio_vgpu_dmabuf_info ...
>>
>> I think we should have something like this:
>>
>> struct vfio_vgpu_plane_info {
>>         __u64 start;
>>         __u64 drm_format_mod;
>>         __u32 drm_format;
>>         __u32 width;
>>         __u32 height;
>>         __u32 stride;
>>         __u32 size;
>>         __u32 x_pos;
>>         __u32 y_pos;
>>        __u32 padding;
>> };
>>
>> struct vfio_vgpu_query_plane {
>> 	__u32 argsz;
>> 	__u32 flags;
>> 	struct vfio_vgpu_plane_info plane_info;
>>        __u32 plane_id;
>>        __u32 padding;
>> };
>>
>> struct vfio_vgpu_create_dmabuf {
>> 	__u32 argsz;
>> 	__u32 flags;
>> 	struct vfio_vgpu_plane_info plane_info;
>>        __u32 plane_id;
>>        __s32 fd;
>> };
> Good suggestion will apply in the next version.
> Thanks for review :)
> 

Can you define what are the expected values of 'flags' would be?

Thanks,
Kirti

> Chenxg.
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* RE: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
  2017-05-31 17:22         ` Kirti Wankhede
@ 2017-06-01  3:01           ` Chen, Xiaoguang
  -1 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-06-01  3:01 UTC (permalink / raw)
  To: Kirti Wankhede, Gerd Hoffmann, alex.williamson, chris, intel-gfx,
	linux-kernel, zhenyuw, Lv, Zhiyuan, intel-gvt-dev, Wang, Zhi A,
	Tian, Kevin

Hi Kirti,

>-----Original Message-----
>From: Kirti Wankhede [mailto:kwankhede@nvidia.com]
>Sent: Thursday, June 01, 2017 1:23 AM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>; Gerd Hoffmann
><kraxel@redhat.com>; alex.williamson@redhat.com; chris@chris-wilson.co.uk;
>intel-gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
>
>
>
>On 5/31/2017 11:48 AM, Chen, Xiaoguang wrote:
>> Hi,
>>
>>> -----Original Message-----
>>> From: Gerd Hoffmann [mailto:kraxel@redhat.com]
>>> Sent: Monday, May 29, 2017 3:20 PM
>>> To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
>>> alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
>>> gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>>> zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>;
>>> intel-gvt- dev@lists.freedesktop.org; Wang, Zhi A
>>> <zhi.a.wang@intel.com>; Tian, Kevin <kevin.tian@intel.com>
>>> Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf
>>> operations
>>>
>>>> +struct vfio_vgpu_dmabuf_info {
>>>> +	__u32 argsz;
>>>> +	__u32 flags;
>>>> +	struct vfio_vgpu_plane_info plane_info;
>>>> +	__s32 fd;
>>>> +	__u32 pad;
>>>> +};
>>>
>>> Hmm, now you have argsz and flags twice in vfio_vgpu_dmabuf_info ...
>>>
>>> I think we should have something like this:
>>>
>>> struct vfio_vgpu_plane_info {
>>>         __u64 start;
>>>         __u64 drm_format_mod;
>>>         __u32 drm_format;
>>>         __u32 width;
>>>         __u32 height;
>>>         __u32 stride;
>>>         __u32 size;
>>>         __u32 x_pos;
>>>         __u32 y_pos;
>>>        __u32 padding;
>>> };
>>>
>>> struct vfio_vgpu_query_plane {
>>> 	__u32 argsz;
>>> 	__u32 flags;
>>> 	struct vfio_vgpu_plane_info plane_info;
>>>        __u32 plane_id;
>>>        __u32 padding;
>>> };
>>>
>>> struct vfio_vgpu_create_dmabuf {
>>> 	__u32 argsz;
>>> 	__u32 flags;
>>> 	struct vfio_vgpu_plane_info plane_info;
>>>        __u32 plane_id;
>>>        __s32 fd;
>>> };
>> Good suggestion will apply in the next version.
>> Thanks for review :)
>>
>
>Can you define what are the expected values of 'flags' would be?
Flags is not used in this case.  It is defined to follow the rules of vfio ioctls.

>
>Thanks,
>Kirti
>
>> Chenxg.
>>

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
@ 2017-06-01  3:01           ` Chen, Xiaoguang
  0 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-06-01  3:01 UTC (permalink / raw)
  To: Kirti Wankhede, Gerd Hoffmann, alex.williamson, chris, intel-gfx,
	linux-kernel, zhenyuw, Lv, Zhiyuan, intel-gvt-dev, Wang, Zhi A,
	Tian, Kevin

Hi Kirti,

>-----Original Message-----
>From: Kirti Wankhede [mailto:kwankhede@nvidia.com]
>Sent: Thursday, June 01, 2017 1:23 AM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>; Gerd Hoffmann
><kraxel@redhat.com>; alex.williamson@redhat.com; chris@chris-wilson.co.uk;
>intel-gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
>
>
>
>On 5/31/2017 11:48 AM, Chen, Xiaoguang wrote:
>> Hi,
>>
>>> -----Original Message-----
>>> From: Gerd Hoffmann [mailto:kraxel@redhat.com]
>>> Sent: Monday, May 29, 2017 3:20 PM
>>> To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
>>> alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
>>> gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>>> zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>;
>>> intel-gvt- dev@lists.freedesktop.org; Wang, Zhi A
>>> <zhi.a.wang@intel.com>; Tian, Kevin <kevin.tian@intel.com>
>>> Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf
>>> operations
>>>
>>>> +struct vfio_vgpu_dmabuf_info {
>>>> +	__u32 argsz;
>>>> +	__u32 flags;
>>>> +	struct vfio_vgpu_plane_info plane_info;
>>>> +	__s32 fd;
>>>> +	__u32 pad;
>>>> +};
>>>
>>> Hmm, now you have argsz and flags twice in vfio_vgpu_dmabuf_info ...
>>>
>>> I think we should have something like this:
>>>
>>> struct vfio_vgpu_plane_info {
>>>         __u64 start;
>>>         __u64 drm_format_mod;
>>>         __u32 drm_format;
>>>         __u32 width;
>>>         __u32 height;
>>>         __u32 stride;
>>>         __u32 size;
>>>         __u32 x_pos;
>>>         __u32 y_pos;
>>>        __u32 padding;
>>> };
>>>
>>> struct vfio_vgpu_query_plane {
>>> 	__u32 argsz;
>>> 	__u32 flags;
>>> 	struct vfio_vgpu_plane_info plane_info;
>>>        __u32 plane_id;
>>>        __u32 padding;
>>> };
>>>
>>> struct vfio_vgpu_create_dmabuf {
>>> 	__u32 argsz;
>>> 	__u32 flags;
>>> 	struct vfio_vgpu_plane_info plane_info;
>>>        __u32 plane_id;
>>>        __s32 fd;
>>> };
>> Good suggestion will apply in the next version.
>> Thanks for review :)
>>
>
>Can you define what are the expected values of 'flags' would be?
Flags is not used in this case.  It is defined to follow the rules of vfio ioctls.

>
>Thanks,
>Kirti
>
>> Chenxg.
>>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* RE: [PATCH v6 5/6] drm/i915/gvt: Dmabuf support for GVT-g
  2017-05-31 12:04     ` Gerd Hoffmann
@ 2017-06-01  3:02       ` Chen, Xiaoguang
  -1 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-06-01  3:02 UTC (permalink / raw)
  To: Gerd Hoffmann, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, Lv, Zhiyuan, intel-gvt-dev, Wang, Zhi A, Tian, Kevin

Hi Gerd,

>-----Original Message-----
>From: intel-gvt-dev [mailto:intel-gvt-dev-bounces@lists.freedesktop.org] On
>Behalf Of Gerd Hoffmann
>Sent: Wednesday, May 31, 2017 8:05 PM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
>alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
>gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 5/6] drm/i915/gvt: Dmabuf support for GVT-g
>
>On Sat, 2017-05-27 at 16:38 +0800, Xiaoguang Chen wrote:
>> +       if (plane_id == PLANE_PRIMARY) {
>
>Should be DRM_PLANE_TYPE_PRIMARY (likewise for the cursor).
OK. I will change in the next version.

>_______________________________________________
>intel-gvt-dev mailing list
>intel-gvt-dev@lists.freedesktop.org
>https://lists.freedesktop.org/mailman/listinfo/intel-gvt-dev

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

* Re: [PATCH v6 5/6] drm/i915/gvt: Dmabuf support for GVT-g
@ 2017-06-01  3:02       ` Chen, Xiaoguang
  0 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-06-01  3:02 UTC (permalink / raw)
  To: Gerd Hoffmann, alex.williamson, chris, intel-gfx, linux-kernel,
	zhenyuw, Lv, Zhiyuan, intel-gvt-dev, Wang, Zhi A, Tian, Kevin

Hi Gerd,

>-----Original Message-----
>From: intel-gvt-dev [mailto:intel-gvt-dev-bounces@lists.freedesktop.org] On
>Behalf Of Gerd Hoffmann
>Sent: Wednesday, May 31, 2017 8:05 PM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
>alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
>gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 5/6] drm/i915/gvt: Dmabuf support for GVT-g
>
>On Sat, 2017-05-27 at 16:38 +0800, Xiaoguang Chen wrote:
>> +       if (plane_id == PLANE_PRIMARY) {
>
>Should be DRM_PLANE_TYPE_PRIMARY (likewise for the cursor).
OK. I will change in the next version.

>_______________________________________________
>intel-gvt-dev mailing list
>intel-gvt-dev@lists.freedesktop.org
>https://lists.freedesktop.org/mailman/listinfo/intel-gvt-dev
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 5/6] drm/i915/gvt: Dmabuf support for GVT-g
  2017-05-27  8:38   ` Xiaoguang Chen
@ 2017-06-01  9:15     ` Chris Wilson
  -1 siblings, 0 replies; 74+ messages in thread
From: Chris Wilson @ 2017-06-01  9:15 UTC (permalink / raw)
  To: Xiaoguang Chen
  Cc: alex.williamson, kraxel, intel-gfx, linux-kernel, zhenyuw,
	zhiyuan.lv, intel-gvt-dev, zhi.a.wang, kevin.tian

On Sat, May 27, 2017 at 04:38:51PM +0800, Xiaoguang Chen wrote:
> dmabuf for GVT-g can be exported to users who can use the dmabuf to show
> the desktop of vm which use intel vgpu.
> 
> Currently we provide query and create new dmabuf operations.
> 
> Users of dmabuf can cache some created dmabufs and related information
> such as the framebuffer's address, size, tiling mode, width, height etc.
> When refresh the screen first query the currnet vgpu's frambuffer and
> compare with the cached ones(address, size, tiling, width, height etc)
> if found one then reuse the found dmabuf to gain performance improvment.
> 
> If there is no dmabuf created yet or not found in the cached dmabufs then
> need to create a new dmabuf. To create a dmabuf first a gem object will
> be created and the backing storage of this gem object is the vgpu's
> framebuffer(primary/cursor).
> Set caching mode, change tiling mode and set domains of this gem object
> is not supported.
> Then associate this gem object to a dmabuf and export this dmabuf.
> A file descriptor will be generated for this dmabuf and this file
> descriptor can be sent to user space to do display.
> 
> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
> ---
>  drivers/gpu/drm/i915/gvt/Makefile      |   2 +-
>  drivers/gpu/drm/i915/gvt/dmabuf.c      | 269 +++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/gvt/dmabuf.h      |  37 +++++
>  drivers/gpu/drm/i915/gvt/gvt.h         |   1 +
>  drivers/gpu/drm/i915/i915_gem.c        |  26 +++-
>  drivers/gpu/drm/i915/i915_gem_object.h |   9 ++
>  6 files changed, 342 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/gvt/dmabuf.c
>  create mode 100644 drivers/gpu/drm/i915/gvt/dmabuf.h
> 
> diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile
> index 192ca26..e480f7d 100644
> --- a/drivers/gpu/drm/i915/gvt/Makefile
> +++ b/drivers/gpu/drm/i915/gvt/Makefile
> @@ -2,7 +2,7 @@ GVT_DIR := gvt
>  GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \
>  	interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \
>  	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o \
> -	fb_decoder.o
> +	fb_decoder.o dmabuf.o
>  
>  ccflags-y				+= -I$(src) -I$(src)/$(GVT_DIR) -Wall
>  i915-y					+= $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
> new file mode 100644
> index 0000000..c831e91
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
> @@ -0,0 +1,269 @@
> +/*
> + * Copyright 2017 Intel Corporation. All rights reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Authors:
> + *    Zhiyuan Lv <zhiyuan.lv@intel.com>
> + *
> + * Contributors:
> + *    Xiaoguang Chen <xiaoguang.chen@intel.com>
> + */
> +
> +#include <linux/dma-buf.h>
> +#include <drm/drmP.h>
> +#include <linux/vfio.h>
> +
> +#include "i915_drv.h"
> +#include "gvt.h"
> +
> +#define GEN8_DECODE_PTE(pte) (pte & GENMASK_ULL(63, 12))
> +
> +static struct sg_table *intel_vgpu_gem_get_pages(
> +		struct drm_i915_gem_object *obj)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
> +	struct sg_table *st;
> +	struct scatterlist *sg;
> +	int i, ret;
> +	gen8_pte_t __iomem *gtt_entries;
> +	struct intel_vgpu_fb_info *fb_info;
> +
> +	fb_info = (struct intel_vgpu_fb_info *)obj->gvt_info;
> +	if (WARN_ON(!fb_info))
> +		return ERR_PTR(-ENODEV);
> +
> +	st = kmalloc(sizeof(*st), GFP_KERNEL);
> +	if (!st) {
> +		ret = -ENOMEM;
> +		return ERR_PTR(ret);

Tidier.

> +	}
> +
> +	ret = sg_alloc_table(st, fb_info->fb_size, GFP_KERNEL);
> +	if (ret) {
> +		kfree(st);
> +		return ERR_PTR(ret);
> +	}
> +	gtt_entries = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm +
> +		(fb_info->fb_addr >> PAGE_SHIFT);
> +	for_each_sg(st->sgl, sg, fb_info->fb_size, i) {
> +		sg->offset = 0;
> +		sg->length = PAGE_SIZE;
> +		sg_dma_address(sg) =
> +			GEN8_DECODE_PTE(readq(&gtt_entries[i]));
> +		sg_dma_len(sg) = PAGE_SIZE;
> +	}
> +
> +	return st;
> +}
> +
> +static void intel_vgpu_gem_put_pages(struct drm_i915_gem_object *obj,
> +		struct sg_table *pages)
> +{
> +	sg_free_table(pages);
> +	kfree(pages);
> +}
> +
> +static const struct drm_i915_gem_object_ops intel_vgpu_gem_ops = {
> +	.flags = I915_GEM_OBJECT_IS_PROXY,
> +	.get_pages = intel_vgpu_gem_get_pages,
> +	.put_pages = intel_vgpu_gem_put_pages,
> +};
> +
> +static struct drm_i915_gem_object *intel_vgpu_create_gem(struct drm_device *dev,
> +		struct vfio_vgpu_plane_info *info)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +	struct drm_i915_gem_object *obj;
> +
> +	obj = i915_gem_object_alloc(dev_priv);
> +	if (obj == NULL)
> +		return NULL;
> +
> +	drm_gem_private_object_init(dev, &obj->base,
> +		info->size << PAGE_SHIFT);
> +	i915_gem_object_init(obj, &intel_vgpu_gem_ops);
> +
> +	obj->base.read_domains = I915_GEM_DOMAIN_GTT;
> +	obj->base.write_domain = 0;
> +	/* Change tiling mode from user space is not supported to a GVT-g's
> +	 * dma-buf gem object.
> +	 * We increase the obj's framebuffer_references to disable this kind
> +	 * of operation.
> +	 */
> +	obj->framebuffer_references++;

If it is only for that, don't. Just use the is_proxy: return -EPERM. So
that you don't make the mistake of leaving the counter dangling and the
error code is consistent.

What you probably should consider though is setting obj->pin_display.
That will fix up coherency along a few more paths.

> +	if (IS_SKYLAKE(dev_priv)) {
> +		unsigned int tiling_mode = 0;
> +		unsigned int stride = 0;
> +
> +		switch (info->drm_format_mod << 10) {
> +		case PLANE_CTL_TILED_LINEAR:
> +			tiling_mode = I915_TILING_NONE;
> +			break;
> +		case PLANE_CTL_TILED_X:
> +			tiling_mode = I915_TILING_X;
> +			stride = info->stride;
> +			break;
> +		case PLANE_CTL_TILED_Y:
> +			tiling_mode = I915_TILING_Y;
> +			stride = info->stride;
> +			break;
> +		default:
> +			gvt_dbg_core("not supported tiling mode\n");
> +		}
> +		obj->tiling_and_stride = tiling_mode | stride;
> +	} else {
> +		obj->tiling_and_stride = info->drm_format_mod ?
> +					I915_TILING_X : 0;
> +	}
> +
> +	return obj;
> +}

> +
> +int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args)
> +{
> +	struct drm_device *dev = &vgpu->gvt->dev_priv->drm;
> +	struct vfio_vgpu_plane_info *info = args;
> +
> +	return intel_vgpu_get_plane_info(dev, vgpu, info);
> +}
> +
> +int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args)
> +{
> +	struct dma_buf *dmabuf;
> +	struct drm_i915_gem_object *obj;
> +	struct drm_device *dev = &vgpu->gvt->dev_priv->drm;
> +	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
> +	struct intel_vgpu_fb_info *fb_info;
> +	int ret;
> +
> +	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
> +	if (ret != 0)
> +		return ret;
> +
> +	obj = intel_vgpu_create_gem(dev, &gvt_dmabuf->plane_info);
> +	if (obj == NULL) {
> +		gvt_vgpu_err("create gvt gem obj failed:%d\n", vgpu->id);
> +		return -ENOMEM;
> +	}
> +	fb_info = kmalloc(sizeof(*fb_info), GFP_KERNEL);
> +	if (!fb_info) {
> +		i915_gem_object_put(obj);
> +		gvt_vgpu_err("allocate intel vgpu fb info failed\n");
> +		return -ENOMEM;
> +	}
> +	fb_info->fb_addr = gvt_dmabuf->plane_info.start;
> +	fb_info->fb_size = gvt_dmabuf->plane_info.size;
> +	fb_info->vgpu = vgpu;
> +	obj->gvt_info = fb_info;
> +
> +	dmabuf = i915_gem_prime_export(dev, &obj->base, DRM_CLOEXEC | DRM_RDWR);
> +
> +	if (IS_ERR(dmabuf)) {
> +		kfree(fb_info);
> +		i915_gem_object_free(obj);
> +		gvt_vgpu_err("export dma-buf failed\n");

Develop a habit for using onion unwind for errors.

> +		return PTR_ERR(dmabuf);
> +	}
> +
> +	ret = dma_buf_fd(dmabuf, DRM_CLOEXEC | DRM_RDWR);
> +	if (ret < 0) {
> +		kfree(fb_info);
> +		i915_gem_object_free(obj);
> +		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
> +		return ret;
> +	}
> +	gvt_dmabuf->fd = ret;
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 0c1cbe9..14be3b0 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -1609,6 +1609,12 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
>  	if (!obj)
>  		return -ENOENT;
>  
> +	/* proxy gem object does not support setting domain */
> +	if (i915_gem_object_is_proxy(obj)) {
> +		i915_gem_object_put(obj);
> +		return -EPERM;

Hook into the onion.

> +	}
> +
>  	/* Try to flush the object off the GPU without holding the lock.
>  	 * We will repeat the flush holding the lock in the normal manner
>  	 * to catch cases where we are gazumped.
> @@ -1677,6 +1683,12 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
>  	if (!obj)
>  		return -ENOENT;
>  
> +	/* proxy gem obj does not support this operation */
> +	if (i915_gem_object_is_proxy(obj)) {
> +		i915_gem_object_put(obj);
> +		return -EPERM;
> +	}
> +
>  	/* Pinned buffers may be scanout, so flush the cache */
>  	i915_gem_object_flush_if_display(obj);
>  	i915_gem_object_put(obj);
> @@ -1727,7 +1739,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
>  	 */
>  	if (!obj->base.filp) {
>  		i915_gem_object_put(obj);
> -		return -EINVAL;
> +		return -EPERM;
>  	}
>  
>  	addr = vm_mmap(obj->base.filp, 0, args->size,
> @@ -3717,6 +3729,12 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
>  	if (!obj)
>  		return -ENOENT;
>  
> +	/* proxy gem obj does not support setting caching mode */
> +	if (i915_gem_object_is_proxy(obj)) {
> +		i915_gem_object_put(obj);
> +		return -EPERM;

Use the onion.
> +	}
> +
>  	if (obj->cache_level == level)
>  		goto out;
>  
> @@ -4168,6 +4186,12 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
>  	if (!obj)
>  		return -ENOENT;
>  
> +	/* proxy gem obj does not support changing backding storage */
> +	if (i915_gem_object_is_proxy(obj)) {
> +		i915_gem_object_put(obj);

More onion.

> +		return -EPERM;
> +	}
> +
>  	err = mutex_lock_interruptible(&obj->mm.lock);
>  	if (err)
>  		goto out;

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH v6 5/6] drm/i915/gvt: Dmabuf support for GVT-g
@ 2017-06-01  9:15     ` Chris Wilson
  0 siblings, 0 replies; 74+ messages in thread
From: Chris Wilson @ 2017-06-01  9:15 UTC (permalink / raw)
  To: Xiaoguang Chen; +Cc: intel-gfx, linux-kernel, zhiyuan.lv, intel-gvt-dev, kraxel

On Sat, May 27, 2017 at 04:38:51PM +0800, Xiaoguang Chen wrote:
> dmabuf for GVT-g can be exported to users who can use the dmabuf to show
> the desktop of vm which use intel vgpu.
> 
> Currently we provide query and create new dmabuf operations.
> 
> Users of dmabuf can cache some created dmabufs and related information
> such as the framebuffer's address, size, tiling mode, width, height etc.
> When refresh the screen first query the currnet vgpu's frambuffer and
> compare with the cached ones(address, size, tiling, width, height etc)
> if found one then reuse the found dmabuf to gain performance improvment.
> 
> If there is no dmabuf created yet or not found in the cached dmabufs then
> need to create a new dmabuf. To create a dmabuf first a gem object will
> be created and the backing storage of this gem object is the vgpu's
> framebuffer(primary/cursor).
> Set caching mode, change tiling mode and set domains of this gem object
> is not supported.
> Then associate this gem object to a dmabuf and export this dmabuf.
> A file descriptor will be generated for this dmabuf and this file
> descriptor can be sent to user space to do display.
> 
> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
> ---
>  drivers/gpu/drm/i915/gvt/Makefile      |   2 +-
>  drivers/gpu/drm/i915/gvt/dmabuf.c      | 269 +++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/gvt/dmabuf.h      |  37 +++++
>  drivers/gpu/drm/i915/gvt/gvt.h         |   1 +
>  drivers/gpu/drm/i915/i915_gem.c        |  26 +++-
>  drivers/gpu/drm/i915/i915_gem_object.h |   9 ++
>  6 files changed, 342 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/gvt/dmabuf.c
>  create mode 100644 drivers/gpu/drm/i915/gvt/dmabuf.h
> 
> diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile
> index 192ca26..e480f7d 100644
> --- a/drivers/gpu/drm/i915/gvt/Makefile
> +++ b/drivers/gpu/drm/i915/gvt/Makefile
> @@ -2,7 +2,7 @@ GVT_DIR := gvt
>  GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \
>  	interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \
>  	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o \
> -	fb_decoder.o
> +	fb_decoder.o dmabuf.o
>  
>  ccflags-y				+= -I$(src) -I$(src)/$(GVT_DIR) -Wall
>  i915-y					+= $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
> new file mode 100644
> index 0000000..c831e91
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
> @@ -0,0 +1,269 @@
> +/*
> + * Copyright 2017 Intel Corporation. All rights reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Authors:
> + *    Zhiyuan Lv <zhiyuan.lv@intel.com>
> + *
> + * Contributors:
> + *    Xiaoguang Chen <xiaoguang.chen@intel.com>
> + */
> +
> +#include <linux/dma-buf.h>
> +#include <drm/drmP.h>
> +#include <linux/vfio.h>
> +
> +#include "i915_drv.h"
> +#include "gvt.h"
> +
> +#define GEN8_DECODE_PTE(pte) (pte & GENMASK_ULL(63, 12))
> +
> +static struct sg_table *intel_vgpu_gem_get_pages(
> +		struct drm_i915_gem_object *obj)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
> +	struct sg_table *st;
> +	struct scatterlist *sg;
> +	int i, ret;
> +	gen8_pte_t __iomem *gtt_entries;
> +	struct intel_vgpu_fb_info *fb_info;
> +
> +	fb_info = (struct intel_vgpu_fb_info *)obj->gvt_info;
> +	if (WARN_ON(!fb_info))
> +		return ERR_PTR(-ENODEV);
> +
> +	st = kmalloc(sizeof(*st), GFP_KERNEL);
> +	if (!st) {
> +		ret = -ENOMEM;
> +		return ERR_PTR(ret);

Tidier.

> +	}
> +
> +	ret = sg_alloc_table(st, fb_info->fb_size, GFP_KERNEL);
> +	if (ret) {
> +		kfree(st);
> +		return ERR_PTR(ret);
> +	}
> +	gtt_entries = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm +
> +		(fb_info->fb_addr >> PAGE_SHIFT);
> +	for_each_sg(st->sgl, sg, fb_info->fb_size, i) {
> +		sg->offset = 0;
> +		sg->length = PAGE_SIZE;
> +		sg_dma_address(sg) =
> +			GEN8_DECODE_PTE(readq(&gtt_entries[i]));
> +		sg_dma_len(sg) = PAGE_SIZE;
> +	}
> +
> +	return st;
> +}
> +
> +static void intel_vgpu_gem_put_pages(struct drm_i915_gem_object *obj,
> +		struct sg_table *pages)
> +{
> +	sg_free_table(pages);
> +	kfree(pages);
> +}
> +
> +static const struct drm_i915_gem_object_ops intel_vgpu_gem_ops = {
> +	.flags = I915_GEM_OBJECT_IS_PROXY,
> +	.get_pages = intel_vgpu_gem_get_pages,
> +	.put_pages = intel_vgpu_gem_put_pages,
> +};
> +
> +static struct drm_i915_gem_object *intel_vgpu_create_gem(struct drm_device *dev,
> +		struct vfio_vgpu_plane_info *info)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +	struct drm_i915_gem_object *obj;
> +
> +	obj = i915_gem_object_alloc(dev_priv);
> +	if (obj == NULL)
> +		return NULL;
> +
> +	drm_gem_private_object_init(dev, &obj->base,
> +		info->size << PAGE_SHIFT);
> +	i915_gem_object_init(obj, &intel_vgpu_gem_ops);
> +
> +	obj->base.read_domains = I915_GEM_DOMAIN_GTT;
> +	obj->base.write_domain = 0;
> +	/* Change tiling mode from user space is not supported to a GVT-g's
> +	 * dma-buf gem object.
> +	 * We increase the obj's framebuffer_references to disable this kind
> +	 * of operation.
> +	 */
> +	obj->framebuffer_references++;

If it is only for that, don't. Just use the is_proxy: return -EPERM. So
that you don't make the mistake of leaving the counter dangling and the
error code is consistent.

What you probably should consider though is setting obj->pin_display.
That will fix up coherency along a few more paths.

> +	if (IS_SKYLAKE(dev_priv)) {
> +		unsigned int tiling_mode = 0;
> +		unsigned int stride = 0;
> +
> +		switch (info->drm_format_mod << 10) {
> +		case PLANE_CTL_TILED_LINEAR:
> +			tiling_mode = I915_TILING_NONE;
> +			break;
> +		case PLANE_CTL_TILED_X:
> +			tiling_mode = I915_TILING_X;
> +			stride = info->stride;
> +			break;
> +		case PLANE_CTL_TILED_Y:
> +			tiling_mode = I915_TILING_Y;
> +			stride = info->stride;
> +			break;
> +		default:
> +			gvt_dbg_core("not supported tiling mode\n");
> +		}
> +		obj->tiling_and_stride = tiling_mode | stride;
> +	} else {
> +		obj->tiling_and_stride = info->drm_format_mod ?
> +					I915_TILING_X : 0;
> +	}
> +
> +	return obj;
> +}

> +
> +int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args)
> +{
> +	struct drm_device *dev = &vgpu->gvt->dev_priv->drm;
> +	struct vfio_vgpu_plane_info *info = args;
> +
> +	return intel_vgpu_get_plane_info(dev, vgpu, info);
> +}
> +
> +int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args)
> +{
> +	struct dma_buf *dmabuf;
> +	struct drm_i915_gem_object *obj;
> +	struct drm_device *dev = &vgpu->gvt->dev_priv->drm;
> +	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
> +	struct intel_vgpu_fb_info *fb_info;
> +	int ret;
> +
> +	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
> +	if (ret != 0)
> +		return ret;
> +
> +	obj = intel_vgpu_create_gem(dev, &gvt_dmabuf->plane_info);
> +	if (obj == NULL) {
> +		gvt_vgpu_err("create gvt gem obj failed:%d\n", vgpu->id);
> +		return -ENOMEM;
> +	}
> +	fb_info = kmalloc(sizeof(*fb_info), GFP_KERNEL);
> +	if (!fb_info) {
> +		i915_gem_object_put(obj);
> +		gvt_vgpu_err("allocate intel vgpu fb info failed\n");
> +		return -ENOMEM;
> +	}
> +	fb_info->fb_addr = gvt_dmabuf->plane_info.start;
> +	fb_info->fb_size = gvt_dmabuf->plane_info.size;
> +	fb_info->vgpu = vgpu;
> +	obj->gvt_info = fb_info;
> +
> +	dmabuf = i915_gem_prime_export(dev, &obj->base, DRM_CLOEXEC | DRM_RDWR);
> +
> +	if (IS_ERR(dmabuf)) {
> +		kfree(fb_info);
> +		i915_gem_object_free(obj);
> +		gvt_vgpu_err("export dma-buf failed\n");

Develop a habit for using onion unwind for errors.

> +		return PTR_ERR(dmabuf);
> +	}
> +
> +	ret = dma_buf_fd(dmabuf, DRM_CLOEXEC | DRM_RDWR);
> +	if (ret < 0) {
> +		kfree(fb_info);
> +		i915_gem_object_free(obj);
> +		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
> +		return ret;
> +	}
> +	gvt_dmabuf->fd = ret;
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 0c1cbe9..14be3b0 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -1609,6 +1609,12 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
>  	if (!obj)
>  		return -ENOENT;
>  
> +	/* proxy gem object does not support setting domain */
> +	if (i915_gem_object_is_proxy(obj)) {
> +		i915_gem_object_put(obj);
> +		return -EPERM;

Hook into the onion.

> +	}
> +
>  	/* Try to flush the object off the GPU without holding the lock.
>  	 * We will repeat the flush holding the lock in the normal manner
>  	 * to catch cases where we are gazumped.
> @@ -1677,6 +1683,12 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
>  	if (!obj)
>  		return -ENOENT;
>  
> +	/* proxy gem obj does not support this operation */
> +	if (i915_gem_object_is_proxy(obj)) {
> +		i915_gem_object_put(obj);
> +		return -EPERM;
> +	}
> +
>  	/* Pinned buffers may be scanout, so flush the cache */
>  	i915_gem_object_flush_if_display(obj);
>  	i915_gem_object_put(obj);
> @@ -1727,7 +1739,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
>  	 */
>  	if (!obj->base.filp) {
>  		i915_gem_object_put(obj);
> -		return -EINVAL;
> +		return -EPERM;
>  	}
>  
>  	addr = vm_mmap(obj->base.filp, 0, args->size,
> @@ -3717,6 +3729,12 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
>  	if (!obj)
>  		return -ENOENT;
>  
> +	/* proxy gem obj does not support setting caching mode */
> +	if (i915_gem_object_is_proxy(obj)) {
> +		i915_gem_object_put(obj);
> +		return -EPERM;

Use the onion.
> +	}
> +
>  	if (obj->cache_level == level)
>  		goto out;
>  
> @@ -4168,6 +4186,12 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
>  	if (!obj)
>  		return -ENOENT;
>  
> +	/* proxy gem obj does not support changing backding storage */
> +	if (i915_gem_object_is_proxy(obj)) {
> +		i915_gem_object_put(obj);

More onion.

> +		return -EPERM;
> +	}
> +
>  	err = mutex_lock_interruptible(&obj->mm.lock);
>  	if (err)
>  		goto out;

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
  2017-06-01  3:01           ` Chen, Xiaoguang
@ 2017-06-01 16:38             ` Alex Williamson
  -1 siblings, 0 replies; 74+ messages in thread
From: Alex Williamson @ 2017-06-01 16:38 UTC (permalink / raw)
  To: Chen, Xiaoguang
  Cc: Kirti Wankhede, Gerd Hoffmann, chris, intel-gfx, linux-kernel,
	zhenyuw, Lv, Zhiyuan, intel-gvt-dev, Wang, Zhi A, Tian, Kevin

On Thu, 1 Jun 2017 03:01:28 +0000
"Chen, Xiaoguang" <xiaoguang.chen@intel.com> wrote:

> Hi Kirti,
> 
> >-----Original Message-----
> >From: Kirti Wankhede [mailto:kwankhede@nvidia.com]
> >Sent: Thursday, June 01, 2017 1:23 AM
> >To: Chen, Xiaoguang <xiaoguang.chen@intel.com>; Gerd Hoffmann
> ><kraxel@redhat.com>; alex.williamson@redhat.com; chris@chris-wilson.co.uk;
> >intel-gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
> >zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
> >dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
> ><kevin.tian@intel.com>
> >Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
> >
> >
> >
> >On 5/31/2017 11:48 AM, Chen, Xiaoguang wrote:  
> >> Hi,
> >>  
> >>> -----Original Message-----
> >>> From: Gerd Hoffmann [mailto:kraxel@redhat.com]
> >>> Sent: Monday, May 29, 2017 3:20 PM
> >>> To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
> >>> alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
> >>> gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
> >>> zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>;
> >>> intel-gvt- dev@lists.freedesktop.org; Wang, Zhi A
> >>> <zhi.a.wang@intel.com>; Tian, Kevin <kevin.tian@intel.com>
> >>> Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf
> >>> operations
> >>>  
> >>>> +struct vfio_vgpu_dmabuf_info {
> >>>> +	__u32 argsz;
> >>>> +	__u32 flags;
> >>>> +	struct vfio_vgpu_plane_info plane_info;
> >>>> +	__s32 fd;
> >>>> +	__u32 pad;
> >>>> +};  
> >>>
> >>> Hmm, now you have argsz and flags twice in vfio_vgpu_dmabuf_info ...
> >>>
> >>> I think we should have something like this:
> >>>
> >>> struct vfio_vgpu_plane_info {
> >>>         __u64 start;
> >>>         __u64 drm_format_mod;
> >>>         __u32 drm_format;
> >>>         __u32 width;
> >>>         __u32 height;
> >>>         __u32 stride;
> >>>         __u32 size;
> >>>         __u32 x_pos;
> >>>         __u32 y_pos;
> >>>        __u32 padding;
> >>> };
> >>>
> >>> struct vfio_vgpu_query_plane {
> >>> 	__u32 argsz;
> >>> 	__u32 flags;
> >>> 	struct vfio_vgpu_plane_info plane_info;
> >>>        __u32 plane_id;
> >>>        __u32 padding;
> >>> };
> >>>
> >>> struct vfio_vgpu_create_dmabuf {
> >>> 	__u32 argsz;
> >>> 	__u32 flags;
> >>> 	struct vfio_vgpu_plane_info plane_info;
> >>>        __u32 plane_id;
> >>>        __s32 fd;
> >>> };  
> >> Good suggestion will apply in the next version.
> >> Thanks for review :)
> >>  
> >
> >Can you define what are the expected values of 'flags' would be?  
> Flags is not used in this case.  It is defined to follow the rules of vfio ioctls.

An important note about flags, the vendor driver must validate it.  If
they don't and the user passes an arbitrary value there, then we have a
backwards compatibility issue with ever attempting to use the flags
field.  The user passing in a flag unknown to the vendor driver should
return an -EINVAL response.  In this case, we haven't defined any
flags, so the vendor driver needs to force the user to pass zero.
Thanks,

Alex

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
@ 2017-06-01 16:38             ` Alex Williamson
  0 siblings, 0 replies; 74+ messages in thread
From: Alex Williamson @ 2017-06-01 16:38 UTC (permalink / raw)
  To: Chen, Xiaoguang
  Cc: intel-gfx, linux-kernel, Kirti Wankhede, Gerd Hoffmann,
	intel-gvt-dev, Lv, Zhiyuan

On Thu, 1 Jun 2017 03:01:28 +0000
"Chen, Xiaoguang" <xiaoguang.chen@intel.com> wrote:

> Hi Kirti,
> 
> >-----Original Message-----
> >From: Kirti Wankhede [mailto:kwankhede@nvidia.com]
> >Sent: Thursday, June 01, 2017 1:23 AM
> >To: Chen, Xiaoguang <xiaoguang.chen@intel.com>; Gerd Hoffmann
> ><kraxel@redhat.com>; alex.williamson@redhat.com; chris@chris-wilson.co.uk;
> >intel-gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
> >zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
> >dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
> ><kevin.tian@intel.com>
> >Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
> >
> >
> >
> >On 5/31/2017 11:48 AM, Chen, Xiaoguang wrote:  
> >> Hi,
> >>  
> >>> -----Original Message-----
> >>> From: Gerd Hoffmann [mailto:kraxel@redhat.com]
> >>> Sent: Monday, May 29, 2017 3:20 PM
> >>> To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
> >>> alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
> >>> gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
> >>> zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>;
> >>> intel-gvt- dev@lists.freedesktop.org; Wang, Zhi A
> >>> <zhi.a.wang@intel.com>; Tian, Kevin <kevin.tian@intel.com>
> >>> Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf
> >>> operations
> >>>  
> >>>> +struct vfio_vgpu_dmabuf_info {
> >>>> +	__u32 argsz;
> >>>> +	__u32 flags;
> >>>> +	struct vfio_vgpu_plane_info plane_info;
> >>>> +	__s32 fd;
> >>>> +	__u32 pad;
> >>>> +};  
> >>>
> >>> Hmm, now you have argsz and flags twice in vfio_vgpu_dmabuf_info ...
> >>>
> >>> I think we should have something like this:
> >>>
> >>> struct vfio_vgpu_plane_info {
> >>>         __u64 start;
> >>>         __u64 drm_format_mod;
> >>>         __u32 drm_format;
> >>>         __u32 width;
> >>>         __u32 height;
> >>>         __u32 stride;
> >>>         __u32 size;
> >>>         __u32 x_pos;
> >>>         __u32 y_pos;
> >>>        __u32 padding;
> >>> };
> >>>
> >>> struct vfio_vgpu_query_plane {
> >>> 	__u32 argsz;
> >>> 	__u32 flags;
> >>> 	struct vfio_vgpu_plane_info plane_info;
> >>>        __u32 plane_id;
> >>>        __u32 padding;
> >>> };
> >>>
> >>> struct vfio_vgpu_create_dmabuf {
> >>> 	__u32 argsz;
> >>> 	__u32 flags;
> >>> 	struct vfio_vgpu_plane_info plane_info;
> >>>        __u32 plane_id;
> >>>        __s32 fd;
> >>> };  
> >> Good suggestion will apply in the next version.
> >> Thanks for review :)
> >>  
> >
> >Can you define what are the expected values of 'flags' would be?  
> Flags is not used in this case.  It is defined to follow the rules of vfio ioctls.

An important note about flags, the vendor driver must validate it.  If
they don't and the user passes an arbitrary value there, then we have a
backwards compatibility issue with ever attempting to use the flags
field.  The user passing in a flag unknown to the vendor driver should
return an -EINVAL response.  In this case, we haven't defined any
flags, so the vendor driver needs to force the user to pass zero.
Thanks,

Alex
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
  2017-05-27  8:38   ` Xiaoguang Chen
@ 2017-06-01 18:08     ` Alex Williamson
  -1 siblings, 0 replies; 74+ messages in thread
From: Alex Williamson @ 2017-06-01 18:08 UTC (permalink / raw)
  To: Xiaoguang Chen
  Cc: kraxel, chris, intel-gfx, linux-kernel, zhenyuw, zhiyuan.lv,
	intel-gvt-dev, zhi.a.wang, kevin.tian

On Sat, 27 May 2017 16:38:52 +0800
Xiaoguang Chen <xiaoguang.chen@intel.com> wrote:

> User space should create the management fd for the dma-buf operation first.
> Then user can query the plane information and create dma-buf if necessary
> using the management fd.
> 
> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
> ---
>  drivers/gpu/drm/i915/gvt/dmabuf.c |  12 ++++
>  drivers/gpu/drm/i915/gvt/dmabuf.h |   5 ++
>  drivers/gpu/drm/i915/gvt/gvt.c    |   2 +
>  drivers/gpu/drm/i915/gvt/gvt.h    |   5 ++
>  drivers/gpu/drm/i915/gvt/kvmgt.c  | 144 ++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/gvt/vgpu.c   |   1 +
>  6 files changed, 169 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
> index c831e91..9759e9a 100644
> --- a/drivers/gpu/drm/i915/gvt/dmabuf.c
> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
> @@ -226,6 +226,7 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args)
>  	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
>  	struct intel_vgpu_fb_info *fb_info;
>  	int ret;
> +	struct intel_vgpu_dmabuf_obj *dmabuf_obj;
>  
>  	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
>  	if (ret != 0)
> @@ -263,6 +264,17 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args)
>  		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
>  		return ret;
>  	}
> +	dmabuf_obj = kmalloc(sizeof(*dmabuf_obj), GFP_KERNEL);
> +	if (dmabuf_obj == NULL) {
> +		kfree(fb_info);
> +		i915_gem_object_put(obj);
> +		gvt_vgpu_err("alloc dmabuf_obj failed\n");
> +		return -ENOMEM;
> +	}
> +	dmabuf_obj->obj = obj;
> +	INIT_LIST_HEAD(&dmabuf_obj->list);
> +	list_add_tail(&dmabuf_obj->list, &vgpu->dmabuf_obj_list_head);
> +
>  	gvt_dmabuf->fd = ret;
>  
>  	return 0;
> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h b/drivers/gpu/drm/i915/gvt/dmabuf.h
> index 8be9979..cafa781 100644
> --- a/drivers/gpu/drm/i915/gvt/dmabuf.h
> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
> @@ -31,6 +31,11 @@ struct intel_vgpu_fb_info {
>  	uint32_t fb_size;
>  };
>  
> +struct intel_vgpu_dmabuf_obj {
> +	struct drm_i915_gem_object *obj;
> +	struct list_head list;
> +};
> +
>  int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);
>  int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args);
>  
> diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c
> index 2032917..dbc3f86 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.c
> +++ b/drivers/gpu/drm/i915/gvt/gvt.c
> @@ -54,6 +54,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {
>  	.vgpu_reset = intel_gvt_reset_vgpu,
>  	.vgpu_activate = intel_gvt_activate_vgpu,
>  	.vgpu_deactivate = intel_gvt_deactivate_vgpu,
> +	.vgpu_query_plane = intel_vgpu_query_plane,
> +	.vgpu_create_dmabuf = intel_vgpu_create_dmabuf,
>  };
>  
>  /**
> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
> index 763a8c5..a855797 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> @@ -185,8 +185,11 @@ struct intel_vgpu {
>  		struct kvm *kvm;
>  		struct work_struct release_work;
>  		atomic_t released;
> +		struct vfio_device *vfio_device;
>  	} vdev;
>  #endif
> +	int dmabuf_mgr_fd;
> +	struct list_head dmabuf_obj_list_head;
>  };
>  
>  struct intel_gvt_gm {
> @@ -467,6 +470,8 @@ struct intel_gvt_ops {
>  	void (*vgpu_reset)(struct intel_vgpu *);
>  	void (*vgpu_activate)(struct intel_vgpu *);
>  	void (*vgpu_deactivate)(struct intel_vgpu *);
> +	int (*vgpu_query_plane)(struct intel_vgpu *vgpu, void *);
> +	int (*vgpu_create_dmabuf)(struct intel_vgpu *vgpu, void *);
>  };
>  
>  
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 389f072..a079080 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -41,6 +41,7 @@
>  #include <linux/kvm_host.h>
>  #include <linux/vfio.h>
>  #include <linux/mdev.h>
> +#include <linux/anon_inodes.h>
>  
>  #include "i915_drv.h"
>  #include "gvt.h"
> @@ -524,6 +525,125 @@ static int intel_vgpu_reg_init_opregion(struct intel_vgpu *vgpu)
>  	return ret;
>  }
>  
> +static int kvmgt_get_vfio_device(struct intel_vgpu *vgpu)
> +{
> +	struct vfio_device *device;
> +
> +	device = vfio_device_get_from_dev(mdev_dev(vgpu->vdev.mdev));
> +	if (device == NULL)
> +		return -ENODEV;
> +	vgpu->vdev.vfio_device = device;
> +
> +	return 0;
> +}
> +
> +static void kvmgt_put_vfio_device(struct intel_vgpu *vgpu)
> +{
> +	vfio_device_put(vgpu->vdev.vfio_device);
> +}
> +
> +static int intel_vgpu_dmabuf_mgr_fd_mmap(struct file *file,
> +		struct vm_area_struct *vma)
> +{
> +	return -EPERM;
> +}
> +
> +static int intel_vgpu_dmabuf_mgr_fd_release(struct inode *inode,
> +		struct file *filp)
> +{
> +	struct intel_vgpu *vgpu = filp->private_data;
> +	struct intel_vgpu_dmabuf_obj *obj;
> +	struct list_head *pos;
> +
> +	if (WARN_ON(!vgpu->vdev.vfio_device))
> +		return -ENODEV;
> +
> +	list_for_each(pos, &vgpu->dmabuf_obj_list_head) {
> +		obj = container_of(pos, struct intel_vgpu_dmabuf_obj, list);
> +		if (WARN_ON(!obj))
> +			return -ENODEV;
> +		kfree(obj->obj->gvt_info);
> +		i915_gem_object_put(obj->obj);
> +		kfree(obj);
> +		kvmgt_put_vfio_device(vgpu);

Can we do this?  If I understand, we're releasing all the references
and allocations for the dmabuf fds on release of the manager fd.  What
happens if the user continues trying to access those dmabuf fds after
this?

> +	}
> +	kvmgt_put_vfio_device(vgpu);
> +
> +	return 0;
> +}
> +
> +static long intel_vgpu_dmabuf_mgr_fd_ioctl(struct file *filp,
> +		unsigned int ioctl, unsigned long arg)
> +{
> +	struct intel_vgpu *vgpu = filp->private_data;
> +	int minsz;
> +	int ret;
> +	struct fd f;
> +
> +	f = fdget(vgpu->dmabuf_mgr_fd);
> +	if (!f.file)
> +		return -EBADF;
> +
> +	if (ioctl == VFIO_DEVICE_QUERY_PLANE) {
> +		struct vfio_vgpu_plane_info info;
> +
> +		minsz = offsetofend(struct vfio_vgpu_plane_info, resv);
> +		if (copy_from_user(&info, (void __user *)arg, minsz)) {
> +			fdput(f);
> +			return -EFAULT;
> +		}
> +		if (info.argsz < minsz) {
> +			fdput(f);
> +			return -EINVAL;
> +		}
> +		ret = intel_gvt_ops->vgpu_query_plane(vgpu, &info);
> +		if (ret != 0) {
> +			fdput(f);
> +			gvt_vgpu_err("query plane failed:%d\n", ret);
> +			return -EINVAL;
> +		}
> +		fdput(f);
> +		return copy_to_user((void __user *)arg, &info, minsz) ?
> +								-EFAULT : 0;
> +	} else if (ioctl == VFIO_DEVICE_CREATE_DMABUF) {
> +		struct vfio_vgpu_dmabuf_info dmabuf;
> +
> +		minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);
> +		if (copy_from_user(&dmabuf, (void __user *)arg, minsz)) {
> +			fdput(f);
> +			return -EFAULT;
> +		}
> +		if (dmabuf.argsz < minsz) {
> +			fdput(f);
> +			return -EINVAL;
> +		}
> +		ret = kvmgt_get_vfio_device(vgpu);
> +		if (ret != 0)
> +			return ret;

Missed an fdput, though I'm not sure I understand the value of the
original fdget or the dmabuf_mgr_fd field at all.  dmabuf_mgr_fd is
only used here, presumably to add a reference to the fd while we're in
the ioctl, but we're in the ioctl function of that fd, so I think there
are already references elsewhere.

> +
> +		ret = intel_gvt_ops->vgpu_create_dmabuf(vgpu, &dmabuf);
> +		if (ret != 0) {
> +			kvmgt_put_vfio_device(vgpu);
> +			fdput(f);
> +			return -EINVAL;

Why not return the errno that vgpu_create_dmabuf provided?

> +		}
> +		fdput(f);
> +		return copy_to_user((void __user *)arg, &dmabuf, minsz) ?
> +								-EFAULT : 0;
> +	}
> +
> +	fdput(f);
> +	gvt_vgpu_err("unsupported dmabuf operation\n");
> +
> +	return -EINVAL;
> +}
> +
> +static const struct file_operations intel_vgpu_dmabuf_mgr_fd_ops = {
> +	.release        = intel_vgpu_dmabuf_mgr_fd_release,
> +	.unlocked_ioctl = intel_vgpu_dmabuf_mgr_fd_ioctl,
> +	.mmap           = intel_vgpu_dmabuf_mgr_fd_mmap,
> +	.llseek         = noop_llseek,
> +};
>  static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
>  {
>  	struct intel_vgpu *vgpu = NULL;
> @@ -1259,6 +1379,30 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
>  	} else if (cmd == VFIO_DEVICE_RESET) {
>  		intel_gvt_ops->vgpu_reset(vgpu);
>  		return 0;
> +	} else if (cmd == VFIO_DEVICE_GET_FD) {
> +		int fd;
> +		u32 type;
> +		int ret;
> +
> +		if (copy_from_user(&type, (void __user *)arg, sizeof(type)))
> +			return -EINVAL;
> +		if (type != VFIO_DEVICE_DMABUF_MGR_FD)
> +			return -EINVAL;
> +
> +		ret = kvmgt_get_vfio_device(vgpu);
> +		if (ret != 0)
> +			return ret;
> +
> +		fd = anon_inode_getfd("intel-vgpu-dmabuf-mgr-fd",
> +			&intel_vgpu_dmabuf_mgr_fd_ops,
> +			vgpu, O_RDWR | O_CLOEXEC);
> +		if (fd < 0) {
> +			gvt_vgpu_err("create dmabuf mgr fd failed\n");
> +			return -EINVAL;

Error path leaks vfio_device reference.

> +		}
> +		vgpu->dmabuf_mgr_fd = fd;

As above, unclear value of this field, additionally, what if the user
calls VFIO_DEVICE_GET_FD more than once?

> +
> +		return fd;
>  	}
>  
>  	return 0;
> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
> index 6e3cbd8..af6fc74 100644
> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
> @@ -346,6 +346,7 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
>  	vgpu->gvt = gvt;
>  	vgpu->sched_ctl.weight = param->weight;
>  	bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
> +	INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
>  
>  	intel_vgpu_init_cfg_space(vgpu, param->primary);
>  

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

* Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
@ 2017-06-01 18:08     ` Alex Williamson
  0 siblings, 0 replies; 74+ messages in thread
From: Alex Williamson @ 2017-06-01 18:08 UTC (permalink / raw)
  To: Xiaoguang Chen; +Cc: intel-gfx, linux-kernel, zhiyuan.lv, intel-gvt-dev, kraxel

On Sat, 27 May 2017 16:38:52 +0800
Xiaoguang Chen <xiaoguang.chen@intel.com> wrote:

> User space should create the management fd for the dma-buf operation first.
> Then user can query the plane information and create dma-buf if necessary
> using the management fd.
> 
> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
> ---
>  drivers/gpu/drm/i915/gvt/dmabuf.c |  12 ++++
>  drivers/gpu/drm/i915/gvt/dmabuf.h |   5 ++
>  drivers/gpu/drm/i915/gvt/gvt.c    |   2 +
>  drivers/gpu/drm/i915/gvt/gvt.h    |   5 ++
>  drivers/gpu/drm/i915/gvt/kvmgt.c  | 144 ++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/gvt/vgpu.c   |   1 +
>  6 files changed, 169 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
> index c831e91..9759e9a 100644
> --- a/drivers/gpu/drm/i915/gvt/dmabuf.c
> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
> @@ -226,6 +226,7 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args)
>  	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
>  	struct intel_vgpu_fb_info *fb_info;
>  	int ret;
> +	struct intel_vgpu_dmabuf_obj *dmabuf_obj;
>  
>  	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
>  	if (ret != 0)
> @@ -263,6 +264,17 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args)
>  		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
>  		return ret;
>  	}
> +	dmabuf_obj = kmalloc(sizeof(*dmabuf_obj), GFP_KERNEL);
> +	if (dmabuf_obj == NULL) {
> +		kfree(fb_info);
> +		i915_gem_object_put(obj);
> +		gvt_vgpu_err("alloc dmabuf_obj failed\n");
> +		return -ENOMEM;
> +	}
> +	dmabuf_obj->obj = obj;
> +	INIT_LIST_HEAD(&dmabuf_obj->list);
> +	list_add_tail(&dmabuf_obj->list, &vgpu->dmabuf_obj_list_head);
> +
>  	gvt_dmabuf->fd = ret;
>  
>  	return 0;
> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h b/drivers/gpu/drm/i915/gvt/dmabuf.h
> index 8be9979..cafa781 100644
> --- a/drivers/gpu/drm/i915/gvt/dmabuf.h
> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
> @@ -31,6 +31,11 @@ struct intel_vgpu_fb_info {
>  	uint32_t fb_size;
>  };
>  
> +struct intel_vgpu_dmabuf_obj {
> +	struct drm_i915_gem_object *obj;
> +	struct list_head list;
> +};
> +
>  int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);
>  int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args);
>  
> diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c
> index 2032917..dbc3f86 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.c
> +++ b/drivers/gpu/drm/i915/gvt/gvt.c
> @@ -54,6 +54,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {
>  	.vgpu_reset = intel_gvt_reset_vgpu,
>  	.vgpu_activate = intel_gvt_activate_vgpu,
>  	.vgpu_deactivate = intel_gvt_deactivate_vgpu,
> +	.vgpu_query_plane = intel_vgpu_query_plane,
> +	.vgpu_create_dmabuf = intel_vgpu_create_dmabuf,
>  };
>  
>  /**
> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
> index 763a8c5..a855797 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> @@ -185,8 +185,11 @@ struct intel_vgpu {
>  		struct kvm *kvm;
>  		struct work_struct release_work;
>  		atomic_t released;
> +		struct vfio_device *vfio_device;
>  	} vdev;
>  #endif
> +	int dmabuf_mgr_fd;
> +	struct list_head dmabuf_obj_list_head;
>  };
>  
>  struct intel_gvt_gm {
> @@ -467,6 +470,8 @@ struct intel_gvt_ops {
>  	void (*vgpu_reset)(struct intel_vgpu *);
>  	void (*vgpu_activate)(struct intel_vgpu *);
>  	void (*vgpu_deactivate)(struct intel_vgpu *);
> +	int (*vgpu_query_plane)(struct intel_vgpu *vgpu, void *);
> +	int (*vgpu_create_dmabuf)(struct intel_vgpu *vgpu, void *);
>  };
>  
>  
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 389f072..a079080 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -41,6 +41,7 @@
>  #include <linux/kvm_host.h>
>  #include <linux/vfio.h>
>  #include <linux/mdev.h>
> +#include <linux/anon_inodes.h>
>  
>  #include "i915_drv.h"
>  #include "gvt.h"
> @@ -524,6 +525,125 @@ static int intel_vgpu_reg_init_opregion(struct intel_vgpu *vgpu)
>  	return ret;
>  }
>  
> +static int kvmgt_get_vfio_device(struct intel_vgpu *vgpu)
> +{
> +	struct vfio_device *device;
> +
> +	device = vfio_device_get_from_dev(mdev_dev(vgpu->vdev.mdev));
> +	if (device == NULL)
> +		return -ENODEV;
> +	vgpu->vdev.vfio_device = device;
> +
> +	return 0;
> +}
> +
> +static void kvmgt_put_vfio_device(struct intel_vgpu *vgpu)
> +{
> +	vfio_device_put(vgpu->vdev.vfio_device);
> +}
> +
> +static int intel_vgpu_dmabuf_mgr_fd_mmap(struct file *file,
> +		struct vm_area_struct *vma)
> +{
> +	return -EPERM;
> +}
> +
> +static int intel_vgpu_dmabuf_mgr_fd_release(struct inode *inode,
> +		struct file *filp)
> +{
> +	struct intel_vgpu *vgpu = filp->private_data;
> +	struct intel_vgpu_dmabuf_obj *obj;
> +	struct list_head *pos;
> +
> +	if (WARN_ON(!vgpu->vdev.vfio_device))
> +		return -ENODEV;
> +
> +	list_for_each(pos, &vgpu->dmabuf_obj_list_head) {
> +		obj = container_of(pos, struct intel_vgpu_dmabuf_obj, list);
> +		if (WARN_ON(!obj))
> +			return -ENODEV;
> +		kfree(obj->obj->gvt_info);
> +		i915_gem_object_put(obj->obj);
> +		kfree(obj);
> +		kvmgt_put_vfio_device(vgpu);

Can we do this?  If I understand, we're releasing all the references
and allocations for the dmabuf fds on release of the manager fd.  What
happens if the user continues trying to access those dmabuf fds after
this?

> +	}
> +	kvmgt_put_vfio_device(vgpu);
> +
> +	return 0;
> +}
> +
> +static long intel_vgpu_dmabuf_mgr_fd_ioctl(struct file *filp,
> +		unsigned int ioctl, unsigned long arg)
> +{
> +	struct intel_vgpu *vgpu = filp->private_data;
> +	int minsz;
> +	int ret;
> +	struct fd f;
> +
> +	f = fdget(vgpu->dmabuf_mgr_fd);
> +	if (!f.file)
> +		return -EBADF;
> +
> +	if (ioctl == VFIO_DEVICE_QUERY_PLANE) {
> +		struct vfio_vgpu_plane_info info;
> +
> +		minsz = offsetofend(struct vfio_vgpu_plane_info, resv);
> +		if (copy_from_user(&info, (void __user *)arg, minsz)) {
> +			fdput(f);
> +			return -EFAULT;
> +		}
> +		if (info.argsz < minsz) {
> +			fdput(f);
> +			return -EINVAL;
> +		}
> +		ret = intel_gvt_ops->vgpu_query_plane(vgpu, &info);
> +		if (ret != 0) {
> +			fdput(f);
> +			gvt_vgpu_err("query plane failed:%d\n", ret);
> +			return -EINVAL;
> +		}
> +		fdput(f);
> +		return copy_to_user((void __user *)arg, &info, minsz) ?
> +								-EFAULT : 0;
> +	} else if (ioctl == VFIO_DEVICE_CREATE_DMABUF) {
> +		struct vfio_vgpu_dmabuf_info dmabuf;
> +
> +		minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);
> +		if (copy_from_user(&dmabuf, (void __user *)arg, minsz)) {
> +			fdput(f);
> +			return -EFAULT;
> +		}
> +		if (dmabuf.argsz < minsz) {
> +			fdput(f);
> +			return -EINVAL;
> +		}
> +		ret = kvmgt_get_vfio_device(vgpu);
> +		if (ret != 0)
> +			return ret;

Missed an fdput, though I'm not sure I understand the value of the
original fdget or the dmabuf_mgr_fd field at all.  dmabuf_mgr_fd is
only used here, presumably to add a reference to the fd while we're in
the ioctl, but we're in the ioctl function of that fd, so I think there
are already references elsewhere.

> +
> +		ret = intel_gvt_ops->vgpu_create_dmabuf(vgpu, &dmabuf);
> +		if (ret != 0) {
> +			kvmgt_put_vfio_device(vgpu);
> +			fdput(f);
> +			return -EINVAL;

Why not return the errno that vgpu_create_dmabuf provided?

> +		}
> +		fdput(f);
> +		return copy_to_user((void __user *)arg, &dmabuf, minsz) ?
> +								-EFAULT : 0;
> +	}
> +
> +	fdput(f);
> +	gvt_vgpu_err("unsupported dmabuf operation\n");
> +
> +	return -EINVAL;
> +}
> +
> +static const struct file_operations intel_vgpu_dmabuf_mgr_fd_ops = {
> +	.release        = intel_vgpu_dmabuf_mgr_fd_release,
> +	.unlocked_ioctl = intel_vgpu_dmabuf_mgr_fd_ioctl,
> +	.mmap           = intel_vgpu_dmabuf_mgr_fd_mmap,
> +	.llseek         = noop_llseek,
> +};
>  static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
>  {
>  	struct intel_vgpu *vgpu = NULL;
> @@ -1259,6 +1379,30 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
>  	} else if (cmd == VFIO_DEVICE_RESET) {
>  		intel_gvt_ops->vgpu_reset(vgpu);
>  		return 0;
> +	} else if (cmd == VFIO_DEVICE_GET_FD) {
> +		int fd;
> +		u32 type;
> +		int ret;
> +
> +		if (copy_from_user(&type, (void __user *)arg, sizeof(type)))
> +			return -EINVAL;
> +		if (type != VFIO_DEVICE_DMABUF_MGR_FD)
> +			return -EINVAL;
> +
> +		ret = kvmgt_get_vfio_device(vgpu);
> +		if (ret != 0)
> +			return ret;
> +
> +		fd = anon_inode_getfd("intel-vgpu-dmabuf-mgr-fd",
> +			&intel_vgpu_dmabuf_mgr_fd_ops,
> +			vgpu, O_RDWR | O_CLOEXEC);
> +		if (fd < 0) {
> +			gvt_vgpu_err("create dmabuf mgr fd failed\n");
> +			return -EINVAL;

Error path leaks vfio_device reference.

> +		}
> +		vgpu->dmabuf_mgr_fd = fd;

As above, unclear value of this field, additionally, what if the user
calls VFIO_DEVICE_GET_FD more than once?

> +
> +		return fd;
>  	}
>  
>  	return 0;
> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
> index 6e3cbd8..af6fc74 100644
> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
> @@ -346,6 +346,7 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
>  	vgpu->gvt = gvt;
>  	vgpu->sched_ctl.weight = param->weight;
>  	bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
> +	INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
>  
>  	intel_vgpu_init_cfg_space(vgpu, param->primary);
>  

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
  2017-06-01 16:38             ` Alex Williamson
@ 2017-06-01 18:46               ` Kirti Wankhede
  -1 siblings, 0 replies; 74+ messages in thread
From: Kirti Wankhede @ 2017-06-01 18:46 UTC (permalink / raw)
  To: Alex Williamson, Chen, Xiaoguang
  Cc: Gerd Hoffmann, chris, intel-gfx, linux-kernel, zhenyuw, Lv,
	Zhiyuan, intel-gvt-dev, Wang, Zhi A, Tian, Kevin



On 6/1/2017 10:08 PM, Alex Williamson wrote:
> On Thu, 1 Jun 2017 03:01:28 +0000
> "Chen, Xiaoguang" <xiaoguang.chen@intel.com> wrote:
> 
>> Hi Kirti,
>>
>>> -----Original Message-----
>>> From: Kirti Wankhede [mailto:kwankhede@nvidia.com]
>>> Sent: Thursday, June 01, 2017 1:23 AM
>>> To: Chen, Xiaoguang <xiaoguang.chen@intel.com>; Gerd Hoffmann
>>> <kraxel@redhat.com>; alex.williamson@redhat.com; chris@chris-wilson.co.uk;
>>> intel-gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>>> zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>>> dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
>>> <kevin.tian@intel.com>
>>> Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
>>>
>>>
>>>
>>> On 5/31/2017 11:48 AM, Chen, Xiaoguang wrote:  
>>>> Hi,
>>>>  
>>>>> -----Original Message-----
>>>>> From: Gerd Hoffmann [mailto:kraxel@redhat.com]
>>>>> Sent: Monday, May 29, 2017 3:20 PM
>>>>> To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
>>>>> alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
>>>>> gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>>>>> zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>;
>>>>> intel-gvt- dev@lists.freedesktop.org; Wang, Zhi A
>>>>> <zhi.a.wang@intel.com>; Tian, Kevin <kevin.tian@intel.com>
>>>>> Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf
>>>>> operations
>>>>>  
>>>>>> +struct vfio_vgpu_dmabuf_info {
>>>>>> +	__u32 argsz;
>>>>>> +	__u32 flags;
>>>>>> +	struct vfio_vgpu_plane_info plane_info;
>>>>>> +	__s32 fd;
>>>>>> +	__u32 pad;
>>>>>> +};  
>>>>>
>>>>> Hmm, now you have argsz and flags twice in vfio_vgpu_dmabuf_info ...
>>>>>
>>>>> I think we should have something like this:
>>>>>
>>>>> struct vfio_vgpu_plane_info {
>>>>>         __u64 start;
>>>>>         __u64 drm_format_mod;
>>>>>         __u32 drm_format;
>>>>>         __u32 width;
>>>>>         __u32 height;
>>>>>         __u32 stride;
>>>>>         __u32 size;
>>>>>         __u32 x_pos;
>>>>>         __u32 y_pos;
>>>>>        __u32 padding;
>>>>> };
>>>>>
>>>>> struct vfio_vgpu_query_plane {
>>>>> 	__u32 argsz;
>>>>> 	__u32 flags;
>>>>> 	struct vfio_vgpu_plane_info plane_info;
>>>>>        __u32 plane_id;
>>>>>        __u32 padding;
>>>>> };
>>>>>
>>>>> struct vfio_vgpu_create_dmabuf {
>>>>> 	__u32 argsz;
>>>>> 	__u32 flags;
>>>>> 	struct vfio_vgpu_plane_info plane_info;
>>>>>        __u32 plane_id;
>>>>>        __s32 fd;
>>>>> };  
>>>> Good suggestion will apply in the next version.
>>>> Thanks for review :)
>>>>  
>>>
>>> Can you define what are the expected values of 'flags' would be?  
>> Flags is not used in this case.  It is defined to follow the rules of vfio ioctls.
> 
> An important note about flags, the vendor driver must validate it.  If
> they don't and the user passes an arbitrary value there, then we have a
> backwards compatibility issue with ever attempting to use the flags
> field.  The user passing in a flag unknown to the vendor driver should
> return an -EINVAL response.  In this case, we haven't defined any
> flags, so the vendor driver needs to force the user to pass zero.

There are two ways QEMU can get surface for console:
1. adding a region using region capability
2. dmabuf

In both the above case surface parameters need to be queried from vendor
driver are same. The structure would be :

struct vfio_vgpu_surface_info {
        __u64 start;
        __u32 width;
        __u32 height;
        __u32 stride;
        __u32 size;
        __u32 x_pos;
        __u32 y_pos;
        __u32 padding;
        /* Only used when VFIO_VGPU_SURFACE_DMABUF_* flags set */
        __u64 drm_format_mod;
        __u32 drm_format;
};

We can use one ioctl to query surface information from vendor driver,
structure would look like:

struct vfio_vgpu_get_surface_info{
	__u32 argsz;
	__u32 flags;
#define VFIO_VGPU_SURFACE_DMABUF_CREATE	(1 << 0) /* Create dmabuf */
#define VFIO_VGPU_SURFACE_DMABUF_QUERY	(1 << 1) /* Query surface info
for dmabuf */
#define VFIO_VGPU_SURFACE_REGION_QUERY	(1 << 2) /* Query surface info
for REGION type  */
	struct vfio_vgpu_surface_info surface;
        __u32 plane_id;
        __s32 fd;
};

#define VFIO_DEVICE_SURFACE_INFO _IO(VFIO_TYPE, VFIO_BASE + 15)

Vendor driver should return -EINVAL, if that type of query is not
supported.

I would like to design this interface to support both type, region cap
and dmabuf.

Thanks,
Kirti

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
@ 2017-06-01 18:46               ` Kirti Wankhede
  0 siblings, 0 replies; 74+ messages in thread
From: Kirti Wankhede @ 2017-06-01 18:46 UTC (permalink / raw)
  To: Alex Williamson, Chen, Xiaoguang
  Cc: intel-gfx, linux-kernel, Lv, Zhiyuan, intel-gvt-dev, Gerd Hoffmann



On 6/1/2017 10:08 PM, Alex Williamson wrote:
> On Thu, 1 Jun 2017 03:01:28 +0000
> "Chen, Xiaoguang" <xiaoguang.chen@intel.com> wrote:
> 
>> Hi Kirti,
>>
>>> -----Original Message-----
>>> From: Kirti Wankhede [mailto:kwankhede@nvidia.com]
>>> Sent: Thursday, June 01, 2017 1:23 AM
>>> To: Chen, Xiaoguang <xiaoguang.chen@intel.com>; Gerd Hoffmann
>>> <kraxel@redhat.com>; alex.williamson@redhat.com; chris@chris-wilson.co.uk;
>>> intel-gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>>> zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>>> dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
>>> <kevin.tian@intel.com>
>>> Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
>>>
>>>
>>>
>>> On 5/31/2017 11:48 AM, Chen, Xiaoguang wrote:  
>>>> Hi,
>>>>  
>>>>> -----Original Message-----
>>>>> From: Gerd Hoffmann [mailto:kraxel@redhat.com]
>>>>> Sent: Monday, May 29, 2017 3:20 PM
>>>>> To: Chen, Xiaoguang <xiaoguang.chen@intel.com>;
>>>>> alex.williamson@redhat.com; chris@chris-wilson.co.uk; intel-
>>>>> gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>>>>> zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>;
>>>>> intel-gvt- dev@lists.freedesktop.org; Wang, Zhi A
>>>>> <zhi.a.wang@intel.com>; Tian, Kevin <kevin.tian@intel.com>
>>>>> Subject: Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf
>>>>> operations
>>>>>  
>>>>>> +struct vfio_vgpu_dmabuf_info {
>>>>>> +	__u32 argsz;
>>>>>> +	__u32 flags;
>>>>>> +	struct vfio_vgpu_plane_info plane_info;
>>>>>> +	__s32 fd;
>>>>>> +	__u32 pad;
>>>>>> +};  
>>>>>
>>>>> Hmm, now you have argsz and flags twice in vfio_vgpu_dmabuf_info ...
>>>>>
>>>>> I think we should have something like this:
>>>>>
>>>>> struct vfio_vgpu_plane_info {
>>>>>         __u64 start;
>>>>>         __u64 drm_format_mod;
>>>>>         __u32 drm_format;
>>>>>         __u32 width;
>>>>>         __u32 height;
>>>>>         __u32 stride;
>>>>>         __u32 size;
>>>>>         __u32 x_pos;
>>>>>         __u32 y_pos;
>>>>>        __u32 padding;
>>>>> };
>>>>>
>>>>> struct vfio_vgpu_query_plane {
>>>>> 	__u32 argsz;
>>>>> 	__u32 flags;
>>>>> 	struct vfio_vgpu_plane_info plane_info;
>>>>>        __u32 plane_id;
>>>>>        __u32 padding;
>>>>> };
>>>>>
>>>>> struct vfio_vgpu_create_dmabuf {
>>>>> 	__u32 argsz;
>>>>> 	__u32 flags;
>>>>> 	struct vfio_vgpu_plane_info plane_info;
>>>>>        __u32 plane_id;
>>>>>        __s32 fd;
>>>>> };  
>>>> Good suggestion will apply in the next version.
>>>> Thanks for review :)
>>>>  
>>>
>>> Can you define what are the expected values of 'flags' would be?  
>> Flags is not used in this case.  It is defined to follow the rules of vfio ioctls.
> 
> An important note about flags, the vendor driver must validate it.  If
> they don't and the user passes an arbitrary value there, then we have a
> backwards compatibility issue with ever attempting to use the flags
> field.  The user passing in a flag unknown to the vendor driver should
> return an -EINVAL response.  In this case, we haven't defined any
> flags, so the vendor driver needs to force the user to pass zero.

There are two ways QEMU can get surface for console:
1. adding a region using region capability
2. dmabuf

In both the above case surface parameters need to be queried from vendor
driver are same. The structure would be :

struct vfio_vgpu_surface_info {
        __u64 start;
        __u32 width;
        __u32 height;
        __u32 stride;
        __u32 size;
        __u32 x_pos;
        __u32 y_pos;
        __u32 padding;
        /* Only used when VFIO_VGPU_SURFACE_DMABUF_* flags set */
        __u64 drm_format_mod;
        __u32 drm_format;
};

We can use one ioctl to query surface information from vendor driver,
structure would look like:

struct vfio_vgpu_get_surface_info{
	__u32 argsz;
	__u32 flags;
#define VFIO_VGPU_SURFACE_DMABUF_CREATE	(1 << 0) /* Create dmabuf */
#define VFIO_VGPU_SURFACE_DMABUF_QUERY	(1 << 1) /* Query surface info
for dmabuf */
#define VFIO_VGPU_SURFACE_REGION_QUERY	(1 << 2) /* Query surface info
for REGION type  */
	struct vfio_vgpu_surface_info surface;
        __u32 plane_id;
        __s32 fd;
};

#define VFIO_DEVICE_SURFACE_INFO _IO(VFIO_TYPE, VFIO_BASE + 15)

Vendor driver should return -EINVAL, if that type of query is not
supported.

I would like to design this interface to support both type, region cap
and dmabuf.

Thanks,
Kirti
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* RE: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
  2017-06-01 18:08     ` Alex Williamson
@ 2017-06-02  3:24       ` Chen, Xiaoguang
  -1 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-06-02  3:24 UTC (permalink / raw)
  To: Alex Williamson
  Cc: kraxel, chris, intel-gfx, linux-kernel, zhenyuw, Lv, Zhiyuan,
	intel-gvt-dev, Wang, Zhi A, Tian, Kevin

Hi Alex,

>-----Original Message-----
>From: Alex Williamson [mailto:alex.williamson@redhat.com]
>Sent: Friday, June 02, 2017 2:08 AM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
>Cc: kraxel@redhat.com; chris@chris-wilson.co.uk; intel-
>gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get
>the dma-buf
>
>On Sat, 27 May 2017 16:38:52 +0800
>Xiaoguang Chen <xiaoguang.chen@intel.com> wrote:
>
>> User space should create the management fd for the dma-buf operation first.
>> Then user can query the plane information and create dma-buf if
>> necessary using the management fd.
>>
>> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
>> ---
>>  drivers/gpu/drm/i915/gvt/dmabuf.c |  12 ++++
>>  drivers/gpu/drm/i915/gvt/dmabuf.h |   5 ++
>>  drivers/gpu/drm/i915/gvt/gvt.c    |   2 +
>>  drivers/gpu/drm/i915/gvt/gvt.h    |   5 ++
>>  drivers/gpu/drm/i915/gvt/kvmgt.c  | 144
>++++++++++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/i915/gvt/vgpu.c   |   1 +
>>  6 files changed, 169 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c
>> b/drivers/gpu/drm/i915/gvt/dmabuf.c
>> index c831e91..9759e9a 100644
>> --- a/drivers/gpu/drm/i915/gvt/dmabuf.c
>> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
>> @@ -226,6 +226,7 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu,
>void *args)
>>  	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
>>  	struct intel_vgpu_fb_info *fb_info;
>>  	int ret;
>> +	struct intel_vgpu_dmabuf_obj *dmabuf_obj;
>>
>>  	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
>>  	if (ret != 0)
>> @@ -263,6 +264,17 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu,
>void *args)
>>  		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
>>  		return ret;
>>  	}
>> +	dmabuf_obj = kmalloc(sizeof(*dmabuf_obj), GFP_KERNEL);
>> +	if (dmabuf_obj == NULL) {
>> +		kfree(fb_info);
>> +		i915_gem_object_put(obj);
>> +		gvt_vgpu_err("alloc dmabuf_obj failed\n");
>> +		return -ENOMEM;
>> +	}
>> +	dmabuf_obj->obj = obj;
>> +	INIT_LIST_HEAD(&dmabuf_obj->list);
>> +	list_add_tail(&dmabuf_obj->list, &vgpu->dmabuf_obj_list_head);
>> +
>>  	gvt_dmabuf->fd = ret;
>>
>>  	return 0;
>> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h
>> b/drivers/gpu/drm/i915/gvt/dmabuf.h
>> index 8be9979..cafa781 100644
>> --- a/drivers/gpu/drm/i915/gvt/dmabuf.h
>> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
>> @@ -31,6 +31,11 @@ struct intel_vgpu_fb_info {
>>  	uint32_t fb_size;
>>  };
>>
>> +struct intel_vgpu_dmabuf_obj {
>> +	struct drm_i915_gem_object *obj;
>> +	struct list_head list;
>> +};
>> +
>>  int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);  int
>> intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args);
>>
>> diff --git a/drivers/gpu/drm/i915/gvt/gvt.c
>> b/drivers/gpu/drm/i915/gvt/gvt.c index 2032917..dbc3f86 100644
>> --- a/drivers/gpu/drm/i915/gvt/gvt.c
>> +++ b/drivers/gpu/drm/i915/gvt/gvt.c
>> @@ -54,6 +54,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {
>>  	.vgpu_reset = intel_gvt_reset_vgpu,
>>  	.vgpu_activate = intel_gvt_activate_vgpu,
>>  	.vgpu_deactivate = intel_gvt_deactivate_vgpu,
>> +	.vgpu_query_plane = intel_vgpu_query_plane,
>> +	.vgpu_create_dmabuf = intel_vgpu_create_dmabuf,
>>  };
>>
>>  /**
>> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h
>> b/drivers/gpu/drm/i915/gvt/gvt.h index 763a8c5..a855797 100644
>> --- a/drivers/gpu/drm/i915/gvt/gvt.h
>> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
>> @@ -185,8 +185,11 @@ struct intel_vgpu {
>>  		struct kvm *kvm;
>>  		struct work_struct release_work;
>>  		atomic_t released;
>> +		struct vfio_device *vfio_device;
>>  	} vdev;
>>  #endif
>> +	int dmabuf_mgr_fd;
>> +	struct list_head dmabuf_obj_list_head;
>>  };
>>
>>  struct intel_gvt_gm {
>> @@ -467,6 +470,8 @@ struct intel_gvt_ops {
>>  	void (*vgpu_reset)(struct intel_vgpu *);
>>  	void (*vgpu_activate)(struct intel_vgpu *);
>>  	void (*vgpu_deactivate)(struct intel_vgpu *);
>> +	int (*vgpu_query_plane)(struct intel_vgpu *vgpu, void *);
>> +	int (*vgpu_create_dmabuf)(struct intel_vgpu *vgpu, void *);
>>  };
>>
>>
>> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
>> b/drivers/gpu/drm/i915/gvt/kvmgt.c
>> index 389f072..a079080 100644
>> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
>> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
>> @@ -41,6 +41,7 @@
>>  #include <linux/kvm_host.h>
>>  #include <linux/vfio.h>
>>  #include <linux/mdev.h>
>> +#include <linux/anon_inodes.h>
>>
>>  #include "i915_drv.h"
>>  #include "gvt.h"
>> @@ -524,6 +525,125 @@ static int intel_vgpu_reg_init_opregion(struct
>intel_vgpu *vgpu)
>>  	return ret;
>>  }
>>
>> +static int kvmgt_get_vfio_device(struct intel_vgpu *vgpu) {
>> +	struct vfio_device *device;
>> +
>> +	device = vfio_device_get_from_dev(mdev_dev(vgpu->vdev.mdev));
>> +	if (device == NULL)
>> +		return -ENODEV;
>> +	vgpu->vdev.vfio_device = device;
>> +
>> +	return 0;
>> +}
>> +
>> +static void kvmgt_put_vfio_device(struct intel_vgpu *vgpu) {
>> +	vfio_device_put(vgpu->vdev.vfio_device);
>> +}
>> +
>> +static int intel_vgpu_dmabuf_mgr_fd_mmap(struct file *file,
>> +		struct vm_area_struct *vma)
>> +{
>> +	return -EPERM;
>> +}
>> +
>> +static int intel_vgpu_dmabuf_mgr_fd_release(struct inode *inode,
>> +		struct file *filp)
>> +{
>> +	struct intel_vgpu *vgpu = filp->private_data;
>> +	struct intel_vgpu_dmabuf_obj *obj;
>> +	struct list_head *pos;
>> +
>> +	if (WARN_ON(!vgpu->vdev.vfio_device))
>> +		return -ENODEV;
>> +
>> +	list_for_each(pos, &vgpu->dmabuf_obj_list_head) {
>> +		obj = container_of(pos, struct intel_vgpu_dmabuf_obj, list);
>> +		if (WARN_ON(!obj))
>> +			return -ENODEV;
>> +		kfree(obj->obj->gvt_info);
>> +		i915_gem_object_put(obj->obj);
>> +		kfree(obj);
>> +		kvmgt_put_vfio_device(vgpu);
>
>Can we do this?  If I understand, we're releasing all the references and allocations
>for the dmabuf fds on release of the manager fd.  What happens if the user
>continues trying to access those dmabuf fds after this?
I think we can do this here.
The dma-buf's release function dma_buf_release() will be called by kernel which means all the created dmabufs will be invalid even we do not release all the references and allocations here.

>
>> +	}
>> +	kvmgt_put_vfio_device(vgpu);
>> +
>> +	return 0;
>> +}
>> +
>> +static long intel_vgpu_dmabuf_mgr_fd_ioctl(struct file *filp,
>> +		unsigned int ioctl, unsigned long arg) {
>> +	struct intel_vgpu *vgpu = filp->private_data;
>> +	int minsz;
>> +	int ret;
>> +	struct fd f;
>> +
>> +	f = fdget(vgpu->dmabuf_mgr_fd);
>> +	if (!f.file)
>> +		return -EBADF;
>> +
>> +	if (ioctl == VFIO_DEVICE_QUERY_PLANE) {
>> +		struct vfio_vgpu_plane_info info;
>> +
>> +		minsz = offsetofend(struct vfio_vgpu_plane_info, resv);
>> +		if (copy_from_user(&info, (void __user *)arg, minsz)) {
>> +			fdput(f);
>> +			return -EFAULT;
>> +		}
>> +		if (info.argsz < minsz) {
>> +			fdput(f);
>> +			return -EINVAL;
>> +		}
>> +		ret = intel_gvt_ops->vgpu_query_plane(vgpu, &info);
>> +		if (ret != 0) {
>> +			fdput(f);
>> +			gvt_vgpu_err("query plane failed:%d\n", ret);
>> +			return -EINVAL;
>> +		}
>> +		fdput(f);
>> +		return copy_to_user((void __user *)arg, &info, minsz) ?
>> +								-EFAULT : 0;
>> +	} else if (ioctl == VFIO_DEVICE_CREATE_DMABUF) {
>> +		struct vfio_vgpu_dmabuf_info dmabuf;
>> +
>> +		minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);
>> +		if (copy_from_user(&dmabuf, (void __user *)arg, minsz)) {
>> +			fdput(f);
>> +			return -EFAULT;
>> +		}
>> +		if (dmabuf.argsz < minsz) {
>> +			fdput(f);
>> +			return -EINVAL;
>> +		}
>> +		ret = kvmgt_get_vfio_device(vgpu);
>> +		if (ret != 0)
>> +			return ret;
>
>Missed an fdput, though I'm not sure I understand the value of the original fdget
>or the dmabuf_mgr_fd field at all.  dmabuf_mgr_fd is only used here, presumably
>to add a reference to the fd while we're in the ioctl, but we're in the ioctl function
>of that fd, so I think there are already references elsewhere.
Make sense. Fdget/fdput can be removed.

>
>> +
>> +		ret = intel_gvt_ops->vgpu_create_dmabuf(vgpu, &dmabuf);
>> +		if (ret != 0) {
>> +			kvmgt_put_vfio_device(vgpu);
>> +			fdput(f);
>> +			return -EINVAL;
>
>Why not return the errno that vgpu_create_dmabuf provided?
Will change to use the returned errno.

>
>> +		}
>> +		fdput(f);
>> +		return copy_to_user((void __user *)arg, &dmabuf, minsz) ?
>> +								-EFAULT : 0;
>> +	}
>> +
>> +	fdput(f);
>> +	gvt_vgpu_err("unsupported dmabuf operation\n");
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static const struct file_operations intel_vgpu_dmabuf_mgr_fd_ops = {
>> +	.release        = intel_vgpu_dmabuf_mgr_fd_release,
>> +	.unlocked_ioctl = intel_vgpu_dmabuf_mgr_fd_ioctl,
>> +	.mmap           = intel_vgpu_dmabuf_mgr_fd_mmap,
>> +	.llseek         = noop_llseek,
>> +};
>>  static int intel_vgpu_create(struct kobject *kobj, struct mdev_device
>> *mdev)  {
>>  	struct intel_vgpu *vgpu = NULL;
>> @@ -1259,6 +1379,30 @@ static long intel_vgpu_ioctl(struct mdev_device
>*mdev, unsigned int cmd,
>>  	} else if (cmd == VFIO_DEVICE_RESET) {
>>  		intel_gvt_ops->vgpu_reset(vgpu);
>>  		return 0;
>> +	} else if (cmd == VFIO_DEVICE_GET_FD) {
>> +		int fd;
>> +		u32 type;
>> +		int ret;
>> +
>> +		if (copy_from_user(&type, (void __user *)arg, sizeof(type)))
>> +			return -EINVAL;
>> +		if (type != VFIO_DEVICE_DMABUF_MGR_FD)
>> +			return -EINVAL;
>> +
>> +		ret = kvmgt_get_vfio_device(vgpu);
>> +		if (ret != 0)
>> +			return ret;
>> +
>> +		fd = anon_inode_getfd("intel-vgpu-dmabuf-mgr-fd",
>> +			&intel_vgpu_dmabuf_mgr_fd_ops,
>> +			vgpu, O_RDWR | O_CLOEXEC);
>> +		if (fd < 0) {
>> +			gvt_vgpu_err("create dmabuf mgr fd failed\n");
>> +			return -EINVAL;
>
>Error path leaks vfio_device reference.
Will correct in the next version.

>
>> +		}
>> +		vgpu->dmabuf_mgr_fd = fd;
>
>As above, unclear value of this field, additionally, what if the user calls
>VFIO_DEVICE_GET_FD more than once?
Ah, good question.
VFIO_DEVICE_GET_FD should only be called once.
And we should add a check if the vgpu->dmabuf_mgr_fd is not 0 which means VFIO_DEVICE_GET_FD had been called before we should return an error.

>
>> +
>> +		return fd;
>>  	}
>>
>>  	return 0;
>> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c
>> b/drivers/gpu/drm/i915/gvt/vgpu.c index 6e3cbd8..af6fc74 100644
>> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
>> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
>> @@ -346,6 +346,7 @@ static struct intel_vgpu
>*__intel_gvt_create_vgpu(struct intel_gvt *gvt,
>>  	vgpu->gvt = gvt;
>>  	vgpu->sched_ctl.weight = param->weight;
>>  	bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
>> +	INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
>>
>>  	intel_vgpu_init_cfg_space(vgpu, param->primary);
>>

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

* Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
@ 2017-06-02  3:24       ` Chen, Xiaoguang
  0 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-06-02  3:24 UTC (permalink / raw)
  To: Alex Williamson
  Cc: intel-gfx, linux-kernel, Lv, Zhiyuan, intel-gvt-dev, kraxel

Hi Alex,

>-----Original Message-----
>From: Alex Williamson [mailto:alex.williamson@redhat.com]
>Sent: Friday, June 02, 2017 2:08 AM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
>Cc: kraxel@redhat.com; chris@chris-wilson.co.uk; intel-
>gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get
>the dma-buf
>
>On Sat, 27 May 2017 16:38:52 +0800
>Xiaoguang Chen <xiaoguang.chen@intel.com> wrote:
>
>> User space should create the management fd for the dma-buf operation first.
>> Then user can query the plane information and create dma-buf if
>> necessary using the management fd.
>>
>> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
>> ---
>>  drivers/gpu/drm/i915/gvt/dmabuf.c |  12 ++++
>>  drivers/gpu/drm/i915/gvt/dmabuf.h |   5 ++
>>  drivers/gpu/drm/i915/gvt/gvt.c    |   2 +
>>  drivers/gpu/drm/i915/gvt/gvt.h    |   5 ++
>>  drivers/gpu/drm/i915/gvt/kvmgt.c  | 144
>++++++++++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/i915/gvt/vgpu.c   |   1 +
>>  6 files changed, 169 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c
>> b/drivers/gpu/drm/i915/gvt/dmabuf.c
>> index c831e91..9759e9a 100644
>> --- a/drivers/gpu/drm/i915/gvt/dmabuf.c
>> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
>> @@ -226,6 +226,7 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu,
>void *args)
>>  	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
>>  	struct intel_vgpu_fb_info *fb_info;
>>  	int ret;
>> +	struct intel_vgpu_dmabuf_obj *dmabuf_obj;
>>
>>  	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
>>  	if (ret != 0)
>> @@ -263,6 +264,17 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu,
>void *args)
>>  		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
>>  		return ret;
>>  	}
>> +	dmabuf_obj = kmalloc(sizeof(*dmabuf_obj), GFP_KERNEL);
>> +	if (dmabuf_obj == NULL) {
>> +		kfree(fb_info);
>> +		i915_gem_object_put(obj);
>> +		gvt_vgpu_err("alloc dmabuf_obj failed\n");
>> +		return -ENOMEM;
>> +	}
>> +	dmabuf_obj->obj = obj;
>> +	INIT_LIST_HEAD(&dmabuf_obj->list);
>> +	list_add_tail(&dmabuf_obj->list, &vgpu->dmabuf_obj_list_head);
>> +
>>  	gvt_dmabuf->fd = ret;
>>
>>  	return 0;
>> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h
>> b/drivers/gpu/drm/i915/gvt/dmabuf.h
>> index 8be9979..cafa781 100644
>> --- a/drivers/gpu/drm/i915/gvt/dmabuf.h
>> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
>> @@ -31,6 +31,11 @@ struct intel_vgpu_fb_info {
>>  	uint32_t fb_size;
>>  };
>>
>> +struct intel_vgpu_dmabuf_obj {
>> +	struct drm_i915_gem_object *obj;
>> +	struct list_head list;
>> +};
>> +
>>  int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);  int
>> intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args);
>>
>> diff --git a/drivers/gpu/drm/i915/gvt/gvt.c
>> b/drivers/gpu/drm/i915/gvt/gvt.c index 2032917..dbc3f86 100644
>> --- a/drivers/gpu/drm/i915/gvt/gvt.c
>> +++ b/drivers/gpu/drm/i915/gvt/gvt.c
>> @@ -54,6 +54,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {
>>  	.vgpu_reset = intel_gvt_reset_vgpu,
>>  	.vgpu_activate = intel_gvt_activate_vgpu,
>>  	.vgpu_deactivate = intel_gvt_deactivate_vgpu,
>> +	.vgpu_query_plane = intel_vgpu_query_plane,
>> +	.vgpu_create_dmabuf = intel_vgpu_create_dmabuf,
>>  };
>>
>>  /**
>> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h
>> b/drivers/gpu/drm/i915/gvt/gvt.h index 763a8c5..a855797 100644
>> --- a/drivers/gpu/drm/i915/gvt/gvt.h
>> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
>> @@ -185,8 +185,11 @@ struct intel_vgpu {
>>  		struct kvm *kvm;
>>  		struct work_struct release_work;
>>  		atomic_t released;
>> +		struct vfio_device *vfio_device;
>>  	} vdev;
>>  #endif
>> +	int dmabuf_mgr_fd;
>> +	struct list_head dmabuf_obj_list_head;
>>  };
>>
>>  struct intel_gvt_gm {
>> @@ -467,6 +470,8 @@ struct intel_gvt_ops {
>>  	void (*vgpu_reset)(struct intel_vgpu *);
>>  	void (*vgpu_activate)(struct intel_vgpu *);
>>  	void (*vgpu_deactivate)(struct intel_vgpu *);
>> +	int (*vgpu_query_plane)(struct intel_vgpu *vgpu, void *);
>> +	int (*vgpu_create_dmabuf)(struct intel_vgpu *vgpu, void *);
>>  };
>>
>>
>> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
>> b/drivers/gpu/drm/i915/gvt/kvmgt.c
>> index 389f072..a079080 100644
>> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
>> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
>> @@ -41,6 +41,7 @@
>>  #include <linux/kvm_host.h>
>>  #include <linux/vfio.h>
>>  #include <linux/mdev.h>
>> +#include <linux/anon_inodes.h>
>>
>>  #include "i915_drv.h"
>>  #include "gvt.h"
>> @@ -524,6 +525,125 @@ static int intel_vgpu_reg_init_opregion(struct
>intel_vgpu *vgpu)
>>  	return ret;
>>  }
>>
>> +static int kvmgt_get_vfio_device(struct intel_vgpu *vgpu) {
>> +	struct vfio_device *device;
>> +
>> +	device = vfio_device_get_from_dev(mdev_dev(vgpu->vdev.mdev));
>> +	if (device == NULL)
>> +		return -ENODEV;
>> +	vgpu->vdev.vfio_device = device;
>> +
>> +	return 0;
>> +}
>> +
>> +static void kvmgt_put_vfio_device(struct intel_vgpu *vgpu) {
>> +	vfio_device_put(vgpu->vdev.vfio_device);
>> +}
>> +
>> +static int intel_vgpu_dmabuf_mgr_fd_mmap(struct file *file,
>> +		struct vm_area_struct *vma)
>> +{
>> +	return -EPERM;
>> +}
>> +
>> +static int intel_vgpu_dmabuf_mgr_fd_release(struct inode *inode,
>> +		struct file *filp)
>> +{
>> +	struct intel_vgpu *vgpu = filp->private_data;
>> +	struct intel_vgpu_dmabuf_obj *obj;
>> +	struct list_head *pos;
>> +
>> +	if (WARN_ON(!vgpu->vdev.vfio_device))
>> +		return -ENODEV;
>> +
>> +	list_for_each(pos, &vgpu->dmabuf_obj_list_head) {
>> +		obj = container_of(pos, struct intel_vgpu_dmabuf_obj, list);
>> +		if (WARN_ON(!obj))
>> +			return -ENODEV;
>> +		kfree(obj->obj->gvt_info);
>> +		i915_gem_object_put(obj->obj);
>> +		kfree(obj);
>> +		kvmgt_put_vfio_device(vgpu);
>
>Can we do this?  If I understand, we're releasing all the references and allocations
>for the dmabuf fds on release of the manager fd.  What happens if the user
>continues trying to access those dmabuf fds after this?
I think we can do this here.
The dma-buf's release function dma_buf_release() will be called by kernel which means all the created dmabufs will be invalid even we do not release all the references and allocations here.

>
>> +	}
>> +	kvmgt_put_vfio_device(vgpu);
>> +
>> +	return 0;
>> +}
>> +
>> +static long intel_vgpu_dmabuf_mgr_fd_ioctl(struct file *filp,
>> +		unsigned int ioctl, unsigned long arg) {
>> +	struct intel_vgpu *vgpu = filp->private_data;
>> +	int minsz;
>> +	int ret;
>> +	struct fd f;
>> +
>> +	f = fdget(vgpu->dmabuf_mgr_fd);
>> +	if (!f.file)
>> +		return -EBADF;
>> +
>> +	if (ioctl == VFIO_DEVICE_QUERY_PLANE) {
>> +		struct vfio_vgpu_plane_info info;
>> +
>> +		minsz = offsetofend(struct vfio_vgpu_plane_info, resv);
>> +		if (copy_from_user(&info, (void __user *)arg, minsz)) {
>> +			fdput(f);
>> +			return -EFAULT;
>> +		}
>> +		if (info.argsz < minsz) {
>> +			fdput(f);
>> +			return -EINVAL;
>> +		}
>> +		ret = intel_gvt_ops->vgpu_query_plane(vgpu, &info);
>> +		if (ret != 0) {
>> +			fdput(f);
>> +			gvt_vgpu_err("query plane failed:%d\n", ret);
>> +			return -EINVAL;
>> +		}
>> +		fdput(f);
>> +		return copy_to_user((void __user *)arg, &info, minsz) ?
>> +								-EFAULT : 0;
>> +	} else if (ioctl == VFIO_DEVICE_CREATE_DMABUF) {
>> +		struct vfio_vgpu_dmabuf_info dmabuf;
>> +
>> +		minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);
>> +		if (copy_from_user(&dmabuf, (void __user *)arg, minsz)) {
>> +			fdput(f);
>> +			return -EFAULT;
>> +		}
>> +		if (dmabuf.argsz < minsz) {
>> +			fdput(f);
>> +			return -EINVAL;
>> +		}
>> +		ret = kvmgt_get_vfio_device(vgpu);
>> +		if (ret != 0)
>> +			return ret;
>
>Missed an fdput, though I'm not sure I understand the value of the original fdget
>or the dmabuf_mgr_fd field at all.  dmabuf_mgr_fd is only used here, presumably
>to add a reference to the fd while we're in the ioctl, but we're in the ioctl function
>of that fd, so I think there are already references elsewhere.
Make sense. Fdget/fdput can be removed.

>
>> +
>> +		ret = intel_gvt_ops->vgpu_create_dmabuf(vgpu, &dmabuf);
>> +		if (ret != 0) {
>> +			kvmgt_put_vfio_device(vgpu);
>> +			fdput(f);
>> +			return -EINVAL;
>
>Why not return the errno that vgpu_create_dmabuf provided?
Will change to use the returned errno.

>
>> +		}
>> +		fdput(f);
>> +		return copy_to_user((void __user *)arg, &dmabuf, minsz) ?
>> +								-EFAULT : 0;
>> +	}
>> +
>> +	fdput(f);
>> +	gvt_vgpu_err("unsupported dmabuf operation\n");
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static const struct file_operations intel_vgpu_dmabuf_mgr_fd_ops = {
>> +	.release        = intel_vgpu_dmabuf_mgr_fd_release,
>> +	.unlocked_ioctl = intel_vgpu_dmabuf_mgr_fd_ioctl,
>> +	.mmap           = intel_vgpu_dmabuf_mgr_fd_mmap,
>> +	.llseek         = noop_llseek,
>> +};
>>  static int intel_vgpu_create(struct kobject *kobj, struct mdev_device
>> *mdev)  {
>>  	struct intel_vgpu *vgpu = NULL;
>> @@ -1259,6 +1379,30 @@ static long intel_vgpu_ioctl(struct mdev_device
>*mdev, unsigned int cmd,
>>  	} else if (cmd == VFIO_DEVICE_RESET) {
>>  		intel_gvt_ops->vgpu_reset(vgpu);
>>  		return 0;
>> +	} else if (cmd == VFIO_DEVICE_GET_FD) {
>> +		int fd;
>> +		u32 type;
>> +		int ret;
>> +
>> +		if (copy_from_user(&type, (void __user *)arg, sizeof(type)))
>> +			return -EINVAL;
>> +		if (type != VFIO_DEVICE_DMABUF_MGR_FD)
>> +			return -EINVAL;
>> +
>> +		ret = kvmgt_get_vfio_device(vgpu);
>> +		if (ret != 0)
>> +			return ret;
>> +
>> +		fd = anon_inode_getfd("intel-vgpu-dmabuf-mgr-fd",
>> +			&intel_vgpu_dmabuf_mgr_fd_ops,
>> +			vgpu, O_RDWR | O_CLOEXEC);
>> +		if (fd < 0) {
>> +			gvt_vgpu_err("create dmabuf mgr fd failed\n");
>> +			return -EINVAL;
>
>Error path leaks vfio_device reference.
Will correct in the next version.

>
>> +		}
>> +		vgpu->dmabuf_mgr_fd = fd;
>
>As above, unclear value of this field, additionally, what if the user calls
>VFIO_DEVICE_GET_FD more than once?
Ah, good question.
VFIO_DEVICE_GET_FD should only be called once.
And we should add a check if the vgpu->dmabuf_mgr_fd is not 0 which means VFIO_DEVICE_GET_FD had been called before we should return an error.

>
>> +
>> +		return fd;
>>  	}
>>
>>  	return 0;
>> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c
>> b/drivers/gpu/drm/i915/gvt/vgpu.c index 6e3cbd8..af6fc74 100644
>> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
>> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
>> @@ -346,6 +346,7 @@ static struct intel_vgpu
>*__intel_gvt_create_vgpu(struct intel_gvt *gvt,
>>  	vgpu->gvt = gvt;
>>  	vgpu->sched_ctl.weight = param->weight;
>>  	bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
>> +	INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
>>
>>  	intel_vgpu_init_cfg_space(vgpu, param->primary);
>>

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
  2017-06-02  3:24       ` Chen, Xiaoguang
@ 2017-06-02  3:34         ` Alex Williamson
  -1 siblings, 0 replies; 74+ messages in thread
From: Alex Williamson @ 2017-06-02  3:34 UTC (permalink / raw)
  To: Chen, Xiaoguang
  Cc: kraxel, chris, intel-gfx, linux-kernel, zhenyuw, Lv, Zhiyuan,
	intel-gvt-dev, Wang, Zhi A, Tian, Kevin

On Fri, 2 Jun 2017 03:24:35 +0000
"Chen, Xiaoguang" <xiaoguang.chen@intel.com> wrote:

> Hi Alex,
> 
> >-----Original Message-----
> >From: Alex Williamson [mailto:alex.williamson@redhat.com]
> >Sent: Friday, June 02, 2017 2:08 AM
> >To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
> >Cc: kraxel@redhat.com; chris@chris-wilson.co.uk; intel-
> >gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
> >zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
> >dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
> ><kevin.tian@intel.com>
> >Subject: Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get
> >the dma-buf
> >
> >On Sat, 27 May 2017 16:38:52 +0800
> >Xiaoguang Chen <xiaoguang.chen@intel.com> wrote:
> >  
> >> User space should create the management fd for the dma-buf operation first.
> >> Then user can query the plane information and create dma-buf if
> >> necessary using the management fd.
> >>
> >> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
> >> ---
> >>  drivers/gpu/drm/i915/gvt/dmabuf.c |  12 ++++
> >>  drivers/gpu/drm/i915/gvt/dmabuf.h |   5 ++
> >>  drivers/gpu/drm/i915/gvt/gvt.c    |   2 +
> >>  drivers/gpu/drm/i915/gvt/gvt.h    |   5 ++
> >>  drivers/gpu/drm/i915/gvt/kvmgt.c  | 144  
> >++++++++++++++++++++++++++++++++++++++  
> >>  drivers/gpu/drm/i915/gvt/vgpu.c   |   1 +
> >>  6 files changed, 169 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> b/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> index c831e91..9759e9a 100644
> >> --- a/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> @@ -226,6 +226,7 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu,  
> >void *args)  
> >>  	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
> >>  	struct intel_vgpu_fb_info *fb_info;
> >>  	int ret;
> >> +	struct intel_vgpu_dmabuf_obj *dmabuf_obj;
> >>
> >>  	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
> >>  	if (ret != 0)
> >> @@ -263,6 +264,17 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu,  
> >void *args)  
> >>  		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
> >>  		return ret;
> >>  	}
> >> +	dmabuf_obj = kmalloc(sizeof(*dmabuf_obj), GFP_KERNEL);
> >> +	if (dmabuf_obj == NULL) {
> >> +		kfree(fb_info);
> >> +		i915_gem_object_put(obj);
> >> +		gvt_vgpu_err("alloc dmabuf_obj failed\n");
> >> +		return -ENOMEM;
> >> +	}
> >> +	dmabuf_obj->obj = obj;
> >> +	INIT_LIST_HEAD(&dmabuf_obj->list);
> >> +	list_add_tail(&dmabuf_obj->list, &vgpu->dmabuf_obj_list_head);
> >> +
> >>  	gvt_dmabuf->fd = ret;
> >>
> >>  	return 0;
> >> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> b/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> index 8be9979..cafa781 100644
> >> --- a/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> @@ -31,6 +31,11 @@ struct intel_vgpu_fb_info {
> >>  	uint32_t fb_size;
> >>  };
> >>
> >> +struct intel_vgpu_dmabuf_obj {
> >> +	struct drm_i915_gem_object *obj;
> >> +	struct list_head list;
> >> +};
> >> +
> >>  int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);  int
> >> intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args);
> >>
> >> diff --git a/drivers/gpu/drm/i915/gvt/gvt.c
> >> b/drivers/gpu/drm/i915/gvt/gvt.c index 2032917..dbc3f86 100644
> >> --- a/drivers/gpu/drm/i915/gvt/gvt.c
> >> +++ b/drivers/gpu/drm/i915/gvt/gvt.c
> >> @@ -54,6 +54,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {
> >>  	.vgpu_reset = intel_gvt_reset_vgpu,
> >>  	.vgpu_activate = intel_gvt_activate_vgpu,
> >>  	.vgpu_deactivate = intel_gvt_deactivate_vgpu,
> >> +	.vgpu_query_plane = intel_vgpu_query_plane,
> >> +	.vgpu_create_dmabuf = intel_vgpu_create_dmabuf,
> >>  };
> >>
> >>  /**
> >> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h
> >> b/drivers/gpu/drm/i915/gvt/gvt.h index 763a8c5..a855797 100644
> >> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> >> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> >> @@ -185,8 +185,11 @@ struct intel_vgpu {
> >>  		struct kvm *kvm;
> >>  		struct work_struct release_work;
> >>  		atomic_t released;
> >> +		struct vfio_device *vfio_device;
> >>  	} vdev;
> >>  #endif
> >> +	int dmabuf_mgr_fd;
> >> +	struct list_head dmabuf_obj_list_head;
> >>  };
> >>
> >>  struct intel_gvt_gm {
> >> @@ -467,6 +470,8 @@ struct intel_gvt_ops {
> >>  	void (*vgpu_reset)(struct intel_vgpu *);
> >>  	void (*vgpu_activate)(struct intel_vgpu *);
> >>  	void (*vgpu_deactivate)(struct intel_vgpu *);
> >> +	int (*vgpu_query_plane)(struct intel_vgpu *vgpu, void *);
> >> +	int (*vgpu_create_dmabuf)(struct intel_vgpu *vgpu, void *);
> >>  };
> >>
> >>
> >> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> index 389f072..a079080 100644
> >> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> @@ -41,6 +41,7 @@
> >>  #include <linux/kvm_host.h>
> >>  #include <linux/vfio.h>
> >>  #include <linux/mdev.h>
> >> +#include <linux/anon_inodes.h>
> >>
> >>  #include "i915_drv.h"
> >>  #include "gvt.h"
> >> @@ -524,6 +525,125 @@ static int intel_vgpu_reg_init_opregion(struct  
> >intel_vgpu *vgpu)  
> >>  	return ret;
> >>  }
> >>
> >> +static int kvmgt_get_vfio_device(struct intel_vgpu *vgpu) {
> >> +	struct vfio_device *device;
> >> +
> >> +	device = vfio_device_get_from_dev(mdev_dev(vgpu->vdev.mdev));
> >> +	if (device == NULL)
> >> +		return -ENODEV;
> >> +	vgpu->vdev.vfio_device = device;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static void kvmgt_put_vfio_device(struct intel_vgpu *vgpu) {
> >> +	vfio_device_put(vgpu->vdev.vfio_device);
> >> +}
> >> +
> >> +static int intel_vgpu_dmabuf_mgr_fd_mmap(struct file *file,
> >> +		struct vm_area_struct *vma)
> >> +{
> >> +	return -EPERM;
> >> +}
> >> +
> >> +static int intel_vgpu_dmabuf_mgr_fd_release(struct inode *inode,
> >> +		struct file *filp)
> >> +{
> >> +	struct intel_vgpu *vgpu = filp->private_data;
> >> +	struct intel_vgpu_dmabuf_obj *obj;
> >> +	struct list_head *pos;
> >> +
> >> +	if (WARN_ON(!vgpu->vdev.vfio_device))
> >> +		return -ENODEV;
> >> +
> >> +	list_for_each(pos, &vgpu->dmabuf_obj_list_head) {
> >> +		obj = container_of(pos, struct intel_vgpu_dmabuf_obj, list);
> >> +		if (WARN_ON(!obj))
> >> +			return -ENODEV;
> >> +		kfree(obj->obj->gvt_info);
> >> +		i915_gem_object_put(obj->obj);
> >> +		kfree(obj);
> >> +		kvmgt_put_vfio_device(vgpu);  
> >
> >Can we do this?  If I understand, we're releasing all the references and allocations
> >for the dmabuf fds on release of the manager fd.  What happens if the user
> >continues trying to access those dmabuf fds after this?  
> I think we can do this here.
> The dma-buf's release function dma_buf_release() will be called by kernel which means all the created dmabufs will be invalid even we do not release all the references and allocations here.

Are you assuming that the user has closed the dmabuf fds?  They could
close the manager fd first, should the dmabuf fd continue to work?
  
> >> +	}
> >> +	kvmgt_put_vfio_device(vgpu);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static long intel_vgpu_dmabuf_mgr_fd_ioctl(struct file *filp,
> >> +		unsigned int ioctl, unsigned long arg) {
> >> +	struct intel_vgpu *vgpu = filp->private_data;
> >> +	int minsz;
> >> +	int ret;
> >> +	struct fd f;
> >> +
> >> +	f = fdget(vgpu->dmabuf_mgr_fd);
> >> +	if (!f.file)
> >> +		return -EBADF;
> >> +
> >> +	if (ioctl == VFIO_DEVICE_QUERY_PLANE) {
> >> +		struct vfio_vgpu_plane_info info;
> >> +
> >> +		minsz = offsetofend(struct vfio_vgpu_plane_info, resv);
> >> +		if (copy_from_user(&info, (void __user *)arg, minsz)) {
> >> +			fdput(f);
> >> +			return -EFAULT;
> >> +		}
> >> +		if (info.argsz < minsz) {
> >> +			fdput(f);
> >> +			return -EINVAL;
> >> +		}
> >> +		ret = intel_gvt_ops->vgpu_query_plane(vgpu, &info);
> >> +		if (ret != 0) {
> >> +			fdput(f);
> >> +			gvt_vgpu_err("query plane failed:%d\n", ret);
> >> +			return -EINVAL;
> >> +		}
> >> +		fdput(f);
> >> +		return copy_to_user((void __user *)arg, &info, minsz) ?
> >> +								-EFAULT : 0;
> >> +	} else if (ioctl == VFIO_DEVICE_CREATE_DMABUF) {
> >> +		struct vfio_vgpu_dmabuf_info dmabuf;
> >> +
> >> +		minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);
> >> +		if (copy_from_user(&dmabuf, (void __user *)arg, minsz)) {
> >> +			fdput(f);
> >> +			return -EFAULT;
> >> +		}
> >> +		if (dmabuf.argsz < minsz) {
> >> +			fdput(f);
> >> +			return -EINVAL;
> >> +		}
> >> +		ret = kvmgt_get_vfio_device(vgpu);
> >> +		if (ret != 0)
> >> +			return ret;  
> >
> >Missed an fdput, though I'm not sure I understand the value of the original fdget
> >or the dmabuf_mgr_fd field at all.  dmabuf_mgr_fd is only used here, presumably
> >to add a reference to the fd while we're in the ioctl, but we're in the ioctl function
> >of that fd, so I think there are already references elsewhere.  
> Make sense. Fdget/fdput can be removed.
> 
> >  
> >> +
> >> +		ret = intel_gvt_ops->vgpu_create_dmabuf(vgpu, &dmabuf);
> >> +		if (ret != 0) {
> >> +			kvmgt_put_vfio_device(vgpu);
> >> +			fdput(f);
> >> +			return -EINVAL;  
> >
> >Why not return the errno that vgpu_create_dmabuf provided?  
> Will change to use the returned errno.
> 
> >  
> >> +		}
> >> +		fdput(f);
> >> +		return copy_to_user((void __user *)arg, &dmabuf, minsz) ?
> >> +								-EFAULT : 0;
> >> +	}
> >> +
> >> +	fdput(f);
> >> +	gvt_vgpu_err("unsupported dmabuf operation\n");
> >> +
> >> +	return -EINVAL;
> >> +}
> >> +
> >> +static const struct file_operations intel_vgpu_dmabuf_mgr_fd_ops = {
> >> +	.release        = intel_vgpu_dmabuf_mgr_fd_release,
> >> +	.unlocked_ioctl = intel_vgpu_dmabuf_mgr_fd_ioctl,
> >> +	.mmap           = intel_vgpu_dmabuf_mgr_fd_mmap,
> >> +	.llseek         = noop_llseek,
> >> +};
> >>  static int intel_vgpu_create(struct kobject *kobj, struct mdev_device
> >> *mdev)  {
> >>  	struct intel_vgpu *vgpu = NULL;
> >> @@ -1259,6 +1379,30 @@ static long intel_vgpu_ioctl(struct mdev_device  
> >*mdev, unsigned int cmd,  
> >>  	} else if (cmd == VFIO_DEVICE_RESET) {
> >>  		intel_gvt_ops->vgpu_reset(vgpu);
> >>  		return 0;
> >> +	} else if (cmd == VFIO_DEVICE_GET_FD) {
> >> +		int fd;
> >> +		u32 type;
> >> +		int ret;
> >> +
> >> +		if (copy_from_user(&type, (void __user *)arg, sizeof(type)))
> >> +			return -EINVAL;
> >> +		if (type != VFIO_DEVICE_DMABUF_MGR_FD)
> >> +			return -EINVAL;
> >> +
> >> +		ret = kvmgt_get_vfio_device(vgpu);
> >> +		if (ret != 0)
> >> +			return ret;
> >> +
> >> +		fd = anon_inode_getfd("intel-vgpu-dmabuf-mgr-fd",
> >> +			&intel_vgpu_dmabuf_mgr_fd_ops,
> >> +			vgpu, O_RDWR | O_CLOEXEC);
> >> +		if (fd < 0) {
> >> +			gvt_vgpu_err("create dmabuf mgr fd failed\n");
> >> +			return -EINVAL;  
> >
> >Error path leaks vfio_device reference.  
> Will correct in the next version.
> 
> >  
> >> +		}
> >> +		vgpu->dmabuf_mgr_fd = fd;  
> >
> >As above, unclear value of this field, additionally, what if the user calls
> >VFIO_DEVICE_GET_FD more than once?  
> Ah, good question.
> VFIO_DEVICE_GET_FD should only be called once.
> And we should add a check if the vgpu->dmabuf_mgr_fd is not 0 which means VFIO_DEVICE_GET_FD had been called before we should return an error.

Except we no longer need that fd and we should probably use an atomic
'opened' so it's not racy.  Thanks,

Alex

> >> +
> >> +		return fd;
> >>  	}
> >>
> >>  	return 0;
> >> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c
> >> b/drivers/gpu/drm/i915/gvt/vgpu.c index 6e3cbd8..af6fc74 100644
> >> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
> >> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
> >> @@ -346,6 +346,7 @@ static struct intel_vgpu  
> >*__intel_gvt_create_vgpu(struct intel_gvt *gvt,  
> >>  	vgpu->gvt = gvt;
> >>  	vgpu->sched_ctl.weight = param->weight;
> >>  	bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
> >> +	INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
> >>
> >>  	intel_vgpu_init_cfg_space(vgpu, param->primary);
> >>  
> 

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

* Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
@ 2017-06-02  3:34         ` Alex Williamson
  0 siblings, 0 replies; 74+ messages in thread
From: Alex Williamson @ 2017-06-02  3:34 UTC (permalink / raw)
  To: Chen, Xiaoguang
  Cc: intel-gfx, linux-kernel, Lv, Zhiyuan, intel-gvt-dev, kraxel

On Fri, 2 Jun 2017 03:24:35 +0000
"Chen, Xiaoguang" <xiaoguang.chen@intel.com> wrote:

> Hi Alex,
> 
> >-----Original Message-----
> >From: Alex Williamson [mailto:alex.williamson@redhat.com]
> >Sent: Friday, June 02, 2017 2:08 AM
> >To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
> >Cc: kraxel@redhat.com; chris@chris-wilson.co.uk; intel-
> >gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
> >zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
> >dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
> ><kevin.tian@intel.com>
> >Subject: Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get
> >the dma-buf
> >
> >On Sat, 27 May 2017 16:38:52 +0800
> >Xiaoguang Chen <xiaoguang.chen@intel.com> wrote:
> >  
> >> User space should create the management fd for the dma-buf operation first.
> >> Then user can query the plane information and create dma-buf if
> >> necessary using the management fd.
> >>
> >> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
> >> ---
> >>  drivers/gpu/drm/i915/gvt/dmabuf.c |  12 ++++
> >>  drivers/gpu/drm/i915/gvt/dmabuf.h |   5 ++
> >>  drivers/gpu/drm/i915/gvt/gvt.c    |   2 +
> >>  drivers/gpu/drm/i915/gvt/gvt.h    |   5 ++
> >>  drivers/gpu/drm/i915/gvt/kvmgt.c  | 144  
> >++++++++++++++++++++++++++++++++++++++  
> >>  drivers/gpu/drm/i915/gvt/vgpu.c   |   1 +
> >>  6 files changed, 169 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> b/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> index c831e91..9759e9a 100644
> >> --- a/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> @@ -226,6 +226,7 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu,  
> >void *args)  
> >>  	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
> >>  	struct intel_vgpu_fb_info *fb_info;
> >>  	int ret;
> >> +	struct intel_vgpu_dmabuf_obj *dmabuf_obj;
> >>
> >>  	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
> >>  	if (ret != 0)
> >> @@ -263,6 +264,17 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu,  
> >void *args)  
> >>  		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
> >>  		return ret;
> >>  	}
> >> +	dmabuf_obj = kmalloc(sizeof(*dmabuf_obj), GFP_KERNEL);
> >> +	if (dmabuf_obj == NULL) {
> >> +		kfree(fb_info);
> >> +		i915_gem_object_put(obj);
> >> +		gvt_vgpu_err("alloc dmabuf_obj failed\n");
> >> +		return -ENOMEM;
> >> +	}
> >> +	dmabuf_obj->obj = obj;
> >> +	INIT_LIST_HEAD(&dmabuf_obj->list);
> >> +	list_add_tail(&dmabuf_obj->list, &vgpu->dmabuf_obj_list_head);
> >> +
> >>  	gvt_dmabuf->fd = ret;
> >>
> >>  	return 0;
> >> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> b/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> index 8be9979..cafa781 100644
> >> --- a/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> @@ -31,6 +31,11 @@ struct intel_vgpu_fb_info {
> >>  	uint32_t fb_size;
> >>  };
> >>
> >> +struct intel_vgpu_dmabuf_obj {
> >> +	struct drm_i915_gem_object *obj;
> >> +	struct list_head list;
> >> +};
> >> +
> >>  int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);  int
> >> intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args);
> >>
> >> diff --git a/drivers/gpu/drm/i915/gvt/gvt.c
> >> b/drivers/gpu/drm/i915/gvt/gvt.c index 2032917..dbc3f86 100644
> >> --- a/drivers/gpu/drm/i915/gvt/gvt.c
> >> +++ b/drivers/gpu/drm/i915/gvt/gvt.c
> >> @@ -54,6 +54,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {
> >>  	.vgpu_reset = intel_gvt_reset_vgpu,
> >>  	.vgpu_activate = intel_gvt_activate_vgpu,
> >>  	.vgpu_deactivate = intel_gvt_deactivate_vgpu,
> >> +	.vgpu_query_plane = intel_vgpu_query_plane,
> >> +	.vgpu_create_dmabuf = intel_vgpu_create_dmabuf,
> >>  };
> >>
> >>  /**
> >> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h
> >> b/drivers/gpu/drm/i915/gvt/gvt.h index 763a8c5..a855797 100644
> >> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> >> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> >> @@ -185,8 +185,11 @@ struct intel_vgpu {
> >>  		struct kvm *kvm;
> >>  		struct work_struct release_work;
> >>  		atomic_t released;
> >> +		struct vfio_device *vfio_device;
> >>  	} vdev;
> >>  #endif
> >> +	int dmabuf_mgr_fd;
> >> +	struct list_head dmabuf_obj_list_head;
> >>  };
> >>
> >>  struct intel_gvt_gm {
> >> @@ -467,6 +470,8 @@ struct intel_gvt_ops {
> >>  	void (*vgpu_reset)(struct intel_vgpu *);
> >>  	void (*vgpu_activate)(struct intel_vgpu *);
> >>  	void (*vgpu_deactivate)(struct intel_vgpu *);
> >> +	int (*vgpu_query_plane)(struct intel_vgpu *vgpu, void *);
> >> +	int (*vgpu_create_dmabuf)(struct intel_vgpu *vgpu, void *);
> >>  };
> >>
> >>
> >> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> index 389f072..a079080 100644
> >> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> @@ -41,6 +41,7 @@
> >>  #include <linux/kvm_host.h>
> >>  #include <linux/vfio.h>
> >>  #include <linux/mdev.h>
> >> +#include <linux/anon_inodes.h>
> >>
> >>  #include "i915_drv.h"
> >>  #include "gvt.h"
> >> @@ -524,6 +525,125 @@ static int intel_vgpu_reg_init_opregion(struct  
> >intel_vgpu *vgpu)  
> >>  	return ret;
> >>  }
> >>
> >> +static int kvmgt_get_vfio_device(struct intel_vgpu *vgpu) {
> >> +	struct vfio_device *device;
> >> +
> >> +	device = vfio_device_get_from_dev(mdev_dev(vgpu->vdev.mdev));
> >> +	if (device == NULL)
> >> +		return -ENODEV;
> >> +	vgpu->vdev.vfio_device = device;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static void kvmgt_put_vfio_device(struct intel_vgpu *vgpu) {
> >> +	vfio_device_put(vgpu->vdev.vfio_device);
> >> +}
> >> +
> >> +static int intel_vgpu_dmabuf_mgr_fd_mmap(struct file *file,
> >> +		struct vm_area_struct *vma)
> >> +{
> >> +	return -EPERM;
> >> +}
> >> +
> >> +static int intel_vgpu_dmabuf_mgr_fd_release(struct inode *inode,
> >> +		struct file *filp)
> >> +{
> >> +	struct intel_vgpu *vgpu = filp->private_data;
> >> +	struct intel_vgpu_dmabuf_obj *obj;
> >> +	struct list_head *pos;
> >> +
> >> +	if (WARN_ON(!vgpu->vdev.vfio_device))
> >> +		return -ENODEV;
> >> +
> >> +	list_for_each(pos, &vgpu->dmabuf_obj_list_head) {
> >> +		obj = container_of(pos, struct intel_vgpu_dmabuf_obj, list);
> >> +		if (WARN_ON(!obj))
> >> +			return -ENODEV;
> >> +		kfree(obj->obj->gvt_info);
> >> +		i915_gem_object_put(obj->obj);
> >> +		kfree(obj);
> >> +		kvmgt_put_vfio_device(vgpu);  
> >
> >Can we do this?  If I understand, we're releasing all the references and allocations
> >for the dmabuf fds on release of the manager fd.  What happens if the user
> >continues trying to access those dmabuf fds after this?  
> I think we can do this here.
> The dma-buf's release function dma_buf_release() will be called by kernel which means all the created dmabufs will be invalid even we do not release all the references and allocations here.

Are you assuming that the user has closed the dmabuf fds?  They could
close the manager fd first, should the dmabuf fd continue to work?
  
> >> +	}
> >> +	kvmgt_put_vfio_device(vgpu);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static long intel_vgpu_dmabuf_mgr_fd_ioctl(struct file *filp,
> >> +		unsigned int ioctl, unsigned long arg) {
> >> +	struct intel_vgpu *vgpu = filp->private_data;
> >> +	int minsz;
> >> +	int ret;
> >> +	struct fd f;
> >> +
> >> +	f = fdget(vgpu->dmabuf_mgr_fd);
> >> +	if (!f.file)
> >> +		return -EBADF;
> >> +
> >> +	if (ioctl == VFIO_DEVICE_QUERY_PLANE) {
> >> +		struct vfio_vgpu_plane_info info;
> >> +
> >> +		minsz = offsetofend(struct vfio_vgpu_plane_info, resv);
> >> +		if (copy_from_user(&info, (void __user *)arg, minsz)) {
> >> +			fdput(f);
> >> +			return -EFAULT;
> >> +		}
> >> +		if (info.argsz < minsz) {
> >> +			fdput(f);
> >> +			return -EINVAL;
> >> +		}
> >> +		ret = intel_gvt_ops->vgpu_query_plane(vgpu, &info);
> >> +		if (ret != 0) {
> >> +			fdput(f);
> >> +			gvt_vgpu_err("query plane failed:%d\n", ret);
> >> +			return -EINVAL;
> >> +		}
> >> +		fdput(f);
> >> +		return copy_to_user((void __user *)arg, &info, minsz) ?
> >> +								-EFAULT : 0;
> >> +	} else if (ioctl == VFIO_DEVICE_CREATE_DMABUF) {
> >> +		struct vfio_vgpu_dmabuf_info dmabuf;
> >> +
> >> +		minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);
> >> +		if (copy_from_user(&dmabuf, (void __user *)arg, minsz)) {
> >> +			fdput(f);
> >> +			return -EFAULT;
> >> +		}
> >> +		if (dmabuf.argsz < minsz) {
> >> +			fdput(f);
> >> +			return -EINVAL;
> >> +		}
> >> +		ret = kvmgt_get_vfio_device(vgpu);
> >> +		if (ret != 0)
> >> +			return ret;  
> >
> >Missed an fdput, though I'm not sure I understand the value of the original fdget
> >or the dmabuf_mgr_fd field at all.  dmabuf_mgr_fd is only used here, presumably
> >to add a reference to the fd while we're in the ioctl, but we're in the ioctl function
> >of that fd, so I think there are already references elsewhere.  
> Make sense. Fdget/fdput can be removed.
> 
> >  
> >> +
> >> +		ret = intel_gvt_ops->vgpu_create_dmabuf(vgpu, &dmabuf);
> >> +		if (ret != 0) {
> >> +			kvmgt_put_vfio_device(vgpu);
> >> +			fdput(f);
> >> +			return -EINVAL;  
> >
> >Why not return the errno that vgpu_create_dmabuf provided?  
> Will change to use the returned errno.
> 
> >  
> >> +		}
> >> +		fdput(f);
> >> +		return copy_to_user((void __user *)arg, &dmabuf, minsz) ?
> >> +								-EFAULT : 0;
> >> +	}
> >> +
> >> +	fdput(f);
> >> +	gvt_vgpu_err("unsupported dmabuf operation\n");
> >> +
> >> +	return -EINVAL;
> >> +}
> >> +
> >> +static const struct file_operations intel_vgpu_dmabuf_mgr_fd_ops = {
> >> +	.release        = intel_vgpu_dmabuf_mgr_fd_release,
> >> +	.unlocked_ioctl = intel_vgpu_dmabuf_mgr_fd_ioctl,
> >> +	.mmap           = intel_vgpu_dmabuf_mgr_fd_mmap,
> >> +	.llseek         = noop_llseek,
> >> +};
> >>  static int intel_vgpu_create(struct kobject *kobj, struct mdev_device
> >> *mdev)  {
> >>  	struct intel_vgpu *vgpu = NULL;
> >> @@ -1259,6 +1379,30 @@ static long intel_vgpu_ioctl(struct mdev_device  
> >*mdev, unsigned int cmd,  
> >>  	} else if (cmd == VFIO_DEVICE_RESET) {
> >>  		intel_gvt_ops->vgpu_reset(vgpu);
> >>  		return 0;
> >> +	} else if (cmd == VFIO_DEVICE_GET_FD) {
> >> +		int fd;
> >> +		u32 type;
> >> +		int ret;
> >> +
> >> +		if (copy_from_user(&type, (void __user *)arg, sizeof(type)))
> >> +			return -EINVAL;
> >> +		if (type != VFIO_DEVICE_DMABUF_MGR_FD)
> >> +			return -EINVAL;
> >> +
> >> +		ret = kvmgt_get_vfio_device(vgpu);
> >> +		if (ret != 0)
> >> +			return ret;
> >> +
> >> +		fd = anon_inode_getfd("intel-vgpu-dmabuf-mgr-fd",
> >> +			&intel_vgpu_dmabuf_mgr_fd_ops,
> >> +			vgpu, O_RDWR | O_CLOEXEC);
> >> +		if (fd < 0) {
> >> +			gvt_vgpu_err("create dmabuf mgr fd failed\n");
> >> +			return -EINVAL;  
> >
> >Error path leaks vfio_device reference.  
> Will correct in the next version.
> 
> >  
> >> +		}
> >> +		vgpu->dmabuf_mgr_fd = fd;  
> >
> >As above, unclear value of this field, additionally, what if the user calls
> >VFIO_DEVICE_GET_FD more than once?  
> Ah, good question.
> VFIO_DEVICE_GET_FD should only be called once.
> And we should add a check if the vgpu->dmabuf_mgr_fd is not 0 which means VFIO_DEVICE_GET_FD had been called before we should return an error.

Except we no longer need that fd and we should probably use an atomic
'opened' so it's not racy.  Thanks,

Alex

> >> +
> >> +		return fd;
> >>  	}
> >>
> >>  	return 0;
> >> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c
> >> b/drivers/gpu/drm/i915/gvt/vgpu.c index 6e3cbd8..af6fc74 100644
> >> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
> >> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
> >> @@ -346,6 +346,7 @@ static struct intel_vgpu  
> >*__intel_gvt_create_vgpu(struct intel_gvt *gvt,  
> >>  	vgpu->gvt = gvt;
> >>  	vgpu->sched_ctl.weight = param->weight;
> >>  	bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
> >> +	INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
> >>
> >>  	intel_vgpu_init_cfg_space(vgpu, param->primary);
> >>  
> 

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
  2017-06-01 18:46               ` Kirti Wankhede
@ 2017-06-02  8:38                 ` Gerd Hoffmann
  -1 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-06-02  8:38 UTC (permalink / raw)
  To: Kirti Wankhede, Alex Williamson, Chen, Xiaoguang
  Cc: chris, intel-gfx, linux-kernel, zhenyuw, Lv, Zhiyuan,
	intel-gvt-dev, Wang, Zhi A, Tian, Kevin


> struct vfio_vgpu_surface_info {
>         __u64 start;
>         __u32 width;
>         __u32 height;
>         __u32 stride;
>         __u32 size;
>         __u32 x_pos;
>         __u32 y_pos;
>         __u32 padding;
>         /* Only used when VFIO_VGPU_SURFACE_DMABUF_* flags set */
>         __u64 drm_format_mod;
>         __u32 drm_format;

Why for dmabufs only?  Shouldn't the region specify the format too? 
Even in case you are using a fixed one (say DRM_FORMAT_XRGB8888) you
can explicitly say so in drm_format (and set drm_format_mod to zero).

cheers,
  Gerd

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
@ 2017-06-02  8:38                 ` Gerd Hoffmann
  0 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-06-02  8:38 UTC (permalink / raw)
  To: Kirti Wankhede, Alex Williamson, Chen, Xiaoguang
  Cc: chris, intel-gfx, linux-kernel, zhenyuw, Lv, Zhiyuan,
	intel-gvt-dev, Wang, Zhi A, Tian, Kevin


> struct vfio_vgpu_surface_info {
>         __u64 start;
>         __u32 width;
>         __u32 height;
>         __u32 stride;
>         __u32 size;
>         __u32 x_pos;
>         __u32 y_pos;
>         __u32 padding;
>         /* Only used when VFIO_VGPU_SURFACE_DMABUF_* flags set */
>         __u64 drm_format_mod;
>         __u32 drm_format;

Why for dmabufs only?  Shouldn't the region specify the format too? 
Even in case you are using a fixed one (say DRM_FORMAT_XRGB8888) you
can explicitly say so in drm_format (and set drm_format_mod to zero).

cheers,
  Gerd

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

* RE: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
  2017-06-02  3:34         ` Alex Williamson
@ 2017-06-02  9:31           ` Chen, Xiaoguang
  -1 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-06-02  9:31 UTC (permalink / raw)
  To: Alex Williamson
  Cc: kraxel, chris, intel-gfx, linux-kernel, zhenyuw, Lv, Zhiyuan,
	intel-gvt-dev, Wang, Zhi A, Tian, Kevin



>-----Original Message-----
>From: Alex Williamson [mailto:alex.williamson@redhat.com]
>Sent: Friday, June 02, 2017 11:35 AM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
>Cc: kraxel@redhat.com; chris@chris-wilson.co.uk; intel-
>gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get
>the dma-buf
>
>On Fri, 2 Jun 2017 03:24:35 +0000
>"Chen, Xiaoguang" <xiaoguang.chen@intel.com> wrote:
>
>> Hi Alex,
>>
>> >-----Original Message-----
>> >From: Alex Williamson [mailto:alex.williamson@redhat.com]
>> >Sent: Friday, June 02, 2017 2:08 AM
>> >To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
>> >Cc: kraxel@redhat.com; chris@chris-wilson.co.uk; intel-
>> >gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>> >zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>;
>> >intel-gvt- dev@lists.freedesktop.org; Wang, Zhi A
>> ><zhi.a.wang@intel.com>; Tian, Kevin <kevin.tian@intel.com>
>> >Subject: Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user
>> >space can get the dma-buf
>> >
>> >On Sat, 27 May 2017 16:38:52 +0800
>> >Xiaoguang Chen <xiaoguang.chen@intel.com> wrote:
>> >
>> >> User space should create the management fd for the dma-buf operation first.
>> >> Then user can query the plane information and create dma-buf if
>> >> necessary using the management fd.
>> >>
>> >> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
>> >> ---
>> >>  drivers/gpu/drm/i915/gvt/dmabuf.c |  12 ++++
>> >>  drivers/gpu/drm/i915/gvt/dmabuf.h |   5 ++
>> >>  drivers/gpu/drm/i915/gvt/gvt.c    |   2 +
>> >>  drivers/gpu/drm/i915/gvt/gvt.h    |   5 ++
>> >>  drivers/gpu/drm/i915/gvt/kvmgt.c  | 144
>> >++++++++++++++++++++++++++++++++++++++
>> >>  drivers/gpu/drm/i915/gvt/vgpu.c   |   1 +
>> >>  6 files changed, 169 insertions(+)
>> >>
>> >> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c
>> >> b/drivers/gpu/drm/i915/gvt/dmabuf.c
>> >> index c831e91..9759e9a 100644
>> >> --- a/drivers/gpu/drm/i915/gvt/dmabuf.c
>> >> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
>> >> @@ -226,6 +226,7 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu
>> >> *vgpu,
>> >void *args)
>> >>  	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
>> >>  	struct intel_vgpu_fb_info *fb_info;
>> >>  	int ret;
>> >> +	struct intel_vgpu_dmabuf_obj *dmabuf_obj;
>> >>
>> >>  	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
>> >>  	if (ret != 0)
>> >> @@ -263,6 +264,17 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu
>> >> *vgpu,
>> >void *args)
>> >>  		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
>> >>  		return ret;
>> >>  	}
>> >> +	dmabuf_obj = kmalloc(sizeof(*dmabuf_obj), GFP_KERNEL);
>> >> +	if (dmabuf_obj == NULL) {
>> >> +		kfree(fb_info);
>> >> +		i915_gem_object_put(obj);
>> >> +		gvt_vgpu_err("alloc dmabuf_obj failed\n");
>> >> +		return -ENOMEM;
>> >> +	}
>> >> +	dmabuf_obj->obj = obj;
>> >> +	INIT_LIST_HEAD(&dmabuf_obj->list);
>> >> +	list_add_tail(&dmabuf_obj->list, &vgpu->dmabuf_obj_list_head);
>> >> +
>> >>  	gvt_dmabuf->fd = ret;
>> >>
>> >>  	return 0;
>> >> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h
>> >> b/drivers/gpu/drm/i915/gvt/dmabuf.h
>> >> index 8be9979..cafa781 100644
>> >> --- a/drivers/gpu/drm/i915/gvt/dmabuf.h
>> >> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
>> >> @@ -31,6 +31,11 @@ struct intel_vgpu_fb_info {
>> >>  	uint32_t fb_size;
>> >>  };
>> >>
>> >> +struct intel_vgpu_dmabuf_obj {
>> >> +	struct drm_i915_gem_object *obj;
>> >> +	struct list_head list;
>> >> +};
>> >> +
>> >>  int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);
>> >> int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args);
>> >>
>> >> diff --git a/drivers/gpu/drm/i915/gvt/gvt.c
>> >> b/drivers/gpu/drm/i915/gvt/gvt.c index 2032917..dbc3f86 100644
>> >> --- a/drivers/gpu/drm/i915/gvt/gvt.c
>> >> +++ b/drivers/gpu/drm/i915/gvt/gvt.c
>> >> @@ -54,6 +54,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {
>> >>  	.vgpu_reset = intel_gvt_reset_vgpu,
>> >>  	.vgpu_activate = intel_gvt_activate_vgpu,
>> >>  	.vgpu_deactivate = intel_gvt_deactivate_vgpu,
>> >> +	.vgpu_query_plane = intel_vgpu_query_plane,
>> >> +	.vgpu_create_dmabuf = intel_vgpu_create_dmabuf,
>> >>  };
>> >>
>> >>  /**
>> >> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h
>> >> b/drivers/gpu/drm/i915/gvt/gvt.h index 763a8c5..a855797 100644
>> >> --- a/drivers/gpu/drm/i915/gvt/gvt.h
>> >> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
>> >> @@ -185,8 +185,11 @@ struct intel_vgpu {
>> >>  		struct kvm *kvm;
>> >>  		struct work_struct release_work;
>> >>  		atomic_t released;
>> >> +		struct vfio_device *vfio_device;
>> >>  	} vdev;
>> >>  #endif
>> >> +	int dmabuf_mgr_fd;
>> >> +	struct list_head dmabuf_obj_list_head;
>> >>  };
>> >>
>> >>  struct intel_gvt_gm {
>> >> @@ -467,6 +470,8 @@ struct intel_gvt_ops {
>> >>  	void (*vgpu_reset)(struct intel_vgpu *);
>> >>  	void (*vgpu_activate)(struct intel_vgpu *);
>> >>  	void (*vgpu_deactivate)(struct intel_vgpu *);
>> >> +	int (*vgpu_query_plane)(struct intel_vgpu *vgpu, void *);
>> >> +	int (*vgpu_create_dmabuf)(struct intel_vgpu *vgpu, void *);
>> >>  };
>> >>
>> >>
>> >> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
>> >> b/drivers/gpu/drm/i915/gvt/kvmgt.c
>> >> index 389f072..a079080 100644
>> >> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
>> >> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
>> >> @@ -41,6 +41,7 @@
>> >>  #include <linux/kvm_host.h>
>> >>  #include <linux/vfio.h>
>> >>  #include <linux/mdev.h>
>> >> +#include <linux/anon_inodes.h>
>> >>
>> >>  #include "i915_drv.h"
>> >>  #include "gvt.h"
>> >> @@ -524,6 +525,125 @@ static int
>> >> intel_vgpu_reg_init_opregion(struct
>> >intel_vgpu *vgpu)
>> >>  	return ret;
>> >>  }
>> >>
>> >> +static int kvmgt_get_vfio_device(struct intel_vgpu *vgpu) {
>> >> +	struct vfio_device *device;
>> >> +
>> >> +	device = vfio_device_get_from_dev(mdev_dev(vgpu->vdev.mdev));
>> >> +	if (device == NULL)
>> >> +		return -ENODEV;
>> >> +	vgpu->vdev.vfio_device = device;
>> >> +
>> >> +	return 0;
>> >> +}
>> >> +
>> >> +static void kvmgt_put_vfio_device(struct intel_vgpu *vgpu) {
>> >> +	vfio_device_put(vgpu->vdev.vfio_device);
>> >> +}
>> >> +
>> >> +static int intel_vgpu_dmabuf_mgr_fd_mmap(struct file *file,
>> >> +		struct vm_area_struct *vma)
>> >> +{
>> >> +	return -EPERM;
>> >> +}
>> >> +
>> >> +static int intel_vgpu_dmabuf_mgr_fd_release(struct inode *inode,
>> >> +		struct file *filp)
>> >> +{
>> >> +	struct intel_vgpu *vgpu = filp->private_data;
>> >> +	struct intel_vgpu_dmabuf_obj *obj;
>> >> +	struct list_head *pos;
>> >> +
>> >> +	if (WARN_ON(!vgpu->vdev.vfio_device))
>> >> +		return -ENODEV;
>> >> +
>> >> +	list_for_each(pos, &vgpu->dmabuf_obj_list_head) {
>> >> +		obj = container_of(pos, struct intel_vgpu_dmabuf_obj, list);
>> >> +		if (WARN_ON(!obj))
>> >> +			return -ENODEV;
>> >> +		kfree(obj->obj->gvt_info);
>> >> +		i915_gem_object_put(obj->obj);
>> >> +		kfree(obj);
>> >> +		kvmgt_put_vfio_device(vgpu);
>> >
>> >Can we do this?  If I understand, we're releasing all the references
>> >and allocations for the dmabuf fds on release of the manager fd.
>> >What happens if the user continues trying to access those dmabuf fds after
>this?
>> I think we can do this here.
>> The dma-buf's release function dma_buf_release() will be called by kernel which
>means all the created dmabufs will be invalid even we do not release all the
>references and allocations here.
>
>Are you assuming that the user has closed the dmabuf fds?  They could close the
>manager fd first, should the dmabuf fd continue to work?
If guest vm was shutdown it is ok system will release the allocated fds including the management fd and dmabuf fds.
But if user call the close() to close the management fd deliberately there are problems in current implementation.

Usually vendor of dma-buf defines its own dma_buf_ops(map, unmap, release.....) so vendor can release the reference and allocations in the release callback.
The calling sequence is: dma-buf framework's release()->vendor's dma-buf release(i915's in our case).

But in our case we did not create the dma-buf from the scratch but calling an existing i915 function i915_gem_prime_export() to create a dma-buf which use the i915's dma-buf-ops. 
In order to use this function we must create a gem object first(the reference count of the gem object is now 1!!!). 

When i915's dma-buf's release() callback is called it will try to free the gem object associated with the dma-buf if its ref count is 0. But in our case the ref count is 1 so no free callback is called so we can not release allocations there.
So we have to release our dma-buf releated allocations in the management fd's release callback which means the dma-bufs' life cycle must the same with the management fd.

The reason we call i915_gem_prime_export() to create a dma-buf is we do not need to change the i915's dma-buf framework.

So: 1) we maintain current implementation that the dma-bufs have the same lifecycle with the management fd. User can not close the management fd. Or
        2) we create the dma-buf from scratch which need to change the dma-buf infrastructure of i915.

Chenxg
>
>> >> +	}
>> >> +	kvmgt_put_vfio_device(vgpu);
>> >> +
>> >> +	return 0;
>> >> +}
>> >> +
>> >> +static long intel_vgpu_dmabuf_mgr_fd_ioctl(struct file *filp,
>> >> +		unsigned int ioctl, unsigned long arg) {
>> >> +	struct intel_vgpu *vgpu = filp->private_data;
>> >> +	int minsz;
>> >> +	int ret;
>> >> +	struct fd f;
>> >> +
>> >> +	f = fdget(vgpu->dmabuf_mgr_fd);
>> >> +	if (!f.file)
>> >> +		return -EBADF;
>> >> +
>> >> +	if (ioctl == VFIO_DEVICE_QUERY_PLANE) {
>> >> +		struct vfio_vgpu_plane_info info;
>> >> +
>> >> +		minsz = offsetofend(struct vfio_vgpu_plane_info, resv);
>> >> +		if (copy_from_user(&info, (void __user *)arg, minsz)) {
>> >> +			fdput(f);
>> >> +			return -EFAULT;
>> >> +		}
>> >> +		if (info.argsz < minsz) {
>> >> +			fdput(f);
>> >> +			return -EINVAL;
>> >> +		}
>> >> +		ret = intel_gvt_ops->vgpu_query_plane(vgpu, &info);
>> >> +		if (ret != 0) {
>> >> +			fdput(f);
>> >> +			gvt_vgpu_err("query plane failed:%d\n", ret);
>> >> +			return -EINVAL;
>> >> +		}
>> >> +		fdput(f);
>> >> +		return copy_to_user((void __user *)arg, &info, minsz) ?
>> >> +								-EFAULT : 0;
>> >> +	} else if (ioctl == VFIO_DEVICE_CREATE_DMABUF) {
>> >> +		struct vfio_vgpu_dmabuf_info dmabuf;
>> >> +
>> >> +		minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);
>> >> +		if (copy_from_user(&dmabuf, (void __user *)arg, minsz)) {
>> >> +			fdput(f);
>> >> +			return -EFAULT;
>> >> +		}
>> >> +		if (dmabuf.argsz < minsz) {
>> >> +			fdput(f);
>> >> +			return -EINVAL;
>> >> +		}
>> >> +		ret = kvmgt_get_vfio_device(vgpu);
>> >> +		if (ret != 0)
>> >> +			return ret;
>> >
>> >Missed an fdput, though I'm not sure I understand the value of the
>> >original fdget or the dmabuf_mgr_fd field at all.  dmabuf_mgr_fd is
>> >only used here, presumably to add a reference to the fd while we're
>> >in the ioctl, but we're in the ioctl function of that fd, so I think there are
>already references elsewhere.
>> Make sense. Fdget/fdput can be removed.
>>
>> >
>> >> +
>> >> +		ret = intel_gvt_ops->vgpu_create_dmabuf(vgpu, &dmabuf);
>> >> +		if (ret != 0) {
>> >> +			kvmgt_put_vfio_device(vgpu);
>> >> +			fdput(f);
>> >> +			return -EINVAL;
>> >
>> >Why not return the errno that vgpu_create_dmabuf provided?
>> Will change to use the returned errno.
>>
>> >
>> >> +		}
>> >> +		fdput(f);
>> >> +		return copy_to_user((void __user *)arg, &dmabuf, minsz) ?
>> >> +								-EFAULT : 0;
>> >> +	}
>> >> +
>> >> +	fdput(f);
>> >> +	gvt_vgpu_err("unsupported dmabuf operation\n");
>> >> +
>> >> +	return -EINVAL;
>> >> +}
>> >> +
>> >> +static const struct file_operations intel_vgpu_dmabuf_mgr_fd_ops = {
>> >> +	.release        = intel_vgpu_dmabuf_mgr_fd_release,
>> >> +	.unlocked_ioctl = intel_vgpu_dmabuf_mgr_fd_ioctl,
>> >> +	.mmap           = intel_vgpu_dmabuf_mgr_fd_mmap,
>> >> +	.llseek         = noop_llseek,
>> >> +};
>> >>  static int intel_vgpu_create(struct kobject *kobj, struct
>> >> mdev_device
>> >> *mdev)  {
>> >>  	struct intel_vgpu *vgpu = NULL;
>> >> @@ -1259,6 +1379,30 @@ static long intel_vgpu_ioctl(struct
>> >> mdev_device
>> >*mdev, unsigned int cmd,
>> >>  	} else if (cmd == VFIO_DEVICE_RESET) {
>> >>  		intel_gvt_ops->vgpu_reset(vgpu);
>> >>  		return 0;
>> >> +	} else if (cmd == VFIO_DEVICE_GET_FD) {
>> >> +		int fd;
>> >> +		u32 type;
>> >> +		int ret;
>> >> +
>> >> +		if (copy_from_user(&type, (void __user *)arg, sizeof(type)))
>> >> +			return -EINVAL;
>> >> +		if (type != VFIO_DEVICE_DMABUF_MGR_FD)
>> >> +			return -EINVAL;
>> >> +
>> >> +		ret = kvmgt_get_vfio_device(vgpu);
>> >> +		if (ret != 0)
>> >> +			return ret;
>> >> +
>> >> +		fd = anon_inode_getfd("intel-vgpu-dmabuf-mgr-fd",
>> >> +			&intel_vgpu_dmabuf_mgr_fd_ops,
>> >> +			vgpu, O_RDWR | O_CLOEXEC);
>> >> +		if (fd < 0) {
>> >> +			gvt_vgpu_err("create dmabuf mgr fd failed\n");
>> >> +			return -EINVAL;
>> >
>> >Error path leaks vfio_device reference.
>> Will correct in the next version.
>>
>> >
>> >> +		}
>> >> +		vgpu->dmabuf_mgr_fd = fd;
>> >
>> >As above, unclear value of this field, additionally, what if the user
>> >calls VFIO_DEVICE_GET_FD more than once?
>> Ah, good question.
>> VFIO_DEVICE_GET_FD should only be called once.
>> And we should add a check if the vgpu->dmabuf_mgr_fd is not 0 which means
>VFIO_DEVICE_GET_FD had been called before we should return an error.
>
>Except we no longer need that fd and we should probably use an atomic 'opened'
>so it's not racy.  Thanks,
>
>Alex
>
>> >> +
>> >> +		return fd;
>> >>  	}
>> >>
>> >>  	return 0;
>> >> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c
>> >> b/drivers/gpu/drm/i915/gvt/vgpu.c index 6e3cbd8..af6fc74 100644
>> >> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
>> >> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
>> >> @@ -346,6 +346,7 @@ static struct intel_vgpu
>> >*__intel_gvt_create_vgpu(struct intel_gvt *gvt,
>> >>  	vgpu->gvt = gvt;
>> >>  	vgpu->sched_ctl.weight = param->weight;
>> >>  	bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
>> >> +	INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
>> >>
>> >>  	intel_vgpu_init_cfg_space(vgpu, param->primary);
>> >>
>>

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

* Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
@ 2017-06-02  9:31           ` Chen, Xiaoguang
  0 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-06-02  9:31 UTC (permalink / raw)
  To: Alex Williamson
  Cc: intel-gfx, linux-kernel, Lv, Zhiyuan, intel-gvt-dev, kraxel



>-----Original Message-----
>From: Alex Williamson [mailto:alex.williamson@redhat.com]
>Sent: Friday, June 02, 2017 11:35 AM
>To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
>Cc: kraxel@redhat.com; chris@chris-wilson.co.uk; intel-
>gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
>dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
><kevin.tian@intel.com>
>Subject: Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get
>the dma-buf
>
>On Fri, 2 Jun 2017 03:24:35 +0000
>"Chen, Xiaoguang" <xiaoguang.chen@intel.com> wrote:
>
>> Hi Alex,
>>
>> >-----Original Message-----
>> >From: Alex Williamson [mailto:alex.williamson@redhat.com]
>> >Sent: Friday, June 02, 2017 2:08 AM
>> >To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
>> >Cc: kraxel@redhat.com; chris@chris-wilson.co.uk; intel-
>> >gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
>> >zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>;
>> >intel-gvt- dev@lists.freedesktop.org; Wang, Zhi A
>> ><zhi.a.wang@intel.com>; Tian, Kevin <kevin.tian@intel.com>
>> >Subject: Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user
>> >space can get the dma-buf
>> >
>> >On Sat, 27 May 2017 16:38:52 +0800
>> >Xiaoguang Chen <xiaoguang.chen@intel.com> wrote:
>> >
>> >> User space should create the management fd for the dma-buf operation first.
>> >> Then user can query the plane information and create dma-buf if
>> >> necessary using the management fd.
>> >>
>> >> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
>> >> ---
>> >>  drivers/gpu/drm/i915/gvt/dmabuf.c |  12 ++++
>> >>  drivers/gpu/drm/i915/gvt/dmabuf.h |   5 ++
>> >>  drivers/gpu/drm/i915/gvt/gvt.c    |   2 +
>> >>  drivers/gpu/drm/i915/gvt/gvt.h    |   5 ++
>> >>  drivers/gpu/drm/i915/gvt/kvmgt.c  | 144
>> >++++++++++++++++++++++++++++++++++++++
>> >>  drivers/gpu/drm/i915/gvt/vgpu.c   |   1 +
>> >>  6 files changed, 169 insertions(+)
>> >>
>> >> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c
>> >> b/drivers/gpu/drm/i915/gvt/dmabuf.c
>> >> index c831e91..9759e9a 100644
>> >> --- a/drivers/gpu/drm/i915/gvt/dmabuf.c
>> >> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
>> >> @@ -226,6 +226,7 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu
>> >> *vgpu,
>> >void *args)
>> >>  	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
>> >>  	struct intel_vgpu_fb_info *fb_info;
>> >>  	int ret;
>> >> +	struct intel_vgpu_dmabuf_obj *dmabuf_obj;
>> >>
>> >>  	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
>> >>  	if (ret != 0)
>> >> @@ -263,6 +264,17 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu
>> >> *vgpu,
>> >void *args)
>> >>  		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
>> >>  		return ret;
>> >>  	}
>> >> +	dmabuf_obj = kmalloc(sizeof(*dmabuf_obj), GFP_KERNEL);
>> >> +	if (dmabuf_obj == NULL) {
>> >> +		kfree(fb_info);
>> >> +		i915_gem_object_put(obj);
>> >> +		gvt_vgpu_err("alloc dmabuf_obj failed\n");
>> >> +		return -ENOMEM;
>> >> +	}
>> >> +	dmabuf_obj->obj = obj;
>> >> +	INIT_LIST_HEAD(&dmabuf_obj->list);
>> >> +	list_add_tail(&dmabuf_obj->list, &vgpu->dmabuf_obj_list_head);
>> >> +
>> >>  	gvt_dmabuf->fd = ret;
>> >>
>> >>  	return 0;
>> >> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h
>> >> b/drivers/gpu/drm/i915/gvt/dmabuf.h
>> >> index 8be9979..cafa781 100644
>> >> --- a/drivers/gpu/drm/i915/gvt/dmabuf.h
>> >> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
>> >> @@ -31,6 +31,11 @@ struct intel_vgpu_fb_info {
>> >>  	uint32_t fb_size;
>> >>  };
>> >>
>> >> +struct intel_vgpu_dmabuf_obj {
>> >> +	struct drm_i915_gem_object *obj;
>> >> +	struct list_head list;
>> >> +};
>> >> +
>> >>  int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);
>> >> int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args);
>> >>
>> >> diff --git a/drivers/gpu/drm/i915/gvt/gvt.c
>> >> b/drivers/gpu/drm/i915/gvt/gvt.c index 2032917..dbc3f86 100644
>> >> --- a/drivers/gpu/drm/i915/gvt/gvt.c
>> >> +++ b/drivers/gpu/drm/i915/gvt/gvt.c
>> >> @@ -54,6 +54,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {
>> >>  	.vgpu_reset = intel_gvt_reset_vgpu,
>> >>  	.vgpu_activate = intel_gvt_activate_vgpu,
>> >>  	.vgpu_deactivate = intel_gvt_deactivate_vgpu,
>> >> +	.vgpu_query_plane = intel_vgpu_query_plane,
>> >> +	.vgpu_create_dmabuf = intel_vgpu_create_dmabuf,
>> >>  };
>> >>
>> >>  /**
>> >> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h
>> >> b/drivers/gpu/drm/i915/gvt/gvt.h index 763a8c5..a855797 100644
>> >> --- a/drivers/gpu/drm/i915/gvt/gvt.h
>> >> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
>> >> @@ -185,8 +185,11 @@ struct intel_vgpu {
>> >>  		struct kvm *kvm;
>> >>  		struct work_struct release_work;
>> >>  		atomic_t released;
>> >> +		struct vfio_device *vfio_device;
>> >>  	} vdev;
>> >>  #endif
>> >> +	int dmabuf_mgr_fd;
>> >> +	struct list_head dmabuf_obj_list_head;
>> >>  };
>> >>
>> >>  struct intel_gvt_gm {
>> >> @@ -467,6 +470,8 @@ struct intel_gvt_ops {
>> >>  	void (*vgpu_reset)(struct intel_vgpu *);
>> >>  	void (*vgpu_activate)(struct intel_vgpu *);
>> >>  	void (*vgpu_deactivate)(struct intel_vgpu *);
>> >> +	int (*vgpu_query_plane)(struct intel_vgpu *vgpu, void *);
>> >> +	int (*vgpu_create_dmabuf)(struct intel_vgpu *vgpu, void *);
>> >>  };
>> >>
>> >>
>> >> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
>> >> b/drivers/gpu/drm/i915/gvt/kvmgt.c
>> >> index 389f072..a079080 100644
>> >> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
>> >> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
>> >> @@ -41,6 +41,7 @@
>> >>  #include <linux/kvm_host.h>
>> >>  #include <linux/vfio.h>
>> >>  #include <linux/mdev.h>
>> >> +#include <linux/anon_inodes.h>
>> >>
>> >>  #include "i915_drv.h"
>> >>  #include "gvt.h"
>> >> @@ -524,6 +525,125 @@ static int
>> >> intel_vgpu_reg_init_opregion(struct
>> >intel_vgpu *vgpu)
>> >>  	return ret;
>> >>  }
>> >>
>> >> +static int kvmgt_get_vfio_device(struct intel_vgpu *vgpu) {
>> >> +	struct vfio_device *device;
>> >> +
>> >> +	device = vfio_device_get_from_dev(mdev_dev(vgpu->vdev.mdev));
>> >> +	if (device == NULL)
>> >> +		return -ENODEV;
>> >> +	vgpu->vdev.vfio_device = device;
>> >> +
>> >> +	return 0;
>> >> +}
>> >> +
>> >> +static void kvmgt_put_vfio_device(struct intel_vgpu *vgpu) {
>> >> +	vfio_device_put(vgpu->vdev.vfio_device);
>> >> +}
>> >> +
>> >> +static int intel_vgpu_dmabuf_mgr_fd_mmap(struct file *file,
>> >> +		struct vm_area_struct *vma)
>> >> +{
>> >> +	return -EPERM;
>> >> +}
>> >> +
>> >> +static int intel_vgpu_dmabuf_mgr_fd_release(struct inode *inode,
>> >> +		struct file *filp)
>> >> +{
>> >> +	struct intel_vgpu *vgpu = filp->private_data;
>> >> +	struct intel_vgpu_dmabuf_obj *obj;
>> >> +	struct list_head *pos;
>> >> +
>> >> +	if (WARN_ON(!vgpu->vdev.vfio_device))
>> >> +		return -ENODEV;
>> >> +
>> >> +	list_for_each(pos, &vgpu->dmabuf_obj_list_head) {
>> >> +		obj = container_of(pos, struct intel_vgpu_dmabuf_obj, list);
>> >> +		if (WARN_ON(!obj))
>> >> +			return -ENODEV;
>> >> +		kfree(obj->obj->gvt_info);
>> >> +		i915_gem_object_put(obj->obj);
>> >> +		kfree(obj);
>> >> +		kvmgt_put_vfio_device(vgpu);
>> >
>> >Can we do this?  If I understand, we're releasing all the references
>> >and allocations for the dmabuf fds on release of the manager fd.
>> >What happens if the user continues trying to access those dmabuf fds after
>this?
>> I think we can do this here.
>> The dma-buf's release function dma_buf_release() will be called by kernel which
>means all the created dmabufs will be invalid even we do not release all the
>references and allocations here.
>
>Are you assuming that the user has closed the dmabuf fds?  They could close the
>manager fd first, should the dmabuf fd continue to work?
If guest vm was shutdown it is ok system will release the allocated fds including the management fd and dmabuf fds.
But if user call the close() to close the management fd deliberately there are problems in current implementation.

Usually vendor of dma-buf defines its own dma_buf_ops(map, unmap, release.....) so vendor can release the reference and allocations in the release callback.
The calling sequence is: dma-buf framework's release()->vendor's dma-buf release(i915's in our case).

But in our case we did not create the dma-buf from the scratch but calling an existing i915 function i915_gem_prime_export() to create a dma-buf which use the i915's dma-buf-ops. 
In order to use this function we must create a gem object first(the reference count of the gem object is now 1!!!). 

When i915's dma-buf's release() callback is called it will try to free the gem object associated with the dma-buf if its ref count is 0. But in our case the ref count is 1 so no free callback is called so we can not release allocations there.
So we have to release our dma-buf releated allocations in the management fd's release callback which means the dma-bufs' life cycle must the same with the management fd.

The reason we call i915_gem_prime_export() to create a dma-buf is we do not need to change the i915's dma-buf framework.

So: 1) we maintain current implementation that the dma-bufs have the same lifecycle with the management fd. User can not close the management fd. Or
        2) we create the dma-buf from scratch which need to change the dma-buf infrastructure of i915.

Chenxg
>
>> >> +	}
>> >> +	kvmgt_put_vfio_device(vgpu);
>> >> +
>> >> +	return 0;
>> >> +}
>> >> +
>> >> +static long intel_vgpu_dmabuf_mgr_fd_ioctl(struct file *filp,
>> >> +		unsigned int ioctl, unsigned long arg) {
>> >> +	struct intel_vgpu *vgpu = filp->private_data;
>> >> +	int minsz;
>> >> +	int ret;
>> >> +	struct fd f;
>> >> +
>> >> +	f = fdget(vgpu->dmabuf_mgr_fd);
>> >> +	if (!f.file)
>> >> +		return -EBADF;
>> >> +
>> >> +	if (ioctl == VFIO_DEVICE_QUERY_PLANE) {
>> >> +		struct vfio_vgpu_plane_info info;
>> >> +
>> >> +		minsz = offsetofend(struct vfio_vgpu_plane_info, resv);
>> >> +		if (copy_from_user(&info, (void __user *)arg, minsz)) {
>> >> +			fdput(f);
>> >> +			return -EFAULT;
>> >> +		}
>> >> +		if (info.argsz < minsz) {
>> >> +			fdput(f);
>> >> +			return -EINVAL;
>> >> +		}
>> >> +		ret = intel_gvt_ops->vgpu_query_plane(vgpu, &info);
>> >> +		if (ret != 0) {
>> >> +			fdput(f);
>> >> +			gvt_vgpu_err("query plane failed:%d\n", ret);
>> >> +			return -EINVAL;
>> >> +		}
>> >> +		fdput(f);
>> >> +		return copy_to_user((void __user *)arg, &info, minsz) ?
>> >> +								-EFAULT : 0;
>> >> +	} else if (ioctl == VFIO_DEVICE_CREATE_DMABUF) {
>> >> +		struct vfio_vgpu_dmabuf_info dmabuf;
>> >> +
>> >> +		minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);
>> >> +		if (copy_from_user(&dmabuf, (void __user *)arg, minsz)) {
>> >> +			fdput(f);
>> >> +			return -EFAULT;
>> >> +		}
>> >> +		if (dmabuf.argsz < minsz) {
>> >> +			fdput(f);
>> >> +			return -EINVAL;
>> >> +		}
>> >> +		ret = kvmgt_get_vfio_device(vgpu);
>> >> +		if (ret != 0)
>> >> +			return ret;
>> >
>> >Missed an fdput, though I'm not sure I understand the value of the
>> >original fdget or the dmabuf_mgr_fd field at all.  dmabuf_mgr_fd is
>> >only used here, presumably to add a reference to the fd while we're
>> >in the ioctl, but we're in the ioctl function of that fd, so I think there are
>already references elsewhere.
>> Make sense. Fdget/fdput can be removed.
>>
>> >
>> >> +
>> >> +		ret = intel_gvt_ops->vgpu_create_dmabuf(vgpu, &dmabuf);
>> >> +		if (ret != 0) {
>> >> +			kvmgt_put_vfio_device(vgpu);
>> >> +			fdput(f);
>> >> +			return -EINVAL;
>> >
>> >Why not return the errno that vgpu_create_dmabuf provided?
>> Will change to use the returned errno.
>>
>> >
>> >> +		}
>> >> +		fdput(f);
>> >> +		return copy_to_user((void __user *)arg, &dmabuf, minsz) ?
>> >> +								-EFAULT : 0;
>> >> +	}
>> >> +
>> >> +	fdput(f);
>> >> +	gvt_vgpu_err("unsupported dmabuf operation\n");
>> >> +
>> >> +	return -EINVAL;
>> >> +}
>> >> +
>> >> +static const struct file_operations intel_vgpu_dmabuf_mgr_fd_ops = {
>> >> +	.release        = intel_vgpu_dmabuf_mgr_fd_release,
>> >> +	.unlocked_ioctl = intel_vgpu_dmabuf_mgr_fd_ioctl,
>> >> +	.mmap           = intel_vgpu_dmabuf_mgr_fd_mmap,
>> >> +	.llseek         = noop_llseek,
>> >> +};
>> >>  static int intel_vgpu_create(struct kobject *kobj, struct
>> >> mdev_device
>> >> *mdev)  {
>> >>  	struct intel_vgpu *vgpu = NULL;
>> >> @@ -1259,6 +1379,30 @@ static long intel_vgpu_ioctl(struct
>> >> mdev_device
>> >*mdev, unsigned int cmd,
>> >>  	} else if (cmd == VFIO_DEVICE_RESET) {
>> >>  		intel_gvt_ops->vgpu_reset(vgpu);
>> >>  		return 0;
>> >> +	} else if (cmd == VFIO_DEVICE_GET_FD) {
>> >> +		int fd;
>> >> +		u32 type;
>> >> +		int ret;
>> >> +
>> >> +		if (copy_from_user(&type, (void __user *)arg, sizeof(type)))
>> >> +			return -EINVAL;
>> >> +		if (type != VFIO_DEVICE_DMABUF_MGR_FD)
>> >> +			return -EINVAL;
>> >> +
>> >> +		ret = kvmgt_get_vfio_device(vgpu);
>> >> +		if (ret != 0)
>> >> +			return ret;
>> >> +
>> >> +		fd = anon_inode_getfd("intel-vgpu-dmabuf-mgr-fd",
>> >> +			&intel_vgpu_dmabuf_mgr_fd_ops,
>> >> +			vgpu, O_RDWR | O_CLOEXEC);
>> >> +		if (fd < 0) {
>> >> +			gvt_vgpu_err("create dmabuf mgr fd failed\n");
>> >> +			return -EINVAL;
>> >
>> >Error path leaks vfio_device reference.
>> Will correct in the next version.
>>
>> >
>> >> +		}
>> >> +		vgpu->dmabuf_mgr_fd = fd;
>> >
>> >As above, unclear value of this field, additionally, what if the user
>> >calls VFIO_DEVICE_GET_FD more than once?
>> Ah, good question.
>> VFIO_DEVICE_GET_FD should only be called once.
>> And we should add a check if the vgpu->dmabuf_mgr_fd is not 0 which means
>VFIO_DEVICE_GET_FD had been called before we should return an error.
>
>Except we no longer need that fd and we should probably use an atomic 'opened'
>so it's not racy.  Thanks,
>
>Alex
>
>> >> +
>> >> +		return fd;
>> >>  	}
>> >>
>> >>  	return 0;
>> >> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c
>> >> b/drivers/gpu/drm/i915/gvt/vgpu.c index 6e3cbd8..af6fc74 100644
>> >> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
>> >> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
>> >> @@ -346,6 +346,7 @@ static struct intel_vgpu
>> >*__intel_gvt_create_vgpu(struct intel_gvt *gvt,
>> >>  	vgpu->gvt = gvt;
>> >>  	vgpu->sched_ctl.weight = param->weight;
>> >>  	bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
>> >> +	INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
>> >>
>> >>  	intel_vgpu_init_cfg_space(vgpu, param->primary);
>> >>
>>

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
  2017-06-02  9:31           ` Chen, Xiaoguang
@ 2017-06-02 14:58             ` Alex Williamson
  -1 siblings, 0 replies; 74+ messages in thread
From: Alex Williamson @ 2017-06-02 14:58 UTC (permalink / raw)
  To: Chen, Xiaoguang
  Cc: kraxel, chris, intel-gfx, linux-kernel, zhenyuw, Lv, Zhiyuan,
	intel-gvt-dev, Wang, Zhi A, Tian, Kevin

On Fri, 2 Jun 2017 09:31:41 +0000
"Chen, Xiaoguang" <xiaoguang.chen@intel.com> wrote:

> >-----Original Message-----
> >From: Alex Williamson [mailto:alex.williamson@redhat.com]
> >Sent: Friday, June 02, 2017 11:35 AM
> >To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
> >Cc: kraxel@redhat.com; chris@chris-wilson.co.uk; intel-
> >gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
> >zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
> >dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
> ><kevin.tian@intel.com>
> >Subject: Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get
> >the dma-buf
> >
> >On Fri, 2 Jun 2017 03:24:35 +0000
> >"Chen, Xiaoguang" <xiaoguang.chen@intel.com> wrote:
> >  
> >> Hi Alex,
> >>  
> >> >-----Original Message-----
> >> >From: Alex Williamson [mailto:alex.williamson@redhat.com]
> >> >Sent: Friday, June 02, 2017 2:08 AM
> >> >To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
> >> >Cc: kraxel@redhat.com; chris@chris-wilson.co.uk; intel-
> >> >gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
> >> >zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>;
> >> >intel-gvt- dev@lists.freedesktop.org; Wang, Zhi A
> >> ><zhi.a.wang@intel.com>; Tian, Kevin <kevin.tian@intel.com>
> >> >Subject: Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user
> >> >space can get the dma-buf
> >> >
> >> >On Sat, 27 May 2017 16:38:52 +0800
> >> >Xiaoguang Chen <xiaoguang.chen@intel.com> wrote:
> >> >  
> >> >> User space should create the management fd for the dma-buf operation first.
> >> >> Then user can query the plane information and create dma-buf if
> >> >> necessary using the management fd.
> >> >>
> >> >> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
> >> >> ---
> >> >>  drivers/gpu/drm/i915/gvt/dmabuf.c |  12 ++++
> >> >>  drivers/gpu/drm/i915/gvt/dmabuf.h |   5 ++
> >> >>  drivers/gpu/drm/i915/gvt/gvt.c    |   2 +
> >> >>  drivers/gpu/drm/i915/gvt/gvt.h    |   5 ++
> >> >>  drivers/gpu/drm/i915/gvt/kvmgt.c  | 144  
> >> >++++++++++++++++++++++++++++++++++++++  
> >> >>  drivers/gpu/drm/i915/gvt/vgpu.c   |   1 +
> >> >>  6 files changed, 169 insertions(+)
> >> >>
> >> >> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> >> b/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> >> index c831e91..9759e9a 100644
> >> >> --- a/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> >> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> >> @@ -226,6 +226,7 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu
> >> >> *vgpu,  
> >> >void *args)  
> >> >>  	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
> >> >>  	struct intel_vgpu_fb_info *fb_info;
> >> >>  	int ret;
> >> >> +	struct intel_vgpu_dmabuf_obj *dmabuf_obj;
> >> >>
> >> >>  	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
> >> >>  	if (ret != 0)
> >> >> @@ -263,6 +264,17 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu
> >> >> *vgpu,  
> >> >void *args)  
> >> >>  		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
> >> >>  		return ret;
> >> >>  	}
> >> >> +	dmabuf_obj = kmalloc(sizeof(*dmabuf_obj), GFP_KERNEL);
> >> >> +	if (dmabuf_obj == NULL) {
> >> >> +		kfree(fb_info);
> >> >> +		i915_gem_object_put(obj);
> >> >> +		gvt_vgpu_err("alloc dmabuf_obj failed\n");
> >> >> +		return -ENOMEM;
> >> >> +	}
> >> >> +	dmabuf_obj->obj = obj;
> >> >> +	INIT_LIST_HEAD(&dmabuf_obj->list);
> >> >> +	list_add_tail(&dmabuf_obj->list, &vgpu->dmabuf_obj_list_head);
> >> >> +
> >> >>  	gvt_dmabuf->fd = ret;
> >> >>
> >> >>  	return 0;
> >> >> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> >> b/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> >> index 8be9979..cafa781 100644
> >> >> --- a/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> >> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> >> @@ -31,6 +31,11 @@ struct intel_vgpu_fb_info {
> >> >>  	uint32_t fb_size;
> >> >>  };
> >> >>
> >> >> +struct intel_vgpu_dmabuf_obj {
> >> >> +	struct drm_i915_gem_object *obj;
> >> >> +	struct list_head list;
> >> >> +};
> >> >> +
> >> >>  int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);
> >> >> int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args);
> >> >>
> >> >> diff --git a/drivers/gpu/drm/i915/gvt/gvt.c
> >> >> b/drivers/gpu/drm/i915/gvt/gvt.c index 2032917..dbc3f86 100644
> >> >> --- a/drivers/gpu/drm/i915/gvt/gvt.c
> >> >> +++ b/drivers/gpu/drm/i915/gvt/gvt.c
> >> >> @@ -54,6 +54,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {
> >> >>  	.vgpu_reset = intel_gvt_reset_vgpu,
> >> >>  	.vgpu_activate = intel_gvt_activate_vgpu,
> >> >>  	.vgpu_deactivate = intel_gvt_deactivate_vgpu,
> >> >> +	.vgpu_query_plane = intel_vgpu_query_plane,
> >> >> +	.vgpu_create_dmabuf = intel_vgpu_create_dmabuf,
> >> >>  };
> >> >>
> >> >>  /**
> >> >> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h
> >> >> b/drivers/gpu/drm/i915/gvt/gvt.h index 763a8c5..a855797 100644
> >> >> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> >> >> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> >> >> @@ -185,8 +185,11 @@ struct intel_vgpu {
> >> >>  		struct kvm *kvm;
> >> >>  		struct work_struct release_work;
> >> >>  		atomic_t released;
> >> >> +		struct vfio_device *vfio_device;
> >> >>  	} vdev;
> >> >>  #endif
> >> >> +	int dmabuf_mgr_fd;
> >> >> +	struct list_head dmabuf_obj_list_head;
> >> >>  };
> >> >>
> >> >>  struct intel_gvt_gm {
> >> >> @@ -467,6 +470,8 @@ struct intel_gvt_ops {
> >> >>  	void (*vgpu_reset)(struct intel_vgpu *);
> >> >>  	void (*vgpu_activate)(struct intel_vgpu *);
> >> >>  	void (*vgpu_deactivate)(struct intel_vgpu *);
> >> >> +	int (*vgpu_query_plane)(struct intel_vgpu *vgpu, void *);
> >> >> +	int (*vgpu_create_dmabuf)(struct intel_vgpu *vgpu, void *);
> >> >>  };
> >> >>
> >> >>
> >> >> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> >> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> >> index 389f072..a079080 100644
> >> >> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> >> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> >> @@ -41,6 +41,7 @@
> >> >>  #include <linux/kvm_host.h>
> >> >>  #include <linux/vfio.h>
> >> >>  #include <linux/mdev.h>
> >> >> +#include <linux/anon_inodes.h>
> >> >>
> >> >>  #include "i915_drv.h"
> >> >>  #include "gvt.h"
> >> >> @@ -524,6 +525,125 @@ static int
> >> >> intel_vgpu_reg_init_opregion(struct  
> >> >intel_vgpu *vgpu)  
> >> >>  	return ret;
> >> >>  }
> >> >>
> >> >> +static int kvmgt_get_vfio_device(struct intel_vgpu *vgpu) {
> >> >> +	struct vfio_device *device;
> >> >> +
> >> >> +	device = vfio_device_get_from_dev(mdev_dev(vgpu->vdev.mdev));
> >> >> +	if (device == NULL)
> >> >> +		return -ENODEV;
> >> >> +	vgpu->vdev.vfio_device = device;
> >> >> +
> >> >> +	return 0;
> >> >> +}
> >> >> +
> >> >> +static void kvmgt_put_vfio_device(struct intel_vgpu *vgpu) {
> >> >> +	vfio_device_put(vgpu->vdev.vfio_device);
> >> >> +}
> >> >> +
> >> >> +static int intel_vgpu_dmabuf_mgr_fd_mmap(struct file *file,
> >> >> +		struct vm_area_struct *vma)
> >> >> +{
> >> >> +	return -EPERM;
> >> >> +}
> >> >> +
> >> >> +static int intel_vgpu_dmabuf_mgr_fd_release(struct inode *inode,
> >> >> +		struct file *filp)
> >> >> +{
> >> >> +	struct intel_vgpu *vgpu = filp->private_data;
> >> >> +	struct intel_vgpu_dmabuf_obj *obj;
> >> >> +	struct list_head *pos;
> >> >> +
> >> >> +	if (WARN_ON(!vgpu->vdev.vfio_device))
> >> >> +		return -ENODEV;
> >> >> +
> >> >> +	list_for_each(pos, &vgpu->dmabuf_obj_list_head) {
> >> >> +		obj = container_of(pos, struct intel_vgpu_dmabuf_obj, list);
> >> >> +		if (WARN_ON(!obj))
> >> >> +			return -ENODEV;
> >> >> +		kfree(obj->obj->gvt_info);
> >> >> +		i915_gem_object_put(obj->obj);
> >> >> +		kfree(obj);
> >> >> +		kvmgt_put_vfio_device(vgpu);  
> >> >
> >> >Can we do this?  If I understand, we're releasing all the references
> >> >and allocations for the dmabuf fds on release of the manager fd.
> >> >What happens if the user continues trying to access those dmabuf fds after  
> >this?  
> >> I think we can do this here.
> >> The dma-buf's release function dma_buf_release() will be called by kernel which  
> >means all the created dmabufs will be invalid even we do not release all the
> >references and allocations here.
> >
> >Are you assuming that the user has closed the dmabuf fds?  They could close the
> >manager fd first, should the dmabuf fd continue to work?  
> If guest vm was shutdown it is ok system will release the allocated fds including the management fd and dmabuf fds.
> But if user call the close() to close the management fd deliberately there are problems in current implementation.
> 
> Usually vendor of dma-buf defines its own dma_buf_ops(map, unmap, release.....) so vendor can release the reference and allocations in the release callback.
> The calling sequence is: dma-buf framework's release()->vendor's dma-buf release(i915's in our case).
> 
> But in our case we did not create the dma-buf from the scratch but calling an existing i915 function i915_gem_prime_export() to create a dma-buf which use the i915's dma-buf-ops. 
> In order to use this function we must create a gem object first(the reference count of the gem object is now 1!!!). 
> 
> When i915's dma-buf's release() callback is called it will try to free the gem object associated with the dma-buf if its ref count is 0. But in our case the ref count is 1 so no free callback is called so we can not release allocations there.
> So we have to release our dma-buf releated allocations in the management fd's release callback which means the dma-bufs' life cycle must the same with the management fd.
> 
> The reason we call i915_gem_prime_export() to create a dma-buf is we do not need to change the i915's dma-buf framework.
> 
> So: 1) we maintain current implementation that the dma-bufs have the same lifecycle with the management fd. User can not close the management fd. Or
>         2) we create the dma-buf from scratch which need to change the dma-buf infrastructure of i915.

We cannot simply say that the user isn't allowed to release them in
that order.  If they do, how does it break, including what might mmaps
into those dmabufs provide them access to after the underlying object is
removed. If the policy is that the management fd cannot be released
until the dmabufs are closed, then that needs to be actively enforced.
Otherwise it needs to be supported.  Requiring changes to dmabuf
handling in the i915 code isn't an excuse IMO.  Thanks,

Alex

> >> >> +	}
> >> >> +	kvmgt_put_vfio_device(vgpu);
> >> >> +
> >> >> +	return 0;
> >> >> +}
> >> >> +
> >> >> +static long intel_vgpu_dmabuf_mgr_fd_ioctl(struct file *filp,
> >> >> +		unsigned int ioctl, unsigned long arg) {
> >> >> +	struct intel_vgpu *vgpu = filp->private_data;
> >> >> +	int minsz;
> >> >> +	int ret;
> >> >> +	struct fd f;
> >> >> +
> >> >> +	f = fdget(vgpu->dmabuf_mgr_fd);
> >> >> +	if (!f.file)
> >> >> +		return -EBADF;
> >> >> +
> >> >> +	if (ioctl == VFIO_DEVICE_QUERY_PLANE) {
> >> >> +		struct vfio_vgpu_plane_info info;
> >> >> +
> >> >> +		minsz = offsetofend(struct vfio_vgpu_plane_info, resv);
> >> >> +		if (copy_from_user(&info, (void __user *)arg, minsz)) {
> >> >> +			fdput(f);
> >> >> +			return -EFAULT;
> >> >> +		}
> >> >> +		if (info.argsz < minsz) {
> >> >> +			fdput(f);
> >> >> +			return -EINVAL;
> >> >> +		}
> >> >> +		ret = intel_gvt_ops->vgpu_query_plane(vgpu, &info);
> >> >> +		if (ret != 0) {
> >> >> +			fdput(f);
> >> >> +			gvt_vgpu_err("query plane failed:%d\n", ret);
> >> >> +			return -EINVAL;
> >> >> +		}
> >> >> +		fdput(f);
> >> >> +		return copy_to_user((void __user *)arg, &info, minsz) ?
> >> >> +								-EFAULT : 0;
> >> >> +	} else if (ioctl == VFIO_DEVICE_CREATE_DMABUF) {
> >> >> +		struct vfio_vgpu_dmabuf_info dmabuf;
> >> >> +
> >> >> +		minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);
> >> >> +		if (copy_from_user(&dmabuf, (void __user *)arg, minsz)) {
> >> >> +			fdput(f);
> >> >> +			return -EFAULT;
> >> >> +		}
> >> >> +		if (dmabuf.argsz < minsz) {
> >> >> +			fdput(f);
> >> >> +			return -EINVAL;
> >> >> +		}
> >> >> +		ret = kvmgt_get_vfio_device(vgpu);
> >> >> +		if (ret != 0)
> >> >> +			return ret;  
> >> >
> >> >Missed an fdput, though I'm not sure I understand the value of the
> >> >original fdget or the dmabuf_mgr_fd field at all.  dmabuf_mgr_fd is
> >> >only used here, presumably to add a reference to the fd while we're
> >> >in the ioctl, but we're in the ioctl function of that fd, so I think there are  
> >already references elsewhere.  
> >> Make sense. Fdget/fdput can be removed.
> >>  
> >> >  
> >> >> +
> >> >> +		ret = intel_gvt_ops->vgpu_create_dmabuf(vgpu, &dmabuf);
> >> >> +		if (ret != 0) {
> >> >> +			kvmgt_put_vfio_device(vgpu);
> >> >> +			fdput(f);
> >> >> +			return -EINVAL;  
> >> >
> >> >Why not return the errno that vgpu_create_dmabuf provided?  
> >> Will change to use the returned errno.
> >>  
> >> >  
> >> >> +		}
> >> >> +		fdput(f);
> >> >> +		return copy_to_user((void __user *)arg, &dmabuf, minsz) ?
> >> >> +								-EFAULT : 0;
> >> >> +	}
> >> >> +
> >> >> +	fdput(f);
> >> >> +	gvt_vgpu_err("unsupported dmabuf operation\n");
> >> >> +
> >> >> +	return -EINVAL;
> >> >> +}
> >> >> +
> >> >> +static const struct file_operations intel_vgpu_dmabuf_mgr_fd_ops = {
> >> >> +	.release        = intel_vgpu_dmabuf_mgr_fd_release,
> >> >> +	.unlocked_ioctl = intel_vgpu_dmabuf_mgr_fd_ioctl,
> >> >> +	.mmap           = intel_vgpu_dmabuf_mgr_fd_mmap,
> >> >> +	.llseek         = noop_llseek,
> >> >> +};
> >> >>  static int intel_vgpu_create(struct kobject *kobj, struct
> >> >> mdev_device
> >> >> *mdev)  {
> >> >>  	struct intel_vgpu *vgpu = NULL;
> >> >> @@ -1259,6 +1379,30 @@ static long intel_vgpu_ioctl(struct
> >> >> mdev_device  
> >> >*mdev, unsigned int cmd,  
> >> >>  	} else if (cmd == VFIO_DEVICE_RESET) {
> >> >>  		intel_gvt_ops->vgpu_reset(vgpu);
> >> >>  		return 0;
> >> >> +	} else if (cmd == VFIO_DEVICE_GET_FD) {
> >> >> +		int fd;
> >> >> +		u32 type;
> >> >> +		int ret;
> >> >> +
> >> >> +		if (copy_from_user(&type, (void __user *)arg, sizeof(type)))
> >> >> +			return -EINVAL;
> >> >> +		if (type != VFIO_DEVICE_DMABUF_MGR_FD)
> >> >> +			return -EINVAL;
> >> >> +
> >> >> +		ret = kvmgt_get_vfio_device(vgpu);
> >> >> +		if (ret != 0)
> >> >> +			return ret;
> >> >> +
> >> >> +		fd = anon_inode_getfd("intel-vgpu-dmabuf-mgr-fd",
> >> >> +			&intel_vgpu_dmabuf_mgr_fd_ops,
> >> >> +			vgpu, O_RDWR | O_CLOEXEC);
> >> >> +		if (fd < 0) {
> >> >> +			gvt_vgpu_err("create dmabuf mgr fd failed\n");
> >> >> +			return -EINVAL;  
> >> >
> >> >Error path leaks vfio_device reference.  
> >> Will correct in the next version.
> >>  
> >> >  
> >> >> +		}
> >> >> +		vgpu->dmabuf_mgr_fd = fd;  
> >> >
> >> >As above, unclear value of this field, additionally, what if the user
> >> >calls VFIO_DEVICE_GET_FD more than once?  
> >> Ah, good question.
> >> VFIO_DEVICE_GET_FD should only be called once.
> >> And we should add a check if the vgpu->dmabuf_mgr_fd is not 0 which means  
> >VFIO_DEVICE_GET_FD had been called before we should return an error.
> >
> >Except we no longer need that fd and we should probably use an atomic 'opened'
> >so it's not racy.  Thanks,
> >
> >Alex
> >  
> >> >> +
> >> >> +		return fd;
> >> >>  	}
> >> >>
> >> >>  	return 0;
> >> >> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c
> >> >> b/drivers/gpu/drm/i915/gvt/vgpu.c index 6e3cbd8..af6fc74 100644
> >> >> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
> >> >> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
> >> >> @@ -346,6 +346,7 @@ static struct intel_vgpu  
> >> >*__intel_gvt_create_vgpu(struct intel_gvt *gvt,  
> >> >>  	vgpu->gvt = gvt;
> >> >>  	vgpu->sched_ctl.weight = param->weight;
> >> >>  	bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
> >> >> +	INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
> >> >>
> >> >>  	intel_vgpu_init_cfg_space(vgpu, param->primary);
> >> >>  
> >>  
> 

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

* Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
@ 2017-06-02 14:58             ` Alex Williamson
  0 siblings, 0 replies; 74+ messages in thread
From: Alex Williamson @ 2017-06-02 14:58 UTC (permalink / raw)
  To: Chen, Xiaoguang
  Cc: intel-gfx, linux-kernel, Lv, Zhiyuan, intel-gvt-dev, kraxel

On Fri, 2 Jun 2017 09:31:41 +0000
"Chen, Xiaoguang" <xiaoguang.chen@intel.com> wrote:

> >-----Original Message-----
> >From: Alex Williamson [mailto:alex.williamson@redhat.com]
> >Sent: Friday, June 02, 2017 11:35 AM
> >To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
> >Cc: kraxel@redhat.com; chris@chris-wilson.co.uk; intel-
> >gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
> >zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-
> >dev@lists.freedesktop.org; Wang, Zhi A <zhi.a.wang@intel.com>; Tian, Kevin
> ><kevin.tian@intel.com>
> >Subject: Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get
> >the dma-buf
> >
> >On Fri, 2 Jun 2017 03:24:35 +0000
> >"Chen, Xiaoguang" <xiaoguang.chen@intel.com> wrote:
> >  
> >> Hi Alex,
> >>  
> >> >-----Original Message-----
> >> >From: Alex Williamson [mailto:alex.williamson@redhat.com]
> >> >Sent: Friday, June 02, 2017 2:08 AM
> >> >To: Chen, Xiaoguang <xiaoguang.chen@intel.com>
> >> >Cc: kraxel@redhat.com; chris@chris-wilson.co.uk; intel-
> >> >gfx@lists.freedesktop.org; linux-kernel@vger.kernel.org;
> >> >zhenyuw@linux.intel.com; Lv, Zhiyuan <zhiyuan.lv@intel.com>;
> >> >intel-gvt- dev@lists.freedesktop.org; Wang, Zhi A
> >> ><zhi.a.wang@intel.com>; Tian, Kevin <kevin.tian@intel.com>
> >> >Subject: Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user
> >> >space can get the dma-buf
> >> >
> >> >On Sat, 27 May 2017 16:38:52 +0800
> >> >Xiaoguang Chen <xiaoguang.chen@intel.com> wrote:
> >> >  
> >> >> User space should create the management fd for the dma-buf operation first.
> >> >> Then user can query the plane information and create dma-buf if
> >> >> necessary using the management fd.
> >> >>
> >> >> Signed-off-by: Xiaoguang Chen <xiaoguang.chen@intel.com>
> >> >> ---
> >> >>  drivers/gpu/drm/i915/gvt/dmabuf.c |  12 ++++
> >> >>  drivers/gpu/drm/i915/gvt/dmabuf.h |   5 ++
> >> >>  drivers/gpu/drm/i915/gvt/gvt.c    |   2 +
> >> >>  drivers/gpu/drm/i915/gvt/gvt.h    |   5 ++
> >> >>  drivers/gpu/drm/i915/gvt/kvmgt.c  | 144  
> >> >++++++++++++++++++++++++++++++++++++++  
> >> >>  drivers/gpu/drm/i915/gvt/vgpu.c   |   1 +
> >> >>  6 files changed, 169 insertions(+)
> >> >>
> >> >> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> >> b/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> >> index c831e91..9759e9a 100644
> >> >> --- a/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> >> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
> >> >> @@ -226,6 +226,7 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu
> >> >> *vgpu,  
> >> >void *args)  
> >> >>  	struct vfio_vgpu_dmabuf_info *gvt_dmabuf = args;
> >> >>  	struct intel_vgpu_fb_info *fb_info;
> >> >>  	int ret;
> >> >> +	struct intel_vgpu_dmabuf_obj *dmabuf_obj;
> >> >>
> >> >>  	ret = intel_vgpu_get_plane_info(dev, vgpu, &gvt_dmabuf->plane_info);
> >> >>  	if (ret != 0)
> >> >> @@ -263,6 +264,17 @@ int intel_vgpu_create_dmabuf(struct intel_vgpu
> >> >> *vgpu,  
> >> >void *args)  
> >> >>  		gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret);
> >> >>  		return ret;
> >> >>  	}
> >> >> +	dmabuf_obj = kmalloc(sizeof(*dmabuf_obj), GFP_KERNEL);
> >> >> +	if (dmabuf_obj == NULL) {
> >> >> +		kfree(fb_info);
> >> >> +		i915_gem_object_put(obj);
> >> >> +		gvt_vgpu_err("alloc dmabuf_obj failed\n");
> >> >> +		return -ENOMEM;
> >> >> +	}
> >> >> +	dmabuf_obj->obj = obj;
> >> >> +	INIT_LIST_HEAD(&dmabuf_obj->list);
> >> >> +	list_add_tail(&dmabuf_obj->list, &vgpu->dmabuf_obj_list_head);
> >> >> +
> >> >>  	gvt_dmabuf->fd = ret;
> >> >>
> >> >>  	return 0;
> >> >> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> >> b/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> >> index 8be9979..cafa781 100644
> >> >> --- a/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> >> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
> >> >> @@ -31,6 +31,11 @@ struct intel_vgpu_fb_info {
> >> >>  	uint32_t fb_size;
> >> >>  };
> >> >>
> >> >> +struct intel_vgpu_dmabuf_obj {
> >> >> +	struct drm_i915_gem_object *obj;
> >> >> +	struct list_head list;
> >> >> +};
> >> >> +
> >> >>  int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);
> >> >> int intel_vgpu_create_dmabuf(struct intel_vgpu *vgpu, void *args);
> >> >>
> >> >> diff --git a/drivers/gpu/drm/i915/gvt/gvt.c
> >> >> b/drivers/gpu/drm/i915/gvt/gvt.c index 2032917..dbc3f86 100644
> >> >> --- a/drivers/gpu/drm/i915/gvt/gvt.c
> >> >> +++ b/drivers/gpu/drm/i915/gvt/gvt.c
> >> >> @@ -54,6 +54,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {
> >> >>  	.vgpu_reset = intel_gvt_reset_vgpu,
> >> >>  	.vgpu_activate = intel_gvt_activate_vgpu,
> >> >>  	.vgpu_deactivate = intel_gvt_deactivate_vgpu,
> >> >> +	.vgpu_query_plane = intel_vgpu_query_plane,
> >> >> +	.vgpu_create_dmabuf = intel_vgpu_create_dmabuf,
> >> >>  };
> >> >>
> >> >>  /**
> >> >> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h
> >> >> b/drivers/gpu/drm/i915/gvt/gvt.h index 763a8c5..a855797 100644
> >> >> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> >> >> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> >> >> @@ -185,8 +185,11 @@ struct intel_vgpu {
> >> >>  		struct kvm *kvm;
> >> >>  		struct work_struct release_work;
> >> >>  		atomic_t released;
> >> >> +		struct vfio_device *vfio_device;
> >> >>  	} vdev;
> >> >>  #endif
> >> >> +	int dmabuf_mgr_fd;
> >> >> +	struct list_head dmabuf_obj_list_head;
> >> >>  };
> >> >>
> >> >>  struct intel_gvt_gm {
> >> >> @@ -467,6 +470,8 @@ struct intel_gvt_ops {
> >> >>  	void (*vgpu_reset)(struct intel_vgpu *);
> >> >>  	void (*vgpu_activate)(struct intel_vgpu *);
> >> >>  	void (*vgpu_deactivate)(struct intel_vgpu *);
> >> >> +	int (*vgpu_query_plane)(struct intel_vgpu *vgpu, void *);
> >> >> +	int (*vgpu_create_dmabuf)(struct intel_vgpu *vgpu, void *);
> >> >>  };
> >> >>
> >> >>
> >> >> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> >> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> >> index 389f072..a079080 100644
> >> >> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> >> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> >> >> @@ -41,6 +41,7 @@
> >> >>  #include <linux/kvm_host.h>
> >> >>  #include <linux/vfio.h>
> >> >>  #include <linux/mdev.h>
> >> >> +#include <linux/anon_inodes.h>
> >> >>
> >> >>  #include "i915_drv.h"
> >> >>  #include "gvt.h"
> >> >> @@ -524,6 +525,125 @@ static int
> >> >> intel_vgpu_reg_init_opregion(struct  
> >> >intel_vgpu *vgpu)  
> >> >>  	return ret;
> >> >>  }
> >> >>
> >> >> +static int kvmgt_get_vfio_device(struct intel_vgpu *vgpu) {
> >> >> +	struct vfio_device *device;
> >> >> +
> >> >> +	device = vfio_device_get_from_dev(mdev_dev(vgpu->vdev.mdev));
> >> >> +	if (device == NULL)
> >> >> +		return -ENODEV;
> >> >> +	vgpu->vdev.vfio_device = device;
> >> >> +
> >> >> +	return 0;
> >> >> +}
> >> >> +
> >> >> +static void kvmgt_put_vfio_device(struct intel_vgpu *vgpu) {
> >> >> +	vfio_device_put(vgpu->vdev.vfio_device);
> >> >> +}
> >> >> +
> >> >> +static int intel_vgpu_dmabuf_mgr_fd_mmap(struct file *file,
> >> >> +		struct vm_area_struct *vma)
> >> >> +{
> >> >> +	return -EPERM;
> >> >> +}
> >> >> +
> >> >> +static int intel_vgpu_dmabuf_mgr_fd_release(struct inode *inode,
> >> >> +		struct file *filp)
> >> >> +{
> >> >> +	struct intel_vgpu *vgpu = filp->private_data;
> >> >> +	struct intel_vgpu_dmabuf_obj *obj;
> >> >> +	struct list_head *pos;
> >> >> +
> >> >> +	if (WARN_ON(!vgpu->vdev.vfio_device))
> >> >> +		return -ENODEV;
> >> >> +
> >> >> +	list_for_each(pos, &vgpu->dmabuf_obj_list_head) {
> >> >> +		obj = container_of(pos, struct intel_vgpu_dmabuf_obj, list);
> >> >> +		if (WARN_ON(!obj))
> >> >> +			return -ENODEV;
> >> >> +		kfree(obj->obj->gvt_info);
> >> >> +		i915_gem_object_put(obj->obj);
> >> >> +		kfree(obj);
> >> >> +		kvmgt_put_vfio_device(vgpu);  
> >> >
> >> >Can we do this?  If I understand, we're releasing all the references
> >> >and allocations for the dmabuf fds on release of the manager fd.
> >> >What happens if the user continues trying to access those dmabuf fds after  
> >this?  
> >> I think we can do this here.
> >> The dma-buf's release function dma_buf_release() will be called by kernel which  
> >means all the created dmabufs will be invalid even we do not release all the
> >references and allocations here.
> >
> >Are you assuming that the user has closed the dmabuf fds?  They could close the
> >manager fd first, should the dmabuf fd continue to work?  
> If guest vm was shutdown it is ok system will release the allocated fds including the management fd and dmabuf fds.
> But if user call the close() to close the management fd deliberately there are problems in current implementation.
> 
> Usually vendor of dma-buf defines its own dma_buf_ops(map, unmap, release.....) so vendor can release the reference and allocations in the release callback.
> The calling sequence is: dma-buf framework's release()->vendor's dma-buf release(i915's in our case).
> 
> But in our case we did not create the dma-buf from the scratch but calling an existing i915 function i915_gem_prime_export() to create a dma-buf which use the i915's dma-buf-ops. 
> In order to use this function we must create a gem object first(the reference count of the gem object is now 1!!!). 
> 
> When i915's dma-buf's release() callback is called it will try to free the gem object associated with the dma-buf if its ref count is 0. But in our case the ref count is 1 so no free callback is called so we can not release allocations there.
> So we have to release our dma-buf releated allocations in the management fd's release callback which means the dma-bufs' life cycle must the same with the management fd.
> 
> The reason we call i915_gem_prime_export() to create a dma-buf is we do not need to change the i915's dma-buf framework.
> 
> So: 1) we maintain current implementation that the dma-bufs have the same lifecycle with the management fd. User can not close the management fd. Or
>         2) we create the dma-buf from scratch which need to change the dma-buf infrastructure of i915.

We cannot simply say that the user isn't allowed to release them in
that order.  If they do, how does it break, including what might mmaps
into those dmabufs provide them access to after the underlying object is
removed. If the policy is that the management fd cannot be released
until the dmabufs are closed, then that needs to be actively enforced.
Otherwise it needs to be supported.  Requiring changes to dmabuf
handling in the i915 code isn't an excuse IMO.  Thanks,

Alex

> >> >> +	}
> >> >> +	kvmgt_put_vfio_device(vgpu);
> >> >> +
> >> >> +	return 0;
> >> >> +}
> >> >> +
> >> >> +static long intel_vgpu_dmabuf_mgr_fd_ioctl(struct file *filp,
> >> >> +		unsigned int ioctl, unsigned long arg) {
> >> >> +	struct intel_vgpu *vgpu = filp->private_data;
> >> >> +	int minsz;
> >> >> +	int ret;
> >> >> +	struct fd f;
> >> >> +
> >> >> +	f = fdget(vgpu->dmabuf_mgr_fd);
> >> >> +	if (!f.file)
> >> >> +		return -EBADF;
> >> >> +
> >> >> +	if (ioctl == VFIO_DEVICE_QUERY_PLANE) {
> >> >> +		struct vfio_vgpu_plane_info info;
> >> >> +
> >> >> +		minsz = offsetofend(struct vfio_vgpu_plane_info, resv);
> >> >> +		if (copy_from_user(&info, (void __user *)arg, minsz)) {
> >> >> +			fdput(f);
> >> >> +			return -EFAULT;
> >> >> +		}
> >> >> +		if (info.argsz < minsz) {
> >> >> +			fdput(f);
> >> >> +			return -EINVAL;
> >> >> +		}
> >> >> +		ret = intel_gvt_ops->vgpu_query_plane(vgpu, &info);
> >> >> +		if (ret != 0) {
> >> >> +			fdput(f);
> >> >> +			gvt_vgpu_err("query plane failed:%d\n", ret);
> >> >> +			return -EINVAL;
> >> >> +		}
> >> >> +		fdput(f);
> >> >> +		return copy_to_user((void __user *)arg, &info, minsz) ?
> >> >> +								-EFAULT : 0;
> >> >> +	} else if (ioctl == VFIO_DEVICE_CREATE_DMABUF) {
> >> >> +		struct vfio_vgpu_dmabuf_info dmabuf;
> >> >> +
> >> >> +		minsz = offsetofend(struct vfio_vgpu_dmabuf_info, resv);
> >> >> +		if (copy_from_user(&dmabuf, (void __user *)arg, minsz)) {
> >> >> +			fdput(f);
> >> >> +			return -EFAULT;
> >> >> +		}
> >> >> +		if (dmabuf.argsz < minsz) {
> >> >> +			fdput(f);
> >> >> +			return -EINVAL;
> >> >> +		}
> >> >> +		ret = kvmgt_get_vfio_device(vgpu);
> >> >> +		if (ret != 0)
> >> >> +			return ret;  
> >> >
> >> >Missed an fdput, though I'm not sure I understand the value of the
> >> >original fdget or the dmabuf_mgr_fd field at all.  dmabuf_mgr_fd is
> >> >only used here, presumably to add a reference to the fd while we're
> >> >in the ioctl, but we're in the ioctl function of that fd, so I think there are  
> >already references elsewhere.  
> >> Make sense. Fdget/fdput can be removed.
> >>  
> >> >  
> >> >> +
> >> >> +		ret = intel_gvt_ops->vgpu_create_dmabuf(vgpu, &dmabuf);
> >> >> +		if (ret != 0) {
> >> >> +			kvmgt_put_vfio_device(vgpu);
> >> >> +			fdput(f);
> >> >> +			return -EINVAL;  
> >> >
> >> >Why not return the errno that vgpu_create_dmabuf provided?  
> >> Will change to use the returned errno.
> >>  
> >> >  
> >> >> +		}
> >> >> +		fdput(f);
> >> >> +		return copy_to_user((void __user *)arg, &dmabuf, minsz) ?
> >> >> +								-EFAULT : 0;
> >> >> +	}
> >> >> +
> >> >> +	fdput(f);
> >> >> +	gvt_vgpu_err("unsupported dmabuf operation\n");
> >> >> +
> >> >> +	return -EINVAL;
> >> >> +}
> >> >> +
> >> >> +static const struct file_operations intel_vgpu_dmabuf_mgr_fd_ops = {
> >> >> +	.release        = intel_vgpu_dmabuf_mgr_fd_release,
> >> >> +	.unlocked_ioctl = intel_vgpu_dmabuf_mgr_fd_ioctl,
> >> >> +	.mmap           = intel_vgpu_dmabuf_mgr_fd_mmap,
> >> >> +	.llseek         = noop_llseek,
> >> >> +};
> >> >>  static int intel_vgpu_create(struct kobject *kobj, struct
> >> >> mdev_device
> >> >> *mdev)  {
> >> >>  	struct intel_vgpu *vgpu = NULL;
> >> >> @@ -1259,6 +1379,30 @@ static long intel_vgpu_ioctl(struct
> >> >> mdev_device  
> >> >*mdev, unsigned int cmd,  
> >> >>  	} else if (cmd == VFIO_DEVICE_RESET) {
> >> >>  		intel_gvt_ops->vgpu_reset(vgpu);
> >> >>  		return 0;
> >> >> +	} else if (cmd == VFIO_DEVICE_GET_FD) {
> >> >> +		int fd;
> >> >> +		u32 type;
> >> >> +		int ret;
> >> >> +
> >> >> +		if (copy_from_user(&type, (void __user *)arg, sizeof(type)))
> >> >> +			return -EINVAL;
> >> >> +		if (type != VFIO_DEVICE_DMABUF_MGR_FD)
> >> >> +			return -EINVAL;
> >> >> +
> >> >> +		ret = kvmgt_get_vfio_device(vgpu);
> >> >> +		if (ret != 0)
> >> >> +			return ret;
> >> >> +
> >> >> +		fd = anon_inode_getfd("intel-vgpu-dmabuf-mgr-fd",
> >> >> +			&intel_vgpu_dmabuf_mgr_fd_ops,
> >> >> +			vgpu, O_RDWR | O_CLOEXEC);
> >> >> +		if (fd < 0) {
> >> >> +			gvt_vgpu_err("create dmabuf mgr fd failed\n");
> >> >> +			return -EINVAL;  
> >> >
> >> >Error path leaks vfio_device reference.  
> >> Will correct in the next version.
> >>  
> >> >  
> >> >> +		}
> >> >> +		vgpu->dmabuf_mgr_fd = fd;  
> >> >
> >> >As above, unclear value of this field, additionally, what if the user
> >> >calls VFIO_DEVICE_GET_FD more than once?  
> >> Ah, good question.
> >> VFIO_DEVICE_GET_FD should only be called once.
> >> And we should add a check if the vgpu->dmabuf_mgr_fd is not 0 which means  
> >VFIO_DEVICE_GET_FD had been called before we should return an error.
> >
> >Except we no longer need that fd and we should probably use an atomic 'opened'
> >so it's not racy.  Thanks,
> >
> >Alex
> >  
> >> >> +
> >> >> +		return fd;
> >> >>  	}
> >> >>
> >> >>  	return 0;
> >> >> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c
> >> >> b/drivers/gpu/drm/i915/gvt/vgpu.c index 6e3cbd8..af6fc74 100644
> >> >> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
> >> >> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
> >> >> @@ -346,6 +346,7 @@ static struct intel_vgpu  
> >> >*__intel_gvt_create_vgpu(struct intel_gvt *gvt,  
> >> >>  	vgpu->gvt = gvt;
> >> >>  	vgpu->sched_ctl.weight = param->weight;
> >> >>  	bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
> >> >> +	INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
> >> >>
> >> >>  	intel_vgpu_init_cfg_space(vgpu, param->primary);
> >> >>  
> >>  
> 

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
  2017-06-02 14:58             ` Alex Williamson
@ 2017-06-02 15:23               ` Gerd Hoffmann
  -1 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-06-02 15:23 UTC (permalink / raw)
  To: Alex Williamson, Chen, Xiaoguang
  Cc: chris, intel-gfx, linux-kernel, zhenyuw, Lv, Zhiyuan,
	intel-gvt-dev, Wang, Zhi A, Tian, Kevin

  Hi,

> > When i915's dma-buf's release() callback is called it will try to
> > free the gem object associated with the dma-buf if its ref count is
> > 0. But in our case the ref count is 1 so no free callback is called
> > so we can not release allocations there.

Why the ref count is one?  Who holds a reference and why?
Maybe it should be the other way around, i.e. the dmabuf holds a
reference on the vgpu instance backing it, i.e. you can't delete the
vgpu while dma-bufs exist?

> We cannot simply say that the user isn't allowed to release them in
> that order.

Yep, not going to fly.  Can happen even unintentionally because we can
pass around dmabufs to other processes.  Example: qemu passes dmabuf to
spice-client, then qemu crashes.  mgmt fd is closed before dmabuf fd
then.  The kernel must be able to handle that.

cheers,
  Gerd

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

* Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
@ 2017-06-02 15:23               ` Gerd Hoffmann
  0 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-06-02 15:23 UTC (permalink / raw)
  To: Alex Williamson, Chen, Xiaoguang
  Cc: intel-gfx, linux-kernel, Lv, Zhiyuan, intel-gvt-dev

  Hi,

> > When i915's dma-buf's release() callback is called it will try to
> > free the gem object associated with the dma-buf if its ref count is
> > 0. But in our case the ref count is 1 so no free callback is called
> > so we can not release allocations there.

Why the ref count is one?  Who holds a reference and why?
Maybe it should be the other way around, i.e. the dmabuf holds a
reference on the vgpu instance backing it, i.e. you can't delete the
vgpu while dma-bufs exist?

> We cannot simply say that the user isn't allowed to release them in
> that order.

Yep, not going to fly.  Can happen even unintentionally because we can
pass around dmabufs to other processes.  Example: qemu passes dmabuf to
spice-client, then qemu crashes.  mgmt fd is closed before dmabuf fd
then.  The kernel must be able to handle that.

cheers,
  Gerd
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* RE: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
  2017-06-02 15:23               ` Gerd Hoffmann
@ 2017-06-05  2:39                 ` Chen, Xiaoguang
  -1 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-06-05  2:39 UTC (permalink / raw)
  To: Gerd Hoffmann, Alex Williamson
  Cc: Tian, Kevin, intel-gfx, linux-kernel, zhenyuw, chris, Lv,
	Zhiyuan, intel-gvt-dev, Wang, Zhi A

Hi, 

>-----Original Message-----
>From: intel-gvt-dev [mailto:intel-gvt-dev-bounces@lists.freedesktop.org] On
>Behalf Of Gerd Hoffmann
>Sent: Friday, June 02, 2017 11:24 PM
>To: Alex Williamson <alex.williamson@redhat.com>; Chen, Xiaoguang
><xiaoguang.chen@intel.com>
>Cc: Tian, Kevin <kevin.tian@intel.com>; intel-gfx@lists.freedesktop.org; linux-
>kernel@vger.kernel.org; zhenyuw@linux.intel.com; chris@chris-wilson.co.uk; Lv,
>Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-dev@lists.freedesktop.org; Wang, Zhi
>A <zhi.a.wang@intel.com>
>Subject: Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get
>the dma-buf
>
>  Hi,
>
>> > When i915's dma-buf's release() callback is called it will try to
>> > free the gem object associated with the dma-buf if its ref count is
>> > 0. But in our case the ref count is 1 so no free callback is called
>> > so we can not release allocations there.
>
>Why the ref count is one?  
The gem object is created by us while creating the dma-buf(the ref count of the gem object is initialized to 1).
Later when user import the dma-buf the ref count of the gem object associate with the dma-buf will increased.
When user finished using the dma-buf it will decrease the ref count.
But the ref count of the gem object will become 1 when all the user finished using the dma-buf because we create the gem object(the test also showing this result).

Typically user only export a dma-buf(no gem object yet) then when user import the dma-buf then a gem object will be created.
But in our case we do not implement the dma-buf from scratch but calling the i915_gem_prime_export() where a gem object is an input parameter.

Chenxg


>Who holds a reference and why?
>Maybe it should be the other way around, i.e. the dmabuf holds a reference on
>the vgpu instance backing it, i.e. you can't delete the vgpu while dma-bufs exist?
>
>> We cannot simply say that the user isn't allowed to release them in
>> that order.
>
>Yep, not going to fly.  Can happen even unintentionally because we can pass
>around dmabufs to other processes.  Example: qemu passes dmabuf to spice-
>client, then qemu crashes.  mgmt fd is closed before dmabuf fd then.  The kernel
>must be able to handle that.
>
>cheers,
>  Gerd
>_______________________________________________
>intel-gvt-dev mailing list
>intel-gvt-dev@lists.freedesktop.org
>https://lists.freedesktop.org/mailman/listinfo/intel-gvt-dev

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

* Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
@ 2017-06-05  2:39                 ` Chen, Xiaoguang
  0 siblings, 0 replies; 74+ messages in thread
From: Chen, Xiaoguang @ 2017-06-05  2:39 UTC (permalink / raw)
  To: Gerd Hoffmann, Alex Williamson
  Cc: intel-gfx, linux-kernel, Lv, Zhiyuan, intel-gvt-dev

Hi, 

>-----Original Message-----
>From: intel-gvt-dev [mailto:intel-gvt-dev-bounces@lists.freedesktop.org] On
>Behalf Of Gerd Hoffmann
>Sent: Friday, June 02, 2017 11:24 PM
>To: Alex Williamson <alex.williamson@redhat.com>; Chen, Xiaoguang
><xiaoguang.chen@intel.com>
>Cc: Tian, Kevin <kevin.tian@intel.com>; intel-gfx@lists.freedesktop.org; linux-
>kernel@vger.kernel.org; zhenyuw@linux.intel.com; chris@chris-wilson.co.uk; Lv,
>Zhiyuan <zhiyuan.lv@intel.com>; intel-gvt-dev@lists.freedesktop.org; Wang, Zhi
>A <zhi.a.wang@intel.com>
>Subject: Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get
>the dma-buf
>
>  Hi,
>
>> > When i915's dma-buf's release() callback is called it will try to
>> > free the gem object associated with the dma-buf if its ref count is
>> > 0. But in our case the ref count is 1 so no free callback is called
>> > so we can not release allocations there.
>
>Why the ref count is one?  
The gem object is created by us while creating the dma-buf(the ref count of the gem object is initialized to 1).
Later when user import the dma-buf the ref count of the gem object associate with the dma-buf will increased.
When user finished using the dma-buf it will decrease the ref count.
But the ref count of the gem object will become 1 when all the user finished using the dma-buf because we create the gem object(the test also showing this result).

Typically user only export a dma-buf(no gem object yet) then when user import the dma-buf then a gem object will be created.
But in our case we do not implement the dma-buf from scratch but calling the i915_gem_prime_export() where a gem object is an input parameter.

Chenxg


>Who holds a reference and why?
>Maybe it should be the other way around, i.e. the dmabuf holds a reference on
>the vgpu instance backing it, i.e. you can't delete the vgpu while dma-bufs exist?
>
>> We cannot simply say that the user isn't allowed to release them in
>> that order.
>
>Yep, not going to fly.  Can happen even unintentionally because we can pass
>around dmabufs to other processes.  Example: qemu passes dmabuf to spice-
>client, then qemu crashes.  mgmt fd is closed before dmabuf fd then.  The kernel
>must be able to handle that.
>
>cheers,
>  Gerd
>_______________________________________________
>intel-gvt-dev mailing list
>intel-gvt-dev@lists.freedesktop.org
>https://lists.freedesktop.org/mailman/listinfo/intel-gvt-dev
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
  2017-06-02  8:38                 ` Gerd Hoffmann
@ 2017-06-05  8:26                   ` Kirti Wankhede
  -1 siblings, 0 replies; 74+ messages in thread
From: Kirti Wankhede @ 2017-06-05  8:26 UTC (permalink / raw)
  To: Gerd Hoffmann, Alex Williamson, Chen, Xiaoguang
  Cc: chris, intel-gfx, linux-kernel, zhenyuw, Lv, Zhiyuan,
	intel-gvt-dev, Wang, Zhi A, Tian, Kevin



On 6/2/2017 2:08 PM, Gerd Hoffmann wrote:
> 
>> struct vfio_vgpu_surface_info {
>>         __u64 start;
>>         __u32 width;
>>         __u32 height;
>>         __u32 stride;
>>         __u32 size;
>>         __u32 x_pos;
>>         __u32 y_pos;
>>         __u32 padding;
>>         /* Only used when VFIO_VGPU_SURFACE_DMABUF_* flags set */
>>         __u64 drm_format_mod;
>>         __u32 drm_format;
> 
> Why for dmabufs only?  Shouldn't the region specify the format too? 
> Even in case you are using a fixed one (say DRM_FORMAT_XRGB8888) you
> can explicitly say so in drm_format (and set drm_format_mod to zero).
> 

Definitions for PIXMAN formats and DRM formats are different. I think
we need a flag to specify the format of surface that vendor driver is
going to provide, PIXMAN or DRM.
If surface is provided through region in PIXMAN format, existing
functions in QEMU can be used to get format from bpp value,
qemu_default_pixman_format(). Similarly, display surface can be updated
by QEMU using qemu_create_displaysurface_from() from mmaped region.

Thanks,
Kirti

> cheers,
>   Gerd
> 

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
@ 2017-06-05  8:26                   ` Kirti Wankhede
  0 siblings, 0 replies; 74+ messages in thread
From: Kirti Wankhede @ 2017-06-05  8:26 UTC (permalink / raw)
  To: Gerd Hoffmann, Alex Williamson, Chen, Xiaoguang
  Cc: intel-gfx, linux-kernel, Lv, Zhiyuan, intel-gvt-dev



On 6/2/2017 2:08 PM, Gerd Hoffmann wrote:
> 
>> struct vfio_vgpu_surface_info {
>>         __u64 start;
>>         __u32 width;
>>         __u32 height;
>>         __u32 stride;
>>         __u32 size;
>>         __u32 x_pos;
>>         __u32 y_pos;
>>         __u32 padding;
>>         /* Only used when VFIO_VGPU_SURFACE_DMABUF_* flags set */
>>         __u64 drm_format_mod;
>>         __u32 drm_format;
> 
> Why for dmabufs only?  Shouldn't the region specify the format too? 
> Even in case you are using a fixed one (say DRM_FORMAT_XRGB8888) you
> can explicitly say so in drm_format (and set drm_format_mod to zero).
> 

Definitions for PIXMAN formats and DRM formats are different. I think
we need a flag to specify the format of surface that vendor driver is
going to provide, PIXMAN or DRM.
If surface is provided through region in PIXMAN format, existing
functions in QEMU can be used to get format from bpp value,
qemu_default_pixman_format(). Similarly, display surface can be updated
by QEMU using qemu_create_displaysurface_from() from mmaped region.

Thanks,
Kirti

> cheers,
>   Gerd
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
  2017-06-05  2:39                 ` Chen, Xiaoguang
@ 2017-06-06  7:35                   ` Gerd Hoffmann
  -1 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-06-06  7:35 UTC (permalink / raw)
  To: Chen, Xiaoguang, Alex Williamson
  Cc: Tian, Kevin, intel-gfx, linux-kernel, zhenyuw, chris, Lv,
	Zhiyuan, intel-gvt-dev, Wang, Zhi A

  Hi,

> > Why the ref count is one?  
> 
> The gem object is created by us while creating the dma-buf(the ref
> count of the gem object is initialized to 1).
> Later when user import the dma-buf the ref count of the gem object
> associate with the dma-buf will increased.

Creating the dma-buf should increase the gem object reference count
too.  So you should be able to unref the gem object after creating the
dma-buf.  That way the dma-buf is the only instance holding a reference
to the gem object, and when the dma-buf goes away (due to userspace
closing all file handles referring to it) the gem object will be
released too because the refcount goes down to zero then.

cheers,
  Gerd

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

* Re: [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf
@ 2017-06-06  7:35                   ` Gerd Hoffmann
  0 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-06-06  7:35 UTC (permalink / raw)
  To: Chen, Xiaoguang, Alex Williamson
  Cc: intel-gfx, linux-kernel, Lv, Zhiyuan, intel-gvt-dev

  Hi,

> > Why the ref count is one?  
> 
> The gem object is created by us while creating the dma-buf(the ref
> count of the gem object is initialized to 1).
> Later when user import the dma-buf the ref count of the gem object
> associate with the dma-buf will increased.

Creating the dma-buf should increase the gem object reference count
too.  So you should be able to unref the gem object after creating the
dma-buf.  That way the dma-buf is the only instance holding a reference
to the gem object, and when the dma-buf goes away (due to userspace
closing all file handles referring to it) the gem object will be
released too because the refcount goes down to zero then.

cheers,
  Gerd
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
  2017-06-05  8:26                   ` Kirti Wankhede
@ 2017-06-06  7:59                     ` Gerd Hoffmann
  -1 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-06-06  7:59 UTC (permalink / raw)
  To: Kirti Wankhede, Alex Williamson, Chen, Xiaoguang
  Cc: chris, intel-gfx, linux-kernel, zhenyuw, Lv, Zhiyuan,
	intel-gvt-dev, Wang, Zhi A, Tian, Kevin

On Mon, 2017-06-05 at 13:56 +0530, Kirti Wankhede wrote:
> 
> On 6/2/2017 2:08 PM, Gerd Hoffmann wrote:
> > 
> > > struct vfio_vgpu_surface_info {
> > >         __u64 start;
> > >         __u32 width;
> > >         __u32 height;
> > >         __u32 stride;
> > >         __u32 size;
> > >         __u32 x_pos;
> > >         __u32 y_pos;
> > >         __u32 padding;
> > >         /* Only used when VFIO_VGPU_SURFACE_DMABUF_* flags set */
> > >         __u64 drm_format_mod;
> > >         __u32 drm_format;
> > 
> > Why for dmabufs only?  Shouldn't the region specify the format
> > too? 
> > Even in case you are using a fixed one (say
> > DRM_FORMAT_XRGB8888) you
> > can explicitly say so in drm_format (and set drm_format_mod to
> > zero).
> > 
> 
> Definitions for PIXMAN formats and DRM formats are different. I think
> we need a flag to specify the format of surface that vendor driver is
> going to provide, PIXMAN or DRM.

No need to put that into the ioctl interface.  First, the kernel should
not worry about what userspace uses to process the data.  Second (most)
drm formats can trivially be mapped into pixman formats.

For example: PIXMAN_x8r8g8b8 (little endian) == DRM_FORMAT_XRGB8888

> If surface is provided through region in PIXMAN format, existing
> functions in QEMU can be used to get format from bpp value,
> qemu_default_pixman_format(). Similarly, display surface can be
> updated
> by QEMU using qemu_create_displaysurface_from() from mmaped region.

A thin wrapper which accepts a struct vfio_vgpu_surface_info and
translates that into a qemu_create_displaysurface_from() call should be
pretty small.

cheers,
  Gerd

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

* Re: [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations
@ 2017-06-06  7:59                     ` Gerd Hoffmann
  0 siblings, 0 replies; 74+ messages in thread
From: Gerd Hoffmann @ 2017-06-06  7:59 UTC (permalink / raw)
  To: Kirti Wankhede, Alex Williamson, Chen, Xiaoguang
  Cc: intel-gfx, linux-kernel, Lv, Zhiyuan, intel-gvt-dev

On Mon, 2017-06-05 at 13:56 +0530, Kirti Wankhede wrote:
> 
> On 6/2/2017 2:08 PM, Gerd Hoffmann wrote:
> > 
> > > struct vfio_vgpu_surface_info {
> > >         __u64 start;
> > >         __u32 width;
> > >         __u32 height;
> > >         __u32 stride;
> > >         __u32 size;
> > >         __u32 x_pos;
> > >         __u32 y_pos;
> > >         __u32 padding;
> > >         /* Only used when VFIO_VGPU_SURFACE_DMABUF_* flags set */
> > >         __u64 drm_format_mod;
> > >         __u32 drm_format;
> > 
> > Why for dmabufs only?  Shouldn't the region specify the format
> > too? 
> > Even in case you are using a fixed one (say
> > DRM_FORMAT_XRGB8888) you
> > can explicitly say so in drm_format (and set drm_format_mod to
> > zero).
> > 
> 
> Definitions for PIXMAN formats and DRM formats are different. I think
> we need a flag to specify the format of surface that vendor driver is
> going to provide, PIXMAN or DRM.

No need to put that into the ioctl interface.  First, the kernel should
not worry about what userspace uses to process the data.  Second (most)
drm formats can trivially be mapped into pixman formats.

For example: PIXMAN_x8r8g8b8 (little endian) == DRM_FORMAT_XRGB8888

> If surface is provided through region in PIXMAN format, existing
> functions in QEMU can be used to get format from bpp value,
> qemu_default_pixman_format(). Similarly, display surface can be
> updated
> by QEMU using qemu_create_displaysurface_from() from mmaped region.

A thin wrapper which accepts a struct vfio_vgpu_surface_info and
translates that into a qemu_create_displaysurface_from() call should be
pretty small.

cheers,
  Gerd
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

end of thread, other threads:[~2017-06-06  7:59 UTC | newest]

Thread overview: 74+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-27  8:38 [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g Xiaoguang Chen
2017-05-27  8:38 ` Xiaoguang Chen
2017-05-27  8:38 ` [PATCH v6 1/6] drm/i915/gvt: Extend the GVT-g architecture to support vfio device region Xiaoguang Chen
2017-05-27  8:38   ` Xiaoguang Chen
2017-05-27  8:38 ` [PATCH v6 2/6] drm/i915/gvt: OpRegion support for GVT-g Xiaoguang Chen
2017-05-27  8:38   ` Xiaoguang Chen
2017-05-31  4:47   ` Zhenyu Wang
2017-05-31  4:47     ` Zhenyu Wang
2017-05-31  6:22     ` Chen, Xiaoguang
2017-05-31  6:22       ` Chen, Xiaoguang
2017-05-31  6:30       ` Zhenyu Wang
2017-05-31  6:30         ` Zhenyu Wang
2017-05-31  6:44         ` Chen, Xiaoguang
2017-05-31  6:44           ` Chen, Xiaoguang
2017-05-27  8:38 ` [PATCH v6 3/6] drm/i915/gvt: Frame buffer decoder " Xiaoguang Chen
2017-05-27  8:38   ` Xiaoguang Chen
2017-05-31  5:12   ` Zhenyu Wang
2017-05-31  5:12     ` Zhenyu Wang
2017-05-31  6:46     ` Chen, Xiaoguang
2017-05-31  6:46       ` Chen, Xiaoguang
2017-05-27  8:38 ` [PATCH v6 4/6] vfio: Define vfio based vgpu's dma-buf operations Xiaoguang Chen
2017-05-29  7:20   ` Gerd Hoffmann
2017-05-29  7:20     ` Gerd Hoffmann
2017-05-31  6:18     ` Chen, Xiaoguang
2017-05-31  6:18       ` Chen, Xiaoguang
2017-05-31 17:22       ` Kirti Wankhede
2017-05-31 17:22         ` Kirti Wankhede
2017-06-01  3:01         ` Chen, Xiaoguang
2017-06-01  3:01           ` Chen, Xiaoguang
2017-06-01 16:38           ` Alex Williamson
2017-06-01 16:38             ` Alex Williamson
2017-06-01 18:46             ` Kirti Wankhede
2017-06-01 18:46               ` Kirti Wankhede
2017-06-02  8:38               ` Gerd Hoffmann
2017-06-02  8:38                 ` Gerd Hoffmann
2017-06-05  8:26                 ` Kirti Wankhede
2017-06-05  8:26                   ` Kirti Wankhede
2017-06-06  7:59                   ` Gerd Hoffmann
2017-06-06  7:59                     ` Gerd Hoffmann
2017-05-27  8:38 ` [PATCH v6 5/6] drm/i915/gvt: Dmabuf support for GVT-g Xiaoguang Chen
2017-05-27  8:38   ` Xiaoguang Chen
2017-05-31 12:04   ` Gerd Hoffmann
2017-05-31 12:04     ` Gerd Hoffmann
2017-06-01  3:02     ` Chen, Xiaoguang
2017-06-01  3:02       ` Chen, Xiaoguang
2017-06-01  9:15   ` Chris Wilson
2017-06-01  9:15     ` Chris Wilson
2017-05-27  8:38 ` [PATCH v6 6/6] drm/i915/gvt: Adding interface so user space can get the dma-buf Xiaoguang Chen
2017-05-27  8:38   ` Xiaoguang Chen
2017-06-01 18:08   ` Alex Williamson
2017-06-01 18:08     ` Alex Williamson
2017-06-02  3:24     ` Chen, Xiaoguang
2017-06-02  3:24       ` Chen, Xiaoguang
2017-06-02  3:34       ` Alex Williamson
2017-06-02  3:34         ` Alex Williamson
2017-06-02  9:31         ` Chen, Xiaoguang
2017-06-02  9:31           ` Chen, Xiaoguang
2017-06-02 14:58           ` Alex Williamson
2017-06-02 14:58             ` Alex Williamson
2017-06-02 15:23             ` Gerd Hoffmann
2017-06-02 15:23               ` Gerd Hoffmann
2017-06-05  2:39               ` Chen, Xiaoguang
2017-06-05  2:39                 ` Chen, Xiaoguang
2017-06-06  7:35                 ` Gerd Hoffmann
2017-06-06  7:35                   ` Gerd Hoffmann
2017-05-27  8:44 ` ✗ Fi.CI.BAT: failure for drm/i915/gvt: dma-buf support for GVT-g (rev6) Patchwork
2017-05-30 10:23 ` [PATCH v6 0/6] drm/i915/gvt: Dma-buf support for GVT-g Gerd Hoffmann
2017-05-30 10:23   ` Gerd Hoffmann
2017-05-31  2:29   ` Chen, Xiaoguang
2017-05-31  2:29     ` Chen, Xiaoguang
2017-05-31  8:59     ` Gerd Hoffmann
2017-05-31  8:59       ` Gerd Hoffmann
2017-05-31  9:07       ` Chen, Xiaoguang
2017-05-31  9:07         ` Chen, Xiaoguang

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.