All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/7] drm/i915/gvt: Enable vGPU local display direct flip
@ 2018-12-03  7:35 Tina Zhang
  2018-12-03  7:35 ` [RFC PATCH 1/7] drm/i915: Introduce meta framebuffer Tina Zhang
                   ` (7 more replies)
  0 siblings, 8 replies; 14+ messages in thread
From: Tina Zhang @ 2018-12-03  7:35 UTC (permalink / raw)
  Cc: kalyan.kondapally, intel-gfx, intel-gvt-dev


This series is used to enable the local display direct flip feature for vGPUs
on Gen9.

vGPU Local Display Direct Flip Feature
--------------------------------------

This feature provides vGPUs with the capablities to control a subset of
the local HW display engine resources to display output from a virtualized
environment.

With this local display direct flip feature, vGPUs can leverage HW display
engine's capablities to compose their framebuffers and post the final outputs
to the local display monitors.


Design Ideas
------------

1) Plane assignment

Host userspace is in charge of the plane assignment.The idea is to use a special
intel_framebuffer object called meta framebuffer to stand for a vGPU's plane in
the host-side, so that the plane assignment can be achieved with the existing KMS
ioctls (e.g. DRM_IOCTL_MODE_SETPLANE).

Meta framebuffers are created and initilized during vGPU creation. In order to
let userspace get the userspace ids of a vGPU's meta framebuffers, a new attribute
called "plane_id_index" is proposed. Userspace can echo the plane number to the
attribution and then use cat to dump the userspace id of the meta framebuffer
standing for that plane in the host-side.

The assignment doesn't need to be happened before a VM running with the vGPU. The
assignment can be dynamic.

2) vGPU page flip operation mediation

The main idea is to leverage the atomic framework in host to update the plane
registers on behalf of vGPUs, as vGPU cannot directly program these registers in
VMs. Here are the steps:

Step 1: GVT-g gets the plane state values from vGPU's plane registers.

Step 2: GVT-g updates the fields of the meta framebuffer with the values decoded
from the vGPU's plane state.

The fields of the meta framebuffer will be updated every time when the vGPU does
page flip operation so that the meta framebuffer can describe the vGPU's framebuffer
attached on the plane all the time.

Although most of the virtual plane state can be decoded back into the fields of
the drm_framebuffer to leverage the host atomic framework to program this state
values to the hardware plane registers, there are still a few of them cannot be
handled in this way. For the plane state values like PLANE_SURF, this patch set
just programs the HW register with the values got from vGPU's plane registers
directly.

Step 3: With this special drm_framebuffer, the vGPU's direct page flip can be
conducted through the host atomic framework. And we leverage both async atomic
plane update framework and sync atomic plane update framework. If the vGPU's page
flip request can be satisfied through updating plane registers, the async atomic
plane update is used as the fast path to do the plane update. Otherwise, it means
the vGPU's page flip needs to recalculate display resources like DDB, so the sync
atomic plane update framework is used instead.

3) vGPU interrupt

This patch-set provides each vGPU with the hardware vblank interrupt event.


Patch-set Organization
----------------------

- drm/i915: Introduce meta framebuffer
  Introduce the meta framebuffer object.

- drm/i915/gvt: Use meta fbs to stand for vGPU's planes
  Make GVT-g as the meta framebuffer producor and introduce a new attribute
  called "plane_id_index" for userspace to get the id through sys.

- drm/i915: Introduce async plane update to i915
- drm/i915: Extend async plane update to other planes
  These two patches are used to discuss the async plane update i915 support.

- drm/i915/gvt: Introduce vGPU plane page flip framework
- drm/i915/gvt: Enable guest direct page flip
  These are about the vGPU page flip operation mediation implementation.

- drm/i915/gvt: Introduce HW Vblank interrupt to vGPU
  Enable vGPU's to use HW vblank interrupt event.


To-do list
----------

Here are some interesting candidates:

- Assigning planes with defaults during host booting
  This feature aims to provide a way for host i915 do the plane assignment without
  userspace's help.
- Host i915 DDB fixed allocation support.
  This feature will provide a fixed DDB allocation for each HW planes.
- Cursor plane assignment
  This work can enable cursor plane assignment.
- Guest YUV framebuffer decoding
  Some YUV framebuffer information cannot be decoded correctly. More fields might
  be added to meta_framebuffer structure to save them, just like what we hand the
  PLANE_SURF in this series.
- Guest framebuffer rotation feature support
  Need to be handled like the PLANE_SURF in the series.

Tina Zhang (7):
  drm/i915: Introduce meta framebuffer
  drm/i915/gvt: Use meta fbs to stand for vGPU's planes
  drm/i915: Introduce async plane update to i915
  drm/i915: Extend async plane update to other planes
  drm/i915/gvt: Introduce vGPU plane page flip framework
  drm/i915/gvt: Enable guest direct page flip
  drm/i915/gvt: Introduce HW Vblank interrupt to vGPU

 drivers/gpu/drm/i915/gvt/display.c        | 445 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/gvt/display.h        |  21 +-
 drivers/gpu/drm/i915/gvt/gvt.c            | 112 ++++++++
 drivers/gpu/drm/i915/gvt/gvt.h            |  19 ++
 drivers/gpu/drm/i915/gvt/handlers.c       |  42 ++-
 drivers/gpu/drm/i915/gvt/interrupt.c      |  54 ++++
 drivers/gpu/drm/i915/gvt/interrupt.h      |   2 +
 drivers/gpu/drm/i915/gvt/kvmgt.c          |  46 +++
 drivers/gpu/drm/i915/intel_atomic_plane.c |  66 +++++
 drivers/gpu/drm/i915/intel_display.c      |  11 +
 drivers/gpu/drm/i915/intel_drv.h          |  15 +
 drivers/gpu/drm/i915/intel_sprite.c       |  19 +-
 12 files changed, 836 insertions(+), 16 deletions(-)

-- 
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] 14+ messages in thread

* [RFC PATCH 1/7] drm/i915: Introduce meta framebuffer
  2018-12-03  7:35 [RFC PATCH 0/7] drm/i915/gvt: Enable vGPU local display direct flip Tina Zhang
@ 2018-12-03  7:35 ` Tina Zhang
  2018-12-03  7:35 ` [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's planes Tina Zhang
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Tina Zhang @ 2018-12-03  7:35 UTC (permalink / raw)
  Cc: Daniel Vetter, intel-gfx, kalyan.kondapally, intel-gvt-dev

Meta framebuffer, as a special intel_framebuffer, is used to describe
an intel_framebuffer which is already pinned to the GGTT space and can
be accessed by the display engine HW.

In the virtualization world, with the help of GVT-g, vGPUs can share
the entire global GTT space and be able to pin their framebuffers to
the global GTT space. However, vGPUs cannot be able to access the
display HW registers which are fully controlled by host i915.

In order to support the vGPU local display direct flip feature, which
is the vGPU can have several assigned display planes and can post its
framebuffers to those assigned planes, host i915 must program the
display plane registers on behalf of the vGPU. However, without the
knowledge of the vGPU's framebuffers, host i915 cannot program those
plane registers correctly. To fill this gap, the meta framebuffer is
introduced.

The meta framebuffer is used by host i915 to describe the framebuffer
pinned to the GGTT space by guest OS.

Signed-off-by: Tina Zhang <tina.zhang@intel.com>
Signed-off-by: Zhi Wang <zhi.a.wang@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_drv.h    | 15 +++++++++++++++
 drivers/gpu/drm/i915/intel_sprite.c | 19 ++++++++++++++++++-
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f575ba2..6cf345c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -187,6 +187,12 @@ enum intel_output_type {
 #define INTEL_DSI_VIDEO_MODE	0
 #define INTEL_DSI_COMMAND_MODE	1
 
+
+enum {
+	INTEL_META_FB_VGPU = 1,
+	INTEL_META_FB_MAX,
+};
+
 struct intel_framebuffer {
 	struct drm_framebuffer base;
 	struct intel_rotation_info rot_info;
@@ -200,6 +206,15 @@ struct intel_framebuffer {
 		unsigned int x, y;
 		unsigned int pitch; /* pixels */
 	} rotated[2];
+
+	struct {
+		u32 type_id;
+		u32 ggtt_offset;
+		void *private;
+		void (*update)(struct intel_framebuffer *intel_fb,
+			       enum pipe pipe, enum plane_id plane_id);
+		bool should_be_offscreen;
+	} meta_fb;
 };
 
 struct intel_fbdev {
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index abe1938..16a0a5d4 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -486,9 +486,26 @@ skl_program_plane(struct intel_plane *plane,
 	uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
 	struct intel_plane *linked = plane_state->linked_plane;
 	const struct drm_framebuffer *fb = plane_state->base.fb;
+	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 	u8 alpha = plane_state->base.alpha >> 8;
 	unsigned long irqflags;
 	u32 keymsk, keymax;
+	u32 offset;
+
+	if (intel_fb->meta_fb.type_id == INTEL_META_FB_VGPU) {
+
+		if (!intel_fb->meta_fb.update)
+			return;
+
+		intel_fb->meta_fb.update(intel_fb, pipe, plane_id);
+
+		if (intel_fb->meta_fb.should_be_offscreen)
+			return;
+
+		offset = intel_fb->meta_fb.ggtt_offset;
+	} else {
+		offset = intel_plane_ggtt_offset(plane_state);
+	}
 
 	/* Sizes are 0 based */
 	src_w--;
@@ -558,7 +575,7 @@ skl_program_plane(struct intel_plane *plane,
 
 	I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
 	I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
-		      intel_plane_ggtt_offset(plane_state) + surf_addr);
+		      offset + surf_addr);
 
 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
-- 
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] 14+ messages in thread

* [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's planes
  2018-12-03  7:35 [RFC PATCH 0/7] drm/i915/gvt: Enable vGPU local display direct flip Tina Zhang
  2018-12-03  7:35 ` [RFC PATCH 1/7] drm/i915: Introduce meta framebuffer Tina Zhang
@ 2018-12-03  7:35 ` Tina Zhang
  2018-12-03  8:21   ` Zhenyu Wang
  2018-12-03  7:35 ` [RFC PATCH 3/7] drm/i915: Introduce async plane update to i915 Tina Zhang
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 14+ messages in thread
From: Tina Zhang @ 2018-12-03  7:35 UTC (permalink / raw)
  Cc: intel-gfx, kalyan.kondapally, intel-gvt-dev

Create and initialize vGPU meta framebuffers during vGPU's creation.
Each meta framebuffer is an intel_framebuffer. Userspace can get the
userspace visible identifier of that meta framebuffer by accessing
plane_id_index attribute.

For example:
In "/sys/bus/pci/devices/0000\:00\:02.0/$vGPU_id/intel_vgpu/" directory,

   /* plane_id_index: pipe#(bit16:8) and plane#(bit7:0)*/
   echo "0x10" > plane_index_id //Set the index to the plane 0 of pipe 1

   /*
    * Dump userspace visible identifier of the meta framebuffer
    * standing for the primary plane of the vGPU's pipe one
    */
   cat plane_index_id //dump the id for plane 0 of pipe 1

Then userspace can use this id with the exsting KMS IOCTL, e.g.
drmModeSetPlane, to assign a physical plane to this virtual plane.

Signed-off-by: Tina Zhang <tina.zhang@intel.com>
Cc: Zhenyu Wang <zhenyuw@linux.intel.com>
Cc: Zhi Wang <zhi.a.wang@intel.com>
---
 drivers/gpu/drm/i915/gvt/display.c | 150 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/gvt.h     |  16 ++++
 drivers/gpu/drm/i915/gvt/kvmgt.c   |  46 ++++++++++++
 3 files changed, 212 insertions(+)

diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
index df1e141..a9176a1 100644
--- a/drivers/gpu/drm/i915/gvt/display.c
+++ b/drivers/gpu/drm/i915/gvt/display.c
@@ -442,6 +442,152 @@ void intel_gvt_emulate_vblank(struct intel_gvt *gvt)
 	mutex_unlock(&gvt->lock);
 }
 
+struct intel_vgpu_fb_meta_data {
+	u32 vgpu_plane_id; /* vgpu_id(23:16):vgpu_pipe(15:8):vgpu_plane(7:0)*/
+	struct intel_vgpu *vgpu; // the vGPU this meta_fb belongs to
+};
+
+static void meta_fb_destroy(struct drm_framebuffer *fb)
+{
+	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+
+	if (intel_fb->meta_fb.type_id != INTEL_META_FB_VGPU)
+		return;
+
+	kfree(intel_fb->meta_fb.private);
+	intel_fb->meta_fb.private = NULL;
+
+	drm_framebuffer_cleanup(fb);
+	kfree(intel_fb);
+}
+
+static void clean_meta_fb(struct intel_vgpu *vgpu)
+{
+	enum pipe pipe;
+	enum plane_id plane_id;
+	struct intel_framebuffer *intel_fb;
+
+	for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) {
+		for (plane_id = 0; plane_id < I915_MAX_PLANES; plane_id++) {
+			intel_fb = vgpu->display.meta_fbs.meta_fb[pipe][plane_id];
+			if (!intel_fb)
+				drm_framebuffer_put(&intel_fb->base);
+
+			intel_fb = NULL;
+		}
+	}
+}
+
+static int meta_fb_create_handle(struct drm_framebuffer *fb,
+				 struct drm_file *file,
+				 unsigned int *handle)
+{
+	return -ENODEV;
+}
+
+static int meta_fb_dirty(struct drm_framebuffer *fb,
+			 struct drm_file *file,
+			 unsigned int flags,
+			 unsigned int color,
+			 struct drm_clip_rect *clips,
+			 unsigned int num_clips)
+{
+	return 0;
+}
+
+static const struct drm_framebuffer_funcs meta_fb_funcs = {
+	.destroy = meta_fb_destroy,
+	.create_handle = meta_fb_create_handle,
+	.dirty = meta_fb_dirty,
+};
+
+static void meta_fb_update(struct intel_framebuffer *intel_fb,
+			   enum pipe pipe, enum plane_id plane_id)
+{
+	struct intel_vgpu_fb_meta_data *meta_data;
+	struct intel_gvt *gvt;
+
+	if (!intel_fb || intel_fb->meta_fb.type_id != INTEL_META_FB_VGPU)
+		return;
+
+	meta_data = intel_fb->meta_fb.private;
+	gvt = meta_data->vgpu->gvt;
+
+	if (gvt->assigned_plane[pipe][plane_id].vgpu_plane_id !=
+						meta_data->vgpu_plane_id) {
+		gvt->assigned_plane[pipe][plane_id].vgpu_plane_id =
+						meta_data->vgpu_plane_id;
+		gvt->assigned_plane[pipe][plane_id].framebuffer_id =
+						intel_fb->base.base.id;
+		intel_fb->meta_fb.ggtt_offset = 0;
+		intel_fb->meta_fb.should_be_offscreen = true;
+	} else if (!intel_fb->meta_fb.ggtt_offset) {
+		intel_fb->meta_fb.should_be_offscreen = true;
+	} else {
+		intel_fb->meta_fb.should_be_offscreen = false;
+	}
+}
+
+static int init_meta_fb(struct intel_vgpu *vgpu)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	struct intel_vgpu_fb_meta_data *meta_data;
+	struct drm_mode_fb_cmd2 mode_cmd;
+	struct intel_framebuffer *intel_fb;
+	enum pipe pipe;
+	enum plane_id plane_id;
+	int ret = 0;
+
+	for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) {
+		for (plane_id = 0; plane_id < I915_MAX_PLANES; plane_id++) {
+			intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
+			if (!intel_fb)
+				return -ENOMEM;
+
+			/*
+			 * Create a drm_framebuffer with defaults.
+			 */
+			mode_cmd.pixel_format = DRM_FORMAT_XRGB8888;
+			mode_cmd.width = dev_priv->drm.mode_config.max_width;
+			mode_cmd.height = dev_priv->drm.mode_config.max_height;
+			mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
+			mode_cmd.handles[0] = 0;
+			mode_cmd.pitches[0] = mode_cmd.width * 4;
+			mode_cmd.offsets[0] = 0;
+			mode_cmd.modifier[0] = DRM_FORMAT_MOD_LINEAR;
+
+			drm_helper_mode_fill_fb_struct(&dev_priv->drm,
+						       &intel_fb->base, &mode_cmd);
+
+			ret = drm_framebuffer_init(&dev_priv->drm,
+						   &intel_fb->base, &meta_fb_funcs);
+			if (ret) {
+				DRM_ERROR("%s: framebuffer init failed %d\n",
+					  __func__, ret);
+				kfree(intel_fb);
+				return ret;
+			}
+
+			meta_data = kmalloc(sizeof(struct intel_vgpu_fb_meta_data),
+					    GFP_KERNEL);
+			if (unlikely(!meta_data)) {
+				return -ENOMEM;
+			}
+
+			meta_data->vgpu_plane_id = (vgpu->id << 16) |
+				(pipe << 8) | plane_id;
+			meta_data->vgpu = vgpu;
+
+			intel_fb->meta_fb.private = meta_data;
+			intel_fb->meta_fb.update = meta_fb_update;
+			intel_fb->meta_fb.type_id = INTEL_META_FB_VGPU;
+
+			vgpu->display.meta_fbs.meta_fb[pipe][plane_id] = intel_fb;
+		}
+	}
+	return 0;
+}
+
 /**
  * intel_vgpu_clean_display - clean vGPU virtual display emulation
  * @vgpu: a vGPU
@@ -457,6 +603,8 @@ void intel_vgpu_clean_display(struct intel_vgpu *vgpu)
 		clean_virtual_dp_monitor(vgpu, PORT_D);
 	else
 		clean_virtual_dp_monitor(vgpu, PORT_B);
+
+	clean_meta_fb(vgpu);
 }
 
 /**
@@ -476,6 +624,8 @@ int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution)
 
 	intel_vgpu_init_i2c_edid(vgpu);
 
+	init_meta_fb(vgpu);
+
 	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
 		return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D,
 						resolution);
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index 31f6cdb..0ab10b0 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -131,10 +131,16 @@ struct intel_vgpu_opregion {
 
 #define vgpu_opregion(vgpu) (&(vgpu->opregion))
 
+struct intel_vgpu_meta_fbs {
+	struct intel_framebuffer *meta_fb[I915_MAX_PIPES][I915_MAX_PLANES];
+	u32 plane_id_index;
+};
+
 struct intel_vgpu_display {
 	struct intel_vgpu_i2c_edid i2c_edid;
 	struct intel_vgpu_port ports[I915_MAX_PORTS];
 	struct intel_vgpu_sbi sbi;
+	struct intel_vgpu_meta_fbs meta_fbs;
 };
 
 struct vgpu_sched_ctl {
@@ -301,6 +307,13 @@ struct intel_vgpu_type {
 	enum intel_vgpu_edid resolution;
 };
 
+struct assigned_plane {
+	u32 vgpu_plane_id;
+
+	/* userspace visible identifier */
+	int framebuffer_id;
+};
+
 struct intel_gvt {
 	/* GVT scope lock, protect GVT itself, and all resource currently
 	 * not yet protected by special locks(vgpu and scheduler lock).
@@ -340,6 +353,9 @@ struct intel_gvt {
 	} engine_mmio_list;
 
 	struct dentry *debugfs_root;
+
+	/* vGPU plane assignment */
+	struct assigned_plane assigned_plane[I915_MAX_PIPES][I915_MAX_PLANES];
 };
 
 static inline struct intel_gvt *to_gvt(struct drm_i915_private *i915)
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index c107214..7f4704d 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -1420,12 +1420,58 @@ hw_id_show(struct device *dev, struct device_attribute *attr,
 	return sprintf(buf, "\n");
 }
 
