From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: virtio-dev-return-4749-cohuck=redhat.com@lists.oasis-open.org Sender: List-Post: List-Help: List-Unsubscribe: List-Subscribe: Received: from lists.oasis-open.org (oasis-open.org [10.110.1.242]) by lists.oasis-open.org (Postfix) with ESMTP id F38DF985CA0 for ; Fri, 27 Jul 2018 11:58:23 +0000 (UTC) Date: Fri, 27 Jul 2018 14:58:18 +0300 From: "Michael S. Tsirkin" Message-ID: <20180727145637-mutt-send-email-mst@kernel.org> References: <20180704054347.29527-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20180704054347.29527-1-kraxel@redhat.com> Subject: Re: [virtio-dev] [PATCH v2] Add virtio gpu device specification. To: Gerd Hoffmann Cc: virtio-dev@lists.oasis-open.org, Laszlo Ersek List-ID: On Wed, Jul 04, 2018 at 07:43:47AM +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. > > Cc: Laszlo Ersek > Signed-off-by: Gerd Hoffmann I started the voting on this, thanks everyone. Once this goes in, I hope we can add 3d/virgl as well to catch up to what's used in the field. > --- > 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..5d4709ad30 > --- /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_TO_HOST_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_TO_HOST_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_TO_HOST_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