forked from oasis-tcs/virtio-spec
-
Notifications
You must be signed in to change notification settings - Fork 0
/
virtio-gpu.tex
855 lines (699 loc) · 30.6 KB
/
virtio-gpu.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
\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 mode. 3D mode will offload rendering ops to
the host gpu and therefore requires a gpu with 3D support on the host
machine.
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 through 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.
\item[VIRTIO_GPU_F_EDID (1)] EDID is supported.
\item[VIRTIO_GPU_F_RESOURCE_UUID (2)] assigning resources UUIDs for export
to other virtio devices is supported.
\item[VIRTIO_GPU_F_RESOURCE_BLOB (3)] creating and using size-based blob
resources is supported.
\item[VIRTIO_GPU_F_CONTEXT_INIT (4)] multiple context types and
synchronization timelines supported. Requires VIRTIO_GPU_F_VIRGL.
\end{description}
\subsection{Device configuration layout}\label{sec:Device Types / GPU Device / Device configuration layout}
GPU device configuration uses the following layout structure and
definitions:
\begin{lstlisting}
#define VIRTIO_GPU_EVENT_DISPLAY (1 << 0)
struct virtio_gpu_config {
le32 events_read;
le32 events_clear;
le32 num_scanouts;
le32 num_capsets;
};
\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.
\item[\field{num_capsets}] specifies the maximum number of capability
sets supported by the device. The minimum value is zero.
\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. In case EDID support is
negotiated (VIRTIO_GPU_F_EDID feature flag) the device SHOULD also
fetch the updated EDID blobs using the VIRTIO_GPU_CMD_GET_EDID
command.
\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 EDID support is negotiated
(VIRTIO_GPU_F_EDID feature flag) the device SHOULD also fetch the EDID
information using the VIRTIO_GPU_CMD_GET_EDID command. If no
information is available or all displays are disabled the driver MAY
choose to use a fallback, such as 1024x768 at display 0.
The driver SHOULD query all shared memory regions supported by the device.
If the device supports shared memory, the \field{shmid} of a region MUST
(see \ref{sec:Basic Facilities of a Virtio Device /
Shared Memory Regions}~\nameref{sec:Basic Facilities of a Virtio Device /
Shared Memory Regions}) be one of the following:
\begin{lstlisting}
enum virtio_gpu_shm_id {
VIRTIO_GPU_SHM_ID_UNDEFINED = 0,
VIRTIO_GPU_SHM_ID_HOST_VISIBLE = 1,
};
\end{lstlisting}
The shared memory region with VIRTIO_GPU_SHM_ID_HOST_VISIBLE is referred as
the "host visible memory region". The device MUST support the
VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB and VIRTIO_GPU_CMD_RESOURCE_UNMAP_BLOB
if the host visible memory region is available.
\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, unless shared memory
regions are supported. 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}
All requests and responses on the virt queues have a fixed header
using the following layout structure and definitions:
\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,
VIRTIO_GPU_CMD_GET_CAPSET_INFO,
VIRTIO_GPU_CMD_GET_CAPSET,
VIRTIO_GPU_CMD_GET_EDID,
VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID,
VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB,
VIRTIO_GPU_CMD_SET_SCANOUT_BLOB,
/* 3d commands */
VIRTIO_GPU_CMD_CTX_CREATE = 0x0200,
VIRTIO_GPU_CMD_CTX_DESTROY,
VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE,
VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE,
VIRTIO_GPU_CMD_RESOURCE_CREATE_3D,
VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D,
VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D,
VIRTIO_GPU_CMD_SUBMIT_3D,
VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB,
VIRTIO_GPU_CMD_RESOURCE_UNMAP_BLOB,
/* 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,
VIRTIO_GPU_RESP_OK_CAPSET_INFO,
VIRTIO_GPU_RESP_OK_CAPSET,
VIRTIO_GPU_RESP_OK_EDID,
VIRTIO_GPU_RESP_OK_RESOURCE_UUID,
VIRTIO_GPU_RESP_OK_MAP_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)
#define VIRTIO_GPU_FLAG_INFO_RING_IDX (1 << 1)
struct virtio_gpu_ctrl_hdr {
le32 type;
le32 flags;
le64 fence_id;
le32 ctx_id;
u8 ring_idx;
u8 padding[3];
};
\end{lstlisting}
The fixed header \field{struct virtio_gpu_ctrl_hdr} in each
request includes the following fields:
\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).
\item[\field{ring_idx}] If VIRTIO_GPU_F_CONTEXT_INIT is supported, then
the driver MAY set VIRTIO_GPU_FLAG_INFO_RING_IDX bit in the request
\field{flags}. In that case:
\begin{itemize*}
\item \field{ring_idx} indicates the value of a context-specific ring
index. The minimum value is 0 and maximum value is 63 (inclusive).
\item If VIRTIO_GPU_FLAG_FENCE is set, \field{fence_id} acts as a
sequence number on the synchronization timeline defined by
\field{ctx_idx} and the ring index.
\item If VIRTIO_GPU_FLAG_FENCE is set and when the command associated
with \field{fence_id} is complete, the device MUST send a response for
all outstanding commands with a sequence number less than or equal to
\field{fence_id} on the same synchronization timeline.
\end{itemize*}
\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_GET_EDID] Retrieve the EDID data for a given
scanout. Request data is \field{struct virtio_gpu_get_edid}).
Response type is VIRTIO_GPU_RESP_OK_EDID, response data is
\field{struct virtio_gpu_resp_edid}. Support is optional and
negotiated using the VIRTIO_GPU_F_EDID feature flag.
\begin{lstlisting}
struct virtio_gpu_get_edid {
struct virtio_gpu_ctrl_hdr hdr;
le32 scanout;
le32 padding;
};
struct virtio_gpu_resp_edid {
struct virtio_gpu_ctrl_hdr hdr;
le32 size;
le32 padding;
u8 edid[1024];
};
\end{lstlisting}
The response contains the EDID display data blob (as specified by
VESA) for the scanout.
\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.
\item[VIRTIO_GPU_CMD_GET_CAPSET_INFO] Gets the information associated with
a particular \field{capset_index}, which MUST less than \field{num_capsets}
defined in the device configuration. Request data is
\field{struct virtio_gpu_get_capset_info}. Response type is
VIRTIO_GPU_RESP_OK_CAPSET_INFO.
On success, \field{struct virtio_gpu_resp_capset_info} contains the
\field{capset_id}, \field{capset_max_version}, \field{capset_max_size}
associated with capset at the specified {capset_idex}. field{capset_id} MUST
be one of the following (see listing for values):
\begin{itemize*}
\item \href{https://gitlab.freedesktop.org/virgl/virglrenderer/-/blob/master/src/virgl_hw.h#L526}{VIRTIO_GPU_CAPSET_VIRGL} --
the first edition of Virgl (Gallium OpenGL) protocol.
\item \href{https://gitlab.freedesktop.org/virgl/virglrenderer/-/blob/master/src/virgl_hw.h#L550}{VIRTIO_GPU_CAPSET_VIRGL2} --
the second edition of Virgl (Gallium OpenGL) protocol after the capset fix.
\item \href{https://android.googlesource.com/device/generic/vulkan-cereal/+/refs/heads/master/protocols/}{VIRTIO_GPU_CAPSET_GFXSTREAM} --
gfxtream's (mostly) autogenerated GLES and Vulkan streaming protocols.
\item \href{https://gitlab.freedesktop.org/olv/venus-protocol}{VIRTIO_GPU_CAPSET_VENUS} --
Mesa's (mostly) autogenerated Vulkan protocol.
\item \href{https://chromium.googlesource.com/chromiumos/platform/crosvm/+/refs/heads/main/rutabaga_gfx/src/cross_domain/cross_domain_protocol.rs}{VIRTIO_GPU_CAPSET_CROSS_DOMAIN} --
protocol for display virtualization via Wayland proxying.
\end{itemize*}
\begin{lstlisting}
struct virtio_gpu_get_capset_info {
struct virtio_gpu_ctrl_hdr hdr;
le32 capset_index;
le32 padding;
};
#define VIRTIO_GPU_CAPSET_VIRGL 1
#define VIRTIO_GPU_CAPSET_VIRGL2 2
#define VIRTIO_GPU_CAPSET_GFXSTREAM 3
#define VIRTIO_GPU_CAPSET_VENUS 4
#define VIRTIO_GPU_CAPSET_CROSS_DOMAIN 5
struct virtio_gpu_resp_capset_info {
struct virtio_gpu_ctrl_hdr hdr;
le32 capset_id;
le32 capset_max_version;
le32 capset_max_size;
le32 padding;
};
\end{lstlisting}
\item[VIRTIO_GPU_CMD_GET_CAPSET] Gets the capset associated with a
particular \field{capset_id} and \field{capset_version}. Request data is
\field{struct virtio_gpu_get_capset}. Response type is
VIRTIO_GPU_RESP_OK_CAPSET.
\begin{lstlisting}
struct virtio_gpu_get_capset {
struct virtio_gpu_ctrl_hdr hdr;
le32 capset_id;
le32 capset_version;
};
struct virtio_gpu_resp_capset {
struct virtio_gpu_ctrl_hdr hdr;
u8 capset_data[];
};
\end{lstlisting}
\item[VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID] Creates an exported object from
a resource. Request data is \field{struct
virtio_gpu_resource_assign_uuid}. Response type is
VIRTIO_GPU_RESP_OK_RESOURCE_UUID, response data is \field{struct
virtio_gpu_resp_resource_uuid}. Support is optional and negotiated
using the VIRTIO_GPU_F_RESOURCE_UUID feature flag.
\begin{lstlisting}
struct virtio_gpu_resource_assign_uuid {
struct virtio_gpu_ctrl_hdr hdr;
le32 resource_id;
le32 padding;
};
struct virtio_gpu_resp_resource_uuid {
struct virtio_gpu_ctrl_hdr hdr;
u8 uuid[16];
};
\end{lstlisting}
The response contains a UUID which identifies the exported object created from
the host private resource. Note that if the resource has an attached backing,
modifications made to the host private resource through the exported object by
other devices are not visible in the attached backing until they are transferred
into the backing.
\item[VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB] Creates a virtio-gpu blob
resource. Request data is \field{struct
virtio_gpu_resource_create_blob}, followed by \field{struct
virtio_gpu_mem_entry} entries. Response type is
VIRTIO_GPU_RESP_OK_NODATA. Support is optional and negotiated
using the VIRTIO_GPU_F_RESOURCE_BLOB feature flag.
\begin{lstlisting}
#define VIRTIO_GPU_BLOB_MEM_GUEST 0x0001
#define VIRTIO_GPU_BLOB_MEM_HOST3D 0x0002
#define VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST 0x0003
#define VIRTIO_GPU_BLOB_FLAG_USE_MAPPABLE 0x0001
#define VIRTIO_GPU_BLOB_FLAG_USE_SHAREABLE 0x0002
#define VIRTIO_GPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004
struct virtio_gpu_resource_create_blob {
struct virtio_gpu_ctrl_hdr hdr;
le32 resource_id;
le32 blob_mem;
le32 blob_flags;
le32 nr_entries;
le64 blob_id;
le64 size;
};
\end{lstlisting}
A blob resource is a container for:
\begin{itemize*}
\item a guest memory allocation (referred to as a
"guest-only blob resource").
\item a host memory allocation (referred to as a
"host-only blob resource").
\item a guest memory and host memory allocation (referred
to as a "default blob resource").
\end{itemize*}
The memory properties of the blob resource MUST be described by
\field{blob_mem}, which MUST be non-zero.
For default and guest-only blob resources, \field{nr_entries} guest
memory entries may be assigned to the resource. For default blob resources
(i.e, when \field{blob_mem} is VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST), these
memory entries are used as a shadow buffer for the host memory. To
facilitate drivers that support swap-in and swap-out, \field{nr_entries} may
be zero and VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING may be subsequently used.
VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING may be used to unassign memory entries.
\field{blob_mem} can only be VIRTIO_GPU_BLOB_MEM_HOST3D and
VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST if VIRTIO_GPU_F_VIRGL is supported.
VIRTIO_GPU_BLOB_MEM_GUEST is valid regardless whether VIRTIO_GPU_F_VIRGL
is supported or not.
For VIRTIO_GPU_BLOB_MEM_HOST3D and VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST, the
virtio-gpu resource MUST be created from the rendering context local object
identified by the \field{blob_id}. The actual allocation is done via
VIRTIO_GPU_CMD_SUBMIT_3D.
The driver MUST inform the device if the blob resource is used for
memory access, sharing between driver instances and/or sharing with
other devices. This is done via the \field{blob_flags} field.
If VIRTIO_GPU_F_VIRGL is set, both VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D
and VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D may be used to update the
resource. There is no restriction on the image/buffer view the driver
has on the blob resource.
\item[VIRTIO_GPU_CMD_SET_SCANOUT_BLOB] sets scanout parameters for a
blob resource. Request data is
\field{struct virtio_gpu_set_scanout_blob}. Response type is
VIRTIO_GPU_RESP_OK_NODATA. Support is optional and negotiated
using the VIRTIO_GPU_F_RESOURCE_BLOB feature flag.
\begin{lstlisting}
struct virtio_gpu_set_scanout_blob {
struct virtio_gpu_ctrl_hdr hdr;
struct virtio_gpu_rect r;
le32 scanout_id;
le32 resource_id;
le32 width;
le32 height;
le32 format;
le32 padding;
le32 strides[4];
le32 offsets[4];
};
\end{lstlisting}
The rectangle \field{r} represents the portion of the blob resource being
displayed. The rest is the metadata associated with the blob resource. The
format MUST be one of \field{enum virtio_gpu_formats}. The format MAY be
compressed with header and data planes.
\end{description}
\subsubsection{Device Operation: controlq (3d)}\label{sec:Device Types / GPU Device / Device Operation / Device Operation: controlq (3d)}
These commands are supported by the device if the VIRTIO_GPU_F_VIRGL
feature flag is set.
\begin{description}
\item[VIRTIO_GPU_CMD_CTX_CREATE] creates a context for submitting an opaque
command stream. Request data is \field{struct virtio_gpu_ctx_create}.
Response type is VIRTIO_GPU_RESP_OK_NODATA.
\begin{lstlisting}
#define VIRTIO_GPU_CONTEXT_INIT_CAPSET_ID_MASK 0x000000ff;
struct virtio_gpu_ctx_create {
struct virtio_gpu_ctrl_hdr hdr;
le32 nlen;
le32 context_init;
char debug_name[64];
};
\end{lstlisting}
The implementation MUST create a context for the given \field{ctx_id} in
the \field{hdr}. For debugging purposes, a \field{debug_name} and it's
length \field{nlen} is provided by the driver. If
VIRTIO_GPU_F_CONTEXT_INIT is supported, then lower 8 bits of
\field{context_init} MAY contain the \field{capset_id} associated with
context. In that case, then the device MUST create a context that can
handle the specified command stream.
If the lower 8-bits of the \field{context_init} are zero, then the type of
the context is determined by the device.
\item[VIRTIO_GPU_CMD_CTX_DESTROY]
\item[VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE]
\item[VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE]
Manage virtio-gpu 3d contexts.
\item[VIRTIO_GPU_CMD_RESOURCE_CREATE_3D]
Create virtio-gpu 3d resources.
\item[VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D]
\item[VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D]
Transfer data from and to virtio-gpu 3d resources.
\item[VIRTIO_GPU_CMD_SUBMIT_3D]
Submit an opaque command stream. The type of the command stream is
determined when creating a context.
\item[VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB] maps a host-only
blob resource into an offset in the host visible memory region. Request
data is \field{struct virtio_gpu_resource_map_blob}. The driver MUST
not map a blob resource that is already mapped. Response type is
VIRTIO_GPU_RESP_OK_MAP_INFO. Support is optional and negotiated
using the VIRTIO_GPU_F_RESOURCE_BLOB feature flag and checking for
the presence of the host visible memory region.
\begin{lstlisting}
struct virtio_gpu_resource_map_blob {
struct virtio_gpu_ctrl_hdr hdr;
le32 resource_id;
le32 padding;
le64 offset;
};
#define VIRTIO_GPU_MAP_CACHE_MASK 0x0f
#define VIRTIO_GPU_MAP_CACHE_NONE 0x00
#define VIRTIO_GPU_MAP_CACHE_CACHED 0x01
#define VIRTIO_GPU_MAP_CACHE_UNCACHED 0x02
#define VIRTIO_GPU_MAP_CACHE_WC 0x03
struct virtio_gpu_resp_map_info {
struct virtio_gpu_ctrl_hdr hdr;
u32 map_info;
u32 padding;
};
\end{lstlisting}
\item[VIRTIO_GPU_CMD_RESOURCE_UNMAP_BLOB] unmaps a
host-only blob resource from the host visible memory region. Request data
is \field{struct virtio_gpu_resource_unmap_blob}. Response type is
VIRTIO_GPU_RESP_OK_NODATA. Support is optional and negotiated
using the VIRTIO_GPU_F_RESOURCE_BLOB feature flag and checking for
the presence of the host visible memory region.
\begin{lstlisting}
struct virtio_gpu_resource_unmap_blob {
struct virtio_gpu_ctrl_hdr hdr;
le32 resource_id;
le32 padding;
};
\end{lstlisting}
\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{https://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).