Re: [PATCH v13 5/7] vfio: ABI for mdev display dma-buf operation

Alex Williamson
2017-08-08T18:07:55Z

On Tue, 8 Aug 2017 14:18:07 +0530
Kirti Wankhede <kwankhede@nvidia.com> wrote:

> On 8/7/2017 11:13 PM, Alex Williamson wrote:
> > On Mon, 7 Aug 2017 08:11:43 +0000
> > "Zhang, Tina" <tina.zhang@intel.com> wrote:
> >
> >> After going through the previous discussions, here are some summaries may be related to the current discussion:
> >> 1. How does user mode figure the device capabilities between region and dma-buf?
> >> VFIO_DEVICE_GET_REGION_INFO could tell if the mdev supports region case.
> >> Otherwise, the mdev supports dma-buf.
> >
> > Why do we need to make this assumption?
>
> Right, we should not make such assumption. Vendor driver might not
> support both or disable console vnc ( for example, for performance
> testing console VNC need to be disabled)
>
> > What happens when dma-buf is
> > superseded? What happens if a device supports both dma-buf and
> > regions? We have a flags field in vfio_device_gfx_plane_info, doesn't
> > it make sense to use it to identify which field, between region_index
> > and fd, is valid? We could even put region_index and fd into a union
> > with the flag bits indicating how to interpret the union, but I'm not
> > sure everyone was onboard with this idea. Seems like a waste of 4
> > bytes not to do that though.
> >
>
> Agree.
>
> > Thinking further, is the user ever in a situation where they query the
> > graphics plane info and can handle either a dma-buf or a region? It
> > seems more likely that the user needs to know early on which is
> > supported and would then require that they continue to see compatible
> > plane information... Should the user then be able to specify whether
> > they want a dma-buf or a region? Perhaps these flag bits are actually
> > input and the return should be -errno if the driver cannot produce
> > something compatible.
> >
> > Maybe we'd therefore define 3 flag bits: PROBE, DMABUF, REGION. In
> > this initial implementation, DMABUF or REGION would always be set by
> > the user to request that type of interface. Additionally, the QUERY
> > bit could be set to probe compatibility, thus if PROBE and REGION are
> > set, the vendor driver would return success only if it supports the
> > region based interface. If PROBE and DMABUF are set, the vendor driver
> > returns success only if the dma-buf based interface is supported. The
> > value of the remainder of the structure is undefined for PROBE.
> > Additionally setting both DMABUF and REGION is invalid. Undefined
> > flags bits must be validated as zero by the drivers for future use
> > (thus if we later define DMABUFv2, an older driver should
> > automatically return -errno when probed or requested).
> >
>
> Are you saying all of this to be part of VFIO_DEVICE_QUERY_GFX_PLANE ioctl?
>
> Let me summarize what we need, taking QEMU as reference:
> 1. From vfio_initfn(), for REGION case, get region info:
> vfio_get_dev_region_info(.., VFIO_REGION_SUBTYPE_CONSOLE_REGION,
> &vdev->console_opregion)
>
> If above return success, setup console REGION and mmap.
> I don't know what is required for DMABUF at this moment.
>
> If console VNC is supported either DMABUF or REGION, initialize console
> and register its callback operations:
>
> static const GraphicHwOps vfio_console_ops = {
> .gfx_update = vfio_console_update_display,
> };
>
> vdev->console = graphic_console_init(DEVICE(vdev), 0, &vfio_console_ops,
> vdev);

I might structure it that vfio_initfn() would call
ioctl(VFIO_DEVICE_QUERY_GFX_PLANE) with the PROBE bit set with either
DMABUF or REGION set as the interface type in the flags field. If
REGION is the probed interface and success is returned, then QEMU might
go look for regions of the appropriate type, however the
vfio_device_gfx_plane_info structure is canonical source for the region
index, so QEMU would probably be wise to use that and only use the
region type for consistency testing.

> 2. On above console registration, vfio_console_update_display() gets
> called for each refresh cycle of console. In that:
> - call ioctl(VFIO_DEVICE_QUERY_GFX_PLANE)
> - if (queried size > 0), update QEMU console surface (for REGION case
> read mmaped region, for DMABUF read surface using fd)

