Merge tag 'pull-request-2023-07-10v2' of https://gitlab.com/thuth/qemu into staging
[qemu/armbru.git] / hw / virtio / virtio-qmp.c
blob3d32dbec8d7592c44b072b1af7a49896d1ea6a26
1 /*
2 * Virtio QMP helpers
4 * Copyright IBM, Corp. 2007
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "qemu/osdep.h"
13 #include "virtio-qmp.h"
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"
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"
34 #include CONFIG_DEVICES
36 #define FEATURE_ENTRY(name, desc) (qmp_virtio_feature_map_t) \
37 { .virtio_bit = name, .feature_desc = desc }
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
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, "" }
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: Backend 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, "" }
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, "" }
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, "" }
199 #endif
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, "" }
212 #endif
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, "" }
235 #endif
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, "" }
247 #endif
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, "" }
327 #endif
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 supported"),
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, "" }
350 #endif
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, "" }
362 #endif
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, "" }
376 #endif
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, "" }
390 #endif
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, "" }
410 #endif
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, "" }
419 #endif
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, "" }
444 #endif
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, "" }
458 #endif
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, "" }
470 #endif
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; \
480 else { \
481 bit = 1ULL << map[i].virtio_bit; \
483 if ((bitmap & bit) == 0) { \
484 continue; \
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; \
492 list; \
495 VirtioDeviceStatus *qmp_decode_status(uint8_t bitmap)
497 VirtioDeviceStatus *status;
498 uint8_t bit;
499 int i;
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;
509 return status;
512 VhostDeviceProtocols *qmp_decode_protocols(uint64_t bitmap)
514 VhostDeviceProtocols *vhu_protocols;
515 uint64_t bit;
516 int i;
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;
527 return vhu_protocols;
530 VirtioDeviceFeatures *qmp_decode_features(uint16_t device_id, uint64_t bitmap)
532 VirtioDeviceFeatures *features;
533 uint64_t bit;
534 int i;
536 features = g_new0(VirtioDeviceFeatures, 1);
537 features->has_dev_features = true;
539 /* transport features */
540 features->transports = CONVERT_FEATURES(strList, virtio_transport_map, 0,
541 bitmap);
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();
660 features->has_unknown_dev_features = bitmap != 0;
661 if (features->has_unknown_dev_features) {
662 features->unknown_dev_features = bitmap;
665 return features;
668 VirtioInfoList *qmp_x_query_virtio(Error **errp)
670 VirtioInfoList *list = NULL;
671 VirtioInfo *node;
672 VirtIODevice *vdev;
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);
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);
690 g_string_free(is_realized, true);
692 qobject_unref(obj);
695 return list;
698 VirtIODevice *qmp_find_virtio_device(const char *path)
700 VirtIODevice *vdev;
702 QTAILQ_FOREACH(vdev, &virtio_list, next) {
703 DeviceState *dev = DEVICE(vdev);
705 if (strcmp(dev->canonical_path, path) != 0) {
706 continue;
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;
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;
727 /* device exists in QOM tree & is realized */
728 qobject_unref(obj);
729 return vdev;
731 return NULL;
734 VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp)
736 VirtIODevice *vdev;
737 VirtioStatus *status;
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;
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);
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;
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;
782 if (vdev->vhost_started) {
783 VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
784 struct vhost_dev *hdev = vdc->get_vhost(vdev);
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;
805 return status;
808 VirtVhostQueueStatus *qmp_x_query_virtio_vhost_queue_status(const char *path,
809 uint16_t queue,
810 Error **errp)
812 VirtIODevice *vdev;
813 VirtVhostQueueStatus *status;
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;
821 if (!vdev->vhost_started) {
822 error_setg(errp, "Error: vhost device has not started yet");
823 return NULL;
826 VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
827 struct vhost_dev *hdev = vdc->get_vhost(vdev);
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;
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;
849 return status;