+static ssize_t
+plane_id_index_show(struct device *dev, struct device_attribute *attr,
+	 char *buf)
+{
+	struct mdev_device *mdev = mdev_from_dev(dev);
+
+	if (mdev) {
+		struct intel_vgpu *vgpu = (struct intel_vgpu *)
+			mdev_get_drvdata(mdev);
+		enum pipe pipe = vgpu->display.meta_fbs.plane_id_index &
+			0x000000F0;
+		enum plane_id plane_id = vgpu->display.meta_fbs.plane_id_index &
+			0x0000000F;
+
+		if ((pipe < I915_MAX_PIPES || plane_id < I915_MAX_PLANES) &&
+			vgpu->display.meta_fbs.meta_fb[pipe][plane_id]) {
+			return sprintf(buf, "%u\n",
+			       vgpu->display.meta_fbs.meta_fb[pipe][plane_id]->base.base.id);
+		}
+	}
+	return sprintf(buf, "\n");
+}
+
+static ssize_t
+plane_id_index_store(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t n)
+{
+	struct mdev_device *mdev = mdev_from_dev(dev);
+	ssize_t ret;
+	u32 val;
+
+	ret = kstrtou32(buf, 0, &val);
+	if (ret)
+		return ret;
+
+	if (mdev) {
+		struct intel_vgpu *vgpu = (struct intel_vgpu *)
+			mdev_get_drvdata(mdev);
+		vgpu->display.meta_fbs.plane_id_index = val;
+	}
+
+	return n;
+}
+
 static DEVICE_ATTR_RO(vgpu_id);
 static DEVICE_ATTR_RO(hw_id);
+static DEVICE_ATTR_RW(plane_id_index);
 
 static struct attribute *intel_vgpu_attrs[] = {
 	&dev_attr_vgpu_id.attr,
 	&dev_attr_hw_id.attr,
+	&dev_attr_plane_id_index.attr,
 	NULL
 };
 
-- 
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] 14+ messages in thread

* [RFC PATCH 3/7] drm/i915: Introduce async plane update to i915
  2018-12-03  7:35 [RFC PATCH 0/7] drm/i915/gvt: Enable vGPU local display direct flip Tina Zhang
  2018-12-03  7:35 ` [RFC PATCH 1/7] drm/i915: Introduce meta framebuffer Tina Zhang
  2018-12-03  7:35 ` [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's planes Tina Zhang
@ 2018-12-03  7:35 ` Tina Zhang
  2018-12-03  7:35 ` [RFC PATCH 4/7] drm/i915: Extend async plane update to other planes Tina Zhang
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Tina Zhang @ 2018-12-03  7:35 UTC (permalink / raw)
  Cc: Daniel Vetter, intel-gfx, Gustavo Padovan, Helen Koike,
	Enric Balletbo i Serra, kalyan.kondapally, intel-gvt-dev

This patch is separated from the following patch:
https://lists.freedesktop.org/archives/dri-devel/2018-June/179592.html

This patch introduces the implementation async plane update callbacks
to i915. The original idea is to use async plane update framework to
update cursors.

The next patch of this series try to extend this idea to support other
planes.

Signed-off-by: Tina Zhang <tina.zhang@intel.com>
Cc: Gustavo Padovan <gustavo.padovan@collabora.com>
Cc: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Cc: Helen Koike <helen.koike@collabora.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic_plane.c | 69 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c      | 11 +++++
 2 files changed, 80 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
index 905f8ef..dddd3a7 100644
--- a/drivers/gpu/drm/i915/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
@@ -217,10 +217,79 @@ void intel_update_planes_on_crtc(struct intel_atomic_state *old_state,
 	}
 }
 
+static int intel_plane_atomic_async_check(struct drm_plane *plane,
+					  struct drm_plane_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+
+	if (plane->type != DRM_PLANE_TYPE_CURSOR)
+		return -EINVAL;
+
+	crtc_state = drm_atomic_get_existing_crtc_state(state->state,
+							state->crtc);
+	if (WARN_ON(!crtc_state))
+		return -EINVAL;
+
+	/*
+	 * When crtc is inactive or there is a modeset pending,
+	 * wait for it to complete in the slowpath
+	 */
+	if (!crtc_state->active || to_intel_crtc_state(crtc_state)->update_pipe)
+		return -EINVAL;
+
+	/*
+	 * If any parameters change that may affect watermarks,
+	 * take the slowpath. Only changing fb or position should be
+	 * in the fastpath.
+	 */
+	if (plane->state->crtc != state->crtc ||
+	    plane->state->src_w != state->src_w ||
+	    plane->state->src_h != state->src_h ||
+	    plane->state->crtc_w != state->crtc_w ||
+	    plane->state->crtc_h != state->crtc_h ||
+	    !plane->state->fb != !state->fb)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void intel_plane_atomic_async_update(struct drm_plane *plane,
+					    struct drm_plane_state *new_state)
+{
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	struct drm_crtc *crtc = plane->state->crtc;
+	struct drm_framebuffer *old_fb;
+
+	old_fb = plane->state->fb;
+
+	i915_gem_track_fb(intel_fb_obj(old_fb), intel_fb_obj(new_state->fb),
+			  intel_plane->frontbuffer_bit);
+
+	plane->state->src_x = new_state->src_x;
+	plane->state->src_y = new_state->src_y;
+	plane->state->crtc_x = new_state->crtc_x;
+	plane->state->crtc_y = new_state->crtc_y;
+	plane->state->fb = new_state->fb;
+
+	new_state->fb = old_fb;
+
+	if (plane->state->visible) {
+		trace_intel_update_plane(plane, to_intel_crtc(crtc));
+		intel_plane->update_plane(intel_plane,
+					  to_intel_crtc_state(crtc->state),
+					  to_intel_plane_state(plane->state));
+	} else {
+		trace_intel_disable_plane(plane, to_intel_crtc(crtc));
+		intel_plane->disable_plane(intel_plane, to_intel_crtc(crtc));
+	}
+}
+
 const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
 	.prepare_fb = intel_prepare_plane_fb,
 	.cleanup_fb = intel_cleanup_plane_fb,
 	.atomic_check = intel_plane_atomic_check,
+	.atomic_async_check = intel_plane_atomic_async_check,
+	.atomic_async_update = intel_plane_atomic_async_update,
 };
 
 /**
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 132e978..b64708b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13050,6 +13050,14 @@ static int intel_atomic_commit(struct drm_device *dev,
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	int ret = 0;
 
+	if (state->async_update) {
+		ret = drm_atomic_helper_prepare_planes(dev, state);
+		if (ret)
+			return ret;
+		drm_atomic_helper_async_commit(dev, state);
+		return 0;
+	}
+
 	drm_atomic_state_get(state);
 	i915_sw_fence_init(&intel_state->commit_ready,
 			   intel_atomic_commit_ready);
@@ -13275,6 +13283,9 @@ intel_prepare_plane_fb(struct drm_plane *plane,
 	struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb);
 	int ret;
 
+	if (new_state->state->async_update)
+		return 0;
+
 	if (old_obj) {
 		struct drm_crtc_state *crtc_state =
 			drm_atomic_get_new_crtc_state(new_state->state,
-- 
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] 14+ messages in thread

* [RFC PATCH 4/7] drm/i915: Extend async plane update to other planes
  2018-12-03  7:35 [RFC PATCH 0/7] drm/i915/gvt: Enable vGPU local display direct flip Tina Zhang
                   ` (2 preceding siblings ...)
  2018-12-03  7:35 ` [RFC PATCH 3/7] drm/i915: Introduce async plane update to i915 Tina Zhang
@ 2018-12-03  7:35 ` Tina Zhang
  2018-12-03  7:35 ` [RFC PATCH 5/7] drm/i915/gvt: Introduce vGPU plane page flip framework Tina Zhang
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Tina Zhang @ 2018-12-03  7:35 UTC (permalink / raw)
  Cc: Daniel Vetter, intel-gfx, Gustavo Padovan, Helen Koike,
	Enric Balletbo i Serra, kalyan.kondapally, intel-gvt-dev

Extend async plane update idea to more planes.

Signed-off-by: Tina Zhang <tina.zhang@intel.com>
Cc: Gustavo Padovan <gustavo.padovan@collabora.com>
Cc: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Cc: Helen Koike <helen.koike@collabora.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic_plane.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
index dddd3a7..b4c37ee 100644
--- a/drivers/gpu/drm/i915/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
@@ -222,9 +222,6 @@ static int intel_plane_atomic_async_check(struct drm_plane *plane,
 {
 	struct drm_crtc_state *crtc_state;
 
-	if (plane->type != DRM_PLANE_TYPE_CURSOR)
-		return -EINVAL;
-
 	crtc_state = drm_atomic_get_existing_crtc_state(state->state,
 							state->crtc);
 	if (WARN_ON(!crtc_state))
-- 
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] 14+ messages in thread

* [RFC PATCH 5/7] drm/i915/gvt: Introduce vGPU plane page flip framework
  2018-12-03  7:35 [RFC PATCH 0/7] drm/i915/gvt: Enable vGPU local display direct flip Tina Zhang
                   ` (3 preceding siblings ...)
  2018-12-03  7:35 ` [RFC PATCH 4/7] drm/i915: Extend async plane update to other planes Tina Zhang
@ 2018-12-03  7:35 ` Tina Zhang
  2018-12-03  7:35 ` [RFC PATCH 6/7] drm/i915/gvt: Enable guest direct page flip Tina Zhang
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Tina Zhang @ 2018-12-03  7:35 UTC (permalink / raw)
  Cc: intel-gfx, kalyan.kondapally, intel-gvt-dev

The vGPU plane page flip framework supports to update the assigned planes
with the meta framebuffer information during guest vGPU page flip.

With the updated meta framebuffer information, the proposed framework
will use the asynchronous atomic commit path to do the plane update
on behalf of vGPUs as much as possible.

Signed-off-by: Tina Zhang <tina.zhang@intel.com>
Cc: Zhenyu Wang <zhenyuw@linux.intel.com>
Cc: Zhi Wang <zhi.a.wang@intel.com>
---
 drivers/gpu/drm/i915/gvt/display.c | 265 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/display.h |  18 +++
 2 files changed, 283 insertions(+)

diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
index a9176a1..e06d8d6 100644
--- a/drivers/gpu/drm/i915/gvt/display.c
+++ b/drivers/gpu/drm/i915/gvt/display.c
@@ -32,6 +32,9 @@
  *
  */
 
