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