mirror of https://github.com/xemu-project/xemu.git
vhost-user: add vhost_user_gpu_set_socket()
Add a new vhost-user message to give a unix socket to a vhost-user backend for GPU display updates. Back when I started that work, I added a new GPU channel because the vhost-user protocol wasn't bidirectional. Since then, there is a vhost-user-slave channel for the slave to send requests to the master. We could extend it with GPU messages. However, the GPU protocol is quite orthogonal to vhost-user, thus I chose to have a new dedicated channel. See vhost-user-gpu.rst for the protocol details. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-id: 20190524130946.31736-2-marcandre.lureau@redhat.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
da35f7f1ee
commit
bd2e44fee4
|
@ -1676,6 +1676,12 @@ F: hw/display/virtio-gpu*
|
||||||
F: hw/display/virtio-vga.c
|
F: hw/display/virtio-vga.c
|
||||||
F: include/hw/virtio/virtio-gpu.h
|
F: include/hw/virtio/virtio-gpu.h
|
||||||
|
|
||||||
|
vhost-user-gpu
|
||||||
|
M: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||||
|
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||||
|
S: Maintained
|
||||||
|
F: docs/interop/vhost-user-gpu.rst
|
||||||
|
|
||||||
Cirrus VGA
|
Cirrus VGA
|
||||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||||
S: Odd Fixes
|
S: Odd Fixes
|
||||||
|
|
|
@ -130,6 +130,7 @@ vu_request_to_string(unsigned int req)
|
||||||
REQ(VHOST_USER_POSTCOPY_END),
|
REQ(VHOST_USER_POSTCOPY_END),
|
||||||
REQ(VHOST_USER_GET_INFLIGHT_FD),
|
REQ(VHOST_USER_GET_INFLIGHT_FD),
|
||||||
REQ(VHOST_USER_SET_INFLIGHT_FD),
|
REQ(VHOST_USER_SET_INFLIGHT_FD),
|
||||||
|
REQ(VHOST_USER_GPU_SET_SOCKET),
|
||||||
REQ(VHOST_USER_MAX),
|
REQ(VHOST_USER_MAX),
|
||||||
};
|
};
|
||||||
#undef REQ
|
#undef REQ
|
||||||
|
|
|
@ -94,6 +94,7 @@ typedef enum VhostUserRequest {
|
||||||
VHOST_USER_POSTCOPY_END = 30,
|
VHOST_USER_POSTCOPY_END = 30,
|
||||||
VHOST_USER_GET_INFLIGHT_FD = 31,
|
VHOST_USER_GET_INFLIGHT_FD = 31,
|
||||||
VHOST_USER_SET_INFLIGHT_FD = 32,
|
VHOST_USER_SET_INFLIGHT_FD = 32,
|
||||||
|
VHOST_USER_GPU_SET_SOCKET = 33,
|
||||||
VHOST_USER_MAX
|
VHOST_USER_MAX
|
||||||
} VhostUserRequest;
|
} VhostUserRequest;
|
||||||
|
|
||||||
|
|
|
@ -16,3 +16,4 @@ Contents:
|
||||||
live-block-operations
|
live-block-operations
|
||||||
pr-helper
|
pr-helper
|
||||||
vhost-user
|
vhost-user
|
||||||
|
vhost-user-gpu
|
||||||
|
|
|
@ -0,0 +1,242 @@
|
||||||
|
=======================
|
||||||
|
Vhost-user-gpu Protocol
|
||||||
|
=======================
|
||||||
|
|
||||||
|
:Licence: This work is licensed under the terms of the GNU GPL,
|
||||||
|
version 2 or later. See the COPYING file in the top-level
|
||||||
|
directory.
|
||||||
|
|
||||||
|
.. contents:: Table of Contents
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
The vhost-user-gpu protocol is aiming at sharing the rendering result
|
||||||
|
of a virtio-gpu, done from a vhost-user slave process to a vhost-user
|
||||||
|
master process (such as QEMU). It bears a resemblance to a display
|
||||||
|
server protocol, if you consider QEMU as the display server and the
|
||||||
|
slave as the client, but in a very limited way. Typically, it will
|
||||||
|
work by setting a scanout/display configuration, before sending flush
|
||||||
|
events for the display updates. It will also update the cursor shape
|
||||||
|
and position.
|
||||||
|
|
||||||
|
The protocol is sent over a UNIX domain stream socket, since it uses
|
||||||
|
socket ancillary data to share opened file descriptors (DMABUF fds or
|
||||||
|
shared memory). The socket is usually obtained via
|
||||||
|
``VHOST_USER_GPU_SET_SOCKET``.
|
||||||
|
|
||||||
|
Requests are sent by the *slave*, and the optional replies by the
|
||||||
|
*master*.
|
||||||
|
|
||||||
|
Wire format
|
||||||
|
===========
|
||||||
|
|
||||||
|
Unless specified differently, numbers are in the machine native byte
|
||||||
|
order.
|
||||||
|
|
||||||
|
A vhost-user-gpu message (request and reply) consists of 3 header
|
||||||
|
fields and a payload.
|
||||||
|
|
||||||
|
+---------+-------+------+---------+
|
||||||
|
| request | flags | size | payload |
|
||||||
|
+---------+-------+------+---------+
|
||||||
|
|
||||||
|
Header
|
||||||
|
------
|
||||||
|
|
||||||
|
:request: ``u32``, type of the request
|
||||||
|
|
||||||
|
:flags: ``u32``, 32-bit bit field:
|
||||||
|
|
||||||
|
- Bit 2 is the reply flag - needs to be set on each reply
|
||||||
|
|
||||||
|
:size: ``u32``, size of the payload
|
||||||
|
|
||||||
|
Payload types
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Depending on the request type, **payload** can be:
|
||||||
|
|
||||||
|
VhostUserGpuCursorPos
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
+------------+---+---+
|
||||||
|
| scanout-id | x | y |
|
||||||
|
+------------+---+---+
|
||||||
|
|
||||||
|
:scanout-id: ``u32``, the scanout where the cursor is located
|
||||||
|
|
||||||
|
:x/y: ``u32``, the cursor postion
|
||||||
|
|
||||||
|
VhostUserGpuCursorUpdate
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
+-----+-------+-------+--------+
|
||||||
|
| pos | hot_x | hot_y | cursor |
|
||||||
|
+-----+-------+-------+--------+
|
||||||
|
|
||||||
|
:pos: a ``VhostUserGpuCursorPos``, the cursor location
|
||||||
|
|
||||||
|
:hot_x/hot_y: ``u32``, the cursor hot location
|
||||||
|
|
||||||
|
:cursor: ``[u32; 64 * 64]``, 64x64 RGBA cursor data (PIXMAN_a8r8g8b8 format)
|
||||||
|
|
||||||
|
VhostUserGpuScanout
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
+------------+---+---+
|
||||||
|
| scanout-id | w | h |
|
||||||
|
+------------+---+---+
|
||||||
|
|
||||||
|
:scanout-id: ``u32``, the scanout configuration to set
|
||||||
|
|
||||||
|
:w/h: ``u32``, the scanout width/height size
|
||||||
|
|
||||||
|
VhostUserGpuUpdate
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
+------------+---+---+---+---+------+
|
||||||
|
| scanout-id | x | y | w | h | data |
|
||||||
|
+------------+---+---+---+---+------+
|
||||||
|
|
||||||
|
:scanout-id: ``u32``, the scanout content to update
|
||||||
|
|
||||||
|
:x/y/w/h: ``u32``, region of the update
|
||||||
|
|
||||||
|
:data: RGB data (PIXMAN_x8r8g8b8 format)
|
||||||
|
|
||||||
|
VhostUserGpuDMABUFScanout
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
+------------+---+---+---+---+-----+-----+--------+-------+--------+
|
||||||
|
| scanout-id | x | y | w | h | fdw | fwh | stride | flags | fourcc |
|
||||||
|
+------------+---+---+---+---+-----+-----+--------+-------+--------+
|
||||||
|
|
||||||
|
:scanout-id: ``u32``, the scanout configuration to set
|
||||||
|
|
||||||
|
:x/y: ``u32``, the location of the scanout within the DMABUF
|
||||||
|
|
||||||
|
:w/h: ``u32``, the scanout width/height size
|
||||||
|
|
||||||
|
:fdw/fdh/stride/flags: ``u32``, the DMABUF width/height/stride/flags
|
||||||
|
|
||||||
|
:fourcc: ``i32``, the DMABUF fourcc
|
||||||
|
|
||||||
|
|
||||||
|
C structure
|
||||||
|
-----------
|
||||||
|
|
||||||
|
In QEMU the vhost-user-gpu message is implemented with the following struct:
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
typedef struct VhostUserGpuMsg {
|
||||||
|
uint32_t request; /* VhostUserGpuRequest */
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t size; /* the following payload size */
|
||||||
|
union {
|
||||||
|
VhostUserGpuCursorPos cursor_pos;
|
||||||
|
VhostUserGpuCursorUpdate cursor_update;
|
||||||
|
VhostUserGpuScanout scanout;
|
||||||
|
VhostUserGpuUpdate update;
|
||||||
|
VhostUserGpuDMABUFScanout dmabuf_scanout;
|
||||||
|
struct virtio_gpu_resp_display_info display_info;
|
||||||
|
uint64_t u64;
|
||||||
|
} payload;
|
||||||
|
} QEMU_PACKED VhostUserGpuMsg;
|
||||||
|
|
||||||
|
Protocol features
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
None yet.
|
||||||
|
|
||||||
|
As the protocol may need to evolve, new messages and communication
|
||||||
|
changes are negotiated thanks to preliminary
|
||||||
|
``VHOST_USER_GPU_GET_PROTOCOL_FEATURES`` and
|
||||||
|
``VHOST_USER_GPU_SET_PROTOCOL_FEATURES`` requests.
|
||||||
|
|
||||||
|
Communication
|
||||||
|
=============
|
||||||
|
|
||||||
|
Message types
|
||||||
|
-------------
|
||||||
|
|
||||||
|
``VHOST_USER_GPU_GET_PROTOCOL_FEATURES``
|
||||||
|
:id: 1
|
||||||
|
:request payload: N/A
|
||||||
|
:reply payload: ``u64``
|
||||||
|
|
||||||
|
Get the supported protocol features bitmask.
|
||||||
|
|
||||||
|
``VHOST_USER_GPU_SET_PROTOCOL_FEATURES``
|
||||||
|
:id: 2
|
||||||
|
:request payload: ``u64``
|
||||||
|
:reply payload: N/A
|
||||||
|
|
||||||
|
Enable protocol features using a bitmask.
|
||||||
|
|
||||||
|
``VHOST_USER_GPU_GET_DISPLAY_INFO``
|
||||||
|
:id: 3
|
||||||
|
:request payload: N/A
|
||||||
|
:reply payload: ``struct virtio_gpu_resp_display_info`` (from virtio specification)
|
||||||
|
|
||||||
|
Get the preferred display configuration.
|
||||||
|
|
||||||
|
``VHOST_USER_GPU_CURSOR_POS``
|
||||||
|
:id: 4
|
||||||
|
:request payload: ``VhostUserGpuCursorPos``
|
||||||
|
:reply payload: N/A
|
||||||
|
|
||||||
|
Set/show the cursor position.
|
||||||
|
|
||||||
|
``VHOST_USER_GPU_CURSOR_POS_HIDE``
|
||||||
|
:id: 5
|
||||||
|
:request payload: ``VhostUserGpuCursorPos``
|
||||||
|
:reply payload: N/A
|
||||||
|
|
||||||
|
Set/hide the cursor.
|
||||||
|
|
||||||
|
``VHOST_USER_GPU_CURSOR_UPDATE``
|
||||||
|
:id: 6
|
||||||
|
:request payload: ``VhostUserGpuCursorUpdate``
|
||||||
|
:reply payload: N/A
|
||||||
|
|
||||||
|
Update the cursor shape and location.
|
||||||
|
|
||||||
|
``VHOST_USER_GPU_SCANOUT``
|
||||||
|
:id: 7
|
||||||
|
:request payload: ``VhostUserGpuScanout``
|
||||||
|
:reply payload: N/A
|
||||||
|
|
||||||
|
Set the scanout resolution. To disable a scanout, the dimensions
|
||||||
|
width/height are set to 0.
|
||||||
|
|
||||||
|
``VHOST_USER_GPU_UPDATE``
|
||||||
|
:id: 8
|
||||||
|
:request payload: ``VhostUserGpuUpdate``
|
||||||
|
:reply payload: N/A
|
||||||
|
|
||||||
|
Update the scanout content. The data payload contains the graphical bits.
|
||||||
|
The display should be flushed and presented.
|
||||||
|
|
||||||
|
``VHOST_USER_GPU_DMABUF_SCANOUT``
|
||||||
|
:id: 9
|
||||||
|
:request payload: ``VhostUserGpuDMABUFScanout``
|
||||||
|
:reply payload: N/A
|
||||||
|
|
||||||
|
Set the scanout resolution/configuration, and share a DMABUF file
|
||||||
|
descriptor for the scanout content, which is passed as ancillary
|
||||||
|
data. To disable a scanout, the dimensions width/height are set
|
||||||
|
to 0, there is no file descriptor passed.
|
||||||
|
|
||||||
|
``VHOST_USER_GPU_DMABUF_UPDATE``
|
||||||
|
:id: 10
|
||||||
|
:request payload: ``VhostUserGpuUpdate``
|
||||||
|
:reply payload: empty payload
|
||||||
|
|
||||||
|
The display should be flushed and presented according to updated
|
||||||
|
region from ``VhostUserGpuUpdate``.
|
||||||
|
|
||||||
|
Note: there is no data payload, since the scanout is shared thanks
|
||||||
|
to DMABUF, that must have been set previously with
|
||||||
|
``VHOST_USER_GPU_DMABUF_SCANOUT``.
|
|
@ -1163,6 +1163,15 @@ Master message types
|
||||||
send the shared inflight buffer back to slave so that slave could
|
send the shared inflight buffer back to slave so that slave could
|
||||||
get inflight I/O after a crash or restart.
|
get inflight I/O after a crash or restart.
|
||||||
|
|
||||||
|
``VHOST_USER_GPU_SET_SOCKET``
|
||||||
|
:id: 33
|
||||||
|
:equivalent ioctl: N/A
|
||||||
|
:master payload: N/A
|
||||||
|
|
||||||
|
Sets the GPU protocol socket file descriptor, which is passed as
|
||||||
|
ancillary data. The GPU protocol is used to inform the master of
|
||||||
|
rendering state and updates. See vhost-user-gpu.rst for details.
|
||||||
|
|
||||||
Slave message types
|
Slave message types
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,7 @@ typedef enum VhostUserRequest {
|
||||||
VHOST_USER_POSTCOPY_END = 30,
|
VHOST_USER_POSTCOPY_END = 30,
|
||||||
VHOST_USER_GET_INFLIGHT_FD = 31,
|
VHOST_USER_GET_INFLIGHT_FD = 31,
|
||||||
VHOST_USER_SET_INFLIGHT_FD = 32,
|
VHOST_USER_SET_INFLIGHT_FD = 32,
|
||||||
|
VHOST_USER_GPU_SET_SOCKET = 33,
|
||||||
VHOST_USER_MAX
|
VHOST_USER_MAX
|
||||||
} VhostUserRequest;
|
} VhostUserRequest;
|
||||||
|
|
||||||
|
@ -353,6 +354,16 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd)
|
||||||
|
{
|
||||||
|
VhostUserMsg msg = {
|
||||||
|
.hdr.request = VHOST_USER_GPU_SET_SOCKET,
|
||||||
|
.hdr.flags = VHOST_USER_VERSION,
|
||||||
|
};
|
||||||
|
|
||||||
|
return vhost_user_write(dev, &msg, &fd, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base,
|
static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base,
|
||||||
struct vhost_log *log)
|
struct vhost_log *log)
|
||||||
{
|
{
|
||||||
|
|
|
@ -170,4 +170,6 @@ int vhost_backend_invalidate_device_iotlb(struct vhost_dev *dev,
|
||||||
int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev,
|
int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev,
|
||||||
struct vhost_iotlb_msg *imsg);
|
struct vhost_iotlb_msg *imsg);
|
||||||
|
|
||||||
|
int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd);
|
||||||
|
|
||||||
#endif /* VHOST_BACKEND_H */
|
#endif /* VHOST_BACKEND_H */
|
||||||
|
|
Loading…
Reference in New Issue