+#include <drm/drm_mode.h>
+#include <drm/drm_atomic_uapi.h>
+#include <drm/drm_atomic_helper.h>
 #include "i915_drv.h"
 #include "gvt.h"
 
@@ -442,6 +445,268 @@ void intel_gvt_emulate_vblank(struct intel_gvt *gvt)
 	mutex_unlock(&gvt->lock);
 }
 
+static bool check_vgpu_plane_table(struct intel_gvt *gvt, u32 vgpu_plane_id,
+				   enum pipe *pipe, enum plane_id *plane_id,
+				   u32 *framebuffer_id)
+{
+	int i, j;
+
+	for (i = 0; i < I915_MAX_PIPES; i++) {
+		for (j = 0; j < I915_MAX_PLANES; j++)
+			if (gvt->assigned_plane[i][j].vgpu_plane_id ==
+			    vgpu_plane_id) {
+				*pipe = i;
+				*plane_id = j;
+				*framebuffer_id =
+				gvt->assigned_plane[i][j].framebuffer_id;
+				break;
+			}
+
+		if (j < I915_MAX_PLANES)
+			return true;
+	}
+
+	return false;
+}
+
+static u64 plane_ctl_modifier(u64 fb_tiling)
+{
+	switch (fb_tiling) {
+	case PLANE_CTL_TILED_LINEAR:
+		return DRM_FORMAT_MOD_LINEAR;
+	case PLANE_CTL_TILED_X:
+		return I915_FORMAT_MOD_X_TILED;
+	case PLANE_CTL_TILED_Y:
+		return I915_FORMAT_MOD_Y_TILED;
+	case PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE:
+		return I915_FORMAT_MOD_Y_TILED_CCS;
+	case PLANE_CTL_TILED_YF:
+		return I915_FORMAT_MOD_Yf_TILED;
+	case PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE:
+		return I915_FORMAT_MOD_Yf_TILED_CCS;
+	default:
+		MISSING_CASE(fb_tiling);
+	}
+
+	return 0;
+}
+
+static int vgpu_fb_update(struct intel_gvt *gvt,
+			  struct drm_framebuffer *fb,
+			  struct intel_vgpu_plane_info *vgpu_plane_info,
+			  struct drm_mode_fb_cmd2 *mode_cmd)
+{
+	int ret;
+
+	if (vgpu_plane_info->plane == PLANE_PRIMARY) {
+		struct intel_vgpu_primary_plane_format plane;
+
+		ret = intel_vgpu_decode_primary_plane(vgpu_plane_info->vgpu, &plane);
+		if (ret)
+			return ret;
+
+		mode_cmd->pixel_format = plane.drm_format;
+		mode_cmd->width = plane.width;
+		mode_cmd->height = plane.height;
+		mode_cmd->handles[0] = 0;
+		mode_cmd->offsets[0] = 0;
+		mode_cmd->pitches[0] = plane.stride;
+		mode_cmd->flags = DRM_MODE_FB_MODIFIERS;
+		mode_cmd->modifier[0] = plane_ctl_modifier(plane.tiled);
+	} else if (vgpu_plane_info->plane == PLANE_CURSOR) {
+		struct intel_vgpu_cursor_plane_format plane;
+
+		ret = intel_vgpu_decode_cursor_plane(vgpu_plane_info->vgpu, &plane);
+		if (ret)
+			return ret;
+
+		mode_cmd->pixel_format = plane.drm_format;
+		mode_cmd->width = plane.width;
+		mode_cmd->height = plane.height;
+		mode_cmd->handles[0] = 0;
+		mode_cmd->offsets[0] = 0;
+		mode_cmd->pitches[0] = plane.width * (plane.bpp / 8);
+		mode_cmd->flags = DRM_MODE_FB_MODIFIERS;
+		mode_cmd->modifier[0] = 0;
+	} else {
+		struct intel_vgpu_sprite_plane_format plane;
+
+		ret = intel_vgpu_decode_sprite_plane(vgpu_plane_info->vgpu, &plane);
+		if (ret)
+			return ret;
+
+		mode_cmd->pixel_format = plane.hw_format;
+		mode_cmd->width = plane.width;
+		mode_cmd->height = plane.height;
+		mode_cmd->handles[0] = 0;
+		mode_cmd->offsets[0] = 0;
+		mode_cmd->pitches[0] = plane.stride;
+		mode_cmd->flags = DRM_MODE_FB_MODIFIERS;
+		mode_cmd->modifier[0] = plane_ctl_modifier(plane.tiled);
+	}
+
+	return ret;
+}
+
+static int update_vgpu_assigned_plane(struct intel_gvt *gvt,
+				    struct drm_plane *plane,
+				    struct drm_crtc *crtc,
+				    struct drm_framebuffer *fb,
+				    struct drm_modeset_acquire_ctx *ctx,
+				    struct intel_vgpu_plane_info *vgpu_plane_info)
+{
+	struct drm_device *drm = &gvt->dev_priv->drm;
+	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+	struct drm_atomic_state *state;
+	struct drm_plane_state *plane_state;
+	struct drm_mode_fb_cmd2 mode_cmd;
+	int ret = 0;
+
+	state = drm_atomic_state_alloc(plane->dev);
+	if (!state)
+		return -ENOMEM;
+
+	state->acquire_ctx = ctx;
+	plane_state = drm_atomic_get_plane_state(state, plane);
+	if (IS_ERR(plane_state)) {
+		ret = PTR_ERR(plane_state);
+		goto fail;
+	}
+
+	ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
+	if (ret != 0)
+		goto fail;
+	drm_atomic_set_fb_for_plane(plane_state, fb);
+
+	ret = vgpu_fb_update(gvt, fb, vgpu_plane_info, &mode_cmd);
+	if (ret)
+		goto fail;
+
+	if (memcmp(mode_cmd.pitches, fb->pitches, 16) ||
+	    memcmp(mode_cmd.offsets, fb->offsets, 16) ||
+	    drm_get_format_info(drm, &mode_cmd) != fb->format ||
+	    mode_cmd.modifier[0] != fb->modifier ||
+	    drm_atomic_helper_async_check(drm, state))
+		state->async_update = false;
+	else
+		state->async_update = true;
+
+	drm_helper_mode_fill_fb_struct(plane->dev, fb, &mode_cmd);
+	plane_state->src_x = vgpu_plane_info->plane_offset & 0x0000ffff;
+	plane_state->src_y = (vgpu_plane_info->plane_offset >> 16) & 0x0000ffff;
+	plane_state->src_w = mode_cmd.width << 16;
+	plane_state->src_h = mode_cmd.height << 16;
+
+	intel_fb->meta_fb.ggtt_offset = vgpu_plane_info->offset;
+
+	/* Don't allow full modeset */
+	state->allow_modeset = false;
+
+	ret = drm_atomic_commit(state);
+fail:
+	drm_atomic_state_put(state);
+	return ret;
+}
+
+static int vgpu_plane_update_internal(struct intel_gvt *gvt,
+				   struct drm_plane *plane,
+				   struct drm_crtc *crtc,
+				   struct drm_framebuffer *fb,
+				   struct drm_modeset_acquire_ctx *ctx,
+				   struct intel_vgpu_plane_info *vgpu_plane_info)
+{
+	int ret = 0;
+
+	/* Check whether this plane is usable on this CRTC */
+	if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
+		DRM_DEBUG_KMS("Invalid crtc for plane\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = update_vgpu_assigned_plane(gvt, plane, crtc, fb, ctx, vgpu_plane_info);
+
+out:
+	return ret;
+}
+
+void intel_vgpu_plane_update(struct intel_gvt *gvt,
+		       struct intel_vgpu_plane_info *vgpu_plane_info)
+{
+	struct drm_device *drm = &gvt->dev_priv->drm;
+	struct drm_modeset_acquire_ctx ctx;
+	struct drm_mode_object *obj_fb = NULL;
+	struct drm_plane *plane;
+	struct intel_plane *intel_plane = NULL;
+	struct intel_crtc *intel_crtc;
+	struct intel_framebuffer *intel_fb;
+	u32 framebuffer_id = 0;
+	enum pipe pipe;
+	enum plane_id plane_id;
+	int ret;
+
+	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
+retry:
+	ret = drm_modeset_lock_all_ctx(drm, &ctx);
+	if (ret)
+		goto fail;
+
+	ret = check_vgpu_plane_table(gvt, vgpu_plane_info->id, &pipe,
+			       &plane_id, &framebuffer_id);
+	if (!ret) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	DRM_DEBUG_KMS("%s: pipe is %d, plane_id is %d, fb_id is %d\n",
+		      __func__, pipe, plane_id, framebuffer_id);
+
+	if (framebuffer_id) {
+		intel_crtc = intel_get_crtc_for_pipe(gvt->dev_priv, pipe);
+
+		drm_for_each_plane(plane, drm) {
+			intel_plane = to_intel_plane(plane);
+			if (intel_plane->pipe == pipe &&
+				intel_plane->id == plane_id)
+				break;
+
+			intel_plane = NULL;
+		}
+		if (!intel_plane)
+			goto fail;
+
+		//vGPU might want to disable the assigned plane
+		if (vgpu_plane_info->offset == 0) {
+			intel_plane->disable_plane(intel_plane, intel_crtc);
+			goto out;
+		}
+
+		obj_fb = idr_find(&drm->mode_config.crtc_idr, framebuffer_id);
+		intel_fb = to_intel_framebuffer(obj_to_fb(obj_fb));
+
+	} else {
+		DRM_DEBUG_KMS("no assgined plane for the vGPU plane 0x%x\n",
+							vgpu_plane_info->id);
+		goto fail;
+	}
+
+	ret = vgpu_plane_update_internal(gvt, &intel_plane->base,
+					 &intel_crtc->base, &intel_fb->base,
+					 &ctx, vgpu_plane_info);
+
+fail:
+	if (ret == -EDEADLK) {
+		ret = drm_modeset_backoff(&ctx);
+		if (!ret)
+			goto retry;
+	}
+out:
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+}
+
+
+
 struct intel_vgpu_fb_meta_data {
 	u32 vgpu_plane_id; /* vgpu_id(23:16):vgpu_pipe(15:8):vgpu_plane(7:0)*/
 	struct intel_vgpu *vgpu; // the vGPU this meta_fb belongs to
diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h
index ea7c1c5..5d929bb 100644
--- a/drivers/gpu/drm/i915/gvt/display.h
+++ b/drivers/gpu/drm/i915/gvt/display.h
@@ -160,6 +160,20 @@ enum intel_vgpu_edid {
 	GVT_EDID_NUM,
 };
 
+struct intel_vgpu_plane_info {
+	u32 id;; /* vgpu plane id */
+	enum plane_id plane;
+	struct intel_vgpu *vgpu;
+
+	/* vGPU plane registers values. */
+	u32 offset;
+	u32 stride;
+	u32 control;
+	u32 plane_offset;
+
+	u32 size;
+};
+
 static inline char *vgpu_edid_str(enum intel_vgpu_edid id)
 {
 	switch (id) {
@@ -181,4 +195,8 @@ void intel_vgpu_clean_display(struct intel_vgpu *vgpu);
 
 int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe);
 
+
+void intel_vgpu_plane_update(struct intel_gvt *gvt,
+		       struct intel_vgpu_plane_info *plane_info);
+
 #endif
-- 
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] 14+ messages in thread

* [RFC PATCH 6/7] drm/i915/gvt: Enable guest direct page flip
  2018-12-03  7:35 [RFC PATCH 0/7] drm/i915/gvt: Enable vGPU local display direct flip Tina Zhang
                   ` (4 preceding siblings ...)
  2018-12-03  7:35 ` [RFC PATCH 5/7] drm/i915/gvt: Introduce vGPU plane page flip framework Tina Zhang
@ 2018-12-03  7:35 ` Tina Zhang
  2018-12-03  7:35 ` [RFC PATCH 7/7] drm/i915/gvt: Introduce HW Vblank interrupt to vGPU Tina Zhang
  2018-12-03  7:53 ` ✗ Fi.CI.BAT: failure for drm/i915/gvt: Enable vGPU local display direct flip Patchwork
  7 siblings, 0 replies; 14+ messages in thread
From: Tina Zhang @ 2018-12-03  7:35 UTC (permalink / raw)
  Cc: intel-gfx, kalyan.kondapally, intel-gvt-dev

Use the vGPU direct plane flip framework do the guest direct page
flip.

Signed-off-by: Tina Zhang <tina.zhang@intel.com>
Cc: Zhenyu Wang <zhenyuw@linux.intel.com>
Cc: Zhi Wang <zhi.a.wang@intel.com>
---
 drivers/gpu/drm/i915/gvt/handlers.c | 38 +++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c
index b5475c9..89a22a5 100644
--- a/drivers/gpu/drm/i915/gvt/handlers.c
+++ b/drivers/gpu/drm/i915/gvt/handlers.c
@@ -743,6 +743,35 @@ static int south_chicken2_mmio_write(struct intel_vgpu *vgpu,
 	return 0;
 }
 
+static int handle_vgpu_page_flip(struct intel_vgpu *vgpu, int pipe,
+							enum plane_id plane)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	struct intel_vgpu_plane_info vgpu_plane_info;
+	u32 vgpu_id = vgpu->id;
+	u32 pipe_id = pipe;
+	u32 plane_id = plane;
+	u32 vgpu_plane_id = (vgpu_id << 16) | (pipe_id << 8) | plane_id;
+
+	if (plane == PLANE_CURSOR) {
+		DRM_DEBUG_KMS("Assigning CURSOR plane hasn't been supported\n");
+	} else { /* primary plane and sprite plane */
+		vgpu_plane_info.id = vgpu_plane_id;
+		vgpu_plane_info.plane = PLANE_PRIMARY;
+		vgpu_plane_info.offset = vgpu_vreg_t(vgpu, DSPSURF(pipe)) &
+							I915_GTT_PAGE_MASK;
+		vgpu_plane_info.stride = vgpu_vreg_t(vgpu, DSPSTRIDE(pipe)) & 0x3ff;
+		vgpu_plane_info.control = vgpu_vreg_t(vgpu, DSPCNTR(pipe));
+		vgpu_plane_info.size = vgpu_vreg_t(vgpu, DSPSIZE(pipe));
+		vgpu_plane_info.plane_offset = vgpu_vreg_t(vgpu, DSPOFFSET(pipe));
+		vgpu_plane_info.vgpu = vgpu;
+	}
+
+	intel_vgpu_plane_update(vgpu->gvt, &vgpu_plane_info);
+
+	return 0;
+}
+
 #define DSPSURF_TO_PIPE(offset) \
 	calc_index(offset, _DSPASURF, _DSPBSURF, 0, DSPSURF(PIPE_C))
 
@@ -761,6 +790,8 @@ static int pri_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
 	write_vreg(vgpu, offset, p_data, bytes);
 	vgpu_vreg_t(vgpu, surflive_reg) = vgpu_vreg(vgpu, offset);
 
+	handle_vgpu_page_flip(vgpu, index, PLANE_PRIMARY);
+
 	set_bit(flip_event[index], vgpu->irq.flip_done_event[index]);
 	return 0;
 }
@@ -768,10 +799,15 @@ static int pri_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
 #define SPRSURF_TO_PIPE(offset) \
 	calc_index(offset, _SPRA_SURF, _SPRB_SURF, 0, SPRSURF(PIPE_C))
 
+#define SPRSURF_TO_PLANE(offset, pipe) \
+	calc_index(offset, _PLANE_SURF_1(pipe), _PLANE_SURF_2(pipe), \
+			_PLANE_SURF_3(pipe), PLANE_SURF(PIPE_C, PLANE_CURSOR))
+
 static int spr_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
 		void *p_data, unsigned int bytes)
 {
 	unsigned int index = SPRSURF_TO_PIPE(offset);
+	unsigned int plane = SPRSURF_TO_PLANE(offset, index);
 	i915_reg_t surflive_reg = SPRSURFLIVE(index);
 	int flip_event[] = {
 		[PIPE_A] = SPRITE_A_FLIP_DONE,
@@ -782,6 +818,8 @@ static int spr_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
 	write_vreg(vgpu, offset, p_data, bytes);
 	vgpu_vreg_t(vgpu, surflive_reg) = vgpu_vreg(vgpu, offset);
 
+	handle_vgpu_page_flip(vgpu, index, plane);
+
 	set_bit(flip_event[index], vgpu->irq.flip_done_event[index]);
 	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] 14+ messages in thread

* [RFC PATCH 7/7] drm/i915/gvt: Introduce HW Vblank interrupt to vGPU
  2018-12-03  7:35 [RFC PATCH 0/7] drm/i915/gvt: Enable vGPU local display direct flip Tina Zhang
                   ` (5 preceding siblings ...)
  2018-12-03  7:35 ` [RFC PATCH 6/7] drm/i915/gvt: Enable guest direct page flip Tina Zhang
@ 2018-12-03  7:35 ` Tina Zhang
  2018-12-03  7:53 ` ✗ Fi.CI.BAT: failure for drm/i915/gvt: Enable vGPU local display direct flip Patchwork
  7 siblings, 0 replies; 14+ messages in thread
From: Tina Zhang @ 2018-12-03  7:35 UTC (permalink / raw)
  Cc: intel-gfx, kalyan.kondapally, intel-gvt-dev

For each physical crtc, Gvt-g has a kernel thread to get the HW vblank
event on time and inject the interrupt event to the vGPUs which the
display planes of the crtc are assigned to.

Signed-off-by: Tina Zhang <tina.zhang@intel.com>
Cc: Zhenyu Wang <zhenyuw@linux.intel.com>
Cc: Zhi Wang <zhi.a.wang@intel.com>
---
 drivers/gpu/drm/i915/gvt/display.c   |  30 ++++++----
 drivers/gpu/drm/i915/gvt/display.h   |   3 +-
 drivers/gpu/drm/i915/gvt/gvt.c       | 112 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/gvt.h       |   3 +
 drivers/gpu/drm/i915/gvt/handlers.c  |   4 +-
 drivers/gpu/drm/i915/gvt/interrupt.c |  54 +++++++++++++++++
 drivers/gpu/drm/i915/gvt/interrupt.h |   2 +
 7 files changed, 193 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
index e06d8d6..eec8336 100644
--- a/drivers/gpu/drm/i915/gvt/display.c
+++ b/drivers/gpu/drm/i915/gvt/display.c
@@ -358,7 +358,7 @@ static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num,
  * enabled/disabled virtual pipes.
  *
  */
-void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt)
+void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt, bool use_hw_vblank)
 {
 	struct intel_gvt_irq *irq = &gvt->irq;
 	struct intel_vgpu *vgpu;
@@ -369,25 +369,29 @@ void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt)
 	for_each_active_vgpu(gvt, vgpu, id) {
 		for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) {
 			if (pipe_is_enabled(vgpu, pipe)) {
-				found = true;
-				break;
+				if (use_hw_vblank) {
+					wake_up_process(gvt->vblank_thread[pipe]);
+				} else {
+					found = true;
+					break;
+				}
 			}
 		}
-		if (found)
-			break;
 	}
 
-	/* all the pipes are disabled */
-	if (!found)
-		hrtimer_cancel(&irq->vblank_timer.timer);
-	else
-		hrtimer_start(&irq->vblank_timer.timer,
-			ktime_add_ns(ktime_get(), irq->vblank_timer.period),
-			HRTIMER_MODE_ABS);
+	if (!use_hw_vblank) {
+		/* all the pipes are disabled */
+		if (!found)
+			hrtimer_cancel(&irq->vblank_timer.timer);
+		else
+			hrtimer_start(&irq->vblank_timer.timer,
+				      ktime_add_ns(ktime_get(), irq->vblank_timer.period),
+				      HRTIMER_MODE_ABS);
+	}
 	mutex_unlock(&gvt->lock);
 }
 
-static void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe)
+void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe)
 {
 	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
 	struct intel_vgpu_irq *irq = &vgpu->irq;
diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h
index 5d929bb..e0a85df 100644
--- a/drivers/gpu/drm/i915/gvt/display.h
+++ b/drivers/gpu/drm/i915/gvt/display.h
@@ -187,12 +187,13 @@ static inline char *vgpu_edid_str(enum intel_vgpu_edid id)
 }
 
 void intel_gvt_emulate_vblank(struct intel_gvt *gvt);
-void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt);
+void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt, bool use_hw_vblank);
 
 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);
 
+void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe);
 int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe);
 
 
diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c
index 733a2a0..a017ac4 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.c
+++ b/drivers/gpu/drm/i915/gvt/gvt.c
@@ -250,6 +250,94 @@ static void init_device_info(struct intel_gvt *gvt)
 	info->msi_cap_offset = pdev->msi_cap;
 }
 
+static int emulate_crtc_a_vblank_thread(void *data)
+{
+	struct intel_gvt *gvt = (struct intel_gvt *)data;
+	struct drm_device *dev = &gvt->dev_priv->drm;
+	struct intel_vgpu *vgpu;
+	struct completion vblank_done = gvt->vblank_done[PIPE_A];
+	int ret;
+	int id;
+
+	DRM_DEBUG_KMS("vblank service thread a start\n");
+
+	while (!kthread_should_stop()) {
+		init_completion(&vblank_done);
+retry:
+		ret = intel_gvt_register_HW_vblank_event(dev, &vblank_done, PIPE_A);
+		if (ret) {
+			goto retry;
+		}
+
+		/* wait for the complete */
+		wait_for_completion_interruptible(&vblank_done);
+
+		/* inject the vblank to gvt */
+		for_each_active_vgpu(gvt, vgpu, id)
+			emulate_vblank_on_pipe(vgpu, PIPE_A);
+	}
+
+	return 0;
+}
+
+static int emulate_crtc_b_vblank_thread(void *data)
+{
+	struct intel_gvt *gvt = (struct intel_gvt *)data;
+	struct drm_device *dev = &gvt->dev_priv->drm;
+	struct intel_vgpu *vgpu;
+	struct completion vblank_done = gvt->vblank_done[PIPE_B];
+	int ret;
+	int id;
+
+	DRM_DEBUG_KMS("vblank service thread b start\n");
+
+	while (!kthread_should_stop()) {
+		init_completion(&vblank_done);
+retry:
+		ret = intel_gvt_register_HW_vblank_event(dev, &vblank_done, PIPE_B);
+		if (ret)
+			goto retry;
+
+		/* wait for the complete */
+		wait_for_completion_interruptible(&vblank_done);
+
+		/* inject the vblank to gvt */
+		for_each_active_vgpu(gvt, vgpu, id)
+			emulate_vblank_on_pipe(vgpu, PIPE_B);
+	}
+
+	return 0;
+}
+
+static int emulate_crtc_c_vblank_thread(void *data)
+{
+	struct intel_gvt *gvt = (struct intel_gvt *)data;
+	struct drm_device *dev = &gvt->dev_priv->drm;
+	struct intel_vgpu *vgpu;
+	struct completion vblank_done = gvt->vblank_done[PIPE_C];
+	int ret;
+	int id;
+
+	DRM_DEBUG_KMS("vblank service thread c start\n");
+
+	while (!kthread_should_stop()) {
+		init_completion(&vblank_done);
+retry:
+		ret = intel_gvt_register_HW_vblank_event(dev, &vblank_done, PIPE_C);
+		if (ret)
+			goto retry;
+
+		/* wait for the complete */
+		wait_for_completion_interruptible(&vblank_done);
+
+		/* inject the vblank to gvt */
+		for_each_active_vgpu(gvt, vgpu, id)
+			emulate_vblank_on_pipe(vgpu, PIPE_C);
+	}
+
+	return 0;
+}
+
 static int gvt_service_thread(void *data)
 {
 	struct intel_gvt *gvt = (struct intel_gvt *)data;
@@ -285,6 +373,9 @@ static int gvt_service_thread(void *data)
 static void clean_service_thread(struct intel_gvt *gvt)
 {
 	kthread_stop(gvt->service_thread);
+	kthread_stop(gvt->vblank_thread[PIPE_A]);
+	kthread_stop(gvt->vblank_thread[PIPE_B]);
+	kthread_stop(gvt->vblank_thread[PIPE_C]);
 }
 
 static int init_service_thread(struct intel_gvt *gvt)
@@ -297,6 +388,27 @@ static int init_service_thread(struct intel_gvt *gvt)
 		gvt_err("fail to start service thread.\n");
 		return PTR_ERR(gvt->service_thread);
 	}
+
+	gvt->vblank_thread[PIPE_A] = kthread_create(emulate_crtc_a_vblank_thread,
+			gvt, "emulate_crtc_a_vblank_thread");
+	if (IS_ERR(gvt->vblank_thread[PIPE_A])) {
+		gvt_err("fail to start service thread.\n");
+		return PTR_ERR(gvt->vblank_thread[PIPE_A]);
+	}
+
+	gvt->vblank_thread[PIPE_B] = kthread_create(emulate_crtc_b_vblank_thread,
+			gvt, "emulate_crtc_b_vblank_thread");
+	if (IS_ERR(gvt->vblank_thread[PIPE_B])) {
+		gvt_err("fail to start service thread.\n");
+		return PTR_ERR(gvt->vblank_thread[PIPE_B]);
+	}
+
+	gvt->vblank_thread[PIPE_C] = kthread_create(emulate_crtc_c_vblank_thread,
+			gvt, "emulate_crtc_c_vblank_thread");
+	if (IS_ERR(gvt->vblank_thread[PIPE_C])) {
+		gvt_err("fail to start service thread.\n");
+		return PTR_ERR(gvt->vblank_thread[PIPE_C]);
+	}
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index 0ab10b0..96903d2 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -356,6 +356,9 @@ struct intel_gvt {
 
 	/* vGPU plane assignment */
 	struct assigned_plane assigned_plane[I915_MAX_PIPES][I915_MAX_PLANES];
+
+	struct task_struct *vblank_thread[I915_MAX_PIPES];
+	struct completion vblank_done[I915_MAX_PIPES];
 };
 
 static inline struct intel_gvt *to_gvt(struct drm_i915_private *i915)
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c
index 89a22a5..4ad6611 100644
--- a/drivers/gpu/drm/i915/gvt/handlers.c
+++ b/drivers/gpu/drm/i915/gvt/handlers.c
@@ -449,10 +449,12 @@ static int pipeconf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
 		vgpu_vreg(vgpu, offset) |= I965_PIPECONF_ACTIVE;
 	else
 		vgpu_vreg(vgpu, offset) &= ~I965_PIPECONF_ACTIVE;
+
 	/* vgpu_lock already hold by emulate mmio r/w */
 	mutex_unlock(&vgpu->vgpu_lock);
-	intel_gvt_check_vblank_emulation(vgpu->gvt);
+	intel_gvt_check_vblank_emulation(vgpu->gvt, true);
 	mutex_lock(&vgpu->vgpu_lock);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/gvt/interrupt.c b/drivers/gpu/drm/i915/gvt/interrupt.c
index 5daa23a..cb92ce4 100644
--- a/drivers/gpu/drm/i915/gvt/interrupt.c
+++ b/drivers/gpu/drm/i915/gvt/interrupt.c
@@ -633,6 +633,60 @@ void intel_vgpu_trigger_virtual_event(struct intel_vgpu *vgpu,
 	ops->check_pending_irq(vgpu);
 }
 
+static void release_vblank_event(struct completion *completion)
+{
+	;
+}
+
+int intel_gvt_register_HW_vblank_event(struct drm_device *dev,
+				     struct completion *vblank_done, int pipe)
+{
+	struct drm_pending_vblank_event *e;
+	struct drm_crtc *crtc;
+	unsigned long flags;
+	int ret;
+
+	DRM_DEBUG_KMS("%s begin with pipe %d, com %p, dev %p", __func__, pipe, vblank_done, dev);
+
+	crtc = drm_crtc_from_index(dev, pipe);
+	if (!crtc) {
+		DRM_ERROR("cannot get crtc %d\n", pipe);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = drm_crtc_vblank_get(crtc);
+	if (ret) {
+		DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret);
+		goto out;
+	}
+
+	e = kzalloc(sizeof *e, GFP_KERNEL);
+	if (!e) {
+		drm_crtc_vblank_put(crtc);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* create a vblank event */
+	e->event.base.type = DRM_EVENT_VBLANK;
+	e->event.base.length = sizeof(e->event);
+	e->pipe = pipe;
+	e->base.completion = vblank_done;
+	e->base.completion_release = release_vblank_event;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	e->sequence = drm_crtc_accurate_vblank_count(crtc) + 1;
+
+	/* add the event to vblank list */
+	list_add_tail(&e->base.link, &dev->vblank_event_list);
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	DRM_DEBUG_KMS("%s: success \n", __func__);
+out:
+	return ret;
+}
+
 static void init_events(
 	struct intel_gvt_irq *irq)
 {
diff --git a/drivers/gpu/drm/i915/gvt/interrupt.h b/drivers/gpu/drm/i915/gvt/interrupt.h
index 5313fb1..ed4936e 100644
--- a/drivers/gpu/drm/i915/gvt/interrupt.h
+++ b/drivers/gpu/drm/i915/gvt/interrupt.h
@@ -213,6 +213,8 @@ struct intel_gvt_irq {
 
 int intel_gvt_init_irq(struct intel_gvt *gvt);
 void intel_gvt_clean_irq(struct intel_gvt *gvt);
+int intel_gvt_register_HW_vblank_event(struct drm_device *dev,
+				 struct completion *vblank_done, int pipe);
 
 void intel_vgpu_trigger_virtual_event(struct intel_vgpu *vgpu,
 	enum intel_gvt_event_type event);
-- 
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] 14+ messages in thread

* ✗ Fi.CI.BAT: failure for drm/i915/gvt: Enable vGPU local display direct flip
  2018-12-03  7:35 [RFC PATCH 0/7] drm/i915/gvt: Enable vGPU local display direct flip Tina Zhang
                   ` (6 preceding siblings ...)
  2018-12-03  7:35 ` [RFC PATCH 7/7] drm/i915/gvt: Introduce HW Vblank interrupt to vGPU Tina Zhang
@ 2018-12-03  7:53 ` Patchwork
  7 siblings, 0 replies; 14+ messages in thread
From: Patchwork @ 2018-12-03  7:53 UTC (permalink / raw)
  To: Tina Zhang; +Cc: intel-gfx

== Series Details ==

Series: drm/i915/gvt: Enable vGPU local display direct flip
URL   : https://patchwork.freedesktop.org/series/53383/
State : failure

== Summary ==

CALL    scripts/checksyscalls.sh
  DESCEND  objtool
  CHK     include/generated/compile.h
  CC [M]  drivers/gpu/drm/i915/intel_atomic_plane.o
In file included from ./include/linux/list.h:9:0,
                 from ./include/linux/agp_backend.h:33,
                 from ./include/drm/drmP.h:35,
                 from drivers/gpu/drm/i915/intel_atomic_plane.c:34:
drivers/gpu/drm/i915/intel_atomic_plane.c: In function ‘intel_plane_atomic_async_update’:
./include/linux/kernel.h:995:41: error: passing argument 2 of ‘intel_plane->disable_plane’ from incompatible pointer type [-Werror=incompatible-pointer-types]
 #define container_of(ptr, type, member) ({    \
                                         ^
drivers/gpu/drm/i915/intel_drv.h:1074:26: note: in expansion of macro ‘container_of’
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
                          ^~~~~~~~~~~~
drivers/gpu/drm/i915/intel_atomic_plane.c:354:43: note: in expansion of macro ‘to_intel_crtc’
   intel_plane->disable_plane(intel_plane, to_intel_crtc(crtc));
                                           ^~~~~~~~~~~~~
./include/linux/kernel.h:995:41: note: expected ‘const struct intel_crtc_state *’ but argument is of type ‘struct intel_crtc *’
 #define container_of(ptr, type, member) ({    \
                                         ^
drivers/gpu/drm/i915/intel_drv.h:1074:26: note: in expansion of macro ‘container_of’
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
                          ^~~~~~~~~~~~
drivers/gpu/drm/i915/intel_atomic_plane.c:354:43: note: in expansion of macro ‘to_intel_crtc’
   intel_plane->disable_plane(intel_plane, to_intel_crtc(crtc));
                                           ^~~~~~~~~~~~~
cc1: all warnings being treated as errors
scripts/Makefile.build:293: recipe for target 'drivers/gpu/drm/i915/intel_atomic_plane.o' failed
make[4]: *** [drivers/gpu/drm/i915/intel_atomic_plane.o] Error 1
scripts/Makefile.build:518: recipe for target 'drivers/gpu/drm/i915' failed
make[3]: *** [drivers/gpu/drm/i915] Error 2
scripts/Makefile.build:518: recipe for target 'drivers/gpu/drm' failed
make[2]: *** [drivers/gpu/drm] Error 2
scripts/Makefile.build:518: recipe for target 'drivers/gpu' failed
make[1]: *** [drivers/gpu] Error 2
Makefile:1060: 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] 14+ messages in thread

* Re: [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's planes
  2018-12-03  7:35 ` [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's planes Tina Zhang
@ 2018-12-03  8:21   ` Zhenyu Wang
  2018-12-03  8:35     ` Zhenyu Wang
                       ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Zhenyu Wang @ 2018-12-03  8:21 UTC (permalink / raw)
  To: Tina Zhang; +Cc: kalyan.kondapally, intel-gfx, intel-gvt-dev


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

On 2018.12.03 15:35:17 +0800, Tina Zhang wrote:
> Create and initialize vGPU meta framebuffers during vGPU's creation.
> Each meta framebuffer is an intel_framebuffer. Userspace can get the
> userspace visible identifier of that meta framebuffer by accessing
> plane_id_index attribute.
> 
> For example:
> In "/sys/bus/pci/devices/0000\:00\:02.0/$vGPU_id/intel_vgpu/" directory,
> 
>    /* plane_id_index: pipe#(bit16:8) and plane#(bit7:0)*/
>    echo "0x10" > plane_index_id //Set the index to the plane 0 of pipe 1
> 
>    /*
>     * Dump userspace visible identifier of the meta framebuffer
>     * standing for the primary plane of the vGPU's pipe one
>     */
>    cat plane_index_id //dump the id for plane 0 of pipe 1
> 
> Then userspace can use this id with the exsting KMS IOCTL, e.g.
> drmModeSetPlane, to assign a physical plane to this virtual plane.

How does user know which plane/pipe is active for vGPU? Looks from
current code it has no way to know that. I think for guest display
assignment, we need to know the display state of vGPU and it looks
there's no state tracking, e.g what if guest driver switches to
another plane for display? How could user know that then adjust for
assignment?

And really don't like sysfs to r/w file for id, even if doesn't use
vfio gfx dmabuf interface for guest display object presentation, a
vendor specific vfio device ioctl if possible is better.

> 
> Signed-off-by: Tina Zhang <tina.zhang@intel.com>
> Cc: Zhenyu Wang <zhenyuw@linux.intel.com>
> Cc: Zhi Wang <zhi.a.wang@intel.com>
> ---
>  drivers/gpu/drm/i915/gvt/display.c | 150 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/gvt/gvt.h     |  16 ++++
>  drivers/gpu/drm/i915/gvt/kvmgt.c   |  46 ++++++++++++
>  3 files changed, 212 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
> index df1e141..a9176a1 100644
> --- a/drivers/gpu/drm/i915/gvt/display.c
> +++ b/drivers/gpu/drm/i915/gvt/display.c
> @@ -442,6 +442,152 @@ void intel_gvt_emulate_vblank(struct intel_gvt *gvt)
>  	mutex_unlock(&gvt->lock);
>  }
>  
> +struct intel_vgpu_fb_meta_data {
> +	u32 vgpu_plane_id; /* vgpu_id(23:16):vgpu_pipe(15:8):vgpu_plane(7:0)*/
> +	struct intel_vgpu *vgpu; // the vGPU this meta_fb belongs to
> +};
> +
> +static void meta_fb_destroy(struct drm_framebuffer *fb)
> +{
> +	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> +
> +	if (intel_fb->meta_fb.type_id != INTEL_META_FB_VGPU)
> +		return;
> +
> +	kfree(intel_fb->meta_fb.private);
> +	intel_fb->meta_fb.private = NULL;
> +
> +	drm_framebuffer_cleanup(fb);
> +	kfree(intel_fb);
> +}
> +
> +static void clean_meta_fb(struct intel_vgpu *vgpu)
> +{
> +	enum pipe pipe;
> +	enum plane_id plane_id;
> +	struct intel_framebuffer *intel_fb;
> +
> +	for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) {
> +		for (plane_id = 0; plane_id < I915_MAX_PLANES; plane_id++) {
> +			intel_fb = vgpu->display.meta_fbs.meta_fb[pipe][plane_id];
> +			if (!intel_fb)
> +				drm_framebuffer_put(&intel_fb->base);
> +
> +			intel_fb = NULL;
> +		}
> +	}
> +}
> +
> +static int meta_fb_create_handle(struct drm_framebuffer *fb,
> +				 struct drm_file *file,
> +				 unsigned int *handle)
> +{
> +	return -ENODEV;
> +}
> +
> +static int meta_fb_dirty(struct drm_framebuffer *fb,
> +			 struct drm_file *file,
> +			 unsigned int flags,
> +			 unsigned int color,
> +			 struct drm_clip_rect *clips,
> +			 unsigned int num_clips)
> +{
> +	return 0;
> +}
> +
> +static const struct drm_framebuffer_funcs meta_fb_funcs = {
> +	.destroy = meta_fb_destroy,
> +	.create_handle = meta_fb_create_handle,
> +	.dirty = meta_fb_dirty,
> +};
> +
> +static void meta_fb_update(struct intel_framebuffer *intel_fb,
> +			   enum pipe pipe, enum plane_id plane_id)
> +{
> +	struct intel_vgpu_fb_meta_data *meta_data;
> +	struct intel_gvt *gvt;
> +
> +	if (!intel_fb || intel_fb->meta_fb.type_id != INTEL_META_FB_VGPU)
> +		return;
> +
> +	meta_data = intel_fb->meta_fb.private;
> +	gvt = meta_data->vgpu->gvt;
> +
> +	if (gvt->assigned_plane[pipe][plane_id].vgpu_plane_id !=
> +						meta_data->vgpu_plane_id) {
> +		gvt->assigned_plane[pipe][plane_id].vgpu_plane_id =
> +						meta_data->vgpu_plane_id;
> +		gvt->assigned_plane[pipe][plane_id].framebuffer_id =
> +						intel_fb->base.base.id;
> +		intel_fb->meta_fb.ggtt_offset = 0;
> +		intel_fb->meta_fb.should_be_offscreen = true;
> +	} else if (!intel_fb->meta_fb.ggtt_offset) {
> +		intel_fb->meta_fb.should_be_offscreen = true;
> +	} else {
> +		intel_fb->meta_fb.should_be_offscreen = false;
> +	}
> +}
> +
> +static int init_meta_fb(struct intel_vgpu *vgpu)
> +{
> +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
> +	struct intel_vgpu_fb_meta_data *meta_data;
> +	struct drm_mode_fb_cmd2 mode_cmd;
> +	struct intel_framebuffer *intel_fb;
> +	enum pipe pipe;
> +	enum plane_id plane_id;
> +	int ret = 0;
> +
> +	for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) {
> +		for (plane_id = 0; plane_id < I915_MAX_PLANES; plane_id++) {
> +			intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
> +			if (!intel_fb)
> +				return -ENOMEM;
> +
> +			/*
> +			 * Create a drm_framebuffer with defaults.
> +			 */
> +			mode_cmd.pixel_format = DRM_FORMAT_XRGB8888;
> +			mode_cmd.width = dev_priv->drm.mode_config.max_width;
> +			mode_cmd.height = dev_priv->drm.mode_config.max_height;
> +			mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
> +			mode_cmd.handles[0] = 0;
> +			mode_cmd.pitches[0] = mode_cmd.width * 4;
> +			mode_cmd.offsets[0] = 0;
> +			mode_cmd.modifier[0] = DRM_FORMAT_MOD_LINEAR;
> +
> +			drm_helper_mode_fill_fb_struct(&dev_priv->drm,
> +						       &intel_fb->base, &mode_cmd);
> +
> +			ret = drm_framebuffer_init(&dev_priv->drm,
> +						   &intel_fb->base, &meta_fb_funcs);
> +			if (ret) {
> +				DRM_ERROR("%s: framebuffer init failed %d\n",
> +					  __func__, ret);
> +				kfree(intel_fb);
> +				return ret;
> +			}
> +
> +			meta_data = kmalloc(sizeof(struct intel_vgpu_fb_meta_data),
> +					    GFP_KERNEL);
> +			if (unlikely(!meta_data)) {
> +				return -ENOMEM;
> +			}
> +
> +			meta_data->vgpu_plane_id = (vgpu->id << 16) |
> +				(pipe << 8) | plane_id;
> +			meta_data->vgpu = vgpu;
> +
> +			intel_fb->meta_fb.private = meta_data;
> +			intel_fb->meta_fb.update = meta_fb_update;
> +			intel_fb->meta_fb.type_id = INTEL_META_FB_VGPU;
> +
> +			vgpu->display.meta_fbs.meta_fb[pipe][plane_id] = intel_fb;
> +		}
> +	}
> +	return 0;
> +}
> +
>  /**
>   * intel_vgpu_clean_display - clean vGPU virtual display emulation
>   * @vgpu: a vGPU
> @@ -457,6 +603,8 @@ void intel_vgpu_clean_display(struct intel_vgpu *vgpu)
>  		clean_virtual_dp_monitor(vgpu, PORT_D);
>  	else
>  		clean_virtual_dp_monitor(vgpu, PORT_B);
> +
> +	clean_meta_fb(vgpu);
>  }
>  
>  /**
> @@ -476,6 +624,8 @@ int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution)
>  
>  	intel_vgpu_init_i2c_edid(vgpu);
>  
> +	init_meta_fb(vgpu);
> +
>  	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
>  		return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D,
>  						resolution);
> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
> index 31f6cdb..0ab10b0 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> @@ -131,10 +131,16 @@ struct intel_vgpu_opregion {
>  
>  #define vgpu_opregion(vgpu) (&(vgpu->opregion))
>  
> +struct intel_vgpu_meta_fbs {
> +	struct intel_framebuffer *meta_fb[I915_MAX_PIPES][I915_MAX_PLANES];
> +	u32 plane_id_index;
> +};
> +
>  struct intel_vgpu_display {
>  	struct intel_vgpu_i2c_edid i2c_edid;
>  	struct intel_vgpu_port ports[I915_MAX_PORTS];
>  	struct intel_vgpu_sbi sbi;
> +	struct intel_vgpu_meta_fbs meta_fbs;
>  };
>  
>  struct vgpu_sched_ctl {
> @@ -301,6 +307,13 @@ struct intel_vgpu_type {
>  	enum intel_vgpu_edid resolution;
>  };
>  
> +struct assigned_plane {
> +	u32 vgpu_plane_id;
> +
> +	/* userspace visible identifier */
> +	int framebuffer_id;
> +};
> +
>  struct intel_gvt {
>  	/* GVT scope lock, protect GVT itself, and all resource currently
>  	 * not yet protected by special locks(vgpu and scheduler lock).
> @@ -340,6 +353,9 @@ struct intel_gvt {
>  	} engine_mmio_list;
>  
>  	struct dentry *debugfs_root;
> +
> +	/* vGPU plane assignment */
> +	struct assigned_plane assigned_plane[I915_MAX_PIPES][I915_MAX_PLANES];
>  };
>  
>  static inline struct intel_gvt *to_gvt(struct drm_i915_private *i915)
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index c107214..7f4704d 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -1420,12 +1420,58 @@ hw_id_show(struct device *dev, struct device_attribute *attr,
>  	return sprintf(buf, "\n");
>  }
>  
> +static ssize_t
> +plane_id_index_show(struct device *dev, struct device_attribute *attr,
> +	 char *buf)
> +{
> +	struct mdev_device *mdev = mdev_from_dev(dev);
> +
> +	if (mdev) {
> +		struct intel_vgpu *vgpu = (struct intel_vgpu *)
> +			mdev_get_drvdata(mdev);
> +		enum pipe pipe = vgpu->display.meta_fbs.plane_id_index &
> +			0x000000F0;
> +		enum plane_id plane_id = vgpu->display.meta_fbs.plane_id_index &
> +			0x0000000F;
> +
> +		if ((pipe < I915_MAX_PIPES || plane_id < I915_MAX_PLANES) &&
> +			vgpu->display.meta_fbs.meta_fb[pipe][plane_id]) {
> +			return sprintf(buf, "%u\n",
> +			       vgpu->display.meta_fbs.meta_fb[pipe][plane_id]->base.base.id);
> +		}
> +	}
> +	return sprintf(buf, "\n");
> +}
> +
> +static ssize_t
> +plane_id_index_store(struct device *dev, struct device_attribute *attr,
> +			     const char *buf, size_t n)
> +{
> +	struct mdev_device *mdev = mdev_from_dev(dev);
> +	ssize_t ret;
> +	u32 val;
> +
> +	ret = kstrtou32(buf, 0, &val);
> +	if (ret)
> +		return ret;
> +
> +	if (mdev) {
> +		struct intel_vgpu *vgpu = (struct intel_vgpu *)
> +			mdev_get_drvdata(mdev);
> +		vgpu->display.meta_fbs.plane_id_index = val;
> +	}
> +
> +	return n;
> +}
> +
>  static DEVICE_ATTR_RO(vgpu_id);
>  static DEVICE_ATTR_RO(hw_id);
> +static DEVICE_ATTR_RW(plane_id_index);
>  
>  static struct attribute *intel_vgpu_attrs[] = {
>  	&dev_attr_vgpu_id.attr,
>  	&dev_attr_hw_id.attr,
> +	&dev_attr_plane_id_index.attr,
>  	NULL
>  };
>  
> -- 
> 2.7.4
> 
> _______________________________________________
> intel-gvt-dev mailing list
> intel-gvt-dev@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gvt-dev

-- 
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] 14+ messages in thread

* Re: [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's planes
  2018-12-03  8:21   ` Zhenyu Wang
@ 2018-12-03  8:35     ` Zhenyu Wang
  2018-12-03  8:58       ` Zhang, Tina
  2018-12-03  8:53     ` Zhang, Tina
  2018-12-03  8:55     ` Zhang, Tina
  2 siblings, 1 reply; 14+ messages in thread
From: Zhenyu Wang @ 2018-12-03  8:35 UTC (permalink / raw)
  To: Zhang, Tina; +Cc: kalyan.kondapally, intel-gfx, intel-gvt-dev


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

On 2018.12.03 16:21:04 +0800, Zhenyu Wang wrote:
> On 2018.12.03 15:35:17 +0800, Tina Zhang wrote:
> > Create and initialize vGPU meta framebuffers during vGPU's creation.
> > Each meta framebuffer is an intel_framebuffer. Userspace can get the
> > userspace visible identifier of that meta framebuffer by accessing
> > plane_id_index attribute.
> > 
> > For example:
> > In "/sys/bus/pci/devices/0000\:00\:02.0/$vGPU_id/intel_vgpu/" directory,
> > 
> >    /* plane_id_index: pipe#(bit16:8) and plane#(bit7:0)*/
> >    echo "0x10" > plane_index_id //Set the index to the plane 0 of pipe 1
> > 
> >    /*
> >     * Dump userspace visible identifier of the meta framebuffer
> >     * standing for the primary plane of the vGPU's pipe one
> >     */
> >    cat plane_index_id //dump the id for plane 0 of pipe 1
> > 
> > Then userspace can use this id with the exsting KMS IOCTL, e.g.
> > drmModeSetPlane, to assign a physical plane to this virtual plane.
> 
> How does user know which plane/pipe is active for vGPU? Looks from
> current code it has no way to know that. I think for guest display
> assignment, we need to know the display state of vGPU and it looks
> there's no state tracking, e.g what if guest driver switches to
> another plane for display? How could user know that then adjust for
> assignment?
> 
> And really don't like sysfs to r/w file for id, even if doesn't use
> vfio gfx dmabuf interface for guest display object presentation, a
> vendor specific vfio device ioctl if possible is better.
>

And add that this device specific info sysfs is created when mdev
device created before it's opened for vGPU instance. So I don't think
it's proper place to put display config info.

-- 
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] 14+ messages in thread

* Re: [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's planes
  2018-12-03  8:21   ` Zhenyu Wang
  2018-12-03  8:35     ` Zhenyu Wang
@ 2018-12-03  8:53     ` Zhang, Tina
  2018-12-03  8:55     ` Zhang, Tina
  2 siblings, 0 replies; 14+ messages in thread
From: Zhang, Tina @ 2018-12-03  8:53 UTC (permalink / raw)
  To: Zhenyu Wang; +Cc: Kondapally, Kalyan, intel-gfx, intel-gvt-dev



> -----Original Message-----
> From: Zhenyu Wang [mailto:zhenyuw@linux.intel.com]
> Sent: Monday, December 3, 2018 4:21 PM
> To: Zhang, Tina <tina.zhang@intel.com>
> Cc: intel-gfx@lists.freedesktop.org; Kondapally, Kalyan
> <kalyan.kondapally@intel.com>; intel-gvt-dev@lists.freedesktop.org; Wang, Zhi
> A <zhi.a.wang@intel.com>
> Subject: Re: [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's
> planes
> 
> On 2018.12.03 15:35:17 +0800, Tina Zhang wrote:
> > Create and initialize vGPU meta framebuffers during vGPU's creation.
> > Each meta framebuffer is an intel_framebuffer. Userspace can get the
> > userspace visible identifier of that meta framebuffer by accessing
> > plane_id_index attribute.
> >
> > For example:
> > In "/sys/bus/pci/devices/0000\:00\:02.0/$vGPU_id/intel_vgpu/"
> > directory,
> >
> >    /* plane_id_index: pipe#(bit16:8) and plane#(bit7:0)*/
> >    echo "0x10" > plane_index_id //Set the index to the plane 0 of pipe
> > 1
> >
> >    /*
> >     * Dump userspace visible identifier of the meta framebuffer
> >     * standing for the primary plane of the vGPU's pipe one
> >     */
> >    cat plane_index_id //dump the id for plane 0 of pipe 1
> >
> > Then userspace can use this id with the exsting KMS IOCTL, e.g.
> > drmModeSetPlane, to assign a physical plane to this virtual plane.
> 
> How does user know which plane/pipe is active for vGPU? Looks from current
> code it has no way to know that. I think for guest display assignment, we need
> to know the display state of vGPU and it looks there's no state tracking, e.g what
> if guest driver switches to another plane for display? How could user know that
> then adjust for assignment?
So far, GVT-g has supported multi-heads. In another word, there is only one priramy
plane for each vGPU.

GVT-g only provides the EDID for one fixed display port and in the guest point
of view, there is only one pipe having a connected monitor, a.k.a only the planes on
one pipe can be used by guest OS.

> 
> And really don't like sysfs to r/w file for id, even if doesn't use vfio gfx dmabuf
> interface for guest display object presentation, a vendor specific vfio device ioctl
> if possible is better.
Yeah, we could consider about that.
Thanks.

BR,
Tina
> 
> >
> > Signed-off-by: Tina Zhang <tina.zhang@intel.com>
> > Cc: Zhenyu Wang <zhenyuw@linux.intel.com>
> > Cc: Zhi Wang <zhi.a.wang@intel.com>
> > ---
> >  drivers/gpu/drm/i915/gvt/display.c | 150
> +++++++++++++++++++++++++++++++++++++
> >  drivers/gpu/drm/i915/gvt/gvt.h     |  16 ++++
> >  drivers/gpu/drm/i915/gvt/kvmgt.c   |  46 ++++++++++++
> >  3 files changed, 212 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/gvt/display.c
> > b/drivers/gpu/drm/i915/gvt/display.c
> > index df1e141..a9176a1 100644
> > --- a/drivers/gpu/drm/i915/gvt/display.c
> > +++ b/drivers/gpu/drm/i915/gvt/display.c
> > @@ -442,6 +442,152 @@ void intel_gvt_emulate_vblank(struct intel_gvt
> *gvt)
> >  	mutex_unlock(&gvt->lock);
> >  }
> >
> > +struct intel_vgpu_fb_meta_data {
> > +	u32 vgpu_plane_id; /*
> vgpu_id(23:16):vgpu_pipe(15:8):vgpu_plane(7:0)*/
> > +	struct intel_vgpu *vgpu; // the vGPU this meta_fb belongs to };
> > +
> > +static void meta_fb_destroy(struct drm_framebuffer *fb) {
> > +	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> > +
> > +	if (intel_fb->meta_fb.type_id != INTEL_META_FB_VGPU)
> > +		return;
> > +
> > +	kfree(intel_fb->meta_fb.private);
> > +	intel_fb->meta_fb.private = NULL;
> > +
> > +	drm_framebuffer_cleanup(fb);
> > +	kfree(intel_fb);
> > +}
> > +
> > +static void clean_meta_fb(struct intel_vgpu *vgpu) {
> > +	enum pipe pipe;
> > +	enum plane_id plane_id;
> > +	struct intel_framebuffer *intel_fb;
> > +
> > +	for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) {
> > +		for (plane_id = 0; plane_id < I915_MAX_PLANES; plane_id++) {
> > +			intel_fb = vgpu-
> >display.meta_fbs.meta_fb[pipe][plane_id];
> > +			if (!intel_fb)
> > +				drm_framebuffer_put(&intel_fb->base);
> > +
> > +			intel_fb = NULL;
> > +		}
> > +	}
> > +}
> > +
> > +static int meta_fb_create_handle(struct drm_framebuffer *fb,
> > +				 struct drm_file *file,
> > +				 unsigned int *handle)
> > +{
> > +	return -ENODEV;
> > +}
> > +
> > +static int meta_fb_dirty(struct drm_framebuffer *fb,
> > +			 struct drm_file *file,
> > +			 unsigned int flags,
> > +			 unsigned int color,
> > +			 struct drm_clip_rect *clips,
> > +			 unsigned int num_clips)
> > +{
> > +	return 0;
> > +}
> > +
> > +static const struct drm_framebuffer_funcs meta_fb_funcs = {
> > +	.destroy = meta_fb_destroy,
> > +	.create_handle = meta_fb_create_handle,
> > +	.dirty = meta_fb_dirty,
> > +};
> > +
> > +static void meta_fb_update(struct intel_framebuffer *intel_fb,
> > +			   enum pipe pipe, enum plane_id plane_id) {
> > +	struct intel_vgpu_fb_meta_data *meta_data;
> > +	struct intel_gvt *gvt;
> > +
> > +	if (!intel_fb || intel_fb->meta_fb.type_id != INTEL_META_FB_VGPU)
> > +		return;
> > +
> > +	meta_data = intel_fb->meta_fb.private;
> > +	gvt = meta_data->vgpu->gvt;
> > +
> > +	if (gvt->assigned_plane[pipe][plane_id].vgpu_plane_id !=
> > +						meta_data->vgpu_plane_id) {
> > +		gvt->assigned_plane[pipe][plane_id].vgpu_plane_id =
> > +						meta_data->vgpu_plane_id;
> > +		gvt->assigned_plane[pipe][plane_id].framebuffer_id =
> > +						intel_fb->base.base.id;
> > +		intel_fb->meta_fb.ggtt_offset = 0;
> > +		intel_fb->meta_fb.should_be_offscreen = true;
> > +	} else if (!intel_fb->meta_fb.ggtt_offset) {
> > +		intel_fb->meta_fb.should_be_offscreen = true;
> > +	} else {
> > +		intel_fb->meta_fb.should_be_offscreen = false;
> > +	}
> > +}
> > +
> > +static int init_meta_fb(struct intel_vgpu *vgpu) {
> > +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
> > +	struct intel_vgpu_fb_meta_data *meta_data;
> > +	struct drm_mode_fb_cmd2 mode_cmd;
> > +	struct intel_framebuffer *intel_fb;
> > +	enum pipe pipe;
> > +	enum plane_id plane_id;
> > +	int ret = 0;
> > +
> > +	for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) {
> > +		for (plane_id = 0; plane_id < I915_MAX_PLANES; plane_id++) {
> > +			intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
> > +			if (!intel_fb)
> > +				return -ENOMEM;
> > +
> > +			/*
> > +			 * Create a drm_framebuffer with defaults.
> > +			 */
> > +			mode_cmd.pixel_format = DRM_FORMAT_XRGB8888;
> > +			mode_cmd.width = dev_priv-
> >drm.mode_config.max_width;
> > +			mode_cmd.height = dev_priv-
> >drm.mode_config.max_height;
> > +			mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
> > +			mode_cmd.handles[0] = 0;
> > +			mode_cmd.pitches[0] = mode_cmd.width * 4;
> > +			mode_cmd.offsets[0] = 0;
> > +			mode_cmd.modifier[0] =
> DRM_FORMAT_MOD_LINEAR;
> > +
> > +			drm_helper_mode_fill_fb_struct(&dev_priv->drm,
> > +						       &intel_fb->base,
> &mode_cmd);
> > +
> > +			ret = drm_framebuffer_init(&dev_priv->drm,
> > +						   &intel_fb->base,
> &meta_fb_funcs);
> > +			if (ret) {
> > +				DRM_ERROR("%s: framebuffer init
> failed %d\n",
> > +					  __func__, ret);
> > +				kfree(intel_fb);
> > +				return ret;
> > +			}
> > +
> > +			meta_data = kmalloc(sizeof(struct
> intel_vgpu_fb_meta_data),
> > +					    GFP_KERNEL);
> > +			if (unlikely(!meta_data)) {
> > +				return -ENOMEM;
> > +			}
> > +
> > +			meta_data->vgpu_plane_id = (vgpu->id << 16) |
> > +				(pipe << 8) | plane_id;
> > +			meta_data->vgpu = vgpu;
> > +
> > +			intel_fb->meta_fb.private = meta_data;
> > +			intel_fb->meta_fb.update = meta_fb_update;
> > +			intel_fb->meta_fb.type_id = INTEL_META_FB_VGPU;
> > +
> > +			vgpu->display.meta_fbs.meta_fb[pipe][plane_id] =
> intel_fb;
> > +		}
> > +	}
> > +	return 0;
> > +}
> > +
> >  /**
> >   * intel_vgpu_clean_display - clean vGPU virtual display emulation
> >   * @vgpu: a vGPU
> > @@ -457,6 +603,8 @@ void intel_vgpu_clean_display(struct intel_vgpu
> *vgpu)
> >  		clean_virtual_dp_monitor(vgpu, PORT_D);
> >  	else
> >  		clean_virtual_dp_monitor(vgpu, PORT_B);
> > +
> > +	clean_meta_fb(vgpu);
> >  }
> >
> >  /**
> > @@ -476,6 +624,8 @@ int intel_vgpu_init_display(struct intel_vgpu
> > *vgpu, u64 resolution)
> >
> >  	intel_vgpu_init_i2c_edid(vgpu);
> >
> > +	init_meta_fb(vgpu);
> > +
> >  	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
> >  		return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D,
> >  						resolution);
> > diff --git a/drivers/gpu/drm/i915/gvt/gvt.h
> > b/drivers/gpu/drm/i915/gvt/gvt.h index 31f6cdb..0ab10b0 100644
> > --- a/drivers/gpu/drm/i915/gvt/gvt.h
> > +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> > @@ -131,10 +131,16 @@ struct intel_vgpu_opregion {
> >
> >  #define vgpu_opregion(vgpu) (&(vgpu->opregion))
> >
> > +struct intel_vgpu_meta_fbs {
> > +	struct intel_framebuffer
> *meta_fb[I915_MAX_PIPES][I915_MAX_PLANES];
> > +	u32 plane_id_index;
> > +};
> > +
> >  struct intel_vgpu_display {
> >  	struct intel_vgpu_i2c_edid i2c_edid;
> >  	struct intel_vgpu_port ports[I915_MAX_PORTS];
> >  	struct intel_vgpu_sbi sbi;
> > +	struct intel_vgpu_meta_fbs meta_fbs;
> >  };
> >
> >  struct vgpu_sched_ctl {
> > @@ -301,6 +307,13 @@ struct intel_vgpu_type {
> >  	enum intel_vgpu_edid resolution;
> >  };
> >
> > +struct assigned_plane {
> > +	u32 vgpu_plane_id;
> > +
> > +	/* userspace visible identifier */
> > +	int framebuffer_id;
> > +};
> > +
> >  struct intel_gvt {
> >  	/* GVT scope lock, protect GVT itself, and all resource currently
> >  	 * not yet protected by special locks(vgpu and scheduler lock).
> > @@ -340,6 +353,9 @@ struct intel_gvt {
> >  	} engine_mmio_list;
> >
> >  	struct dentry *debugfs_root;
> > +
> > +	/* vGPU plane assignment */
> > +	struct assigned_plane
> > +assigned_plane[I915_MAX_PIPES][I915_MAX_PLANES];
> >  };
> >
> >  static inline struct intel_gvt *to_gvt(struct drm_i915_private *i915)
> > diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> > b/drivers/gpu/drm/i915/gvt/kvmgt.c
> > index c107214..7f4704d 100644
> > --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> > +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> > @@ -1420,12 +1420,58 @@ hw_id_show(struct device *dev, struct
> device_attribute *attr,
> >  	return sprintf(buf, "\n");
> >  }
> >
> > +static ssize_t
> > +plane_id_index_show(struct device *dev, struct device_attribute *attr,
> > +	 char *buf)
> > +{
> > +	struct mdev_device *mdev = mdev_from_dev(dev);
> > +
> > +	if (mdev) {
> > +		struct intel_vgpu *vgpu = (struct intel_vgpu *)
> > +			mdev_get_drvdata(mdev);
> > +		enum pipe pipe = vgpu->display.meta_fbs.plane_id_index &
> > +			0x000000F0;
> > +		enum plane_id plane_id = vgpu-
> >display.meta_fbs.plane_id_index &
> > +			0x0000000F;
> > +
> > +		if ((pipe < I915_MAX_PIPES || plane_id < I915_MAX_PLANES)
> &&
> > +			vgpu->display.meta_fbs.meta_fb[pipe][plane_id]) {
> > +			return sprintf(buf, "%u\n",
> > +			       vgpu->display.meta_fbs.meta_fb[pipe][plane_id]-
> >base.base.id);
> > +		}
> > +	}
> > +	return sprintf(buf, "\n");
> > +}
> > +
> > +static ssize_t
> > +plane_id_index_store(struct device *dev, struct device_attribute *attr,
> > +			     const char *buf, size_t n)
> > +{
> > +	struct mdev_device *mdev = mdev_from_dev(dev);
> > +	ssize_t ret;
> > +	u32 val;
> > +
> > +	ret = kstrtou32(buf, 0, &val);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if (mdev) {
> > +		struct intel_vgpu *vgpu = (struct intel_vgpu *)
> > +			mdev_get_drvdata(mdev);
> > +		vgpu->display.meta_fbs.plane_id_index = val;
> > +	}
> > +
> > +	return n;
> > +}
> > +
> >  static DEVICE_ATTR_RO(vgpu_id);
> >  static DEVICE_ATTR_RO(hw_id);
> > +static DEVICE_ATTR_RW(plane_id_index);
> >
> >  static struct attribute *intel_vgpu_attrs[] = {
> >  	&dev_attr_vgpu_id.attr,
> >  	&dev_attr_hw_id.attr,
> > +	&dev_attr_plane_id_index.attr,
> >  	NULL
> >  };
> >
> > --
> > 2.7.4
> >
> > _______________________________________________
> > intel-gvt-dev mailing list
> > intel-gvt-dev@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gvt-dev
> 
> --
> 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] 14+ messages in thread