The ioctl would be called with REGION or DMABUF based on the initial
probe call, ex. we probed that REGION is supported and now we continue
to ask for region based updates. QEMU would need to verify the region
index matches that already mapped, remapping a different region if
necessary, and interpret the graphics parameters to provide the screen
update.

> Alex, in your proposal above, my understanding is
> ioctl(VFIO_DEVICE_QUERY_GFX_PLANE) with PROBE flag should be called in
> step #1.
> In step #2, ioctl(VFIO_DEVICE_QUERY_GFX_PLANE) will be without PROBE
> flag, but either DMABUF or REGION flag based on what is returned as
> supported by vendor driver in step #1. Is that correct?

Yes, that's the idea. Does it make sense/provide value?

> > It seems like this handles all the cases, the user can ask what's
> > supported and specifies the interface they want on every call. The
> > user therefore can also choose between region_index and fd and we can
> > make that a union.
> >
> >> 2. For dma-buf, how to differentiate unsupported vs not initialized?
> >> For dma-buf, when the mdev doesn't support some arguments, -EINVAL will be returned. And -errno will return when meeting other failures, like -ENOMEM.
> >> If the mdev is not initialized, there won't be any returned err. Just zero all the fields in structure vfio_device_gfx_plane_info.
> >
> > So we're relying on special values again :-\ For which fields is zero
> > not a valid value? I prefer the probe interface above unless there are
> > better ideas.
> >
>
> PROBE will be called during vdev initialization and after that
> vfio_console_update_display() gets called at every console refresh
> cycle. But until driver in guest is loaded, mmaped buffer/ DMABUF will
> not be populated with correct surface data. In that case for QUERY,
> vendor driver should return (atleast) size=0 which means there is
> nothing to copy. Once guest driver is loaded and surface is created by
> guest driver, QUERY interface should return valid size.

That seems reasonable and well specified. Thanks,

Alex

