[RFC PATCH v2 1/3] drm/i915/gvt: Introduce vgpu shadow framebuffer

Tina Zhang tina.zhang at intel.com
Fri May 10 04:15:26 UTC 2019


Shadow framebuffer is introduced to track the framebuffer attached on
virtual plane in guest. Instread of letting guest framebuffer with
guest GGTT address go on HW plane, the shadow framebuffer pinned on
host GGTT space with guest framebuffer decoded info is controlled by
gvt-g, where the shadow framebuffer can be committed to HW plane thru
the host drm/kms framework APIs.

Signed-off-by: Tina Zhang <tina.zhang at intel.com>
---
 drivers/gpu/drm/i915/gvt/display.c | 110 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/display.h |   2 +-
 drivers/gpu/drm/i915/gvt/dmabuf.c  |   2 +-
 drivers/gpu/drm/i915/gvt/dmabuf.h  |   4 +-
 drivers/gpu/drm/i915/gvt/gvt.h     |   7 +++
 5 files changed, 122 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
index e1c313d..0a80036 100644
--- a/drivers/gpu/drm/i915/gvt/display.c
+++ b/drivers/gpu/drm/i915/gvt/display.c
@@ -32,6 +32,10 @@
  *
  */
 
+#include <drm/drm_mode.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_atomic_uapi.h>
+#include <drm/drm_atomic_helper.h>
 #include "i915_drv.h"
 #include "gvt.h"
 
@@ -444,6 +448,108 @@ void intel_gvt_emulate_vblank(struct intel_gvt *gvt)
 	mutex_unlock(&gvt->lock);
 }
 