* Re: [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's planes
  2018-12-03  8:21   ` Zhenyu Wang
  2018-12-03  8:35     ` Zhenyu Wang
  2018-12-03  8:53     ` Zhang, Tina
@ 2018-12-03  8:55     ` Zhang, Tina
  2 siblings, 0 replies; 14+ messages in thread
From: Zhang, Tina @ 2018-12-03  8:55 UTC (permalink / raw)
  To: Zhenyu Wang; +Cc: Kondapally, Kalyan, intel-gfx, intel-gvt-dev



> -----Original Message-----
> From: Zhang, Tina
> Sent: Monday, December 3, 2018 4:53 PM
> To: 'Zhenyu Wang' <zhenyuw@linux.intel.com>
> Cc: intel-gfx@lists.freedesktop.org; Kondapally, Kalyan
> <kalyan.kondapally@intel.com>; intel-gvt-dev@lists.freedesktop.org; Wang, Zhi
> A <zhi.a.wang@intel.com>
> Subject: RE: [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's
> planes
> 
> 
> 
> > -----Original Message-----
> > From: Zhenyu Wang [mailto:zhenyuw@linux.intel.com]
> > Sent: Monday, December 3, 2018 4:21 PM
> > To: Zhang, Tina <tina.zhang@intel.com>
> > Cc: intel-gfx@lists.freedesktop.org; Kondapally, Kalyan
> > <kalyan.kondapally@intel.com>; intel-gvt-dev@lists.freedesktop.org;
> > Wang, Zhi A <zhi.a.wang@intel.com>
> > Subject: Re: [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for
> > vGPU's planes
> >
> > On 2018.12.03 15:35:17 +0800, Tina Zhang wrote:
> > > Create and initialize vGPU meta framebuffers during vGPU's creation.
> > > Each meta framebuffer is an intel_framebuffer. Userspace can get the
> > > userspace visible identifier of that meta framebuffer by accessing
> > > plane_id_index attribute.
> > >
> > > For example:
> > > In "/sys/bus/pci/devices/0000\:00\:02.0/$vGPU_id/intel_vgpu/"
> > > directory,
> > >
> > >    /* plane_id_index: pipe#(bit16:8) and plane#(bit7:0)*/
> > >    echo "0x10" > plane_index_id //Set the index to the plane 0 of
> > > pipe
> > > 1
> > >
> > >    /*
> > >     * Dump userspace visible identifier of the meta framebuffer
> > >     * standing for the primary plane of the vGPU's pipe one
> > >     */
> > >    cat plane_index_id //dump the id for plane 0 of pipe 1
> > >
> > > Then userspace can use this id with the exsting KMS IOCTL, e.g.
> > > drmModeSetPlane, to assign a physical plane to this virtual plane.
> >
> > How does user know which plane/pipe is active for vGPU? Looks from
> > current code it has no way to know that. I think for guest display
> > assignment, we need to know the display state of vGPU and it looks
> > there's no state tracking, e.g what if guest driver switches to
> > another plane for display? How could user know that then adjust for
> assignment?
> So far, GVT-g has supported multi-heads. In another word, there is only one
> priramy plane for each vGPU.
The "has" here was actually "hasn't". Sorry for this typo.

BR,
Tina
> 
> GVT-g only provides the EDID for one fixed display port and in the guest point of
> view, there is only one pipe having a connected monitor, a.k.a only the planes
> on one pipe can be used by guest OS.
> 
> >
> > And really don't like sysfs to r/w file for id, even if doesn't use
> > vfio gfx dmabuf interface for guest display object presentation, a
> > vendor specific vfio device ioctl if possible is better.
> Yeah, we could consider about that.
> Thanks.
> 
> BR,
> Tina
> >
> > >
> > > Signed-off-by: Tina Zhang <tina.zhang@intel.com>
> > > Cc: Zhenyu Wang <zhenyuw@linux.intel.com>
> > > Cc: Zhi Wang <zhi.a.wang@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/gvt/display.c | 150
> > +++++++++++++++++++++++++++++++++++++
> > >  drivers/gpu/drm/i915/gvt/gvt.h     |  16 ++++
> > >  drivers/gpu/drm/i915/gvt/kvmgt.c   |  46 ++++++++++++
> > >  3 files changed, 212 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/i915/gvt/display.c
> > > b/drivers/gpu/drm/i915/gvt/display.c
> > > index df1e141..a9176a1 100644
> > > --- a/drivers/gpu/drm/i915/gvt/display.c
> > > +++ b/drivers/gpu/drm/i915/gvt/display.c
> > > @@ -442,6 +442,152 @@ void intel_gvt_emulate_vblank(struct intel_gvt
> > *gvt)
> > >  	mutex_unlock(&gvt->lock);
> > >  }
> > >
> > > +struct intel_vgpu_fb_meta_data {
> > > +	u32 vgpu_plane_id; /*
> > vgpu_id(23:16):vgpu_pipe(15:8):vgpu_plane(7:0)*/
> > > +	struct intel_vgpu *vgpu; // the vGPU this meta_fb belongs to };
> > > +
> > > +static void meta_fb_destroy(struct drm_framebuffer *fb) {
> > > +	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> > > +
> > > +	if (intel_fb->meta_fb.type_id != INTEL_META_FB_VGPU)
> > > +		return;
> > > +
> > > +	kfree(intel_fb->meta_fb.private);
> > > +	intel_fb->meta_fb.private = NULL;
> > > +
> > > +	drm_framebuffer_cleanup(fb);
> > > +	kfree(intel_fb);
> > > +}
> > > +
> > > +static void clean_meta_fb(struct intel_vgpu *vgpu) {
> > > +	enum pipe pipe;
> > > +	enum plane_id plane_id;
> > > +	struct intel_framebuffer *intel_fb;
> > > +
> > > +	for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) {
> > > +		for (plane_id = 0; plane_id < I915_MAX_PLANES; plane_id++) {
> > > +			intel_fb = vgpu-
> > >display.meta_fbs.meta_fb[pipe][plane_id];
> > > +			if (!intel_fb)
> > > +				drm_framebuffer_put(&intel_fb->base);
> > > +
> > > +			intel_fb = NULL;
> > > +		}
> > > +	}
> > > +}
> > > +
> > > +static int meta_fb_create_handle(struct drm_framebuffer *fb,
> > > +				 struct drm_file *file,
> > > +				 unsigned int *handle)
> > > +{
> > > +	return -ENODEV;
> > > +}
> > > +
> > > +static int meta_fb_dirty(struct drm_framebuffer *fb,
> > > +			 struct drm_file *file,
> > > +			 unsigned int flags,
> > > +			 unsigned int color,
> > > +			 struct drm_clip_rect *clips,
> > > +			 unsigned int num_clips)
> > > +{
> > > +	return 0;
> > > +}
> > > +
> > > +static const struct drm_framebuffer_funcs meta_fb_funcs = {
> > > +	.destroy = meta_fb_destroy,
> > > +	.create_handle = meta_fb_create_handle,
> > > +	.dirty = meta_fb_dirty,
> > > +};
> > > +
> > > +static void meta_fb_update(struct intel_framebuffer *intel_fb,
> > > +			   enum pipe pipe, enum plane_id plane_id) {
> > > +	struct intel_vgpu_fb_meta_data *meta_data;
> > > +	struct intel_gvt *gvt;
> > > +
> > > +	if (!intel_fb || intel_fb->meta_fb.type_id != INTEL_META_FB_VGPU)
> > > +		return;
> > > +
> > > +	meta_data = intel_fb->meta_fb.private;
> > > +	gvt = meta_data->vgpu->gvt;
> > > +
> > > +	if (gvt->assigned_plane[pipe][plane_id].vgpu_plane_id !=
> > > +						meta_data->vgpu_plane_id) {
> > > +		gvt->assigned_plane[pipe][plane_id].vgpu_plane_id =
> > > +						meta_data->vgpu_plane_id;
> > > +		gvt->assigned_plane[pipe][plane_id].framebuffer_id =
> > > +						intel_fb->base.base.id;
> > > +		intel_fb->meta_fb.ggtt_offset = 0;
> > > +		intel_fb->meta_fb.should_be_offscreen = true;
> > > +	} else if (!intel_fb->meta_fb.ggtt_offset) {
> > > +		intel_fb->meta_fb.should_be_offscreen = true;
> > > +	} else {
> > > +		intel_fb->meta_fb.should_be_offscreen = false;
> > > +	}
> > > +}
> > > +
> > > +static int init_meta_fb(struct intel_vgpu *vgpu) {
> > > +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
> > > +	struct intel_vgpu_fb_meta_data *meta_data;
> > > +	struct drm_mode_fb_cmd2 mode_cmd;
> > > +	struct intel_framebuffer *intel_fb;
> > > +	enum pipe pipe;
> > > +	enum plane_id plane_id;
> > > +	int ret = 0;
> > > +
> > > +	for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) {
> > > +		for (plane_id = 0; plane_id < I915_MAX_PLANES; plane_id++) {
> > > +			intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
> > > +			if (!intel_fb)
> > > +				return -ENOMEM;
> > > +
> > > +			/*
> > > +			 * Create a drm_framebuffer with defaults.
> > > +			 */
> > > +			mode_cmd.pixel_format = DRM_FORMAT_XRGB8888;
> > > +			mode_cmd.width = dev_priv-
> > >drm.mode_config.max_width;
> > > +			mode_cmd.height = dev_priv-
> > >drm.mode_config.max_height;
> > > +			mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
> > > +			mode_cmd.handles[0] = 0;
> > > +			mode_cmd.pitches[0] = mode_cmd.width * 4;
> > > +			mode_cmd.offsets[0] = 0;
> > > +			mode_cmd.modifier[0] =
> > DRM_FORMAT_MOD_LINEAR;
> > > +
> > > +			drm_helper_mode_fill_fb_struct(&dev_priv->drm,
> > > +						       &intel_fb->base,
> > &mode_cmd);
> > > +
> > > +			ret = drm_framebuffer_init(&dev_priv->drm,
> > > +						   &intel_fb->base,
> > &meta_fb_funcs);
> > > +			if (ret) {
> > > +				DRM_ERROR("%s: framebuffer init
> > failed %d\n",
> > > +					  __func__, ret);
> > > +				kfree(intel_fb);
> > > +				return ret;
> > > +			}
> > > +
> > > +			meta_data = kmalloc(sizeof(struct
> > intel_vgpu_fb_meta_data),
> > > +					    GFP_KERNEL);
> > > +			if (unlikely(!meta_data)) {
> > > +				return -ENOMEM;
> > > +			}
> > > +
> > > +			meta_data->vgpu_plane_id = (vgpu->id << 16) |
> > > +				(pipe << 8) | plane_id;
> > > +			meta_data->vgpu = vgpu;
> > > +
> > > +			intel_fb->meta_fb.private = meta_data;
> > > +			intel_fb->meta_fb.update = meta_fb_update;
> > > +			intel_fb->meta_fb.type_id = INTEL_META_FB_VGPU;
> > > +
> > > +			vgpu->display.meta_fbs.meta_fb[pipe][plane_id] =
> > intel_fb;
> > > +		}
> > > +	}
> > > +	return 0;
> > > +}
> > > +
> > >  /**
> > >   * intel_vgpu_clean_display - clean vGPU virtual display emulation
> > >   * @vgpu: a vGPU
> > > @@ -457,6 +603,8 @@ void intel_vgpu_clean_display(struct intel_vgpu
> > *vgpu)
> > >  		clean_virtual_dp_monitor(vgpu, PORT_D);
> > >  	else
> > >  		clean_virtual_dp_monitor(vgpu, PORT_B);
> > > +
> > > +	clean_meta_fb(vgpu);
> > >  }
> > >
> > >  /**
> > > @@ -476,6 +624,8 @@ int intel_vgpu_init_display(struct intel_vgpu
> > > *vgpu, u64 resolution)
> > >
> > >  	intel_vgpu_init_i2c_edid(vgpu);
> > >
> > > +	init_meta_fb(vgpu);
> > > +
> > >  	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
> > >  		return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D,
> > >  						resolution);
> > > diff --git a/drivers/gpu/drm/i915/gvt/gvt.h
> > > b/drivers/gpu/drm/i915/gvt/gvt.h index 31f6cdb..0ab10b0 100644
> > > --- a/drivers/gpu/drm/i915/gvt/gvt.h
> > > +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> > > @@ -131,10 +131,16 @@ struct intel_vgpu_opregion {
> > >
> > >  #define vgpu_opregion(vgpu) (&(vgpu->opregion))
> > >
> > > +struct intel_vgpu_meta_fbs {
> > > +	struct intel_framebuffer
> > *meta_fb[I915_MAX_PIPES][I915_MAX_PLANES];
> > > +	u32 plane_id_index;
> > > +};
> > > +
> > >  struct intel_vgpu_display {
> > >  	struct intel_vgpu_i2c_edid i2c_edid;
> > >  	struct intel_vgpu_port ports[I915_MAX_PORTS];
> > >  	struct intel_vgpu_sbi sbi;
> > > +	struct intel_vgpu_meta_fbs meta_fbs;
> > >  };
> > >
> > >  struct vgpu_sched_ctl {
> > > @@ -301,6 +307,13 @@ struct intel_vgpu_type {
> > >  	enum intel_vgpu_edid resolution;
> > >  };
> > >
> > > +struct assigned_plane {
> > > +	u32 vgpu_plane_id;
> > > +
> > > +	/* userspace visible identifier */
> > > +	int framebuffer_id;
> > > +};
> > > +
> > >  struct intel_gvt {
> > >  	/* GVT scope lock, protect GVT itself, and all resource currently
> > >  	 * not yet protected by special locks(vgpu and scheduler lock).
> > > @@ -340,6 +353,9 @@ struct intel_gvt {
> > >  	} engine_mmio_list;
> > >
> > >  	struct dentry *debugfs_root;
> > > +
> > > +	/* vGPU plane assignment */
> > > +	struct assigned_plane
> > > +assigned_plane[I915_MAX_PIPES][I915_MAX_PLANES];
> > >  };
> > >
> > >  static inline struct intel_gvt *to_gvt(struct drm_i915_private
> > > *i915) diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> > > b/drivers/gpu/drm/i915/gvt/kvmgt.c
> > > index c107214..7f4704d 100644
> > > --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> > > +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> > > @@ -1420,12 +1420,58 @@ hw_id_show(struct device *dev, struct
> > device_attribute *attr,
> > >  	return sprintf(buf, "\n");
> > >  }
> > >
> > > +static ssize_t
> > > +plane_id_index_show(struct device *dev, struct device_attribute *attr,
> > > +	 char *buf)
> > > +{
> > > +	struct mdev_device *mdev = mdev_from_dev(dev);
> > > +
> > > +	if (mdev) {
> > > +		struct intel_vgpu *vgpu = (struct intel_vgpu *)
> > > +			mdev_get_drvdata(mdev);
> > > +		enum pipe pipe = vgpu->display.meta_fbs.plane_id_index &
> > > +			0x000000F0;
> > > +		enum plane_id plane_id = vgpu-
> > >display.meta_fbs.plane_id_index &
> > > +			0x0000000F;
> > > +
> > > +		if ((pipe < I915_MAX_PIPES || plane_id < I915_MAX_PLANES)
> > &&
> > > +			vgpu->display.meta_fbs.meta_fb[pipe][plane_id]) {
> > > +			return sprintf(buf, "%u\n",
> > > +			       vgpu->display.meta_fbs.meta_fb[pipe][plane_id]-
> > >base.base.id);
> > > +		}
> > > +	}
> > > +	return sprintf(buf, "\n");
> > > +}
> > > +
> > > +static ssize_t
> > > +plane_id_index_store(struct device *dev, struct device_attribute *attr,
> > > +			     const char *buf, size_t n)
> > > +{
> > > +	struct mdev_device *mdev = mdev_from_dev(dev);
> > > +	ssize_t ret;
> > > +	u32 val;
> > > +
> > > +	ret = kstrtou32(buf, 0, &val);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	if (mdev) {
> > > +		struct intel_vgpu *vgpu = (struct intel_vgpu *)
> > > +			mdev_get_drvdata(mdev);
> > > +		vgpu->display.meta_fbs.plane_id_index = val;
> > > +	}
> > > +
> > > +	return n;
> > > +}
> > > +
> > >  static DEVICE_ATTR_RO(vgpu_id);
> > >  static DEVICE_ATTR_RO(hw_id);
> > > +static DEVICE_ATTR_RW(plane_id_index);
> > >
> > >  static struct attribute *intel_vgpu_attrs[] = {
> > >  	&dev_attr_vgpu_id.attr,
> > >  	&dev_attr_hw_id.attr,
> > > +	&dev_attr_plane_id_index.attr,
> > >  	NULL
> > >  };
> > >
> > > --
> > > 2.7.4
> > >
> > > _______________________________________________
> > > intel-gvt-dev mailing list
> > > intel-gvt-dev@lists.freedesktop.org
> > > https://lists.freedesktop.org/mailman/listinfo/intel-gvt-dev
> >
> > --
> > 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] 14+ messages in thread

