From: "Michael S. Tsirkin" <mst@redhat.com>
To: Gerd Hoffmann <kraxel@redhat.com>
Cc: virtio-dev@lists.oasis-open.org
Subject: Re: [virtio-dev] [PATCH] Add virtio gpu device specification.
Date: Tue, 3 Jul 2018 03:15:20 +0300 [thread overview]
Message-ID: <20180703031324-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <20180627061525.32537-1-kraxel@redhat.com>
On Wed, Jun 27, 2018 at 08:15:25AM +0200, Gerd Hoffmann wrote:
> Support for 2d mode (3d/virgl mode is not covered by this patch) has
> been added to the linux kernel version 4.2 and to qemu version 2.4.
>
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
No comments so far, as Gerd seems to be the only one with both
understanding the field and willing to contribute to the spec, I will
start voting in a couple of days unless there's interest from TC members
in working on this.
> ---
> content.tex | 2 +
> virtio-gpu.tex | 481 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 483 insertions(+)
> create mode 100644 virtio-gpu.tex
>
> diff --git a/content.tex b/content.tex
> index be1823431d..d41c2f8d76 100644
> --- a/content.tex
> +++ b/content.tex
> @@ -5325,6 +5325,8 @@ descriptor for the \field{sense_len}, \field{residual},
> \field{status_qualifier}, \field{status}, \field{response} and
> \field{sense} fields.
>
> +\input{virtio-gpu.tex}
> +
> \chapter{Reserved Feature Bits}\label{sec:Reserved Feature Bits}
>
> Currently these device-independent feature bits defined:
> diff --git a/virtio-gpu.tex b/virtio-gpu.tex
> new file mode 100644
> index 0000000000..34cf493bbc
> --- /dev/null
> +++ b/virtio-gpu.tex
> @@ -0,0 +1,481 @@
> +\section{GPU Device}\label{sec:Device Types / GPU Device}
> +
> +virtio-gpu is a virtio based graphics adapter. It can operate in 2D
> +mode and in 3D (virgl) mode. 3D mode will offload rendering ops to
> +the host gpu and therefore requires a gpu with 3D support on the host
> +machine.
> +
> +3D mode is not covered (yet) in this specification, even though it is
> +mentioned here and there due to some details of the virtual hardware
> +being designed with 3D mode in mind.
> +
> +In 2D mode the virtio-gpu device provides support for ARGB Hardware
> +cursors and multiple scanouts (aka heads).
> +
> +\subsection{Device ID}\label{sec:Device Types / GPU Device / Device ID}
> +
> +16
> +
> +\subsection{Virtqueues}\label{sec:Device Types / GPU Device / Virtqueues}
> +
> +\begin{description}
> +\item[0] controlq - queue for sending control commands
> +\item[1] cursorq - queue for sending cursor updates
> +\end{description}
> +
> +Both queues have the same format. Each request and each response have
> +a fixed header, followed by command specific data fields. The
> +separate cursor queue is the "fast track" for cursor commands
> +(VIRTIO_GPU_CMD_UPDATE_CURSOR and VIRTIO_GPU_CMD_MOVE_CURSOR), so they
> +go though without being delayed by time-consuming commands in the
> +control queue.
> +
> +\subsection{Feature bits}\label{sec:Device Types / GPU Device / Feature bits}
> +
> +\begin{description}
> +\item[VIRTIO_GPU_F_VIRGL (0)] virgl 3D mode is supported.
> +\end{description}
> +
> +\subsection{Device configuration layout}\label{sec:Device Types / GPU Device / Device configuration layout}
> +
> +\begin{lstlisting}
> +#define VIRTIO_GPU_EVENT_DISPLAY (1 << 0)
> +
> +struct virtio_gpu_config {
> + le32 events_read;
> + le32 events_clear;
> + le32 num_scanouts;
> + le32 reserved;
> +}
> +\end{lstlisting}
> +
> +\subsubsection{Device configuration fields}
> +
> +\begin{description}
> +\item[\field{events_read}] signals pending events to the driver. The
> + driver MUST NOT write to this field.
> +\item[\field{events_clear}] clears pending events in the device.
> + Writing a '1' into a bit will clear the corresponding bit in
> + \field{events_read}, mimicking write-to-clear behavior.
> +\item[\field{num_scanouts}] specifies the maximum number of scanouts
> + supported by the device. Minimum value is 1, maximum value is 16.
> +\end{description}
> +
> +\subsubsection{Events}
> +
> +\begin{description}
> +\item[VIRTIO_GPU_EVENT_DISPLAY] Display configuration has changed.
> + The driver SHOULD use the VIRTIO_GPU_CMD_GET_DISPLAY_INFO command to
> + fetch the information from the device.
> +\end{description}
> +
> +\devicenormative{\subsection}{Device Initialization}{Device Types / GPU Device / Device Initialization}
> +
> +The driver SHOULD query the display information from the device using
> +the VIRTIO_GPU_CMD_GET_DISPLAY_INFO command and use that information
> +for the initial scanout setup. In case no information is available or
> +all displays are disabled the driver MAY choose to use a fallback,
> +such as 1024x768 at display 0.
> +
> +\subsection{Device Operation}\label{sec:Device Types / GPU Device / Device Operation}
> +
> +The virtio-gpu is based around the concept of resources private to the
> +host, the guest must DMA transfer into these resources. This is a
> +design requirement in order to interface with future 3D rendering. In
> +the unaccelerated 2D mode there is no support for DMA transfers from
> +resources, just to them.
> +
> +Resources are initially simple 2D resources, consisting of a width,
> +height and format along with an identifier. The guest must then attach
> +backing store to the resources in order for DMA transfers to
> +work. This is like a GART in a real GPU.
> +
> +\subsubsection{Device Operation: Create a framebuffer and configure scanout}
> +
> +\begin{itemize*}
> +\item Create a host resource using VIRTIO_GPU_CMD_RESOURCE_CREATE_2D.
> +\item Allocate a framebuffer from guest ram, and attach it as backing
> + storage to the resource just created, using
> + VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING. Scatter lists are
> + supported, so the framebuffer doesn't need to be contignous in guest
> + physical memory.
> +\item Use VIRTIO_GPU_CMD_SET_SCANOUT to link the framebuffer to
> + a display scanout.
> +\end{itemize*}
> +
> +\subsubsection{Device Operation: Update a framebuffer and scanout}
> +
> +\begin{itemize*}
> +\item Render to your framebuffer memory.
> +\item Use VIRTIO_GPU_CMD_TRANSFER_SEND_2D to update the host resource
> + from guest memory.
> +\item Use VIRTIO_GPU_CMD_RESOURCE_FLUSH to flush the updated resource
> + to the display.
> +\end{itemize*}
> +
> +\subsubsection{Device Operation: Using pageflip}
> +
> +It is possible to create multiple framebuffers, flip between them
> +using VIRTIO_GPU_CMD_SET_SCANOUT and VIRTIO_GPU_CMD_RESOURCE_FLUSH,
> +and update the invisible framebuffer using
> +VIRTIO_GPU_CMD_TRANSFER_SEND_2D.
> +
> +\subsubsection{Device Operation: Multihead setup}
> +
> +In case two or more displays are present there are different ways to
> +configure things:
> +
> +\begin{itemize*}
> +\item Create a single framebuffer, link it to all displays
> + (mirroring).
> +\item Create an framebuffer for each display.
> +\item Create one big framebuffer, configure scanouts to display a
> + different rectangle of that framebuffer each.
> +\end{itemize*}
> +
> +\devicenormative{\subsubsection}{Device Operation: Command lifecycle and fencing}{Device Types / GPU Device / Device Operation / Device Operation: Command lifecycle and fencing}
> +
> +The device MAY process controlq commands asyncronously and return them
> +to the driver before the processing is complete. If the driver needs
> +to know when the processing is finished it can set the
> +VIRTIO_GPU_FLAG_FENCE flag in the request. The device MUST finish the
> +processing before returning the command then.
> +
> +Note: current qemu implementation does asyncrounous processing only in
> +3d mode, when offloading the processing to the host gpu.
> +
> +\subsubsection{Device Operation: Configure mouse cursor}
> +
> +The mouse cursor image is a normal resource, except that it must be
> +64x64 in size. The driver MUST create and populate the resource
> +(using the usual VIRTIO_GPU_CMD_RESOURCE_CREATE_2D,
> +VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING and
> +VIRTIO_GPU_CMD_TRANSFER_SEND_2D controlq commands) and make sure they
> +are completed (using VIRTIO_GPU_FLAG_FENCE).
> +
> +Then VIRTIO_GPU_CMD_UPDATE_CURSOR can be sent to the cursorq to set
> +the pointer shape and position. To move the pointer without updating
> +the shape use VIRTIO_GPU_CMD_MOVE_CURSOR instead.
> +
> +\subsubsection{Device Operation: Request header}\label{sec:Device Types / GPU Device / Device Operation / Device Operation: Request header}
> +
> +\begin{lstlisting}
> +enum virtio_gpu_ctrl_type {
> +
> + /* 2d commands */
> + VIRTIO_GPU_CMD_GET_DISPLAY_INFO = 0x0100,
> + VIRTIO_GPU_CMD_RESOURCE_CREATE_2D,
> + VIRTIO_GPU_CMD_RESOURCE_UNREF,
> + VIRTIO_GPU_CMD_SET_SCANOUT,
> + VIRTIO_GPU_CMD_RESOURCE_FLUSH,
> + VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D,
> + VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING,
> + VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING,
> +
> + /* cursor commands */
> + VIRTIO_GPU_CMD_UPDATE_CURSOR = 0x0300,
> + VIRTIO_GPU_CMD_MOVE_CURSOR,
> +
> + /* success responses */
> + VIRTIO_GPU_RESP_OK_NODATA = 0x1100,
> + VIRTIO_GPU_RESP_OK_DISPLAY_INFO,
> +
> + /* error responses */
> + VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200,
> + VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY,
> + VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID,
> + VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID,
> + VIRTIO_GPU_RESP_ERR_INVALID_CONTEXT_ID,
> + VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER,
> +};
> +
> +#define VIRTIO_GPU_FLAG_FENCE (1 << 0)
> +
> +struct virtio_gpu_ctrl_hdr {
> + le32 type;
> + le32 flags;
> + le64 fence_id;
> + le32 ctx_id;
> + le32 padding;
> +};
> +\end{lstlisting}
> +
> +All requests and responses on the virt queues have the fixed header
> +\field{struct virtio_gpu_ctrl_hdr}.
> +
> +\begin{description}
> +\item[\field{type}] specifies the type of the driver request
> + (VIRTIO_GPU_CMD_*) or device response (VIRTIO_GPU_RESP_*).
> +\item[\field{flags}] request / response flags.
> +\item[\field{fence_id}] If the driver sets the VIRTIO_GPU_FLAG_FENCE
> + bit in the request \field{flags} field the device MUST:
> + \begin{itemize*}
> + \item set VIRTIO_GPU_FLAG_FENCE bit in the response,
> + \item copy the content of the \field{fence_id} field from the
> + request to the response, and
> + \item send the response only after command processing is complete.
> + \end{itemize*}
> +\item[\field{ctx_id}] Rendering context (used in 3D mode only).
> +\end{description}
> +
> +On success the device will return VIRTIO_GPU_RESP_OK_NODATA in
> +case there is no payload. Otherwise the \field{type} field will
> +indicate the kind of payload.
> +
> +On error the device will return one of the
> +VIRTIO_GPU_RESP_ERR_* error codes.
> +
> +\subsubsection{Device Operation: controlq}\label{sec:Device Types / GPU Device / Device Operation / Device Operation: controlq}
> +
> +For any coordinates given 0,0 is top left, larger x moves right,
> +larger y moves down.
> +
> +\begin{description}
> +
> +\item[VIRTIO_GPU_CMD_GET_DISPLAY_INFO] Retrieve the current output
> + configuration. No request data (just bare \field{struct
> + virtio_gpu_ctrl_hdr}). Response type is
> + VIRTIO_GPU_RESP_OK_DISPLAY_INFO, response data is \field{struct
> + virtio_gpu_resp_display_info}.
> +
> +\begin{lstlisting}
> +#define VIRTIO_GPU_MAX_SCANOUTS 16
> +
> +struct virtio_gpu_rect {
> + le32 x;
> + le32 y;
> + le32 width;
> + le32 height;
> +};
> +
> +struct virtio_gpu_resp_display_info {
> + struct virtio_gpu_ctrl_hdr hdr;
> + struct virtio_gpu_display_one {
> + struct virtio_gpu_rect r;
> + le32 enabled;
> + le32 flags;
> + } pmodes[VIRTIO_GPU_MAX_SCANOUTS];
> +};
> +\end{lstlisting}
> +
> +The response contains a list of per-scanout information. The info
> +contains whether the scanout is enabled and what its preferred
> +position and size is.
> +
> +The size (fields \field{width} and \field{height}) is similar to the
> +native panel resolution in EDID display information, except that in
> +the virtual machine case the size can change when the host window
> +representing the guest display is gets resized.
> +
> +The position (fields \field{x} and \field{y}) describe how the
> +displays are arranged (i.e. which is -- for example -- the left
> +display).
> +
> +The \field{enabled} field is set when the user enabled the display.
> +It is roughly the same as the connected state of a phyiscal display
> +connector.
> +
> +\item[VIRTIO_GPU_CMD_RESOURCE_CREATE_2D] Create a 2D resource on the
> + host. Request data is \field{struct virtio_gpu_resource_create_2d}.
> + Response type is VIRTIO_GPU_RESP_OK_NODATA.
> +
> +\begin{lstlisting}
> +enum virtio_gpu_formats {
> + VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM = 1,
> + VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM = 2,
> + VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM = 3,
> + VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM = 4,
> +
> + VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM = 67,
> + VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM = 68,
> +
> + VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM = 121,
> + VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM = 134,
> +};
> +
> +struct virtio_gpu_resource_create_2d {
> + struct virtio_gpu_ctrl_hdr hdr;
> + le32 resource_id;
> + le32 format;
> + le32 width;
> + le32 height;
> +};
> +\end{lstlisting}
> +
> +This creates a 2D resource on the host with the specified width,
> +height and format. The resource ids are generated by the guest.
> +
> +\item[VIRTIO_GPU_CMD_RESOURCE_UNREF] Destroy a resource. Request data
> + is \field{struct virtio_gpu_resource_unref}. Response type is
> + VIRTIO_GPU_RESP_OK_NODATA.
> +
> +\begin{lstlisting}
> +struct virtio_gpu_resource_unref {
> + struct virtio_gpu_ctrl_hdr hdr;
> + le32 resource_id;
> + le32 padding;
> +};
> +\end{lstlisting}
> +
> +This informs the host that a resource is no longer required by the
> +guest.
> +
> +\item[VIRTIO_GPU_CMD_SET_SCANOUT] Set the scanout parameters for a
> + single output. Request data is \field{struct
> + virtio_gpu_set_scanout}. Response type is
> + VIRTIO_GPU_RESP_OK_NODATA.
> +
> +\begin{lstlisting}
> +struct virtio_gpu_set_scanout {
> + struct virtio_gpu_ctrl_hdr hdr;
> + struct virtio_gpu_rect r;
> + le32 scanout_id;
> + le32 resource_id;
> +};
> +\end{lstlisting}
> +
> +This sets the scanout parameters for a single scanout. The resource_id
> +is the resource to be scanned out from, along with a rectangle.
> +
> +Scanout rectangles must be completely covered by the underlying
> +resource. Overlapping (or identical) scanouts are allowed, typical
> +use case is screen mirroring.
> +
> +The driver can use resource_id = 0 to disable a scanout.
> +
> +\item[VIRTIO_GPU_CMD_RESOURCE_FLUSH] Flush a scanout resource Request
> + data is \field{struct virtio_gpu_resource_flush}. Response type is
> + VIRTIO_GPU_RESP_OK_NODATA.
> +
> +\begin{lstlisting}
> +struct virtio_gpu_resource_flush {
> + struct virtio_gpu_ctrl_hdr hdr;
> + struct virtio_gpu_rect r;
> + le32 resource_id;
> + le32 padding;
> +};
> +\end{lstlisting}
> +
> +This flushes a resource to screen. It takes a rectangle and a
> +resource id, and flushes any scanouts the resource is being used on.
> +
> +\item[VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D] Transfer from guest memory
> + to host resource. Request data is \field{struct
> + virtio_gpu_transfer_to_host_2d}. Response type is
> + VIRTIO_GPU_RESP_OK_NODATA.
> +
> +\begin{lstlisting}
> +struct virtio_gpu_transfer_to_host_2d {
> + struct virtio_gpu_ctrl_hdr hdr;
> + struct virtio_gpu_rect r;
> + le64 offset;
> + le32 resource_id;
> + le32 padding;
> +};
> +\end{lstlisting}
> +
> +This takes a resource id along with an destination offset into the
> +resource, and a box to transfer to the host backing for the resource.
> +
> +\item[VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING] Assign backing pages to
> + a resource. Request data is \field{struct
> + virtio_gpu_resource_attach_backing}, followed by \field{struct
> + virtio_gpu_mem_entry} entries. Response type is
> + VIRTIO_GPU_RESP_OK_NODATA.
> +
> +\begin{lstlisting}
> +struct virtio_gpu_resource_attach_backing {
> + struct virtio_gpu_ctrl_hdr hdr;
> + le32 resource_id;
> + le32 nr_entries;
> +};
> +
> +struct virtio_gpu_mem_entry {
> + le64 addr;
> + le32 length;
> + le32 padding;
> +};
> +\end{lstlisting}
> +
> +This assign an array of guest pages as the backing store for a
> +resource. These pages are then used for the transfer operations for
> +that resource from that point on.
> +
> +\item[VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING] Detach backing pages
> + from a resource. Request data is \field{struct
> + virtio_gpu_resource_detach_backing}. Response type is
> + VIRTIO_GPU_RESP_OK_NODATA.
> +
> +\begin{lstlisting}
> +struct virtio_gpu_resource_detach_backing {
> + struct virtio_gpu_ctrl_hdr hdr;
> + le32 resource_id;
> + le32 padding;
> +};
> +\end{lstlisting}
> +
> +This detaches any backing pages from a resource, to be used in case of
> +guest swapping or object destruction.
> +
> +\end{description}
> +
> +\subsubsection{Device Operation: cursorq}\label{sec:Device Types / GPU Device / Device Operation / Device Operation: cursorq}
> +
> +Both cursorq commands use the same command struct.
> +
> +\begin{lstlisting}
> +struct virtio_gpu_cursor_pos {
> + le32 scanout_id;
> + le32 x;
> + le32 y;
> + le32 padding;
> +};
> +
> +struct virtio_gpu_update_cursor {
> + struct virtio_gpu_ctrl_hdr hdr;
> + struct virtio_gpu_cursor_pos pos;
> + le32 resource_id;
> + le32 hot_x;
> + le32 hot_y;
> + le32 padding;
> +};
> +\end{lstlisting}
> +
> +\begin{description}
> +
> +\item[VIRTIO_GPU_CMD_UPDATE_CURSOR]
> +Update cursor.
> +Request data is \field{struct virtio_gpu_update_cursor}.
> +Response type is VIRTIO_GPU_RESP_OK_NODATA.
> +
> +Full cursor update. Cursor will be loaded from the specified
> +\field{resource_id} and will be moved to \field{pos}. The driver must
> +transfer the cursor into the resource beforehand (using control queue
> +commands) and make sure the commands to fill the resource are actually
> +processed (using fencing).
> +
> +\item[VIRTIO_GPU_CMD_MOVE_CURSOR]
> +Move cursor.
> +Request data is \field{struct virtio_gpu_update_cursor}.
> +Response type is VIRTIO_GPU_RESP_OK_NODATA.
> +
> +Move cursor to the place specified in \field{pos}. The other fields
> +are not used and will be ignored by the device.
> +
> +\end{description}
> +
> +\subsection{VGA Compatibility}\label{sec:Device Types / GPU Device / VGA Compatibility}
> +
> +Applies to Virtio Over PCI only. The GPU device can come with and
> +without VGA compatibility. The PCI class should be DISPLAY_VGA if VGA
> +compatibility is present and DISPLAY_OTHER otherwise.
> +
> +VGA compatibility: PCI region 0 has the linear framebuffer, standard
> +vga registers are present. Configuring a scanout
> +(VIRTIO_GPU_CMD_SET_SCANOUT) switches the device from vga
> +compatibility mode into native virtio mode. A reset switches it back
> +into vga compatibility mode.
> +
> +Note: qemu implementation also provides bochs dispi interface io ports
> +and mmio bar at pci region 1 and is therefore fully compatible with
> +the qemu stdvga (see \href{http://git.qemu-project.org/?p=qemu.git;a=blob;f=docs/specs/standard-vga.txt;hb=HEAD}{docs/specs/standard-vga.txt} in the qemu source tree).
> --
> 2.9.3
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: virtio-dev-unsubscribe@lists.oasis-open.org
> For additional commands, e-mail: virtio-dev-help@lists.oasis-open.org
---------------------------------------------------------------------
To unsubscribe, e-mail: virtio-dev-unsubscribe@lists.oasis-open.org
For additional commands, e-mail: virtio-dev-help@lists.oasis-open.org
next prev parent reply other threads:[~2018-07-03 0:15 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-27 6:15 [virtio-dev] [PATCH] Add virtio gpu device specification Gerd Hoffmann
2018-07-03 0:15 ` Michael S. Tsirkin [this message]
2018-07-03 13:03 ` Laszlo Ersek
[not found] <1462367134-23894-1-git-send-email-kraxel@redhat.com>
[not found] ` <20160509144316.GI3372@stefanha-x1.localdomain>
[not found] ` <1462874939.8035.52.camel@redhat.com>
[not found] ` <1462879537.8035.53.camel@redhat.com>
2018-06-20 3:15 ` Michael S. Tsirkin
2018-06-27 6:15 ` Gerd Hoffmann
2018-06-27 18:56 ` Michael S. Tsirkin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180703031324-mutt-send-email-mst@kernel.org \
--to=mst@redhat.com \
--cc=kraxel@redhat.com \
--cc=virtio-dev@lists.oasis-open.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox