xref: /openbmc/qemu/hw/virtio/virtio-qmp.c (revision d447a624)
1 /*
2  * Virtio QMP helpers
3  *
4  * Copyright IBM, Corp. 2007
5  *
6  * Authors:
7  *  Anthony Liguori   <aliguori@us.ibm.com>
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11 
12 #include "qemu/osdep.h"
13 #include "virtio-qmp.h"
14 
15 #include "qapi/error.h"
16 #include "qapi/qapi-commands-virtio.h"
17 #include "qapi/qapi-commands-qom.h"
18 #include "qapi/qmp/qobject.h"
19 #include "qapi/qmp/qjson.h"
20 
21 #include "standard-headers/linux/virtio_ids.h"
22 #include "standard-headers/linux/vhost_types.h"
23 #include "standard-headers/linux/virtio_blk.h"
24 #include "standard-headers/linux/virtio_console.h"
25 #include "standard-headers/linux/virtio_gpu.h"
26 #include "standard-headers/linux/virtio_net.h"
27 #include "standard-headers/linux/virtio_scsi.h"
28 #include "standard-headers/linux/virtio_i2c.h"
29 #include "standard-headers/linux/virtio_balloon.h"
30 #include "standard-headers/linux/virtio_iommu.h"
31 #include "standard-headers/linux/virtio_mem.h"
32 #include "standard-headers/linux/virtio_vsock.h"
33 
34 #include CONFIG_DEVICES
35 
36 #define FEATURE_ENTRY(name, desc) (qmp_virtio_feature_map_t) \
37     { .virtio_bit = name, .feature_desc = desc }
38 
39 enum VhostUserProtocolFeature {
40     VHOST_USER_PROTOCOL_F_MQ = 0,
41     VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1,
42     VHOST_USER_PROTOCOL_F_RARP = 2,
43     VHOST_USER_PROTOCOL_F_REPLY_ACK = 3,
44     VHOST_USER_PROTOCOL_F_NET_MTU = 4,
45     VHOST_USER_PROTOCOL_F_BACKEND_REQ = 5,
46     VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6,
47     VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7,
48     VHOST_USER_PROTOCOL_F_PAGEFAULT = 8,
49     VHOST_USER_PROTOCOL_F_CONFIG = 9,
50     VHOST_USER_PROTOCOL_F_BACKEND_SEND_FD = 10,
51     VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11,
52     VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD = 12,
53     VHOST_USER_PROTOCOL_F_RESET_DEVICE = 13,
54     VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS = 14,
55     VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS = 15,
56     VHOST_USER_PROTOCOL_F_MAX
57 };
58 
59 /* Virtio transport features mapping */
60 static const qmp_virtio_feature_map_t virtio_transport_map[] = {
61     /* Virtio device transport features */
62 #ifndef VIRTIO_CONFIG_NO_LEGACY
63     FEATURE_ENTRY(VIRTIO_F_NOTIFY_ON_EMPTY, \
64             "VIRTIO_F_NOTIFY_ON_EMPTY: Notify when device runs out of avail. "
65             "descs. on VQ"),
66     FEATURE_ENTRY(VIRTIO_F_ANY_LAYOUT, \
67             "VIRTIO_F_ANY_LAYOUT: Device accepts arbitrary desc. layouts"),
68 #endif /* !VIRTIO_CONFIG_NO_LEGACY */
69     FEATURE_ENTRY(VIRTIO_F_VERSION_1, \
70             "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)"),
71     FEATURE_ENTRY(VIRTIO_F_IOMMU_PLATFORM, \
72             "VIRTIO_F_IOMMU_PLATFORM: Device can be used on IOMMU platform"),
73     FEATURE_ENTRY(VIRTIO_F_RING_PACKED, \
74             "VIRTIO_F_RING_PACKED: Device supports packed VQ layout"),
75     FEATURE_ENTRY(VIRTIO_F_IN_ORDER, \
76             "VIRTIO_F_IN_ORDER: Device uses buffers in same order as made "
77             "available by driver"),
78     FEATURE_ENTRY(VIRTIO_F_ORDER_PLATFORM, \
79             "VIRTIO_F_ORDER_PLATFORM: Memory accesses ordered by platform"),
80     FEATURE_ENTRY(VIRTIO_F_SR_IOV, \
81             "VIRTIO_F_SR_IOV: Device supports single root I/O virtualization"),
82     FEATURE_ENTRY(VIRTIO_F_RING_RESET, \
83             "VIRTIO_F_RING_RESET: Driver can reset a queue individually"),
84     /* Virtio ring transport features */
85     FEATURE_ENTRY(VIRTIO_RING_F_INDIRECT_DESC, \
86             "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported"),
87     FEATURE_ENTRY(VIRTIO_RING_F_EVENT_IDX, \
88             "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled"),
89     { -1, "" }
90 };
91 
92 /* Vhost-user protocol features mapping */
93 static const qmp_virtio_feature_map_t vhost_user_protocol_map[] = {
94     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_MQ, \
95             "VHOST_USER_PROTOCOL_F_MQ: Multiqueue protocol supported"),
96     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_LOG_SHMFD, \
97             "VHOST_USER_PROTOCOL_F_LOG_SHMFD: Shared log memory fd supported"),
98     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_RARP, \
99             "VHOST_USER_PROTOCOL_F_RARP: Vhost-user back-end RARP broadcasting "
100             "supported"),
101     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_REPLY_ACK, \
102             "VHOST_USER_PROTOCOL_F_REPLY_ACK: Requested operation status ack. "
103             "supported"),
104     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_NET_MTU, \
105             "VHOST_USER_PROTOCOL_F_NET_MTU: Expose host MTU to guest supported"),
106     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_BACKEND_REQ, \
107             "VHOST_USER_PROTOCOL_F_BACKEND_REQ: Socket fd for back-end initiated "
108             "requests supported"),
109     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CROSS_ENDIAN, \
110             "VHOST_USER_PROTOCOL_F_CROSS_ENDIAN: Endianness of VQs for legacy "
111             "devices supported"),
112     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CRYPTO_SESSION, \
113             "VHOST_USER_PROTOCOL_F_CRYPTO_SESSION: Session creation for crypto "
114             "operations supported"),
115     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_PAGEFAULT, \
116             "VHOST_USER_PROTOCOL_F_PAGEFAULT: Request servicing on userfaultfd "
117             "for accessed pages supported"),
118     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CONFIG, \
119             "VHOST_USER_PROTOCOL_F_CONFIG: Vhost-user messaging for virtio "
120             "device configuration space supported"),
121     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_BACKEND_SEND_FD, \
122             "VHOST_USER_PROTOCOL_F_BACKEND_SEND_FD: Backend fd communication "
123             "channel supported"),
124     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_HOST_NOTIFIER, \
125             "VHOST_USER_PROTOCOL_F_HOST_NOTIFIER: Host notifiers for specified "
126             "VQs supported"),
127     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD, \
128             "VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD: Shared inflight I/O buffers "
129             "supported"),
130     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_RESET_DEVICE, \
131             "VHOST_USER_PROTOCOL_F_RESET_DEVICE: Disabling all rings and "
132             "resetting internal device state supported"),
133     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS, \
134             "VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS: In-band messaging "
135             "supported"),
136     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS, \
137             "VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS: Configuration for "
138             "memory slots supported"),
139     { -1, "" }
140 };
141 
142 /* virtio device configuration statuses */
143 static const qmp_virtio_feature_map_t virtio_config_status_map[] = {
144     FEATURE_ENTRY(VIRTIO_CONFIG_S_DRIVER_OK, \
145             "VIRTIO_CONFIG_S_DRIVER_OK: Driver setup and ready"),
146     FEATURE_ENTRY(VIRTIO_CONFIG_S_FEATURES_OK, \
147             "VIRTIO_CONFIG_S_FEATURES_OK: Feature negotiation complete"),
148     FEATURE_ENTRY(VIRTIO_CONFIG_S_DRIVER, \
149             "VIRTIO_CONFIG_S_DRIVER: Guest OS compatible with device"),
150     FEATURE_ENTRY(VIRTIO_CONFIG_S_NEEDS_RESET, \
151             "VIRTIO_CONFIG_S_NEEDS_RESET: Irrecoverable error, device needs "
152             "reset"),
153     FEATURE_ENTRY(VIRTIO_CONFIG_S_FAILED, \
154             "VIRTIO_CONFIG_S_FAILED: Error in guest, device failed"),
155     FEATURE_ENTRY(VIRTIO_CONFIG_S_ACKNOWLEDGE, \
156             "VIRTIO_CONFIG_S_ACKNOWLEDGE: Valid virtio device found"),
157     { -1, "" }
158 };
159 
160 /* virtio-blk features mapping */
161 #ifdef CONFIG_VIRTIO_BLK
162 static const qmp_virtio_feature_map_t virtio_blk_feature_map[] = {
163     FEATURE_ENTRY(VIRTIO_BLK_F_SIZE_MAX, \
164             "VIRTIO_BLK_F_SIZE_MAX: Max segment size is size_max"),
165     FEATURE_ENTRY(VIRTIO_BLK_F_SEG_MAX, \
166             "VIRTIO_BLK_F_SEG_MAX: Max segments in a request is seg_max"),
167     FEATURE_ENTRY(VIRTIO_BLK_F_GEOMETRY, \
168             "VIRTIO_BLK_F_GEOMETRY: Legacy geometry available"),
169     FEATURE_ENTRY(VIRTIO_BLK_F_RO, \
170             "VIRTIO_BLK_F_RO: Device is read-only"),
171     FEATURE_ENTRY(VIRTIO_BLK_F_BLK_SIZE, \
172             "VIRTIO_BLK_F_BLK_SIZE: Block size of disk available"),
173     FEATURE_ENTRY(VIRTIO_BLK_F_TOPOLOGY, \
174             "VIRTIO_BLK_F_TOPOLOGY: Topology information available"),
175     FEATURE_ENTRY(VIRTIO_BLK_F_MQ, \
176             "VIRTIO_BLK_F_MQ: Multiqueue supported"),
177     FEATURE_ENTRY(VIRTIO_BLK_F_DISCARD, \
178             "VIRTIO_BLK_F_DISCARD: Discard command supported"),
179     FEATURE_ENTRY(VIRTIO_BLK_F_WRITE_ZEROES, \
180             "VIRTIO_BLK_F_WRITE_ZEROES: Write zeroes command supported"),
181     FEATURE_ENTRY(VIRTIO_BLK_F_ZONED, \
182             "VIRTIO_BLK_F_ZONED: Zoned block devices"),
183 #ifndef VIRTIO_BLK_NO_LEGACY
184     FEATURE_ENTRY(VIRTIO_BLK_F_BARRIER, \
185             "VIRTIO_BLK_F_BARRIER: Request barriers supported"),
186     FEATURE_ENTRY(VIRTIO_BLK_F_SCSI, \
187             "VIRTIO_BLK_F_SCSI: SCSI packet commands supported"),
188     FEATURE_ENTRY(VIRTIO_BLK_F_FLUSH, \
189             "VIRTIO_BLK_F_FLUSH: Flush command supported"),
190     FEATURE_ENTRY(VIRTIO_BLK_F_CONFIG_WCE, \
191             "VIRTIO_BLK_F_CONFIG_WCE: Cache writeback and writethrough modes "
192             "supported"),
193 #endif /* !VIRTIO_BLK_NO_LEGACY */
194     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
195             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
196     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
197             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
198             "negotiation supported"),
199     { -1, "" }
200 };
201 #endif
202 
203 /* virtio-serial features mapping */
204 #ifdef CONFIG_VIRTIO_SERIAL
205 static const qmp_virtio_feature_map_t virtio_serial_feature_map[] = {
206     FEATURE_ENTRY(VIRTIO_CONSOLE_F_SIZE, \
207             "VIRTIO_CONSOLE_F_SIZE: Host providing console size"),
208     FEATURE_ENTRY(VIRTIO_CONSOLE_F_MULTIPORT, \
209             "VIRTIO_CONSOLE_F_MULTIPORT: Multiple ports for device supported"),
210     FEATURE_ENTRY(VIRTIO_CONSOLE_F_EMERG_WRITE, \
211             "VIRTIO_CONSOLE_F_EMERG_WRITE: Emergency write supported"),
212     { -1, "" }
213 };
214 #endif
215 
216 /* virtio-gpu features mapping */
217 #ifdef CONFIG_VIRTIO_GPU
218 static const qmp_virtio_feature_map_t virtio_gpu_feature_map[] = {
219     FEATURE_ENTRY(VIRTIO_GPU_F_VIRGL, \
220             "VIRTIO_GPU_F_VIRGL: Virgl 3D mode supported"),
221     FEATURE_ENTRY(VIRTIO_GPU_F_EDID, \
222             "VIRTIO_GPU_F_EDID: EDID metadata supported"),
223     FEATURE_ENTRY(VIRTIO_GPU_F_RESOURCE_UUID, \
224             "VIRTIO_GPU_F_RESOURCE_UUID: Resource UUID assigning supported"),
225     FEATURE_ENTRY(VIRTIO_GPU_F_RESOURCE_BLOB, \
226             "VIRTIO_GPU_F_RESOURCE_BLOB: Size-based blob resources supported"),
227     FEATURE_ENTRY(VIRTIO_GPU_F_CONTEXT_INIT, \
228             "VIRTIO_GPU_F_CONTEXT_INIT: Context types and synchronization "
229             "timelines supported"),
230     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
231             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
232     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
233             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
234             "negotiation supported"),
235     { -1, "" }
236 };
237 #endif
238 
239 /* virtio-input features mapping */
240 #ifdef CONFIG_VIRTIO_INPUT
241 static const qmp_virtio_feature_map_t virtio_input_feature_map[] = {
242     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
243             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
244     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
245             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
246             "negotiation supported"),
247     { -1, "" }
248 };
249 #endif
250 
251 /* virtio-net features mapping */
252 #ifdef CONFIG_VIRTIO_NET
253 static const qmp_virtio_feature_map_t virtio_net_feature_map[] = {
254     FEATURE_ENTRY(VIRTIO_NET_F_CSUM, \
255             "VIRTIO_NET_F_CSUM: Device handling packets with partial checksum "
256             "supported"),
257     FEATURE_ENTRY(VIRTIO_NET_F_GUEST_CSUM, \
258             "VIRTIO_NET_F_GUEST_CSUM: Driver handling packets with partial "
259             "checksum supported"),
260     FEATURE_ENTRY(VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \
261             "VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: Control channel offloading "
262             "reconfig. supported"),
263     FEATURE_ENTRY(VIRTIO_NET_F_MTU, \
264             "VIRTIO_NET_F_MTU: Device max MTU reporting supported"),
265     FEATURE_ENTRY(VIRTIO_NET_F_MAC, \
266             "VIRTIO_NET_F_MAC: Device has given MAC address"),
267     FEATURE_ENTRY(VIRTIO_NET_F_GUEST_TSO4, \
268             "VIRTIO_NET_F_GUEST_TSO4: Driver can receive TSOv4"),
269     FEATURE_ENTRY(VIRTIO_NET_F_GUEST_TSO6, \
270             "VIRTIO_NET_F_GUEST_TSO6: Driver can receive TSOv6"),
271     FEATURE_ENTRY(VIRTIO_NET_F_GUEST_ECN, \
272             "VIRTIO_NET_F_GUEST_ECN: Driver can receive TSO with ECN"),
273     FEATURE_ENTRY(VIRTIO_NET_F_GUEST_UFO, \
274             "VIRTIO_NET_F_GUEST_UFO: Driver can receive UFO"),
275     FEATURE_ENTRY(VIRTIO_NET_F_HOST_TSO4, \
276             "VIRTIO_NET_F_HOST_TSO4: Device can receive TSOv4"),
277     FEATURE_ENTRY(VIRTIO_NET_F_HOST_TSO6, \
278             "VIRTIO_NET_F_HOST_TSO6: Device can receive TSOv6"),
279     FEATURE_ENTRY(VIRTIO_NET_F_HOST_ECN, \
280             "VIRTIO_NET_F_HOST_ECN: Device can receive TSO with ECN"),
281     FEATURE_ENTRY(VIRTIO_NET_F_HOST_UFO, \
282             "VIRTIO_NET_F_HOST_UFO: Device can receive UFO"),
283     FEATURE_ENTRY(VIRTIO_NET_F_MRG_RXBUF, \
284             "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers"),
285     FEATURE_ENTRY(VIRTIO_NET_F_STATUS, \
286             "VIRTIO_NET_F_STATUS: Configuration status field available"),
287     FEATURE_ENTRY(VIRTIO_NET_F_CTRL_VQ, \
288             "VIRTIO_NET_F_CTRL_VQ: Control channel available"),
289     FEATURE_ENTRY(VIRTIO_NET_F_CTRL_RX, \
290             "VIRTIO_NET_F_CTRL_RX: Control channel RX mode supported"),
291     FEATURE_ENTRY(VIRTIO_NET_F_CTRL_VLAN, \
292             "VIRTIO_NET_F_CTRL_VLAN: Control channel VLAN filtering supported"),
293     FEATURE_ENTRY(VIRTIO_NET_F_CTRL_RX_EXTRA, \
294             "VIRTIO_NET_F_CTRL_RX_EXTRA: Extra RX mode control supported"),
295     FEATURE_ENTRY(VIRTIO_NET_F_GUEST_ANNOUNCE, \
296             "VIRTIO_NET_F_GUEST_ANNOUNCE: Driver sending gratuitous packets "
297             "supported"),
298     FEATURE_ENTRY(VIRTIO_NET_F_MQ, \
299             "VIRTIO_NET_F_MQ: Multiqueue with automatic receive steering "
300             "supported"),
301     FEATURE_ENTRY(VIRTIO_NET_F_CTRL_MAC_ADDR, \
302             "VIRTIO_NET_F_CTRL_MAC_ADDR: MAC address set through control "
303             "channel"),
304     FEATURE_ENTRY(VIRTIO_NET_F_HASH_REPORT, \
305             "VIRTIO_NET_F_HASH_REPORT: Hash reporting supported"),
306     FEATURE_ENTRY(VIRTIO_NET_F_RSS, \
307             "VIRTIO_NET_F_RSS: RSS RX steering supported"),
308     FEATURE_ENTRY(VIRTIO_NET_F_RSC_EXT, \
309             "VIRTIO_NET_F_RSC_EXT: Extended coalescing info supported"),
310     FEATURE_ENTRY(VIRTIO_NET_F_STANDBY, \
311             "VIRTIO_NET_F_STANDBY: Device acting as standby for primary "
312             "device with same MAC addr. supported"),
313     FEATURE_ENTRY(VIRTIO_NET_F_SPEED_DUPLEX, \
314             "VIRTIO_NET_F_SPEED_DUPLEX: Device set linkspeed and duplex"),
315 #ifndef VIRTIO_NET_NO_LEGACY
316     FEATURE_ENTRY(VIRTIO_NET_F_GSO, \
317             "VIRTIO_NET_F_GSO: Handling GSO-type packets supported"),
318 #endif /* !VIRTIO_NET_NO_LEGACY */
319     FEATURE_ENTRY(VHOST_NET_F_VIRTIO_NET_HDR, \
320             "VHOST_NET_F_VIRTIO_NET_HDR: Virtio-net headers for RX and TX "
321             "packets supported"),
322     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
323             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
324     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
325             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
326             "negotiation supported"),
327     { -1, "" }
328 };
329 #endif
330 
331 /* virtio-scsi features mapping */
332 #ifdef CONFIG_VIRTIO_SCSI
333 static const qmp_virtio_feature_map_t virtio_scsi_feature_map[] = {
334     FEATURE_ENTRY(VIRTIO_SCSI_F_INOUT, \
335             "VIRTIO_SCSI_F_INOUT: Requests including read and writable data "
336             "buffers supported"),
337     FEATURE_ENTRY(VIRTIO_SCSI_F_HOTPLUG, \
338             "VIRTIO_SCSI_F_HOTPLUG: Reporting and handling hot-plug events "
339             "supported"),
340     FEATURE_ENTRY(VIRTIO_SCSI_F_CHANGE, \
341             "VIRTIO_SCSI_F_CHANGE: Reporting and handling LUN changes "
342             "supported"),
343     FEATURE_ENTRY(VIRTIO_SCSI_F_T10_PI, \
344             "VIRTIO_SCSI_F_T10_PI: T10 info included in request header"),
345     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
346             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
347     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
348             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
349             "negotiation supported"),
350     { -1, "" }
351 };
352 #endif
353 
354 /* virtio/vhost-user-fs features mapping */
355 #ifdef CONFIG_VHOST_USER_FS
356 static const qmp_virtio_feature_map_t virtio_fs_feature_map[] = {
357     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
358             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
359     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
360             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
361             "negotiation supported"),
362     { -1, "" }
363 };
364 #endif
365 
366 /* virtio/vhost-user-i2c features mapping */
367 #ifdef CONFIG_VIRTIO_I2C_ADAPTER
368 static const qmp_virtio_feature_map_t virtio_i2c_feature_map[] = {
369     FEATURE_ENTRY(VIRTIO_I2C_F_ZERO_LENGTH_REQUEST, \
370             "VIRTIO_I2C_F_ZERO_LEGNTH_REQUEST: Zero length requests supported"),
371     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
372             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
373     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
374             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
375             "negotiation supported"),
376     { -1, "" }
377 };
378 #endif
379 
380 /* virtio/vhost-vsock features mapping */
381 #ifdef CONFIG_VHOST_VSOCK
382 static const qmp_virtio_feature_map_t virtio_vsock_feature_map[] = {
383     FEATURE_ENTRY(VIRTIO_VSOCK_F_SEQPACKET, \
384             "VIRTIO_VSOCK_F_SEQPACKET: SOCK_SEQPACKET supported"),
385     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
386             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
387     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
388             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
389             "negotiation supported"),
390     { -1, "" }
391 };
392 #endif
393 
394 /* virtio-balloon features mapping */
395 #ifdef CONFIG_VIRTIO_BALLOON
396 static const qmp_virtio_feature_map_t virtio_balloon_feature_map[] = {
397     FEATURE_ENTRY(VIRTIO_BALLOON_F_MUST_TELL_HOST, \
398             "VIRTIO_BALLOON_F_MUST_TELL_HOST: Tell host before reclaiming "
399             "pages"),
400     FEATURE_ENTRY(VIRTIO_BALLOON_F_STATS_VQ, \
401             "VIRTIO_BALLOON_F_STATS_VQ: Guest memory stats VQ available"),
402     FEATURE_ENTRY(VIRTIO_BALLOON_F_DEFLATE_ON_OOM, \
403             "VIRTIO_BALLOON_F_DEFLATE_ON_OOM: Deflate balloon when guest OOM"),
404     FEATURE_ENTRY(VIRTIO_BALLOON_F_FREE_PAGE_HINT, \
405             "VIRTIO_BALLOON_F_FREE_PAGE_HINT: VQ reporting free pages enabled"),
406     FEATURE_ENTRY(VIRTIO_BALLOON_F_PAGE_POISON, \
407             "VIRTIO_BALLOON_F_PAGE_POISON: Guest page poisoning enabled"),
408     FEATURE_ENTRY(VIRTIO_BALLOON_F_REPORTING, \
409             "VIRTIO_BALLOON_F_REPORTING: Page reporting VQ enabled"),
410     { -1, "" }
411 };
412 #endif
413 
414 /* virtio-crypto features mapping */
415 #ifdef CONFIG_VIRTIO_CRYPTO
416 static const qmp_virtio_feature_map_t virtio_crypto_feature_map[] = {
417     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
418             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
419     { -1, "" }
420 };
421 #endif
422 
423 /* virtio-iommu features mapping */
424 #ifdef CONFIG_VIRTIO_IOMMU
425 static const qmp_virtio_feature_map_t virtio_iommu_feature_map[] = {
426     FEATURE_ENTRY(VIRTIO_IOMMU_F_INPUT_RANGE, \
427             "VIRTIO_IOMMU_F_INPUT_RANGE: Range of available virtual addrs. "
428             "available"),
429     FEATURE_ENTRY(VIRTIO_IOMMU_F_DOMAIN_RANGE, \
430             "VIRTIO_IOMMU_F_DOMAIN_RANGE: Number of supported domains "
431             "available"),
432     FEATURE_ENTRY(VIRTIO_IOMMU_F_MAP_UNMAP, \
433             "VIRTIO_IOMMU_F_MAP_UNMAP: Map and unmap requests available"),
434     FEATURE_ENTRY(VIRTIO_IOMMU_F_BYPASS, \
435             "VIRTIO_IOMMU_F_BYPASS: Endpoints not attached to domains are in "
436             "bypass mode"),
437     FEATURE_ENTRY(VIRTIO_IOMMU_F_PROBE, \
438             "VIRTIO_IOMMU_F_PROBE: Probe requests available"),
439     FEATURE_ENTRY(VIRTIO_IOMMU_F_MMIO, \
440             "VIRTIO_IOMMU_F_MMIO: VIRTIO_IOMMU_MAP_F_MMIO flag available"),
441     FEATURE_ENTRY(VIRTIO_IOMMU_F_BYPASS_CONFIG, \
442             "VIRTIO_IOMMU_F_BYPASS_CONFIG: Bypass field of IOMMU config "
443             "available"),
444     { -1, "" }
445 };
446 #endif
447 
448 /* virtio-mem features mapping */
449 #ifdef CONFIG_VIRTIO_MEM
450 static const qmp_virtio_feature_map_t virtio_mem_feature_map[] = {
451 #ifndef CONFIG_ACPI
452     FEATURE_ENTRY(VIRTIO_MEM_F_ACPI_PXM, \
453             "VIRTIO_MEM_F_ACPI_PXM: node_id is an ACPI PXM and is valid"),
454 #endif /* !CONFIG_ACPI */
455     FEATURE_ENTRY(VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, \
456             "VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE: Unplugged memory cannot be "
457             "accessed"),
458     { -1, "" }
459 };
460 #endif
461 
462 /* virtio-rng features mapping */
463 #ifdef CONFIG_VIRTIO_RNG
464 static const qmp_virtio_feature_map_t virtio_rng_feature_map[] = {
465     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
466             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
467     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
468             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
469             "negotiation supported"),
470     { -1, "" }
471 };
472 #endif
473 
474 #define CONVERT_FEATURES(type, map, is_status, bitmap)   \
475     ({                                                   \
476         type *list = NULL;                               \
477         type *node;                                      \
478         for (i = 0; map[i].virtio_bit != -1; i++) {      \
479             if (is_status) {                             \
480                 bit = map[i].virtio_bit;                 \
481             }                                            \
482             else {                                       \
483                 bit = 1ULL << map[i].virtio_bit;         \
484             }                                            \
485             if ((bitmap & bit) == 0) {                   \
486                 continue;                                \
487             }                                            \
488             node = g_new0(type, 1);                      \
489             node->value = g_strdup(map[i].feature_desc); \
490             node->next = list;                           \
491             list = node;                                 \
492             bitmap ^= bit;                               \
493         }                                                \
494         list;                                            \
495     })
496 
497 VirtioDeviceStatus *qmp_decode_status(uint8_t bitmap)
498 {
499     VirtioDeviceStatus *status;
500     uint8_t bit;
501     int i;
502 
503     status = g_new0(VirtioDeviceStatus, 1);
504     status->statuses = CONVERT_FEATURES(strList, virtio_config_status_map,
505                                         1, bitmap);
506     status->has_unknown_statuses = bitmap != 0;
507     if (status->has_unknown_statuses) {
508         status->unknown_statuses = bitmap;
509     }
510 
511     return status;
512 }
513 
514 VhostDeviceProtocols *qmp_decode_protocols(uint64_t bitmap)
515 {
516     VhostDeviceProtocols *vhu_protocols;
517     uint64_t bit;
518     int i;
519 
520     vhu_protocols = g_new0(VhostDeviceProtocols, 1);
521     vhu_protocols->protocols =
522                     CONVERT_FEATURES(strList,
523                                      vhost_user_protocol_map, 0, bitmap);
524     vhu_protocols->has_unknown_protocols = bitmap != 0;
525     if (vhu_protocols->has_unknown_protocols) {
526         vhu_protocols->unknown_protocols = bitmap;
527     }
528 
529     return vhu_protocols;
530 }
531 
532 VirtioDeviceFeatures *qmp_decode_features(uint16_t device_id, uint64_t bitmap)
533 {
534     VirtioDeviceFeatures *features;
535     uint64_t bit;
536     int i;
537 
538     features = g_new0(VirtioDeviceFeatures, 1);
539     features->has_dev_features = true;
540 
541     /* transport features */
542     features->transports = CONVERT_FEATURES(strList, virtio_transport_map, 0,
543                                             bitmap);
544 
545     /* device features */
546     switch (device_id) {
547 #ifdef CONFIG_VIRTIO_SERIAL
548     case VIRTIO_ID_CONSOLE:
549         features->dev_features =
550             CONVERT_FEATURES(strList, virtio_serial_feature_map, 0, bitmap);
551         break;
552 #endif
553 #ifdef CONFIG_VIRTIO_BLK
554     case VIRTIO_ID_BLOCK:
555         features->dev_features =
556             CONVERT_FEATURES(strList, virtio_blk_feature_map, 0, bitmap);
557         break;
558 #endif
559 #ifdef CONFIG_VIRTIO_GPU
560     case VIRTIO_ID_GPU:
561         features->dev_features =
562             CONVERT_FEATURES(strList, virtio_gpu_feature_map, 0, bitmap);
563         break;
564 #endif
565 #ifdef CONFIG_VIRTIO_NET
566     case VIRTIO_ID_NET:
567         features->dev_features =
568             CONVERT_FEATURES(strList, virtio_net_feature_map, 0, bitmap);
569         break;
570 #endif
571 #ifdef CONFIG_VIRTIO_SCSI
572     case VIRTIO_ID_SCSI:
573         features->dev_features =
574             CONVERT_FEATURES(strList, virtio_scsi_feature_map, 0, bitmap);
575         break;
576 #endif
577 #ifdef CONFIG_VIRTIO_BALLOON
578     case VIRTIO_ID_BALLOON:
579         features->dev_features =
580             CONVERT_FEATURES(strList, virtio_balloon_feature_map, 0, bitmap);
581         break;
582 #endif
583 #ifdef CONFIG_VIRTIO_IOMMU
584     case VIRTIO_ID_IOMMU:
585         features->dev_features =
586             CONVERT_FEATURES(strList, virtio_iommu_feature_map, 0, bitmap);
587         break;
588 #endif
589 #ifdef CONFIG_VIRTIO_INPUT
590     case VIRTIO_ID_INPUT:
591         features->dev_features =
592             CONVERT_FEATURES(strList, virtio_input_feature_map, 0, bitmap);
593         break;
594 #endif
595 #ifdef CONFIG_VHOST_USER_FS
596     case VIRTIO_ID_FS:
597         features->dev_features =
598             CONVERT_FEATURES(strList, virtio_fs_feature_map, 0, bitmap);
599         break;
600 #endif
601 #ifdef CONFIG_VHOST_VSOCK
602     case VIRTIO_ID_VSOCK:
603         features->dev_features =
604             CONVERT_FEATURES(strList, virtio_vsock_feature_map, 0, bitmap);
605         break;
606 #endif
607 #ifdef CONFIG_VIRTIO_CRYPTO
608     case VIRTIO_ID_CRYPTO:
609         features->dev_features =
610             CONVERT_FEATURES(strList, virtio_crypto_feature_map, 0, bitmap);
611         break;
612 #endif
613 #ifdef CONFIG_VIRTIO_MEM
614     case VIRTIO_ID_MEM:
615         features->dev_features =
616             CONVERT_FEATURES(strList, virtio_mem_feature_map, 0, bitmap);
617         break;
618 #endif
619 #ifdef CONFIG_VIRTIO_I2C_ADAPTER
620     case VIRTIO_ID_I2C_ADAPTER:
621         features->dev_features =
622             CONVERT_FEATURES(strList, virtio_i2c_feature_map, 0, bitmap);
623         break;
624 #endif
625 #ifdef CONFIG_VIRTIO_RNG
626     case VIRTIO_ID_RNG:
627         features->dev_features =
628             CONVERT_FEATURES(strList, virtio_rng_feature_map, 0, bitmap);
629         break;
630 #endif
631     /* No features */
632     case VIRTIO_ID_9P:
633     case VIRTIO_ID_PMEM:
634     case VIRTIO_ID_IOMEM:
635     case VIRTIO_ID_RPMSG:
636     case VIRTIO_ID_CLOCK:
637     case VIRTIO_ID_MAC80211_WLAN:
638     case VIRTIO_ID_MAC80211_HWSIM:
639     case VIRTIO_ID_RPROC_SERIAL:
640     case VIRTIO_ID_MEMORY_BALLOON:
641     case VIRTIO_ID_CAIF:
642     case VIRTIO_ID_SIGNAL_DIST:
643     case VIRTIO_ID_PSTORE:
644     case VIRTIO_ID_SOUND:
645     case VIRTIO_ID_BT:
646     case VIRTIO_ID_RPMB:
647     case VIRTIO_ID_VIDEO_ENCODER:
648     case VIRTIO_ID_VIDEO_DECODER:
649     case VIRTIO_ID_SCMI:
650     case VIRTIO_ID_NITRO_SEC_MOD:
651     case VIRTIO_ID_WATCHDOG:
652     case VIRTIO_ID_CAN:
653     case VIRTIO_ID_DMABUF:
654     case VIRTIO_ID_PARAM_SERV:
655     case VIRTIO_ID_AUDIO_POLICY:
656     case VIRTIO_ID_GPIO:
657         break;
658     default:
659         g_assert_not_reached();
660     }
661 
662     features->has_unknown_dev_features = bitmap != 0;
663     if (features->has_unknown_dev_features) {
664         features->unknown_dev_features = bitmap;
665     }
666 
667     return features;
668 }
669 
670 VirtioInfoList *qmp_x_query_virtio(Error **errp)
671 {
672     VirtioInfoList *list = NULL;
673     VirtioInfo *node;
674     VirtIODevice *vdev;
675 
676     QTAILQ_FOREACH(vdev, &virtio_list, next) {
677         DeviceState *dev = DEVICE(vdev);
678         Error *err = NULL;
679         QObject *obj = qmp_qom_get(dev->canonical_path, "realized", &err);
680 
681         if (err == NULL) {
682             GString *is_realized = qobject_to_json_pretty(obj, true);
683             /* virtio device is NOT realized, remove it from list */
684             if (!strncmp(is_realized->str, "false", 4)) {
685                 QTAILQ_REMOVE(&virtio_list, vdev, next);
686             } else {
687                 node = g_new(VirtioInfo, 1);
688                 node->path = g_strdup(dev->canonical_path);
689                 node->name = g_strdup(vdev->name);
690                 QAPI_LIST_PREPEND(list, node);
691             }
692            g_string_free(is_realized, true);
693         }
694         qobject_unref(obj);
695     }
696 
697     return list;
698 }
699 
700 VirtIODevice *qmp_find_virtio_device(const char *path)
701 {
702     VirtIODevice *vdev;
703 
704     QTAILQ_FOREACH(vdev, &virtio_list, next) {
705         DeviceState *dev = DEVICE(vdev);
706 
707         if (strcmp(dev->canonical_path, path) != 0) {
708             continue;
709         }
710 
711         Error *err = NULL;
712         QObject *obj = qmp_qom_get(dev->canonical_path, "realized", &err);
713         if (err == NULL) {
714             GString *is_realized = qobject_to_json_pretty(obj, true);
715             /* virtio device is NOT realized, remove it from list */
716             if (!strncmp(is_realized->str, "false", 4)) {
717                 g_string_free(is_realized, true);
718                 qobject_unref(obj);
719                 QTAILQ_REMOVE(&virtio_list, vdev, next);
720                 return NULL;
721             }
722             g_string_free(is_realized, true);
723         } else {
724             /* virtio device doesn't exist in QOM tree */
725             QTAILQ_REMOVE(&virtio_list, vdev, next);
726             qobject_unref(obj);
727             return NULL;
728         }
729         /* device exists in QOM tree & is realized */
730         qobject_unref(obj);
731         return vdev;
732     }
733     return NULL;
734 }
735 
736 VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp)
737 {
738     VirtIODevice *vdev;
739     VirtioStatus *status;
740 
741     vdev = qmp_find_virtio_device(path);
742     if (vdev == NULL) {
743         error_setg(errp, "Path %s is not a VirtIODevice", path);
744         return NULL;
745     }
746 
747     status = g_new0(VirtioStatus, 1);
748     status->name = g_strdup(vdev->name);
749     status->device_id = vdev->device_id;
750     status->vhost_started = vdev->vhost_started;
751     status->guest_features = qmp_decode_features(vdev->device_id,
752                                                  vdev->guest_features);
753     status->host_features = qmp_decode_features(vdev->device_id,
754                                                 vdev->host_features);
755     status->backend_features = qmp_decode_features(vdev->device_id,
756                                                    vdev->backend_features);
757 
758     switch (vdev->device_endian) {
759     case VIRTIO_DEVICE_ENDIAN_LITTLE:
760         status->device_endian = g_strdup("little");
761         break;
762     case VIRTIO_DEVICE_ENDIAN_BIG:
763         status->device_endian = g_strdup("big");
764         break;
765     default:
766         status->device_endian = g_strdup("unknown");
767         break;
768     }
769 
770     status->num_vqs = virtio_get_num_queues(vdev);
771     status->status = qmp_decode_status(vdev->status);
772     status->isr = vdev->isr;
773     status->queue_sel = vdev->queue_sel;
774     status->vm_running = vdev->vm_running;
775     status->broken = vdev->broken;
776     status->disabled = vdev->disabled;
777     status->use_started = vdev->use_started;
778     status->started = vdev->started;
779     status->start_on_kick = vdev->start_on_kick;
780     status->disable_legacy_check = vdev->disable_legacy_check;
781     status->bus_name = g_strdup(vdev->bus_name);
782     status->use_guest_notifier_mask = vdev->use_guest_notifier_mask;
783 
784     if (vdev->vhost_started) {
785         VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
786         struct vhost_dev *hdev = vdc->get_vhost(vdev);
787 
788         status->vhost_dev = g_new0(VhostStatus, 1);
789         status->vhost_dev->n_mem_sections = hdev->n_mem_sections;
790         status->vhost_dev->n_tmp_sections = hdev->n_tmp_sections;
791         status->vhost_dev->nvqs = hdev->nvqs;
792         status->vhost_dev->vq_index = hdev->vq_index;
793         status->vhost_dev->features =
794             qmp_decode_features(vdev->device_id, hdev->features);
795         status->vhost_dev->acked_features =
796             qmp_decode_features(vdev->device_id, hdev->acked_features);
797         status->vhost_dev->backend_features =
798             qmp_decode_features(vdev->device_id, hdev->backend_features);
799         status->vhost_dev->protocol_features =
800             qmp_decode_protocols(hdev->protocol_features);
801         status->vhost_dev->max_queues = hdev->max_queues;
802         status->vhost_dev->backend_cap = hdev->backend_cap;
803         status->vhost_dev->log_enabled = hdev->log_enabled;
804         status->vhost_dev->log_size = hdev->log_size;
805     }
806 
807     return status;
808 }
809 
810 VirtVhostQueueStatus *qmp_x_query_virtio_vhost_queue_status(const char *path,
811                                                             uint16_t queue,
812                                                             Error **errp)
813 {
814     VirtIODevice *vdev;
815     VirtVhostQueueStatus *status;
816 
817     vdev = qmp_find_virtio_device(path);
818     if (vdev == NULL) {
819         error_setg(errp, "Path %s is not a VirtIODevice", path);
820         return NULL;
821     }
822 
823     if (!vdev->vhost_started) {
824         error_setg(errp, "Error: vhost device has not started yet");
825         return NULL;
826     }
827 
828     VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
829     struct vhost_dev *hdev = vdc->get_vhost(vdev);
830 
831     if (queue < hdev->vq_index || queue >= hdev->vq_index + hdev->nvqs) {
832         error_setg(errp, "Invalid vhost virtqueue number %d", queue);
833         return NULL;
834     }
835 
836     status = g_new0(VirtVhostQueueStatus, 1);
837     status->name = g_strdup(vdev->name);
838     status->kick = hdev->vqs[queue].kick;
839     status->call = hdev->vqs[queue].call;
840     status->desc = (uintptr_t)hdev->vqs[queue].desc;
841     status->avail = (uintptr_t)hdev->vqs[queue].avail;
842     status->used = (uintptr_t)hdev->vqs[queue].used;
843     status->num = hdev->vqs[queue].num;
844     status->desc_phys = hdev->vqs[queue].desc_phys;
845     status->desc_size = hdev->vqs[queue].desc_size;
846     status->avail_phys = hdev->vqs[queue].avail_phys;
847     status->avail_size = hdev->vqs[queue].avail_size;
848     status->used_phys = hdev->vqs[queue].used_phys;
849     status->used_size = hdev->vqs[queue].used_size;
850 
851     return status;
852 }
853