* Re: [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's planes
  2018-12-03  8:35     ` Zhenyu Wang
@ 2018-12-03  8:58       ` Zhang, Tina
  0 siblings, 0 replies; 14+ messages in thread
From: Zhang, Tina @ 2018-12-03  8:58 UTC (permalink / raw)
  To: Zhenyu Wang; +Cc: Kondapally, Kalyan, intel-gfx, intel-gvt-dev



> -----Original Message-----
> From: Zhenyu Wang [mailto:zhenyuw@linux.intel.com]
> Sent: Monday, December 3, 2018 4:36 PM
> To: Zhang, Tina <tina.zhang@intel.com>
> Cc: intel-gfx@lists.freedesktop.org; Kondapally, Kalyan
> <kalyan.kondapally@intel.com>; intel-gvt-dev@lists.freedesktop.org; Wang, Zhi
> A <zhi.a.wang@intel.com>
> Subject: Re: [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's
> planes
> 
> On 2018.12.03 16:21:04 +0800, Zhenyu Wang wrote:
> > On 2018.12.03 15:35:17 +0800, Tina Zhang wrote:
> > > Create and initialize vGPU meta framebuffers during vGPU's creation.
> > > Each meta framebuffer is an intel_framebuffer. Userspace can get the
> > > userspace visible identifier of that meta framebuffer by accessing
> > > plane_id_index attribute.
> > >
> > > For example:
> > > In "/sys/bus/pci/devices/0000\:00\:02.0/$vGPU_id/intel_vgpu/"
> > > directory,
> > >
> > >    /* plane_id_index: pipe#(bit16:8) and plane#(bit7:0)*/
> > >    echo "0x10" > plane_index_id //Set the index to the plane 0 of
> > > pipe 1
> > >
> > >    /*
> > >     * Dump userspace visible identifier of the meta framebuffer
> > >     * standing for the primary plane of the vGPU's pipe one
> > >     */
> > >    cat plane_index_id //dump the id for plane 0 of pipe 1
> > >
> > > Then userspace can use this id with the exsting KMS IOCTL, e.g.
> > > drmModeSetPlane, to assign a physical plane to this virtual plane.
> >
> > How does user know which plane/pipe is active for vGPU? Looks from
> > current code it has no way to know that. I think for guest display
> > assignment, we need to know the display state of vGPU and it looks
> > there's no state tracking, e.g what if guest driver switches to
> > another plane for display? How could user know that then adjust for
> > assignment?
> >
> > And really don't like sysfs to r/w file for id, even if doesn't use
> > vfio gfx dmabuf interface for guest display object presentation, a
> > vendor specific vfio device ioctl if possible is better.
> >
> 
> And add that this device specific info sysfs is created when mdev device created
> before it's opened for vGPU instance. So I don't think it's proper place to put
> display config info.
It's actually one of the intel_vgpu attributes. And it's created during vGPU being created.
Thanks.

BR,
Tina
> 
> --
> 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] 14+ messages in thread

end of thread, other threads:[~2018-12-03  8:58 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-03  7:35 [RFC PATCH 0/7] drm/i915/gvt: Enable vGPU local display direct flip Tina Zhang
2018-12-03  7:35 ` [RFC PATCH 1/7] drm/i915: Introduce meta framebuffer Tina Zhang
2018-12-03  7:35 ` [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's planes Tina Zhang
2018-12-03  8:21   ` Zhenyu Wang
2018-12-03  8:35     ` Zhenyu Wang
2018-12-03  8:58       ` Zhang, Tina
2018-12-03  8:53     ` Zhang, Tina
2018-12-03  8:55     ` Zhang, Tina
2018-12-03  7:35 ` [RFC PATCH 3/7] drm/i915: Introduce async plane update to i915 Tina Zhang
2018-12-03  7:35 ` [RFC PATCH 4/7] drm/i915: Extend async plane update to other planes Tina Zhang
2018-12-03  7:35 ` [RFC PATCH 5/7] drm/i915/gvt: Introduce vGPU plane page flip framework Tina Zhang
2018-12-03  7:35 ` [RFC PATCH 6/7] drm/i915/gvt: Enable guest direct page flip Tina Zhang
2018-12-03  7:35 ` [RFC PATCH 7/7] drm/i915/gvt: Introduce HW Vblank interrupt to vGPU Tina Zhang
2018-12-03  7:53 ` ✗ Fi.CI.BAT: failure for drm/i915/gvt: Enable vGPU local display direct flip Patchwork

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.