[RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's planes
Zhenyu Wang
zhenyuw at linux.intel.com
Mon Dec 3 08:21:04 UTC 2018
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 at intel.com>
> Cc: Zhenyu Wang <zhenyuw at linux.intel.com>
> Cc: Zhi Wang <zhi.a.wang at 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 at 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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/intel-gvt-dev/attachments/20181203/acd7b6a8/attachment.sig>
More information about the intel-gvt-dev
mailing list