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