+static void clean_shadow_fbs(struct intel_vgpu *vgpu)
+{
+	int plane_id;
+	struct drm_framebuffer *fb;
+	struct drm_i915_gem_object *obj;
+
+	for (plane_id = PRIMARY_PLANE; plane_id < GVT_MAX_PLANE; plane_id++) {
+		fb = vgpu->display.shadow_fbs.shadow_fb[plane_id];
+		if (fb) {
+			drm_framebuffer_put(fb);
+			vgpu->display.shadow_fbs.shadow_fb[plane_id] = NULL;
+		}
+
+		obj = vgpu->display.shadow_fbs.shadow_obj[plane_id];
+		if (obj) {
+			kfree(obj->gvt_info);
+
+			i915_gem_object_put(obj);
+			vgpu->display.shadow_fbs.shadow_obj[plane_id] = NULL;
+		}
+	}
+}
+
+static int shadow_fb_create(struct intel_vgpu *vgpu,
+			    enum intel_gvt_plane_type type)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	struct intel_vgpu_fb_info *info;
+	struct drm_mode_fb_cmd2 mode_cmd;
+	struct drm_framebuffer *fb;
+	struct drm_i915_gem_object *obj;
+	int ret = 0;
+
+	info = kzalloc(sizeof(struct intel_vgpu_fb_info),
+			       GFP_KERNEL);
+	if (unlikely(!info)) {
+		gvt_vgpu_err("allocate intel vgpu fb info failed\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (type == CURSOR_PLANE) {
+		mode_cmd.width = dev_priv->drm.mode_config.cursor_width;
+		mode_cmd.height = dev_priv->drm.mode_config.cursor_height;
+	} else {
+		mode_cmd.width = dev_priv->drm.mode_config.max_width;
+		mode_cmd.height = dev_priv->drm.mode_config.max_height;
+	}
+
+	info->size = (mode_cmd.width * mode_cmd.height * 4 + PAGE_SIZE - 1)
+					>> PAGE_SHIFT;
+	info->drm_format_mod = DRM_FORMAT_MOD_LINEAR;
+	info->vgpu_id = vgpu->id;
+	obj = vgpu_create_gem(&dev_priv->drm, info);
+	if (obj == NULL) {
+		gvt_vgpu_err("create gvt gem obj failed\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * Create a drm_framebuffer with defaults.
+	 */
+	mode_cmd.pixel_format = DRM_FORMAT_XRGB8888;
+	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;
+	fb = intel_framebuffer_create(obj, &mode_cmd);
+	if (IS_ERR(fb)) {
+		gvt_vgpu_err("create framebuffer failed\n");
+		i915_gem_object_put(obj);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	obj->gvt_info = info;
+
+	vgpu->display.shadow_fbs.shadow_fb[type] = fb;
+	vgpu->display.shadow_fbs.shadow_obj[type] = obj;
+
+out:
+	return ret;
+}
+
+static int init_shadow_fbs(struct intel_vgpu *vgpu)
+{
+	enum intel_gvt_plane_type type;
+	int ret = 0;
+
+	for (type = PRIMARY_PLANE; type < GVT_MAX_PLANE; type++) {
+		ret = shadow_fb_create(vgpu, type);
+		if (ret) {
+			clean_shadow_fbs(vgpu);
+			break;
+		}
+	}
+
+	return ret;
+}
+
 /**
  * intel_vgpu_emulate_hotplug - trigger hotplug event for vGPU
  * @vgpu: a vGPU
@@ -490,6 +596,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_shadow_fbs(vgpu);
 }
 
 /**
@@ -509,6 +617,8 @@ int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution)
 
 	intel_vgpu_init_i2c_edid(vgpu);
 
+	init_shadow_fbs(vgpu);
+
 	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ||
 	    IS_COFFEELAKE(dev_priv))
 		return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D,
diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h
index a87f33e..2ae3217 100644
--- a/drivers/gpu/drm/i915/gvt/display.h
+++ b/drivers/gpu/drm/i915/gvt/display.h
@@ -126,7 +126,7 @@ enum intel_gvt_plane_type {
 	PRIMARY_PLANE = 0,
 	CURSOR_PLANE,
 	SPRITE_PLANE,
-	MAX_PLANE
+	GVT_MAX_PLANE
 };
 
 struct intel_vgpu_dpcd_data {
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
index 4e1e425..e9adcd4 100644
--- a/drivers/gpu/drm/i915/gvt/dmabuf.c
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
@@ -147,7 +147,7 @@ static const struct drm_i915_gem_object_ops intel_vgpu_gem_ops = {
 	.release = vgpu_gem_release,
 };
 
-static struct drm_i915_gem_object *vgpu_create_gem(struct drm_device *dev,
+struct drm_i915_gem_object *vgpu_create_gem(struct drm_device *dev,
 		struct intel_vgpu_fb_info *info)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h b/drivers/gpu/drm/i915/gvt/dmabuf.h
index 5f8f03f..cf97eb4 100644
--- a/drivers/gpu/drm/i915/gvt/dmabuf.h
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
@@ -45,6 +45,7 @@ struct intel_vgpu_fb_info {
 	__u32 y_pos;	/* vertical position of cursor plane */
 	__u32 x_hot;    /* horizontal position of cursor hotspot */
 	__u32 y_hot;    /* vertical position of cursor hotspot */
+	__u32 vgpu_id;
 	struct intel_vgpu_dmabuf_obj *obj;
 };
 
@@ -63,5 +64,6 @@ struct intel_vgpu_dmabuf_obj {
 int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args);
 int intel_vgpu_get_dmabuf(struct intel_vgpu *vgpu, unsigned int dmabuf_id);
 void intel_vgpu_dmabuf_cleanup(struct intel_vgpu *vgpu);
-
+struct drm_i915_gem_object *vgpu_create_gem(struct drm_device *dev,
+					    struct intel_vgpu_fb_info *info);
 #endif
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index f5a328b..1bc10a7 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -124,10 +124,17 @@ struct intel_vgpu_opregion {
 
 #define vgpu_opregion(vgpu) (&(vgpu->opregion))
 
+struct intel_vgpu_shadow_fbs {
+	struct drm_framebuffer *shadow_fb[GVT_MAX_PLANE];
+	struct drm_i915_gem_object *shadow_obj[GVT_MAX_PLANE];
+	bool enable_direct_flip;
+};
+
 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_shadow_fbs shadow_fbs;
 };
 
 struct vgpu_sched_ctl {
-- 
2.7.4



More information about the intel-gvt-dev mailing list