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