> >> 3. The id field in structure vfio_device_gfx_plane_info
> >> So far we haven't figured out the usage of this field for dma-buf usage. So, this field is changed to "region_index" and only used for region usage.
> >> In previous discussions, we thought this "id" field might be used for both dma-buf and region usages.
> >> So, we proposed some ways, like adding flags field to the structure. Another way to do it was to add this:
> >> enum vfio_device_gfx_type {
> >> VFIO_DEVICE_GFX_NONE,
> >> VFIO_DEVICE_GFX_DMABUF,
> >> VFIO_DEVICE_GFX_REGION,
> >> };
> >>
> >> struct vfio_device_gfx_query_caps {
> >> __u32 argsz;
> >> __u32 flags;
> >> enum vfio_device_gfx_type;
> >> };
> >> Obviously, we don't need to consider this again, unless we find the "region_index" means something for dma-buf usage.
> >
> > The usefulness of this ioctl seems really limited and once again we get
> > into a situation where having two ioctls leaves doubt whether this is
> > describing the current plane state. Thanks,
> >
> > Alex
> >
> >>>>>>>>> include/uapi/linux/vfio.h | 28 ++++++++++++++++++++++++++++
> >>>>>>>>> 1 file changed, 28 insertions(+)
> >>>>>>>>>
> >>>>>>>>> diff --git a/include/uapi/linux/vfio.h
> >>>>>>>>> b/include/uapi/linux/vfio.h index ae46105..827a230 100644
> >>>>>>>>> --- a/include/uapi/linux/vfio.h
> >>>>>>>>> +++ b/include/uapi/linux/vfio.h
> >>>>>>>>> @@ -502,6 +502,34 @@ struct vfio_pci_hot_reset {
> >>>>>>>>>
> >>>>>>>>> #define VFIO_DEVICE_PCI_HOT_RESET _IO(VFIO_TYPE,
> >>> VFIO_BASE +
> >>>>>>>> 13)
> >>>>>>>>>
> >>>>>>>>> +/**
> >>>>>>>>> + * VFIO_DEVICE_QUERY_GFX_PLANE - _IOW(VFIO_TYPE,
> >>> VFIO_BASE
> >>>> +
> >>>>>> 14,
> >>>>>>>>> +struct vfio_device_query_gfx_plane)
> >>>>>>>>> + *
> >>>>>>>>> + * Set the drm_plane_type and retrieve information about
> >>>>>>>>> +the gfx
> >>>> plane.
> >>>>>>>>> + *
> >>>>>>>>> + * Return: 0 on success, -errno on failure.
> >>>>>>>>> + */
> >>>>>>>>> +struct vfio_device_gfx_plane_info {
> >>>>>>>>> + __u32 argsz;
> >>>>>>>>> + __u32 flags;
> >>>>>>>>> + /* in */
> >>>>>>>>> + __u32 drm_plane_type; /* type of plane: DRM_PLANE_TYPE_*
> >>>> */
> >>>>>>>>> + /* out */
> >>>>>>>>> + __u32 drm_format; /* drm format of plane */
> >>>>>>>>> + __u64 drm_format_mod; /* tiled mode */
> >>>>>>>>> + __u32 width; /* width of plane */
> >>>>>>>>> + __u32 height; /* height of plane */
> >>>>>>>>> + __u32 stride; /* stride of plane */
> >>>>>>>>> + __u32 size; /* size of plane in bytes, align on page*/
> >>>>>>>>> + __u32 x_pos; /* horizontal position of cursor plane, upper
> >>>> left corner
> >>>>>>>> in pixels */
> >>>>>>>>> + __u32 y_pos; /* vertical position of cursor plane, upper left
> >>>> corner in
> >>>>>>>> lines*/
> >>>>>>>>> + __u32 region_index;
> >>>>>>>>> + __s32 fd; /* dma-buf fd */
> >>>>>>>>
> >>>>>>>> How do I know which of these is valid, region_index or fd?
> >>>>>>>> Can I ask for one vs the other? What are the errno values to
> >>>>>>>> differentiate unsupported vs not initialized? Is there a "probe"
> >>>>>>>> flag that I can use to determine what the device supports
> >>>>>>>> without allocating
> >>>>>> those resources yet?
> >>>>>>> Dma-buf won't use region_index, which means region_index is zero
> >>>>>>> all the
> >>>>>> time for dma-buf usage.
> >>>>>>> As we discussed, there won't be errno if not initialized, just
> >>>>>>> keep all fields
> >>>> zero.
> >>>>>>> I will add the comments about these in the next version. Thanks
> >>>>>>
> >>>>>> Zero is a valid region index.
> >>>>> If zero is valid, can we find out other invalid value? How about 0xffffffff?
> >>>>
> >>>> Unlikely, but also valid. Isn't this why we have a flags field in the
> >>>> structure, so we don't need to rely on implicit values as invalid.
> >>>> Also, all of the previously discussed usage models needs to be
> >>>> documented, either here in the header or in a Documentation/ file.
> >>> According to the previously discussion, we also have the following propose:
> >>> enum vfio_device_gfx_type {
> >>> VFIO_DEVICE_GFX_NONE,
> >>> VFIO_DEVICE_GFX_DMABUF,
> >>> VFIO_DEVICE_GFX_REGION,
> >>> };
> >>>
> >>> struct vfio_device_gfx_query_caps {
> >>> __u32 argsz;
> >>> __u32 flags;
> >>> enum vfio_device_gfx_type;
> >>> };
> >>> So, we may need to add one more ioctl, e.g. VFIO_DEVICE_QUERY_GFX_CAPS.
> >>> User mode can query this before querying the plan info, and to see which usage
> >>> (dma-buf or region) is supported.
> >>> Does it still make sense?
> >>> Thanks.
> >> So, I think we can rely on VFIO_DEVICE_GET_REGION_INFO to tell user mode whether the region case is using, instead of introducing a new ioctl.
> >> Thanks
> >>
> >> Tina
> >>>
> >>> Tina
> >>>
> >>>
> >>>> Thanks,
> >>>>
> >>>> Alex
> >>>> _______________________________________________
> >>>> dri-devel mailing list
> >>>> dri-devel@lists.freedesktop.org
> >>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
> >